@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.
- package/dist/handlers/collection.d.ts +12 -0
- package/dist/handlers/collection.d.ts.map +1 -0
- package/dist/handlers/collection.js +64 -0
- package/dist/handlers/collection.js.map +1 -0
- package/dist/handlers/create-handler.d.ts +9 -9
- package/dist/handlers/create-handler.d.ts.map +1 -1
- package/dist/handlers/create-handler.js.map +1 -1
- package/dist/handlers/index.d.ts +1 -1
- package/dist/handlers/index.d.ts.map +1 -1
- package/dist/handlers/index.js +1 -1
- package/dist/handlers/index.js.map +1 -1
- package/dist/handlers/types.d.ts +18 -12
- package/dist/handlers/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/proxy/collection.d.ts +9 -0
- package/dist/proxy/collection.d.ts.map +1 -0
- package/dist/proxy/collection.js +21 -0
- package/dist/proxy/collection.js.map +1 -0
- package/dist/proxy/handler.d.ts +3 -3
- package/dist/proxy/handler.d.ts.map +1 -1
- package/dist/proxy/handler.js +2 -1
- package/dist/proxy/handler.js.map +1 -1
- package/dist/proxy/index.d.ts +1 -1
- package/dist/proxy/index.d.ts.map +1 -1
- package/dist/proxy/index.js +3 -3
- package/dist/proxy/index.js.map +1 -1
- package/dist/pull.d.ts +5 -5
- package/dist/pull.d.ts.map +1 -1
- package/dist/pull.js +8 -8
- package/dist/pull.js.map +1 -1
- package/dist/push.d.ts +5 -5
- package/dist/push.d.ts.map +1 -1
- package/dist/push.js +5 -3
- package/dist/push.js.map +1 -1
- package/dist/subscriptions/resolve.d.ts +5 -4
- package/dist/subscriptions/resolve.d.ts.map +1 -1
- package/dist/subscriptions/resolve.js +4 -2
- package/dist/subscriptions/resolve.js.map +1 -1
- package/dist/sync.d.ts +21 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +23 -0
- package/dist/sync.js.map +1 -0
- package/package.json +2 -2
- package/src/handlers/collection.ts +121 -0
- package/src/handlers/create-handler.ts +23 -14
- package/src/handlers/index.ts +1 -1
- package/src/handlers/types.ts +29 -12
- package/src/index.ts +1 -0
- package/src/notify.test.ts +17 -17
- package/src/proxy/collection.ts +39 -0
- package/src/proxy/handler.test.ts +9 -7
- package/src/proxy/handler.ts +4 -4
- package/src/proxy/index.ts +8 -3
- package/src/pull.ts +35 -23
- package/src/push.ts +15 -8
- package/src/subscriptions/resolve.ts +11 -5
- package/src/sync.ts +101 -0
- package/dist/handlers/registry.d.ts +0 -20
- package/dist/handlers/registry.d.ts.map +0 -1
- package/dist/handlers/registry.js +0 -88
- package/dist/handlers/registry.js.map +0 -1
- package/dist/proxy/registry.d.ts +0 -35
- package/dist/proxy/registry.d.ts.map +0 -1
- package/dist/proxy/registry.js +0 -49
- package/dist/proxy/registry.js.map +0 -1
- package/src/handlers/registry.ts +0 -109
- 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
|
|
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<
|
|
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:
|
|
184
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
142
|
+
auth: Auth;
|
|
138
143
|
subscriptions: SyncSubscriptionRequest[];
|
|
139
|
-
handlers:
|
|
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
|
|
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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"}
|
package/dist/proxy/registry.d.ts
DELETED
|
@@ -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"}
|
package/dist/proxy/registry.js
DELETED
|
@@ -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"}
|
package/src/handlers/registry.ts
DELETED
|
@@ -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
|
-
}
|
package/src/proxy/registry.ts
DELETED
|
@@ -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
|
-
}
|