@syncular/server 0.0.1-60
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 +180 -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/index.d.ts +5 -0
- package/dist/dialect/index.d.ts.map +1 -0
- package/dist/dialect/index.js +5 -0
- package/dist/dialect/index.js.map +1 -0
- package/dist/dialect/types.d.ts +170 -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 +99 -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 +31 -0
- package/dist/proxy/mutation-detector.d.ts.map +1 -0
- package/dist/proxy/mutation-detector.js +61 -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 +414 -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 +329 -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 +63 -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 +33 -0
- package/dist/snapshot-chunks/db-metadata.d.ts.map +1 -0
- package/dist/snapshot-chunks/db-metadata.js +169 -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 +65 -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 +59 -0
- package/dist/snapshot-chunks.d.ts.map +1 -0
- package/dist/snapshot-chunks.js +202 -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.ts +290 -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/index.ts +5 -0
- package/src/dialect/types.ts +222 -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.ts +152 -0
- package/src/proxy/index.ts +18 -0
- package/src/proxy/mutation-detector.ts +83 -0
- package/src/proxy/oplog.ts +144 -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 +551 -0
- package/src/push.ts +457 -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.ts +238 -0
- package/src/snapshot-chunks/index.ts +9 -0
- package/src/snapshot-chunks/types.ts +79 -0
- package/src/snapshot-chunks.ts +301 -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 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dialect/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dialect/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Server Sync Dialect Interface
|
|
3
|
+
*
|
|
4
|
+
* Abstracts database-specific operations for commit-log sync.
|
|
5
|
+
* Supports the new JSONB scopes model.
|
|
6
|
+
*/
|
|
7
|
+
import type { ScopeValues, StoredScopes, SyncOp } from '@syncular/core';
|
|
8
|
+
import type { Kysely, Transaction } from 'kysely';
|
|
9
|
+
import type { SyncChangeRow, SyncCommitRow, SyncCoreDb } from '../schema';
|
|
10
|
+
/**
|
|
11
|
+
* Common database executor type that works with both Kysely and Transaction.
|
|
12
|
+
* Generic version allows for extended database types that include sync tables.
|
|
13
|
+
*/
|
|
14
|
+
export type DbExecutor<DB extends SyncCoreDb = SyncCoreDb> = Kysely<DB> | Transaction<DB>;
|
|
15
|
+
/**
|
|
16
|
+
* Supported dialect names.
|
|
17
|
+
*/
|
|
18
|
+
export type ServerSyncDialectName = string;
|
|
19
|
+
export interface ServerSyncDialect {
|
|
20
|
+
readonly name: ServerSyncDialectName;
|
|
21
|
+
/** Create sync tables + indexes (idempotent) */
|
|
22
|
+
ensureSyncSchema<DB extends SyncCoreDb>(db: Kysely<DB>): Promise<void>;
|
|
23
|
+
/** Create console-specific tables (e.g., sync_request_events) - optional */
|
|
24
|
+
ensureConsoleSchema?<DB extends SyncCoreDb>(db: Kysely<DB>): Promise<void>;
|
|
25
|
+
/** Execute callback in a transaction (or directly if transactions not supported). */
|
|
26
|
+
executeInTransaction<DB extends SyncCoreDb, T>(db: Kysely<DB>, fn: (executor: DbExecutor<DB>) => Promise<T>): Promise<T>;
|
|
27
|
+
/** Set REPEATABLE READ (or closest equivalent) */
|
|
28
|
+
setRepeatableRead<DB extends SyncCoreDb>(trx: DbExecutor<DB>): Promise<void>;
|
|
29
|
+
/** Read the maximum committed commit_seq (0 if none) */
|
|
30
|
+
readMaxCommitSeq<DB extends SyncCoreDb>(db: DbExecutor<DB>, options?: {
|
|
31
|
+
partitionId?: string;
|
|
32
|
+
}): Promise<number>;
|
|
33
|
+
/** Read the minimum committed commit_seq (0 if none) */
|
|
34
|
+
readMinCommitSeq<DB extends SyncCoreDb>(db: DbExecutor<DB>, options?: {
|
|
35
|
+
partitionId?: string;
|
|
36
|
+
}): Promise<number>;
|
|
37
|
+
/**
|
|
38
|
+
* Read the next commit sequence numbers that have changes for the given tables.
|
|
39
|
+
* Must return commit_seq values in ascending order.
|
|
40
|
+
*/
|
|
41
|
+
readCommitSeqsForPull<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
42
|
+
cursor: number;
|
|
43
|
+
limitCommits: number;
|
|
44
|
+
tables: string[];
|
|
45
|
+
partitionId?: string;
|
|
46
|
+
}): Promise<number[]>;
|
|
47
|
+
/** Read commit metadata for commit_seq values */
|
|
48
|
+
readCommits<DB extends SyncCoreDb>(db: DbExecutor<DB>, commitSeqs: number[], options?: {
|
|
49
|
+
partitionId?: string;
|
|
50
|
+
}): Promise<SyncCommitRow[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Read changes for commit_seq values, filtered by table and scopes.
|
|
53
|
+
* Uses JSONB filtering for scope matching.
|
|
54
|
+
*/
|
|
55
|
+
readChangesForCommits<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
56
|
+
commitSeqs: number[];
|
|
57
|
+
table: string;
|
|
58
|
+
scopes: ScopeValues;
|
|
59
|
+
partitionId?: string;
|
|
60
|
+
}): Promise<SyncChangeRow[]>;
|
|
61
|
+
/**
|
|
62
|
+
* Optimized incremental pull for a subscription.
|
|
63
|
+
*
|
|
64
|
+
* Returns change rows joined with commit metadata and filtered by
|
|
65
|
+
* the subscription's table and scope values.
|
|
66
|
+
*/
|
|
67
|
+
readIncrementalPullRows<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
68
|
+
table: string;
|
|
69
|
+
scopes: ScopeValues;
|
|
70
|
+
cursor: number;
|
|
71
|
+
limitCommits: number;
|
|
72
|
+
partitionId?: string;
|
|
73
|
+
}): Promise<Array<{
|
|
74
|
+
commit_seq: number;
|
|
75
|
+
actor_id: string;
|
|
76
|
+
created_at: string;
|
|
77
|
+
change_id: number;
|
|
78
|
+
table: string;
|
|
79
|
+
row_id: string;
|
|
80
|
+
op: SyncOp;
|
|
81
|
+
row_json: unknown | null;
|
|
82
|
+
row_version: number | null;
|
|
83
|
+
scopes: StoredScopes;
|
|
84
|
+
}>>;
|
|
85
|
+
/**
|
|
86
|
+
* Streaming incremental pull for large result sets.
|
|
87
|
+
*
|
|
88
|
+
* Yields changes one at a time instead of loading all into memory.
|
|
89
|
+
* Use this when expecting large numbers of changes.
|
|
90
|
+
*/
|
|
91
|
+
streamIncrementalPullRows?<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
92
|
+
table: string;
|
|
93
|
+
scopes: ScopeValues;
|
|
94
|
+
cursor: number;
|
|
95
|
+
limitCommits: number;
|
|
96
|
+
partitionId?: string;
|
|
97
|
+
}): AsyncGenerator<{
|
|
98
|
+
commit_seq: number;
|
|
99
|
+
actor_id: string;
|
|
100
|
+
created_at: string;
|
|
101
|
+
change_id: number;
|
|
102
|
+
table: string;
|
|
103
|
+
row_id: string;
|
|
104
|
+
op: SyncOp;
|
|
105
|
+
row_json: unknown | null;
|
|
106
|
+
row_version: number | null;
|
|
107
|
+
scopes: StoredScopes;
|
|
108
|
+
}>;
|
|
109
|
+
/**
|
|
110
|
+
* Optional compaction of the change log to reduce storage.
|
|
111
|
+
*
|
|
112
|
+
* Keeps full history for the most recent N hours.
|
|
113
|
+
* For older history, keeps only the newest change per (table, row_id, scopes).
|
|
114
|
+
*/
|
|
115
|
+
compactChanges<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
116
|
+
fullHistoryHours: number;
|
|
117
|
+
}): Promise<number>;
|
|
118
|
+
/**
|
|
119
|
+
* Record/update a client cursor for tracking and pruning.
|
|
120
|
+
*/
|
|
121
|
+
recordClientCursor<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
|
|
122
|
+
partitionId?: string;
|
|
123
|
+
clientId: string;
|
|
124
|
+
actorId: string;
|
|
125
|
+
cursor: number;
|
|
126
|
+
effectiveScopes: ScopeValues;
|
|
127
|
+
}): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Convert a StoredScopes object to database representation.
|
|
130
|
+
* For Postgres: returns as-is (native JSONB)
|
|
131
|
+
* For SQLite: returns JSON.stringify()
|
|
132
|
+
*/
|
|
133
|
+
scopesToDb(scopes: StoredScopes): unknown;
|
|
134
|
+
/**
|
|
135
|
+
* Convert database scopes representation to StoredScopes.
|
|
136
|
+
*/
|
|
137
|
+
dbToScopes(value: unknown): StoredScopes;
|
|
138
|
+
/**
|
|
139
|
+
* Whether the dialect supports SELECT ... FOR UPDATE row locking.
|
|
140
|
+
* Postgres: true
|
|
141
|
+
* SQLite: false (uses database-level locking)
|
|
142
|
+
*/
|
|
143
|
+
readonly supportsForUpdate: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Whether the dialect supports SAVEPOINT / ROLLBACK TO SAVEPOINT.
|
|
146
|
+
* Postgres/SQLite: true
|
|
147
|
+
* D1 (Durable Object): false (blocks raw SAVEPOINT statements)
|
|
148
|
+
*/
|
|
149
|
+
readonly supportsSavepoints: boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Read distinct tables from sync_changes for a given commit.
|
|
152
|
+
* Used for realtime notifications.
|
|
153
|
+
*/
|
|
154
|
+
readAffectedTablesFromChanges<DB extends SyncCoreDb>(db: DbExecutor<DB>, commitSeq: number, options?: {
|
|
155
|
+
partitionId?: string;
|
|
156
|
+
}): Promise<string[]>;
|
|
157
|
+
/**
|
|
158
|
+
* Convert database array representation to string[].
|
|
159
|
+
* For Postgres: returns as-is (native array)
|
|
160
|
+
* For SQLite: returns JSON.parse() or empty array if null
|
|
161
|
+
*/
|
|
162
|
+
dbToArray(value: unknown): string[];
|
|
163
|
+
/**
|
|
164
|
+
* Convert string[] to database array representation.
|
|
165
|
+
* For Postgres: returns as-is (native array)
|
|
166
|
+
* For SQLite: returns JSON.stringify()
|
|
167
|
+
*/
|
|
168
|
+
arrayToDb(values: string[]): unknown;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dialect/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/dialect/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Conflict result builder
|
|
3
|
+
*
|
|
4
|
+
* Helper for building conflict results in server table handlers.
|
|
5
|
+
*/
|
|
6
|
+
import type { ApplyOperationResult } from '../shapes/types';
|
|
7
|
+
export interface BuildConflictResultArgs {
|
|
8
|
+
/** Index of the operation in the batch */
|
|
9
|
+
opIndex: number;
|
|
10
|
+
/** Current server row data */
|
|
11
|
+
serverRow: unknown;
|
|
12
|
+
/** Current server version */
|
|
13
|
+
serverVersion: number;
|
|
14
|
+
/** Client's base version (what they thought they were updating) */
|
|
15
|
+
baseVersion: number | null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build a conflict result for applyOperation.
|
|
19
|
+
*
|
|
20
|
+
* Use this when the client's base version doesn't match the server's current version,
|
|
21
|
+
* indicating a concurrent modification conflict.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const handler: ServerTableHandler = {
|
|
26
|
+
* table: 'tasks',
|
|
27
|
+
* async applyOperation(ctx, op, opIndex) {
|
|
28
|
+
* const existing = await ctx.db
|
|
29
|
+
* .selectFrom('tasks')
|
|
30
|
+
* .selectAll()
|
|
31
|
+
* .where('id', '=', op.row_id)
|
|
32
|
+
* .executeTakeFirst();
|
|
33
|
+
*
|
|
34
|
+
* // Check for version conflict
|
|
35
|
+
* if (existing && op.base_version !== null && existing.version !== op.base_version) {
|
|
36
|
+
* return {
|
|
37
|
+
* result: buildConflictResult({
|
|
38
|
+
* opIndex,
|
|
39
|
+
* serverRow: existing,
|
|
40
|
+
* serverVersion: existing.version,
|
|
41
|
+
* baseVersion: op.base_version,
|
|
42
|
+
* }),
|
|
43
|
+
* };
|
|
44
|
+
* }
|
|
45
|
+
*
|
|
46
|
+
* // ... apply the operation
|
|
47
|
+
* },
|
|
48
|
+
* };
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildConflictResult(args: BuildConflictResultArgs): ApplyOperationResult['result'];
|
|
52
|
+
//# sourceMappingURL=conflict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.d.ts","sourceRoot":"","sources":["../../src/helpers/conflict.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE5D,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,6BAA6B;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,uBAAuB,GAC5B,oBAAoB,CAAC,QAAQ,CAAC,CAQhC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - Conflict result builder
|
|
3
|
+
*
|
|
4
|
+
* Helper for building conflict results in server table handlers.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Build a conflict result for applyOperation.
|
|
8
|
+
*
|
|
9
|
+
* Use this when the client's base version doesn't match the server's current version,
|
|
10
|
+
* indicating a concurrent modification conflict.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const handler: ServerTableHandler = {
|
|
15
|
+
* table: 'tasks',
|
|
16
|
+
* async applyOperation(ctx, op, opIndex) {
|
|
17
|
+
* const existing = await ctx.db
|
|
18
|
+
* .selectFrom('tasks')
|
|
19
|
+
* .selectAll()
|
|
20
|
+
* .where('id', '=', op.row_id)
|
|
21
|
+
* .executeTakeFirst();
|
|
22
|
+
*
|
|
23
|
+
* // Check for version conflict
|
|
24
|
+
* if (existing && op.base_version !== null && existing.version !== op.base_version) {
|
|
25
|
+
* return {
|
|
26
|
+
* result: buildConflictResult({
|
|
27
|
+
* opIndex,
|
|
28
|
+
* serverRow: existing,
|
|
29
|
+
* serverVersion: existing.version,
|
|
30
|
+
* baseVersion: op.base_version,
|
|
31
|
+
* }),
|
|
32
|
+
* };
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* // ... apply the operation
|
|
36
|
+
* },
|
|
37
|
+
* };
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function buildConflictResult(args) {
|
|
41
|
+
return {
|
|
42
|
+
opIndex: args.opIndex,
|
|
43
|
+
status: 'conflict',
|
|
44
|
+
message: `Version conflict: server=${args.serverVersion}, base=${args.baseVersion}`,
|
|
45
|
+
server_version: args.serverVersion,
|
|
46
|
+
server_row: args.serverRow,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=conflict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.js","sourceRoot":"","sources":["../../src/helpers/conflict.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAeH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAA6B,EACG;IAChC,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,UAAU;QAClB,OAAO,EAAE,4BAA4B,IAAI,CAAC,aAAa,UAAU,IAAI,CAAC,WAAW,EAAE;QACnF,cAAc,EAAE,IAAI,CAAC,aAAa;QAClC,UAAU,EAAE,IAAI,CAAC,SAAS;KAC3B,CAAC;AAAA,CACH"}
|