@syncular/server 0.0.6-55 → 0.0.6-66

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 (70) hide show
  1. package/dist/handlers/collection.d.ts +12 -0
  2. package/dist/handlers/collection.d.ts.map +1 -0
  3. package/dist/handlers/collection.js +64 -0
  4. package/dist/handlers/collection.js.map +1 -0
  5. package/dist/handlers/create-handler.d.ts +9 -9
  6. package/dist/handlers/create-handler.d.ts.map +1 -1
  7. package/dist/handlers/create-handler.js.map +1 -1
  8. package/dist/handlers/index.d.ts +1 -1
  9. package/dist/handlers/index.d.ts.map +1 -1
  10. package/dist/handlers/index.js +1 -1
  11. package/dist/handlers/index.js.map +1 -1
  12. package/dist/handlers/types.d.ts +18 -12
  13. package/dist/handlers/types.d.ts.map +1 -1
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/proxy/collection.d.ts +9 -0
  19. package/dist/proxy/collection.d.ts.map +1 -0
  20. package/dist/proxy/collection.js +21 -0
  21. package/dist/proxy/collection.js.map +1 -0
  22. package/dist/proxy/handler.d.ts +3 -3
  23. package/dist/proxy/handler.d.ts.map +1 -1
  24. package/dist/proxy/handler.js +2 -1
  25. package/dist/proxy/handler.js.map +1 -1
  26. package/dist/proxy/index.d.ts +1 -1
  27. package/dist/proxy/index.d.ts.map +1 -1
  28. package/dist/proxy/index.js +3 -3
  29. package/dist/proxy/index.js.map +1 -1
  30. package/dist/pull.d.ts +5 -5
  31. package/dist/pull.d.ts.map +1 -1
  32. package/dist/pull.js +8 -8
  33. package/dist/pull.js.map +1 -1
  34. package/dist/push.d.ts +5 -5
  35. package/dist/push.d.ts.map +1 -1
  36. package/dist/push.js +5 -3
  37. package/dist/push.js.map +1 -1
  38. package/dist/subscriptions/resolve.d.ts +5 -4
  39. package/dist/subscriptions/resolve.d.ts.map +1 -1
  40. package/dist/subscriptions/resolve.js +4 -2
  41. package/dist/subscriptions/resolve.js.map +1 -1
  42. package/dist/sync.d.ts +21 -0
  43. package/dist/sync.d.ts.map +1 -0
  44. package/dist/sync.js +23 -0
  45. package/dist/sync.js.map +1 -0
  46. package/package.json +2 -2
  47. package/src/handlers/collection.ts +121 -0
  48. package/src/handlers/create-handler.ts +23 -14
  49. package/src/handlers/index.ts +1 -1
  50. package/src/handlers/types.ts +29 -12
  51. package/src/index.ts +1 -0
  52. package/src/notify.test.ts +17 -17
  53. package/src/proxy/collection.ts +39 -0
  54. package/src/proxy/handler.test.ts +9 -7
  55. package/src/proxy/handler.ts +4 -4
  56. package/src/proxy/index.ts +8 -3
  57. package/src/pull.ts +35 -23
  58. package/src/push.ts +15 -8
  59. package/src/subscriptions/resolve.ts +11 -5
  60. package/src/sync.ts +101 -0
  61. package/dist/handlers/registry.d.ts +0 -20
  62. package/dist/handlers/registry.d.ts.map +0 -1
  63. package/dist/handlers/registry.js +0 -88
  64. package/dist/handlers/registry.js.map +0 -1
  65. package/dist/proxy/registry.d.ts +0 -35
  66. package/dist/proxy/registry.d.ts.map +0 -1
  67. package/dist/proxy/registry.js +0 -49
  68. package/dist/proxy/registry.js.map +0 -1
  69. package/src/handlers/registry.ts +0 -109
  70. package/src/proxy/registry.ts +0 -56
package/src/push.ts CHANGED
@@ -16,7 +16,11 @@ 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
+ import {
20
+ getServerHandlerOrThrow,
21
+ type ServerHandlerCollection,
22
+ } from './handlers/collection';
23
+ import type { SyncServerAuth } from './handlers/types';
20
24
  import type { SyncCoreDb } from './schema';
