Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-stale-consumer-registry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@core/sync-service': patch
---

Fix race condition in `ConsumerRegistry.unregister_name/1` that left stale PIDs in the ETS table. Uses atomic `:ets.match_delete/2` to remove the entry only if it still belongs to the dying process, preventing accidental deletion of a replacement consumer's entry.
5 changes: 0 additions & 5 deletions .changeset/index-any-and-in-where-clauses.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/lovely-icons-sit.md

This file was deleted.

142 changes: 142 additions & 0 deletions .github/workflows/check-skills.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# check-skills.yml — Drop this into your library repo's .github/workflows/
#
# Checks for stale intent skills after a release and opens a review PR
# if any skills need attention. The PR body includes a prompt you can
# paste into Claude Code, Cursor, or any coding agent to update them.
#
# Triggers: new release published, or manual workflow_dispatch.
#
# Template variables (replaced by `intent setup`):
# @electric-sql/client

name: Check Skills

on:
release:
types: [published]
workflow_dispatch: {}

permissions:
contents: write
pull-requests: write

jobs:
check:
name: Check for stale skills
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20

- name: Install intent
run: npm install -g @tanstack/intent

- name: Check staleness
id: stale
run: |
OUTPUT=$(npx @tanstack/intent stale --json 2>&1) || true
echo "$OUTPUT"

# Check if any skills need review
NEEDS_REVIEW=$(echo "$OUTPUT" | node -e "
const input = require('fs').readFileSync('/dev/stdin','utf8');
try {
const reports = JSON.parse(input);
const stale = reports.flatMap(r =>
r.skills.filter(s => s.needsReview).map(s => ({ library: r.library, skill: s.name, reasons: s.reasons }))
);
if (stale.length > 0) {
console.log(JSON.stringify(stale));
}
} catch {}
")

if [ -z "$NEEDS_REVIEW" ]; then
echo "has_stale=false" >> "$GITHUB_OUTPUT"
else
echo "has_stale=true" >> "$GITHUB_OUTPUT"
# Escape for multiline GH output
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "stale_json<<$EOF" >> "$GITHUB_OUTPUT"
echo "$NEEDS_REVIEW" >> "$GITHUB_OUTPUT"
echo "$EOF" >> "$GITHUB_OUTPUT"
fi

- name: Build summary
if: steps.stale.outputs.has_stale == 'true'
id: summary
run: |
node -e "
const stale = JSON.parse(process.env.STALE_JSON);
const lines = stale.map(s =>
'- **' + s.skill + '** (' + s.library + '): ' + s.reasons.join(', ')
);
const summary = lines.join('\n');

const prompt = [
'Review and update the following stale intent skills for @electric-sql/client:',
'',
...stale.map(s => '- ' + s.skill + ': ' + s.reasons.join(', ')),
'',
'For each stale skill:',
'1. Read the current SKILL.md file',
'2. Check what changed in the library since the skill was last updated',
'3. Update the skill content to reflect current APIs and behavior',
'4. Run \`npx @tanstack/intent validate\` to verify the updated skill',
].join('\n');

// Write outputs
const fs = require('fs');
const eof = require('crypto').randomBytes(15).toString('base64');
fs.appendFileSync(process.env.GITHUB_OUTPUT,
'summary<<' + eof + '\n' + summary + '\n' + eof + '\n' +
'prompt<<' + eof + '\n' + prompt + '\n' + eof + '\n'
);
"
env:
STALE_JSON: ${{ steps.stale.outputs.stale_json }}

- name: Open review PR
if: steps.stale.outputs.has_stale == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ github.event.release.tag_name || 'manual' }}"
BRANCH="skills/review-${VERSION}"

git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git checkout -b "$BRANCH"
git commit --allow-empty -m "chore: review stale skills for ${VERSION}"
git push origin "$BRANCH"

gh pr create \
--title "Review stale skills (${VERSION})" \
--body "$(cat <<'PREOF'
## Stale Skills Detected

The following skills may need updates after the latest release:

${{ steps.summary.outputs.summary }}

---

### Update Prompt

Paste this into your coding agent (Claude Code, Cursor, etc.):

~~~
${{ steps.summary.outputs.prompt }}
~~~

PREOF
)" \
--head "$BRANCH" \
--base main
53 changes: 53 additions & 0 deletions .github/workflows/notify-intent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# notify-intent.yml — Drop this into your library repo's .github/workflows/
#
# Fires a repository_dispatch event to TanStack/intent whenever docs or
# source files change on merge to main. This triggers the skill staleness
# check workflow in the intent repo.
#
# Requirements:
# - A fine-grained PAT with contents:write on TanStack/intent stored
# as the INTENT_NOTIFY_TOKEN repository secret.
#
# Template variables (replaced by `intent setup`):
# @electric-sql/client
# website/docs/**
# packages/typescript-client/src/**

name: Notify Intent

on:
push:
branches: [main]
paths:
- 'website/docs/**'
- 'packages/typescript-client/src/**'
- 'packages/y-electric/src/**'

jobs:
notify:
name: Notify TanStack Intent
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2

- name: Collect changed files
id: changes
run: |
FILES=$(git diff --name-only HEAD~1 HEAD | jq -R -s -c 'split("\n") | map(select(length > 0))')
echo "files=$FILES" >> "$GITHUB_OUTPUT"

