@syncular/server 0.0.6-96 → 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
package/src/sqlite3.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server/sqlite3 - node-sqlite3 dialect for sync
|
|
3
|
+
*
|
|
4
|
+
* Provides a Kysely dialect for the callback-based `sqlite3` npm package.
|
|
5
|
+
* SQLite-compatible — use with @syncular/server/sqlite.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
CompiledQuery,
|
|
10
|
+
DatabaseConnection,
|
|
11
|
+
Dialect,
|
|
12
|
+
QueryResult,
|
|
13
|
+
} from 'kysely';
|
|
14
|
+
import { BaseSqliteDialect, BaseSqliteDriver } from 'kysely-generic-sqlite';
|
|
15
|
+
import sqlite3 from 'sqlite3';
|
|
16
|
+
|
|
17
|
+
export interface Sqlite3PathOptions {
|
|
18
|
+
/** Path to SQLite database file, or ':memory:' for in-memory */
|
|
19
|
+
path: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface Sqlite3InstanceOptions {
|
|
23
|
+
/** An existing sqlite3.Database instance */
|
|
24
|
+
database: sqlite3.Database;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type Sqlite3Options = Sqlite3PathOptions | Sqlite3InstanceOptions;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create the sqlite3 dialect directly.
|
|
31
|
+
*/
|
|
32
|
+
export function createSqlite3Dialect(options: Sqlite3Options): Dialect {
|
|
33
|
+
return new BaseSqliteDialect(() => new Sqlite3Driver(options));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class Sqlite3Driver extends BaseSqliteDriver {
|
|
37
|
+
#db: sqlite3.Database | undefined;
|
|
38
|
+
|
|
39
|
+
constructor(options: Sqlite3Options) {
|
|
40
|
+
super(async () => {
|
|
41
|
+
this.#db = await resolveSqlite3Database(options);
|
|
42
|
+
this.conn = new Sqlite3Connection(this.#db);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async destroy(): Promise<void> {
|
|
47
|
+
const db = this.#db;
|
|
48
|
+
this.#db = undefined;
|
|
49
|
+
if (!db) return;
|
|
50
|
+
|
|
51
|
+
await new Promise<void>((resolve, reject) => {
|
|
52
|
+
db.close((err) => {
|
|
53
|
+
if (err) {
|
|
54
|
+
reject(err);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
resolve();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function resolveSqlite3Database(
|
|
64
|
+
options: Sqlite3Options
|
|
65
|
+
): Promise<sqlite3.Database> {
|
|
66
|
+
if ('database' in options) {
|
|
67
|
+
return options.database;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return new Promise<sqlite3.Database>((resolve, reject) => {
|
|
71
|
+
const db = new sqlite3.Database(options.path, (err) => {
|
|
72
|
+
if (err) {
|
|
73
|
+
reject(err);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
resolve(db);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class Sqlite3Connection implements DatabaseConnection {
|
|
82
|
+
readonly #db: sqlite3.Database;
|
|
83
|
+
|
|
84
|
+
constructor(db: sqlite3.Database) {
|
|
85
|
+
this.#db = db;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async executeQuery<R>(compiledQuery: CompiledQuery): Promise<QueryResult<R>> {
|
|
89
|
+
const { sql, parameters } = compiledQuery;
|
|
90
|
+
const params = [...parameters];
|
|
91
|
+
|
|
92
|
+
const hasReturning = /\breturning\b/i.test(sql);
|
|
93
|
+
const isSelectLike = /^\s*(select|pragma|explain|with)\b/i.test(sql);
|
|
94
|
+
const isInsert = /^\s*(insert|replace)\b/i.test(sql);
|
|
95
|
+
|
|
96
|
+
if (isSelectLike || hasReturning) {
|
|
97
|
+
return new Promise<QueryResult<R>>((resolve, reject) => {
|
|
98
|
+
this.#db.all(sql, params, (err: Error | null, rows: R[]) => {
|
|
99
|
+
if (err) {
|
|
100
|
+
reject(err);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const normalizedRows = rows ?? [];
|
|
105
|
+
resolve({
|
|
106
|
+
rows: normalizedRows,
|
|
107
|
+
...(hasReturning
|
|
108
|
+
? { numAffectedRows: BigInt(normalizedRows.length) }
|
|
109
|
+
: {}),
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return new Promise<QueryResult<R>>((resolve, reject) => {
|
|
116
|
+
this.#db.run(sql, params, function onRun(err: Error | null) {
|
|
117
|
+
if (err) {
|
|
118
|
+
reject(err);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
resolve({
|
|
123
|
+
rows: [],
|
|
124
|
+
numAffectedRows: BigInt(this.changes),
|
|
125
|
+
...(isInsert ? { insertId: BigInt(this.lastID) } : {}),
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
streamQuery<R>(
|
|
132
|
+
_compiledQuery: CompiledQuery,
|
|
133
|
+
_chunkSize?: number
|
|
134
|
+
): AsyncIterableIterator<QueryResult<R>> {
|
|
135
|
+
throw new Error('sqlite3 driver does not support streaming');
|
|
136
|
+
}
|
|
137
|
+
}
|
package/src/stats.ts
CHANGED
|
@@ -4,23 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
import type { Kysely, SelectQueryBuilder, SqlBool } from 'kysely';
|
|
6
6
|
import { sql } from 'kysely';
|
|
7
|
+
import { coerceNumber } from './dialect/helpers';
|
|
7
8
|
import type { SyncCoreDb } from './schema';
|
|
8
9
|
|
|
9
10
|
// biome-ignore lint/complexity/noBannedTypes: Kysely uses `{}` as the initial "no selected columns yet" marker.
|
|
10
11
|
type EmptySelection = {};
|
|
11
12
|
|
|
12
|
-
function coerceNumber(value: unknown): number | null {
|
|
13
|
-
if (value === null || value === undefined) return null;
|
|
14
|
-
if (typeof value === 'number') return Number.isFinite(value) ? value : null;
|
|
15
|
-
if (typeof value === 'bigint')
|
|
16
|
-
return Number.isFinite(Number(value)) ? Number(value) : null;
|
|
17
|
-
if (typeof value === 'string') {
|
|
18
|
-
const n = Number(value);
|
|
19
|
-
return Number.isFinite(n) ? n : null;
|
|
20
|
-
}
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
13
|
export interface SyncStats {
|
|
25
14
|
commitCount: number;
|
|
26
15
|
changeCount: number;
|
|
@@ -30,6 +19,35 @@ export interface SyncStats {
|
|
|
30
19
|
activeClientCount: number;
|
|
31
20
|
minActiveClientCursor: number | null;
|
|
32
21
|
maxActiveClientCursor: number | null;
|
|
22
|
+
snapshotChunkCount: number;
|
|
23
|
+
snapshotChunkBytes: number;
|
|
24
|
+
expiredSnapshotChunkCount: number;
|
|
25
|
+
expiredSnapshotChunkBytes: number;
|
|
26
|
+
snapshotArtifactCount: number;
|
|
27
|
+
snapshotArtifactBytes: number;
|
|
28
|
+
expiredSnapshotArtifactCount: number;
|
|
29
|
+
expiredSnapshotArtifactBytes: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface CachePressureRow {
|
|
33
|
+
total_count: unknown;
|
|
34
|
+
total_bytes: unknown;
|
|
35
|
+
expired_count: unknown;
|
|
36
|
+
expired_bytes: unknown;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function mapCachePressure(row: CachePressureRow | undefined): {
|
|
40
|
+
count: number;
|
|
41
|
+
bytes: number;
|
|
42
|
+
expiredCount: number;
|
|
43
|
+
expiredBytes: number;
|
|
44
|
+
} {
|
|
45
|
+
return {
|
|
46
|
+
count: coerceNumber(row?.total_count) ?? 0,
|
|
47
|
+
bytes: coerceNumber(row?.total_bytes) ?? 0,
|
|
48
|
+
expiredCount: coerceNumber(row?.expired_count) ?? 0,
|
|
49
|
+
expiredBytes: coerceNumber(row?.expired_bytes) ?? 0,
|
|
50
|
+
};
|
|
33
51
|
}
|
|
34
52
|
|
|
35
53
|
export async function readSyncStats<DB extends SyncCoreDb>(
|
|
@@ -41,6 +59,7 @@ export async function readSyncStats<DB extends SyncCoreDb>(
|
|
|
41
59
|
|
|
42
60
|
const activeWindowMs = options.activeWindowMs ?? 14 * 24 * 60 * 60 * 1000;
|
|
43
61
|
const cutoffIso = new Date(Date.now() - activeWindowMs).toISOString();
|
|
62
|
+
const nowIso = new Date().toISOString();
|
|
44
63
|
const partitionId = options.partitionId;
|
|
45
64
|
|
|
46
65
|
let commitQuery = (
|
|
@@ -97,13 +116,49 @@ export async function readSyncStats<DB extends SyncCoreDb>(
|
|
|
97
116
|
);
|
|
98
117
|
}
|
|
99
118
|
|
|
100
|
-
const
|
|
119
|
+
const partitionFilter = partitionId
|
|
120
|
+
? sql`where partition_id = ${partitionId}`
|
|
121
|
+
: sql``;
|
|
122
|
+
|
|
123
|
+
const [
|
|
124
|
+
commitRow,
|
|
125
|
+
changeRow,
|
|
126
|
+
clientRow,
|
|
127
|
+
activeClientRow,
|
|
128
|
+
chunkPressureRow,
|
|
129
|
+
artifactPressureRow,
|
|
130
|
+
] = await Promise.all([
|
|
101
131
|
commitQuery.executeTakeFirst(),
|
|
102
132
|
changeQuery.executeTakeFirst(),
|
|
103
133
|
clientQuery.executeTakeFirst(),
|
|
104
134
|
activeClientQuery.executeTakeFirst(),
|
|
135
|
+
sql<CachePressureRow>`
|
|
136
|
+
select
|
|
137
|
+
count(*) as total_count,
|
|
138
|
+
coalesce(sum(byte_length), 0) as total_bytes,
|
|
139
|
+
coalesce(sum(case when expires_at <= ${nowIso} then 1 else 0 end), 0) as expired_count,
|
|
140
|
+
coalesce(sum(case when expires_at <= ${nowIso} then byte_length else 0 end), 0) as expired_bytes
|
|
141
|
+
from ${sql.table('sync_snapshot_chunks')}
|
|
142
|
+
${partitionFilter}
|
|
143
|
+
`
|
|
144
|
+
.execute(db)
|
|
145
|
+
.then((result) => result.rows[0]),
|
|
146
|
+
sql<CachePressureRow>`
|
|
147
|
+
select
|
|
148
|
+
count(*) as total_count,
|
|
149
|
+
coalesce(sum(byte_length), 0) as total_bytes,
|
|
150
|
+
coalesce(sum(case when expires_at <= ${nowIso} then 1 else 0 end), 0) as expired_count,
|
|
151
|
+
coalesce(sum(case when expires_at <= ${nowIso} then byte_length else 0 end), 0) as expired_bytes
|
|
152
|
+
from ${sql.table('sync_snapshot_artifacts')}
|
|
153
|
+
${partitionFilter}
|
|
154
|
+
`
|
|
155
|
+
.execute(db)
|
|
156
|
+
.then((result) => result.rows[0]),
|
|
105
157
|
]);
|
|
106
158
|
|
|
159
|
+
const chunkPressure = mapCachePressure(chunkPressureRow);
|
|
160
|
+
const artifactPressure = mapCachePressure(artifactPressureRow);
|
|
161
|
+
|
|
107
162
|
return {
|
|
108
163
|
commitCount: coerceNumber(commitRow?.commitCount) ?? 0,
|
|
109
164
|
changeCount: coerceNumber(changeRow?.changeCount) ?? 0,
|
|
@@ -113,5 +168,13 @@ export async function readSyncStats<DB extends SyncCoreDb>(
|
|
|
113
168
|
activeClientCount: coerceNumber(activeClientRow?.activeClientCount) ?? 0,
|
|
114
169
|
minActiveClientCursor: coerceNumber(activeClientRow?.minActiveClientCursor),
|
|
115
170
|
maxActiveClientCursor: coerceNumber(activeClientRow?.maxActiveClientCursor),
|
|
171
|
+
snapshotChunkCount: chunkPressure.count,
|
|
172
|
+
snapshotChunkBytes: chunkPressure.bytes,
|
|
173
|
+
expiredSnapshotChunkCount: chunkPressure.expiredCount,
|
|
174
|
+
expiredSnapshotChunkBytes: chunkPressure.expiredBytes,
|
|
175
|
+
snapshotArtifactCount: artifactPressure.count,
|
|
176
|
+
snapshotArtifactBytes: artifactPressure.bytes,
|
|
177
|
+
expiredSnapshotArtifactCount: artifactPressure.expiredCount,
|
|
178
|
+
expiredSnapshotArtifactBytes: artifactPressure.expiredBytes,
|
|
116
179
|
};
|
|
117
180
|
}
|
|
@@ -37,6 +37,11 @@ export interface ScopeCacheBackend {
|
|
|
37
37
|
get<DB extends SyncCoreDb, Auth extends SyncServerAuth>(
|
|
38
38
|
args: ScopeCacheContext<DB, Auth>
|
|
39
39
|
): Promise<ScopeValues | null>;
|
|
40
|
+
getOrResolve?<DB extends SyncCoreDb, Auth extends SyncServerAuth>(
|
|
41
|
+
args: ScopeCacheContext<DB, Auth> & {
|
|
42
|
+
load: () => Promise<ScopeValues | null>;
|
|
43
|
+
}
|
|
44
|
+
): Promise<ScopeValues | null>;
|
|
40
45
|
set<DB extends SyncCoreDb, Auth extends SyncServerAuth>(
|
|
41
46
|
args: ScopeCacheSetContext<DB, Auth>
|
|
42
47
|
): Promise<void>;
|
|
@@ -117,6 +122,10 @@ export function createMemoryScopeCache(
|
|
|
117
122
|
options?.maxEntries ?? DEFAULT_MEMORY_SCOPE_CACHE_MAX_ENTRIES;
|
|
118
123
|
const now = options?.now ?? Date.now;
|
|
119
124
|
const buckets = new WeakMap<object, Map<string, MemoryScopeCacheEntry>>();
|
|
125
|
+
const inflightByDb = new WeakMap<
|
|
126
|
+
object,
|
|
127
|
+
Map<string, Promise<ScopeValues | null>>
|
|
128
|
+
>();
|
|
120
129
|
|
|
121
130
|
function getBucket(db: object): Map<string, MemoryScopeCacheEntry> {
|
|
122
131
|
const existing = buckets.get(db);
|
|
@@ -128,6 +137,18 @@ export function createMemoryScopeCache(
|
|
|
128
137
|
return created;
|
|
129
138
|
}
|
|
130
139
|
|
|
140
|
+
function getInflightBucket(
|
|
141
|
+
db: object
|
|
142
|
+
): Map<string, Promise<ScopeValues | null>> {
|
|
143
|
+
const existing = inflightByDb.get(db);
|
|
144
|
+
if (existing) {
|
|
145
|
+
return existing;
|
|
146
|
+
}
|
|
147
|
+
const created = new Map<string, Promise<ScopeValues | null>>();
|
|
148
|
+
inflightByDb.set(db, created);
|
|
149
|
+
return created;
|
|
150
|
+
}
|
|
151
|
+
|
|
131
152
|
function evictOldest(bucket: Map<string, MemoryScopeCacheEntry>): void {
|
|
132
153
|
while (bucket.size > maxEntries) {
|
|
133
154
|
const oldestKey = bucket.keys().next().value;
|
|
@@ -155,6 +176,43 @@ export function createMemoryScopeCache(
|
|
|
155
176
|
|
|
156
177
|
return cloneScopeValues(entry.scopes);
|
|
157
178
|
},
|
|
179
|
+
async getOrResolve(args) {
|
|
180
|
+
const cached = await this.get(args);
|
|
181
|
+
if (cached !== null) {
|
|
182
|
+
return cached;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const inflightBucket = getInflightBucket(args.db);
|
|
186
|
+
const inflight = inflightBucket.get(args.cacheKey);
|
|
187
|
+
if (inflight) {
|
|
188
|
+
const resolved = await inflight;
|
|
189
|
+
return resolved ? cloneScopeValues(resolved) : null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const pending = args
|
|
193
|
+
.load()
|
|
194
|
+
.then(async (resolved) => {
|
|
195
|
+
if (resolved !== null && ttlMs > 0) {
|
|
196
|
+
const bucket = getBucket(args.db);
|
|
197
|
+
if (bucket.has(args.cacheKey)) {
|
|
198
|
+
bucket.delete(args.cacheKey);
|
|
199
|
+
}
|
|
200
|
+
bucket.set(args.cacheKey, {
|
|
201
|
+
scopes: cloneScopeValues(resolved),
|
|
202
|
+
expiresAt: now() + ttlMs,
|
|
203
|
+
});
|
|
204
|
+
evictOldest(bucket);
|
|
205
|
+
}
|
|
206
|
+
return resolved;
|
|
207
|
+
})
|
|
208
|
+
.finally(() => {
|
|
209
|
+
inflightBucket.delete(args.cacheKey);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
inflightBucket.set(args.cacheKey, pending);
|
|
213
|
+
const resolved = await pending;
|
|
214
|
+
return resolved ? cloneScopeValues(resolved) : null;
|
|
215
|
+
},
|
|
158
216
|
async set(args) {
|
|
159
217
|
const bucket = getBucket(args.db);
|
|
160
218
|
if (ttlMs <= 0) {
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
collectScopeVars,
|
|
3
3
|
type ScopeValues,
|
|
4
4
|
type SyncSubscriptionRequest,
|
|
5
5
|
} from '@syncular/core';
|
|
6
6
|
import type { Kysely } from 'kysely';
|
|
7
|
-
import {
|
|
8
|
-
getServerHandler,
|
|
9
|
-
type ServerHandlerCollection,
|
|
10
|
-
} from '../handlers/collection';
|
|
7
|
+
import type { ServerHandlerCollection } from '../handlers/collection';
|
|
11
8
|
import type { SyncServerAuth } from '../handlers/types';
|
|
12
9
|
import type { SyncCoreDb } from '../schema';
|
|
13
10
|
import { createDefaultScopeCacheKey, type ScopeCacheBackend } from './cache';
|
|
@@ -29,6 +26,8 @@ export interface ResolvedSubscription {
|
|
|
29
26
|
params: Record<string, unknown> | undefined;
|
|
30
27
|
cursor: number;
|
|
31
28
|
bootstrapState?: SyncSubscriptionRequest['bootstrapState'];
|
|
29
|
+
verifiedRoot?: string;
|
|
30
|
+
crdtStateVectors: SyncSubscriptionRequest['crdtStateVectors'];
|
|
32
31
|
status: 'active' | 'revoked';
|
|
33
32
|
}
|
|
34
33
|
|
|
@@ -92,19 +91,6 @@ function scopesEmpty(scopes: ScopeValues): boolean {
|
|
|
92
91
|
return true;
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
/**
|
|
96
|
-
* Collect valid scope keys from handler scope patterns.
|
|
97
|
-
*/
|
|
98
|
-
function collectScopeKeys(scopePatterns: readonly string[]): Set<string> {
|
|
99
|
-
const keys = new Set<string>();
|
|
100
|
-
for (const pattern of scopePatterns) {
|
|
101
|
-
for (const key of extractScopeVars(pattern)) {
|
|
102
|
-
keys.add(key);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return keys;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
94
|
function validateScopeKeys(args: {
|
|
109
95
|
scopeValues: ScopeValues;
|
|
110
96
|
validScopeKeys: Set<string>;
|
|
@@ -166,14 +152,14 @@ export async function resolveEffectiveScopesForSubscriptions<
|
|
|
166
152
|
);
|
|
167
153
|
}
|
|
168
154
|
|
|
169
|
-
const handler =
|
|
155
|
+
const handler = args.handlers.byTable.get(sub.table);
|
|
170
156
|
if (!handler) {
|
|
171
157
|
throw new InvalidSubscriptionScopeError(
|
|
172
158
|
`Unknown table: ${sub.table} for subscription ${sub.id}`
|
|
173
159
|
);
|
|
174
160
|
}
|
|
175
161
|
|
|
176
|
-
const validScopeKeys =
|
|
162
|
+
const validScopeKeys = collectScopeVars(handler.scopePatterns);
|
|
177
163
|
const requested = sub.scopes ?? {};
|
|
178
164
|
validateScopeKeys({
|
|
179
165
|
scopeValues: requested,
|
|
@@ -193,72 +179,101 @@ export async function resolveEffectiveScopesForSubscriptions<
|
|
|
193
179
|
if (requestScopeCache.has(scopeCacheKey)) {
|
|
194
180
|
allowed = requestScopeCache.get(scopeCacheKey) ?? null;
|
|
195
181
|
} else {
|
|
196
|
-
|
|
197
|
-
let sharedCacheHit = false;
|
|
182
|
+
let resolveFailed = false;
|
|
198
183
|
|
|
199
|
-
|
|
184
|
+
const loadAllowedScopes = async (): Promise<ScopeValues> => {
|
|
200
185
|
try {
|
|
201
|
-
|
|
186
|
+
return await handler.resolveScopes({
|
|
202
187
|
db: args.db,
|
|
188
|
+
actorId: args.auth.actorId,
|
|
203
189
|
auth: args.auth,
|
|
204
|
-
table: sub.table,
|
|
205
|
-
cacheKey: scopeCacheKey,
|
|
206
190
|
});
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
sharedCacheHit = true;
|
|
210
|
-
}
|
|
211
|
-
} catch (cacheErr) {
|
|
191
|
+
} catch (resolveErr) {
|
|
192
|
+
resolveFailed = true;
|
|
212
193
|
console.error(
|
|
213
|
-
`[
|
|
214
|
-
|
|
194
|
+
`[resolveScopes] Failed for table ${sub.table}, subscription ${sub.id}:`,
|
|
195
|
+
resolveErr
|
|
215
196
|
);
|
|
197
|
+
throw resolveErr;
|
|
216
198
|
}
|
|
217
|
-
}
|
|
199
|
+
};
|
|
218
200
|
|
|
219
|
-
if (
|
|
201
|
+
if (args.scopeCache?.getOrResolve) {
|
|
220
202
|
try {
|
|
221
|
-
allowed = await
|
|
203
|
+
allowed = await args.scopeCache.getOrResolve({
|
|
222
204
|
db: args.db,
|
|
223
|
-
actorId: args.auth.actorId,
|
|
224
205
|
auth: args.auth,
|
|
225
|
-
});
|
|
226
|
-
} catch (resolveErr) {
|
|
227
|
-
// Scope resolution failed - mark subscription as revoked
|
|
228
|
-
// rather than failing the entire pull
|
|
229
|
-
console.error(
|
|
230
|
-
`[resolveScopes] Failed for table ${sub.table}, subscription ${sub.id}:`,
|
|
231
|
-
resolveErr
|
|
232
|
-
);
|
|
233
|
-
requestScopeCache.set(scopeCacheKey, null);
|
|
234
|
-
out.push({
|
|
235
|
-
id: sub.id,
|
|
236
206
|
table: sub.table,
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
cursor: sub.cursor,
|
|
240
|
-
bootstrapState: sub.bootstrapState ?? null,
|
|
241
|
-
status: 'revoked',
|
|
207
|
+
cacheKey: scopeCacheKey,
|
|
208
|
+
load: loadAllowedScopes,
|
|
242
209
|
});
|
|
243
|
-
|
|
210
|
+
} catch {
|
|
211
|
+
allowed = null;
|
|
244
212
|
}
|
|
213
|
+
} else {
|
|
214
|
+
allowed = null;
|
|
215
|
+
let sharedCacheHit = false;
|
|
245
216
|
|
|
246
|
-
if (args.scopeCache
|
|
217
|
+
if (args.scopeCache) {
|
|
247
218
|
try {
|
|
248
|
-
await args.scopeCache.
|
|
219
|
+
const cachedAllowed = await args.scopeCache.get({
|
|
249
220
|
db: args.db,
|
|
250
221
|
auth: args.auth,
|
|
251
222
|
table: sub.table,
|
|
252
223
|
cacheKey: scopeCacheKey,
|
|
253
|
-
scopes: allowed,
|
|
254
224
|
});
|
|
225
|
+
if (cachedAllowed !== null) {
|
|
226
|
+
allowed = cachedAllowed;
|
|
227
|
+
sharedCacheHit = true;
|
|
228
|
+
}
|
|
255
229
|
} catch (cacheErr) {
|
|
256
230
|
console.error(
|
|
257
|
-
`[scopeCache.
|
|
231
|
+
`[scopeCache.get] Failed for table ${sub.table}, subscription ${sub.id}:`,
|
|
258
232
|
cacheErr
|
|
259
233
|
);
|
|
260
234
|
}
|
|
261
235
|
}
|
|
236
|
+
|
|
237
|
+
if (!sharedCacheHit) {
|
|
238
|
+
try {
|
|
239
|
+
allowed = await loadAllowedScopes();
|
|
240
|
+
} catch {
|
|
241
|
+
allowed = null;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (args.scopeCache && allowed !== null) {
|
|
245
|
+
try {
|
|
246
|
+
await args.scopeCache.set({
|
|
247
|
+
db: args.db,
|
|
248
|
+
auth: args.auth,
|
|
249
|
+
table: sub.table,
|
|
250
|
+
cacheKey: scopeCacheKey,
|
|
251
|
+
scopes: allowed,
|
|
252
|
+
});
|
|
253
|
+
} catch (cacheErr) {
|
|
254
|
+
console.error(
|
|
255
|
+
`[scopeCache.set] Failed for table ${sub.table}, subscription ${sub.id}:`,
|
|
256
|
+
cacheErr
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (resolveFailed) {
|
|
264
|
+
requestScopeCache.set(scopeCacheKey, null);
|
|
265
|
+
out.push({
|
|
266
|
+
id: sub.id,
|
|
267
|
+
table: sub.table,
|
|
268
|
+
scopes: {},
|
|
269
|
+
params: sub.params,
|
|
270
|
+
cursor: sub.cursor,
|
|
271
|
+
bootstrapState: sub.bootstrapState ?? null,
|
|
272
|
+
verifiedRoot: sub.verifiedRoot,
|
|
273
|
+
crdtStateVectors: sub.crdtStateVectors,
|
|
274
|
+
status: 'revoked',
|
|
275
|
+
});
|
|
276
|
+
continue;
|
|
262
277
|
}
|
|
263
278
|
|
|
264
279
|
requestScopeCache.set(scopeCacheKey, allowed);
|
|
@@ -272,6 +287,8 @@ export async function resolveEffectiveScopesForSubscriptions<
|
|
|
272
287
|
params: sub.params,
|
|
273
288
|
cursor: sub.cursor,
|
|
274
289
|
bootstrapState: sub.bootstrapState ?? null,
|
|
290
|
+
verifiedRoot: sub.verifiedRoot,
|
|
291
|
+
crdtStateVectors: sub.crdtStateVectors,
|
|
275
292
|
status: 'revoked',
|
|
276
293
|
});
|
|
277
294
|
continue;
|
|
@@ -288,6 +305,26 @@ export async function resolveEffectiveScopesForSubscriptions<
|
|
|
288
305
|
// Intersect with requested scopes
|
|
289
306
|
const effective = intersectScopes(requested, allowed);
|
|
290
307
|
|
|
308
|
+
// If a requested scope key lost all access after intersection,
|
|
309
|
+
// treat the subscription as revoked to avoid partially-scoped leaks.
|
|
310
|
+
const missingRequestedKey = Object.keys(requested).some(
|
|
311
|
+
(key) => !Object.hasOwn(effective, key)
|
|
312
|
+
);
|
|
313
|
+
if (missingRequestedKey) {
|
|
314
|
+
out.push({
|
|
315
|
+
id: sub.id,
|
|
316
|
+
table: sub.table,
|
|
317
|
+
scopes: {},
|
|
318
|
+
params: sub.params,
|
|
319
|
+
cursor: sub.cursor,
|
|
320
|
+
bootstrapState: sub.bootstrapState ?? null,
|
|
321
|
+
verifiedRoot: sub.verifiedRoot,
|
|
322
|
+
crdtStateVectors: sub.crdtStateVectors,
|
|
323
|
+
status: 'revoked',
|
|
324
|
+
});
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
|
|
291
328
|
if (scopesEmpty(effective)) {
|
|
292
329
|
out.push({
|
|
293
330
|
id: sub.id,
|
|
@@ -296,6 +333,8 @@ export async function resolveEffectiveScopesForSubscriptions<
|
|
|
296
333
|
params: sub.params,
|
|
297
334
|
cursor: sub.cursor,
|
|
298
335
|
bootstrapState: sub.bootstrapState ?? null,
|
|
336
|
+
verifiedRoot: sub.verifiedRoot,
|
|
337
|
+
crdtStateVectors: sub.crdtStateVectors,
|
|
299
338
|
status: 'revoked',
|
|
300
339
|
});
|
|
301
340
|
continue;
|
|
@@ -308,6 +347,8 @@ export async function resolveEffectiveScopesForSubscriptions<
|
|
|
308
347
|
params: sub.params,
|
|
309
348
|
cursor: sub.cursor,
|
|
310
349
|
bootstrapState: sub.bootstrapState ?? null,
|
|
350
|
+
verifiedRoot: sub.verifiedRoot,
|
|
351
|
+
crdtStateVectors: sub.crdtStateVectors,
|
|
311
352
|
status: 'active',
|
|
312
353
|
});
|
|
313
354
|
}
|
package/src/sync.ts
CHANGED
|
@@ -3,11 +3,13 @@ import type {
|
|
|
3
3
|
ColumnCodecSource,
|
|
4
4
|
ScopeDefinition,
|
|
5
5
|
} from '@syncular/core';
|
|
6
|
+
import { registerTableOrThrow } from '@syncular/core';
|
|
6
7
|
import {
|
|
7
8
|
type CreateServerHandlerOptions,
|
|
8
9
|
createServerHandler,
|
|
9
10
|
} from './handlers';
|
|
10
11
|
import type { ServerTableHandler, SyncServerAuth } from './handlers/types';
|
|
12
|
+
import type { SyncServerPushPlugin } from './plugins/types';
|
|
11
13
|
import type { SyncCoreDb } from './schema';
|
|
12
14
|
|
|
13
15
|
type SharedTableName<ServerDB, ClientDB> = keyof ServerDB &
|
|
@@ -31,6 +33,7 @@ export interface ServerSyncConfig<
|
|
|
31
33
|
> {
|
|
32
34
|
authenticate: (request: Request) => Promise<Auth | null> | Auth | null;
|
|
33
35
|
handlers: ServerTableHandler<ServerDB, Auth>[];
|
|
36
|
+
plugins?: SyncServerPushPlugin<ServerDB, Auth>[];
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
export interface DefineServerSyncOptions<Auth extends SyncServerAuth> {
|
|
@@ -54,6 +57,8 @@ export interface ServerSyncBuilder<
|
|
|
54
57
|
ScopeDefs
|
|
55
58
|
>
|
|
56
59
|
): this;
|
|
60
|
+
|
|
61
|
+
addPushPlugin(plugin: SyncServerPushPlugin<ServerDB, Auth>): this;
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
export function defineServerSync<
|
|
@@ -65,11 +70,13 @@ export function defineServerSync<
|
|
|
65
70
|
options: DefineServerSyncOptions<Auth>
|
|
66
71
|
): ServerSyncBuilder<ServerDB, ClientDB, ScopeDefs, Auth> {
|
|
67
72
|
const handlers: ServerTableHandler<ServerDB, Auth>[] = [];
|
|
73
|
+
const plugins: SyncServerPushPlugin<ServerDB, Auth>[] = [];
|
|
68
74
|
const registeredTables = new Set<string>();
|
|
69
75
|
|
|
70
76
|
const sync: ServerSyncBuilder<ServerDB, ClientDB, ScopeDefs, Auth> = {
|
|
71
77
|
authenticate: options.authenticate,
|
|
72
78
|
handlers,
|
|
79
|
+
plugins,
|
|
73
80
|
addHandler<TableName extends SharedTableName<ServerDB, ClientDB>>(
|
|
74
81
|
handlerOptions: ServerSyncHandlerOptionsForTable<
|
|
75
82
|
ServerDB,
|
|
@@ -79,11 +86,11 @@ export function defineServerSync<
|
|
|
79
86
|
ScopeDefs
|
|
80
87
|
>
|
|
81
88
|
) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
|
|
89
|
+
registerTableOrThrow(
|
|
90
|
+
registeredTables,
|
|
91
|
+
handlerOptions.table,
|
|
92
|
+
(table) => `Server table handler already registered: ${table}`
|
|
93
|
+
);
|
|
87
94
|
|
|
88
95
|
handlers.push(
|
|
89
96
|
createServerHandler({
|
|
@@ -92,7 +99,10 @@ export function defineServerSync<
|
|
|
92
99
|
codecDialect: options.codecDialect,
|
|
93
100
|
})
|
|
94
101
|
);
|
|
95
|
-
|
|
102
|
+
return sync;
|
|
103
|
+
},
|
|
104
|
+
addPushPlugin(plugin: SyncServerPushPlugin<ServerDB, Auth>) {
|
|
105
|
+
plugins.push(plugin);
|
|
96
106
|
return sync;
|
|
97
107
|
},
|
|
98
108
|
};
|