electric-shapes について
Electric を使う開発者向けに、@electric-sql/client の ShapeStream でデータを同期・処理する方法を説明するスキルです。フィルター、列選択、フィールド名の変換、再試行、ストリームの再開を扱います。
主な機能
- 01条件による行のフィルタリング
- 02主キーを含む列の選択
- 03データベース列名の変換
- 04エラー時の再試行設定
- 05保存位置からのストリーム再開
- 06カスタム型の解析
活用シーン
- 01特定のユーザーや状態のデータ同期
- 02データベース列名のクライアント形式への変換
- 03保存済みオフセットからの同期再開
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ electric-sql/ electric --skill electric-shapesインストール後、Claude Code で/electric-shapesを入力して読み込まれたか確認します。
同梱ファイルreferences/type-parsers.mdreferences/where-clause.md
詳細
Electric — シェイプストリーミング
セットアップ
import { ShapeStream, Shape } from '@electric-sql/client'
const stream = new ShapeStream({
url: '/api/todos', // Your proxy route, NOT direct Electric URL
// Built-in parsers auto-handle: bool, int2, int4, float4, float8, json, jsonb
// Add custom parsers for other types (see references/type-parsers.md)
parser: {
timestamptz: (date: string) => new Date(date),
},
})
const shape = new Shape(stream)
shape.subscribe(({ rows }) => {
console.log('synced rows:', rows)
})
// Wait for initial sync
const rows = await shape.rows
基本パターン
WHERE 句と位置パラメーターで行をフィルタリングする
const stream = new ShapeStream({
url: '/api/todos',
params: {
table: 'todos',
where: 'user_id = $1 AND status = $2',
params: { '1': userId, '2': 'active' },
},
})
特定の列を選択する(主キーを含める必要があります)
const stream = new ShapeStream({
url: '/api/todos',
params: {
table: 'todos',
columns: ['id', 'title', 'status'], // PK required
},
})
snake_case と camelCase の間で列名をマッピングする
import { ShapeStream, snakeCamelMapper } from '@electric-sql/client'
const stream = new ShapeStream({
url: '/api/todos',
columnMapper: snakeCamelMapper(),
})
// DB column "created_at" arrives as "createdAt" in client
// WHERE clauses auto-translate: "createdAt" → "created_at"
リトライでエラーを処理する
const stream = new ShapeStream({
url: '/api/todos',
onError: (error) => {
console.error('sync error', error)
return {} // Return {} to retry; returning void stops the stream
},
})
401 エラー時の認証トークンの更新については、electric-proxy-auth/SKILL.md を参照してください。
保存したオフセットから再開する
const stream = new ShapeStream({
url: '/api/todos',
offset: storedOffset, // Both offset AND handle required
handle: storedHandle,
})
更新時に古い値を含むレプリカを取得する
const stream = new ShapeStream({
url: '/api/todos',
params: {
table: 'todos',
replica: 'full', // Sends unchanged columns + old_value on updates
},
})
よくある間違い
重大:onError から void を返すと同期が永久に停止する
誤り:
const stream = new ShapeStream({
url: '/api/todos',
onError: (error) => {
console.error('sync error', error)
// Returning nothing = stream stops forever
},
})
正しい例:
const stream = new ShapeStream({
url: '/api/todos',
onError: (error) => {
console.error('sync error', error)
return {} // Return {} to retry
},
})
onError が undefined を返すと、ストリームを永久に停止するシグナルになります。リトライするには少なくとも {} を返し、更新した値でリトライするには { headers, params } を返してください。
ソース:packages/typescript-client/src/client.ts:409-418
高:主キーを含めずに列を指定する
誤り:
const stream = new ShapeStream({
url: '/api/todos',
params: {
table: 'todos',
columns: ['title', 'status'],
},
})
正しい例:
const stream = new ShapeStream({
url: '/api/todos',
params: {
table: 'todos',
columns: ['id', 'title', 'status'],
},
})
サーバーは 400 エラーを返します。columns リストには必ず主キーの列を含めてください。
ソース:website/docs/guides/shapes.md
高:再開時に handle を指定せず offset を設定する
誤り:
new ShapeStream({
url: '/api/todos',
offset: storedOffset,
})
正しい例:
new ShapeStream({
url: '/api/todos',
offset: storedOffset,
handle: storedHandle,
})
MissingShapeHandleError がスローされます。保存した位置からストリームを再開するには、offset と handle の両方が必要です。
ソース:packages/typescript-client/src/client.ts:1997-2003
高:WHERE 句で非決定的関数を使用する
誤り:
const stream = new ShapeStream({
url: '/api/events',
params: {
table: 'events',
where: 'start_time > now()',
},
})
正しい例:
const stream = new ShapeStream({
url: '/api/events',
params: {
table: 'events',
where: 'start_time > $1',
params: { '1': new Date().toISOString() },
},
})
サーバーは now()、random()、count() などの非決定的関数を含む WHERE 句を拒否します。静的な値または位置パラメーターを使用してください。
ソース:packages/sync-service/lib/electric/replication/eval/env/known_functions.ex
高:Postgres のカスタム型を解析しない
誤り:
const stream = new ShapeStream({
url: '/api/events',
})
// createdAt will be string "2024-01-15T10:30:00.000Z", not a Date
正しい例:
const stream = new ShapeStream({
url: '/api/events',
parser: {
timestamptz: (date: string) => new Date(date),
timestamp: (date: string) => new Date(date),
},
})
Electric は bool、int2、int4、float4、float8、json、jsonb、int8(→ BigInt)を自動的に解析します。それ以外の型はすべて文字列として届くため、timestamptz、date、numeric などにはカスタムパーサーを追加してください。全リストについては references/type-parsers.md を参照してください。
ソース:AGENTS.md:300-308
中:params で予約済みのパラメーター名を使用する
誤り:
const stream = new ShapeStream({
url: '/api/todos',
params: {
table: 'todos',
cursor: 'abc', // Reserved!
offset: '0', // Reserved!
},
})
正しい例:
const stream = new ShapeStream({
url: '/api/todos',
params: {
table: 'todos',
page_cursor: 'abc',
page_offset: '0',
},
})
ReservedParamError がスローされます。cursor、handle、live、offset、cache-buster および subset__* をプレフィックスとするすべてのパラメーター名は、Electric プロトコルで予約されています。
ソース:packages/typescript-client/src/client.ts:1984-1985
中:実行中のストリームのシェイプオプションを変更する
誤り:
const stream = new ShapeStream({
url: '/api/todos',
params: { table: 'todos', where: "status = 'active'" },
})
// Later...
stream.options.params.where = "status = 'done'" // No effect!
正しい例:
// Create a new stream with different params
const newStream = new ShapeStream({
url: '/api/todos',
params: { table: 'todos', where: "status = 'done'" },
})
シェイプはサブスクリプションごとに不変です。実行中のストリームで params を変更しても効果はありません。フィルターを変更する場合は、新しい ShapeStream インスタンスを作成してください。
ソース:AGENTS.md:106
参考資料
関連項目:electric-proxy-auth/SKILL.md — シェイプ URL は Electric に直接ではなく、プロキシのルートを指す必要があります。 関連項目:electric-debugging/SKILL.md — 同期の問題を診断するうえで、onError の動作とバックオフは不可欠です。
バージョン
@electric-sql/client v1.5.10 が対象です。