21
25
 
22
26
  // biome-ignore lint/complexity/noBannedTypes: Kysely uses `{}` as the initial "no selected columns yet" marker.
@@ -177,17 +181,19 @@ function recordPushMetrics(args: {
177
181
  );
178
182
  }
179
183
 
180
- export async function pushCommit<DB extends SyncCoreDb>(args: {
184
+ export async function pushCommit<
185
+ DB extends SyncCoreDb,
186
+ Auth extends SyncServerAuth,
187
+ >(args: {
181
188
  db: Kysely<DB>;
182
189
  dialect: ServerSyncDialect;
183
- handlers: TableRegistry<DB>;
184
- actorId: string;
185
- partitionId?: string;
190
+ handlers: ServerHandlerCollection<DB, Auth>;
191
+ auth: Auth;
186
192
  request: SyncPushRequest;
187
193
  }): Promise<PushCommitResult> {
188
194
  const { db, dialect, handlers, request } = args;
189
- const actorId = args.actorId;
190
- const partitionId = args.partitionId ?? 'default';
195
+ const actorId = args.auth.actorId;
196
+ const partitionId = args.auth.partitionId ?? 'default';
191
197
  const requestedOps = Array.isArray(request.operations)
192
198
  ? request.operations
193
199
  : [];
@@ -425,12 +431,13 @@ export async function pushCommit<DB extends SyncCoreDb>(args: {
425
431
 
426
432
  for (let i = 0; i < ops.length; i++) {
427
433
  const op = ops[i]!;
428
- const handler = handlers.getOrThrow(op.table);
434
+ const handler = getServerHandlerOrThrow(handlers, op.table);
429
435
  const applied = await handler.applyOperation(
430
436
  {
431
437
  db: trx,
432
438
  trx,
433
439
  actorId,
440
+ auth: args.auth,
434
441
  clientId: request.clientId,
435
442
  commitId,
436
443
  schemaVersion: request.schemaVersion,
@@ -4,7 +4,11 @@ import {
4
4
  type SyncSubscriptionRequest,
5
5
  } from '@syncular/core';
6
6
  import type { Kysely } from 'kysely';
7
- import type { TableRegistry } from '../handlers/registry';
7
+ import {
8
+ getServerHandler,
9
+ type ServerHandlerCollection,
10
+ } from '../handlers/collection';
11
+ import type { SyncServerAuth } from '../handlers/types';
8
12
  import type { SyncCoreDb } from '../schema';
9
13
 
10
14
  export class InvalidSubscriptionScopeError extends Error {
@@ -132,11 +136,12 @@ function validateScopeKeys(args: {
132
136
  */
133
137
  export async function resolveEffectiveScopesForSubscriptions<
134
138
  DB extends SyncCoreDb,
139
+ Auth extends SyncServerAuth,
135
140
  >(args: {
136
141
  db: Kysely<DB>;
137
- actorId: string;
142
+ auth: Auth;
138
143
  subscriptions: SyncSubscriptionRequest[];
139
- handlers: TableRegistry<DB>;
144
+ handlers: ServerHandlerCollection<DB, Auth>;
140
145
  }): Promise<ResolvedSubscription[]> {
141
146
  const out: ResolvedSubscription[] = [];
142
147
  const seenIds = new Set<string>();
@@ -158,7 +163,7 @@ export async function resolveEffectiveScopesForSubscriptions<
158
163
  );
159
164
  }
160
165
 
161
- const handler = args.handlers.get(sub.table);
166
+ const handler = getServerHandler(args.handlers, sub.table);
162
167
  if (!handler) {
163
168
  throw new InvalidSubscriptionScopeError(
164
169
  `Unknown table: ${sub.table} for subscription ${sub.id}`
@@ -180,7 +185,8 @@ export async function resolveEffectiveScopesForSubscriptions<
180
185
  try {
181
186
  allowed = await handler.resolveScopes({
182
187
  db: args.db,
183
- actorId: args.actorId,
188
+ actorId: args.auth.actorId,
189
+ auth: args.auth,
184
190
  });
185
191
  } catch (resolveErr) {
186
192
  // Scope resolution failed - mark subscription as revoked
package/src/sync.ts ADDED
@@ -0,0 +1,101 @@
1
+ import type {
2
+ ColumnCodecDialect,
3
+ ColumnCodecSource,
4
+ ScopeDefinition,
5
+ } from '@syncular/core';
6
+ import {
7
+ type CreateServerHandlerOptions,
8
+ createServerHandler,
9
+ } from './handlers';
10
+ import type { ServerTableHandler, SyncServerAuth } from './handlers/types';
11
+ import type { SyncCoreDb } from './schema';
12
+
13
+ type SharedTableName<ServerDB, ClientDB> = keyof ServerDB &
14
+ keyof ClientDB &
15
+ string;
16
+
17
+ export type ServerSyncHandlerOptionsForTable<
18
+ ServerDB extends SyncCoreDb,
19
+ ClientDB,
20
+ TableName extends SharedTableName<ServerDB, ClientDB>,
21
+ Auth extends SyncServerAuth,
22
+ ScopeDefs extends readonly ScopeDefinition[],
23
+ > = Omit<
24
+ CreateServerHandlerOptions<ServerDB, ClientDB, TableName, Auth, ScopeDefs>,
25
+ 'columnCodecs' | 'codecDialect'
26
+ >;
27
+
28
+ export interface ServerSyncConfig<
29
+ ServerDB extends SyncCoreDb = SyncCoreDb,
30
+ Auth extends SyncServerAuth = SyncServerAuth,
31
+ > {
32
+ authenticate: (request: Request) => Promise<Auth | null> | Auth | null;
33
+ handlers: ServerTableHandler<ServerDB, Auth>[];
34
+ }
35
+
36
+ export interface DefineServerSyncOptions<Auth extends SyncServerAuth> {
37
+ authenticate: (request: Request) => Promise<Auth | null> | Auth | null;
38
+ codecs?: ColumnCodecSource;
39
+ codecDialect?: ColumnCodecDialect;
40
+ }
41
+
42
+ export interface ServerSyncBuilder<
43
+ ServerDB extends SyncCoreDb,
44
+ ClientDB,
45
+ ScopeDefs extends readonly ScopeDefinition[],
46
+ Auth extends SyncServerAuth,
47
+ > extends ServerSyncConfig<ServerDB, Auth> {
48
+ addHandler<TableName extends SharedTableName<ServerDB, ClientDB>>(
49
+ options: ServerSyncHandlerOptionsForTable<
50
+ ServerDB,
51
+ ClientDB,
52
+ TableName,
53
+ Auth,
54
+ ScopeDefs
55
+ >
56
+ ): this;
57
+ }
58
+
59
+ export function defineServerSync<
60
+ ServerDB extends SyncCoreDb,
61
+ ClientDB,
62
+ ScopeDefs extends readonly ScopeDefinition[],
63
+ Auth extends SyncServerAuth,
64
+ >(
65
+ options: DefineServerSyncOptions<Auth>
66
+ ): ServerSyncBuilder<ServerDB, ClientDB, ScopeDefs, Auth> {
67
+ const handlers: ServerTableHandler<ServerDB, Auth>[] = [];
68
+ const registeredTables = new Set<string>();
69
+
70
+ const sync: ServerSyncBuilder<ServerDB, ClientDB, ScopeDefs, Auth> = {
71
+ authenticate: options.authenticate,
72
+ handlers,
73
+ addHandler<TableName extends SharedTableName<ServerDB, ClientDB>>(
74
+ handlerOptions: ServerSyncHandlerOptionsForTable<
75
+ ServerDB,
76
+ ClientDB,
77
+ TableName,
78
+ Auth,
79
+ ScopeDefs
80
+ >
81
+ ) {
82
+ if (registeredTables.has(handlerOptions.table)) {
83
+ throw new Error(
84
+ `Server table handler already registered: ${handlerOptions.table}`
85
+ );
86
+ }
87
+
88
+ handlers.push(
89
+ createServerHandler({
90
+ ...handlerOptions,
91
+ columnCodecs: options.codecs,
92
+ codecDialect: options.codecDialect,
93
+ })
94
+ );
95
+ registeredTables.add(handlerOptions.table);
96
+ return sync;
97
+ },
98
+ };
99
+
100
+ return sync;
101
+ }
@@ -1,20 +0,0 @@
1
- import type { SyncCoreDb } from '../schema';
2
- import type { ServerTableHandler } from './types';
3
- export declare class TableRegistry<DB extends SyncCoreDb = SyncCoreDb> {
4
- private tables;
5
- register(handler: ServerTableHandler<DB>): this;
6
- get(table: string): ServerTableHandler<DB> | undefined;
7
- getOrThrow(table: string): ServerTableHandler<DB>;
8
- getAll(): ServerTableHandler<DB>[];
9
- /**
10
- * Return tables in topological order (parents before children).
11
- * Throws if a circular dependency is detected.
12
- */
13
- getBootstrapOrder(): ServerTableHandler<DB>[];
14
- /**
15
- * Return bootstrap order for a target table and its dependencies.
16
- * Parents are returned before children.
17
- */
18
- getBootstrapOrderFor(table: string): ServerTableHandler<DB>[];
19
- }
20
- //# sourceMappingURL=registry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/handlers/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,88 +0,0 @@
1
- export class TableRegistry {
2
- tables = new Map();
3
- register(handler) {
4
- if (this.tables.has(handler.table)) {
5
- throw new Error(`Table "${handler.table}" is already registered`);
6
- }
7
- // Validate dependencies exist
8
- for (const dep of handler.dependsOn ?? []) {
9
- if (!this.tables.has(dep)) {
10
- throw new Error(`Table "${handler.table}" depends on unknown table "${dep}"`);
11
- }
12
- }
13
- this.tables.set(handler.table, handler);
14
- return this;
15
- }
16
- get(table) {
17
- return this.tables.get(table);
18
- }
19
- getOrThrow(table) {
20
- const handler = this.tables.get(table);
21
- if (!handler)
22
- throw new Error(`Unknown table: ${table}`);
23
- return handler;
24
- }
25
- getAll() {
26
- return Array.from(this.tables.values());
27
- }
28
- /**
29
- * Return tables in topological order (parents before children).
30
- * Throws if a circular dependency is detected.
31
- */
32
- getBootstrapOrder() {
33
- const visited = new Set();
34
- const sorted = [];
35
- const visiting = new Set();
36
- const visit = (table) => {
37
- if (visited.has(table))
38
- return;
39
- if (visiting.has(table)) {
40
- throw new Error(`Circular dependency detected involving table "${table}"`);
41
- }
42
- visiting.add(table);
43
- const handler = this.tables.get(table);
44
- if (handler) {
45
- for (const dep of handler.dependsOn ?? []) {
46
- visit(dep);
47
- }
48
- visited.add(table);
49
- visiting.delete(table);
50
- sorted.push(handler);
51
- }
52
- };
53
- for (const table of this.tables.keys()) {
54
- visit(table);
55
- }
56
- return sorted;
57
- }
58
- /**
59
- * Return bootstrap order for a target table and its dependencies.
60
- * Parents are returned before children.
61
- */
62
- getBootstrapOrderFor(table) {
63
- const visited = new Set();
64
- const sorted = [];
65
- const visiting = new Set();
66
- const visit = (name) => {
67
- if (visited.has(name))
68
- return;
69
- if (visiting.has(name)) {
70
- throw new Error(`Circular dependency detected involving table "${name}"`);
71
- }
72
- const handler = this.tables.get(name);
73
- if (!handler) {
74
- throw new Error(`Unknown table: ${name}`);
75
- }
76
- visiting.add(name);
77
- for (const dep of handler.dependsOn ?? []) {
78
- visit(dep);
79
- }
80
- visiting.delete(name);
81
- visited.add(name);
82
- sorted.push(handler);
83
- };
84
- visit(table);
85
- return sorted;
86
- }
87
- }
88
- //# sourceMappingURL=registry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/handlers/registry.ts"],"names":[],"mappings":"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"}
@@ -1,35 +0,0 @@
1
- /**
2
- * @syncular/server - Proxy Table Registry
3
- *
4
- * Registry for proxy table handlers.
5
- */
6
- import type { ProxyTableHandler } from './types';
7
- /**
8
- * Registry for proxy table handlers.
9
- *
10
- * Maps table names to table handlers for oplog generation.
11
- */
12
- export declare class ProxyTableRegistry {
13
- private handlers;
14
- /**
15
- * Register a proxy table handler.
16
- */
17
- register(handler: ProxyTableHandler): this;
18
- /**
19
- * Get handler by table name.
20
- */
21
- get(tableName: string): ProxyTableHandler | undefined;
22
- /**
23
- * Get handler by table name or throw.
24
- */
25
- getOrThrow(tableName: string): ProxyTableHandler;
26
- /**
27
- * Check if a table has a registered handler.
28
- */
29
- has(tableName: string): boolean;
30
- /**
31
- * Get all registered handlers.
32
- */
33
- getAll(): ProxyTableHandler[];
34
- }
35
- //# sourceMappingURL=registry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/proxy/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAwC;IAExD;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAGzC;IAED;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAEpD;IAED;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAM/C;IAED;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE9B;IAED;;OAEG;IACH,MAAM,IAAI,iBAAiB,EAAE,CAE5B;CACF"}
@@ -1,49 +0,0 @@
1
- /**
2
- * @syncular/server - Proxy Table Registry
3
- *
4
- * Registry for proxy table handlers.
5
- */
6
- /**
7
- * Registry for proxy table handlers.
8
- *
9
- * Maps table names to table handlers for oplog generation.
10
- */
11
- export class ProxyTableRegistry {
12
- handlers = new Map();
13
- /**
14
- * Register a proxy table handler.
15
- */
16
- register(handler) {
17
- this.handlers.set(handler.table, handler);
18
- return this;
19
- }
20
- /**
21
- * Get handler by table name.
22
- */
23
- get(tableName) {
24
- return this.handlers.get(tableName);
25
- }
26
- /**
27
- * Get handler by table name or throw.
28
- */
29
- getOrThrow(tableName) {
30
- const handler = this.handlers.get(tableName);
31
- if (!handler) {
32
- throw new Error(`No proxy table registered for table: ${tableName}`);
33
- }
34
- return handler;
35
- }
36
- /**
37
- * Check if a table has a registered handler.
38
- */
39
- has(tableName) {
40
- return this.handlers.has(tableName);
41
- }
42
- /**
43
- * Get all registered handlers.
44
- */
45
- getAll() {
46
- return Array.from(this.handlers.values());
47
- }
48
- }
49
- //# sourceMappingURL=registry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/proxy/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IACrB,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAC;IAExD;;OAEG;IACH,QAAQ,CAAC,OAA0B,EAAQ;QACzC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IAAA,CACb;IAED;;OAEG;IACH,GAAG,CAAC,SAAiB,EAAiC;QACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAAA,CACrC;IAED;;OAEG;IACH,UAAU,CAAC,SAAiB,EAAqB;QAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,wCAAwC,SAAS,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,OAAO,CAAC;IAAA,CAChB;IAED;;OAEG;IACH,GAAG,CAAC,SAAiB,EAAW;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAAA,CACrC;IAED;;OAEG;IACH,MAAM,GAAwB;QAC5B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAAA,CAC3C;CACF"}
@@ -1,109 +0,0 @@
1
- import type { SyncCoreDb } from '../schema';
2
- import type { ServerTableHandler } from './types';
3
-
4
- export class TableRegistry<DB extends SyncCoreDb = SyncCoreDb> {
5
- private tables = new Map<string, ServerTableHandler<DB>>();
6
-
7
- register(handler: ServerTableHandler<DB>): this {
8
- if (this.tables.has(handler.table)) {
9
- throw new Error(`Table "${handler.table}" is already registered`);
10
- }
11
-
12
- // Validate dependencies exist
13
- for (const dep of handler.dependsOn ?? []) {
14
- if (!this.tables.has(dep)) {
15
- throw new Error(
16
- `Table "${handler.table}" depends on unknown table "${dep}"`
17
- );
18
- }
19
- }
20
-
21
- this.tables.set(handler.table, handler);
22
- return this;
23
- }
24
-
25
- get(table: string): ServerTableHandler<DB> | undefined {
26
- return this.tables.get(table);
27
- }
28
-
29
- getOrThrow(table: string): ServerTableHandler<DB> {
30
- const handler = this.tables.get(table);
31
- if (!handler) throw new Error(`Unknown table: ${table}`);
32
- return handler;
33
- }
34
-
35
- getAll(): ServerTableHandler<DB>[] {
36
- return Array.from(this.tables.values());
37
- }
38
-
39
- /**
40
- * Return tables in topological order (parents before children).
41
- * Throws if a circular dependency is detected.
42
- */
43
- getBootstrapOrder(): ServerTableHandler<DB>[] {
44
- const visited = new Set<string>();
45
- const sorted: ServerTableHandler<DB>[] = [];
46
- const visiting = new Set<string>();
47
-
48
- const visit = (table: string) => {
49
- if (visited.has(table)) return;
50
- if (visiting.has(table)) {
51
- throw new Error(
52
- `Circular dependency detected involving table "${table}"`
53
- );
54
- }
55
-
56
- visiting.add(table);
57
- const handler = this.tables.get(table);
58
- if (handler) {
59
- for (const dep of handler.dependsOn ?? []) {
60
- visit(dep);
61
- }
62
- visited.add(table);
63
- visiting.delete(table);
64
- sorted.push(handler);
65
- }
66
- };
67
-
68
- for (const table of this.tables.keys()) {
69
- visit(table);
70
- }
71
-
72
- return sorted;
73
- }
74
-
75
- /**
76
- * Return bootstrap order for a target table and its dependencies.
77
- * Parents are returned before children.
78
- */
79
- getBootstrapOrderFor(table: string): ServerTableHandler<DB>[] {
80
- const visited = new Set<string>();
81
- const sorted: ServerTableHandler<DB>[] = [];
82
- const visiting = new Set<string>();
83
-
84
- const visit = (name: string) => {
85
- if (visited.has(name)) return;
86
- if (visiting.has(name)) {
87
- throw new Error(
88
- `Circular dependency detected involving table "${name}"`
89
- );
90
- }
91
-
92
- const handler = this.tables.get(name);
93
- if (!handler) {
94
- throw new Error(`Unknown table: ${name}`);
95
- }
96
-
97
- visiting.add(name);
98
- for (const dep of handler.dependsOn ?? []) {
99
- visit(dep);
100
- }
101
- visiting.delete(name);
102
- visited.add(name);
103
- sorted.push(handler);
104
- };
105
-
106
- visit(table);
107
- return sorted;
108
- }
109
- }
@@ -1,56 +0,0 @@
1
- /**
2
- * @syncular/server - Proxy Table Registry
3
- *
4
- * Registry for proxy table handlers.
5
- */
6
-
7
- import type { ProxyTableHandler } from './types';
8
-
9
- /**
10
- * Registry for proxy table handlers.
11
- *
12
- * Maps table names to table handlers for oplog generation.
13
- */
14
- export class ProxyTableRegistry {
15
- private handlers = new Map<string, ProxyTableHandler>();
16
-
17
- /**
18
- * Register a proxy table handler.
19
- */
20
- register(handler: ProxyTableHandler): this {
21
- this.handlers.set(handler.table, handler);
22
- return this;
23
- }
24
-
25
- /**
26
- * Get handler by table name.
27
- */
28
- get(tableName: string): ProxyTableHandler | undefined {
29
- return this.handlers.get(tableName);
30
- }
31
-
32
- /**
33
- * Get handler by table name or throw.
34
- */
35
- getOrThrow(tableName: string): ProxyTableHandler {
36
- const handler = this.handlers.get(tableName);
37
- if (!handler) {
38
- throw new Error(`No proxy table registered for table: ${tableName}`);
39
- }
40
- return handler;
41
- }
42
-
43
- /**
44
- * Check if a table has a registered handler.
45
- */
46
- has(tableName: string): boolean {
47
- return this.handlers.has(tableName);
48
- }
49
-
50
- /**
51
- * Get all registered handlers.
52
- */
53
- getAll(): ProxyTableHandler[] {
54
- return Array.from(this.handlers.values());
55
- }
56
- }