@syncular/server 0.0.1-98 → 0.0.2-126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +25 -0
  2. package/dist/blobs/adapters/filesystem.d.ts +31 -0
  3. package/dist/blobs/adapters/filesystem.d.ts.map +1 -0
  4. package/dist/blobs/adapters/filesystem.js +140 -0
  5. package/dist/blobs/adapters/filesystem.js.map +1 -0
  6. package/dist/blobs/adapters/s3.d.ts +3 -2
  7. package/dist/blobs/adapters/s3.d.ts.map +1 -1
  8. package/dist/blobs/adapters/s3.js +49 -0
  9. package/dist/blobs/adapters/s3.js.map +1 -1
  10. package/dist/blobs/index.d.ts +1 -0
  11. package/dist/blobs/index.d.ts.map +1 -1
  12. package/dist/blobs/index.js +1 -0
  13. package/dist/blobs/index.js.map +1 -1
  14. package/dist/compaction.d.ts +1 -1
  15. package/dist/compaction.js +1 -1
  16. package/dist/{shapes → handlers}/create-handler.d.ts +18 -5
  17. package/dist/handlers/create-handler.d.ts.map +1 -0
  18. package/dist/{shapes → handlers}/create-handler.js +54 -17
  19. package/dist/handlers/create-handler.js.map +1 -0
  20. package/dist/handlers/index.d.ts.map +1 -0
  21. package/dist/handlers/index.js.map +1 -0
  22. package/dist/handlers/registry.d.ts.map +1 -0
  23. package/dist/handlers/registry.js.map +1 -0
  24. package/dist/{shapes → handlers}/types.d.ts +7 -7
  25. package/dist/{shapes → handlers}/types.d.ts.map +1 -1
  26. package/dist/{shapes → handlers}/types.js.map +1 -1
  27. package/dist/helpers/conflict.d.ts +1 -1
  28. package/dist/helpers/conflict.d.ts.map +1 -1
  29. package/dist/helpers/emitted-change.d.ts +1 -1
  30. package/dist/helpers/emitted-change.d.ts.map +1 -1
  31. package/dist/index.d.ts +2 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/notify.d.ts +47 -0
  36. package/dist/notify.d.ts.map +1 -0
  37. package/dist/notify.js +85 -0
  38. package/dist/notify.js.map +1 -0
  39. package/dist/proxy/handler.d.ts +1 -1
  40. package/dist/proxy/handler.d.ts.map +1 -1
  41. package/dist/proxy/handler.js +7 -7
  42. package/dist/proxy/handler.js.map +1 -1
  43. package/dist/proxy/oplog.d.ts +1 -1
  44. package/dist/proxy/oplog.d.ts.map +1 -1
  45. package/dist/proxy/oplog.js +6 -6
  46. package/dist/proxy/oplog.js.map +1 -1
  47. package/dist/pull.d.ts +2 -2
  48. package/dist/pull.d.ts.map +1 -1
  49. package/dist/pull.js +48 -9
  50. package/dist/pull.js.map +1 -1
  51. package/dist/push.d.ts +2 -2
  52. package/dist/push.d.ts.map +1 -1
  53. package/dist/push.js +1 -1
  54. package/dist/push.js.map +1 -1
  55. package/dist/snapshot-chunks/db-metadata.d.ts.map +1 -1
  56. package/dist/snapshot-chunks/db-metadata.js +14 -3
  57. package/dist/snapshot-chunks/db-metadata.js.map +1 -1
  58. package/dist/snapshot-chunks/index.d.ts +0 -1
  59. package/dist/snapshot-chunks/index.d.ts.map +1 -1
  60. package/dist/snapshot-chunks/index.js +0 -1
  61. package/dist/snapshot-chunks/index.js.map +1 -1
  62. package/dist/subscriptions/resolve.d.ts +6 -6
  63. package/dist/subscriptions/resolve.d.ts.map +1 -1
  64. package/dist/subscriptions/resolve.js +53 -14
  65. package/dist/subscriptions/resolve.js.map +1 -1
  66. package/package.json +2 -2
  67. package/src/blobs/adapters/filesystem.test.ts +132 -0
  68. package/src/blobs/adapters/filesystem.ts +189 -0
  69. package/src/blobs/adapters/s3.test.ts +522 -0
  70. package/src/blobs/adapters/s3.ts +55 -2
  71. package/src/blobs/index.ts +1 -0
  72. package/src/compaction.ts +1 -1
  73. package/src/{shapes → handlers}/create-handler.ts +111 -21
  74. package/src/{shapes → handlers}/types.ts +10 -7
  75. package/src/helpers/conflict.ts +1 -1
  76. package/src/helpers/emitted-change.ts +1 -1
  77. package/src/index.ts +2 -1
  78. package/src/notify.test.ts +516 -0
  79. package/src/notify.ts +131 -0
  80. package/src/proxy/handler.test.ts +3 -3
  81. package/src/proxy/handler.ts +8 -8
  82. package/src/proxy/oplog.ts +7 -7
  83. package/src/pull.ts +66 -12
  84. package/src/push.ts +3 -3
  85. package/src/snapshot-chunks/db-metadata.test.ts +69 -0
  86. package/src/snapshot-chunks/db-metadata.ts +14 -3
  87. package/src/snapshot-chunks/index.ts +0 -1
  88. package/src/subscriptions/resolve.ts +73 -18
  89. package/dist/shapes/create-handler.d.ts.map +0 -1
  90. package/dist/shapes/create-handler.js.map +0 -1
  91. package/dist/shapes/index.d.ts.map +0 -1
  92. package/dist/shapes/index.js.map +0 -1
  93. package/dist/shapes/registry.d.ts.map +0 -1
  94. package/dist/shapes/registry.js.map +0 -1
  95. package/dist/snapshot-chunks/adapters/s3.d.ts +0 -74
  96. package/dist/snapshot-chunks/adapters/s3.d.ts.map +0 -1
  97. package/dist/snapshot-chunks/adapters/s3.js +0 -50
  98. package/dist/snapshot-chunks/adapters/s3.js.map +0 -1
  99. package/src/snapshot-chunks/adapters/s3.ts +0 -68
  100. /package/dist/{shapes → handlers}/index.d.ts +0 -0
  101. /package/dist/{shapes → handlers}/index.js +0 -0
  102. /package/dist/{shapes → handlers}/registry.d.ts +0 -0
  103. /package/dist/{shapes → handlers}/registry.js +0 -0
  104. /package/dist/{shapes → handlers}/types.js +0 -0
  105. /package/src/{shapes → handlers}/index.ts +0 -0
  106. /package/src/{shapes → handlers}/registry.ts +0 -0
