@syncular/server 0.1.3 → 0.2.1
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/README.md +773 -13
- package/dist/admin.d.ts +136 -0
- package/dist/admin.js +168 -0
- package/dist/blob-handlers.d.ts +69 -0
- package/dist/blob-handlers.js +245 -0
- package/dist/blob-store.d.ts +111 -0
- package/dist/blob-store.js +0 -0
- package/dist/content-encoding.d.ts +27 -0
- package/dist/content-encoding.js +69 -0
- package/dist/context.d.ts +151 -0
- package/dist/context.js +21 -0
- package/dist/crdt-merger.d.ts +28 -0
- package/dist/crdt-merger.js +11 -0
- package/dist/d1-storage.d.ts +50 -0
- package/dist/d1-storage.js +0 -0
- package/dist/errors.d.ts +35 -9
- package/dist/errors.js +220 -11
- package/dist/events-ring.d.ts +55 -0
- package/dist/events-ring.js +96 -0
- package/dist/events.d.ts +231 -0
- package/dist/events.js +22 -0
- package/dist/frame-bytes.d.ts +20 -0
- package/dist/frame-bytes.js +75 -0
- package/dist/handler.d.ts +9 -0
- package/dist/handler.js +490 -0
- package/dist/index.d.ts +42 -33
- package/dist/index.js +45 -27
- package/dist/lease-store.d.ts +50 -0
- package/dist/lease-store.js +0 -0
- package/dist/pg-executor-pglite.d.ts +27 -0
- package/dist/pg-executor-pglite.js +33 -0
- package/dist/pg-executor.d.ts +67 -0
- package/dist/pg-executor.js +56 -0
- package/dist/postgres-fanout.d.ts +83 -0
- package/dist/postgres-fanout.js +71 -0
- package/dist/postgres-storage.d.ts +69 -0
- package/dist/postgres-storage.js +766 -0
- package/dist/prune.d.ts +24 -39
- package/dist/prune.js +44 -146
- package/dist/pull.d.ts +42 -67
- package/dist/pull.js +387 -1187
- package/dist/push.d.ts +31 -66
- package/dist/push.js +406 -655
- package/dist/realtime.d.ts +197 -0
- package/dist/realtime.js +848 -0
- package/dist/relational-rows.d.ts +229 -0
- package/dist/relational-rows.js +514 -0
- package/dist/s3-blob-store.d.ts +142 -0
- package/dist/s3-blob-store.js +458 -0
- package/dist/s3-segment-store.d.ts +95 -0
- package/dist/s3-segment-store.js +380 -0
- package/dist/schema.d.ts +82 -286
- package/dist/schema.js +133 -9
- package/dist/scopes.d.ts +48 -0
- package/dist/scopes.js +98 -0
- package/dist/segment-download.d.ts +14 -0
- package/dist/segment-download.js +125 -0
- package/dist/segment-store.d.ts +81 -0
- package/dist/segment-store.js +63 -0
- package/dist/signed-url.d.ts +139 -0
- package/dist/signed-url.js +143 -0
- package/dist/sigv4.d.ts +97 -0
- package/dist/sigv4.js +161 -0
- package/dist/sqlite-blob-store.d.ts +22 -0
- package/dist/sqlite-blob-store.js +86 -0
- package/dist/sqlite-dialect.d.ts +101 -0
- package/dist/sqlite-dialect.js +250 -0
- package/dist/sqlite-image.d.ts +27 -0
- package/dist/sqlite-image.js +83 -0
- package/dist/sqlite-lease-store.d.ts +21 -0
- package/dist/sqlite-lease-store.js +94 -0
- package/dist/sqlite-segment-store.d.ts +25 -0
- package/dist/sqlite-segment-store.js +115 -0
- package/dist/sqlite-storage.d.ts +47 -0
- package/dist/sqlite-storage.js +477 -0
- package/dist/storage.d.ts +252 -0
- package/dist/storage.js +1 -0
- package/dist/validate.d.ts +83 -0
- package/dist/validate.js +44 -0
- package/package.json +17 -325
- package/src/admin.ts +312 -0
- package/src/blob-handlers.ts +340 -0
- package/src/blob-store.ts +0 -0
- package/src/content-encoding.ts +94 -0
- package/src/context.ts +176 -0
- package/src/crdt-merger.ts +33 -0
- package/src/d1-storage.ts +0 -0
- package/src/errors.ts +241 -19
- package/src/events-ring.ts +116 -0
- package/src/events.ts +291 -0
- package/src/frame-bytes.ts +94 -0
- package/src/handler.ts +678 -0
- package/src/index.ts +44 -27
- package/src/lease-store.ts +0 -0
- package/src/pg-executor-pglite.ts +63 -0
- package/src/pg-executor.ts +87 -0
- package/src/postgres-fanout.ts +143 -0
- package/src/postgres-storage.ts +1182 -0
- package/src/prune.ts +63 -289
- package/src/pull.ts +505 -1805
- package/src/push.ts +623 -1006
- package/src/realtime.ts +1082 -0
- package/src/relational-rows.ts +633 -0
- package/src/s3-blob-store.ts +616 -0
- package/src/s3-segment-store.ts +519 -0
- package/src/schema.ts +242 -281
- package/src/scopes.ts +127 -0
- package/src/segment-download.ts +169 -0
- package/src/segment-store.ts +154 -0
- package/src/signed-url.ts +308 -0
- package/src/sigv4.ts +267 -0
- package/src/sqlite-blob-store.ts +125 -0
- package/src/sqlite-dialect.ts +337 -0
- package/src/sqlite-image.ts +124 -0
- package/src/sqlite-lease-store.ts +144 -0
- package/src/sqlite-segment-store.ts +204 -0
- package/src/sqlite-storage.ts +792 -0
- package/src/storage.ts +316 -0
- package/src/validate.ts +123 -0
- package/dist/auth-leases.d.ts +0 -85
- package/dist/auth-leases.d.ts.map +0 -1
- package/dist/auth-leases.js +0 -368
- package/dist/auth-leases.js.map +0 -1
- package/dist/better-sqlite3.d.ts +0 -22
- package/dist/better-sqlite3.d.ts.map +0 -1
- package/dist/better-sqlite3.js +0 -16
- package/dist/better-sqlite3.js.map +0 -1
- package/dist/blobs/access.d.ts +0 -35
- package/dist/blobs/access.d.ts.map +0 -1
- package/dist/blobs/access.js +0 -149
- package/dist/blobs/access.js.map +0 -1
- package/dist/blobs/adapters/database.d.ts +0 -100
- package/dist/blobs/adapters/database.d.ts.map +0 -1
- package/dist/blobs/adapters/database.js +0 -247
- package/dist/blobs/adapters/database.js.map +0 -1
- package/dist/blobs/index.d.ts +0 -9
- package/dist/blobs/index.d.ts.map +0 -1
- package/dist/blobs/index.js +0 -9
- package/dist/blobs/index.js.map +0 -1
- package/dist/blobs/manager.d.ts +0 -220
- package/dist/blobs/manager.d.ts.map +0 -1
- package/dist/blobs/manager.js +0 -625
- package/dist/blobs/manager.js.map +0 -1
- package/dist/blobs/migrate.d.ts +0 -27
- package/dist/blobs/migrate.d.ts.map +0 -1
- package/dist/blobs/migrate.js +0 -127
- package/dist/blobs/migrate.js.map +0 -1
- package/dist/blobs/types.d.ts +0 -58
- package/dist/blobs/types.d.ts.map +0 -1
- package/dist/blobs/types.js +0 -5
- package/dist/blobs/types.js.map +0 -1
- package/dist/bun-sqlite.d.ts +0 -19
- package/dist/bun-sqlite.d.ts.map +0 -1
- package/dist/bun-sqlite.js +0 -19
- package/dist/bun-sqlite.js.map +0 -1
- package/dist/clients.d.ts +0 -15
- package/dist/clients.d.ts.map +0 -1
- package/dist/clients.js +0 -7
- package/dist/clients.js.map +0 -1
- package/dist/cloudflare/durable-object.d.ts +0 -93
- package/dist/cloudflare/durable-object.d.ts.map +0 -1
- package/dist/cloudflare/durable-object.js +0 -210
- package/dist/cloudflare/durable-object.js.map +0 -1
- package/dist/cloudflare/index.d.ts +0 -22
- package/dist/cloudflare/index.d.ts.map +0 -1
- package/dist/cloudflare/index.js +0 -22
- package/dist/cloudflare/index.js.map +0 -1
- package/dist/cloudflare/r2.d.ts +0 -180
- package/dist/cloudflare/r2.d.ts.map +0 -1
- package/dist/cloudflare/r2.js +0 -258
- package/dist/cloudflare/r2.js.map +0 -1
- package/dist/cloudflare/scope-cache.d.ts +0 -54
- package/dist/cloudflare/scope-cache.d.ts.map +0 -1
- package/dist/cloudflare/scope-cache.js +0 -223
- package/dist/cloudflare/scope-cache.js.map +0 -1
- package/dist/cloudflare/sentry.d.ts +0 -47
- package/dist/cloudflare/sentry.d.ts.map +0 -1
- package/dist/cloudflare/sentry.js +0 -163
- package/dist/cloudflare/sentry.js.map +0 -1
- package/dist/cloudflare/worker.d.ts +0 -46
- package/dist/cloudflare/worker.d.ts.map +0 -1
- package/dist/cloudflare/worker.js +0 -63
- package/dist/cloudflare/worker.js.map +0 -1
- package/dist/commit-integrity.d.ts +0 -38
- package/dist/commit-integrity.d.ts.map +0 -1
- package/dist/commit-integrity.js +0 -260
- package/dist/commit-integrity.js.map +0 -1
- package/dist/compaction.d.ts +0 -27
- package/dist/compaction.d.ts.map +0 -1
- package/dist/compaction.js +0 -49
- package/dist/compaction.js.map +0 -1
- package/dist/crdt-yjs/index.d.ts +0 -99
- package/dist/crdt-yjs/index.d.ts.map +0 -1
- package/dist/crdt-yjs/index.js +0 -629
- package/dist/crdt-yjs/index.js.map +0 -1
- package/dist/d1.d.ts +0 -13
- package/dist/d1.d.ts.map +0 -1
- package/dist/d1.js +0 -14
- package/dist/d1.js.map +0 -1
- package/dist/dialect/base.d.ts +0 -93
- package/dist/dialect/base.d.ts.map +0 -1
- package/dist/dialect/base.js +0 -181
- package/dist/dialect/base.js.map +0 -1
- package/dist/dialect/helpers.d.ts +0 -16
- package/dist/dialect/helpers.d.ts.map +0 -1
- package/dist/dialect/helpers.js +0 -83
- package/dist/dialect/helpers.js.map +0 -1
- package/dist/dialect/index.d.ts +0 -7
- package/dist/dialect/index.d.ts.map +0 -1
- package/dist/dialect/index.js +0 -7
- package/dist/dialect/index.js.map +0 -1
- package/dist/dialect/types.d.ts +0 -187
- package/dist/dialect/types.d.ts.map +0 -1
- package/dist/dialect/types.js +0 -8
- package/dist/dialect/types.js.map +0 -1
- package/dist/encrypted-crdt.d.ts +0 -67
- package/dist/encrypted-crdt.d.ts.map +0 -1
- package/dist/encrypted-crdt.js +0 -426
- package/dist/encrypted-crdt.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/filesystem/index.d.ts +0 -44
- package/dist/filesystem/index.d.ts.map +0 -1
- package/dist/filesystem/index.js +0 -164
- package/dist/filesystem/index.js.map +0 -1
- package/dist/handlers/collection.d.ts +0 -20
- package/dist/handlers/collection.d.ts.map +0 -1
- package/dist/handlers/collection.js +0 -42
- package/dist/handlers/collection.js.map +0 -1
- package/dist/handlers/create-handler.d.ts +0 -156
- package/dist/handlers/create-handler.d.ts.map +0 -1
- package/dist/handlers/create-handler.js +0 -626
- package/dist/handlers/create-handler.js.map +0 -1
- package/dist/handlers/index.d.ts +0 -4
- package/dist/handlers/index.d.ts.map +0 -1
- package/dist/handlers/index.js +0 -4
- package/dist/handlers/index.js.map +0 -1
- package/dist/handlers/types.d.ts +0 -295
- package/dist/handlers/types.d.ts.map +0 -1
- package/dist/handlers/types.js +0 -2
- package/dist/handlers/types.js.map +0 -1
- package/dist/helpers/conflict.d.ts +0 -52
- package/dist/helpers/conflict.d.ts.map +0 -1
- package/dist/helpers/conflict.js +0 -49
- package/dist/helpers/conflict.js.map +0 -1
- package/dist/helpers/emitted-change.d.ts +0 -56
- package/dist/helpers/emitted-change.d.ts.map +0 -1
- package/dist/helpers/emitted-change.js +0 -46
- package/dist/helpers/emitted-change.js.map +0 -1
- package/dist/helpers/index.d.ts +0 -12
- package/dist/helpers/index.d.ts.map +0 -1
- package/dist/helpers/index.js +0 -12
- package/dist/helpers/index.js.map +0 -1
- package/dist/helpers/paginate.d.ts +0 -49
- package/dist/helpers/paginate.d.ts.map +0 -1
- package/dist/helpers/paginate.js +0 -54
- package/dist/helpers/paginate.js.map +0 -1
- package/dist/helpers/scope-authorization.d.ts +0 -7
- package/dist/helpers/scope-authorization.d.ts.map +0 -1
- package/dist/helpers/scope-authorization.js +0 -19
- package/dist/helpers/scope-authorization.js.map +0 -1
- package/dist/helpers/scope-commit-index.d.ts +0 -12
- package/dist/helpers/scope-commit-index.d.ts.map +0 -1
- package/dist/helpers/scope-commit-index.js +0 -35
- package/dist/helpers/scope-commit-index.js.map +0 -1
- package/dist/helpers/scope-strings.d.ts +0 -74
- package/dist/helpers/scope-strings.d.ts.map +0 -1
- package/dist/helpers/scope-strings.js +0 -82
- package/dist/helpers/scope-strings.js.map +0 -1
- package/dist/hono/api-key-auth.d.ts +0 -49
- package/dist/hono/api-key-auth.d.ts.map +0 -1
- package/dist/hono/api-key-auth.js +0 -108
- package/dist/hono/api-key-auth.js.map +0 -1
- package/dist/hono/audit-redaction.d.ts +0 -20
- package/dist/hono/audit-redaction.d.ts.map +0 -1
- package/dist/hono/audit-redaction.js +0 -85
- package/dist/hono/audit-redaction.js.map +0 -1
- package/dist/hono/blobs.d.ts +0 -75
- package/dist/hono/blobs.d.ts.map +0 -1
- package/dist/hono/blobs.js +0 -586
- package/dist/hono/blobs.js.map +0 -1
- package/dist/hono/console/gateway.d.ts +0 -42
- package/dist/hono/console/gateway.d.ts.map +0 -1
- package/dist/hono/console/gateway.js +0 -2158
- package/dist/hono/console/gateway.js.map +0 -1
- package/dist/hono/console/live-auth.d.ts +0 -7
- package/dist/hono/console/live-auth.d.ts.map +0 -1
- package/dist/hono/console/live-auth.js +0 -39
- package/dist/hono/console/live-auth.js.map +0 -1
- package/dist/hono/console/route-descriptor.d.ts +0 -6
- package/dist/hono/console/route-descriptor.d.ts.map +0 -1
- package/dist/hono/console/route-descriptor.js +0 -16
- package/dist/hono/console/route-descriptor.js.map +0 -1
- package/dist/hono/console/routes/api-keys.d.ts +0 -8
- package/dist/hono/console/routes/api-keys.d.ts.map +0 -1
- package/dist/hono/console/routes/api-keys.js +0 -575
- package/dist/hono/console/routes/api-keys.js.map +0 -1
- package/dist/hono/console/routes/clients.d.ts +0 -8
- package/dist/hono/console/routes/clients.d.ts.map +0 -1
- package/dist/hono/console/routes/clients.js +0 -322
- package/dist/hono/console/routes/clients.js.map +0 -1
- package/dist/hono/console/routes/commits.d.ts +0 -8
- package/dist/hono/console/routes/commits.d.ts.map +0 -1
- package/dist/hono/console/routes/commits.js +0 -882
- package/dist/hono/console/routes/commits.js.map +0 -1
- package/dist/hono/console/routes/context.d.ts +0 -188
- package/dist/hono/console/routes/context.d.ts.map +0 -1
- package/dist/hono/console/routes/context.js +0 -633
- package/dist/hono/console/routes/context.js.map +0 -1
- package/dist/hono/console/routes/events.d.ts +0 -8
- package/dist/hono/console/routes/events.d.ts.map +0 -1
- package/dist/hono/console/routes/events.js +0 -501
- package/dist/hono/console/routes/events.js.map +0 -1
- package/dist/hono/console/routes/maintenance.d.ts +0 -8
- package/dist/hono/console/routes/maintenance.d.ts.map +0 -1
- package/dist/hono/console/routes/maintenance.js +0 -341
- package/dist/hono/console/routes/maintenance.js.map +0 -1
- package/dist/hono/console/routes/shared.d.ts +0 -174
- package/dist/hono/console/routes/shared.d.ts.map +0 -1
- package/dist/hono/console/routes/shared.js +0 -583
- package/dist/hono/console/routes/shared.js.map +0 -1
- package/dist/hono/console/routes/stats.d.ts +0 -8
- package/dist/hono/console/routes/stats.d.ts.map +0 -1
- package/dist/hono/console/routes/stats.js +0 -295
- package/dist/hono/console/routes/stats.js.map +0 -1
- package/dist/hono/console/routes/storage.d.ts +0 -8
- package/dist/hono/console/routes/storage.d.ts.map +0 -1
- package/dist/hono/console/routes/storage.js +0 -121
- package/dist/hono/console/routes/storage.js.map +0 -1
- package/dist/hono/console/routes.d.ts +0 -36
- package/dist/hono/console/routes.d.ts.map +0 -1
- package/dist/hono/console/routes.js +0 -112
- package/dist/hono/console/routes.js.map +0 -1
- package/dist/hono/console/schema-errors.d.ts +0 -2
- package/dist/hono/console/schema-errors.d.ts.map +0 -1
- package/dist/hono/console/schema-errors.js +0 -17
- package/dist/hono/console/schema-errors.js.map +0 -1
- package/dist/hono/console/schemas.d.ts +0 -1515
- package/dist/hono/console/schemas.d.ts.map +0 -1
- package/dist/hono/console/schemas.js +0 -661
- package/dist/hono/console/schemas.js.map +0 -1
- package/dist/hono/console/types.d.ts +0 -213
- package/dist/hono/console/types.d.ts.map +0 -1
- package/dist/hono/console/types.js +0 -2
- package/dist/hono/console/types.js.map +0 -1
- package/dist/hono/console/ui.d.ts +0 -38
- package/dist/hono/console/ui.d.ts.map +0 -1
- package/dist/hono/console/ui.js +0 -43
- package/dist/hono/console/ui.js.map +0 -1
- package/dist/hono/create-server.d.ts +0 -71
- package/dist/hono/create-server.d.ts.map +0 -1
- package/dist/hono/create-server.js +0 -121
- package/dist/hono/create-server.js.map +0 -1
- package/dist/hono/errors.d.ts +0 -13
- package/dist/hono/errors.d.ts.map +0 -1
- package/dist/hono/errors.js +0 -21
- package/dist/hono/errors.js.map +0 -1
- package/dist/hono/index.d.ts +0 -20
- package/dist/hono/index.d.ts.map +0 -1
- package/dist/hono/index.js +0 -31
- package/dist/hono/index.js.map +0 -1
- package/dist/hono/openapi.d.ts +0 -72
- package/dist/hono/openapi.d.ts.map +0 -1
- package/dist/hono/openapi.js +0 -99
- package/dist/hono/openapi.js.map +0 -1
- package/dist/hono/proxy/connection-manager.d.ts +0 -78
- package/dist/hono/proxy/connection-manager.d.ts.map +0 -1
- package/dist/hono/proxy/connection-manager.js +0 -251
- package/dist/hono/proxy/connection-manager.js.map +0 -1
- package/dist/hono/proxy/index.d.ts +0 -8
- package/dist/hono/proxy/index.d.ts.map +0 -1
- package/dist/hono/proxy/index.js +0 -8
- package/dist/hono/proxy/index.js.map +0 -1
- package/dist/hono/proxy/routes.d.ts +0 -86
- package/dist/hono/proxy/routes.d.ts.map +0 -1
- package/dist/hono/proxy/routes.js +0 -183
- package/dist/hono/proxy/routes.js.map +0 -1
- package/dist/hono/rate-limit.d.ts +0 -101
- package/dist/hono/rate-limit.d.ts.map +0 -1
- package/dist/hono/rate-limit.js +0 -184
- package/dist/hono/rate-limit.js.map +0 -1
- package/dist/hono/realtime-sync-packs.d.ts +0 -43
- package/dist/hono/realtime-sync-packs.d.ts.map +0 -1
- package/dist/hono/realtime-sync-packs.js +0 -219
- package/dist/hono/realtime-sync-packs.js.map +0 -1
- package/dist/hono/routes/audit.d.ts +0 -12
- package/dist/hono/routes/audit.d.ts.map +0 -1
- package/dist/hono/routes/audit.js +0 -385
- package/dist/hono/routes/audit.js.map +0 -1
- package/dist/hono/routes/auth-leases.d.ts +0 -8
- package/dist/hono/routes/auth-leases.d.ts.map +0 -1
- package/dist/hono/routes/auth-leases.js +0 -88
- package/dist/hono/routes/auth-leases.js.map +0 -1
- package/dist/hono/routes/combined.d.ts +0 -8
- package/dist/hono/routes/combined.d.ts.map +0 -1
- package/dist/hono/routes/combined.js +0 -392
- package/dist/hono/routes/combined.js.map +0 -1
- package/dist/hono/routes/context.d.ts +0 -314
- package/dist/hono/routes/context.d.ts.map +0 -1
- package/dist/hono/routes/context.js +0 -1147
- package/dist/hono/routes/context.js.map +0 -1
- package/dist/hono/routes/health.d.ts +0 -8
- package/dist/hono/routes/health.d.ts.map +0 -1
- package/dist/hono/routes/health.js +0 -16
- package/dist/hono/routes/health.js.map +0 -1
- package/dist/hono/routes/realtime.d.ts +0 -9
- package/dist/hono/routes/realtime.d.ts.map +0 -1
- package/dist/hono/routes/realtime.js +0 -626
- package/dist/hono/routes/realtime.js.map +0 -1
- package/dist/hono/routes/shared.d.ts +0 -689
- package/dist/hono/routes/shared.d.ts.map +0 -1
- package/dist/hono/routes/shared.js +0 -972
- package/dist/hono/routes/shared.js.map +0 -1
- package/dist/hono/routes/snapshots.d.ts +0 -10
- package/dist/hono/routes/snapshots.d.ts.map +0 -1
- package/dist/hono/routes/snapshots.js +0 -281
- package/dist/hono/routes/snapshots.js.map +0 -1
- package/dist/hono/routes.d.ts +0 -19
- package/dist/hono/routes.d.ts.map +0 -1
- package/dist/hono/routes.js +0 -37
- package/dist/hono/routes.js.map +0 -1
- package/dist/hono/validation.d.ts +0 -5
- package/dist/hono/validation.d.ts.map +0 -1
- package/dist/hono/validation.js +0 -47
- package/dist/hono/validation.js.map +0 -1
- package/dist/hono/websocket-origin.d.ts +0 -9
- package/dist/hono/websocket-origin.d.ts.map +0 -1
- package/dist/hono/websocket-origin.js +0 -96
- package/dist/hono/websocket-origin.js.map +0 -1
- package/dist/hono/ws.d.ts +0 -341
- package/dist/hono/ws.d.ts.map +0 -1
- package/dist/hono/ws.js +0 -711
- package/dist/hono/ws.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/libsql.d.ts +0 -29
- package/dist/libsql.d.ts.map +0 -1
- package/dist/libsql.js +0 -25
- package/dist/libsql.js.map +0 -1
- package/dist/migrate.d.ts +0 -14
- package/dist/migrate.d.ts.map +0 -1
- package/dist/migrate.js +0 -13
- package/dist/migrate.js.map +0 -1
- package/dist/neon.d.ts +0 -21
- package/dist/neon.d.ts.map +0 -1
- package/dist/neon.js +0 -22
- package/dist/neon.js.map +0 -1
- package/dist/notify.d.ts +0 -77
- package/dist/notify.d.ts.map +0 -1
- package/dist/notify.js +0 -233
- package/dist/notify.js.map +0 -1
- package/dist/pglite.d.ts +0 -37
- package/dist/pglite.d.ts.map +0 -1
- package/dist/pglite.js +0 -37
- package/dist/pglite.js.map +0 -1
- package/dist/plugins/index.d.ts +0 -2
- package/dist/plugins/index.d.ts.map +0 -1
- package/dist/plugins/index.js +0 -2
- package/dist/plugins/index.js.map +0 -1
- package/dist/plugins/types.d.ts +0 -73
- package/dist/plugins/types.d.ts.map +0 -1
- package/dist/plugins/types.js +0 -30
- package/dist/plugins/types.js.map +0 -1
- package/dist/postgres/index.d.ts +0 -68
- package/dist/postgres/index.d.ts.map +0 -1
- package/dist/postgres/index.js +0 -924
- package/dist/postgres/index.js.map +0 -1
- package/dist/proxy/collection.d.ts +0 -7
- package/dist/proxy/collection.d.ts.map +0 -1
- package/dist/proxy/collection.js +0 -6
- package/dist/proxy/collection.js.map +0 -1
- package/dist/proxy/handler.d.ts +0 -42
- package/dist/proxy/handler.d.ts.map +0 -1
- package/dist/proxy/handler.js +0 -102
- package/dist/proxy/handler.js.map +0 -1
- package/dist/proxy/index.d.ts +0 -9
- package/dist/proxy/index.d.ts.map +0 -1
- package/dist/proxy/index.js +0 -14
- package/dist/proxy/index.js.map +0 -1
- package/dist/proxy/mutation-detector.d.ts +0 -35
- package/dist/proxy/mutation-detector.d.ts.map +0 -1
- package/dist/proxy/mutation-detector.js +0 -246
- package/dist/proxy/mutation-detector.js.map +0 -1
- package/dist/proxy/oplog.d.ts +0 -30
- package/dist/proxy/oplog.d.ts.map +0 -1
- package/dist/proxy/oplog.js +0 -137
- package/dist/proxy/oplog.js.map +0 -1
- package/dist/proxy/types.d.ts +0 -44
- package/dist/proxy/types.d.ts.map +0 -1
- package/dist/proxy/types.js +0 -7
- package/dist/proxy/types.js.map +0 -1
- package/dist/prune.d.ts.map +0 -1
- package/dist/prune.js.map +0 -1
- package/dist/pull.d.ts.map +0 -1
- package/dist/pull.js.map +0 -1
- package/dist/push.d.ts.map +0 -1
- package/dist/push.js.map +0 -1
- package/dist/realtime/in-memory.d.ts +0 -13
- package/dist/realtime/in-memory.d.ts.map +0 -1
- package/dist/realtime/in-memory.js +0 -28
- package/dist/realtime/in-memory.js.map +0 -1
- package/dist/realtime/index.d.ts +0 -4
- package/dist/realtime/index.d.ts.map +0 -1
- package/dist/realtime/index.js +0 -3
- package/dist/realtime/index.js.map +0 -1
- package/dist/realtime/types.d.ts +0 -62
- package/dist/realtime/types.d.ts.map +0 -1
- package/dist/realtime/types.js +0 -19
- package/dist/realtime/types.js.map +0 -1
- package/dist/relay/client-role/forward-engine.d.ts +0 -63
- package/dist/relay/client-role/forward-engine.d.ts.map +0 -1
- package/dist/relay/client-role/forward-engine.js +0 -267
- package/dist/relay/client-role/forward-engine.js.map +0 -1
- package/dist/relay/client-role/index.d.ts +0 -9
- package/dist/relay/client-role/index.d.ts.map +0 -1
- package/dist/relay/client-role/index.js +0 -9
- package/dist/relay/client-role/index.js.map +0 -1
- package/dist/relay/client-role/pull-engine.d.ts +0 -72
- package/dist/relay/client-role/pull-engine.d.ts.map +0 -1
- package/dist/relay/client-role/pull-engine.js +0 -249
- package/dist/relay/client-role/pull-engine.js.map +0 -1
- package/dist/relay/client-role/sequence-mapper.d.ts +0 -65
- package/dist/relay/client-role/sequence-mapper.d.ts.map +0 -1
- package/dist/relay/client-role/sequence-mapper.js +0 -161
- package/dist/relay/client-role/sequence-mapper.js.map +0 -1
- package/dist/relay/evaluation/relay-paths.d.ts +0 -41
- package/dist/relay/evaluation/relay-paths.d.ts.map +0 -1
- package/dist/relay/evaluation/relay-paths.js +0 -504
- package/dist/relay/evaluation/relay-paths.js.map +0 -1
- package/dist/relay/evaluation/rust-boundary.d.ts +0 -47
- package/dist/relay/evaluation/rust-boundary.d.ts.map +0 -1
- package/dist/relay/evaluation/rust-boundary.js +0 -220
- package/dist/relay/evaluation/rust-boundary.js.map +0 -1
- package/dist/relay/index.d.ts +0 -37
- package/dist/relay/index.d.ts.map +0 -1
- package/dist/relay/index.js +0 -44
- package/dist/relay/index.js.map +0 -1
- package/dist/relay/migrate.d.ts +0 -18
- package/dist/relay/migrate.d.ts.map +0 -1
- package/dist/relay/migrate.js +0 -99
- package/dist/relay/migrate.js.map +0 -1
- package/dist/relay/mode-manager.d.ts +0 -60
- package/dist/relay/mode-manager.d.ts.map +0 -1
- package/dist/relay/mode-manager.js +0 -114
- package/dist/relay/mode-manager.js.map +0 -1
- package/dist/relay/realtime.d.ts +0 -90
- package/dist/relay/realtime.d.ts.map +0 -1
- package/dist/relay/realtime.js +0 -147
- package/dist/relay/realtime.js.map +0 -1
- package/dist/relay/relay.d.ts +0 -190
- package/dist/relay/relay.d.ts.map +0 -1
- package/dist/relay/relay.js +0 -320
- package/dist/relay/relay.js.map +0 -1
- package/dist/relay/schema.d.ts +0 -158
- package/dist/relay/schema.d.ts.map +0 -1
- package/dist/relay/schema.js +0 -7
- package/dist/relay/schema.js.map +0 -1
- package/dist/relay/server-role/index.d.ts +0 -56
- package/dist/relay/server-role/index.d.ts.map +0 -1
- package/dist/relay/server-role/index.js +0 -193
- package/dist/relay/server-role/index.js.map +0 -1
- package/dist/relay/server-role/pull.d.ts +0 -27
- package/dist/relay/server-role/pull.d.ts.map +0 -1
- package/dist/relay/server-role/pull.js +0 -24
- package/dist/relay/server-role/pull.js.map +0 -1
- package/dist/relay/server-role/push.d.ts +0 -29
- package/dist/relay/server-role/push.d.ts.map +0 -1
- package/dist/relay/server-role/push.js +0 -122
- package/dist/relay/server-role/push.js.map +0 -1
- package/dist/s3/index.d.ts +0 -83
- package/dist/s3/index.d.ts.map +0 -1
- package/dist/s3/index.js +0 -223
- package/dist/s3/index.js.map +0 -1
- package/dist/schema.d.ts.map +0 -1
- package/dist/schema.js.map +0 -1
- package/dist/service-worker/index.d.ts +0 -114
- package/dist/service-worker/index.d.ts.map +0 -1
- package/dist/service-worker/index.js +0 -487
- package/dist/service-worker/index.js.map +0 -1
- package/dist/snapshot-artifacts/sqlite-bun.d.ts +0 -15
- package/dist/snapshot-artifacts/sqlite-bun.d.ts.map +0 -1
- package/dist/snapshot-artifacts/sqlite-bun.js +0 -128
- package/dist/snapshot-artifacts/sqlite-bun.js.map +0 -1
- package/dist/snapshot-artifacts.d.ts +0 -206
- package/dist/snapshot-artifacts.d.ts.map +0 -1
- package/dist/snapshot-artifacts.js +0 -545
- package/dist/snapshot-artifacts.js.map +0 -1
- package/dist/snapshot-chunks/db-metadata.d.ts +0 -56
- package/dist/snapshot-chunks/db-metadata.d.ts.map +0 -1
- package/dist/snapshot-chunks/db-metadata.js +0 -360
- package/dist/snapshot-chunks/db-metadata.js.map +0 -1
- package/dist/snapshot-chunks/index.d.ts +0 -8
- package/dist/snapshot-chunks/index.d.ts.map +0 -1
- package/dist/snapshot-chunks/index.js +0 -8
- package/dist/snapshot-chunks/index.js.map +0 -1
- package/dist/snapshot-chunks/types.d.ts +0 -80
- package/dist/snapshot-chunks/types.d.ts.map +0 -1
- package/dist/snapshot-chunks/types.js +0 -8
- package/dist/snapshot-chunks/types.js.map +0 -1
- package/dist/snapshot-chunks.d.ts +0 -90
- package/dist/snapshot-chunks.d.ts.map +0 -1
- package/dist/snapshot-chunks.js +0 -304
- package/dist/snapshot-chunks.js.map +0 -1
- package/dist/sqlite/index.d.ts +0 -53
- package/dist/sqlite/index.d.ts.map +0 -1
- package/dist/sqlite/index.js +0 -795
- package/dist/sqlite/index.js.map +0 -1
- package/dist/sqlite3.d.ts +0 -22
- package/dist/sqlite3.d.ts.map +0 -1
- package/dist/sqlite3.js +0 -99
- package/dist/sqlite3.js.map +0 -1
- package/dist/stats.d.ts +0 -28
- package/dist/stats.d.ts.map +0 -1
- package/dist/stats.js +0 -93
- package/dist/stats.js.map +0 -1
- package/dist/subscriptions/cache.d.ts +0 -58
- package/dist/subscriptions/cache.d.ts.map +0 -1
- package/dist/subscriptions/cache.js +0 -250
- package/dist/subscriptions/cache.js.map +0 -1
- package/dist/subscriptions/index.d.ts +0 -3
- package/dist/subscriptions/index.d.ts.map +0 -1
- package/dist/subscriptions/index.js +0 -3
- package/dist/subscriptions/index.js.map +0 -1
- package/dist/subscriptions/resolve.d.ts +0 -40
- package/dist/subscriptions/resolve.d.ts.map +0 -1
- package/dist/subscriptions/resolve.js +0 -275
- package/dist/subscriptions/resolve.js.map +0 -1
- package/dist/sync.d.ts +0 -24
- package/dist/sync.d.ts.map +0 -1
- package/dist/sync.js +0 -27
- package/dist/sync.js.map +0 -1
- package/src/auth-leases.ts +0 -649
- package/src/better-sqlite3.ts +0 -35
- package/src/blobs/access.ts +0 -244
- package/src/blobs/adapters/database.ts +0 -397
- package/src/blobs/index.ts +0 -9
- package/src/blobs/manager.ts +0 -901
- package/src/blobs/migrate.ts +0 -158
- package/src/blobs/types.ts +0 -74
- package/src/bun-sqlite-ambient.d.ts +0 -19
- package/src/bun-sqlite.ts +0 -27
- package/src/clients.ts +0 -22
- package/src/cloudflare/durable-object.ts +0 -289
- package/src/cloudflare/index.ts +0 -22
- package/src/cloudflare/r2.ts +0 -526
- package/src/cloudflare/scope-cache.ts +0 -341
- package/src/cloudflare/sentry.ts +0 -230
- package/src/cloudflare/worker.ts +0 -77
- package/src/commit-integrity.ts +0 -371
- package/src/compaction.ts +0 -77
- package/src/crdt-yjs/index.ts +0 -931
- package/src/d1.ts +0 -16
- package/src/dialect/base.ts +0 -360
- package/src/dialect/helpers.ts +0 -92
- package/src/dialect/index.ts +0 -7
- package/src/dialect/types.ts +0 -247
- package/src/encrypted-crdt.ts +0 -786
- package/src/filesystem/index.ts +0 -262
- package/src/handlers/collection.ts +0 -121
- package/src/handlers/create-handler.ts +0 -1134
- package/src/handlers/index.ts +0 -3
- package/src/handlers/types.ts +0 -403
- package/src/helpers/conflict.ts +0 -64
- package/src/helpers/emitted-change.ts +0 -69
- package/src/helpers/index.ts +0 -12
- package/src/helpers/paginate.ts +0 -82
- package/src/helpers/scope-authorization.ts +0 -27
- package/src/helpers/scope-commit-index.ts +0 -52
- package/src/helpers/scope-strings.ts +0 -101
- package/src/hono/api-key-auth.ts +0 -177
- package/src/hono/audit-redaction.ts +0 -135
- package/src/hono/blobs.ts +0 -851
- package/src/hono/console/gateway.ts +0 -3046
- package/src/hono/console/live-auth.ts +0 -46
- package/src/hono/console/route-descriptor.ts +0 -22
- package/src/hono/console/routes/api-keys.ts +0 -721
- package/src/hono/console/routes/clients.ts +0 -447
- package/src/hono/console/routes/commits.ts +0 -1137
- package/src/hono/console/routes/context.ts +0 -956
- package/src/hono/console/routes/events.ts +0 -669
- package/src/hono/console/routes/maintenance.ts +0 -461
- package/src/hono/console/routes/shared.ts +0 -816
- package/src/hono/console/routes/stats.ts +0 -392
- package/src/hono/console/routes/storage.ts +0 -159
- package/src/hono/console/routes.ts +0 -146
- package/src/hono/console/schema-errors.ts +0 -23
- package/src/hono/console/schemas.ts +0 -914
- package/src/hono/console/types.ts +0 -223
- package/src/hono/console/ui.ts +0 -100
- package/src/hono/create-server.ts +0 -230
- package/src/hono/errors.ts +0 -50
- package/src/hono/index.ts +0 -54
- package/src/hono/openapi.ts +0 -139
- package/src/hono/proxy/connection-manager.ts +0 -340
- package/src/hono/proxy/index.ts +0 -8
- package/src/hono/proxy/routes.ts +0 -272
- package/src/hono/rate-limit.ts +0 -319
- package/src/hono/realtime-sync-packs.ts +0 -354
- package/src/hono/routes/audit.ts +0 -499
- package/src/hono/routes/auth-leases.ts +0 -119
- package/src/hono/routes/combined.ts +0 -583
- package/src/hono/routes/context.ts +0 -1629
- package/src/hono/routes/health.ts +0 -26
- package/src/hono/routes/realtime.ts +0 -808
- package/src/hono/routes/shared.ts +0 -1626
- package/src/hono/routes/snapshots.ts +0 -345
- package/src/hono/routes.ts +0 -68
- package/src/hono/validation.ts +0 -81
- package/src/hono/websocket-origin.ts +0 -131
- package/src/hono/ws.ts +0 -1134
- package/src/libsql.ts +0 -51
- package/src/migrate.ts +0 -20
- package/src/neon.ts +0 -28
- package/src/notify.ts +0 -341
- package/src/pglite.ts +0 -68
- package/src/plugins/index.ts +0 -1
- package/src/plugins/types.ts +0 -144
- package/src/postgres/index.ts +0 -1291
- package/src/proxy/collection.ts +0 -17
- package/src/proxy/handler.ts +0 -159
- package/src/proxy/index.ts +0 -21
- package/src/proxy/mutation-detector.ts +0 -281
- package/src/proxy/oplog.ts +0 -181
- package/src/proxy/types.ts +0 -46
- package/src/realtime/in-memory.ts +0 -33
- package/src/realtime/index.ts +0 -7
- package/src/realtime/types.ts +0 -90
- package/src/relay/bun-types.d.ts +0 -50
- package/src/relay/client-role/forward-engine.ts +0 -355
- package/src/relay/client-role/index.ts +0 -9
- package/src/relay/client-role/pull-engine.ts +0 -329
- package/src/relay/client-role/sequence-mapper.ts +0 -201
- package/src/relay/evaluation/relay-paths.ts +0 -699
- package/src/relay/evaluation/rust-boundary.ts +0 -464
- package/src/relay/index.ts +0 -50
- package/src/relay/migrate.ts +0 -113
- package/src/relay/mode-manager.ts +0 -142
- package/src/relay/realtime.ts +0 -207
- package/src/relay/relay.ts +0 -431
- package/src/relay/schema.ts +0 -171
- package/src/relay/server-role/index.ts +0 -338
- package/src/relay/server-role/pull.ts +0 -43
- package/src/relay/server-role/push.ts +0 -164
- package/src/s3/index.ts +0 -346
- package/src/service-worker/index.ts +0 -773
- package/src/snapshot-artifacts/sqlite-bun.ts +0 -168
- package/src/snapshot-artifacts.ts +0 -896
- package/src/snapshot-chunks/db-metadata.ts +0 -537
- package/src/snapshot-chunks/index.ts +0 -8
- package/src/snapshot-chunks/types.ts +0 -105
- package/src/snapshot-chunks.ts +0 -453
- package/src/sqlite/index.ts +0 -1064
- package/src/sqlite3.ts +0 -137
- package/src/stats.ts +0 -180
- package/src/subscriptions/cache.ts +0 -376
- package/src/subscriptions/index.ts +0 -2
- package/src/subscriptions/resolve.ts +0 -357
- package/src/sync.ts +0 -111
package/src/crdt-yjs/index.ts
DELETED
|
@@ -1,931 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ApplyOperationResult,
|
|
3
|
-
ServerPushPluginPriority,
|
|
4
|
-
type SyncChange,
|
|
5
|
-
type SyncCrdtStateVectorHint,
|
|
6
|
-
type SyncServerPlugin,
|
|
7
|
-
} from '@syncular/server';
|
|
8
|
-
import { sql } from 'kysely';
|
|
9
|
-
import * as Y from 'yjs';
|
|
10
|
-
|
|
11
|
-
export const YJS_PAYLOAD_KEY = '__yjs';
|
|
12
|
-
|
|
13
|
-
const BASE64_PATTERN =
|
|
14
|
-
/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
15
|
-
|
|
16
|
-
export type YjsFieldKind = 'text' | 'xml-fragment' | 'prosemirror';
|
|
17
|
-
|
|
18
|
-
export interface YjsServerFieldRule {
|
|
19
|
-
table: string;
|
|
20
|
-
field: string;
|
|
21
|
-
/**
|
|
22
|
-
* Column that stores canonical serialized Yjs state.
|
|
23
|
-
* Example: "content_yjs_state"
|
|
24
|
-
*/
|
|
25
|
-
stateColumn: string;
|
|
26
|
-
/**
|
|
27
|
-
* Container key inside the Yjs document. Defaults to `field`.
|
|
28
|
-
*/
|
|
29
|
-
containerKey?: string;
|
|
30
|
-
/**
|
|
31
|
-
* Snapshot row id column. Defaults to `id`.
|
|
32
|
-
*/
|
|
33
|
-
rowIdField?: string;
|
|
34
|
-
/**
|
|
35
|
-
* CRDT container type.
|
|
36
|
-
*/
|
|
37
|
-
kind?: YjsFieldKind;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
interface ResolvedYjsServerFieldRule extends YjsServerFieldRule {
|
|
41
|
-
containerKey: string;
|
|
42
|
-
rowIdField: string;
|
|
43
|
-
kind: YjsFieldKind;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface YjsServerUpdateEnvelope {
|
|
47
|
-
updateId: string;
|
|
48
|
-
updateBase64: string;
|
|
49
|
-
requiresStateVectorBase64?: string;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export type YjsServerUpdateInput =
|
|
53
|
-
| YjsServerUpdateEnvelope
|
|
54
|
-
| readonly YjsServerUpdateEnvelope[];
|
|
55
|
-
|
|
56
|
-
export interface YjsServerPayloadEnvelope {
|
|
57
|
-
[field: string]: YjsServerUpdateInput;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface BuildYjsTextUpdateArgs {
|
|
61
|
-
previousStateBase64?: string | Uint8Array | null;
|
|
62
|
-
nextText: string;
|
|
63
|
-
containerKey?: string;
|
|
64
|
-
updateId?: string;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface BuildYjsTextUpdateResult {
|
|
68
|
-
update: YjsServerUpdateEnvelope;
|
|
69
|
-
nextStateBase64: string;
|
|
70
|
-
nextText: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface ApplyYjsTextUpdatesArgs {
|
|
74
|
-
previousStateBase64?: string | Uint8Array | null;
|
|
75
|
-
updates: readonly YjsServerUpdateEnvelope[];
|
|
76
|
-
containerKey?: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export interface ApplyYjsTextUpdatesResult {
|
|
80
|
-
nextStateBase64: string;
|
|
81
|
-
text: string;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface CreateYjsServerModuleOptions {
|
|
85
|
-
name?: string;
|
|
86
|
-
rules: readonly YjsServerFieldRule[];
|
|
87
|
-
envelopeKey?: string;
|
|
88
|
-
/**
|
|
89
|
-
* Throw when envelope payload references fields without matching rules.
|
|
90
|
-
* @default true
|
|
91
|
-
*/
|
|
92
|
-
strict?: boolean;
|
|
93
|
-
/**
|
|
94
|
-
* Remove the Yjs envelope key from processed payload/rows.
|
|
95
|
-
* @default true
|
|
96
|
-
*/
|
|
97
|
-
stripEnvelope?: boolean;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface CreateYjsServerPushPluginOptions
|
|
101
|
-
extends CreateYjsServerModuleOptions {
|
|
102
|
-
priority?: number;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
type RuleIndex = Map<string, Map<string, ResolvedYjsServerFieldRule>>;
|
|
106
|
-
|
|
107
|
-
export interface YjsServerApplyPayloadArgs {
|
|
108
|
-
table: string;
|
|
109
|
-
rowId: string;
|
|
110
|
-
payload: Record<string, unknown>;
|
|
111
|
-
existingRow?: Record<string, unknown> | null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export interface YjsServerMaterializeRowArgs {
|
|
115
|
-
table: string;
|
|
116
|
-
row: Record<string, unknown>;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export type YjsServerStateVectorHint = SyncCrdtStateVectorHint;
|
|
120
|
-
|
|
121
|
-
export interface YjsServerTransformPullChangesArgs {
|
|
122
|
-
table: string;
|
|
123
|
-
changes: readonly SyncChange[];
|
|
124
|
-
crdtStateVectors: readonly YjsServerStateVectorHint[];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export interface YjsServerModule {
|
|
128
|
-
name: string;
|
|
129
|
-
rules: readonly YjsServerFieldRule[];
|
|
130
|
-
envelopeKey: string;
|
|
131
|
-
applyPayload(
|
|
132
|
-
args: YjsServerApplyPayloadArgs
|
|
133
|
-
): Promise<Record<string, unknown>>;
|
|
134
|
-
materializeRow(
|
|
135
|
-
args: YjsServerMaterializeRowArgs
|
|
136
|
-
): Promise<Record<string, unknown>>;
|
|
137
|
-
transformPullChanges(
|
|
138
|
-
args: YjsServerTransformPullChangesArgs
|
|
139
|
-
): Promise<readonly SyncChange[]>;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
143
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function readString(value: unknown): string | null {
|
|
147
|
-
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function bytesToBase64(bytes: Uint8Array): string {
|
|
151
|
-
if (typeof Buffer !== 'undefined') {
|
|
152
|
-
return Buffer.from(bytes).toString('base64');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
let binary = '';
|
|
156
|
-
for (const byte of bytes) {
|
|
157
|
-
binary += String.fromCharCode(byte);
|
|
158
|
-
}
|
|
159
|
-
return btoa(binary);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function tryReadBase64TextFromBytes(bytes: Uint8Array): string | null {
|
|
163
|
-
if (bytes.length === 0) return null;
|
|
164
|
-
try {
|
|
165
|
-
const decoded = new TextDecoder().decode(bytes).trim();
|
|
166
|
-
if (!decoded || !BASE64_PATTERN.test(decoded)) return null;
|
|
167
|
-
return decoded;
|
|
168
|
-
} catch {
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function base64ToBytes(base64: string): Uint8Array {
|
|
174
|
-
if (!BASE64_PATTERN.test(base64)) {
|
|
175
|
-
throw new Error('Invalid base64 string');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (typeof Buffer !== 'undefined') {
|
|
179
|
-
return new Uint8Array(Buffer.from(base64, 'base64'));
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const binary = atob(base64);
|
|
183
|
-
const out = new Uint8Array(binary.length);
|
|
184
|
-
for (let i = 0; i < binary.length; i++) {
|
|
185
|
-
out[i] = binary.charCodeAt(i);
|
|
186
|
-
}
|
|
187
|
-
return out;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function stateValueToBytes(value: unknown): Uint8Array | null {
|
|
191
|
-
if (value instanceof Uint8Array) {
|
|
192
|
-
const encoded = tryReadBase64TextFromBytes(value);
|
|
193
|
-
if (encoded) return base64ToBytes(encoded);
|
|
194
|
-
return value;
|
|
195
|
-
}
|
|
196
|
-
const str = readString(value);
|
|
197
|
-
if (!str) return null;
|
|
198
|
-
return base64ToBytes(str);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function stateValueToBase64(value: unknown): string | null {
|
|
202
|
-
const str = readString(value);
|
|
203
|
-
if (str) return str;
|
|
204
|
-
if (value instanceof Uint8Array) {
|
|
205
|
-
const encoded = tryReadBase64TextFromBytes(value);
|
|
206
|
-
if (encoded) return encoded;
|
|
207
|
-
return bytesToBase64(value);
|
|
208
|
-
}
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function createDocFromState(stateValue: unknown): Y.Doc {
|
|
213
|
-
const doc = new Y.Doc();
|
|
214
|
-
const bytes = stateValueToBytes(stateValue);
|
|
215
|
-
if (bytes && bytes.length > 0) {
|
|
216
|
-
Y.applyUpdate(doc, bytes);
|
|
217
|
-
}
|
|
218
|
-
return doc;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function exportSnapshotBase64(doc: Y.Doc): string {
|
|
222
|
-
return bytesToBase64(Y.encodeStateAsUpdate(doc));
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function exportUpdateFromStateVectorBase64(
|
|
226
|
-
stateValue: unknown,
|
|
227
|
-
stateVectorBase64: string
|
|
228
|
-
): string | null {
|
|
229
|
-
const stateBytes = stateValueToBytes(stateValue);
|
|
230
|
-
if (!stateBytes || stateBytes.length === 0) return null;
|
|
231
|
-
const stateVector = base64ToBytes(stateVectorBase64);
|
|
232
|
-
const doc = new Y.Doc();
|
|
233
|
-
try {
|
|
234
|
-
Y.applyUpdate(doc, stateBytes);
|
|
235
|
-
return bytesToBase64(Y.encodeStateAsUpdate(doc, stateVector));
|
|
236
|
-
} finally {
|
|
237
|
-
doc.destroy();
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function ensureTextContainer(doc: Y.Doc, containerKey: string): string {
|
|
242
|
-
return doc.getText(containerKey).toString();
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function ensureXmlFragmentContainer(doc: Y.Doc, containerKey: string): string {
|
|
246
|
-
return doc.getXmlFragment(containerKey).toString();
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function replaceText(doc: Y.Doc, containerKey: string, nextText: string): void {
|
|
250
|
-
const text = doc.getText(containerKey);
|
|
251
|
-
const currentLength = text.length;
|
|
252
|
-
doc.transact(() => {
|
|
253
|
-
if (currentLength > 0) {
|
|
254
|
-
text.delete(0, currentLength);
|
|
255
|
-
}
|
|
256
|
-
if (nextText.length > 0) {
|
|
257
|
-
text.insert(0, nextText);
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function patchText(doc: Y.Doc, containerKey: string, nextText: string): void {
|
|
263
|
-
const text = doc.getText(containerKey);
|
|
264
|
-
const currentText = text.toString();
|
|
265
|
-
if (currentText === nextText) return;
|
|
266
|
-
|
|
267
|
-
const minLength = Math.min(currentText.length, nextText.length);
|
|
268
|
-
let prefixLength = 0;
|
|
269
|
-
while (
|
|
270
|
-
prefixLength < minLength &&
|
|
271
|
-
currentText.charCodeAt(prefixLength) === nextText.charCodeAt(prefixLength)
|
|
272
|
-
) {
|
|
273
|
-
prefixLength += 1;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
let currentSuffixStart = currentText.length;
|
|
277
|
-
let nextSuffixStart = nextText.length;
|
|
278
|
-
while (
|
|
279
|
-
currentSuffixStart > prefixLength &&
|
|
280
|
-
nextSuffixStart > prefixLength &&
|
|
281
|
-
currentText.charCodeAt(currentSuffixStart - 1) ===
|
|
282
|
-
nextText.charCodeAt(nextSuffixStart - 1)
|
|
283
|
-
) {
|
|
284
|
-
currentSuffixStart -= 1;
|
|
285
|
-
nextSuffixStart -= 1;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const deleteLength = currentSuffixStart - prefixLength;
|
|
289
|
-
const insertSegment = nextText.slice(prefixLength, nextSuffixStart);
|
|
290
|
-
|
|
291
|
-
doc.transact(() => {
|
|
292
|
-
if (deleteLength > 0) {
|
|
293
|
-
text.delete(prefixLength, deleteLength);
|
|
294
|
-
}
|
|
295
|
-
if (insertSegment.length > 0) {
|
|
296
|
-
text.insert(prefixLength, insertSegment);
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function materializeRuleValue(
|
|
302
|
-
doc: Y.Doc,
|
|
303
|
-
rule: ResolvedYjsServerFieldRule
|
|
304
|
-
): unknown {
|
|
305
|
-
if (rule.kind === 'text') {
|
|
306
|
-
return ensureTextContainer(doc, rule.containerKey);
|
|
307
|
-
}
|
|
308
|
-
return ensureXmlFragmentContainer(doc, rule.containerKey);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function seedRuleValueFromPayload(
|
|
312
|
-
doc: Y.Doc,
|
|
313
|
-
rule: ResolvedYjsServerFieldRule,
|
|
314
|
-
source: Record<string, unknown>
|
|
315
|
-
): void {
|
|
316
|
-
if (rule.kind !== 'text') return;
|
|
317
|
-
const initialText = readString(source[rule.field]);
|
|
318
|
-
if (initialText) {
|
|
319
|
-
replaceText(doc, rule.containerKey, initialText);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function createUpdateId(): string {
|
|
324
|
-
const randomUUID = globalThis.crypto?.randomUUID;
|
|
325
|
-
if (typeof randomUUID === 'function') {
|
|
326
|
-
return randomUUID.call(globalThis.crypto);
|
|
327
|
-
}
|
|
328
|
-
const ts = Date.now().toString(36);
|
|
329
|
-
const rnd = Math.random().toString(36).slice(2, 12);
|
|
330
|
-
return `yjs-${ts}-${rnd}`;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function buildRuleIndex(rules: readonly YjsServerFieldRule[]): {
|
|
334
|
-
index: RuleIndex;
|
|
335
|
-
normalizedRules: readonly ResolvedYjsServerFieldRule[];
|
|
336
|
-
} {
|
|
337
|
-
const index: RuleIndex = new Map();
|
|
338
|
-
const normalizedRules: ResolvedYjsServerFieldRule[] = [];
|
|
339
|
-
const seen = new Set<string>();
|
|
340
|
-
|
|
341
|
-
for (const rule of rules) {
|
|
342
|
-
if (!rule.table.trim()) {
|
|
343
|
-
throw new Error('YjsServerFieldRule.table cannot be empty');
|
|
344
|
-
}
|
|
345
|
-
if (!rule.field.trim()) {
|
|
346
|
-
throw new Error('YjsServerFieldRule.field cannot be empty');
|
|
347
|
-
}
|
|
348
|
-
if (!rule.stateColumn.trim()) {
|
|
349
|
-
throw new Error('YjsServerFieldRule.stateColumn cannot be empty');
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const key = `${rule.table}\u001f${rule.field}`;
|
|
353
|
-
if (seen.has(key)) {
|
|
354
|
-
throw new Error(
|
|
355
|
-
`Duplicate Yjs server rule for table "${rule.table}", field "${rule.field}"`
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
seen.add(key);
|
|
359
|
-
|
|
360
|
-
const resolved: ResolvedYjsServerFieldRule = {
|
|
361
|
-
...rule,
|
|
362
|
-
containerKey: rule.containerKey ?? rule.field,
|
|
363
|
-
rowIdField: rule.rowIdField ?? 'id',
|
|
364
|
-
kind: rule.kind ?? 'text',
|
|
365
|
-
};
|
|
366
|
-
normalizedRules.push(resolved);
|
|
367
|
-
|
|
368
|
-
const tableRules = index.get(resolved.table) ?? new Map();
|
|
369
|
-
tableRules.set(resolved.field, resolved);
|
|
370
|
-
index.set(resolved.table, tableRules);
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
return { index, normalizedRules };
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function normalizeUpdateEnvelope(
|
|
377
|
-
value: unknown,
|
|
378
|
-
context: string
|
|
379
|
-
): YjsServerUpdateEnvelope {
|
|
380
|
-
if (!isRecord(value)) {
|
|
381
|
-
throw new Error(`${context} must be an object`);
|
|
382
|
-
}
|
|
383
|
-
const updateId = readString(value.updateId);
|
|
384
|
-
const updateBase64 = readString(value.updateBase64);
|
|
385
|
-
if (!updateId) {
|
|
386
|
-
throw new Error(`${context}.updateId must be a non-empty string`);
|
|
387
|
-
}
|
|
388
|
-
if (!updateBase64) {
|
|
389
|
-
throw new Error(
|
|
390
|
-
`${context}.updateBase64 must be a non-empty base64 string`
|
|
391
|
-
);
|
|
392
|
-
}
|
|
393
|
-
const requiresStateVectorBase64 = readString(value.requiresStateVectorBase64);
|
|
394
|
-
return {
|
|
395
|
-
updateId,
|
|
396
|
-
updateBase64,
|
|
397
|
-
...(requiresStateVectorBase64 ? { requiresStateVectorBase64 } : {}),
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
function normalizeUpdateEnvelopes(
|
|
402
|
-
value: unknown,
|
|
403
|
-
context: string
|
|
404
|
-
): YjsServerUpdateEnvelope[] {
|
|
405
|
-
if (Array.isArray(value)) {
|
|
406
|
-
return value.map((entry, i) =>
|
|
407
|
-
normalizeUpdateEnvelope(entry, `${context}[${i}]`)
|
|
408
|
-
);
|
|
409
|
-
}
|
|
410
|
-
return [normalizeUpdateEnvelope(value, context)];
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/*async function applyYjsTextUpdates(
|
|
414
|
-
args: ApplyYjsTextUpdatesArgs
|
|
415
|
-
): Promise<ApplyYjsTextUpdatesResult> {
|
|
416
|
-
const containerKey = args.containerKey ?? 'text';
|
|
417
|
-
const doc = createDocFromState(args.previousStateBase64);
|
|
418
|
-
try {
|
|
419
|
-
for (const update of args.updates) {
|
|
420
|
-
Y.applyUpdate(doc, base64ToBytes(update.updateBase64));
|
|
421
|
-
}
|
|
422
|
-
const text = ensureTextContainer(doc, containerKey);
|
|
423
|
-
const nextStateBase64 = exportSnapshotBase64(doc);
|
|
424
|
-
return { nextStateBase64, text };
|
|
425
|
-
} finally {
|
|
426
|
-
doc.destroy();
|
|
427
|
-
}
|
|
428
|
-
}*/
|
|
429
|
-
|
|
430
|
-
export async function buildYjsTextUpdate(
|
|
431
|
-
args: BuildYjsTextUpdateArgs
|
|
432
|
-
): Promise<BuildYjsTextUpdateResult> {
|
|
433
|
-
const containerKey = args.containerKey ?? 'text';
|
|
434
|
-
const doc = createDocFromState(args.previousStateBase64);
|
|
435
|
-
try {
|
|
436
|
-
const from = Y.encodeStateVector(doc);
|
|
437
|
-
patchText(doc, containerKey, args.nextText);
|
|
438
|
-
const update = bytesToBase64(Y.encodeStateAsUpdate(doc, from));
|
|
439
|
-
const nextText = ensureTextContainer(doc, containerKey);
|
|
440
|
-
const nextStateBase64 = exportSnapshotBase64(doc);
|
|
441
|
-
|
|
442
|
-
return {
|
|
443
|
-
update: {
|
|
444
|
-
updateId: args.updateId ?? createUpdateId(),
|
|
445
|
-
updateBase64: update,
|
|
446
|
-
},
|
|
447
|
-
nextStateBase64,
|
|
448
|
-
nextText,
|
|
449
|
-
};
|
|
450
|
-
} finally {
|
|
451
|
-
doc.destroy();
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
async function materializeRowFromState(args: {
|
|
456
|
-
table: string;
|
|
457
|
-
row: Record<string, unknown>;
|
|
458
|
-
index: RuleIndex;
|
|
459
|
-
envelopeKey: string;
|
|
460
|
-
stripEnvelope: boolean;
|
|
461
|
-
}): Promise<Record<string, unknown>> {
|
|
462
|
-
const tableRules = args.index.get(args.table);
|
|
463
|
-
if (!tableRules) {
|
|
464
|
-
if (args.stripEnvelope && args.envelopeKey in args.row) {
|
|
465
|
-
const next = { ...args.row };
|
|
466
|
-
delete next[args.envelopeKey];
|
|
467
|
-
return next;
|
|
468
|
-
}
|
|
469
|
-
return args.row;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
let nextRow: Record<string, unknown> | null = null;
|
|
473
|
-
const ensureRow = (): Record<string, unknown> => {
|
|
474
|
-
if (nextRow) return nextRow;
|
|
475
|
-
nextRow = { ...args.row };
|
|
476
|
-
return nextRow;
|
|
477
|
-
};
|
|
478
|
-
|
|
479
|
-
for (const rule of tableRules.values()) {
|
|
480
|
-
const source = nextRow ?? args.row;
|
|
481
|
-
const stateBase64 = stateValueToBase64(source[rule.stateColumn]);
|
|
482
|
-
if (!stateBase64) continue;
|
|
483
|
-
|
|
484
|
-
const doc = createDocFromState(stateBase64);
|
|
485
|
-
try {
|
|
486
|
-
const nextValue = materializeRuleValue(doc, rule);
|
|
487
|
-
if (source[rule.field] !== nextValue) {
|
|
488
|
-
ensureRow()[rule.field] = nextValue;
|
|
489
|
-
}
|
|
490
|
-
} finally {
|
|
491
|
-
doc.destroy();
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
if (args.stripEnvelope) {
|
|
496
|
-
const source = nextRow ?? args.row;
|
|
497
|
-
if (args.envelopeKey in source) {
|
|
498
|
-
const target = ensureRow();
|
|
499
|
-
delete target[args.envelopeKey];
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
return nextRow ?? args.row;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
async function applyYjsEnvelopeToPayload(args: {
|
|
507
|
-
table: string;
|
|
508
|
-
payload: Record<string, unknown>;
|
|
509
|
-
existingRow?: Record<string, unknown> | null;
|
|
510
|
-
index: RuleIndex;
|
|
511
|
-
envelopeKey: string;
|
|
512
|
-
stripEnvelope: boolean;
|
|
513
|
-
strict: boolean;
|
|
514
|
-
}): Promise<Record<string, unknown>> {
|
|
515
|
-
const tableRules = args.index.get(args.table);
|
|
516
|
-
const rawEnvelope = args.payload[args.envelopeKey];
|
|
517
|
-
|
|
518
|
-
if (!tableRules) {
|
|
519
|
-
if (rawEnvelope !== undefined && args.strict) {
|
|
520
|
-
throw new Error(
|
|
521
|
-
`Yjs envelope provided for table "${args.table}" without matching rules`
|
|
522
|
-
);
|
|
523
|
-
}
|
|
524
|
-
if (args.stripEnvelope && rawEnvelope !== undefined) {
|
|
525
|
-
const next = { ...args.payload };
|
|
526
|
-
delete next[args.envelopeKey];
|
|
527
|
-
return next;
|
|
528
|
-
}
|
|
529
|
-
return args.payload;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
const sourceEnvelope = rawEnvelope;
|
|
533
|
-
if (sourceEnvelope !== undefined && !isRecord(sourceEnvelope)) {
|
|
534
|
-
throw new Error(
|
|
535
|
-
`Yjs payload key "${args.envelopeKey}" must be an object for table "${args.table}"`
|
|
536
|
-
);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
const basePayload =
|
|
540
|
-
sourceEnvelope && args.existingRow
|
|
541
|
-
? { ...args.existingRow, ...args.payload }
|
|
542
|
-
: args.payload;
|
|
543
|
-
let nextPayload: Record<string, unknown> | null =
|
|
544
|
-
basePayload === args.payload ? null : basePayload;
|
|
545
|
-
const ensurePayload = (): Record<string, unknown> => {
|
|
546
|
-
if (nextPayload) return nextPayload;
|
|
547
|
-
nextPayload = { ...basePayload };
|
|
548
|
-
return nextPayload;
|
|
549
|
-
};
|
|
550
|
-
|
|
551
|
-
if (sourceEnvelope) {
|
|
552
|
-
for (const [field, rawUpdateInput] of Object.entries(sourceEnvelope)) {
|
|
553
|
-
const rule = tableRules.get(field);
|
|
554
|
-
if (!rule) {
|
|
555
|
-
if (args.strict) {
|
|
556
|
-
throw new Error(
|
|
557
|
-
`No Yjs rule found for envelope field "${field}" on table "${args.table}"`
|
|
558
|
-
);
|
|
559
|
-
}
|
|
560
|
-
continue;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
const updates = normalizeUpdateEnvelopes(
|
|
564
|
-
rawUpdateInput,
|
|
565
|
-
`yjs.${args.table}.${field}`
|
|
566
|
-
);
|
|
567
|
-
|
|
568
|
-
const source = nextPayload ?? basePayload;
|
|
569
|
-
const existingSource = args.existingRow ?? null;
|
|
570
|
-
const baseState =
|
|
571
|
-
(existingSource
|
|
572
|
-
? stateValueToBase64(existingSource[rule.stateColumn])
|
|
573
|
-
: null) ??
|
|
574
|
-
stateValueToBase64(source[rule.stateColumn]) ??
|
|
575
|
-
null;
|
|
576
|
-
|
|
577
|
-
const requiredBase = updates.find(
|
|
578
|
-
(update) => update.requiresStateVectorBase64
|
|
579
|
-
)?.requiresStateVectorBase64;
|
|
580
|
-
if (!baseState && requiredBase) {
|
|
581
|
-
throw new Error(
|
|
582
|
-
`Yjs diff envelope for table "${args.table}" field "${field}" requires local base state vector ${requiredBase}, but no local state is available; full snapshot resync required`
|
|
583
|
-
);
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
const doc = createDocFromState(baseState);
|
|
587
|
-
try {
|
|
588
|
-
if (!baseState) {
|
|
589
|
-
seedRuleValueFromPayload(doc, rule, source);
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
for (const update of updates) {
|
|
593
|
-
if (update.requiresStateVectorBase64) {
|
|
594
|
-
const actualStateVectorBase64 = bytesToBase64(
|
|
595
|
-
Y.encodeStateVector(doc)
|
|
596
|
-
);
|
|
597
|
-
if (actualStateVectorBase64 !== update.requiresStateVectorBase64) {
|
|
598
|
-
throw new Error(
|
|
599
|
-
`Yjs update ${update.updateId} requires base state vector ${update.requiresStateVectorBase64}, but current state vector is ${actualStateVectorBase64}; full snapshot resync required`
|
|
600
|
-
);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
Y.applyUpdate(doc, base64ToBytes(update.updateBase64));
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
const nextValue = materializeRuleValue(doc, rule);
|
|
607
|
-
const nextStateBase64 = exportSnapshotBase64(doc);
|
|
608
|
-
const target = ensurePayload();
|
|
609
|
-
target[rule.field] = nextValue;
|
|
610
|
-
target[rule.stateColumn] = nextStateBase64;
|
|
611
|
-
} finally {
|
|
612
|
-
doc.destroy();
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
if (args.stripEnvelope) {
|
|
618
|
-
const source = nextPayload ?? basePayload;
|
|
619
|
-
if (args.envelopeKey in source) {
|
|
620
|
-
const target = ensurePayload();
|
|
621
|
-
delete target[args.envelopeKey];
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
return nextPayload ?? args.payload;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
function createHintKey(rowId: string, field: string, stateColumn: string) {
|
|
629
|
-
return `${rowId}\u001f${field}\u001f${stateColumn}`;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
function indexStateVectorHints(
|
|
633
|
-
hints: readonly YjsServerStateVectorHint[]
|
|
634
|
-
): Map<string, YjsServerStateVectorHint> {
|
|
635
|
-
const indexed = new Map<string, YjsServerStateVectorHint>();
|
|
636
|
-
for (const hint of hints) {
|
|
637
|
-
if (hint.syncMode !== 'server-merge') continue;
|
|
638
|
-
indexed.set(createHintKey(hint.rowId, hint.field, hint.stateColumn), hint);
|
|
639
|
-
}
|
|
640
|
-
return indexed;
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
function transformPullChangeWithStateVectorHints(args: {
|
|
644
|
-
table: string;
|
|
645
|
-
change: SyncChange;
|
|
646
|
-
index: RuleIndex;
|
|
647
|
-
hintsByKey: ReadonlyMap<string, YjsServerStateVectorHint>;
|
|
648
|
-
envelopeKey: string;
|
|
649
|
-
}): SyncChange {
|
|
650
|
-
if (args.change.op !== 'upsert' || !isRecord(args.change.row_json)) {
|
|
651
|
-
return args.change;
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
const tableRules = args.index.get(args.table);
|
|
655
|
-
if (!tableRules) return args.change;
|
|
656
|
-
|
|
657
|
-
const row = args.change.row_json;
|
|
658
|
-
let nextRow: Record<string, unknown> | null = null;
|
|
659
|
-
let envelope: YjsServerPayloadEnvelope | undefined;
|
|
660
|
-
|
|
661
|
-
const ensureRow = (): Record<string, unknown> => {
|
|
662
|
-
if (nextRow) return nextRow;
|
|
663
|
-
nextRow = { ...row };
|
|
664
|
-
return nextRow;
|
|
665
|
-
};
|
|
666
|
-
|
|
667
|
-
const ensureEnvelope = (): YjsServerPayloadEnvelope => {
|
|
668
|
-
if (envelope) return envelope;
|
|
669
|
-
const target = ensureRow();
|
|
670
|
-
const existingEnvelope = target[args.envelopeKey];
|
|
671
|
-
envelope = {};
|
|
672
|
-
if (isRecord(existingEnvelope)) {
|
|
673
|
-
for (const [field, updateInput] of Object.entries(existingEnvelope)) {
|
|
674
|
-
envelope[field] = updateInput as YjsServerUpdateInput;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
target[args.envelopeKey] = envelope;
|
|
678
|
-
return envelope;
|
|
679
|
-
};
|
|
680
|
-
|
|
681
|
-
for (const rule of tableRules.values()) {
|
|
682
|
-
const hint = args.hintsByKey.get(
|
|
683
|
-
createHintKey(args.change.row_id, rule.field, rule.stateColumn)
|
|
684
|
-
);
|
|
685
|
-
if (!hint) continue;
|
|
686
|
-
|
|
687
|
-
const serverState = row[rule.stateColumn];
|
|
688
|
-
const updateBase64 = exportUpdateFromStateVectorBase64(
|
|
689
|
-
serverState,
|
|
690
|
-
hint.stateVectorBase64
|
|
691
|
-
);
|
|
692
|
-
if (!updateBase64) continue;
|
|
693
|
-
|
|
694
|
-
const target = ensureRow();
|
|
695
|
-
delete target[rule.field];
|
|
696
|
-
delete target[rule.stateColumn];
|
|
697
|
-
ensureEnvelope()[rule.field] = {
|
|
698
|
-
updateId: `server:${args.table}:${args.change.row_id}:${rule.field}:${hint.updatedAt}`,
|
|
699
|
-
updateBase64,
|
|
700
|
-
requiresStateVectorBase64: hint.stateVectorBase64,
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
if (!nextRow) return args.change;
|
|
705
|
-
return {
|
|
706
|
-
...args.change,
|
|
707
|
-
row_json: nextRow,
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
async function transformPullChangesWithStateVectorHints(args: {
|
|
712
|
-
table: string;
|
|
713
|
-
changes: readonly SyncChange[];
|
|
714
|
-
index: RuleIndex;
|
|
715
|
-
envelopeKey: string;
|
|
716
|
-
crdtStateVectors: readonly YjsServerStateVectorHint[];
|
|
717
|
-
}): Promise<readonly SyncChange[]> {
|
|
718
|
-
const tableRules = args.index.get(args.table);
|
|
719
|
-
if (!tableRules || args.crdtStateVectors.length === 0) {
|
|
720
|
-
return args.changes;
|
|
721
|
-
}
|
|
722
|
-
const hintsByKey = indexStateVectorHints(args.crdtStateVectors);
|
|
723
|
-
if (hintsByKey.size === 0) return args.changes;
|
|
724
|
-
|
|
725
|
-
let changed = false;
|
|
726
|
-
const nextChanges = args.changes.map((change) => {
|
|
727
|
-
const nextChange = transformPullChangeWithStateVectorHints({
|
|
728
|
-
table: args.table,
|
|
729
|
-
change,
|
|
730
|
-
index: args.index,
|
|
731
|
-
hintsByKey,
|
|
732
|
-
envelopeKey: args.envelopeKey,
|
|
733
|
-
});
|
|
734
|
-
if (nextChange !== change) changed = true;
|
|
735
|
-
return nextChange;
|
|
736
|
-
});
|
|
737
|
-
|
|
738
|
-
return changed ? nextChanges : args.changes;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
export function createYjsServerModule(
|
|
742
|
-
options: CreateYjsServerModuleOptions
|
|
743
|
-
): YjsServerModule {
|
|
744
|
-
if (options.rules.length === 0) {
|
|
745
|
-
throw new Error(
|
|
746
|
-
'createYjsServerModule requires at least one table/field rule'
|
|
747
|
-
);
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
const envelopeKey = options.envelopeKey ?? YJS_PAYLOAD_KEY;
|
|
751
|
-
const strict = options.strict ?? true;
|
|
752
|
-
const stripEnvelope = options.stripEnvelope ?? true;
|
|
753
|
-
const { index } = buildRuleIndex(options.rules);
|
|
754
|
-
|
|
755
|
-
return {
|
|
756
|
-
name: options.name ?? 'crdt-yjs-server',
|
|
757
|
-
rules: options.rules,
|
|
758
|
-
envelopeKey,
|
|
759
|
-
|
|
760
|
-
async applyPayload(args): Promise<Record<string, unknown>> {
|
|
761
|
-
return await applyYjsEnvelopeToPayload({
|
|
762
|
-
table: args.table,
|
|
763
|
-
payload: args.payload,
|
|
764
|
-
existingRow: args.existingRow,
|
|
765
|
-
index,
|
|
766
|
-
envelopeKey,
|
|
767
|
-
stripEnvelope,
|
|
768
|
-
strict,
|
|
769
|
-
});
|
|
770
|
-
},
|
|
771
|
-
|
|
772
|
-
async materializeRow(args): Promise<Record<string, unknown>> {
|
|
773
|
-
return await materializeRowFromState({
|
|
774
|
-
table: args.table,
|
|
775
|
-
row: args.row,
|
|
776
|
-
index,
|
|
777
|
-
envelopeKey,
|
|
778
|
-
stripEnvelope,
|
|
779
|
-
});
|
|
780
|
-
},
|
|
781
|
-
|
|
782
|
-
async transformPullChanges(args): Promise<readonly SyncChange[]> {
|
|
783
|
-
return await transformPullChangesWithStateVectorHints({
|
|
784
|
-
table: args.table,
|
|
785
|
-
changes: args.changes,
|
|
786
|
-
crdtStateVectors: args.crdtStateVectors,
|
|
787
|
-
index,
|
|
788
|
-
envelopeKey,
|
|
789
|
-
});
|
|
790
|
-
},
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
function buildTableRowIdFieldIndex(
|
|
795
|
-
rules: readonly YjsServerFieldRule[]
|
|
796
|
-
): Map<string, string> {
|
|
797
|
-
const tableRowIdFields = new Map<string, string>();
|
|
798
|
-
|
|
799
|
-
for (const rule of rules) {
|
|
800
|
-
const rowIdField = rule.rowIdField ?? 'id';
|
|
801
|
-
const existing = tableRowIdFields.get(rule.table);
|
|
802
|
-
if (existing && existing !== rowIdField) {
|
|
803
|
-
throw new Error(
|
|
804
|
-
`Yjs rules for table "${rule.table}" must use a single rowIdField`
|
|
805
|
-
);
|
|
806
|
-
}
|
|
807
|
-
tableRowIdFields.set(rule.table, rowIdField);
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
return tableRowIdFields;
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
async function materializeAppliedResult(
|
|
814
|
-
yjsModule: YjsServerModule,
|
|
815
|
-
opTable: string,
|
|
816
|
-
applied: ApplyOperationResult
|
|
817
|
-
): Promise<ApplyOperationResult> {
|
|
818
|
-
let nextResult: ApplyOperationResult['result'] = applied.result;
|
|
819
|
-
let resultChanged = false;
|
|
820
|
-
|
|
821
|
-
if (nextResult.status === 'conflict' && isRecord(nextResult.server_row)) {
|
|
822
|
-
const materializedServerRow = await yjsModule.materializeRow({
|
|
823
|
-
table: opTable,
|
|
824
|
-
row: nextResult.server_row,
|
|
825
|
-
});
|
|
826
|
-
if (materializedServerRow !== nextResult.server_row) {
|
|
827
|
-
nextResult = {
|
|
828
|
-
...nextResult,
|
|
829
|
-
server_row: materializedServerRow,
|
|
830
|
-
};
|
|
831
|
-
resultChanged = true;
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
let emittedChanged = false;
|
|
836
|
-
const nextEmitted: ApplyOperationResult['emittedChanges'] = [];
|
|
837
|
-
for (const emitted of applied.emittedChanges) {
|
|
838
|
-
if (emitted.op !== 'upsert' || !isRecord(emitted.row_json)) {
|
|
839
|
-
nextEmitted.push(emitted);
|
|
840
|
-
continue;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
const materializedRow = await yjsModule.materializeRow({
|
|
844
|
-
table: emitted.table,
|
|
845
|
-
row: emitted.row_json,
|
|
846
|
-
});
|
|
847
|
-
if (materializedRow !== emitted.row_json) {
|
|
848
|
-
emittedChanged = true;
|
|
849
|
-
nextEmitted.push({
|
|
850
|
-
...emitted,
|
|
851
|
-
row_json: materializedRow,
|
|
852
|
-
});
|
|
853
|
-
continue;
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
nextEmitted.push(emitted);
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
if (!resultChanged && !emittedChanged) {
|
|
860
|
-
return applied;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
return {
|
|
864
|
-
result: nextResult,
|
|
865
|
-
emittedChanges: emittedChanged ? nextEmitted : applied.emittedChanges,
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
export function createYjsServerPushPlugin(
|
|
870
|
-
options: CreateYjsServerPushPluginOptions
|
|
871
|
-
): SyncServerPlugin {
|
|
872
|
-
const yjsModule = createYjsServerModule(options);
|
|
873
|
-
const tableRowIdFields = buildTableRowIdFieldIndex(options.rules);
|
|
874
|
-
|
|
875
|
-
return {
|
|
876
|
-
name: options.name ?? yjsModule.name,
|
|
877
|
-
priority: options.priority ?? ServerPushPluginPriority.CRDT,
|
|
878
|
-
|
|
879
|
-
async beforeApplyOperation(args) {
|
|
880
|
-
const op = args.op;
|
|
881
|
-
if (op.op !== 'upsert' || !isRecord(op.payload)) {
|
|
882
|
-
return op;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
const rowIdField = tableRowIdFields.get(op.table);
|
|
886
|
-
let existingRow: Record<string, unknown> | null = null;
|
|
887
|
-
|
|
888
|
-
if (rowIdField) {
|
|
889
|
-
const loadedRows = await sql<Record<string, unknown>>`
|
|
890
|
-
select *
|
|
891
|
-
from ${sql.table(op.table)}
|
|
892
|
-
where ${sql.ref(rowIdField)} = ${sql.val(op.row_id)}
|
|
893
|
-
limit ${sql.val(1)}
|
|
894
|
-
`.execute(args.ctx.trx);
|
|
895
|
-
const loadedRow = loadedRows.rows[0];
|
|
896
|
-
if (loadedRow && isRecord(loadedRow)) {
|
|
897
|
-
existingRow = loadedRow;
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
const nextPayload = await yjsModule.applyPayload({
|
|
902
|
-
table: op.table,
|
|
903
|
-
rowId: op.row_id,
|
|
904
|
-
payload: op.payload,
|
|
905
|
-
existingRow,
|
|
906
|
-
});
|
|
907
|
-
|
|
908
|
-
if (nextPayload === op.payload) return op;
|
|
909
|
-
return {
|
|
910
|
-
...op,
|
|
911
|
-
payload: nextPayload,
|
|
912
|
-
};
|
|
913
|
-
},
|
|
914
|
-
|
|
915
|
-
async afterApplyOperation(args) {
|
|
916
|
-
return await materializeAppliedResult(
|
|
917
|
-
yjsModule,
|
|
918
|
-
args.op.table,
|
|
919
|
-
args.applied
|
|
920
|
-
);
|
|
921
|
-
},
|
|
922
|
-
|
|
923
|
-
async transformPullChanges(args) {
|
|
924
|
-
return await yjsModule.transformPullChanges({
|
|
925
|
-
table: args.subscription.table,
|
|
926
|
-
changes: args.changes,
|
|
927
|
-
crdtStateVectors: args.subscription.crdtStateVectors,
|
|
928
|
-
});
|
|
929
|
-
},
|
|
930
|
-
};
|
|
931
|
-
}
|