@syncular/server 0.0.6-95 → 0.1.0
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 +1 -2
- package/dist/auth-leases.d.ts +85 -0
- package/dist/auth-leases.d.ts.map +1 -0
- package/dist/auth-leases.js +368 -0
- package/dist/auth-leases.js.map +1 -0
- package/dist/better-sqlite3.d.ts +22 -0
- package/dist/better-sqlite3.d.ts.map +1 -0
- package/dist/better-sqlite3.js +16 -0
- package/dist/better-sqlite3.js.map +1 -0
- package/dist/blobs/access.d.ts +35 -0
- package/dist/blobs/access.d.ts.map +1 -0
- package/dist/blobs/access.js +149 -0
- package/dist/blobs/access.js.map +1 -0
- package/dist/blobs/adapters/database.d.ts +26 -9
- package/dist/blobs/adapters/database.d.ts.map +1 -1
- package/dist/blobs/adapters/database.js +68 -23
- package/dist/blobs/adapters/database.js.map +1 -1
- package/dist/blobs/index.d.ts +1 -0
- package/dist/blobs/index.d.ts.map +1 -1
- package/dist/blobs/index.js +5 -4
- package/dist/blobs/index.js.map +1 -1
- package/dist/blobs/manager.d.ts +69 -44
- package/dist/blobs/manager.d.ts.map +1 -1
- package/dist/blobs/manager.js +250 -65
- package/dist/blobs/manager.js.map +1 -1
- package/dist/blobs/migrate.d.ts.map +1 -1
- package/dist/blobs/migrate.js +16 -8
- package/dist/blobs/migrate.js.map +1 -1
- package/dist/blobs/types.d.ts +4 -0
- package/dist/blobs/types.d.ts.map +1 -1
- package/dist/bun-sqlite.d.ts +19 -0
- package/dist/bun-sqlite.d.ts.map +1 -0
- package/dist/bun-sqlite.js +19 -0
- package/dist/bun-sqlite.js.map +1 -0
- package/dist/clients.d.ts +1 -0
- package/dist/clients.d.ts.map +1 -1
- package/dist/clients.js.map +1 -1
- package/dist/cloudflare/durable-object.d.ts +93 -0
- package/dist/cloudflare/durable-object.d.ts.map +1 -0
- package/dist/cloudflare/durable-object.js +210 -0
- package/dist/cloudflare/durable-object.js.map +1 -0
- package/dist/cloudflare/index.d.ts +22 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +22 -0
- package/dist/cloudflare/index.js.map +1 -0
- package/dist/cloudflare/r2.d.ts +180 -0
- package/dist/cloudflare/r2.d.ts.map +1 -0
- package/dist/cloudflare/r2.js +258 -0
- package/dist/cloudflare/r2.js.map +1 -0
- package/dist/cloudflare/scope-cache.d.ts +54 -0
- package/dist/cloudflare/scope-cache.d.ts.map +1 -0
- package/dist/cloudflare/scope-cache.js +223 -0
- package/dist/cloudflare/scope-cache.js.map +1 -0
- package/dist/cloudflare/sentry.d.ts +47 -0
- package/dist/cloudflare/sentry.d.ts.map +1 -0
- package/dist/cloudflare/sentry.js +163 -0
- package/dist/cloudflare/sentry.js.map +1 -0
- package/dist/cloudflare/worker.d.ts +46 -0
- package/dist/cloudflare/worker.d.ts.map +1 -0
- package/dist/cloudflare/worker.js +63 -0
- package/dist/cloudflare/worker.js.map +1 -0
- package/dist/commit-integrity.d.ts +38 -0
- package/dist/commit-integrity.d.ts.map +1 -0
- package/dist/commit-integrity.js +260 -0
- package/dist/commit-integrity.js.map +1 -0
- package/dist/compaction.js.map +1 -1
- package/dist/crdt-yjs/index.d.ts +99 -0
- package/dist/crdt-yjs/index.d.ts.map +1 -0
- package/dist/crdt-yjs/index.js +629 -0
- package/dist/crdt-yjs/index.js.map +1 -0
- package/dist/d1.d.ts +13 -0
- package/dist/d1.d.ts.map +1 -0
- package/dist/d1.js +14 -0
- package/dist/d1.js.map +1 -0
- package/dist/dialect/base.d.ts +11 -1
- package/dist/dialect/base.d.ts.map +1 -1
- package/dist/dialect/base.js +43 -6
- package/dist/dialect/base.js.map +1 -1
- package/dist/dialect/helpers.d.ts +6 -0
- package/dist/dialect/helpers.d.ts.map +1 -1
- package/dist/dialect/helpers.js +24 -0
- package/dist/dialect/helpers.js.map +1 -1
- package/dist/dialect/index.js +3 -3
- package/dist/dialect/types.d.ts +40 -0
- package/dist/dialect/types.d.ts.map +1 -1
- package/dist/encrypted-crdt.d.ts +67 -0
- package/dist/encrypted-crdt.d.ts.map +1 -0
- package/dist/encrypted-crdt.js +426 -0
- package/dist/encrypted-crdt.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -0
- package/dist/filesystem/index.d.ts +44 -0
- package/dist/filesystem/index.d.ts.map +1 -0
- package/dist/filesystem/index.js +164 -0
- package/dist/filesystem/index.js.map +1 -0
- package/dist/handlers/collection.d.ts +11 -3
- package/dist/handlers/collection.d.ts.map +1 -1
- package/dist/handlers/collection.js +34 -56
- package/dist/handlers/collection.js.map +1 -1
- package/dist/handlers/create-handler.d.ts +31 -7
- package/dist/handlers/create-handler.d.ts.map +1 -1
- package/dist/handlers/create-handler.js +332 -115
- package/dist/handlers/create-handler.js.map +1 -1
- package/dist/handlers/index.js +3 -3
- package/dist/handlers/types.d.ts +86 -1
- package/dist/handlers/types.d.ts.map +1 -1
- package/dist/helpers/conflict.js.map +1 -1
- package/dist/helpers/emitted-change.js.map +1 -1
- package/dist/helpers/index.d.ts +2 -0
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +6 -4
- package/dist/helpers/index.js.map +1 -1
- package/dist/helpers/paginate.js.map +1 -1
- package/dist/helpers/scope-authorization.d.ts +7 -0
- package/dist/helpers/scope-authorization.d.ts.map +1 -0
- package/dist/helpers/scope-authorization.js +19 -0
- package/dist/helpers/scope-authorization.js.map +1 -0
- package/dist/helpers/scope-commit-index.d.ts +12 -0
- package/dist/helpers/scope-commit-index.d.ts.map +1 -0
- package/dist/helpers/scope-commit-index.js +35 -0
- package/dist/helpers/scope-commit-index.js.map +1 -0
- package/dist/helpers/scope-strings.js.map +1 -1
- package/dist/hono/api-key-auth.d.ts +49 -0
- package/dist/hono/api-key-auth.d.ts.map +1 -0
- package/dist/hono/api-key-auth.js +108 -0
- package/dist/hono/api-key-auth.js.map +1 -0
- package/dist/hono/audit-redaction.d.ts +20 -0
- package/dist/hono/audit-redaction.d.ts.map +1 -0
- package/dist/hono/audit-redaction.js +85 -0
- package/dist/hono/audit-redaction.js.map +1 -0
- package/dist/hono/blobs.d.ts +75 -0
- package/dist/hono/blobs.d.ts.map +1 -0
- package/dist/hono/blobs.js +586 -0
- package/dist/hono/blobs.js.map +1 -0
- package/dist/hono/console/gateway.d.ts +42 -0
- package/dist/hono/console/gateway.d.ts.map +1 -0
- package/dist/hono/console/gateway.js +2158 -0
- package/dist/hono/console/gateway.js.map +1 -0
- package/dist/hono/console/live-auth.d.ts +7 -0
- package/dist/hono/console/live-auth.d.ts.map +1 -0
- package/dist/hono/console/live-auth.js +39 -0
- package/dist/hono/console/live-auth.js.map +1 -0
- package/dist/hono/console/route-descriptor.d.ts +6 -0
- package/dist/hono/console/route-descriptor.d.ts.map +1 -0
- package/dist/hono/console/route-descriptor.js +16 -0
- package/dist/hono/console/route-descriptor.js.map +1 -0
- package/dist/hono/console/routes/api-keys.d.ts +8 -0
- package/dist/hono/console/routes/api-keys.d.ts.map +1 -0
- package/dist/hono/console/routes/api-keys.js +575 -0
- package/dist/hono/console/routes/api-keys.js.map +1 -0
- package/dist/hono/console/routes/clients.d.ts +8 -0
- package/dist/hono/console/routes/clients.d.ts.map +1 -0
- package/dist/hono/console/routes/clients.js +322 -0
- package/dist/hono/console/routes/clients.js.map +1 -0
- package/dist/hono/console/routes/commits.d.ts +8 -0
- package/dist/hono/console/routes/commits.d.ts.map +1 -0
- package/dist/hono/console/routes/commits.js +882 -0
- package/dist/hono/console/routes/commits.js.map +1 -0
- package/dist/hono/console/routes/context.d.ts +188 -0
- package/dist/hono/console/routes/context.d.ts.map +1 -0
- package/dist/hono/console/routes/context.js +633 -0
- package/dist/hono/console/routes/context.js.map +1 -0
- package/dist/hono/console/routes/events.d.ts +8 -0
- package/dist/hono/console/routes/events.d.ts.map +1 -0
- package/dist/hono/console/routes/events.js +501 -0
- package/dist/hono/console/routes/events.js.map +1 -0
- package/dist/hono/console/routes/maintenance.d.ts +8 -0
- package/dist/hono/console/routes/maintenance.d.ts.map +1 -0
- package/dist/hono/console/routes/maintenance.js +341 -0
- package/dist/hono/console/routes/maintenance.js.map +1 -0
- package/dist/hono/console/routes/shared.d.ts +174 -0
- package/dist/hono/console/routes/shared.d.ts.map +1 -0
- package/dist/hono/console/routes/shared.js +583 -0
- package/dist/hono/console/routes/shared.js.map +1 -0
- package/dist/hono/console/routes/stats.d.ts +8 -0
- package/dist/hono/console/routes/stats.d.ts.map +1 -0
- package/dist/hono/console/routes/stats.js +295 -0
- package/dist/hono/console/routes/stats.js.map +1 -0
- package/dist/hono/console/routes/storage.d.ts +8 -0
- package/dist/hono/console/routes/storage.d.ts.map +1 -0
- package/dist/hono/console/routes/storage.js +121 -0
- package/dist/hono/console/routes/storage.js.map +1 -0
- package/dist/hono/console/routes.d.ts +36 -0
- package/dist/hono/console/routes.d.ts.map +1 -0
- package/dist/hono/console/routes.js +112 -0
- package/dist/hono/console/routes.js.map +1 -0
- package/dist/hono/console/schema-errors.d.ts +2 -0
- package/dist/hono/console/schema-errors.d.ts.map +1 -0
- package/dist/hono/console/schema-errors.js +17 -0
- package/dist/hono/console/schema-errors.js.map +1 -0
- package/dist/hono/console/schemas.d.ts +1515 -0
- package/dist/hono/console/schemas.d.ts.map +1 -0
- package/dist/hono/console/schemas.js +661 -0
- package/dist/hono/console/schemas.js.map +1 -0
- package/dist/hono/console/types.d.ts +213 -0
- package/dist/hono/console/types.d.ts.map +1 -0
- package/dist/hono/console/types.js +2 -0
- package/dist/hono/console/types.js.map +1 -0
- package/dist/hono/console/ui.d.ts +38 -0
- package/dist/hono/console/ui.d.ts.map +1 -0
- package/dist/hono/console/ui.js +43 -0
- package/dist/hono/console/ui.js.map +1 -0
- package/dist/hono/create-server.d.ts +71 -0
- package/dist/hono/create-server.d.ts.map +1 -0
- package/dist/hono/create-server.js +121 -0
- package/dist/hono/create-server.js.map +1 -0
- package/dist/hono/errors.d.ts +13 -0
- package/dist/hono/errors.d.ts.map +1 -0
- package/dist/hono/errors.js +21 -0
- package/dist/hono/errors.js.map +1 -0
- package/dist/hono/index.d.ts +20 -0
- package/dist/hono/index.d.ts.map +1 -0
- package/dist/hono/index.js +31 -0
- package/dist/hono/index.js.map +1 -0
- package/dist/hono/openapi.d.ts +72 -0
- package/dist/hono/openapi.d.ts.map +1 -0
- package/dist/hono/openapi.js +99 -0
- package/dist/hono/openapi.js.map +1 -0
- package/dist/hono/proxy/connection-manager.d.ts +78 -0
- package/dist/hono/proxy/connection-manager.d.ts.map +1 -0
- package/dist/hono/proxy/connection-manager.js +251 -0
- package/dist/hono/proxy/connection-manager.js.map +1 -0
- package/dist/hono/proxy/index.d.ts +8 -0
- package/dist/hono/proxy/index.d.ts.map +1 -0
- package/dist/hono/proxy/index.js +8 -0
- package/dist/hono/proxy/index.js.map +1 -0
- package/dist/hono/proxy/routes.d.ts +86 -0
- package/dist/hono/proxy/routes.d.ts.map +1 -0
- package/dist/hono/proxy/routes.js +183 -0
- package/dist/hono/proxy/routes.js.map +1 -0
- package/dist/hono/rate-limit.d.ts +101 -0
- package/dist/hono/rate-limit.d.ts.map +1 -0
- package/dist/hono/rate-limit.js +184 -0
- package/dist/hono/rate-limit.js.map +1 -0
- package/dist/hono/realtime-sync-packs.d.ts +43 -0
- package/dist/hono/realtime-sync-packs.d.ts.map +1 -0
- package/dist/hono/realtime-sync-packs.js +219 -0
- package/dist/hono/realtime-sync-packs.js.map +1 -0
- package/dist/hono/routes/audit.d.ts +12 -0
- package/dist/hono/routes/audit.d.ts.map +1 -0
- package/dist/hono/routes/audit.js +385 -0
- package/dist/hono/routes/audit.js.map +1 -0
- package/dist/hono/routes/auth-leases.d.ts +8 -0
- package/dist/hono/routes/auth-leases.d.ts.map +1 -0
- package/dist/hono/routes/auth-leases.js +88 -0
- package/dist/hono/routes/auth-leases.js.map +1 -0
- package/dist/hono/routes/combined.d.ts +8 -0
- package/dist/hono/routes/combined.d.ts.map +1 -0
- package/dist/hono/routes/combined.js +392 -0
- package/dist/hono/routes/combined.js.map +1 -0
- package/dist/hono/routes/context.d.ts +314 -0
- package/dist/hono/routes/context.d.ts.map +1 -0
- package/dist/hono/routes/context.js +1147 -0
- package/dist/hono/routes/context.js.map +1 -0
- package/dist/hono/routes/health.d.ts +8 -0
- package/dist/hono/routes/health.d.ts.map +1 -0
- package/dist/hono/routes/health.js +16 -0
- package/dist/hono/routes/health.js.map +1 -0
- package/dist/hono/routes/realtime.d.ts +9 -0
- package/dist/hono/routes/realtime.d.ts.map +1 -0
- package/dist/hono/routes/realtime.js +626 -0
- package/dist/hono/routes/realtime.js.map +1 -0
- package/dist/hono/routes/shared.d.ts +689 -0
- package/dist/hono/routes/shared.d.ts.map +1 -0
- package/dist/hono/routes/shared.js +972 -0
- package/dist/hono/routes/shared.js.map +1 -0
- package/dist/hono/routes/snapshots.d.ts +10 -0
- package/dist/hono/routes/snapshots.d.ts.map +1 -0
- package/dist/hono/routes/snapshots.js +281 -0
- package/dist/hono/routes/snapshots.js.map +1 -0
- package/dist/hono/routes.d.ts +19 -0
- package/dist/hono/routes.d.ts.map +1 -0
- package/dist/hono/routes.js +37 -0
- package/dist/hono/routes.js.map +1 -0
- package/dist/hono/validation.d.ts +5 -0
- package/dist/hono/validation.d.ts.map +1 -0
- package/dist/hono/validation.js +47 -0
- package/dist/hono/validation.js.map +1 -0
- package/dist/hono/websocket-origin.d.ts +9 -0
- package/dist/hono/websocket-origin.d.ts.map +1 -0
- package/dist/hono/websocket-origin.js +96 -0
- package/dist/hono/websocket-origin.js.map +1 -0
- package/dist/hono/ws.d.ts +341 -0
- package/dist/hono/ws.d.ts.map +1 -0
- package/dist/hono/ws.js +711 -0
- package/dist/hono/ws.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -18
- package/dist/index.js.map +1 -1
- package/dist/libsql.d.ts +29 -0
- package/dist/libsql.d.ts.map +1 -0
- package/dist/libsql.js +25 -0
- package/dist/libsql.js.map +1 -0
- package/dist/migrate.js.map +1 -1
- package/dist/neon.d.ts +21 -0
- package/dist/neon.d.ts.map +1 -0
- package/dist/neon.js +22 -0
- package/dist/neon.js.map +1 -0
- package/dist/notify.d.ts +30 -0
- package/dist/notify.d.ts.map +1 -1
- package/dist/notify.js +160 -41
- package/dist/notify.js.map +1 -1
- package/dist/pglite.d.ts +37 -0
- package/dist/pglite.d.ts.map +1 -0
- package/dist/pglite.js +37 -0
- package/dist/pglite.js.map +1 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +2 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/types.d.ts +73 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +30 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/postgres/index.d.ts +68 -0
- package/dist/postgres/index.d.ts.map +1 -0
- package/dist/postgres/index.js +924 -0
- package/dist/postgres/index.js.map +1 -0
- package/dist/proxy/collection.d.ts +0 -2
- package/dist/proxy/collection.d.ts.map +1 -1
- package/dist/proxy/collection.js +2 -17
- package/dist/proxy/collection.js.map +1 -1
- package/dist/proxy/handler.d.ts +1 -1
- package/dist/proxy/handler.d.ts.map +1 -1
- package/dist/proxy/handler.js +3 -4
- package/dist/proxy/handler.js.map +1 -1
- package/dist/proxy/index.d.ts +1 -1
- package/dist/proxy/index.d.ts.map +1 -1
- package/dist/proxy/index.js +3 -3
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/mutation-detector.js.map +1 -1
- package/dist/proxy/oplog.d.ts.map +1 -1
- package/dist/proxy/oplog.js +32 -8
- package/dist/proxy/oplog.js.map +1 -1
- package/dist/prune.d.ts +8 -1
- package/dist/prune.d.ts.map +1 -1
- package/dist/prune.js +68 -28
- package/dist/prune.js.map +1 -1
- package/dist/pull.d.ts +31 -0
- package/dist/pull.d.ts.map +1 -1
- package/dist/pull.js +1014 -474
- package/dist/pull.js.map +1 -1
- package/dist/push.d.ts +36 -2
- package/dist/push.d.ts.map +1 -1
- package/dist/push.js +603 -358
- package/dist/push.js.map +1 -1
- package/dist/realtime/in-memory.js.map +1 -1
- package/dist/realtime/index.d.ts +2 -1
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +2 -1
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime/types.d.ts +12 -0
- package/dist/realtime/types.d.ts.map +1 -1
- package/dist/realtime/types.js +13 -1
- package/dist/realtime/types.js.map +1 -1
- package/dist/relay/client-role/forward-engine.d.ts +63 -0
- package/dist/relay/client-role/forward-engine.d.ts.map +1 -0
- package/dist/relay/client-role/forward-engine.js +267 -0
- package/dist/relay/client-role/forward-engine.js.map +1 -0
- package/dist/relay/client-role/index.d.ts +9 -0
- package/dist/relay/client-role/index.d.ts.map +1 -0
- package/dist/relay/client-role/index.js +9 -0
- package/dist/relay/client-role/index.js.map +1 -0
- package/dist/relay/client-role/pull-engine.d.ts +72 -0
- package/dist/relay/client-role/pull-engine.d.ts.map +1 -0
- package/dist/relay/client-role/pull-engine.js +249 -0
- package/dist/relay/client-role/pull-engine.js.map +1 -0
- package/dist/relay/client-role/sequence-mapper.d.ts +65 -0
- package/dist/relay/client-role/sequence-mapper.d.ts.map +1 -0
- package/dist/relay/client-role/sequence-mapper.js +161 -0
- package/dist/relay/client-role/sequence-mapper.js.map +1 -0
- package/dist/relay/evaluation/relay-paths.d.ts +41 -0
- package/dist/relay/evaluation/relay-paths.d.ts.map +1 -0
- package/dist/relay/evaluation/relay-paths.js +504 -0
- package/dist/relay/evaluation/relay-paths.js.map +1 -0
- package/dist/relay/evaluation/rust-boundary.d.ts +47 -0
- package/dist/relay/evaluation/rust-boundary.d.ts.map +1 -0
- package/dist/relay/evaluation/rust-boundary.js +220 -0
- package/dist/relay/evaluation/rust-boundary.js.map +1 -0
- package/dist/relay/index.d.ts +37 -0
- package/dist/relay/index.d.ts.map +1 -0
- package/dist/relay/index.js +44 -0
- package/dist/relay/index.js.map +1 -0
- package/dist/relay/migrate.d.ts +18 -0
- package/dist/relay/migrate.d.ts.map +1 -0
- package/dist/relay/migrate.js +99 -0
- package/dist/relay/migrate.js.map +1 -0
- package/dist/relay/mode-manager.d.ts +60 -0
- package/dist/relay/mode-manager.d.ts.map +1 -0
- package/dist/relay/mode-manager.js +114 -0
- package/dist/relay/mode-manager.js.map +1 -0
- package/dist/relay/realtime.d.ts +90 -0
- package/dist/relay/realtime.d.ts.map +1 -0
- package/dist/relay/realtime.js +147 -0
- package/dist/relay/realtime.js.map +1 -0
- package/dist/relay/relay.d.ts +190 -0
- package/dist/relay/relay.d.ts.map +1 -0
- package/dist/relay/relay.js +320 -0
- package/dist/relay/relay.js.map +1 -0
- package/dist/relay/schema.d.ts +158 -0
- package/dist/relay/schema.d.ts.map +1 -0
- package/dist/relay/schema.js +7 -0
- package/dist/relay/schema.js.map +1 -0
- package/dist/relay/server-role/index.d.ts +56 -0
- package/dist/relay/server-role/index.d.ts.map +1 -0
- package/dist/relay/server-role/index.js +193 -0
- package/dist/relay/server-role/index.js.map +1 -0
- package/dist/relay/server-role/pull.d.ts +27 -0
- package/dist/relay/server-role/pull.d.ts.map +1 -0
- package/dist/relay/server-role/pull.js +24 -0
- package/dist/relay/server-role/pull.js.map +1 -0
- package/dist/relay/server-role/push.d.ts +29 -0
- package/dist/relay/server-role/push.d.ts.map +1 -0
- package/dist/relay/server-role/push.js +122 -0
- package/dist/relay/server-role/push.js.map +1 -0
- package/dist/s3/index.d.ts +83 -0
- package/dist/s3/index.d.ts.map +1 -0
- package/dist/s3/index.js +223 -0
- package/dist/s3/index.js.map +1 -0
- package/dist/schema.d.ts +137 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +1 -0
- package/dist/schema.js.map +1 -1
- package/dist/service-worker/index.d.ts +114 -0
- package/dist/service-worker/index.d.ts.map +1 -0
- package/dist/service-worker/index.js +487 -0
- package/dist/service-worker/index.js.map +1 -0
- package/dist/snapshot-artifacts/sqlite-bun.d.ts +15 -0
- package/dist/snapshot-artifacts/sqlite-bun.d.ts.map +1 -0
- package/dist/snapshot-artifacts/sqlite-bun.js +128 -0
- package/dist/snapshot-artifacts/sqlite-bun.js.map +1 -0
- package/dist/snapshot-artifacts.d.ts +206 -0
- package/dist/snapshot-artifacts.d.ts.map +1 -0
- package/dist/snapshot-artifacts.js +545 -0
- package/dist/snapshot-artifacts.js.map +1 -0
- package/dist/snapshot-chunks/db-metadata.d.ts +18 -0
- package/dist/snapshot-chunks/db-metadata.d.ts.map +1 -1
- package/dist/snapshot-chunks/db-metadata.js +91 -63
- package/dist/snapshot-chunks/db-metadata.js.map +1 -1
- package/dist/snapshot-chunks/index.js +2 -2
- package/dist/snapshot-chunks/types.d.ts +2 -0
- package/dist/snapshot-chunks/types.d.ts.map +1 -1
- package/dist/snapshot-chunks.d.ts +33 -3
- package/dist/snapshot-chunks.d.ts.map +1 -1
- package/dist/snapshot-chunks.js +136 -55
- package/dist/snapshot-chunks.js.map +1 -1
- package/dist/sqlite/index.d.ts +53 -0
- package/dist/sqlite/index.d.ts.map +1 -0
- package/dist/sqlite/index.js +795 -0
- package/dist/sqlite/index.js.map +1 -0
- package/dist/sqlite3.d.ts +22 -0
- package/dist/sqlite3.d.ts.map +1 -0
- package/dist/sqlite3.js +99 -0
- package/dist/sqlite3.js.map +1 -0
- package/dist/stats.d.ts +8 -0
- package/dist/stats.d.ts.map +1 -1
- package/dist/stats.js +45 -13
- package/dist/stats.js.map +1 -1
- package/dist/subscriptions/cache.d.ts +3 -0
- package/dist/subscriptions/cache.d.ts.map +1 -1
- package/dist/subscriptions/cache.js +44 -0
- package/dist/subscriptions/cache.js.map +1 -1
- package/dist/subscriptions/index.js +2 -2
- package/dist/subscriptions/resolve.d.ts +3 -1
- package/dist/subscriptions/resolve.d.ts.map +1 -1
- package/dist/subscriptions/resolve.js +91 -52
- package/dist/subscriptions/resolve.js.map +1 -1
- package/dist/sync.d.ts +3 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +9 -5
- package/dist/sync.js.map +1 -1
- package/package.json +297 -8
- package/src/auth-leases.ts +649 -0
- package/src/better-sqlite3.ts +35 -0
- package/src/blobs/access.ts +244 -0
- package/src/blobs/adapters/database.ts +125 -43
- package/src/blobs/index.ts +1 -0
- package/src/blobs/manager.ts +366 -65
- package/src/blobs/migrate.ts +16 -8
- package/src/blobs/types.ts +4 -0
- package/src/bun-sqlite-ambient.d.ts +19 -0
- package/src/bun-sqlite.ts +27 -0
- package/src/clients.ts +1 -0
- package/src/cloudflare/durable-object.ts +289 -0
- package/src/cloudflare/index.ts +22 -0
- package/src/cloudflare/r2.ts +526 -0
- package/src/cloudflare/scope-cache.ts +341 -0
- package/src/cloudflare/sentry.ts +230 -0
- package/src/cloudflare/worker.ts +77 -0
- package/src/commit-integrity.ts +371 -0
- package/src/crdt-yjs/index.ts +931 -0
- package/src/d1.ts +16 -0
- package/src/dialect/base.ts +71 -5
- package/src/dialect/helpers.ts +31 -0
- package/src/dialect/types.ts +47 -0
- package/src/encrypted-crdt.ts +786 -0
- package/src/errors.ts +22 -0
- package/src/filesystem/index.ts +262 -0
- package/src/handlers/collection.ts +78 -78
- package/src/handlers/create-handler.ts +540 -147
- package/src/handlers/types.ts +116 -0
- package/src/helpers/index.ts +2 -0
- package/src/helpers/scope-authorization.ts +27 -0
- package/src/helpers/scope-commit-index.ts +52 -0
- package/src/hono/api-key-auth.ts +177 -0
- package/src/hono/audit-redaction.ts +135 -0
- package/src/hono/blobs.ts +851 -0
- package/src/hono/console/gateway.ts +3046 -0
- package/src/hono/console/live-auth.ts +46 -0
- package/src/hono/console/route-descriptor.ts +22 -0
- package/src/hono/console/routes/api-keys.ts +721 -0
- package/src/hono/console/routes/clients.ts +447 -0
- package/src/hono/console/routes/commits.ts +1137 -0
- package/src/hono/console/routes/context.ts +956 -0
- package/src/hono/console/routes/events.ts +669 -0
- package/src/hono/console/routes/maintenance.ts +461 -0
- package/src/hono/console/routes/shared.ts +816 -0
- package/src/hono/console/routes/stats.ts +392 -0
- package/src/hono/console/routes/storage.ts +159 -0
- package/src/hono/console/routes.ts +146 -0
- package/src/hono/console/schema-errors.ts +23 -0
- package/src/hono/console/schemas.ts +914 -0
- package/src/hono/console/types.ts +223 -0
- package/src/hono/console/ui.ts +100 -0
- package/src/hono/create-server.ts +230 -0
- package/src/hono/errors.ts +50 -0
- package/src/hono/index.ts +54 -0
- package/src/hono/openapi.ts +139 -0
- package/src/hono/proxy/connection-manager.ts +340 -0
- package/src/hono/proxy/index.ts +8 -0
- package/src/hono/proxy/routes.ts +272 -0
- package/src/hono/rate-limit.ts +319 -0
- package/src/hono/realtime-sync-packs.ts +354 -0
- package/src/hono/routes/audit.ts +499 -0
- package/src/hono/routes/auth-leases.ts +119 -0
- package/src/hono/routes/combined.ts +583 -0
- package/src/hono/routes/context.ts +1629 -0
- package/src/hono/routes/health.ts +26 -0
- package/src/hono/routes/realtime.ts +808 -0
- package/src/hono/routes/shared.ts +1626 -0
- package/src/hono/routes/snapshots.ts +345 -0
- package/src/hono/routes.ts +68 -0
- package/src/hono/validation.ts +81 -0
- package/src/hono/websocket-origin.ts +131 -0
- package/src/hono/ws.ts +1134 -0
- package/src/index.ts +6 -0
- package/src/libsql.ts +51 -0
- package/src/neon.ts +28 -0
- package/src/notify.ts +224 -44
- package/src/pglite.ts +68 -0
- package/src/plugins/index.ts +1 -0
- package/src/plugins/types.ts +144 -0
- package/src/postgres/index.ts +1291 -0
- package/src/proxy/collection.ts +5 -27
- package/src/proxy/handler.ts +2 -2
- package/src/proxy/index.ts +0 -2
- package/src/proxy/oplog.ts +41 -10
- package/src/prune.ts +137 -36
- package/src/pull.ts +1504 -591
- package/src/push.ts +881 -443
- package/src/realtime/index.ts +2 -0
- package/src/realtime/types.ts +35 -0
- package/src/relay/bun-types.d.ts +50 -0
- package/src/relay/client-role/forward-engine.ts +355 -0
- package/src/relay/client-role/index.ts +9 -0
- package/src/relay/client-role/pull-engine.ts +329 -0
- package/src/relay/client-role/sequence-mapper.ts +201 -0
- package/src/relay/evaluation/relay-paths.ts +699 -0
- package/src/relay/evaluation/rust-boundary.ts +464 -0
- package/src/relay/index.ts +50 -0
- package/src/relay/migrate.ts +113 -0
- package/src/relay/mode-manager.ts +142 -0
- package/src/relay/realtime.ts +207 -0
- package/src/relay/relay.ts +431 -0
- package/src/relay/schema.ts +171 -0
- package/src/relay/server-role/index.ts +338 -0
- package/src/relay/server-role/pull.ts +43 -0
- package/src/relay/server-role/push.ts +164 -0
- package/src/s3/index.ts +346 -0
- package/src/schema.ts +141 -1
- package/src/service-worker/index.ts +773 -0
- package/src/snapshot-artifacts/sqlite-bun.ts +168 -0
- package/src/snapshot-artifacts.ts +896 -0
- package/src/snapshot-chunks/db-metadata.ts +131 -72
- package/src/snapshot-chunks/types.ts +2 -0
- package/src/snapshot-chunks.ts +194 -70
- package/src/sqlite/index.ts +1064 -0
- package/src/sqlite3.ts +137 -0
- package/src/stats.ts +76 -13
- package/src/subscriptions/cache.ts +58 -0
- package/src/subscriptions/resolve.ts +99 -58
- package/src/sync.ts +16 -6
- package/src/blobs/adapters/database.test.ts +0 -67
- package/src/notify.test.ts +0 -520
- package/src/proxy/handler.test.ts +0 -126
- package/src/proxy/mutation-detector.test.ts +0 -71
- package/src/snapshot-chunks/db-metadata.test.ts +0 -172
- package/src/subscriptions/resolve.test.ts +0 -180
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type {
|
|
6
|
-
|
|
6
|
+
BinarySnapshotColumn,
|
|
7
|
+
BinarySnapshotRowsEncoder,
|
|
7
8
|
ScopeValues,
|
|
8
9
|
ScopeValuesFromPatterns,
|
|
9
10
|
ScopeDefinition as SimpleScopeDefinition,
|
|
@@ -15,8 +16,9 @@ import {
|
|
|
15
16
|
applyCodecsToDbRow,
|
|
16
17
|
type ColumnCodecDialect,
|
|
17
18
|
type ColumnCodecSource,
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
createSingleVariableScopeMetadata,
|
|
20
|
+
createTableColumnCodecsResolver,
|
|
21
|
+
type SyncularErrorCode,
|
|
20
22
|
toTableColumnCodecs,
|
|
21
23
|
} from '@syncular/core';
|
|
22
24
|
import type {
|
|
@@ -32,9 +34,12 @@ import type {
|
|
|
32
34
|
UpdateResult,
|
|
33
35
|
} from 'kysely';
|
|
34
36
|
import { sql } from 'kysely';
|
|
37
|
+
import { coerceNumber } from '../dialect/helpers';
|
|
38
|
+
import { rowScopesAllowed } from '../helpers/scope-authorization';
|
|
35
39
|
import type { SyncCoreDb } from '../schema';
|
|
36
40
|
import type {
|
|
37
41
|
ApplyOperationResult,
|
|
42
|
+
BatchApplyOperationInput,
|
|
38
43
|
EmittedChange,
|
|
39
44
|
ServerApplyOperationContext,
|
|
40
45
|
ServerContext,
|
|
@@ -48,14 +53,10 @@ import type {
|
|
|
48
53
|
*/
|
|
49
54
|
type AuthorizeResult =
|
|
50
55
|
| true
|
|
51
|
-
| { error: string; code:
|
|
56
|
+
| { error: string; code: SyncularErrorCode; retriable?: boolean };
|
|
52
57
|
|
|
53
|
-
function classifyConstraintViolationCode(
|
|
54
|
-
|
|
55
|
-
if (normalized.includes('not null')) return 'NOT_NULL_CONSTRAINT';
|
|
56
|
-
if (normalized.includes('unique')) return 'UNIQUE_CONSTRAINT';
|
|
57
|
-
if (normalized.includes('foreign key')) return 'FOREIGN_KEY_CONSTRAINT';
|
|
58
|
-
return 'CONSTRAINT_VIOLATION';
|
|
58
|
+
function classifyConstraintViolationCode(_message: string): SyncularErrorCode {
|
|
59
|
+
return 'sync.constraint_violation';
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
function isConstraintViolationError(message: string): boolean {
|
|
@@ -76,10 +77,36 @@ function isMissingColumnReferenceError(message: string): boolean {
|
|
|
76
77
|
);
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
function readSafeVersionColumn(
|
|
81
|
+
row: Record<string, unknown>,
|
|
82
|
+
versionColumn: string,
|
|
83
|
+
defaultValue: number
|
|
84
|
+
): number {
|
|
85
|
+
const value = row[versionColumn];
|
|
86
|
+
if (value === null || value === undefined) return defaultValue;
|
|
87
|
+
const version = coerceNumber(value);
|
|
88
|
+
if (version === null || !Number.isSafeInteger(version)) {
|
|
89
|
+
throw new Error(`Version column "${versionColumn}" must be a safe integer`);
|
|
90
|
+
}
|
|
91
|
+
return version;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function normalizeOutboundVersionColumn<Row>(
|
|
95
|
+
row: Row,
|
|
96
|
+
versionColumn: string,
|
|
97
|
+
version: number
|
|
98
|
+
): Row {
|
|
99
|
+
if (row === null || typeof row !== 'object' || Array.isArray(row)) {
|
|
100
|
+
return row;
|
|
101
|
+
}
|
|
102
|
+
if (!Object.hasOwn(row, versionColumn)) {
|
|
103
|
+
return row;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
...(row as Record<string, unknown>),
|
|
107
|
+
[versionColumn]: version,
|
|
108
|
+
} as Row;
|
|
109
|
+
}
|
|
83
110
|
|
|
84
111
|
/**
|
|
85
112
|
* Options for creating a declarative server handler.
|
|
@@ -124,6 +151,37 @@ export interface CreateServerHandlerOptions<
|
|
|
124
151
|
/** TTL for cached snapshot chunks in ms */
|
|
125
152
|
snapshotChunkTtlMs?: number;
|
|
126
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Stable binary snapshot column metadata used by binary bootstrap chunks.
|
|
156
|
+
*/
|
|
157
|
+
snapshotBinaryColumns?: readonly BinarySnapshotColumn[];
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Version-aware binary snapshot column metadata. Returning null intentionally
|
|
161
|
+
* disables fallback to current metadata.
|
|
162
|
+
*/
|
|
163
|
+
snapshotBinaryColumnsForVersion?: (
|
|
164
|
+
schemaVersion: number
|
|
165
|
+
) => readonly BinarySnapshotColumn[] | null | undefined;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Optional generated binary snapshot encoder used by binary bootstrap chunks.
|
|
169
|
+
*/
|
|
170
|
+
snapshotBinaryEncoder?: BinarySnapshotRowsEncoder<
|
|
171
|
+
Selectable<ClientDB[TableName]>
|
|
172
|
+
>;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Version-aware generated binary snapshot encoder. Returning null
|
|
176
|
+
* intentionally disables fallback to the current encoder.
|
|
177
|
+
*/
|
|
178
|
+
snapshotBinaryEncoderForVersion?: (
|
|
179
|
+
schemaVersion: number
|
|
180
|
+
) =>
|
|
181
|
+
| BinarySnapshotRowsEncoder<Selectable<ClientDB[TableName]>>
|
|
182
|
+
| null
|
|
183
|
+
| undefined;
|
|
184
|
+
|
|
127
185
|
/**
|
|
128
186
|
* Resolve allowed scope values for the current actor.
|
|
129
187
|
* Called per request to determine what the actor can access.
|
|
@@ -187,6 +245,17 @@ export interface CreateServerHandlerOptions<
|
|
|
187
245
|
*/
|
|
188
246
|
applyOperation?: ServerTableHandler<ServerDB, Auth>['applyOperation'];
|
|
189
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Hint for savepoint optimization on single-op commits.
|
|
250
|
+
*
|
|
251
|
+
* `true` means a rejected single operation never leaves durable writes
|
|
252
|
+
* before returning the rejection result.
|
|
253
|
+
*
|
|
254
|
+
* Defaults to `true` for the built-in applyOperation implementation and
|
|
255
|
+
* `false` when a custom applyOperation is provided.
|
|
256
|
+
*/
|
|
257
|
+
canRejectSingleOperationWithoutSavepoint?: boolean;
|
|
258
|
+
|
|
190
259
|
/**
|
|
191
260
|
* Custom scope extraction from row (for complex scope logic).
|
|
192
261
|
*/
|
|
@@ -254,6 +323,10 @@ export function createServerHandler<
|
|
|
254
323
|
versionColumn = 'server_version',
|
|
255
324
|
dependsOn,
|
|
256
325
|
snapshotChunkTtlMs,
|
|
326
|
+
snapshotBinaryColumns,
|
|
327
|
+
snapshotBinaryColumnsForVersion,
|
|
328
|
+
snapshotBinaryEncoder,
|
|
329
|
+
snapshotBinaryEncoderForVersion,
|
|
257
330
|
resolveScopes,
|
|
258
331
|
transformInbound,
|
|
259
332
|
transformOutbound,
|
|
@@ -262,42 +335,19 @@ export function createServerHandler<
|
|
|
262
335
|
authorize,
|
|
263
336
|
extractScopes: customExtractScopes,
|
|
264
337
|
} = options;
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
// Normalize scopes to pattern map and extract patterns/columns
|
|
281
|
-
const scopeColumnMap = normalizeScopes(scopeDefs);
|
|
282
|
-
const scopePatterns = Object.keys(scopeColumnMap) as ScopePattern[];
|
|
283
|
-
const scopeColumns: ScopeColumnMap = {};
|
|
284
|
-
|
|
285
|
-
for (const [pattern, columnName] of Object.entries(scopeColumnMap)) {
|
|
286
|
-
const vars = extractScopeVars(pattern);
|
|
287
|
-
if (vars.length !== 1) {
|
|
288
|
-
throw new Error(
|
|
289
|
-
`Scope pattern "${pattern}" must contain exactly one placeholder (got ${vars.length}).`
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
const varName = vars[0]!;
|
|
293
|
-
const existing = scopeColumns[varName];
|
|
294
|
-
if (existing && existing !== columnName) {
|
|
295
|
-
throw new Error(
|
|
296
|
-
`Scope variable "${varName}" is mapped to multiple columns: "${existing}" and "${columnName}".`
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
scopeColumns[varName] = columnName;
|
|
300
|
-
}
|
|
338
|
+
const resolveRowCodecs = createTableColumnCodecsResolver(codecs, {
|
|
339
|
+
dialect: codecDialect,
|
|
340
|
+
});
|
|
341
|
+
const primaryKeyColumn = primaryKey as keyof ServerDB[TableName] & string;
|
|
342
|
+
const qualifiedVersionRef = `${table}.${versionColumn}`;
|
|
343
|
+
const resolveTableCodecs = (row: Record<string, unknown>) =>
|
|
344
|
+
resolveRowCodecs(table, row);
|
|
345
|
+
const usePassthroughInbound = !transformInbound && codecs == null;
|
|
346
|
+
|
|
347
|
+
const { scopePatterns, scopeColumnsByVariable: scopeColumns } =
|
|
348
|
+
createSingleVariableScopeMetadata(scopeDefs);
|
|
349
|
+
const scopeColumnEntries = Object.entries(scopeColumns);
|
|
350
|
+
const requiredScopeKeys = Object.keys(scopeColumns);
|
|
301
351
|
|
|
302
352
|
// Default extractScopes from scope columns
|
|
303
353
|
const defaultExtractScopes = (row: Record<string, unknown>): StoredScopes => {
|
|
@@ -321,12 +371,101 @@ export function createServerHandler<
|
|
|
321
371
|
const resolved = await resolveScopes(ctx);
|
|
322
372
|
const normalized: ScopeValues = {};
|
|
323
373
|
for (const [scopeKey, scopeValue] of Object.entries(resolved)) {
|
|
324
|
-
|
|
374
|
+
// null/undefined means "no access for this scope" and is skipped.
|
|
375
|
+
if (scopeValue === null || scopeValue === undefined) continue;
|
|
376
|
+
if (typeof scopeValue === 'string') {
|
|
377
|
+
normalized[scopeKey] = scopeValue;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (Array.isArray(scopeValue)) {
|
|
381
|
+
const invalidIndex = scopeValue.findIndex(
|
|
382
|
+
(entry) => typeof entry !== 'string'
|
|
383
|
+
);
|
|
384
|
+
if (invalidIndex !== -1) {
|
|
385
|
+
throw new Error(
|
|
386
|
+
`resolveScopes() for table "${table}" returned a non-string entry ` +
|
|
387
|
+
`(${typeof scopeValue[invalidIndex]}) at index ${invalidIndex} of scope "${scopeKey}". ` +
|
|
388
|
+
'Scope values must be strings or string arrays.'
|
|
389
|
+
);
|
|
390
|
+
}
|
|
325
391
|
normalized[scopeKey] = scopeValue;
|
|
392
|
+
continue;
|
|
326
393
|
}
|
|
394
|
+
throw new Error(
|
|
395
|
+
`resolveScopes() for table "${table}" returned an invalid value ` +
|
|
396
|
+
`(${typeof scopeValue}) for scope "${scopeKey}". ` +
|
|
397
|
+
'Scope values must be strings or string arrays.'
|
|
398
|
+
);
|
|
327
399
|
}
|
|
328
400
|
return normalized;
|
|
329
401
|
};
|
|
402
|
+
const writeScopeCache = new WeakMap<
|
|
403
|
+
ServerApplyOperationContext<ServerDB, Auth>,
|
|
404
|
+
Promise<ScopeValues>
|
|
405
|
+
>();
|
|
406
|
+
|
|
407
|
+
const resolveWriteScopes = (
|
|
408
|
+
ctx: ServerApplyOperationContext<ServerDB, Auth>
|
|
409
|
+
): Promise<ScopeValues> => {
|
|
410
|
+
const cached = writeScopeCache.get(ctx);
|
|
411
|
+
if (cached) return cached;
|
|
412
|
+
const loaded = resolveScopesImpl(ctx);
|
|
413
|
+
writeScopeCache.set(ctx, loaded);
|
|
414
|
+
return loaded;
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const authorizeRowScopes = async (
|
|
418
|
+
ctx: ServerApplyOperationContext<ServerDB, Auth>,
|
|
419
|
+
row: Record<string, unknown>
|
|
420
|
+
): Promise<AuthorizeResult> => {
|
|
421
|
+
if (requiredScopeKeys.length === 0) return true;
|
|
422
|
+
|
|
423
|
+
let allowedScopes: ScopeValues;
|
|
424
|
+
try {
|
|
425
|
+
allowedScopes = await resolveWriteScopes(ctx);
|
|
426
|
+
} catch (resolveErr) {
|
|
427
|
+
console.error(
|
|
428
|
+
`[resolveScopes] Failed for table ${table} during write authorization:`,
|
|
429
|
+
resolveErr
|
|
430
|
+
);
|
|
431
|
+
return {
|
|
432
|
+
error: 'Forbidden',
|
|
433
|
+
code: 'sync.forbidden',
|
|
434
|
+
retriable: false,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const rowScopes = extractScopesImpl(row);
|
|
439
|
+
if (
|
|
440
|
+
rowScopesAllowed({
|
|
441
|
+
rowScopes,
|
|
442
|
+
allowedScopes,
|
|
443
|
+
requiredScopeKeys,
|
|
444
|
+
})
|
|
445
|
+
) {
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return {
|
|
450
|
+
error: 'Forbidden',
|
|
451
|
+
code: 'sync.forbidden',
|
|
452
|
+
retriable: false,
|
|
453
|
+
};
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
const rejectionResult = (
|
|
457
|
+
opIndex: number,
|
|
458
|
+
rejection: Exclude<AuthorizeResult, true>
|
|
459
|
+
): ApplyOperationResult => ({
|
|
460
|
+
result: {
|
|
461
|
+
opIndex,
|
|
462
|
+
status: 'error',
|
|
463
|
+
error: rejection.error,
|
|
464
|
+
code: rejection.code,
|
|
465
|
+
retriable: rejection.retriable ?? false,
|
|
466
|
+
},
|
|
467
|
+
emittedChanges: [],
|
|
468
|
+
});
|
|
330
469
|
|
|
331
470
|
const applyOutboundTransform = (
|
|
332
471
|
row: Selectable<ServerDB[TableName]>
|
|
@@ -348,6 +487,10 @@ export function createServerHandler<
|
|
|
348
487
|
row: Record<string, unknown>,
|
|
349
488
|
schemaVersion: number | undefined
|
|
350
489
|
): Updateable<ServerDB[TableName]> => {
|
|
490
|
+
if (usePassthroughInbound) {
|
|
491
|
+
return row as Updateable<ServerDB[TableName]>;
|
|
492
|
+
}
|
|
493
|
+
|
|
351
494
|
if (transformInbound) {
|
|
352
495
|
return transformInbound(row as Selectable<ClientDB[TableName]>, {
|
|
353
496
|
schemaVersion,
|
|
@@ -371,29 +514,29 @@ export function createServerHandler<
|
|
|
371
514
|
const { ref } = trx.dynamic;
|
|
372
515
|
const scopeValues = ctx.scopeValues;
|
|
373
516
|
|
|
374
|
-
const pageSize = Math.max(1,
|
|
517
|
+
const pageSize = Math.max(1, ctx.limit);
|
|
375
518
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const normalized = Array.isArray(values) ? values : [values];
|
|
382
|
-
if (normalized.length === 0) continue;
|
|
383
|
-
whereConditions.push({ column: columnName, values: normalized });
|
|
384
|
-
}
|
|
519
|
+
let q = trx.selectFrom(table) as SelectQueryBuilder<
|
|
520
|
+
ServerDB,
|
|
521
|
+
keyof ServerDB & string,
|
|
522
|
+
Record<string, unknown>
|
|
523
|
+
>;
|
|
385
524
|
|
|
386
|
-
|
|
525
|
+
q = q.selectAll() as SelectQueryBuilder<
|
|
387
526
|
ServerDB,
|
|
388
527
|
keyof ServerDB & string,
|
|
389
528
|
Record<string, unknown>
|
|
390
529
|
>;
|
|
391
530
|
|
|
392
|
-
for (const
|
|
393
|
-
|
|
394
|
-
|
|
531
|
+
for (const [varName, columnName] of scopeColumnEntries) {
|
|
532
|
+
const values = scopeValues[varName];
|
|
533
|
+
if (values === undefined) continue;
|
|
534
|
+
const normalized = Array.isArray(values) ? values : [values];
|
|
535
|
+
if (normalized.length === 0) continue;
|
|
536
|
+
if (normalized.length === 1) {
|
|
537
|
+
q = q.where(ref<string>(columnName), '=', normalized[0]);
|
|
395
538
|
} else {
|
|
396
|
-
q = q.where(ref<string>(
|
|
539
|
+
q = q.where(ref<string>(columnName), 'in', normalized);
|
|
397
540
|
}
|
|
398
541
|
}
|
|
399
542
|
|
|
@@ -417,10 +560,30 @@ export function createServerHandler<
|
|
|
417
560
|
| undefined)
|
|
418
561
|
: null;
|
|
419
562
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
563
|
+
let outputRows: unknown[];
|
|
564
|
+
if (transformOutbound) {
|
|
565
|
+
outputRows = pageRows.map((r) =>
|
|
566
|
+
applyOutboundTransform(r as Selectable<ServerDB[TableName]>)
|
|
567
|
+
);
|
|
568
|
+
} else {
|
|
569
|
+
const firstRow = pageRows[0] as Record<string, unknown> | undefined;
|
|
570
|
+
const tableCodecs = firstRow
|
|
571
|
+
? toTableColumnCodecs(table, codecs, Object.keys(firstRow), {
|
|
572
|
+
dialect: codecDialect,
|
|
573
|
+
})
|
|
574
|
+
: {};
|
|
575
|
+
if (Object.keys(tableCodecs).length === 0) {
|
|
576
|
+
outputRows = pageRows;
|
|
577
|
+
} else {
|
|
578
|
+
outputRows = pageRows.map((r) =>
|
|
579
|
+
applyCodecsFromDbRow(
|
|
580
|
+
r as Record<string, unknown>,
|
|
581
|
+
tableCodecs,
|
|
582
|
+
codecDialect
|
|
583
|
+
)
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
424
587
|
|
|
425
588
|
return {
|
|
426
589
|
rows: outputRows,
|
|
@@ -445,8 +608,8 @@ export function createServerHandler<
|
|
|
445
608
|
result: {
|
|
446
609
|
opIndex,
|
|
447
610
|
status: 'error',
|
|
448
|
-
error: `
|
|
449
|
-
code: '
|
|
611
|
+
error: `Unknown table: ${op.table}`,
|
|
612
|
+
code: 'sync.unknown_table',
|
|
450
613
|
retriable: false,
|
|
451
614
|
},
|
|
452
615
|
emittedChanges: [],
|
|
@@ -472,6 +635,25 @@ export function createServerHandler<
|
|
|
472
635
|
|
|
473
636
|
// Handle delete
|
|
474
637
|
if (op.op === 'delete') {
|
|
638
|
+
const existingRow = (await (
|
|
639
|
+
trx.selectFrom(table).selectAll() as SelectQueryBuilder<
|
|
640
|
+
ServerDB,
|
|
641
|
+
keyof ServerDB & string,
|
|
642
|
+
Record<string, unknown>
|
|
643
|
+
>
|
|
644
|
+
)
|
|
645
|
+
.where(ref<string>(primaryKey), '=', op.row_id)
|
|
646
|
+
.executeTakeFirst()) as Record<string, unknown> | undefined;
|
|
647
|
+
|
|
648
|
+
if (!existingRow) {
|
|
649
|
+
return { result: { opIndex, status: 'applied' }, emittedChanges: [] };
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
const scopeAuth = await authorizeRowScopes(ctx, existingRow);
|
|
653
|
+
if (scopeAuth !== true) {
|
|
654
|
+
return rejectionResult(opIndex, scopeAuth);
|
|
655
|
+
}
|
|
656
|
+
|
|
475
657
|
const deleted = await (
|
|
476
658
|
trx.deleteFrom(table) as DeleteQueryBuilder<
|
|
477
659
|
ServerDB,
|
|
@@ -484,9 +666,8 @@ export function createServerHandler<
|
|
|
484
666
|
.executeTakeFirst();
|
|
485
667
|
|
|
486
668
|
const deletedRow = deleted as Record<string, unknown> | undefined;
|
|
487
|
-
if (!deletedRow)
|
|
669
|
+
if (!deletedRow)
|
|
488
670
|
return { result: { opIndex, status: 'applied' }, emittedChanges: [] };
|
|
489
|
-
}
|
|
490
671
|
|
|
491
672
|
// Extract scopes from existing row for the delete emission
|
|
492
673
|
const scopes = extractScopesImpl(deletedRow);
|
|
@@ -513,6 +694,29 @@ export function createServerHandler<
|
|
|
513
694
|
? (rawPayload as Record<string, unknown>)
|
|
514
695
|
: {};
|
|
515
696
|
const payload = applyInboundTransform(payloadRecord, ctx.schemaVersion);
|
|
697
|
+
const rowForInsertScopeCheck: Record<string, unknown> = {
|
|
698
|
+
...payload,
|
|
699
|
+
[primaryKey]: op.row_id,
|
|
700
|
+
[versionColumn]: 1,
|
|
701
|
+
};
|
|
702
|
+
|
|
703
|
+
const existingRowBeforeWrite = (await (
|
|
704
|
+
trx.selectFrom(table).selectAll() as SelectQueryBuilder<
|
|
705
|
+
ServerDB,
|
|
706
|
+
keyof ServerDB & string,
|
|
707
|
+
Record<string, unknown>
|
|
708
|
+
>
|
|
709
|
+
)
|
|
710
|
+
.where(ref<string>(primaryKey), '=', op.row_id)
|
|
711
|
+
.executeTakeFirst()) as Record<string, unknown> | undefined;
|
|
712
|
+
|
|
713
|
+
const rowScopeAuth = await authorizeRowScopes(
|
|
714
|
+
ctx,
|
|
715
|
+
existingRowBeforeWrite ?? rowForInsertScopeCheck
|
|
716
|
+
);
|
|
717
|
+
if (rowScopeAuth !== true) {
|
|
718
|
+
return rejectionResult(opIndex, rowScopeAuth);
|
|
719
|
+
}
|
|
516
720
|
|
|
517
721
|
let updated: Record<string, unknown> | undefined;
|
|
518
722
|
let constraintError: { message: string; code: string } | null = null;
|
|
@@ -544,7 +748,7 @@ export function createServerHandler<
|
|
|
544
748
|
.executeTakeFirst()) as Record<string, unknown> | undefined;
|
|
545
749
|
|
|
546
750
|
if (!updated) {
|
|
547
|
-
|
|
751
|
+
let conflictRow = await (
|
|
548
752
|
trx.selectFrom(table).selectAll() as SelectQueryBuilder<
|
|
549
753
|
ServerDB,
|
|
550
754
|
keyof ServerDB & string,
|
|
@@ -554,100 +758,118 @@ export function createServerHandler<
|
|
|
554
758
|
.where(ref<string>(primaryKey), '=', op.row_id)
|
|
555
759
|
.executeTakeFirst();
|
|
556
760
|
|
|
557
|
-
if (!conflictRow) {
|
|
761
|
+
if (!conflictRow && expectedVersion === 0) {
|
|
762
|
+
const insertValues: Record<string, unknown> = {
|
|
763
|
+
...payload,
|
|
764
|
+
[primaryKey]: op.row_id,
|
|
765
|
+
[versionColumn]: 1,
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
try {
|
|
769
|
+
updated = (await (
|
|
770
|
+
trx.insertInto(table) as InsertQueryBuilder<
|
|
771
|
+
ServerDB,
|
|
772
|
+
TableName,
|
|
773
|
+
InsertResult
|
|
774
|
+
>
|
|
775
|
+
)
|
|
776
|
+
.values(insertValues as Insertable<ServerDB[TableName]>)
|
|
777
|
+
.returningAll()
|
|
778
|
+
.executeTakeFirst()) as Record<string, unknown> | undefined;
|
|
779
|
+
} catch (err) {
|
|
780
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
781
|
+
if (!isConstraintViolationError(message)) {
|
|
782
|
+
throw err;
|
|
783
|
+
}
|
|
784
|
+
conflictRow = await (
|
|
785
|
+
trx.selectFrom(table).selectAll() as SelectQueryBuilder<
|
|
786
|
+
ServerDB,
|
|
787
|
+
keyof ServerDB & string,
|
|
788
|
+
Record<string, unknown>
|
|
789
|
+
>
|
|
790
|
+
)
|
|
791
|
+
.where(ref<string>(primaryKey), '=', op.row_id)
|
|
792
|
+
.executeTakeFirst();
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
if (!updated && !conflictRow) {
|
|
558
797
|
return {
|
|
559
798
|
result: {
|
|
560
799
|
opIndex,
|
|
561
800
|
status: 'error',
|
|
562
|
-
error: '
|
|
563
|
-
code: '
|
|
801
|
+
error: 'Row not found for base version',
|
|
802
|
+
code: 'sync.row_missing',
|
|
564
803
|
retriable: false,
|
|
565
804
|
},
|
|
566
805
|
emittedChanges: [],
|
|
567
806
|
};
|
|
568
807
|
}
|
|
569
808
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
809
|
+
if (!updated && conflictRow) {
|
|
810
|
+
const conflictScopeAuth = await authorizeRowScopes(
|
|
811
|
+
ctx,
|
|
812
|
+
conflictRow
|
|
813
|
+
);
|
|
814
|
+
if (conflictScopeAuth !== true) {
|
|
815
|
+
return rejectionResult(opIndex, conflictScopeAuth);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
const existingVersion = readSafeVersionColumn(
|
|
819
|
+
conflictRow,
|
|
820
|
+
versionColumn,
|
|
821
|
+
0
|
|
822
|
+
);
|
|
823
|
+
return {
|
|
824
|
+
result: {
|
|
825
|
+
opIndex,
|
|
826
|
+
status: 'conflict',
|
|
827
|
+
message: `Version conflict: server=${existingVersion}, base=${expectedVersion}`,
|
|
828
|
+
code: 'sync.version_conflict',
|
|
829
|
+
server_version: existingVersion,
|
|
830
|
+
server_row: normalizeOutboundVersionColumn(
|
|
831
|
+
applyOutboundTransform(
|
|
832
|
+
conflictRow as Selectable<ServerDB[TableName]>
|
|
833
|
+
),
|
|
834
|
+
versionColumn,
|
|
835
|
+
existingVersion
|
|
836
|
+
),
|
|
837
|
+
},
|
|
838
|
+
emittedChanges: [],
|
|
839
|
+
};
|
|
840
|
+
}
|
|
584
841
|
}
|
|
585
842
|
} else {
|
|
586
843
|
const updateSet: Record<string, unknown> = {
|
|
587
844
|
...payload,
|
|
588
|
-
[versionColumn]: sql`${sql.ref(
|
|
845
|
+
[versionColumn]: sql`${sql.ref(qualifiedVersionRef)} + 1`,
|
|
589
846
|
};
|
|
590
847
|
delete updateSet[primaryKey];
|
|
591
848
|
for (const col of Object.values(scopeColumns)) {
|
|
592
849
|
delete updateSet[col];
|
|
593
850
|
}
|
|
594
851
|
|
|
852
|
+
const insertValues: Record<string, unknown> = {
|
|
853
|
+
...payload,
|
|
854
|
+
[primaryKey]: op.row_id,
|
|
855
|
+
[versionColumn]: 1,
|
|
856
|
+
};
|
|
857
|
+
|
|
595
858
|
updated = (await (
|
|
596
|
-
trx.
|
|
859
|
+
trx.insertInto(table) as InsertQueryBuilder<
|
|
597
860
|
ServerDB,
|
|
598
861
|
TableName,
|
|
599
|
-
|
|
600
|
-
UpdateResult
|
|
862
|
+
InsertResult
|
|
601
863
|
>
|
|
602
864
|
)
|
|
603
|
-
.
|
|
604
|
-
.
|
|
865
|
+
.values(insertValues as Insertable<ServerDB[TableName]>)
|
|
866
|
+
.onConflict((oc) =>
|
|
867
|
+
oc
|
|
868
|
+
.column(primaryKeyColumn)
|
|
869
|
+
.doUpdateSet(updateSet as UpdateSetObject)
|
|
870
|
+
)
|
|
605
871
|
.returningAll()
|
|
606
872
|
.executeTakeFirst()) as Record<string, unknown> | undefined;
|
|
607
|
-
|
|
608
|
-
if (!updated) {
|
|
609
|
-
const insertValues: Record<string, unknown> = {
|
|
610
|
-
...payload,
|
|
611
|
-
[primaryKey]: op.row_id,
|
|
612
|
-
[versionColumn]: 1,
|
|
613
|
-
};
|
|
614
|
-
|
|
615
|
-
try {
|
|
616
|
-
updated = (await (
|
|
617
|
-
trx.insertInto(table) as InsertQueryBuilder<
|
|
618
|
-
ServerDB,
|
|
619
|
-
TableName,
|
|
620
|
-
InsertResult
|
|
621
|
-
>
|
|
622
|
-
)
|
|
623
|
-
.values(insertValues as Insertable<ServerDB[TableName]>)
|
|
624
|
-
.returningAll()
|
|
625
|
-
.executeTakeFirst()) as Record<string, unknown> | undefined;
|
|
626
|
-
} catch (err) {
|
|
627
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
628
|
-
if (!isConstraintViolationError(message)) {
|
|
629
|
-
throw err;
|
|
630
|
-
}
|
|
631
|
-
updated = (await (
|
|
632
|
-
trx.updateTable(table) as UpdateQueryBuilder<
|
|
633
|
-
ServerDB,
|
|
634
|
-
TableName,
|
|
635
|
-
TableName,
|
|
636
|
-
UpdateResult
|
|
637
|
-
>
|
|
638
|
-
)
|
|
639
|
-
.set(updateSet as UpdateSetObject)
|
|
640
|
-
.where(ref<string>(primaryKey), '=', op.row_id)
|
|
641
|
-
.returningAll()
|
|
642
|
-
.executeTakeFirst()) as Record<string, unknown> | undefined;
|
|
643
|
-
if (!updated) {
|
|
644
|
-
constraintError = {
|
|
645
|
-
message,
|
|
646
|
-
code: classifyConstraintViolationCode(message),
|
|
647
|
-
};
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
873
|
}
|
|
652
874
|
} catch (err) {
|
|
653
875
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -666,8 +888,8 @@ export function createServerHandler<
|
|
|
666
888
|
result: {
|
|
667
889
|
opIndex,
|
|
668
890
|
status: 'error',
|
|
669
|
-
error: '
|
|
670
|
-
code: '
|
|
891
|
+
error: 'Row not found for base version',
|
|
892
|
+
code: 'sync.row_missing',
|
|
671
893
|
retriable: false,
|
|
672
894
|
},
|
|
673
895
|
emittedChanges: [],
|
|
@@ -703,14 +925,16 @@ export function createServerHandler<
|
|
|
703
925
|
}
|
|
704
926
|
|
|
705
927
|
const updatedRow = updated;
|
|
706
|
-
const rowVersion = (updatedRow
|
|
928
|
+
const rowVersion = readSafeVersionColumn(updatedRow, versionColumn, 1);
|
|
707
929
|
|
|
708
930
|
// Extract scopes from updated row
|
|
709
931
|
const scopes = extractScopesImpl(updatedRow);
|
|
710
932
|
|
|
711
933
|
// Transform outbound for emitted change
|
|
712
|
-
const rowJson =
|
|
713
|
-
updated as Selectable<ServerDB[TableName]>
|
|
934
|
+
const rowJson = normalizeOutboundVersionColumn(
|
|
935
|
+
applyOutboundTransform(updated as Selectable<ServerDB[TableName]>),
|
|
936
|
+
versionColumn,
|
|
937
|
+
rowVersion
|
|
714
938
|
);
|
|
715
939
|
|
|
716
940
|
const emitted: EmittedChange = {
|
|
@@ -728,14 +952,183 @@ export function createServerHandler<
|
|
|
728
952
|
};
|
|
729
953
|
};
|
|
730
954
|
|
|
955
|
+
const defaultApplyOperationBatch = async (
|
|
956
|
+
ctx: ServerApplyOperationContext<ServerDB, Auth>,
|
|
957
|
+
operations: BatchApplyOperationInput[]
|
|
958
|
+
): Promise<ApplyOperationResult[]> => {
|
|
959
|
+
if (operations.length === 0) return [];
|
|
960
|
+
|
|
961
|
+
const runSequentialFallback = async (): Promise<ApplyOperationResult[]> => {
|
|
962
|
+
const sequential: ApplyOperationResult[] = [];
|
|
963
|
+
for (const entry of operations) {
|
|
964
|
+
const applied = await defaultApplyOperation(
|
|
965
|
+
ctx,
|
|
966
|
+
entry.op,
|
|
967
|
+
entry.opIndex
|
|
968
|
+
);
|
|
969
|
+
sequential.push(applied);
|
|
970
|
+
if (applied.result.status !== 'applied') {
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return sequential;
|
|
975
|
+
};
|
|
976
|
+
|
|
977
|
+
if (operations.length === 1 || authorize || requiredScopeKeys.length > 0) {
|
|
978
|
+
return runSequentialFallback();
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
const trx = ctx.trx;
|
|
982
|
+
const prepared: Array<{
|
|
983
|
+
entry: BatchApplyOperationInput;
|
|
984
|
+
payload: Record<string, unknown>;
|
|
985
|
+
insertValues: Record<string, unknown>;
|
|
986
|
+
}> = [];
|
|
987
|
+
const seenRowIds = new Set<string>();
|
|
988
|
+
const payloadKeySignatures = new Set<string>();
|
|
989
|
+
|
|
990
|
+
for (const entry of operations) {
|
|
991
|
+
const op = entry.op;
|
|
992
|
+
if (op.table !== table || op.op !== 'upsert' || op.base_version != null) {
|
|
993
|
+
return runSequentialFallback();
|
|
994
|
+
}
|
|
995
|
+
if (seenRowIds.has(op.row_id)) {
|
|
996
|
+
return runSequentialFallback();
|
|
997
|
+
}
|
|
998
|
+
seenRowIds.add(op.row_id);
|
|
999
|
+
|
|
1000
|
+
const rawPayload = op.payload ?? {};
|
|
1001
|
+
const payloadRecord =
|
|
1002
|
+
rawPayload !== null && typeof rawPayload === 'object'
|
|
1003
|
+
? (rawPayload as Record<string, unknown>)
|
|
1004
|
+
: {};
|
|
1005
|
+
const payload = applyInboundTransform(
|
|
1006
|
+
payloadRecord,
|
|
1007
|
+
ctx.schemaVersion
|
|
1008
|
+
) as Record<string, unknown>;
|
|
1009
|
+
|
|
1010
|
+
payloadKeySignatures.add(Object.keys(payload).sort().join('\u0000'));
|
|
1011
|
+
|
|
1012
|
+
const insertValues: Record<string, unknown> = {
|
|
1013
|
+
...payload,
|
|
1014
|
+
[primaryKey]: op.row_id,
|
|
1015
|
+
[versionColumn]: 1,
|
|
1016
|
+
};
|
|
1017
|
+
|
|
1018
|
+
prepared.push({
|
|
1019
|
+
entry,
|
|
1020
|
+
payload,
|
|
1021
|
+
insertValues,
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
if (prepared.length <= 1 || payloadKeySignatures.size !== 1) {
|
|
1026
|
+
return runSequentialFallback();
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
const basePayload = prepared[0]!.payload;
|
|
1030
|
+
const updateSet: Record<string, unknown> = {
|
|
1031
|
+
...basePayload,
|
|
1032
|
+
[versionColumn]: sql`${sql.ref(qualifiedVersionRef)} + 1`,
|
|
1033
|
+
};
|
|
1034
|
+
delete updateSet[primaryKey];
|
|
1035
|
+
for (const col of Object.values(scopeColumns)) {
|
|
1036
|
+
delete updateSet[col];
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
try {
|
|
1040
|
+
const updatedRows = (await (
|
|
1041
|
+
trx.insertInto(table) as InsertQueryBuilder<
|
|
1042
|
+
ServerDB,
|
|
1043
|
+
TableName,
|
|
1044
|
+
InsertResult
|
|
1045
|
+
>
|
|
1046
|
+
)
|
|
1047
|
+
.values(
|
|
1048
|
+
prepared.map(
|
|
1049
|
+
(item) => item.insertValues as Insertable<ServerDB[TableName]>
|
|
1050
|
+
)
|
|
1051
|
+
)
|
|
1052
|
+
.onConflict((oc) =>
|
|
1053
|
+
oc.column(primaryKeyColumn).doUpdateSet(updateSet as UpdateSetObject)
|
|
1054
|
+
)
|
|
1055
|
+
.returningAll()
|
|
1056
|
+
.execute()) as Record<string, unknown>[];
|
|
1057
|
+
|
|
1058
|
+
const updatedById = new Map<string, Record<string, unknown>>();
|
|
1059
|
+
for (const row of updatedRows) {
|
|
1060
|
+
const rowIdValue = row[primaryKey];
|
|
1061
|
+
if (rowIdValue === null || rowIdValue === undefined) continue;
|
|
1062
|
+
updatedById.set(String(rowIdValue), row);
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
const results: ApplyOperationResult[] = [];
|
|
1066
|
+
for (const item of prepared) {
|
|
1067
|
+
const rowId = item.entry.op.row_id;
|
|
1068
|
+
const updated = updatedById.get(rowId);
|
|
1069
|
+
if (!updated) {
|
|
1070
|
+
return runSequentialFallback();
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
const rowVersion = readSafeVersionColumn(updated, versionColumn, 1);
|
|
1074
|
+
const scopes = extractScopesImpl(updated);
|
|
1075
|
+
const rowJson = normalizeOutboundVersionColumn(
|
|
1076
|
+
applyOutboundTransform(updated as Selectable<ServerDB[TableName]>),
|
|
1077
|
+
versionColumn,
|
|
1078
|
+
rowVersion
|
|
1079
|
+
);
|
|
1080
|
+
|
|
1081
|
+
results.push({
|
|
1082
|
+
result: { opIndex: item.entry.opIndex, status: 'applied' },
|
|
1083
|
+
emittedChanges: [
|
|
1084
|
+
{
|
|
1085
|
+
table,
|
|
1086
|
+
row_id: rowId,
|
|
1087
|
+
op: 'upsert',
|
|
1088
|
+
row_json: rowJson,
|
|
1089
|
+
row_version: rowVersion,
|
|
1090
|
+
scopes,
|
|
1091
|
+
},
|
|
1092
|
+
],
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
return results;
|
|
1097
|
+
} catch (err) {
|
|
1098
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1099
|
+
if (isConstraintViolationError(message)) {
|
|
1100
|
+
return runSequentialFallback();
|
|
1101
|
+
}
|
|
1102
|
+
throw err;
|
|
1103
|
+
}
|
|
1104
|
+
};
|
|
1105
|
+
|
|
731
1106
|
return {
|
|
732
1107
|
table,
|
|
1108
|
+
primaryKeyColumn,
|
|
733
1109
|
scopePatterns,
|
|
734
1110
|
dependsOn,
|
|
735
1111
|
snapshotChunkTtlMs,
|
|
1112
|
+
snapshotBinaryColumns,
|
|
1113
|
+
snapshotBinaryColumnsForVersion,
|
|
1114
|
+
snapshotBinaryEncoder: snapshotBinaryEncoder as
|
|
1115
|
+
| BinarySnapshotRowsEncoder
|
|
1116
|
+
| undefined,
|
|
1117
|
+
snapshotBinaryEncoderForVersion: snapshotBinaryEncoderForVersion as
|
|
1118
|
+
| ((
|
|
1119
|
+
schemaVersion: number
|
|
1120
|
+
) => BinarySnapshotRowsEncoder | null | undefined)
|
|
1121
|
+
| undefined,
|
|
1122
|
+
canRejectSingleOperationWithoutSavepoint:
|
|
1123
|
+
options.canRejectSingleOperationWithoutSavepoint ??
|
|
1124
|
+
options.applyOperation === undefined,
|
|
736
1125
|
resolveScopes: resolveScopesImpl,
|
|
737
1126
|
extractScopes: extractScopesImpl,
|
|
738
1127
|
snapshot: options.snapshot ?? defaultSnapshot,
|
|
739
1128
|
applyOperation: options.applyOperation ?? defaultApplyOperation,
|
|
1129
|
+
applyOperationBatch:
|
|
1130
|
+
options.applyOperation === undefined
|
|
1131
|
+
? defaultApplyOperationBatch
|
|
1132
|
+
: undefined,
|
|
740
1133
|
};
|
|
741
1134
|
}
|