- name: Dispatch to intent repo
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.INTENT_NOTIFY_TOKEN }}
repository: TanStack/intent
event-type: skill-check
client-payload: |
{
"package": "@electric-sql/client",
"sha": "${{ github.sha }}",
"changed_files": ${{ steps.changes.outputs.files }}
}
52 changes: 52 additions & 0 deletions .github/workflows/validate-skills.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# validate-skills.yml — Drop this into your library repo's .github/workflows/
#
# Validates skill files on PRs that touch the skills/ directory.
# Ensures frontmatter is correct, names match paths, and files stay under
# the 500-line limit.

name: Validate Skills

on:
pull_request:
paths:
- 'skills/**'
- '**/skills/**'

jobs:
validate:
name: Validate skill files
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20

- name: Install intent CLI
run: npm install -g @tanstack/intent

- name: Find and validate skills
run: |
# Find all directories containing SKILL.md files
SKILLS_DIR=""
if [ -d "skills" ]; then
SKILLS_DIR="skills"
elif [ -d "packages" ]; then
# Monorepo — find skills/ under packages
for dir in packages/*/skills; do
if [ -d "$dir" ]; then
echo "Validating $dir..."
intent validate "$dir"
fi
done
exit 0
fi

if [ -n "$SKILLS_DIR" ]; then
intent validate "$SKILLS_DIR"
else
echo "No skills/ directory found — skipping validation."
fi
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ sst-*.log
response.tmp
.claude
!website/.claude/commands
!website/.claude/skills
!website/.claude/skills
_artifacts
7 changes: 7 additions & 0 deletions examples/tanstack-db-expo-starter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# expo-db-electric-starter

## 1.0.13

### Patch Changes

- Updated dependencies [d1e08b8]
- @electric-sql/client@1.5.12

## 1.0.12

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions examples/tanstack-db-expo-starter/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "expo-db-electric-starter",
"version": "1.0.12",
"version": "1.0.13",
"main": "index.ts",
"scripts": {
"start": "docker compose up -d && expo start",
Expand All @@ -13,7 +13,7 @@
"api": "tsx api/index.ts"
},
"dependencies": {
"@electric-sql/client": "1.5.11",
"@electric-sql/client": "1.5.12",
"@expo/metro-runtime": "~5.0.4",
"@tanstack/electric-db-collection": "^0.0.15",
"@tanstack/react-db": "^0.0.27",
Expand Down
7 changes: 7 additions & 0 deletions packages/experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @electric-sql/experimental

## 6.0.12

### Patch Changes

- Updated dependencies [d1e08b8]
- @electric-sql/client@1.5.12

## 6.0.11

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/experimental/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@electric-sql/experimental",
"description": "Experimental TypeScript features for ElectricSQL.",
"version": "6.0.11",
"version": "6.0.12",
"author": "ElectricSQL team and contributors.",
"bugs": {
"url": "https://github.com/electric-sql/electric/issues"
Expand Down
7 changes: 7 additions & 0 deletions packages/react-hooks/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @electric-sql/react

## 1.0.41

### Patch Changes

- Updated dependencies [d1e08b8]
- @electric-sql/client@1.5.12

## 1.0.40

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/react-hooks/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@electric-sql/react",
"description": "React hooks for ElectricSQL",
"version": "1.0.40",
"version": "1.0.41",
"author": "ElectricSQL team and contributors.",
"bugs": {
"url": "https://github.com/electric-sql/electric/issues"
Expand Down
6 changes: 6 additions & 0 deletions packages/sync-service/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @core/sync-service

## 1.4.13

### Patch Changes

- 8daa822: Index `= ANY(array_field)` and `IN (const_list)` WHERE clause expressions for O(1) shape filtering. ANY clauses reuse the InclusionIndex (via single-element array containment), and IN clauses reuse the EqualityIndex (registering each value separately). At 1000 concurrent shapes, fan-out latency improves by 6x (ANY) and 15x (IN) compared to the previous linear scan.

## 1.4.12

### Patch Changes
Expand Down
1 change: 1 addition & 0 deletions packages/sync-service/CLAUDE.md
1 change: 0 additions & 1 deletion packages/sync-service/lib/electric/shape_cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,6 @@ defmodule Electric.ShapeCache do
start_opts =
opts
|> Map.put(:shape_handle, shape_handle)
|> Map.put(:shape, shape)
|> Map.put(:subqueries_enabled_for_stack?, "allow_subqueries" in feature_flags)

case Shapes.DynamicConsumerSupervisor.start_shape_consumer(stack_id, start_opts) do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,6 @@ defmodule Electric.ShapeCache.ShapeStatus do
end)
end

@spec fetch_shape_by_handle!(stack_id(), shape_handle()) :: Shape.t() | no_return()
def fetch_shape_by_handle!(stack_id, shape_handle)
when is_stack_id(stack_id) and is_shape_handle(shape_handle) do
case fetch_shape_by_handle(stack_id, shape_handle) do
{:ok, shape} -> shape
:error -> raise ArgumentError, message: "No shape found for handle #{inspect(shape_handle)}"
end
end

def has_shape_handle?(stack_id, shape_handle) do
:ets.member(shape_meta_table(stack_id), shape_handle)
end
Expand Down
Loading
Loading