@syncular/server 0.0.1-100
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/blobs/adapters/database.d.ts +83 -0
- package/dist/blobs/adapters/database.d.ts.map +1 -0
- package/dist/blobs/adapters/database.js +202 -0
- package/dist/blobs/adapters/database.js.map +1 -0
- package/dist/blobs/adapters/s3.d.ts +82 -0
- package/dist/blobs/adapters/s3.d.ts.map +1 -0
- package/dist/blobs/adapters/s3.js +170 -0
- package/dist/blobs/adapters/s3.js.map +1 -0
- package/dist/blobs/index.d.ts +9 -0
- package/dist/blobs/index.d.ts.map +1 -0
- package/dist/blobs/index.js +9 -0
- package/dist/blobs/index.js.map +1 -0
- package/dist/blobs/manager.d.ts +195 -0
- package/dist/blobs/manager.d.ts.map +1 -0
- package/dist/blobs/manager.js +440 -0
- package/dist/blobs/manager.js.map +1 -0
- package/dist/blobs/migrate.d.ts +27 -0
- package/dist/blobs/migrate.d.ts.map +1 -0
- package/dist/blobs/migrate.js +119 -0
- package/dist/blobs/migrate.js.map +1 -0
- package/dist/blobs/types.d.ts +54 -0
- package/dist/blobs/types.d.ts.map +1 -0
- package/dist/blobs/types.js +5 -0
- package/dist/blobs/types.js.map +1 -0
- package/dist/clients.d.ts +14 -0
- package/dist/clients.d.ts.map +1 -0
- package/dist/clients.js +7 -0
- package/dist/clients.js.map +1 -0
- package/dist/compaction.d.ts +27 -0
- package/dist/compaction.d.ts.map +1 -0
- package/dist/compaction.js +49 -0
- package/dist/compaction.js.map +1 -0
- package/dist/dialect/base.d.ts +83 -0
- package/dist/dialect/base.d.ts.map +1 -0
- package/dist/dialect/base.js +144 -0
- package/dist/dialect/base.js.map +1 -0
- package/dist/dialect/helpers.d.ts +10 -0
- package/dist/dialect/helpers.d.ts.map +1 -0
- package/dist/dialect/helpers.js +59 -0
- package/dist/dialect/helpers.js.map +1 -0
- package/dist/dialect/index.d.ts +7 -0
- package/dist/dialect/index.d.ts.map +1 -0
- package/dist/dialect/index.js +7 -0
- package/dist/dialect/index.js.map +1 -0
- package/dist/dialect/types.d.ts +149 -0
- package/dist/dialect/types.d.ts.map +1 -0
- package/dist/dialect/types.js +8 -0
- package/dist/dialect/types.js.map +1 -0
- package/dist/helpers/conflict.d.ts +52 -0
- package/dist/helpers/conflict.d.ts.map +1 -0
- package/dist/helpers/conflict.js +49 -0
- package/dist/helpers/conflict.js.map +1 -0
- package/dist/helpers/emitted-change.d.ts +56 -0
- package/dist/helpers/emitted-change.d.ts.map +1 -0
- package/dist/helpers/emitted-change.js +46 -0
- package/dist/helpers/emitted-change.js.map +1 -0
- package/dist/helpers/index.d.ts +10 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +10 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/paginate.d.ts +49 -0
- package/dist/helpers/paginate.d.ts.map +1 -0
- package/dist/helpers/paginate.js +54 -0
- package/dist/helpers/paginate.js.map +1 -0
- package/dist/helpers/scope-strings.d.ts +74 -0
- package/dist/helpers/scope-strings.d.ts.map +1 -0
- package/dist/helpers/scope-strings.js +82 -0
- package/dist/helpers/scope-strings.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/migrate.d.ts +14 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +13 -0
- package/dist/migrate.js.map +1 -0
- package/dist/proxy/handler.d.ts +42 -0
- package/dist/proxy/handler.d.ts.map +1 -0
- package/dist/proxy/handler.js +102 -0
- package/dist/proxy/handler.js.map +1 -0
- package/dist/proxy/index.d.ts +9 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +14 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/proxy/mutation-detector.d.ts +35 -0
- package/dist/proxy/mutation-detector.d.ts.map +1 -0
- package/dist/proxy/mutation-detector.js +246 -0
- package/dist/proxy/mutation-detector.js.map +1 -0
- package/dist/proxy/oplog.d.ts +30 -0
- package/dist/proxy/oplog.d.ts.map +1 -0
- package/dist/proxy/oplog.js +110 -0
- package/dist/proxy/oplog.js.map +1 -0
- package/dist/proxy/registry.d.ts +35 -0
- package/dist/proxy/registry.d.ts.map +1 -0
- package/dist/proxy/registry.js +49 -0
- package/dist/proxy/registry.js.map +1 -0
- package/dist/proxy/types.d.ts +44 -0
- package/dist/proxy/types.d.ts.map +1 -0
- package/dist/proxy/types.js +7 -0
- package/dist/proxy/types.js.map +1 -0
- package/dist/prune.d.ts +37 -0
- package/dist/prune.d.ts.map +1 -0
- package/dist/prune.js +112 -0
- package/dist/prune.js.map +1 -0
- package/dist/pull.d.ts +31 -0
- package/dist/pull.d.ts.map +1 -0
- package/dist/pull.js +608 -0
- package/dist/pull.js.map +1 -0
- package/dist/push.d.ts +33 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/push.js +412 -0
- package/dist/push.js.map +1 -0
- package/dist/realtime/in-memory.d.ts +13 -0
- package/dist/realtime/in-memory.d.ts.map +1 -0
- package/dist/realtime/in-memory.js +28 -0
- package/dist/realtime/in-memory.js.map +1 -0
- package/dist/realtime/index.d.ts +3 -0
- package/dist/realtime/index.d.ts.map +1 -0
- package/dist/realtime/index.js +2 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/realtime/types.d.ts +50 -0
- package/dist/realtime/types.d.ts.map +1 -0
- package/dist/realtime/types.js +7 -0
- package/dist/realtime/types.js.map +1 -0
- package/dist/schema.d.ts +164 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +10 -0
- package/dist/schema.js.map +1 -0
- package/dist/shapes/create-handler.d.ts +119 -0
- package/dist/shapes/create-handler.d.ts.map +1 -0
- package/dist/shapes/create-handler.js +327 -0
- package/dist/shapes/create-handler.js.map +1 -0
- package/dist/shapes/index.d.ts +4 -0
- package/dist/shapes/index.d.ts.map +1 -0
- package/dist/shapes/index.js +4 -0
- package/dist/shapes/index.js.map +1 -0
- package/dist/shapes/registry.d.ts +20 -0
- package/dist/shapes/registry.d.ts.map +1 -0
- package/dist/shapes/registry.js +88 -0
- package/dist/shapes/registry.js.map +1 -0
- package/dist/shapes/types.d.ts +204 -0
- package/dist/shapes/types.d.ts.map +1 -0
- package/dist/shapes/types.js +2 -0
- package/dist/shapes/types.js.map +1 -0
- package/dist/snapshot-chunks/adapters/s3.d.ts +74 -0
- package/dist/snapshot-chunks/adapters/s3.d.ts.map +1 -0
- package/dist/snapshot-chunks/adapters/s3.js +50 -0
- package/dist/snapshot-chunks/adapters/s3.js.map +1 -0
- package/dist/snapshot-chunks/db-metadata.d.ts +38 -0
- package/dist/snapshot-chunks/db-metadata.d.ts.map +1 -0
- package/dist/snapshot-chunks/db-metadata.js +324 -0
- package/dist/snapshot-chunks/db-metadata.js.map +1 -0
- package/dist/snapshot-chunks/index.d.ts +9 -0
- package/dist/snapshot-chunks/index.d.ts.map +1 -0
- package/dist/snapshot-chunks/index.js +9 -0
- package/dist/snapshot-chunks/index.js.map +1 -0
- package/dist/snapshot-chunks/types.d.ts +78 -0
- package/dist/snapshot-chunks/types.d.ts.map +1 -0
- package/dist/snapshot-chunks/types.js +8 -0
- package/dist/snapshot-chunks/types.js.map +1 -0
- package/dist/snapshot-chunks.d.ts +60 -0
- package/dist/snapshot-chunks.d.ts.map +1 -0
- package/dist/snapshot-chunks.js +223 -0
- package/dist/snapshot-chunks.js.map +1 -0
- package/dist/stats.d.ts +19 -0
- package/dist/stats.d.ts.map +1 -0
- package/dist/stats.js +57 -0
- package/dist/stats.js.map +1 -0
- package/dist/subscriptions/index.d.ts +2 -0
- package/dist/subscriptions/index.d.ts.map +1 -0
- package/dist/subscriptions/index.js +2 -0
- package/dist/subscriptions/index.js.map +1 -0
- package/dist/subscriptions/resolve.d.ts +35 -0
- package/dist/subscriptions/resolve.d.ts.map +1 -0
- package/dist/subscriptions/resolve.js +134 -0
- package/dist/subscriptions/resolve.js.map +1 -0
- package/package.json +80 -0
- package/src/blobs/adapters/database.test.ts +67 -0
- package/src/blobs/adapters/database.ts +315 -0
- package/src/blobs/adapters/s3.ts +271 -0
- package/src/blobs/index.ts +9 -0
- package/src/blobs/manager.ts +600 -0
- package/src/blobs/migrate.ts +150 -0
- package/src/blobs/types.ts +70 -0
- package/src/clients.ts +21 -0
- package/src/compaction.ts +77 -0
- package/src/dialect/base.ts +292 -0
- package/src/dialect/helpers.ts +61 -0
- package/src/dialect/index.ts +7 -0
- package/src/dialect/types.ts +197 -0
- package/src/helpers/conflict.ts +64 -0
- package/src/helpers/emitted-change.ts +69 -0
- package/src/helpers/index.ts +10 -0
- package/src/helpers/paginate.ts +82 -0
- package/src/helpers/scope-strings.ts +101 -0
- package/src/index.ts +28 -0
- package/src/migrate.ts +20 -0
- package/src/proxy/handler.test.ts +120 -0
- package/src/proxy/handler.ts +159 -0
- package/src/proxy/index.ts +18 -0
- package/src/proxy/mutation-detector.test.ts +71 -0
- package/src/proxy/mutation-detector.ts +281 -0
- package/src/proxy/oplog.ts +146 -0
- package/src/proxy/registry.ts +56 -0
- package/src/proxy/types.ts +46 -0
- package/src/prune.ts +200 -0
- package/src/pull.ts +858 -0
- package/src/push.ts +583 -0
- package/src/realtime/in-memory.ts +33 -0
- package/src/realtime/index.ts +5 -0
- package/src/realtime/types.ts +55 -0
- package/src/schema.ts +172 -0
- package/src/shapes/create-handler.ts +590 -0
- package/src/shapes/index.ts +3 -0
- package/src/shapes/registry.ts +109 -0
- package/src/shapes/types.ts +267 -0
- package/src/snapshot-chunks/adapters/s3.ts +68 -0
- package/src/snapshot-chunks/db-metadata.test.ts +100 -0
- package/src/snapshot-chunks/db-metadata.ts +466 -0
- package/src/snapshot-chunks/index.ts +9 -0
- package/src/snapshot-chunks/types.ts +103 -0
- package/src/snapshot-chunks.ts +329 -0
- package/src/stats.ts +104 -0
- package/src/subscriptions/index.ts +1 -0
- package/src/subscriptions/resolve.ts +185 -0
|
@@ -0,0 +1,20 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/shapes/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type { ScopePattern, ScopeValues, StoredScopes, SyncOp, SyncOperation, SyncOperationResult } from '@syncular/core';
|
|
2
|
+
import type { ZodSchema, z } from 'zod';
|
|
3
|
+
import type { DbExecutor } from '../dialect/types';
|
|
4
|
+
import type { SyncCoreDb } from '../schema';
|
|
5
|
+
/**
|
|
6
|
+
* Emitted change to be stored in the oplog.
|
|
7
|
+
* Uses JSONB scopes instead of scope_keys array.
|
|
8
|
+
*/
|
|
9
|
+
export interface EmittedChange {
|
|
10
|
+
/** Table name */
|
|
11
|
+
table: string;
|
|
12
|
+
/** Row primary key */
|
|
13
|
+
row_id: string;
|
|
14
|
+
/** Operation type */
|
|
15
|
+
op: SyncOp;
|
|
16
|
+
/** Row data as JSON (null for deletes) */
|
|
17
|
+
row_json: unknown | null;
|
|
18
|
+
/** Row version for optimistic concurrency */
|
|
19
|
+
row_version: number | null;
|
|
20
|
+
/**
|
|
21
|
+
* Scope values for this change (stored as JSONB).
|
|
22
|
+
* Example: { user_id: 'U1', project_id: 'P1' }
|
|
23
|
+
*/
|
|
24
|
+
scopes: StoredScopes;
|
|
25
|
+
}
|
|
26
|
+
export interface ApplyOperationResult {
|
|
27
|
+
result: SyncOperationResult;
|
|
28
|
+
emittedChanges: EmittedChange[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Context for server operations.
|
|
32
|
+
*/
|
|
33
|
+
export interface ServerContext<DB extends SyncCoreDb = SyncCoreDb> {
|
|
34
|
+
/** Database connection (transaction in applyOperation) */
|
|
35
|
+
db: DbExecutor<DB>;
|
|
36
|
+
/** Actor ID (user ID from auth) */
|
|
37
|
+
actorId: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Context passed to snapshot method.
|
|
41
|
+
*/
|
|
42
|
+
export interface ServerSnapshotContext<DB extends SyncCoreDb = SyncCoreDb> extends ServerContext<DB> {
|
|
43
|
+
/** Database executor for the snapshot */
|
|
44
|
+
db: DbExecutor<DB>;
|
|
45
|
+
/** Effective scope values for this subscription */
|
|
46
|
+
scopeValues: ScopeValues;
|
|
47
|
+
/** Pagination cursor (row_id for keyset pagination) */
|
|
48
|
+
cursor: string | null;
|
|
49
|
+
/** Max rows to return */
|
|
50
|
+
limit: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Context passed to applyOperation method.
|
|
54
|
+
*/
|
|
55
|
+
export interface ServerApplyOperationContext<DB extends SyncCoreDb = SyncCoreDb> extends ServerContext<DB> {
|
|
56
|
+
/** Database executor for the operation */
|
|
57
|
+
trx: DbExecutor<DB>;
|
|
58
|
+
/** Client/device identifier */
|
|
59
|
+
clientId: string;
|
|
60
|
+
/** Unique commit identifier */
|
|
61
|
+
commitId: string;
|
|
62
|
+
/**
|
|
63
|
+
* Client's schema version when the commit was created.
|
|
64
|
+
* Use this to transform payloads from older client versions.
|
|
65
|
+
*/
|
|
66
|
+
schemaVersion: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Server-side scope configuration for advanced use cases.
|
|
70
|
+
* Use this when you need custom extraction, access control, or filtering.
|
|
71
|
+
*
|
|
72
|
+
* For simple cases, use the simplified scope array format:
|
|
73
|
+
* `scopes: ['user:{user_id}']`
|
|
74
|
+
*/
|
|
75
|
+
interface ServerScopeConfig {
|
|
76
|
+
/**
|
|
77
|
+
* Column name containing the scope value.
|
|
78
|
+
* For simple patterns like 'user:{user_id}' → column: 'user_id'
|
|
79
|
+
*/
|
|
80
|
+
column?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Custom extractor for complex patterns.
|
|
83
|
+
* Example: extract year/month from a date column
|
|
84
|
+
*/
|
|
85
|
+
extract?: (row: Record<string, unknown>) => Record<string, string>;
|
|
86
|
+
/**
|
|
87
|
+
* Optional access control per scope pattern.
|
|
88
|
+
* Return true if the actor can access this scope value.
|
|
89
|
+
*/
|
|
90
|
+
access?: (ctx: ServerContext, vars: Record<string, string>) => Promise<boolean>;
|
|
91
|
+
/**
|
|
92
|
+
* Optional filter builder for wildcard subscriptions.
|
|
93
|
+
* Called when the subscription uses wildcards for this pattern.
|
|
94
|
+
*/
|
|
95
|
+
toFilter?: (vars: Record<string, string | undefined>, query: unknown) => unknown;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Server shape options - configuration for a table's sync behavior.
|
|
99
|
+
*/
|
|
100
|
+
export interface ServerShapeOptions<DB extends SyncCoreDb = SyncCoreDb, Scopes extends Record<ScopePattern, Record<string, string>> = Record<ScopePattern, Record<string, string>>, TableName extends string = string, Params extends ZodSchema = ZodSchema> {
|
|
101
|
+
/**
|
|
102
|
+
* Scope patterns this shape uses.
|
|
103
|
+
* Array of pattern keys from SharedScopes.
|
|
104
|
+
*/
|
|
105
|
+
scopes: (keyof Scopes)[];
|
|
106
|
+
/**
|
|
107
|
+
* Scope definitions - how each pattern maps to row data.
|
|
108
|
+
* Defaults to using column name = variable name.
|
|
109
|
+
*/
|
|
110
|
+
scopeDefinitions?: Partial<Record<keyof Scopes, ServerScopeConfig>>;
|
|
111
|
+
/**
|
|
112
|
+
* Resolve allowed scope values for the current actor.
|
|
113
|
+
* Called once per request to determine what the actor can access.
|
|
114
|
+
*
|
|
115
|
+
* Returns scope values the actor is allowed to access.
|
|
116
|
+
* The server will intersect requested scopes with these.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* resolveScopes: async (ctx) => ({
|
|
120
|
+
* user_id: [ctx.user.id],
|
|
121
|
+
* project_id: ctx.user.projectIds,
|
|
122
|
+
* })
|
|
123
|
+
*/
|
|
124
|
+
resolveScopes: (ctx: ServerContext<DB>) => Promise<ScopeValues>;
|
|
125
|
+
/**
|
|
126
|
+
* Optional Zod schema for subscription parameters.
|
|
127
|
+
*/
|
|
128
|
+
params?: Params;
|
|
129
|
+
/**
|
|
130
|
+
* Primary key column (default: 'id')
|
|
131
|
+
*/
|
|
132
|
+
primaryKey?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Version column for optimistic concurrency (default: 'server_version')
|
|
135
|
+
*/
|
|
136
|
+
versionColumn?: string;
|
|
137
|
+
/**
|
|
138
|
+
* Tables that must be bootstrapped before this one.
|
|
139
|
+
*/
|
|
140
|
+
dependsOn?: string[];
|
|
141
|
+
/**
|
|
142
|
+
* TTL for cached snapshot chunks (ms). Default: 24 hours.
|
|
143
|
+
*/
|
|
144
|
+
snapshotChunkTtlMs?: number;
|
|
145
|
+
/**
|
|
146
|
+
* Transform client payload → server row on writes.
|
|
147
|
+
*/
|
|
148
|
+
transformInbound?: (payload: Record<string, unknown>, ctx: ServerApplyOperationContext<DB>) => Partial<DB[TableName & keyof DB]>;
|
|
149
|
+
/**
|
|
150
|
+
* Transform server row → client payload on reads.
|
|
151
|
+
*/
|
|
152
|
+
transformOutbound?: (row: DB[TableName & keyof DB]) => Record<string, unknown>;
|
|
153
|
+
/**
|
|
154
|
+
* Custom snapshot implementation.
|
|
155
|
+
* Default uses keyset pagination ordered by primary key.
|
|
156
|
+
*/
|
|
157
|
+
snapshot?: (ctx: ServerSnapshotContext<DB>, params: Params extends ZodSchema ? z.infer<Params> : undefined) => Promise<{
|
|
158
|
+
rows: unknown[];
|
|
159
|
+
nextCursor: string | null;
|
|
160
|
+
}>;
|
|
161
|
+
/**
|
|
162
|
+
* Custom apply operation implementation.
|
|
163
|
+
*/
|
|
164
|
+
applyOperation?: (ctx: ServerApplyOperationContext<DB>, op: SyncOperation, opIndex: number) => Promise<ApplyOperationResult>;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Server-side table handler for snapshots and mutations.
|
|
168
|
+
* This is the internal handler interface used by the sync engine.
|
|
169
|
+
*/
|
|
170
|
+
export interface ServerTableHandler<DB extends SyncCoreDb = SyncCoreDb> {
|
|
171
|
+
/** Table name */
|
|
172
|
+
table: string;
|
|
173
|
+
/** Scope patterns used by this shape */
|
|
174
|
+
scopePatterns: ScopePattern[];
|
|
175
|
+
/**
|
|
176
|
+
* Tables that must be bootstrapped before this one.
|
|
177
|
+
*/
|
|
178
|
+
dependsOn?: string[];
|
|
179
|
+
/**
|
|
180
|
+
* TTL for cached snapshot chunks (ms).
|
|
181
|
+
*/
|
|
182
|
+
snapshotChunkTtlMs?: number;
|
|
183
|
+
/**
|
|
184
|
+
* Resolve allowed scope values for the current actor.
|
|
185
|
+
*/
|
|
186
|
+
resolveScopes: (ctx: ServerContext<DB>) => Promise<ScopeValues>;
|
|
187
|
+
/**
|
|
188
|
+
* Extract stored scopes from a row.
|
|
189
|
+
*/
|
|
190
|
+
extractScopes: (row: Record<string, unknown>) => StoredScopes;
|
|
191
|
+
/**
|
|
192
|
+
* Build a bootstrap snapshot page.
|
|
193
|
+
*/
|
|
194
|
+
snapshot(ctx: ServerSnapshotContext<DB>, params: Record<string, unknown> | undefined): Promise<{
|
|
195
|
+
rows: unknown[];
|
|
196
|
+
nextCursor: string | null;
|
|
197
|
+
}>;
|
|
198
|
+
/**
|
|
199
|
+
* Apply a single operation.
|
|
200
|
+
*/
|
|
201
|
+
applyOperation(ctx: ServerApplyOperationContext<DB>, op: SyncOperation, opIndex: number): Promise<ApplyOperationResult>;
|
|
202
|
+
}
|
|
203
|
+
export {};
|
|
204
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shapes/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shapes/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - S3-compatible snapshot chunk storage adapter
|
|
3
|
+
*
|
|
4
|
+
* Stores snapshot chunk bodies in S3/R2/MinIO with metadata in database.
|
|
5
|
+
*/
|
|
6
|
+
import type { BlobStorageAdapter } from '@syncular/core';
|
|
7
|
+
import type { Kysely } from 'kysely';
|
|
8
|
+
import type { SyncCoreDb } from '../../schema';
|
|
9
|
+
export interface S3SnapshotChunkStorageOptions {
|
|
10
|
+
/** Database instance for metadata */
|
|
11
|
+
db: Kysely<SyncCoreDb>;
|
|
12
|
+
/** S3 blob storage adapter */
|
|
13
|
+
s3Adapter: BlobStorageAdapter;
|
|
14
|
+
/** Optional key prefix for all chunks */
|
|
15
|
+
keyPrefix?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create S3-compatible snapshot chunk storage.
|
|
19
|
+
*
|
|
20
|
+
* Stores chunk bodies in S3/R2/MinIO and metadata in the database.
|
|
21
|
+
* Supports presigned URLs for direct client downloads.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { createS3BlobStorageAdapter } from '@syncular/server/blobs/adapters/s3';
|
|
26
|
+
* import { createS3SnapshotChunkStorage } from '@syncular/server/snapshot-chunks/adapters/s3';
|
|
27
|
+
*
|
|
28
|
+
* const s3Adapter = createS3BlobStorageAdapter({
|
|
29
|
+
* client: new S3Client({ region: 'us-east-1' }),
|
|
30
|
+
* bucket: 'my-snapshot-chunks',
|
|
31
|
+
* commands: { PutObjectCommand, GetObjectCommand, HeadObjectCommand, DeleteObjectCommand },
|
|
32
|
+
* getSignedUrl,
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* const chunkStorage = createS3SnapshotChunkStorage({
|
|
36
|
+
* db: kysely,
|
|
37
|
+
* s3Adapter,
|
|
38
|
+
* keyPrefix: 'snapshots/',
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function createS3SnapshotChunkStorage(options: S3SnapshotChunkStorageOptions): {
|
|
43
|
+
name: string;
|
|
44
|
+
storeChunk: (metadata: Omit<import("..").SnapshotChunkMetadata, "blobHash" | "byteLength" | "chunkId"> & {
|
|
45
|
+
body: Uint8Array<ArrayBufferLike>;
|
|
46
|
+
}) => Promise<{
|
|
47
|
+
id: string;
|
|
48
|
+
byteLength: number;
|
|
49
|
+
sha256: string;
|
|
50
|
+
encoding: "json-row-frame-v1";
|
|
51
|
+
compression: "gzip";
|
|
52
|
+
}>;
|
|
53
|
+
storeChunkStream: (metadata: Omit<import("..").SnapshotChunkMetadata, "blobHash" | "byteLength" | "chunkId"> & {
|
|
54
|
+
bodyStream: ReadableStream<Uint8Array<ArrayBufferLike>>;
|
|
55
|
+
byteLength?: number | undefined;
|
|
56
|
+
}) => Promise<{
|
|
57
|
+
id: string;
|
|
58
|
+
byteLength: number;
|
|
59
|
+
sha256: string;
|
|
60
|
+
encoding: "json-row-frame-v1";
|
|
61
|
+
compression: "gzip";
|
|
62
|
+
}>;
|
|
63
|
+
readChunk: (chunkId: string) => Promise<Uint8Array<ArrayBufferLike> | null>;
|
|
64
|
+
readChunkStream: (chunkId: string) => Promise<ReadableStream<Uint8Array<ArrayBufferLike>> | null>;
|
|
65
|
+
findChunk: (pageKey: import("..").SnapshotChunkPageKey) => Promise<{
|
|
66
|
+
id: string;
|
|
67
|
+
byteLength: number;
|
|
68
|
+
sha256: string;
|
|
69
|
+
encoding: "json-row-frame-v1";
|
|
70
|
+
compression: "gzip";
|
|
71
|
+
} | null>;
|
|
72
|
+
cleanupExpired: (beforeIso: string) => Promise<number>;
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=s3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../../src/snapshot-chunks/adapters/s3.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,WAAW,6BAA6B;IAC5C,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACvB,8BAA8B;IAC9B,SAAS,EAAE,kBAAkB,CAAC;IAC9B,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqBvC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - S3-compatible snapshot chunk storage adapter
|
|
3
|
+
*
|
|
4
|
+
* Stores snapshot chunk bodies in S3/R2/MinIO with metadata in database.
|
|
5
|
+
*/
|
|
6
|
+
import { createDbMetadataChunkStorage } from '../db-metadata.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create S3-compatible snapshot chunk storage.
|
|
9
|
+
*
|
|
10
|
+
* Stores chunk bodies in S3/R2/MinIO and metadata in the database.
|
|
11
|
+
* Supports presigned URLs for direct client downloads.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { createS3BlobStorageAdapter } from '@syncular/server/blobs/adapters/s3';
|
|
16
|
+
* import { createS3SnapshotChunkStorage } from '@syncular/server/snapshot-chunks/adapters/s3';
|
|
17
|
+
*
|
|
18
|
+
* const s3Adapter = createS3BlobStorageAdapter({
|
|
19
|
+
* client: new S3Client({ region: 'us-east-1' }),
|
|
20
|
+
* bucket: 'my-snapshot-chunks',
|
|
21
|
+
* commands: { PutObjectCommand, GetObjectCommand, HeadObjectCommand, DeleteObjectCommand },
|
|
22
|
+
* getSignedUrl,
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const chunkStorage = createS3SnapshotChunkStorage({
|
|
26
|
+
* db: kysely,
|
|
27
|
+
* s3Adapter,
|
|
28
|
+
* keyPrefix: 'snapshots/',
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function createS3SnapshotChunkStorage(options) {
|
|
33
|
+
const { db, s3Adapter, keyPrefix } = options;
|
|
34
|
+
// Wrap the S3 adapter to use prefixed keys
|
|
35
|
+
const prefixedAdapter = keyPrefix
|
|
36
|
+
? {
|
|
37
|
+
...s3Adapter,
|
|
38
|
+
name: `${s3Adapter.name}+prefixed`,
|
|
39
|
+
// Keys are already handled by the S3 adapter, prefix is applied there
|
|
40
|
+
}
|
|
41
|
+
: s3Adapter;
|
|
42
|
+
// Use the database metadata storage with S3 for bodies
|
|
43
|
+
const storage = createDbMetadataChunkStorage({
|
|
44
|
+
db,
|
|
45
|
+
blobAdapter: prefixedAdapter,
|
|
46
|
+
chunkIdPrefix: keyPrefix ? `${keyPrefix.replace(/\/$/, '')}_` : 'chunk_',
|
|
47
|
+
});
|
|
48
|
+
return storage;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=s3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.js","sourceRoot":"","sources":["../../../src/snapshot-chunks/adapters/s3.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAW9D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,4BAA4B,CAC1C,OAAsC,EACtC;IACA,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAE7C,2CAA2C;IAC3C,MAAM,eAAe,GAAuB,SAAS;QACnD,CAAC,CAAC;YACE,GAAG,SAAS;YACZ,IAAI,EAAE,GAAG,SAAS,CAAC,IAAI,WAAW;YAClC,sEAAsE;SACvE;QACH,CAAC,CAAC,SAAS,CAAC;IAEd,uDAAuD;IACvD,MAAM,OAAO,GAAG,4BAA4B,CAAC;QAC3C,EAAE;QACF,WAAW,EAAE,eAAe;QAC5B,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ;KACzE,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AAAA,CAChB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Database-backed metadata store for snapshot chunks
|
|
3
|
+
*
|
|
4
|
+
* Stores chunk metadata in sync_snapshot_chunks_metadata table,
|
|
5
|
+
* body content in blob storage adapter.
|
|
6
|
+
*/
|
|
7
|
+
import { type BlobStorageAdapter, type SyncSnapshotChunkRef } from '@syncular/core';
|
|
8
|
+
import type { Kysely } from 'kysely';
|
|
9
|
+
import type { SyncCoreDb } from '../schema';
|
|
10
|
+
import type { SnapshotChunkMetadata, SnapshotChunkPageKey } from './types';
|
|
11
|
+
export interface DbMetadataSnapshotChunkStorageOptions {
|
|
12
|
+
/** Database instance */
|
|
13
|
+
db: Kysely<SyncCoreDb>;
|
|
14
|
+
/** Blob storage adapter for body content */
|
|
15
|
+
blobAdapter: BlobStorageAdapter;
|
|
16
|
+
/** Optional prefix for chunk IDs */
|
|
17
|
+
chunkIdPrefix?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create a snapshot chunk storage that uses:
|
|
21
|
+
* - Database for metadata (scope, commit seq, etc.)
|
|
22
|
+
* - Blob adapter for body content
|
|
23
|
+
*/
|
|
24
|
+
export declare function createDbMetadataChunkStorage(options: DbMetadataSnapshotChunkStorageOptions): {
|
|
25
|
+
name: string;
|
|
26
|
+
storeChunk: (metadata: Omit<SnapshotChunkMetadata, 'chunkId' | 'byteLength' | 'blobHash'> & {
|
|
27
|
+
body: Uint8Array;
|
|
28
|
+
}) => Promise<SyncSnapshotChunkRef>;
|
|
29
|
+
storeChunkStream: (metadata: Omit<SnapshotChunkMetadata, 'chunkId' | 'byteLength' | 'blobHash'> & {
|
|
30
|
+
bodyStream: ReadableStream<Uint8Array>;
|
|
31
|
+
byteLength?: number;
|
|
32
|
+
}) => Promise<SyncSnapshotChunkRef>;
|
|
33
|
+
readChunk: (chunkId: string) => Promise<Uint8Array | null>;
|
|
34
|
+
readChunkStream: (chunkId: string) => Promise<ReadableStream<Uint8Array> | null>;
|
|
35
|
+
findChunk: (pageKey: SnapshotChunkPageKey) => Promise<SyncSnapshotChunkRef | null>;
|
|
36
|
+
cleanupExpired: (beforeIso: string) => Promise<number>;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=db-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-metadata.d.ts","sourceRoot":"","sources":["../../src/snapshot-chunks/db-metadata.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,KAAK,kBAAkB,EAKvB,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE3E,MAAM,WAAW,qCAAqC;IACpD,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACvB,4CAA4C;IAC5C,WAAW,EAAE,kBAAkB,CAAC;IAChC,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,qCAAqC,GAC7C;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,CACV,QAAQ,EAAE,IAAI,CACZ,qBAAqB,EACrB,SAAS,GAAG,YAAY,GAAG,UAAU,CACtC,GAAG;QACF,IAAI,EAAE,UAAU,CAAC;KAClB,KACE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,gBAAgB,EAAE,CAChB,QAAQ,EAAE,IAAI,CACZ,qBAAqB,EACrB,SAAS,GAAG,YAAY,GAAG,UAAU,CACtC,GAAG;QACF,UAAU,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;QACvC,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,KACE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC3D,eAAe,EAAE,CACf,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;IAChD,SAAS,EAAE,CACT,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC1C,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACxD,CAkZA"}
|