@@ -24,7 +24,7 @@ export interface ExecuteProxyQueryArgs<DB extends SyncCoreDb = SyncCoreDb> {
24
24
  /** Server sync dialect */
25
25
  dialect: ServerSyncDialect;
26
26
  /** Proxy table registry for oplog generation */
27
- shapes: ProxyTableRegistry;
27
+ handlers: ProxyTableRegistry;
28
28
  /** Query context (actor/client IDs) */
29
29
  ctx: ProxyQueryContext;
30
30
  /** SQL query string */
@@ -100,7 +100,7 @@ function buildRawQuery(
100
100
  export async function executeProxyQuery<DB extends SyncCoreDb>(
101
101
  args: ExecuteProxyQueryArgs<DB>
102
102
  ): Promise<ExecuteProxyQueryResult> {
103
- const { db, dialect, shapes, ctx, sqlQuery, parameters } = args;
103
+ const { db, dialect, handlers, ctx, sqlQuery, parameters } = args;
104
104
 
105
105
  const mutation = detectMutation(sqlQuery);
106
106
 
@@ -110,10 +110,10 @@ export async function executeProxyQuery<DB extends SyncCoreDb>(
110
110
  return { rows: result.rows };
111
111
  }
112
112
 
113
- // Check if this table has a registered shape
114
- const shape = shapes.get(mutation.tableName);
115
- if (!shape) {
116
- // No shape registered - execute without oplog
113
+ // Check if this table has a registered handler
114
+ const handler = handlers.get(mutation.tableName);
115
+ if (!handler) {
116
+ // No handler registered - execute without oplog
117
117
  // This allows proxy operations on non-synced tables
118
118
  const result = await buildRawQuery(sqlQuery, parameters).execute(db);
119
119
  return {
@@ -122,7 +122,7 @@ export async function executeProxyQuery<DB extends SyncCoreDb>(
122
122
  };
123
123
  }
124
124
 
125
- // Mutation with registered shape - append RETURNING * and create oplog
125
+ // Mutation with registered handler - append RETURNING * and create oplog
126
126
  const hasReturning = hasReturningClause(sqlQuery);
127
127
  if (hasReturning && !hasReturningWildcard(sqlQuery)) {
128
128
  throw new Error(
@@ -146,7 +146,7 @@ export async function executeProxyQuery<DB extends SyncCoreDb>(
146
146
  actorId: ctx.actorId,
147
147
  clientId: ctx.clientId,
148
148
  partitionId: ctx.partitionId,
149
- shape,
149
+ handler,
150
150
  operation: mutation.operation,
151
151
  rows: affectedRows,
152
152
  });
@@ -30,19 +30,19 @@ export async function createOplogEntries<DB extends SyncCoreDb>(args: {
30
30
  actorId: string;
31
31
  clientId: string;
32
32
  partitionId?: string;
33
- shape: ProxyTableHandler;
33
+ handler: ProxyTableHandler;
34
34
  operation: SyncOp;
35
35
  rows: Record<string, unknown>[];
36
36
  }): Promise<{ commitSeq: number; affectedTables: string[] }> {
37
- const { trx, dialect, actorId, clientId, shape, operation, rows } = args;
37
+ const { trx, dialect, actorId, clientId, handler, operation, rows } = args;
38
38
  const partitionId = args.partitionId ?? 'default';
39
39
 
40
40
  if (rows.length === 0) {
41
41
  return { commitSeq: 0, affectedTables: [] };
42
42
  }
43
43
 
44
- const pk = shape.primaryKey ?? 'id';
45
- const versionCol = shape.versionColumn ?? 'server_version';
44
+ const pk = handler.primaryKey ?? 'id';
45
+ const versionCol = handler.versionColumn ?? 'server_version';
46
46
 
47
47
  // Create commit record
48
48
  const commitResult = await sql<{ commit_seq: number }>`
@@ -73,15 +73,15 @@ export async function createOplogEntries<DB extends SyncCoreDb>(args: {
73
73
 
74
74
  // Compute scopes for all rows and collect changes
75
75
  const affectedTablesSet = new Set<string>();
76
- affectedTablesSet.add(shape.table);
76
+ affectedTablesSet.add(handler.table);
77
77
 
78
78
  const changes = rows.map((row) => {
79
- const scopes = shape.computeScopes(row);
79
+ const scopes = handler.computeScopes(row);
80
80
 
81
81
  return {
82
82
  commit_seq: commitSeq,
83
83
  partition_id: partitionId,
84
- table: shape.table,
84
+ table: handler.table,
85
85
  row_id: String(row[pk]),
86
86
  op: operation,
87
87
  row_json: operation === 'delete' ? null : row,
package/src/pull.ts CHANGED
@@ -20,9 +20,10 @@ import {
20
20
  startSyncSpan,
21
21
  } from '@syncular/core';
22
22
  import type { Kysely } from 'kysely';
23
- import type { ServerSyncDialect } from './dialect/types';
23
+ import type { DbExecutor, ServerSyncDialect } from './dialect/types';
24
+ import type { TableRegistry } from './handlers/registry';
25
+ import { EXTERNAL_CLIENT_ID } from './notify';
24
26
  import type { SyncCoreDb } from './schema';
25
- import type { TableRegistry } from './shapes/registry';
26
27
  import {
27
28
  insertSnapshotChunk,
28
29
  readSnapshotChunkRefByPageKey,
@@ -271,10 +272,37 @@ function recordPullMetrics(args: {
271
272
  );
272
273
  }
273
274
 
275
+ /**
276
+ * Read synthetic commits created by notifyExternalDataChange() after a given cursor.
277
+ * Returns commit_seq and affected tables for each external change commit.
278
+ */
279
+ async function readExternalDataChanges<DB extends SyncCoreDb>(
280
+ trx: DbExecutor<DB>,
281
+ dialect: ServerSyncDialect,
282
+ args: { partitionId: string; afterCursor: number }
283
+ ): Promise<Array<{ commitSeq: number; tables: string[] }>> {
284
+ type SyncExecutor = Pick<Kysely<SyncCoreDb>, 'selectFrom'>;
285
+ const executor = trx as SyncExecutor;
286
+
287
+ const rows = await executor
288
+ .selectFrom('sync_commits')
289
+ .select(['commit_seq', 'affected_tables'])
290
+ .where('partition_id', '=', args.partitionId)
291
+ .where('client_id', '=', EXTERNAL_CLIENT_ID)
292
+ .where('commit_seq', '>', args.afterCursor)
293
+ .orderBy('commit_seq', 'asc')
294
+ .execute();
295
+
296
+ return rows.map((row) => ({
297
+ commitSeq: Number(row.commit_seq),
298
+ tables: dialect.dbToArray(row.affected_tables),
299
+ }));
300
+ }
301
+
274
302
  export async function pull<DB extends SyncCoreDb>(args: {
275
303
  db: Kysely<DB>;
276
304
  dialect: ServerSyncDialect;
277
- shapes: TableRegistry<DB>;
305
+ handlers: TableRegistry<DB>;
278
306
  actorId: string;
279
307
  partitionId?: string;
280
308
  request: SyncPullRequest;
@@ -325,7 +353,7 @@ export async function pull<DB extends SyncCoreDb>(args: {
325
353
  db,
326
354
  actorId: args.actorId,
327
355
  subscriptions: request.subscriptions ?? [],
328
- shapes: args.shapes,
356
+ handlers: args.handlers,
329
357
  });
330
358
 
331
359
  const result = await dialect.executeInTransaction(db, async (trx) => {
@@ -342,10 +370,33 @@ export async function pull<DB extends SyncCoreDb>(args: {
342
370
  const activeSubscriptions: { scopes: ScopeValues }[] = [];
343
371
  const nextCursors: number[] = [];
344
372
 
373
+ // Detect external data changes (synthetic commits from notifyExternalDataChange)
374
+ // Compute minimum cursor across all active subscriptions to scope the query.
375
+ let minSubCursor = Number.MAX_SAFE_INTEGER;
376
+ for (const sub of resolved) {
377
+ if (
378
+ sub.status === 'revoked' ||
379
+ Object.keys(sub.scopes).length === 0
380
+ )
381
+ continue;
382
+ const cursor = Math.max(-1, sub.cursor ?? -1);
383
+ if (cursor >= 0 && cursor < minSubCursor) {
384
+ minSubCursor = cursor;
385
+ }
386
+ }
387
+
388
+ const externalDataChanges =
389
+ minSubCursor < Number.MAX_SAFE_INTEGER && minSubCursor >= 0
390
+ ? await readExternalDataChanges(trx, dialect, {
391
+ partitionId,
392
+ afterCursor: minSubCursor,
393
+ })
394
+ : [];
395
+
345
396
  for (const sub of resolved) {
346
397
  const cursor = Math.max(-1, sub.cursor ?? -1);
347
- // Validate shape exists (throws if not registered)
348
- args.shapes.getOrThrow(sub.shape);
398
+ // Validate table handler exists (throws if not registered)
399
+ args.handlers.getOrThrow(sub.table);
349
400
 
350
401
  if (
351
402
  sub.status === 'revoked' ||
@@ -369,11 +420,14 @@ export async function pull<DB extends SyncCoreDb>(args: {
369
420
  sub.bootstrapState != null ||
370
421
  cursor < 0 ||
371
422
  cursor > maxCommitSeq ||
372
- (minCommitSeq > 0 && cursor < minCommitSeq - 1);
423
+ (minCommitSeq > 0 && cursor < minCommitSeq - 1) ||
424
+ externalDataChanges.some(
425
+ (c) => c.commitSeq > cursor && c.tables.includes(sub.table)
426
+ );
373
427
 
374
428
  if (needsBootstrap) {
375
- const tables = args.shapes
376
- .getBootstrapOrderFor(sub.shape)
429
+ const tables = args.handlers
430
+ .getBootstrapOrderFor(sub.table)
377
431
  .map((handler) => handler.table);
378
432
 
379
433
  const initState: SyncBootstrapState = {
@@ -547,7 +601,7 @@ export async function pull<DB extends SyncCoreDb>(args: {
547
601
  break;
548
602
  }
549
603
 
550
- const tableHandler = args.shapes.getOrThrow(nextTableName);
604
+ const tableHandler = args.handlers.getOrThrow(nextTableName);
551
605
  if (!activeBundle || activeBundle.table !== nextTableName) {
552
606
  if (activeBundle) {
553
607
  await flushSnapshotBundle(activeBundle);
@@ -631,7 +685,7 @@ export async function pull<DB extends SyncCoreDb>(args: {
631
685
  partitionId,
632
686
  cursor,
633
687
  limitCommits,
634
- tables: [sub.shape],
688
+ tables: [sub.table],
635
689
  });
636
690
  const maxScannedCommitSeq =
637
691
  scannedCommitSeqs.length > 0
@@ -656,7 +710,7 @@ export async function pull<DB extends SyncCoreDb>(args: {
656
710
 
657
711
  for await (const row of dialect.iterateIncrementalPullRows(trx, {
658
712
  partitionId,
659
- table: sub.shape,
713
+ table: sub.table,
660
714
  scopes: effectiveScopes,
661
715
  cursor,
662
716
  limitCommits,
package/src/push.ts CHANGED
@@ -16,8 +16,8 @@ import type {
16
16
  } from 'kysely';
17
17
  import { sql } from 'kysely';
18
18
  import type { ServerSyncDialect } from './dialect/types';
19
+ import type { TableRegistry } from './handlers/registry';
19
20
  import type { SyncCoreDb } from './schema';
20
- import type { TableRegistry } from './shapes/registry';
21
21
 
22
22
  // biome-ignore lint/complexity/noBannedTypes: Kysely uses `{}` as the initial "no selected columns yet" marker.
23
23
  type EmptySelection = {};
@@ -136,7 +136,7 @@ function recordPushMetrics(args: {
136
136
  export async function pushCommit<DB extends SyncCoreDb>(args: {
137
137
  db: Kysely<DB>;
138
138
  dialect: ServerSyncDialect;
139
- shapes: TableRegistry<DB>;
139
+ handlers: TableRegistry<DB>;
140
140
  actorId: string;
141
141
  partitionId?: string;
142
142
  request: SyncPushRequest;
@@ -377,7 +377,7 @@ export async function pushCommit<DB extends SyncCoreDb>(args: {
377
377
 
378
378
  for (let i = 0; i < ops.length; i++) {
379
379
  const op = ops[i]!;
380
- const handler = args.shapes.getOrThrow(op.table);
380
+ const handler = args.handlers.getOrThrow(op.table);
381
381
  const applied = await handler.applyOperation(
382
382
  {
383
383
  db: trx,
@@ -36,6 +36,19 @@ function createInMemoryBlobAdapter(): BlobStorageAdapter {
36
36
  };
37
37
  }
38
38
 
39
+ function createBodyStream(
40
+ chunks: readonly Uint8Array[]
41
+ ): ReadableStream<Uint8Array> {
42
+ return new ReadableStream<Uint8Array>({
43
+ start(controller) {
44
+ for (const chunk of chunks) {
45
+ controller.enqueue(chunk);
46
+ }
47
+ controller.close();
48
+ },
49
+ });
50
+ }
51
+
39
52
  describe('createDbMetadataChunkStorage', () => {
40
53
  let db: Kysely<TestDb>;
41
54
 
@@ -97,4 +110,60 @@ describe('createDbMetadataChunkStorage', () => {
97
110
 
98
111
  expect(Number(countResult.rows[0]?.count ?? 0)).toBe(1);
99
112
  });
113
+
114
+ it('disables blob checksums for chunk stream writes', async () => {
115
+ const putStreamMetadata: Array<Record<string, unknown> | undefined> = [];
116
+ const blobAdapter: BlobStorageAdapter = {
117
+ name: 'memory-stream',
118
+ async signUpload() {
119
+ return { url: 'https://example.test/upload', method: 'PUT' };
120
+ },
121
+ async signDownload() {
122
+ return 'https://example.test/download';
123
+ },
124
+ async exists() {
125
+ return false;
126
+ },
127
+ async delete() {},
128
+ async put() {},
129
+ async get() {
130
+ return null;
131
+ },
132
+ async putStream(_hash, stream, metadata) {
133
+ putStreamMetadata.push(metadata);
134
+ const reader = stream.getReader();
135
+ try {
136
+ while (true) {
137
+ const { done } = await reader.read();
138
+ if (done) break;
139
+ }
140
+ } finally {
141
+ reader.releaseLock();
142
+ }
143
+ },
144
+ };
145
+
146
+ const storage = createDbMetadataChunkStorage({
147
+ db,
148
+ blobAdapter,
149
+ });
150
+
151
+ await storage.storeChunkStream({
152
+ partitionId: 'p1',
153
+ scopeKey: 'scope-key',
154
+ scope: 'tasks',
155
+ asOfCommitSeq: 1,
156
+ rowCursor: null,
157
+ rowLimit: 100,
158
+ encoding: 'json-row-frame-v1',
159
+ compression: 'gzip',
160
+ sha256: 'chunk-sha',
161
+ expiresAt: new Date(Date.now() + 60_000).toISOString(),
162
+ byteLength: 4,
163
+ bodyStream: createBodyStream([new Uint8Array([1, 2, 3, 4])]),
164
+ });
165
+
166
+ expect(putStreamMetadata).toHaveLength(1);
167
+ expect(putStreamMetadata[0]?.disableChecksum).toBe(true);
168
+ });
100
169
  });
@@ -288,9 +288,17 @@ export function createDbMetadataChunkStorage(
288
288
  if (!blobExists) {
289
289
  // Store body in blob adapter
290
290
  if (blobAdapter.put) {
291
- await blobAdapter.put(blobHash, body);
291
+ await blobAdapter.put(blobHash, body, {
292
+ disableChecksum: true,
293
+ byteLength: body.length,
294
+ contentLength: body.length,
295
+ });
292
296
  } else if (blobAdapter.putStream) {
293
- await blobAdapter.putStream(blobHash, bytesToStream(body));
297
+ await blobAdapter.putStream(blobHash, bytesToStream(body), {
298
+ disableChecksum: true,
299
+ byteLength: body.length,
300
+ contentLength: body.length,
301
+ });
294
302
  } else {
295
303
  throw new Error(
296
304
  `Blob adapter ${blobAdapter.name} does not support direct put() for snapshot chunks`
@@ -343,10 +351,13 @@ export function createDbMetadataChunkStorage(
343
351
  const uploadPromise =
344
352
  typeof byteLength === 'number'
345
353
  ? blobAdapter.putStream(blobHash, uploadStream, {
354
+ disableChecksum: true,
346
355
  byteLength,
347
356
  contentLength: byteLength,
348
357
  })
349
- : blobAdapter.putStream(blobHash, uploadStream);
358
+ : blobAdapter.putStream(blobHash, uploadStream, {
359
+ disableChecksum: true,
360
+ });
350
361
  const countPromise = streamByteLength(countStream);
351
362
 
352
363
  const [, countedByteLength] = await Promise.all([
@@ -4,6 +4,5 @@
4
4
  * Separates chunk metadata (database) from body content (blob storage).
5
5
  */
6
6
 
7
- export * from './adapters/s3';
8
7
  export * from './db-metadata';
9
8
  export * from './types';
@@ -1,7 +1,11 @@
1
- import type { ScopeValues, SyncSubscriptionRequest } from '@syncular/core';
1
+ import {
2
+ extractScopeVars,
3
+ type ScopeValues,
4
+ type SyncSubscriptionRequest,
5
+ } from '@syncular/core';
2
6
  import type { Kysely } from 'kysely';
7
+ import type { TableRegistry } from '../handlers/registry';
3
8
  import type { SyncCoreDb } from '../schema';
4
- import type { TableRegistry } from '../shapes/registry';
5
9
 
6
10
  export class InvalidSubscriptionScopeError extends Error {
7
11
  constructor(message: string) {
@@ -15,7 +19,7 @@ export class InvalidSubscriptionScopeError extends Error {
15
19
  */
16
20
  export interface ResolvedSubscription {
17
21
  id: string;
18
- shape: string;
22
+ table: string;
19
23
  scopes: ScopeValues;
20
24
  params: Record<string, unknown> | undefined;
21
25
  cursor: number;
@@ -83,12 +87,46 @@ function scopesEmpty(scopes: ScopeValues): boolean {
83
87
  return true;
84
88
  }
85
89
 
90
+ /**
91
+ * Collect valid scope keys from handler scope patterns.
92
+ */
93
+ function collectScopeKeys(scopePatterns: readonly string[]): Set<string> {
94
+ const keys = new Set<string>();
95
+ for (const pattern of scopePatterns) {
96
+ for (const key of extractScopeVars(pattern)) {
97
+ keys.add(key);
98
+ }
99
+ }
100
+ return keys;
101
+ }
102
+
103
+ function validateScopeKeys(args: {
104
+ scopeValues: ScopeValues;
105
+ validScopeKeys: Set<string>;
106
+ source: string;
107
+ subscriptionId: string;
108
+ table: string;
109
+ }): void {
110
+ for (const scopeKey of Object.keys(args.scopeValues)) {
111
+ if (args.validScopeKeys.has(scopeKey)) {
112
+ continue;
113
+ }
114
+ const expectedKeys =
115
+ args.validScopeKeys.size > 0
116
+ ? Array.from(args.validScopeKeys).sort().join(', ')
117
+ : '(none)';
118
+ throw new InvalidSubscriptionScopeError(
119
+ `Invalid scope key "${scopeKey}" in ${args.source} for subscription "${args.subscriptionId}" on table "${args.table}". Expected keys: ${expectedKeys}`
120
+ );
121
+ }
122
+ }
123
+
86
124
  /**
87
125
  * Resolve effective scopes for subscriptions.
88
126
  *
89
127
  * For each subscription:
90
- * 1. Look up the shape by subscription.shape
91
- * 2. Call shape.resolveScopes() to get allowed scopes for this actor
128
+ * 1. Look up the table handler by subscription.table
129
+ * 2. Call handler.resolveScopes() to get allowed scopes for this actor
92
130
  * 3. Intersect requested scopes with allowed scopes
93
131
  * 4. Mark as revoked if no effective scopes
94
132
  */
@@ -98,7 +136,7 @@ export async function resolveEffectiveScopesForSubscriptions<
98
136
  db: Kysely<DB>;
99
137
  actorId: string;
100
138
  subscriptions: SyncSubscriptionRequest[];
101
- shapes: TableRegistry<DB>;
139
+ handlers: TableRegistry<DB>;
102
140
  }): Promise<ResolvedSubscription[]> {
103
141
  const out: ResolvedSubscription[] = [];
104
142
  const seenIds = new Set<string>();
@@ -114,23 +152,33 @@ export async function resolveEffectiveScopesForSubscriptions<
114
152
  }
115
153
  seenIds.add(sub.id);
116
154
 
117
- if (!sub.shape || typeof sub.shape !== 'string') {
155
+ if (!sub.table || typeof sub.table !== 'string') {
118
156
  throw new InvalidSubscriptionScopeError(
119
- `Subscription ${sub.id} requires a shape (table name)`
157
+ `Subscription ${sub.id} requires a table name`
120
158
  );
121
159
  }
122
160
 
123
- const shape = args.shapes.get(sub.shape);
124
- if (!shape) {
161
+ const handler = args.handlers.get(sub.table);
162
+ if (!handler) {
125
163
  throw new InvalidSubscriptionScopeError(
126
- `Unknown shape: ${sub.shape} for subscription ${sub.id}`
164
+ `Unknown table: ${sub.table} for subscription ${sub.id}`
127
165
  );
128
166
  }
129
167
 
130
- // Get allowed scopes from the shape
168
+ const validScopeKeys = collectScopeKeys(handler.scopePatterns);
169
+ const requested = sub.scopes ?? {};
170
+ validateScopeKeys({
171
+ scopeValues: requested,
172
+ validScopeKeys,
173
+ source: 'requested scopes',
174
+ subscriptionId: sub.id,
175
+ table: sub.table,
176
+ });
177
+
178
+ // Get allowed scopes from the handler
131
179
  let allowed: ScopeValues;
132
180
  try {
133
- allowed = await shape.resolveScopes({
181
+ allowed = await handler.resolveScopes({
134
182
  db: args.db,
135
183
  actorId: args.actorId,
136
184
  });
@@ -138,12 +186,12 @@ export async function resolveEffectiveScopesForSubscriptions<
138
186
  // Scope resolution failed - mark subscription as revoked
139
187
  // rather than failing the entire pull
140
188
  console.error(
141
- `[resolveScopes] Failed for shape ${sub.shape}, subscription ${sub.id}:`,
189
+ `[resolveScopes] Failed for table ${sub.table}, subscription ${sub.id}:`,
142
190
  resolveErr
143
191
  );
144
192
  out.push({
145
193
  id: sub.id,
146
- shape: sub.shape,
194
+ table: sub.table,
147
195
  scopes: {},
148
196
  params: sub.params,
149
197
  cursor: sub.cursor,
@@ -153,14 +201,21 @@ export async function resolveEffectiveScopesForSubscriptions<
153
201
  continue;
154
202
  }
155
203
 
204
+ validateScopeKeys({
205
+ scopeValues: allowed,
206
+ validScopeKeys,
207
+ source: 'resolveScopes() result',
208
+ subscriptionId: sub.id,
209
+ table: sub.table,
210
+ });
211
+
156
212
  // Intersect with requested scopes
157
- const requested = sub.scopes ?? {};
158
213
  const effective = intersectScopes(requested, allowed);
159
214
 
160
215
  if (scopesEmpty(effective)) {
161
216
  out.push({
162
217
  id: sub.id,
163
- shape: sub.shape,
218
+ table: sub.table,
164
219
  scopes: {},
165
220
  params: sub.params,
166
221
  cursor: sub.cursor,
@@ -172,7 +227,7 @@ export async function resolveEffectiveScopesForSubscriptions<
172
227
 
173
228
  out.push({
174
229
  id: sub.id,
175
- shape: sub.shape,
230
+ table: sub.table,
176
231
  scopes: effective,
177
232
  params: sub.params,
178
233
  cursor: sub.cursor,
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-handler.d.ts","sourceRoot":"","sources":["../../src/shapes/create-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAEV,WAAW,EACX,eAAe,IAAI,qBAAqB,EACxC,YAAY,EACZ,aAAa,EACd,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAMV,UAAU,EAEV,UAAU,EAGX,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAGV,2BAA2B,EAC3B,aAAa,EAEb,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,KAAK,eAAe,GAChB,IAAI,GACJ;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAoBzD;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,0BAA0B,CACzC,QAAQ,SAAS,UAAU,EAC3B,QAAQ,EACR,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,QAAQ,GAAG,MAAM;IAE1D,iCAAiC;IACjC,KAAK,EAAE,SAAS,CAAC;IAEjB;;;;;;;;;;;;;;OAcG;IACH,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAEhC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB,2CAA2C;IAC3C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;;;;;;OASG;IACH,aAAa,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAEtE;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CACjB,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,EACxB,GAAG,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5B,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAErC;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAClB,GAAG,EAAE,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,KACjC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAEzB;;;OAGG;IACH,SAAS,CAAC,EAAE,CACV,GAAG,EAAE,2BAA2B,CAAC,QAAQ,CAAC,EAC1C,EAAE,EAAE,aAAa,KACd,OAAO,CAAC,eAAe,CAAC,CAAC;IAE9B;;OAEG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC;IAEpD;;OAEG;IACH,cAAc,CAAC,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAEhE;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,YAAY,CAAC;CAChE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,SAAS,UAAU,EAC3B,QAAQ,EACR,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,QAAQ,GAAG,MAAM,EAE1D,OAAO,EAAE,0BAA0B,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,GACjE,kBAAkB,CAAC,QAAQ,CAAC,CA+Y9B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-handler.js","sourceRoot":"","sources":["../../src/shapes/create-handler.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shapes/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shapes/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/shapes/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,qBAAa,aAAa,CAAC,EAAE,SAAS,UAAU,GAAG,UAAU;IAC3D,OAAO,CAAC,MAAM,CAA6C;IAE3D,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC,EAAE,CAAC,GAAG,IAAI,CAgB9C;IAED,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAAC,EAAE,CAAC,GAAG,SAAS,CAErD;IAED,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAIhD;IAED,MAAM,IAAI,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAEjC;IAED;;;OAGG;IACH,iBAAiB,IAAI,kBAAkB,CAAC,EAAE,CAAC,EAAE,CA8B5C;IAED;;;OAGG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAAC,EAAE,CAAC,EAAE,CA6B5D;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/shapes/registry.ts"],"names":[],"mappings":"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"}