@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,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Blob storage migrations
|
|
3
|
+
*
|
|
4
|
+
* These migrations are separate from core sync migrations because
|
|
5
|
+
* blob storage is optional and may use external storage (S3/R2).
|
|
6
|
+
*/
|
|
7
|
+
import { sql } from 'kysely';
|
|
8
|
+
/**
|
|
9
|
+
* Ensures the blob uploads tracking schema exists.
|
|
10
|
+
* This table is required for the blob manager regardless of storage backend.
|
|
11
|
+
*
|
|
12
|
+
* For PostgreSQL.
|
|
13
|
+
*/
|
|
14
|
+
async function ensureBlobUploadsSchemaPostgres(db) {
|
|
15
|
+
await db.schema
|
|
16
|
+
.createTable('sync_blob_uploads')
|
|
17
|
+
.ifNotExists()
|
|
18
|
+
.addColumn('hash', 'text', (col) => col.primaryKey())
|
|
19
|
+
.addColumn('size', 'bigint', (col) => col.notNull())
|
|
20
|
+
.addColumn('mime_type', 'text', (col) => col.notNull())
|
|
21
|
+
.addColumn('status', 'text', (col) => col.notNull())
|
|
22
|
+
.addColumn('actor_id', 'text', (col) => col.notNull())
|
|
23
|
+
.addColumn('created_at', 'timestamptz', (col) => col.notNull().defaultTo(sql `now()`))
|
|
24
|
+
.addColumn('expires_at', 'timestamptz', (col) => col.notNull())
|
|
25
|
+
.addColumn('completed_at', 'timestamptz')
|
|
26
|
+
.execute();
|
|
27
|
+
await db.schema
|
|
28
|
+
.createIndex('idx_sync_blob_uploads_status')
|
|
29
|
+
.ifNotExists()
|
|
30
|
+
.on('sync_blob_uploads')
|
|
31
|
+
.columns(['status'])
|
|
32
|
+
.execute();
|
|
33
|
+
await db.schema
|
|
34
|
+
.createIndex('idx_sync_blob_uploads_expires_at')
|
|
35
|
+
.ifNotExists()
|
|
36
|
+
.on('sync_blob_uploads')
|
|
37
|
+
.columns(['expires_at'])
|
|
38
|
+
.execute();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Ensures the blob uploads tracking schema exists.
|
|
42
|
+
* This table is required for the blob manager regardless of storage backend.
|
|
43
|
+
*
|
|
44
|
+
* For SQLite.
|
|
45
|
+
*/
|
|
46
|
+
async function ensureBlobUploadsSchemasSqlite(db) {
|
|
47
|
+
await db.schema
|
|
48
|
+
.createTable('sync_blob_uploads')
|
|
49
|
+
.ifNotExists()
|
|
50
|
+
.addColumn('hash', 'text', (col) => col.primaryKey())
|
|
51
|
+
.addColumn('size', 'integer', (col) => col.notNull())
|
|
52
|
+
.addColumn('mime_type', 'text', (col) => col.notNull())
|
|
53
|
+
.addColumn('status', 'text', (col) => col.notNull())
|
|
54
|
+
.addColumn('actor_id', 'text', (col) => col.notNull())
|
|
55
|
+
.addColumn('created_at', 'text', (col) => col.notNull().defaultTo(sql `(datetime('now'))`))
|
|
56
|
+
.addColumn('expires_at', 'text', (col) => col.notNull())
|
|
57
|
+
.addColumn('completed_at', 'text')
|
|
58
|
+
.execute();
|
|
59
|
+
await db.schema
|
|
60
|
+
.createIndex('idx_sync_blob_uploads_status')
|
|
61
|
+
.ifNotExists()
|
|
62
|
+
.on('sync_blob_uploads')
|
|
63
|
+
.columns(['status'])
|
|
64
|
+
.execute();
|
|
65
|
+
await db.schema
|
|
66
|
+
.createIndex('idx_sync_blob_uploads_expires_at')
|
|
67
|
+
.ifNotExists()
|
|
68
|
+
.on('sync_blob_uploads')
|
|
69
|
+
.columns(['expires_at'])
|
|
70
|
+
.execute();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Ensures the blob storage schema exists (for database adapter).
|
|
74
|
+
* Only needed if using the database blob storage adapter.
|
|
75
|
+
*
|
|
76
|
+
* For PostgreSQL.
|
|
77
|
+
*/
|
|
78
|
+
export async function ensureBlobStorageSchemaPostgres(db) {
|
|
79
|
+
// First ensure uploads table
|
|
80
|
+
await ensureBlobUploadsSchemaPostgres(db);
|
|
81
|
+
// Then create blobs table
|
|
82
|
+
await db.schema
|
|
83
|
+
.createTable('sync_blobs')
|
|
84
|
+
.ifNotExists()
|
|
85
|
+
.addColumn('hash', 'text', (col) => col.primaryKey())
|
|
86
|
+
.addColumn('size', 'bigint', (col) => col.notNull())
|
|
87
|
+
.addColumn('mime_type', 'text', (col) => col.notNull())
|
|
88
|
+
.addColumn('body', 'bytea', (col) => col.notNull())
|
|
89
|
+
.addColumn('created_at', 'timestamptz', (col) => col.notNull().defaultTo(sql `now()`))
|
|
90
|
+
.execute();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Ensures the blob storage schema exists (for database adapter).
|
|
94
|
+
* Only needed if using the database blob storage adapter.
|
|
95
|
+
*
|
|
96
|
+
* For SQLite.
|
|
97
|
+
*/
|
|
98
|
+
export async function ensureBlobStorageSchemaSqlite(db) {
|
|
99
|
+
// First ensure uploads table
|
|
100
|
+
await ensureBlobUploadsSchemasSqlite(db);
|
|
101
|
+
// Then create blobs table
|
|
102
|
+
await db.schema
|
|
103
|
+
.createTable('sync_blobs')
|
|
104
|
+
.ifNotExists()
|
|
105
|
+
.addColumn('hash', 'text', (col) => col.primaryKey())
|
|
106
|
+
.addColumn('size', 'integer', (col) => col.notNull())
|
|
107
|
+
.addColumn('mime_type', 'text', (col) => col.notNull())
|
|
108
|
+
.addColumn('body', 'blob', (col) => col.notNull())
|
|
109
|
+
.addColumn('created_at', 'text', (col) => col.notNull().defaultTo(sql `(datetime('now'))`))
|
|
110
|
+
.execute();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Drops the blob schema from the database.
|
|
114
|
+
*/
|
|
115
|
+
export async function dropBlobSchema(db) {
|
|
116
|
+
await db.schema.dropTable('sync_blobs').ifExists().execute();
|
|
117
|
+
await db.schema.dropTable('sync_blob_uploads').ifExists().execute();
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/blobs/migrate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Blob storage types
|
|
3
|
+
*/
|
|
4
|
+
import type { Generated } from 'kysely';
|
|
5
|
+
/**
|
|
6
|
+
* Blob uploads tracking table.
|
|
7
|
+
* Tracks initiated uploads and their completion status.
|
|
8
|
+
*/
|
|
9
|
+
export interface SyncBlobUploadsTable {
|
|
10
|
+
/** SHA-256 hash with prefix: "sha256:<hex>" */
|
|
11
|
+
hash: string;
|
|
12
|
+
/** Expected size in bytes */
|
|
13
|
+
size: number;
|
|
14
|
+
/** MIME type */
|
|
15
|
+
mime_type: string;
|
|
16
|
+
/** Upload status */
|
|
17
|
+
status: 'pending' | 'complete';
|
|
18
|
+
/** Actor who initiated the upload */
|
|
19
|
+
actor_id: string;
|
|
20
|
+
/** When the upload was initiated */
|
|
21
|
+
created_at: Generated<string>;
|
|
22
|
+
/** When the upload expires (for cleanup of incomplete uploads) */
|
|
23
|
+
expires_at: string;
|
|
24
|
+
/** When the upload was completed */
|
|
25
|
+
completed_at: string | null;
|
|
26
|
+
}
|
|
27
|
+
export interface SyncBlobUploadsDb {
|
|
28
|
+
sync_blob_uploads: SyncBlobUploadsTable;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Blob storage table (for database adapter).
|
|
32
|
+
* Stores blob content directly in the database.
|
|
33
|
+
*/
|
|
34
|
+
export interface SyncBlobsTable {
|
|
35
|
+
/** SHA-256 hash with prefix: "sha256:<hex>" */
|
|
36
|
+
hash: string;
|
|
37
|
+
/** Size in bytes */
|
|
38
|
+
size: number;
|
|
39
|
+
/** MIME type */
|
|
40
|
+
mime_type: string;
|
|
41
|
+
/** Blob content */
|
|
42
|
+
body: Uint8Array;
|
|
43
|
+
/** When the blob was created */
|
|
44
|
+
created_at: Generated<string>;
|
|
45
|
+
}
|
|
46
|
+
export interface SyncBlobsDb {
|
|
47
|
+
sync_blobs: SyncBlobsTable;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Full database interface for blob storage.
|
|
51
|
+
*/
|
|
52
|
+
export interface SyncBlobDb extends SyncBlobUploadsDb, SyncBlobsDb {
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/blobs/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAMxC;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB;IACpB,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC;IAC/B,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9B,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,oBAAoB,CAAC;CACzC;AAMD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,gCAAgC;IAChC,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,cAAc,CAAC;CAC5B;AAMD;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,iBAAiB,EAAE,WAAW;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/blobs/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Client cursor tracking
|
|
3
|
+
*/
|
|
4
|
+
import type { ScopeValues } from '@syncular/core';
|
|
5
|
+
import type { DbExecutor, ServerSyncDialect } from './dialect/types';
|
|
6
|
+
import type { SyncCoreDb } from './schema';
|
|
7
|
+
export declare function recordClientCursor<DB extends SyncCoreDb>(db: DbExecutor<DB>, dialect: ServerSyncDialect, args: {
|
|
8
|
+
partitionId?: string;
|
|
9
|
+
clientId: string;
|
|
10
|
+
actorId: string;
|
|
11
|
+
cursor: number;
|
|
12
|
+
effectiveScopes: ScopeValues;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../src/clients.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,wBAAsB,kBAAkB,CAAC,EAAE,SAAS,UAAU,EAC5D,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,EAClB,OAAO,EAAE,iBAAiB,EAC1B,IAAI,EAAE;IACJ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,WAAW,CAAC;CAC9B,GACA,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
package/dist/clients.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../src/clients.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,EAAkB,EAClB,OAA0B,EAC1B,IAMC,EACc;IACf,MAAM,OAAO,CAAC,kBAAkB,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;AAAA,CAC5C"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Change-log compaction utilities
|
|
3
|
+
*
|
|
4
|
+
* Compaction reduces storage by deleting intermediate history while preserving
|
|
5
|
+
* the newest change per (shape, table_name, row_id, scope_key) for older data.
|
|
6
|
+
*
|
|
7
|
+
* Dialect-specific implementation lives in `ServerSyncDialect.compactChanges`.
|
|
8
|
+
*/
|
|
9
|
+
import type { DbExecutor, ServerSyncDialect } from './dialect/types';
|
|
10
|
+
import type { SyncCoreDb } from './schema';
|
|
11
|
+
export interface CompactOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Keep full (non-compacted) history for the most recent N hours.
|
|
14
|
+
* Older history may be compacted depending on dialect strategy.
|
|
15
|
+
*/
|
|
16
|
+
fullHistoryHours: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function compactChanges<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
19
|
+
dialect: ServerSyncDialect;
|
|
20
|
+
options: CompactOptions;
|
|
21
|
+
}): Promise<number>;
|
|
22
|
+
export declare function maybeCompactChanges<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
23
|
+
dialect: ServerSyncDialect;
|
|
24
|
+
minIntervalMs: number;
|
|
25
|
+
options: CompactOptions;
|
|
26
|
+
}): Promise<number>;
|
|
27
|
+
//# sourceMappingURL=compaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../src/compaction.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,cAAc,CAAC,EAAE,SAAS,UAAU,EACxD,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,EAClB,IAAI,EAAE;IAAE,OAAO,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAC5D,OAAO,CAAC,MAAM,CAAC,CAIjB;AAqBD,wBAAsB,mBAAmB,CAAC,EAAE,SAAS,UAAU,EAC7D,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,EAClB,IAAI,EAAE;IACJ,OAAO,EAAE,iBAAiB,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,cAAc,CAAC;CACzB,GACA,OAAO,CAAC,MAAM,CAAC,CAqBjB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Change-log compaction utilities
|
|
3
|
+
*
|
|
4
|
+
* Compaction reduces storage by deleting intermediate history while preserving
|
|
5
|
+
* the newest change per (shape, table_name, row_id, scope_key) for older data.
|
|
6
|
+
*
|
|
7
|
+
* Dialect-specific implementation lives in `ServerSyncDialect.compactChanges`.
|
|
8
|
+
*/
|
|
9
|
+
export async function compactChanges(db, args) {
|
|
10
|
+
const fullHistoryHours = Math.max(0, args.options.fullHistoryHours);
|
|
11
|
+
if (fullHistoryHours <= 0)
|
|
12
|
+
return 0;
|
|
13
|
+
return args.dialect.compactChanges(db, { fullHistoryHours });
|
|
14
|
+
}
|
|
15
|
+
const compactStateByDb = new WeakMap();
|
|
16
|
+
function getCompactState(db) {
|
|
17
|
+
const existing = compactStateByDb.get(db);
|
|
18
|
+
if (existing)
|
|
19
|
+
return existing;
|
|
20
|
+
const created = {
|
|
21
|
+
lastCompactAtMs: 0,
|
|
22
|
+
compactInFlight: null,
|
|
23
|
+
};
|
|
24
|
+
compactStateByDb.set(db, created);
|
|
25
|
+
return created;
|
|
26
|
+
}
|
|
27
|
+
export async function maybeCompactChanges(db, args) {
|
|
28
|
+
const state = getCompactState(db);
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
if (now - state.lastCompactAtMs < args.minIntervalMs)
|
|
31
|
+
return 0;
|
|
32
|
+
if (state.compactInFlight)
|
|
33
|
+
return state.compactInFlight;
|
|
34
|
+
state.compactInFlight = (async () => {
|
|
35
|
+
try {
|
|
36
|
+
const deleted = await compactChanges(db, {
|
|
37
|
+
dialect: args.dialect,
|
|
38
|
+
options: args.options,
|
|
39
|
+
});
|
|
40
|
+
state.lastCompactAtMs = Date.now();
|
|
41
|
+
return deleted;
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
state.compactInFlight = null;
|
|
45
|
+
}
|
|
46
|
+
})();
|
|
47
|
+
return state.compactInFlight;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=compaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../src/compaction.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,EAAkB,EAClB,IAA6D,EAC5C;IACjB,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACpE,IAAI,gBAAgB,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC;AAAA,CAC9D;AAOD,MAAM,gBAAgB,GAAG,IAAI,OAAO,EAAwB,CAAC;AAE7D,SAAS,eAAe,CAAC,EAAU,EAAgB;IACjD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,OAAO,GAAiB;QAC5B,eAAe,EAAE,CAAC;QAClB,eAAe,EAAE,IAAI;KACtB,CAAC;IACF,gBAAgB,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAClC,OAAO,OAAO,CAAC;AAAA,CAChB;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,EAAkB,EAClB,IAIC,EACgB;IACjB,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,GAAG,GAAG,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,aAAa;QAAE,OAAO,CAAC,CAAC;IAE/D,IAAI,KAAK,CAAC,eAAe;QAAE,OAAO,KAAK,CAAC,eAAe,CAAC;IAExD,KAAK,CAAC,eAAe,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,EAAE,EAAE;gBACvC,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,CAAC,CAAC;YACH,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACnC,OAAO,OAAO,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC;QAC/B,CAAC;IAAA,CACF,CAAC,EAAE,CAAC;IAEL,OAAO,KAAK,CAAC,eAAe,CAAC;AAAA,CAC9B"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Base Server Sync Dialect
|
|
3
|
+
*
|
|
4
|
+
* Abstract base class that implements shared query methods for all
|
|
5
|
+
* database-specific sync dialect implementations.
|
|
6
|
+
*/
|
|
7
|
+
import type { ScopeValues, StoredScopes } from '@syncular/core';
|
|
8
|
+
import type { Kysely, RawBuilder, Transaction } from 'kysely';
|
|
9
|
+
import type { SyncChangeRow, SyncCommitRow, SyncCoreDb } from '../schema';
|
|
10
|
+
import type { DbExecutor, IncrementalPullRow, IncrementalPullRowsArgs, ServerSyncDialect } from './types';
|
|
11
|
+
/**
|
|
12
|
+
* Abstract base class for server sync dialects.
|
|
13
|
+
*
|
|
14
|
+
* Implements methods that are identical across dialects (pure SQL with no
|
|
15
|
+
* dialect-specific syntax) and methods that differ only in trivial SQL
|
|
16
|
+
* fragments (IN vs ANY, jsonb casts). Dialect-specific fragments are
|
|
17
|
+
* provided via small abstract hook methods.
|
|
18
|
+
*
|
|
19
|
+
* Genuinely different methods (DDL, transaction control, scope filtering,
|
|
20
|
+
* compaction) remain abstract for each dialect to implement.
|
|
21
|
+
*/
|
|
22
|
+
export declare abstract class BaseServerSyncDialect implements ServerSyncDialect {
|
|
23
|
+
abstract readonly name: string;
|
|
24
|
+
abstract readonly supportsForUpdate: boolean;
|
|
25
|
+
abstract readonly supportsSavepoints: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Build a SQL fragment for "column IN/= list of numbers".
|
|
28
|
+
* SQLite: `IN (1, 2, 3)` via sql.join
|
|
29
|
+
* Postgres: `= ANY(ARRAY[1,2,3]::bigint[])`
|
|
30
|
+
*/
|
|
31
|
+
protected abstract buildNumberListFilter(values: number[]): RawBuilder<unknown>;
|
|
32
|
+
/**
|
|
33
|
+
* Build a SQL fragment for "column IN/= list of strings".
|
|
34
|
+
* SQLite: `IN ('a', 'b')` via sql.join
|
|
35
|
+
* Postgres: `= ANY(ARRAY['a','b']::text[])`
|
|
36
|
+
*/
|
|
37
|
+
protected abstract buildStringListFilter(values: string[]): RawBuilder<unknown>;
|
|
38
|
+
abstract ensureSyncSchema<DB extends SyncCoreDb>(db: Kysely<DB>): Promise<void>;
|
|
39
|
+
abstract ensureConsoleSchema?<DB extends SyncCoreDb>(db: Kysely<DB>): Promise<void>;
|
|
40
|
+
abstract executeInTransaction<DB extends SyncCoreDb, T>(db: Kysely<DB>, fn: (executor: DbExecutor<DB>) => Promise<T>): Promise<T>;
|
|
41
|
+
abstract setRepeatableRead<DB extends SyncCoreDb>(trx: DbExecutor<DB>): Promise<void>;
|
|
42
|
+
abstract readChangesForCommits<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
43
|
+
commitSeqs: number[];
|
|
44
|
+
table: string;
|
|
45
|
+
scopes: ScopeValues;
|
|
46
|
+
partitionId?: string;
|
|
47
|
+
}): Promise<SyncChangeRow[]>;
|
|
48
|
+
protected abstract readIncrementalPullRowsBatch<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: Omit<IncrementalPullRowsArgs, 'batchSize'>): Promise<IncrementalPullRow[]>;
|
|
49
|
+
abstract compactChanges<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
50
|
+
fullHistoryHours: number;
|
|
51
|
+
}): Promise<number>;
|
|
52
|
+
abstract scopesToDb(scopes: StoredScopes): unknown;
|
|
53
|
+
abstract dbToArray(value: unknown): string[];
|
|
54
|
+
abstract arrayToDb(values: string[]): unknown;
|
|
55
|
+
readMaxCommitSeq<DB extends SyncCoreDb>(db: Kysely<DB> | Transaction<DB>, options?: {
|
|
56
|
+
partitionId?: string;
|
|
57
|
+
}): Promise<number>;
|
|
58
|
+
readMinCommitSeq<DB extends SyncCoreDb>(db: Kysely<DB> | Transaction<DB>, options?: {
|
|
59
|
+
partitionId?: string;
|
|
60
|
+
}): Promise<number>;
|
|
61
|
+
readAffectedTablesFromChanges<DB extends SyncCoreDb>(db: Kysely<DB> | Transaction<DB>, commitSeq: number, options?: {
|
|
62
|
+
partitionId?: string;
|
|
63
|
+
}): Promise<string[]>;
|
|
64
|
+
dbToScopes(value: unknown): StoredScopes;
|
|
65
|
+
readCommitSeqsForPull<DB extends SyncCoreDb>(db: Kysely<DB> | Transaction<DB>, args: {
|
|
66
|
+
cursor: number;
|
|
67
|
+
limitCommits: number;
|
|
68
|
+
tables: string[];
|
|
69
|
+
partitionId?: string;
|
|
70
|
+
}): Promise<number[]>;
|
|
71
|
+
readCommits<DB extends SyncCoreDb>(db: Kysely<DB> | Transaction<DB>, commitSeqs: number[], options?: {
|
|
72
|
+
partitionId?: string;
|
|
73
|
+
}): Promise<SyncCommitRow[]>;
|
|
74
|
+
recordClientCursor<DB extends SyncCoreDb>(db: Kysely<DB> | Transaction<DB>, args: {
|
|
75
|
+
partitionId?: string;
|
|
76
|
+
clientId: string;
|
|
77
|
+
actorId: string;
|
|
78
|
+
cursor: number;
|
|
79
|
+
effectiveScopes: ScopeValues;
|
|
80
|
+
}): Promise<void>;
|
|
81
|
+
iterateIncrementalPullRows<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: IncrementalPullRowsArgs): AsyncGenerator<IncrementalPullRow>;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/dialect/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Base Server Sync Dialect
|
|
3
|
+
*
|
|
4
|
+
* Abstract base class that implements shared query methods for all
|
|
5
|
+
* database-specific sync dialect implementations.
|
|
6
|
+
*/
|
|
7
|
+
import { sql } from 'kysely';
|
|
8
|
+
import { coerceIsoString, coerceNumber, parseScopes } from './helpers.js';
|
|
9
|
+
/**
|
|
10
|
+
* Abstract base class for server sync dialects.
|
|
11
|
+
*
|
|
12
|
+
* Implements methods that are identical across dialects (pure SQL with no
|
|
13
|
+
* dialect-specific syntax) and methods that differ only in trivial SQL
|
|
14
|
+
* fragments (IN vs ANY, jsonb casts). Dialect-specific fragments are
|
|
15
|
+
* provided via small abstract hook methods.
|
|
16
|
+
*
|
|
17
|
+
* Genuinely different methods (DDL, transaction control, scope filtering,
|
|
18
|
+
* compaction) remain abstract for each dialect to implement.
|
|
19
|
+
*/
|
|
20
|
+
export class BaseServerSyncDialect {
|
|
21
|
+
// ===========================================================================
|
|
22
|
+
// Concrete methods (identical SQL across dialects)
|
|
23
|
+
// ===========================================================================
|
|
24
|
+
async readMaxCommitSeq(db, options) {
|
|
25
|
+
const partitionId = options?.partitionId ?? 'default';
|
|
26
|
+
const res = await sql `
|
|
27
|
+
SELECT max(commit_seq) as max_seq
|
|
28
|
+
FROM sync_commits
|
|
29
|
+
WHERE partition_id = ${partitionId}
|
|
30
|
+
`.execute(db);
|
|
31
|
+
return coerceNumber(res.rows[0]?.max_seq) ?? 0;
|
|
32
|
+
}
|
|
33
|
+
async readMinCommitSeq(db, options) {
|
|
34
|
+
const partitionId = options?.partitionId ?? 'default';
|
|
35
|
+
const res = await sql `
|
|
36
|
+
SELECT min(commit_seq) as min_seq
|
|
37
|
+
FROM sync_commits
|
|
38
|
+
WHERE partition_id = ${partitionId}
|
|
39
|
+
`.execute(db);
|
|
40
|
+
return coerceNumber(res.rows[0]?.min_seq) ?? 0;
|
|
41
|
+
}
|
|
42
|
+
async readAffectedTablesFromChanges(db, commitSeq, options) {
|
|
43
|
+
const partitionId = options?.partitionId ?? 'default';
|
|
44
|
+
const res = await sql `
|
|
45
|
+
SELECT DISTINCT "table"
|
|
46
|
+
FROM sync_changes
|
|
47
|
+
WHERE commit_seq = ${commitSeq}
|
|
48
|
+
AND partition_id = ${partitionId}
|
|
49
|
+
`.execute(db);
|
|
50
|
+
return res.rows
|
|
51
|
+
.map((r) => r.table)
|
|
52
|
+
.filter((t) => typeof t === 'string' && t.length > 0);
|
|
53
|
+
}
|
|
54
|
+
dbToScopes(value) {
|
|
55
|
+
return parseScopes(value);
|
|
56
|
+
}
|
|
57
|
+
// ===========================================================================
|
|
58
|
+
// Concrete methods using hooks (trivial dialect diffs)
|
|
59
|
+
// ===========================================================================
|
|
60
|
+
async readCommitSeqsForPull(db, args) {
|
|
61
|
+
const partitionId = args.partitionId ?? 'default';
|
|
62
|
+
if (args.tables.length === 0)
|
|
63
|
+
return [];
|
|
64
|
+
const tablesFilter = this.buildStringListFilter(args.tables);
|
|
65
|
+
const res = await sql `
|
|
66
|
+
SELECT DISTINCT commit_seq
|
|
67
|
+
FROM sync_table_commits
|
|
68
|
+
WHERE partition_id = ${partitionId}
|
|
69
|
+
AND "table" ${tablesFilter}
|
|
70
|
+
AND commit_seq > ${args.cursor}
|
|
71
|
+
ORDER BY commit_seq ASC
|
|
72
|
+
LIMIT ${args.limitCommits}
|
|
73
|
+
`.execute(db);
|
|
74
|
+
return res.rows
|
|
75
|
+
.map((r) => coerceNumber(r.commit_seq))
|
|
76
|
+
.filter((n) => typeof n === 'number' && Number.isFinite(n) && n > args.cursor);
|
|
77
|
+
}
|
|
78
|
+
async readCommits(db, commitSeqs, options) {
|
|
79
|
+
const partitionId = options?.partitionId ?? 'default';
|
|
80
|
+
if (commitSeqs.length === 0)
|
|
81
|
+
return [];
|
|
82
|
+
const seqsFilter = this.buildNumberListFilter(commitSeqs);
|
|
83
|
+
const res = await sql `
|
|
84
|
+
SELECT commit_seq, actor_id, created_at, result_json
|
|
85
|
+
FROM sync_commits
|
|
86
|
+
WHERE commit_seq ${seqsFilter}
|
|
87
|
+
AND partition_id = ${partitionId}
|
|
88
|
+
ORDER BY commit_seq ASC
|
|
89
|
+
`.execute(db);
|
|
90
|
+
return res.rows.map((row) => ({
|
|
91
|
+
commit_seq: coerceNumber(row.commit_seq) ?? 0,
|
|
92
|
+
actor_id: row.actor_id,
|
|
93
|
+
created_at: coerceIsoString(row.created_at),
|
|
94
|
+
result_json: row.result_json ?? null,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
async recordClientCursor(db, args) {
|
|
98
|
+
const partitionId = args.partitionId ?? 'default';
|
|
99
|
+
const now = new Date().toISOString();
|
|
100
|
+
const scopesJson = JSON.stringify(args.effectiveScopes);
|
|
101
|
+
await sql `
|
|
102
|
+
INSERT INTO sync_client_cursors (partition_id, client_id, actor_id, cursor, effective_scopes, updated_at)
|
|
103
|
+
VALUES (${partitionId}, ${args.clientId}, ${args.actorId}, ${args.cursor}, ${scopesJson}, ${now})
|
|
104
|
+
ON CONFLICT(partition_id, client_id) DO UPDATE SET
|
|
105
|
+
actor_id = ${args.actorId},
|
|
106
|
+
cursor = ${args.cursor},
|
|
107
|
+
effective_scopes = ${scopesJson},
|
|
108
|
+
updated_at = ${now}
|
|
109
|
+
`.execute(db);
|
|
110
|
+
}
|
|
111
|
+
async *iterateIncrementalPullRows(db, args) {
|
|
112
|
+
const limitCommits = Math.max(1, Math.min(500, args.limitCommits));
|
|
113
|
+
const batchSize = Math.max(1, Math.min(limitCommits, args.batchSize ?? 100, 500));
|
|
114
|
+
let processedCommits = 0;
|
|
115
|
+
let cursor = args.cursor;
|
|
116
|
+
while (processedCommits < limitCommits) {
|
|
117
|
+
const remainingCommits = limitCommits - processedCommits;
|
|
118
|
+
const commitLimit = Math.min(batchSize, remainingCommits);
|
|
119
|
+
const rows = await this.readIncrementalPullRowsBatch(db, {
|
|
120
|
+
table: args.table,
|
|
121
|
+
scopes: args.scopes,
|
|
122
|
+
cursor,
|
|
123
|
+
limitCommits: commitLimit,
|
|
124
|
+
partitionId: args.partitionId,
|
|
125
|
+
});
|
|
126
|
+
if (rows.length === 0)
|
|
127
|
+
break;
|
|
128
|
+
let maxCommitSeq = cursor;
|
|
129
|
+
const commitSeqs = new Set();
|
|
130
|
+
for (const row of rows) {
|
|
131
|
+
maxCommitSeq = Math.max(maxCommitSeq, row.commit_seq);
|
|
132
|
+
commitSeqs.add(row.commit_seq);
|
|
133
|
+
yield row;
|
|
134
|
+
}
|
|
135
|
+
if (maxCommitSeq <= cursor)
|
|
136
|
+
break;
|
|
137
|
+
processedCommits += commitSeqs.size;
|
|
138
|
+
cursor = maxCommitSeq;
|
|
139
|
+
if (commitSeqs.size < commitLimit)
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/dialect/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Shared dialect helpers
|
|
3
|
+
*
|
|
4
|
+
* Pure helper functions used by all server sync dialect implementations.
|
|
5
|
+
*/
|
|
6
|
+
import type { StoredScopes } from '@syncular/core';
|
|
7
|
+
export declare function coerceNumber(value: unknown): number | null;
|
|
8
|
+
export declare function coerceIsoString(value: unknown): string;
|
|
9
|
+
export declare function parseScopes(value: unknown): StoredScopes;
|
|
10
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/dialect/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAU1D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAItD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAkCxD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Shared dialect helpers
|
|
3
|
+
*
|
|
4
|
+
* Pure helper functions used by all server sync dialect implementations.
|
|
5
|
+
*/
|
|
6
|
+
export function coerceNumber(value) {
|
|
7
|
+
if (value === null || value === undefined)
|
|
8
|
+
return null;
|
|
9
|
+
if (typeof value === 'number')
|
|
10
|
+
return Number.isFinite(value) ? value : null;
|
|
11
|
+
if (typeof value === 'bigint')
|
|
12
|
+
return Number.isFinite(Number(value)) ? Number(value) : null;
|
|
13
|
+
if (typeof value === 'string') {
|
|
14
|
+
const n = Number(value);
|
|
15
|
+
return Number.isFinite(n) ? n : null;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
export function coerceIsoString(value) {
|
|
20
|
+
if (typeof value === 'string')
|
|
21
|
+
return value;
|
|
22
|
+
if (value instanceof Date)
|
|
23
|
+
return value.toISOString();
|
|
24
|
+
return String(value);
|
|
25
|
+
}
|
|
26
|
+
export function parseScopes(value) {
|
|
27
|
+
if (value === null || value === undefined)
|
|
28
|
+
return {};
|
|
29
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
30
|
+
const result = {};
|
|
31
|
+
for (const [k, v] of Object.entries(value)) {
|
|
32
|
+
if (typeof v === 'string') {
|
|
33
|
+
result[k] = v;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
if (typeof value === 'string') {
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(value);
|
|
41
|
+
if (typeof parsed === 'object' &&
|
|
42
|
+
parsed !== null &&
|
|
43
|
+
!Array.isArray(parsed)) {
|
|
44
|
+
const result = {};
|
|
45
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
46
|
+
if (typeof v === 'string') {
|
|
47
|
+
result[k] = v;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// ignore
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/dialect/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,UAAU,YAAY,CAAC,KAAc,EAAiB;IAC1D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,IAAI,OAAO,KAAK,KAAK,QAAQ;QAC3B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AAAA,CACb;AAED,MAAM,UAAU,eAAe,CAAC,KAAc,EAAU;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,KAAK,YAAY,IAAI;QAAE,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IACtD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AAAA,CACtB;AAED,MAAM,UAAU,WAAW,CAAC,KAAc,EAAgB;IACxD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvD,MAAM,MAAM,GAAiB,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YACtE,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACjC,IACE,OAAO,MAAM,KAAK,QAAQ;gBAC1B,MAAM,KAAK,IAAI;gBACf,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EACtB,CAAC;gBACD,MAAM,MAAM,GAAiB,EAAE,CAAC;gBAChC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CACjC,MAAiC,CAClC,EAAE,CAAC;oBACF,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;wBAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;oBAChB,CAAC;gBACH,CAAC;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AAAA,CACX"}
|