@syncular/server 0.1.3 → 0.2.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 +773 -13
- package/dist/admin.d.ts +136 -0
- package/dist/admin.js +168 -0
- package/dist/blob-handlers.d.ts +69 -0
- package/dist/blob-handlers.js +245 -0
- package/dist/blob-store.d.ts +111 -0
- package/dist/blob-store.js +0 -0
- package/dist/content-encoding.d.ts +27 -0
- package/dist/content-encoding.js +69 -0
- package/dist/context.d.ts +151 -0
- package/dist/context.js +21 -0
- package/dist/crdt-merger.d.ts +28 -0
- package/dist/crdt-merger.js +11 -0
- package/dist/d1-storage.d.ts +50 -0
- package/dist/d1-storage.js +0 -0
- package/dist/errors.d.ts +35 -9
- package/dist/errors.js +220 -11
- package/dist/events-ring.d.ts +55 -0
- package/dist/events-ring.js +96 -0
- package/dist/events.d.ts +231 -0
- package/dist/events.js +22 -0
- package/dist/frame-bytes.d.ts +20 -0
- package/dist/frame-bytes.js +75 -0
- package/dist/handler.d.ts +9 -0
- package/dist/handler.js +490 -0
- package/dist/index.d.ts +42 -33
- package/dist/index.js +45 -27
- package/dist/lease-store.d.ts +50 -0
- package/dist/lease-store.js +0 -0
- package/dist/pg-executor-pglite.d.ts +27 -0
- package/dist/pg-executor-pglite.js +33 -0
- package/dist/pg-executor.d.ts +67 -0
- package/dist/pg-executor.js +56 -0
- package/dist/postgres-fanout.d.ts +83 -0
- package/dist/postgres-fanout.js +71 -0
- package/dist/postgres-storage.d.ts +69 -0
- package/dist/postgres-storage.js +766 -0
- package/dist/prune.d.ts +24 -39
- package/dist/prune.js +44 -146
- package/dist/pull.d.ts +42 -67
- package/dist/pull.js +387 -1187
- package/dist/push.d.ts +31 -66
- package/dist/push.js +406 -655
- package/dist/realtime.d.ts +197 -0
- package/dist/realtime.js +848 -0
- package/dist/relational-rows.d.ts +229 -0
- package/dist/relational-rows.js +514 -0
- package/dist/s3-blob-store.d.ts +142 -0
- package/dist/s3-blob-store.js +458 -0
- package/dist/s3-segment-store.d.ts +95 -0
- package/dist/s3-segment-store.js +380 -0
- package/dist/schema.d.ts +82 -286
- package/dist/schema.js +133 -9
- package/dist/scopes.d.ts +48 -0
- package/dist/scopes.js +98 -0
- package/dist/segment-download.d.ts +14 -0
- package/dist/segment-download.js +125 -0
- package/dist/segment-store.d.ts +81 -0
- package/dist/segment-store.js +63 -0
- package/dist/signed-url.d.ts +139 -0
- package/dist/signed-url.js +143 -0
- package/dist/sigv4.d.ts +97 -0
- package/dist/sigv4.js +161 -0
- package/dist/sqlite-blob-store.d.ts +22 -0
- package/dist/sqlite-blob-store.js +86 -0
- package/dist/sqlite-dialect.d.ts +101 -0
- package/dist/sqlite-dialect.js +250 -0
- package/dist/sqlite-image.d.ts +27 -0
- package/dist/sqlite-image.js +83 -0
- package/dist/sqlite-lease-store.d.ts +21 -0
- package/dist/sqlite-lease-store.js +94 -0
- package/dist/sqlite-segment-store.d.ts +25 -0
- package/dist/sqlite-segment-store.js +115 -0
- package/dist/sqlite-storage.d.ts +47 -0
- package/dist/sqlite-storage.js +477 -0
- package/dist/storage.d.ts +252 -0
- package/dist/storage.js +1 -0
- package/dist/validate.d.ts +83 -0
- package/dist/validate.js +44 -0
- package/package.json +17 -325
- package/src/admin.ts +312 -0
- package/src/blob-handlers.ts +340 -0
- package/src/blob-store.ts +0 -0
- package/src/content-encoding.ts +94 -0
- package/src/context.ts +176 -0
- package/src/crdt-merger.ts +33 -0
- package/src/d1-storage.ts +0 -0
- package/src/errors.ts +241 -19
- package/src/events-ring.ts +116 -0
- package/src/events.ts +291 -0
- package/src/frame-bytes.ts +94 -0
- package/src/handler.ts +678 -0
- package/src/index.ts +44 -27
- package/src/lease-store.ts +0 -0
- package/src/pg-executor-pglite.ts +63 -0
- package/src/pg-executor.ts +87 -0
- package/src/postgres-fanout.ts +143 -0
- package/src/postgres-storage.ts +1182 -0
- package/src/prune.ts +63 -289
- package/src/pull.ts +505 -1805
- package/src/push.ts +623 -1006
- package/src/realtime.ts +1082 -0
- package/src/relational-rows.ts +633 -0
- package/src/s3-blob-store.ts +616 -0
- package/src/s3-segment-store.ts +519 -0
- package/src/schema.ts +242 -281
- package/src/scopes.ts +127 -0
- package/src/segment-download.ts +169 -0
- package/src/segment-store.ts +154 -0
- package/src/signed-url.ts +308 -0
- package/src/sigv4.ts +267 -0
- package/src/sqlite-blob-store.ts +125 -0
- package/src/sqlite-dialect.ts +337 -0
- package/src/sqlite-image.ts +124 -0
- package/src/sqlite-lease-store.ts +144 -0
- package/src/sqlite-segment-store.ts +204 -0
- package/src/sqlite-storage.ts +792 -0
- package/src/storage.ts +316 -0
- package/src/validate.ts +123 -0
- package/dist/auth-leases.d.ts +0 -85
- package/dist/auth-leases.d.ts.map +0 -1
- package/dist/auth-leases.js +0 -368
- package/dist/auth-leases.js.map +0 -1
- package/dist/better-sqlite3.d.ts +0 -22
- package/dist/better-sqlite3.d.ts.map +0 -1
- package/dist/better-sqlite3.js +0 -16
- package/dist/better-sqlite3.js.map +0 -1
- package/dist/blobs/access.d.ts +0 -35
- package/dist/blobs/access.d.ts.map +0 -1
- package/dist/blobs/access.js +0 -149
- package/dist/blobs/access.js.map +0 -1
- package/dist/blobs/adapters/database.d.ts +0 -100
- package/dist/blobs/adapters/database.d.ts.map +0 -1
- package/dist/blobs/adapters/database.js +0 -247
- package/dist/blobs/adapters/database.js.map +0 -1
- package/dist/blobs/index.d.ts +0 -9
- package/dist/blobs/index.d.ts.map +0 -1
- package/dist/blobs/index.js +0 -9
- package/dist/blobs/index.js.map +0 -1
- package/dist/blobs/manager.d.ts +0 -220
- package/dist/blobs/manager.d.ts.map +0 -1
- package/dist/blobs/manager.js +0 -625
- package/dist/blobs/manager.js.map +0 -1
- package/dist/blobs/migrate.d.ts +0 -27
- package/dist/blobs/migrate.d.ts.map +0 -1
- package/dist/blobs/migrate.js +0 -127
- package/dist/blobs/migrate.js.map +0 -1
- package/dist/blobs/types.d.ts +0 -58
- package/dist/blobs/types.d.ts.map +0 -1
- package/dist/blobs/types.js +0 -5
- package/dist/blobs/types.js.map +0 -1
- package/dist/bun-sqlite.d.ts +0 -19
- package/dist/bun-sqlite.d.ts.map +0 -1
- package/dist/bun-sqlite.js +0 -19
- package/dist/bun-sqlite.js.map +0 -1
- package/dist/clients.d.ts +0 -15
- package/dist/clients.d.ts.map +0 -1
- package/dist/clients.js +0 -7
- package/dist/clients.js.map +0 -1
- package/dist/cloudflare/durable-object.d.ts +0 -93
- package/dist/cloudflare/durable-object.d.ts.map +0 -1
- package/dist/cloudflare/durable-object.js +0 -210
- package/dist/cloudflare/durable-object.js.map +0 -1
- package/dist/cloudflare/index.d.ts +0 -22
- package/dist/cloudflare/index.d.ts.map +0 -1
- package/dist/cloudflare/index.js +0 -22
- package/dist/cloudflare/index.js.map +0 -1
- package/dist/cloudflare/r2.d.ts +0 -180
- package/dist/cloudflare/r2.d.ts.map +0 -1
- package/dist/cloudflare/r2.js +0 -258
- package/dist/cloudflare/r2.js.map +0 -1
- package/dist/cloudflare/scope-cache.d.ts +0 -54
- package/dist/cloudflare/scope-cache.d.ts.map +0 -1
- package/dist/cloudflare/scope-cache.js +0 -223
- package/dist/cloudflare/scope-cache.js.map +0 -1
- package/dist/cloudflare/sentry.d.ts +0 -47
- package/dist/cloudflare/sentry.d.ts.map +0 -1
- package/dist/cloudflare/sentry.js +0 -163
- package/dist/cloudflare/sentry.js.map +0 -1
- package/dist/cloudflare/worker.d.ts +0 -46
- package/dist/cloudflare/worker.d.ts.map +0 -1
- package/dist/cloudflare/worker.js +0 -63
- package/dist/cloudflare/worker.js.map +0 -1
- package/dist/commit-integrity.d.ts +0 -38
- package/dist/commit-integrity.d.ts.map +0 -1
- package/dist/commit-integrity.js +0 -260
- package/dist/commit-integrity.js.map +0 -1
- package/dist/compaction.d.ts +0 -27
- package/dist/compaction.d.ts.map +0 -1
- package/dist/compaction.js +0 -49
- package/dist/compaction.js.map +0 -1
- package/dist/crdt-yjs/index.d.ts +0 -99
- package/dist/crdt-yjs/index.d.ts.map +0 -1
- package/dist/crdt-yjs/index.js +0 -629
- package/dist/crdt-yjs/index.js.map +0 -1
- package/dist/d1.d.ts +0 -13
- package/dist/d1.d.ts.map +0 -1
- package/dist/d1.js +0 -14
- package/dist/d1.js.map +0 -1
- package/dist/dialect/base.d.ts +0 -93
- package/dist/dialect/base.d.ts.map +0 -1
- package/dist/dialect/base.js +0 -181
- package/dist/dialect/base.js.map +0 -1
- package/dist/dialect/helpers.d.ts +0 -16
- package/dist/dialect/helpers.d.ts.map +0 -1
- package/dist/dialect/helpers.js +0 -83
- package/dist/dialect/helpers.js.map +0 -1
- package/dist/dialect/index.d.ts +0 -7
- package/dist/dialect/index.d.ts.map +0 -1
- package/dist/dialect/index.js +0 -7
- package/dist/dialect/index.js.map +0 -1
- package/dist/dialect/types.d.ts +0 -187
- package/dist/dialect/types.d.ts.map +0 -1
- package/dist/dialect/types.js +0 -8
- package/dist/dialect/types.js.map +0 -1
- package/dist/encrypted-crdt.d.ts +0 -67
- package/dist/encrypted-crdt.d.ts.map +0 -1
- package/dist/encrypted-crdt.js +0 -426
- package/dist/encrypted-crdt.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/filesystem/index.d.ts +0 -44
- package/dist/filesystem/index.d.ts.map +0 -1
- package/dist/filesystem/index.js +0 -164
- package/dist/filesystem/index.js.map +0 -1
- package/dist/handlers/collection.d.ts +0 -20
- package/dist/handlers/collection.d.ts.map +0 -1
- package/dist/handlers/collection.js +0 -42
- package/dist/handlers/collection.js.map +0 -1
- package/dist/handlers/create-handler.d.ts +0 -156
- package/dist/handlers/create-handler.d.ts.map +0 -1
- package/dist/handlers/create-handler.js +0 -626
- package/dist/handlers/create-handler.js.map +0 -1
- package/dist/handlers/index.d.ts +0 -4
- package/dist/handlers/index.d.ts.map +0 -1
- package/dist/handlers/index.js +0 -4
- package/dist/handlers/index.js.map +0 -1
- package/dist/handlers/types.d.ts +0 -295
- package/dist/handlers/types.d.ts.map +0 -1
- package/dist/handlers/types.js +0 -2
- package/dist/handlers/types.js.map +0 -1
- package/dist/helpers/conflict.d.ts +0 -52
- package/dist/helpers/conflict.d.ts.map +0 -1
- package/dist/helpers/conflict.js +0 -49
- package/dist/helpers/conflict.js.map +0 -1
- package/dist/helpers/emitted-change.d.ts +0 -56
- package/dist/helpers/emitted-change.d.ts.map +0 -1
- package/dist/helpers/emitted-change.js +0 -46
- package/dist/helpers/emitted-change.js.map +0 -1
- package/dist/helpers/index.d.ts +0 -12
- package/dist/helpers/index.d.ts.map +0 -1
- package/dist/helpers/index.js +0 -12
- package/dist/helpers/index.js.map +0 -1
- package/dist/helpers/paginate.d.ts +0 -49
- package/dist/helpers/paginate.d.ts.map +0 -1
- package/dist/helpers/paginate.js +0 -54
- package/dist/helpers/paginate.js.map +0 -1
- package/dist/helpers/scope-authorization.d.ts +0 -7
- package/dist/helpers/scope-authorization.d.ts.map +0 -1
- package/dist/helpers/scope-authorization.js +0 -19
- package/dist/helpers/scope-authorization.js.map +0 -1
- package/dist/helpers/scope-commit-index.d.ts +0 -12
- package/dist/helpers/scope-commit-index.d.ts.map +0 -1
- package/dist/helpers/scope-commit-index.js +0 -35
- package/dist/helpers/scope-commit-index.js.map +0 -1
- package/dist/helpers/scope-strings.d.ts +0 -74
- package/dist/helpers/scope-strings.d.ts.map +0 -1
- package/dist/helpers/scope-strings.js +0 -82
- package/dist/helpers/scope-strings.js.map +0 -1
- package/dist/hono/api-key-auth.d.ts +0 -49
- package/dist/hono/api-key-auth.d.ts.map +0 -1
- package/dist/hono/api-key-auth.js +0 -108
- package/dist/hono/api-key-auth.js.map +0 -1
- package/dist/hono/audit-redaction.d.ts +0 -20
- package/dist/hono/audit-redaction.d.ts.map +0 -1
- package/dist/hono/audit-redaction.js +0 -85
- package/dist/hono/audit-redaction.js.map +0 -1
- package/dist/hono/blobs.d.ts +0 -75
- package/dist/hono/blobs.d.ts.map +0 -1
- package/dist/hono/blobs.js +0 -586
- package/dist/hono/blobs.js.map +0 -1
- package/dist/hono/console/gateway.d.ts +0 -42
- package/dist/hono/console/gateway.d.ts.map +0 -1
- package/dist/hono/console/gateway.js +0 -2158
- package/dist/hono/console/gateway.js.map +0 -1
- package/dist/hono/console/live-auth.d.ts +0 -7
- package/dist/hono/console/live-auth.d.ts.map +0 -1
- package/dist/hono/console/live-auth.js +0 -39
- package/dist/hono/console/live-auth.js.map +0 -1
- package/dist/hono/console/route-descriptor.d.ts +0 -6
- package/dist/hono/console/route-descriptor.d.ts.map +0 -1
- package/dist/hono/console/route-descriptor.js +0 -16
- package/dist/hono/console/route-descriptor.js.map +0 -1
- package/dist/hono/console/routes/api-keys.d.ts +0 -8
- package/dist/hono/console/routes/api-keys.d.ts.map +0 -1
- package/dist/hono/console/routes/api-keys.js +0 -575
- package/dist/hono/console/routes/api-keys.js.map +0 -1
- package/dist/hono/console/routes/clients.d.ts +0 -8
- package/dist/hono/console/routes/clients.d.ts.map +0 -1
- package/dist/hono/console/routes/clients.js +0 -322
- package/dist/hono/console/routes/clients.js.map +0 -1
- package/dist/hono/console/routes/commits.d.ts +0 -8
- package/dist/hono/console/routes/commits.d.ts.map +0 -1
- package/dist/hono/console/routes/commits.js +0 -882
- package/dist/hono/console/routes/commits.js.map +0 -1
- package/dist/hono/console/routes/context.d.ts +0 -188
- package/dist/hono/console/routes/context.d.ts.map +0 -1
- package/dist/hono/console/routes/context.js +0 -633
- package/dist/hono/console/routes/context.js.map +0 -1
- package/dist/hono/console/routes/events.d.ts +0 -8
- package/dist/hono/console/routes/events.d.ts.map +0 -1
- package/dist/hono/console/routes/events.js +0 -501
- package/dist/hono/console/routes/events.js.map +0 -1
- package/dist/hono/console/routes/maintenance.d.ts +0 -8
- package/dist/hono/console/routes/maintenance.d.ts.map +0 -1
- package/dist/hono/console/routes/maintenance.js +0 -341
- package/dist/hono/console/routes/maintenance.js.map +0 -1
- package/dist/hono/console/routes/shared.d.ts +0 -174
- package/dist/hono/console/routes/shared.d.ts.map +0 -1
- package/dist/hono/console/routes/shared.js +0 -583
- package/dist/hono/console/routes/shared.js.map +0 -1
- package/dist/hono/console/routes/stats.d.ts +0 -8
- package/dist/hono/console/routes/stats.d.ts.map +0 -1
- package/dist/hono/console/routes/stats.js +0 -295
- package/dist/hono/console/routes/stats.js.map +0 -1
- package/dist/hono/console/routes/storage.d.ts +0 -8
- package/dist/hono/console/routes/storage.d.ts.map +0 -1
- package/dist/hono/console/routes/storage.js +0 -121
- package/dist/hono/console/routes/storage.js.map +0 -1
- package/dist/hono/console/routes.d.ts +0 -36
- package/dist/hono/console/routes.d.ts.map +0 -1
- package/dist/hono/console/routes.js +0 -112
- package/dist/hono/console/routes.js.map +0 -1
- package/dist/hono/console/schema-errors.d.ts +0 -2
- package/dist/hono/console/schema-errors.d.ts.map +0 -1
- package/dist/hono/console/schema-errors.js +0 -17
- package/dist/hono/console/schema-errors.js.map +0 -1
- package/dist/hono/console/schemas.d.ts +0 -1515
- package/dist/hono/console/schemas.d.ts.map +0 -1
- package/dist/hono/console/schemas.js +0 -661
- package/dist/hono/console/schemas.js.map +0 -1
- package/dist/hono/console/types.d.ts +0 -213
- package/dist/hono/console/types.d.ts.map +0 -1
- package/dist/hono/console/types.js +0 -2
- package/dist/hono/console/types.js.map +0 -1
- package/dist/hono/console/ui.d.ts +0 -38
- package/dist/hono/console/ui.d.ts.map +0 -1
- package/dist/hono/console/ui.js +0 -43
- package/dist/hono/console/ui.js.map +0 -1
- package/dist/hono/create-server.d.ts +0 -71
- package/dist/hono/create-server.d.ts.map +0 -1
- package/dist/hono/create-server.js +0 -121
- package/dist/hono/create-server.js.map +0 -1
- package/dist/hono/errors.d.ts +0 -13
- package/dist/hono/errors.d.ts.map +0 -1
- package/dist/hono/errors.js +0 -21
- package/dist/hono/errors.js.map +0 -1
- package/dist/hono/index.d.ts +0 -20
- package/dist/hono/index.d.ts.map +0 -1
- package/dist/hono/index.js +0 -31
- package/dist/hono/index.js.map +0 -1
- package/dist/hono/openapi.d.ts +0 -72
- package/dist/hono/openapi.d.ts.map +0 -1
- package/dist/hono/openapi.js +0 -99
- package/dist/hono/openapi.js.map +0 -1
- package/dist/hono/proxy/connection-manager.d.ts +0 -78
- package/dist/hono/proxy/connection-manager.d.ts.map +0 -1
- package/dist/hono/proxy/connection-manager.js +0 -251
- package/dist/hono/proxy/connection-manager.js.map +0 -1
- package/dist/hono/proxy/index.d.ts +0 -8
- package/dist/hono/proxy/index.d.ts.map +0 -1
- package/dist/hono/proxy/index.js +0 -8
- package/dist/hono/proxy/index.js.map +0 -1
- package/dist/hono/proxy/routes.d.ts +0 -86
- package/dist/hono/proxy/routes.d.ts.map +0 -1
- package/dist/hono/proxy/routes.js +0 -183
- package/dist/hono/proxy/routes.js.map +0 -1
- package/dist/hono/rate-limit.d.ts +0 -101
- package/dist/hono/rate-limit.d.ts.map +0 -1
- package/dist/hono/rate-limit.js +0 -184
- package/dist/hono/rate-limit.js.map +0 -1
- package/dist/hono/realtime-sync-packs.d.ts +0 -43
- package/dist/hono/realtime-sync-packs.d.ts.map +0 -1
- package/dist/hono/realtime-sync-packs.js +0 -219
- package/dist/hono/realtime-sync-packs.js.map +0 -1
- package/dist/hono/routes/audit.d.ts +0 -12
- package/dist/hono/routes/audit.d.ts.map +0 -1
- package/dist/hono/routes/audit.js +0 -385
- package/dist/hono/routes/audit.js.map +0 -1
- package/dist/hono/routes/auth-leases.d.ts +0 -8
- package/dist/hono/routes/auth-leases.d.ts.map +0 -1
- package/dist/hono/routes/auth-leases.js +0 -88
- package/dist/hono/routes/auth-leases.js.map +0 -1
- package/dist/hono/routes/combined.d.ts +0 -8
- package/dist/hono/routes/combined.d.ts.map +0 -1
- package/dist/hono/routes/combined.js +0 -392
- package/dist/hono/routes/combined.js.map +0 -1
- package/dist/hono/routes/context.d.ts +0 -314
- package/dist/hono/routes/context.d.ts.map +0 -1
- package/dist/hono/routes/context.js +0 -1147
- package/dist/hono/routes/context.js.map +0 -1
- package/dist/hono/routes/health.d.ts +0 -8
- package/dist/hono/routes/health.d.ts.map +0 -1
- package/dist/hono/routes/health.js +0 -16
- package/dist/hono/routes/health.js.map +0 -1
- package/dist/hono/routes/realtime.d.ts +0 -9
- package/dist/hono/routes/realtime.d.ts.map +0 -1
- package/dist/hono/routes/realtime.js +0 -626
- package/dist/hono/routes/realtime.js.map +0 -1
- package/dist/hono/routes/shared.d.ts +0 -689
- package/dist/hono/routes/shared.d.ts.map +0 -1
- package/dist/hono/routes/shared.js +0 -972
- package/dist/hono/routes/shared.js.map +0 -1
- package/dist/hono/routes/snapshots.d.ts +0 -10
- package/dist/hono/routes/snapshots.d.ts.map +0 -1
- package/dist/hono/routes/snapshots.js +0 -281
- package/dist/hono/routes/snapshots.js.map +0 -1
- package/dist/hono/routes.d.ts +0 -19
- package/dist/hono/routes.d.ts.map +0 -1
- package/dist/hono/routes.js +0 -37
- package/dist/hono/routes.js.map +0 -1
- package/dist/hono/validation.d.ts +0 -5
- package/dist/hono/validation.d.ts.map +0 -1
- package/dist/hono/validation.js +0 -47
- package/dist/hono/validation.js.map +0 -1
- package/dist/hono/websocket-origin.d.ts +0 -9
- package/dist/hono/websocket-origin.d.ts.map +0 -1
- package/dist/hono/websocket-origin.js +0 -96
- package/dist/hono/websocket-origin.js.map +0 -1
- package/dist/hono/ws.d.ts +0 -341
- package/dist/hono/ws.d.ts.map +0 -1
- package/dist/hono/ws.js +0 -711
- package/dist/hono/ws.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/libsql.d.ts +0 -29
- package/dist/libsql.d.ts.map +0 -1
- package/dist/libsql.js +0 -25
- package/dist/libsql.js.map +0 -1
- package/dist/migrate.d.ts +0 -14
- package/dist/migrate.d.ts.map +0 -1
- package/dist/migrate.js +0 -13
- package/dist/migrate.js.map +0 -1
- package/dist/neon.d.ts +0 -21
- package/dist/neon.d.ts.map +0 -1
- package/dist/neon.js +0 -22
- package/dist/neon.js.map +0 -1
- package/dist/notify.d.ts +0 -77
- package/dist/notify.d.ts.map +0 -1
- package/dist/notify.js +0 -233
- package/dist/notify.js.map +0 -1
- package/dist/pglite.d.ts +0 -37
- package/dist/pglite.d.ts.map +0 -1
- package/dist/pglite.js +0 -37
- package/dist/pglite.js.map +0 -1
- package/dist/plugins/index.d.ts +0 -2
- package/dist/plugins/index.d.ts.map +0 -1
- package/dist/plugins/index.js +0 -2
- package/dist/plugins/index.js.map +0 -1
- package/dist/plugins/types.d.ts +0 -73
- package/dist/plugins/types.d.ts.map +0 -1
- package/dist/plugins/types.js +0 -30
- package/dist/plugins/types.js.map +0 -1
- package/dist/postgres/index.d.ts +0 -68
- package/dist/postgres/index.d.ts.map +0 -1
- package/dist/postgres/index.js +0 -924
- package/dist/postgres/index.js.map +0 -1
- package/dist/proxy/collection.d.ts +0 -7
- package/dist/proxy/collection.d.ts.map +0 -1
- package/dist/proxy/collection.js +0 -6
- package/dist/proxy/collection.js.map +0 -1
- package/dist/proxy/handler.d.ts +0 -42
- package/dist/proxy/handler.d.ts.map +0 -1
- package/dist/proxy/handler.js +0 -102
- package/dist/proxy/handler.js.map +0 -1
- package/dist/proxy/index.d.ts +0 -9
- package/dist/proxy/index.d.ts.map +0 -1
- package/dist/proxy/index.js +0 -14
- package/dist/proxy/index.js.map +0 -1
- package/dist/proxy/mutation-detector.d.ts +0 -35
- package/dist/proxy/mutation-detector.d.ts.map +0 -1
- package/dist/proxy/mutation-detector.js +0 -246
- package/dist/proxy/mutation-detector.js.map +0 -1
- package/dist/proxy/oplog.d.ts +0 -30
- package/dist/proxy/oplog.d.ts.map +0 -1
- package/dist/proxy/oplog.js +0 -137
- package/dist/proxy/oplog.js.map +0 -1
- package/dist/proxy/types.d.ts +0 -44
- package/dist/proxy/types.d.ts.map +0 -1
- package/dist/proxy/types.js +0 -7
- package/dist/proxy/types.js.map +0 -1
- package/dist/prune.d.ts.map +0 -1
- package/dist/prune.js.map +0 -1
- package/dist/pull.d.ts.map +0 -1
- package/dist/pull.js.map +0 -1
- package/dist/push.d.ts.map +0 -1
- package/dist/push.js.map +0 -1
- package/dist/realtime/in-memory.d.ts +0 -13
- package/dist/realtime/in-memory.d.ts.map +0 -1
- package/dist/realtime/in-memory.js +0 -28
- package/dist/realtime/in-memory.js.map +0 -1
- package/dist/realtime/index.d.ts +0 -4
- package/dist/realtime/index.d.ts.map +0 -1
- package/dist/realtime/index.js +0 -3
- package/dist/realtime/index.js.map +0 -1
- package/dist/realtime/types.d.ts +0 -62
- package/dist/realtime/types.d.ts.map +0 -1
- package/dist/realtime/types.js +0 -19
- package/dist/realtime/types.js.map +0 -1
- package/dist/relay/client-role/forward-engine.d.ts +0 -63
- package/dist/relay/client-role/forward-engine.d.ts.map +0 -1
- package/dist/relay/client-role/forward-engine.js +0 -267
- package/dist/relay/client-role/forward-engine.js.map +0 -1
- package/dist/relay/client-role/index.d.ts +0 -9
- package/dist/relay/client-role/index.d.ts.map +0 -1
- package/dist/relay/client-role/index.js +0 -9
- package/dist/relay/client-role/index.js.map +0 -1
- package/dist/relay/client-role/pull-engine.d.ts +0 -72
- package/dist/relay/client-role/pull-engine.d.ts.map +0 -1
- package/dist/relay/client-role/pull-engine.js +0 -249
- package/dist/relay/client-role/pull-engine.js.map +0 -1
- package/dist/relay/client-role/sequence-mapper.d.ts +0 -65
- package/dist/relay/client-role/sequence-mapper.d.ts.map +0 -1
- package/dist/relay/client-role/sequence-mapper.js +0 -161
- package/dist/relay/client-role/sequence-mapper.js.map +0 -1
- package/dist/relay/evaluation/relay-paths.d.ts +0 -41
- package/dist/relay/evaluation/relay-paths.d.ts.map +0 -1
- package/dist/relay/evaluation/relay-paths.js +0 -504
- package/dist/relay/evaluation/relay-paths.js.map +0 -1
- package/dist/relay/evaluation/rust-boundary.d.ts +0 -47
- package/dist/relay/evaluation/rust-boundary.d.ts.map +0 -1
- package/dist/relay/evaluation/rust-boundary.js +0 -220
- package/dist/relay/evaluation/rust-boundary.js.map +0 -1
- package/dist/relay/index.d.ts +0 -37
- package/dist/relay/index.d.ts.map +0 -1
- package/dist/relay/index.js +0 -44
- package/dist/relay/index.js.map +0 -1
- package/dist/relay/migrate.d.ts +0 -18
- package/dist/relay/migrate.d.ts.map +0 -1
- package/dist/relay/migrate.js +0 -99
- package/dist/relay/migrate.js.map +0 -1
- package/dist/relay/mode-manager.d.ts +0 -60
- package/dist/relay/mode-manager.d.ts.map +0 -1
- package/dist/relay/mode-manager.js +0 -114
- package/dist/relay/mode-manager.js.map +0 -1
- package/dist/relay/realtime.d.ts +0 -90
- package/dist/relay/realtime.d.ts.map +0 -1
- package/dist/relay/realtime.js +0 -147
- package/dist/relay/realtime.js.map +0 -1
- package/dist/relay/relay.d.ts +0 -190
- package/dist/relay/relay.d.ts.map +0 -1
- package/dist/relay/relay.js +0 -320
- package/dist/relay/relay.js.map +0 -1
- package/dist/relay/schema.d.ts +0 -158
- package/dist/relay/schema.d.ts.map +0 -1
- package/dist/relay/schema.js +0 -7
- package/dist/relay/schema.js.map +0 -1
- package/dist/relay/server-role/index.d.ts +0 -56
- package/dist/relay/server-role/index.d.ts.map +0 -1
- package/dist/relay/server-role/index.js +0 -193
- package/dist/relay/server-role/index.js.map +0 -1
- package/dist/relay/server-role/pull.d.ts +0 -27
- package/dist/relay/server-role/pull.d.ts.map +0 -1
- package/dist/relay/server-role/pull.js +0 -24
- package/dist/relay/server-role/pull.js.map +0 -1
- package/dist/relay/server-role/push.d.ts +0 -29
- package/dist/relay/server-role/push.d.ts.map +0 -1
- package/dist/relay/server-role/push.js +0 -122
- package/dist/relay/server-role/push.js.map +0 -1
- package/dist/s3/index.d.ts +0 -83
- package/dist/s3/index.d.ts.map +0 -1
- package/dist/s3/index.js +0 -223
- package/dist/s3/index.js.map +0 -1
- package/dist/schema.d.ts.map +0 -1
- package/dist/schema.js.map +0 -1
- package/dist/service-worker/index.d.ts +0 -114
- package/dist/service-worker/index.d.ts.map +0 -1
- package/dist/service-worker/index.js +0 -487
- package/dist/service-worker/index.js.map +0 -1
- package/dist/snapshot-artifacts/sqlite-bun.d.ts +0 -15
- package/dist/snapshot-artifacts/sqlite-bun.d.ts.map +0 -1
- package/dist/snapshot-artifacts/sqlite-bun.js +0 -128
- package/dist/snapshot-artifacts/sqlite-bun.js.map +0 -1
- package/dist/snapshot-artifacts.d.ts +0 -206
- package/dist/snapshot-artifacts.d.ts.map +0 -1
- package/dist/snapshot-artifacts.js +0 -545
- package/dist/snapshot-artifacts.js.map +0 -1
- package/dist/snapshot-chunks/db-metadata.d.ts +0 -56
- package/dist/snapshot-chunks/db-metadata.d.ts.map +0 -1
- package/dist/snapshot-chunks/db-metadata.js +0 -360
- package/dist/snapshot-chunks/db-metadata.js.map +0 -1
- package/dist/snapshot-chunks/index.d.ts +0 -8
- package/dist/snapshot-chunks/index.d.ts.map +0 -1
- package/dist/snapshot-chunks/index.js +0 -8
- package/dist/snapshot-chunks/index.js.map +0 -1
- package/dist/snapshot-chunks/types.d.ts +0 -80
- package/dist/snapshot-chunks/types.d.ts.map +0 -1
- package/dist/snapshot-chunks/types.js +0 -8
- package/dist/snapshot-chunks/types.js.map +0 -1
- package/dist/snapshot-chunks.d.ts +0 -90
- package/dist/snapshot-chunks.d.ts.map +0 -1
- package/dist/snapshot-chunks.js +0 -304
- package/dist/snapshot-chunks.js.map +0 -1
- package/dist/sqlite/index.d.ts +0 -53
- package/dist/sqlite/index.d.ts.map +0 -1
- package/dist/sqlite/index.js +0 -795
- package/dist/sqlite/index.js.map +0 -1
- package/dist/sqlite3.d.ts +0 -22
- package/dist/sqlite3.d.ts.map +0 -1
- package/dist/sqlite3.js +0 -99
- package/dist/sqlite3.js.map +0 -1
- package/dist/stats.d.ts +0 -28
- package/dist/stats.d.ts.map +0 -1
- package/dist/stats.js +0 -93
- package/dist/stats.js.map +0 -1
- package/dist/subscriptions/cache.d.ts +0 -58
- package/dist/subscriptions/cache.d.ts.map +0 -1
- package/dist/subscriptions/cache.js +0 -250
- package/dist/subscriptions/cache.js.map +0 -1
- package/dist/subscriptions/index.d.ts +0 -3
- package/dist/subscriptions/index.d.ts.map +0 -1
- package/dist/subscriptions/index.js +0 -3
- package/dist/subscriptions/index.js.map +0 -1
- package/dist/subscriptions/resolve.d.ts +0 -40
- package/dist/subscriptions/resolve.d.ts.map +0 -1
- package/dist/subscriptions/resolve.js +0 -275
- package/dist/subscriptions/resolve.js.map +0 -1
- package/dist/sync.d.ts +0 -24
- package/dist/sync.d.ts.map +0 -1
- package/dist/sync.js +0 -27
- package/dist/sync.js.map +0 -1
- package/src/auth-leases.ts +0 -649
- package/src/better-sqlite3.ts +0 -35
- package/src/blobs/access.ts +0 -244
- package/src/blobs/adapters/database.ts +0 -397
- package/src/blobs/index.ts +0 -9
- package/src/blobs/manager.ts +0 -901
- package/src/blobs/migrate.ts +0 -158
- package/src/blobs/types.ts +0 -74
- package/src/bun-sqlite-ambient.d.ts +0 -19
- package/src/bun-sqlite.ts +0 -27
- package/src/clients.ts +0 -22
- package/src/cloudflare/durable-object.ts +0 -289
- package/src/cloudflare/index.ts +0 -22
- package/src/cloudflare/r2.ts +0 -526
- package/src/cloudflare/scope-cache.ts +0 -341
- package/src/cloudflare/sentry.ts +0 -230
- package/src/cloudflare/worker.ts +0 -77
- package/src/commit-integrity.ts +0 -371
- package/src/compaction.ts +0 -77
- package/src/crdt-yjs/index.ts +0 -931
- package/src/d1.ts +0 -16
- package/src/dialect/base.ts +0 -360
- package/src/dialect/helpers.ts +0 -92
- package/src/dialect/index.ts +0 -7
- package/src/dialect/types.ts +0 -247
- package/src/encrypted-crdt.ts +0 -786
- package/src/filesystem/index.ts +0 -262
- package/src/handlers/collection.ts +0 -121
- package/src/handlers/create-handler.ts +0 -1134
- package/src/handlers/index.ts +0 -3
- package/src/handlers/types.ts +0 -403
- package/src/helpers/conflict.ts +0 -64
- package/src/helpers/emitted-change.ts +0 -69
- package/src/helpers/index.ts +0 -12
- package/src/helpers/paginate.ts +0 -82
- package/src/helpers/scope-authorization.ts +0 -27
- package/src/helpers/scope-commit-index.ts +0 -52
- package/src/helpers/scope-strings.ts +0 -101
- package/src/hono/api-key-auth.ts +0 -177
- package/src/hono/audit-redaction.ts +0 -135
- package/src/hono/blobs.ts +0 -851
- package/src/hono/console/gateway.ts +0 -3046
- package/src/hono/console/live-auth.ts +0 -46
- package/src/hono/console/route-descriptor.ts +0 -22
- package/src/hono/console/routes/api-keys.ts +0 -721
- package/src/hono/console/routes/clients.ts +0 -447
- package/src/hono/console/routes/commits.ts +0 -1137
- package/src/hono/console/routes/context.ts +0 -956
- package/src/hono/console/routes/events.ts +0 -669
- package/src/hono/console/routes/maintenance.ts +0 -461
- package/src/hono/console/routes/shared.ts +0 -816
- package/src/hono/console/routes/stats.ts +0 -392
- package/src/hono/console/routes/storage.ts +0 -159
- package/src/hono/console/routes.ts +0 -146
- package/src/hono/console/schema-errors.ts +0 -23
- package/src/hono/console/schemas.ts +0 -914
- package/src/hono/console/types.ts +0 -223
- package/src/hono/console/ui.ts +0 -100
- package/src/hono/create-server.ts +0 -230
- package/src/hono/errors.ts +0 -50
- package/src/hono/index.ts +0 -54
- package/src/hono/openapi.ts +0 -139
- package/src/hono/proxy/connection-manager.ts +0 -340
- package/src/hono/proxy/index.ts +0 -8
- package/src/hono/proxy/routes.ts +0 -272
- package/src/hono/rate-limit.ts +0 -319
- package/src/hono/realtime-sync-packs.ts +0 -354
- package/src/hono/routes/audit.ts +0 -499
- package/src/hono/routes/auth-leases.ts +0 -119
- package/src/hono/routes/combined.ts +0 -583
- package/src/hono/routes/context.ts +0 -1629
- package/src/hono/routes/health.ts +0 -26
- package/src/hono/routes/realtime.ts +0 -808
- package/src/hono/routes/shared.ts +0 -1626
- package/src/hono/routes/snapshots.ts +0 -345
- package/src/hono/routes.ts +0 -68
- package/src/hono/validation.ts +0 -81
- package/src/hono/websocket-origin.ts +0 -131
- package/src/hono/ws.ts +0 -1134
- package/src/libsql.ts +0 -51
- package/src/migrate.ts +0 -20
- package/src/neon.ts +0 -28
- package/src/notify.ts +0 -341
- package/src/pglite.ts +0 -68
- package/src/plugins/index.ts +0 -1
- package/src/plugins/types.ts +0 -144
- package/src/postgres/index.ts +0 -1291
- package/src/proxy/collection.ts +0 -17
- package/src/proxy/handler.ts +0 -159
- package/src/proxy/index.ts +0 -21
- package/src/proxy/mutation-detector.ts +0 -281
- package/src/proxy/oplog.ts +0 -181
- package/src/proxy/types.ts +0 -46
- package/src/realtime/in-memory.ts +0 -33
- package/src/realtime/index.ts +0 -7
- package/src/realtime/types.ts +0 -90
- package/src/relay/bun-types.d.ts +0 -50
- package/src/relay/client-role/forward-engine.ts +0 -355
- package/src/relay/client-role/index.ts +0 -9
- package/src/relay/client-role/pull-engine.ts +0 -329
- package/src/relay/client-role/sequence-mapper.ts +0 -201
- package/src/relay/evaluation/relay-paths.ts +0 -699
- package/src/relay/evaluation/rust-boundary.ts +0 -464
- package/src/relay/index.ts +0 -50
- package/src/relay/migrate.ts +0 -113
- package/src/relay/mode-manager.ts +0 -142
- package/src/relay/realtime.ts +0 -207
- package/src/relay/relay.ts +0 -431
- package/src/relay/schema.ts +0 -171
- package/src/relay/server-role/index.ts +0 -338
- package/src/relay/server-role/pull.ts +0 -43
- package/src/relay/server-role/push.ts +0 -164
- package/src/s3/index.ts +0 -346
- package/src/service-worker/index.ts +0 -773
- package/src/snapshot-artifacts/sqlite-bun.ts +0 -168
- package/src/snapshot-artifacts.ts +0 -896
- package/src/snapshot-chunks/db-metadata.ts +0 -537
- package/src/snapshot-chunks/index.ts +0 -8
- package/src/snapshot-chunks/types.ts +0 -105
- package/src/snapshot-chunks.ts +0 -453
- package/src/sqlite/index.ts +0 -1064
- package/src/sqlite3.ts +0 -137
- package/src/stats.ts +0 -180
- package/src/subscriptions/cache.ts +0 -376
- package/src/subscriptions/index.ts +0 -2
- package/src/subscriptions/resolve.ts +0 -357
- package/src/sync.ts +0 -111
package/src/scopes.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope semantics (SPEC.md §3) — requested ∩ allowed intersection,
|
|
3
|
+
* revocation, stored-scope extraction, write-path authorization, and the
|
|
4
|
+
* §3.5 scope digest.
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
canonicalScopeJson,
|
|
8
|
+
type RowValue,
|
|
9
|
+
type ScopeMap,
|
|
10
|
+
} from '@syncular/core';
|
|
11
|
+
import type { CompiledTable } from './schema';
|
|
12
|
+
|
|
13
|
+
export type StoredScopes = Record<string, string>;
|
|
14
|
+
|
|
15
|
+
/** Outcome of resolving the host's allowed scopes once per request (§3.4). */
|
|
16
|
+
export type ResolvedScopes =
|
|
17
|
+
| { readonly ok: true; readonly allowed: ScopeMap }
|
|
18
|
+
| { readonly ok: false };
|
|
19
|
+
|
|
20
|
+
export type EffectiveOutcome =
|
|
21
|
+
| { readonly status: 'active'; readonly effective: ScopeMap }
|
|
22
|
+
| { readonly status: 'revoked' };
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Effective = requested ∩ allowed per §3.2 rules 4–5. Inputs are assumed
|
|
26
|
+
* key-validated (requested keys declared, no `'*'` requested values).
|
|
27
|
+
*/
|
|
28
|
+
export function computeEffective(
|
|
29
|
+
requested: ScopeMap,
|
|
30
|
+
resolved: ResolvedScopes,
|
|
31
|
+
): EffectiveOutcome {
|
|
32
|
+
if (!resolved.ok) return { status: 'revoked' };
|
|
33
|
+
const effective: ScopeMap = {};
|
|
34
|
+
const requestedKeys = Object.keys(requested);
|
|
35
|
+
for (const key of requestedKeys) {
|
|
36
|
+
const requestedValues = requested[key] ?? [];
|
|
37
|
+
const allowedValues = resolved.allowed[key];
|
|
38
|
+
if (allowedValues === undefined) return { status: 'revoked' };
|
|
39
|
+
let values: string[];
|
|
40
|
+
if (allowedValues.includes('*')) {
|
|
41
|
+
values = [...requestedValues];
|
|
42
|
+
} else {
|
|
43
|
+
values = requestedValues.filter((v) => allowedValues.includes(v));
|
|
44
|
+
}
|
|
45
|
+
if (values.length === 0) return { status: 'revoked' };
|
|
46
|
+
effective[key] = values;
|
|
47
|
+
}
|
|
48
|
+
if (Object.keys(effective).length === 0) return { status: 'revoked' };
|
|
49
|
+
return { status: 'active', effective };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Render a stored scope column value; `undefined` means missing/empty. */
|
|
53
|
+
export function renderScopeValue(
|
|
54
|
+
value: RowValue | undefined,
|
|
55
|
+
): string | undefined {
|
|
56
|
+
if (value === null || value === undefined) return undefined;
|
|
57
|
+
if (value instanceof Uint8Array) return undefined;
|
|
58
|
+
const rendered = typeof value === 'string' ? value : String(value);
|
|
59
|
+
return rendered.length === 0 ? undefined : rendered;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Extract the stored scopes (§3.1) from a decoded row. Returns the missing
|
|
64
|
+
* variable name when a declared scope column is absent or empty.
|
|
65
|
+
*/
|
|
66
|
+
export function storedScopesForRow(
|
|
67
|
+
table: CompiledTable,
|
|
68
|
+
values: readonly RowValue[],
|
|
69
|
+
): { scopes: StoredScopes } | { missing: string } {
|
|
70
|
+
const scopes: StoredScopes = {};
|
|
71
|
+
for (const pattern of table.scopePatterns) {
|
|
72
|
+
const value = renderScopeValue(values[pattern.columnIndex]);
|
|
73
|
+
if (value === undefined) return { missing: pattern.variable };
|
|
74
|
+
scopes[pattern.variable] = value;
|
|
75
|
+
}
|
|
76
|
+
return { scopes };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Write-path authorization (§3.4 steps 2–3): every declared variable's
|
|
81
|
+
* stored value must be present and allowed (or the allowed list holds
|
|
82
|
+
* `'*'`). All declared keys are required — there is no partial pass.
|
|
83
|
+
*/
|
|
84
|
+
export function authorizeWrite(
|
|
85
|
+
table: CompiledTable,
|
|
86
|
+
rowScopes: StoredScopes,
|
|
87
|
+
resolved: ResolvedScopes,
|
|
88
|
+
): boolean {
|
|
89
|
+
if (!resolved.ok) return false;
|
|
90
|
+
for (const pattern of table.scopePatterns) {
|
|
91
|
+
const value = rowScopes[pattern.variable];
|
|
92
|
+
if (value === undefined || value.length === 0) return false;
|
|
93
|
+
const allowedValues = resolved.allowed[pattern.variable];
|
|
94
|
+
if (allowedValues === undefined) return false;
|
|
95
|
+
if (!allowedValues.includes('*') && !allowedValues.includes(value)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Does a change's stored scopes match the effective scopes (§3.2)? */
|
|
103
|
+
export function matchesEffective(
|
|
104
|
+
storedScopes: StoredScopes,
|
|
105
|
+
effective: ScopeMap,
|
|
106
|
+
): boolean {
|
|
107
|
+
for (const [variable, values] of Object.entries(effective)) {
|
|
108
|
+
const stored = storedScopes[variable];
|
|
109
|
+
if (stored === undefined || !values.includes(stored)) return false;
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function sha256Hex(bytes: Uint8Array): Promise<string> {
|
|
115
|
+
const digest = await crypto.subtle.digest(
|
|
116
|
+
'SHA-256',
|
|
117
|
+
bytes.slice().buffer as ArrayBuffer,
|
|
118
|
+
);
|
|
119
|
+
return [...new Uint8Array(digest)]
|
|
120
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
121
|
+
.join('');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** §3.5: SHA-256 over the canonical JSON of the effective-scope map. */
|
|
125
|
+
export async function scopeDigest(effective: ScopeMap): Promise<string> {
|
|
126
|
+
return sha256Hex(new TextEncoder().encode(canonicalScopeJson(effective)));
|
|
127
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Direct segment download with re-authorization (SPEC.md §5.5).
|
|
3
|
+
*
|
|
4
|
+
* A segment reference is not a bearer capability: every download re-runs
|
|
5
|
+
* `resolveScopes`, recomputes the effective scopes from the supplied
|
|
6
|
+
* `X-Syncular-Scopes` requested map, recomputes the scope digest, and
|
|
7
|
+
* compares it with the segment's stored digest. Mismatch, revoked status,
|
|
8
|
+
* or resolution failure ⇒ `sync.forbidden`.
|
|
9
|
+
*/
|
|
10
|
+
import type { ScopeMap } from '@syncular/core';
|
|
11
|
+
import type { SyncRequestContext } from './context';
|
|
12
|
+
import { clockOf, RESOLVER_OUTAGE } from './context';
|
|
13
|
+
import { SyncError, syncError } from './errors';
|
|
14
|
+
import { emitEvent } from './events';
|
|
15
|
+
import { compileSchema } from './schema';
|
|
16
|
+
import { computeEffective, type ResolvedScopes, scopeDigest } from './scopes';
|
|
17
|
+
import type { SegmentRecord } from './segment-store';
|
|
18
|
+
|
|
19
|
+
export interface SegmentDownloadRequest {
|
|
20
|
+
readonly segmentId: string;
|
|
21
|
+
/** The `X-Syncular-Scopes` header: canonical JSON of the requested map. */
|
|
22
|
+
readonly scopesHeader: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface SegmentDownloadResult {
|
|
26
|
+
readonly record: SegmentRecord;
|
|
27
|
+
readonly bytes: Uint8Array;
|
|
28
|
+
/** Response headers per §5.5. */
|
|
29
|
+
readonly headers: Record<string, string>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function parseScopesHeader(header: string): ScopeMap {
|
|
33
|
+
let parsed: unknown;
|
|
34
|
+
try {
|
|
35
|
+
parsed = JSON.parse(header);
|
|
36
|
+
} catch {
|
|
37
|
+
throw syncError('sync.invalid_request', 'X-Syncular-Scopes is not JSON');
|
|
38
|
+
}
|
|
39
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
40
|
+
throw syncError('sync.invalid_request', 'X-Syncular-Scopes must be a map');
|
|
41
|
+
}
|
|
42
|
+
const scopes: ScopeMap = {};
|
|
43
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
44
|
+
if (
|
|
45
|
+
!Array.isArray(value) ||
|
|
46
|
+
value.some((v: unknown) => typeof v !== 'string')
|
|
47
|
+
) {
|
|
48
|
+
throw syncError(
|
|
49
|
+
'sync.invalid_request',
|
|
50
|
+
'X-Syncular-Scopes values must be string lists (§0)',
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
scopes[key] = value as string[];
|
|
54
|
+
}
|
|
55
|
+
return scopes;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function handleSegmentDownload(
|
|
59
|
+
ctx: SyncRequestContext,
|
|
60
|
+
request: SegmentDownloadRequest,
|
|
61
|
+
): Promise<SegmentDownloadResult> {
|
|
62
|
+
const events = ctx.events;
|
|
63
|
+
if (events === undefined) return downloadSegment(ctx, request);
|
|
64
|
+
const clock = clockOf(ctx);
|
|
65
|
+
const startedAtMs = clock();
|
|
66
|
+
try {
|
|
67
|
+
const result = await downloadSegment(ctx, request);
|
|
68
|
+
emitEvent(events, {
|
|
69
|
+
type: 'segment.downloaded',
|
|
70
|
+
atMs: clock(),
|
|
71
|
+
partition: ctx.partition,
|
|
72
|
+
actorId: ctx.actorId,
|
|
73
|
+
segmentId: request.segmentId,
|
|
74
|
+
outcome: 'ok',
|
|
75
|
+
mediaType: result.record.mediaType,
|
|
76
|
+
bytes: result.bytes.length,
|
|
77
|
+
durationMs: clock() - startedAtMs,
|
|
78
|
+
});
|
|
79
|
+
return result;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
emitEvent(events, {
|
|
82
|
+
type: 'segment.downloaded',
|
|
83
|
+
atMs: clock(),
|
|
84
|
+
partition: ctx.partition,
|
|
85
|
+
actorId: ctx.actorId,
|
|
86
|
+
segmentId: request.segmentId,
|
|
87
|
+
outcome: 'error',
|
|
88
|
+
errorCode: error instanceof SyncError ? error.code : 'internal',
|
|
89
|
+
durationMs: clock() - startedAtMs,
|
|
90
|
+
});
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function downloadSegment(
|
|
96
|
+
ctx: SyncRequestContext,
|
|
97
|
+
request: SegmentDownloadRequest,
|
|
98
|
+
): Promise<SegmentDownloadResult> {
|
|
99
|
+
const entry = await ctx.segments.get(request.segmentId);
|
|
100
|
+
if (entry === undefined || entry.record.partition !== ctx.partition) {
|
|
101
|
+
throw syncError('sync.not_found', 'unknown segment (§5.5)');
|
|
102
|
+
}
|
|
103
|
+
if (entry.record.expiresAtMs <= clockOf(ctx)()) {
|
|
104
|
+
throw syncError(
|
|
105
|
+
'sync.segment_expired',
|
|
106
|
+
'segment TTL elapsed — re-pull to mint fresh descriptors (§5.1)',
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const schema = compileSchema(ctx.schema);
|
|
111
|
+
const table = schema.tables.get(entry.record.table);
|
|
112
|
+
if (table === undefined) {
|
|
113
|
+
throw syncError('sync.not_found', 'segment table no longer served');
|
|
114
|
+
}
|
|
115
|
+
const requested = parseScopesHeader(request.scopesHeader);
|
|
116
|
+
for (const [key, values] of Object.entries(requested)) {
|
|
117
|
+
if (!table.declaredVariables.has(key) || values.includes('*')) {
|
|
118
|
+
throw syncError(
|
|
119
|
+
'sync.invalid_subscription',
|
|
120
|
+
'invalid requested scopes (§3.2)',
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let resolved: ResolvedScopes;
|
|
126
|
+
try {
|
|
127
|
+
const allowed = await ctx.resolveScopes({
|
|
128
|
+
partition: ctx.partition,
|
|
129
|
+
actorId: ctx.actorId,
|
|
130
|
+
});
|
|
131
|
+
// §7.3.3: leases authorize sync rounds, never downloads — an outage
|
|
132
|
+
// signal here denies (re-authorization needs live scopes, §5.5).
|
|
133
|
+
resolved =
|
|
134
|
+
allowed === RESOLVER_OUTAGE ? { ok: false } : { ok: true, allowed };
|
|
135
|
+
} catch (error) {
|
|
136
|
+
const events = ctx.events;
|
|
137
|
+
if (events !== undefined) {
|
|
138
|
+
emitEvent(events, {
|
|
139
|
+
type: 'scopes.resolve_failed',
|
|
140
|
+
atMs: clockOf(ctx)(),
|
|
141
|
+
partition: ctx.partition,
|
|
142
|
+
actorId: ctx.actorId,
|
|
143
|
+
phase: 'segment-download',
|
|
144
|
+
message: error instanceof Error ? error.message : String(error),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
resolved = { ok: false };
|
|
148
|
+
}
|
|
149
|
+
const outcome = computeEffective(requested, resolved);
|
|
150
|
+
if (outcome.status !== 'active') {
|
|
151
|
+
throw syncError('sync.forbidden', 'segment scopes not held (§5.5)');
|
|
152
|
+
}
|
|
153
|
+
const digest = await scopeDigest(outcome.effective);
|
|
154
|
+
if (digest !== entry.record.scopeDigest) {
|
|
155
|
+
throw syncError('sync.forbidden', 'scope digest mismatch (§3.5, §5.5)');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
record: entry.record,
|
|
160
|
+
bytes: entry.bytes,
|
|
161
|
+
headers: {
|
|
162
|
+
'Content-Type': 'application/octet-stream',
|
|
163
|
+
ETag: `"${entry.record.segmentId}"`,
|
|
164
|
+
'Cache-Control': 'private, max-age=0',
|
|
165
|
+
// Accept-Encoding: the body may be served compressed (§5.8).
|
|
166
|
+
Vary: 'Authorization, X-Syncular-Scopes, Accept-Encoding',
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-addressed segment store (SPEC.md §5.1).
|
|
3
|
+
*
|
|
4
|
+
* Segments are cache entries, not durable state: identical bytes share one
|
|
5
|
+
* `segmentId` (`"sha256:" + hex`), entries expire on a TTL (default 24 h),
|
|
6
|
+
* and `get` returns expired records so the download path can distinguish
|
|
7
|
+
* `sync.segment_expired` from `sync.not_found` (§5.5).
|
|
8
|
+
*/
|
|
9
|
+
import { sha256Hex } from './scopes';
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_SEGMENT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
12
|
+
|
|
13
|
+
export interface SegmentMetadata {
|
|
14
|
+
readonly partition: string;
|
|
15
|
+
readonly table: string;
|
|
16
|
+
readonly schemaVersion: number;
|
|
17
|
+
readonly mediaType: 'rows' | 'sqlite';
|
|
18
|
+
readonly scopeDigest: string;
|
|
19
|
+
readonly asOfCommitSeq: number;
|
|
20
|
+
readonly rowCount: number;
|
|
21
|
+
readonly rowCursor: string | null;
|
|
22
|
+
readonly nextRowCursor: string | null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface SegmentRecord extends SegmentMetadata {
|
|
26
|
+
readonly segmentId: string;
|
|
27
|
+
readonly byteLength: number;
|
|
28
|
+
readonly createdAtMs: number;
|
|
29
|
+
readonly expiresAtMs: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The §5.3 reuse key: sqlite images are not byte-deterministic, so
|
|
34
|
+
* cross-client dedup is a metadata lookup, not hash convergence — one
|
|
35
|
+
* stored image per (partition, table, schemaVersion, scope digest, pin).
|
|
36
|
+
*/
|
|
37
|
+
export interface SegmentFindKey {
|
|
38
|
+
readonly partition: string;
|
|
39
|
+
readonly table: string;
|
|
40
|
+
readonly schemaVersion: number;
|
|
41
|
+
readonly mediaType: 'rows' | 'sqlite';
|
|
42
|
+
readonly scopeDigest: string;
|
|
43
|
+
readonly asOfCommitSeq: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Coarse store-level counters for the admin/console read surface (TODO
|
|
48
|
+
* §2.5). Optional — a store that omits `stats()` simply cannot report them.
|
|
49
|
+
* All counts include expired-but-not-yet-evicted entries (the store's own
|
|
50
|
+
* bytes on disk), split by media type.
|
|
51
|
+
*/
|
|
52
|
+
export interface SegmentStoreStats {
|
|
53
|
+
readonly count: number;
|
|
54
|
+
readonly bytes: number;
|
|
55
|
+
readonly rowsSegments: number;
|
|
56
|
+
readonly sqliteSegments: number;
|
|
57
|
+
/**
|
|
58
|
+
* ADDITIVE marker — present and `true` only on stores whose counters are
|
|
59
|
+
* approximate (the S3/R2 store's LIST-free pointer accumulator, which can
|
|
60
|
+
* drift under concurrent writers or after lifecycle GC). Absent on the
|
|
61
|
+
* exact in-process stores (memory/sqlite). The admin surface carries it
|
|
62
|
+
* through so the console can label the numbers honestly.
|
|
63
|
+
*/
|
|
64
|
+
readonly approximate?: boolean;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface SegmentStore {
|
|
68
|
+
put(
|
|
69
|
+
metadata: SegmentMetadata,
|
|
70
|
+
bytes: Uint8Array,
|
|
71
|
+
nowMs: number,
|
|
72
|
+
): Promise<SegmentRecord>;
|
|
73
|
+
/** Returns expired records too — expiry is the caller's check (§5.5). */
|
|
74
|
+
get(
|
|
75
|
+
segmentId: string,
|
|
76
|
+
): Promise<{ record: SegmentRecord; bytes: Uint8Array } | undefined>;
|
|
77
|
+
/**
|
|
78
|
+
* Unexpired record for the §5.3 reuse key (whole-table segments only:
|
|
79
|
+
* `rowCursor` null), or undefined. Servers MUST reuse instead of
|
|
80
|
+
* rebuilding sqlite images while one exists (§5.3).
|
|
81
|
+
*/
|
|
82
|
+
find(key: SegmentFindKey, nowMs: number): Promise<SegmentRecord | undefined>;
|
|
83
|
+
/** Admin/console counters (TODO §2.5) — ADDITIVE, optional. */
|
|
84
|
+
stats?(): Promise<SegmentStoreStats>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function segmentIdFor(bytes: Uint8Array): Promise<string> {
|
|
88
|
+
return `sha256:${await sha256Hex(bytes)}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export class MemorySegmentStore implements SegmentStore {
|
|
92
|
+
#ttlMs: number;
|
|
93
|
+
#entries = new Map<string, { record: SegmentRecord; bytes: Uint8Array }>();
|
|
94
|
+
|
|
95
|
+
constructor(options?: { ttlMs?: number }) {
|
|
96
|
+
this.#ttlMs = options?.ttlMs ?? DEFAULT_SEGMENT_TTL_MS;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async put(
|
|
100
|
+
metadata: SegmentMetadata,
|
|
101
|
+
bytes: Uint8Array,
|
|
102
|
+
nowMs: number,
|
|
103
|
+
): Promise<SegmentRecord> {
|
|
104
|
+
const segmentId = await segmentIdFor(bytes);
|
|
105
|
+
const record: SegmentRecord = {
|
|
106
|
+
...metadata,
|
|
107
|
+
segmentId,
|
|
108
|
+
byteLength: bytes.length,
|
|
109
|
+
createdAtMs: nowMs,
|
|
110
|
+
expiresAtMs: nowMs + this.#ttlMs,
|
|
111
|
+
};
|
|
112
|
+
this.#entries.set(segmentId, { record, bytes });
|
|
113
|
+
return record;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async get(
|
|
117
|
+
segmentId: string,
|
|
118
|
+
): Promise<{ record: SegmentRecord; bytes: Uint8Array } | undefined> {
|
|
119
|
+
return this.#entries.get(segmentId);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async find(
|
|
123
|
+
key: SegmentFindKey,
|
|
124
|
+
nowMs: number,
|
|
125
|
+
): Promise<SegmentRecord | undefined> {
|
|
126
|
+
for (const { record } of this.#entries.values()) {
|
|
127
|
+
if (
|
|
128
|
+
record.partition === key.partition &&
|
|
129
|
+
record.table === key.table &&
|
|
130
|
+
record.schemaVersion === key.schemaVersion &&
|
|
131
|
+
record.mediaType === key.mediaType &&
|
|
132
|
+
record.scopeDigest === key.scopeDigest &&
|
|
133
|
+
record.asOfCommitSeq === key.asOfCommitSeq &&
|
|
134
|
+
record.rowCursor === null &&
|
|
135
|
+
record.expiresAtMs > nowMs
|
|
136
|
+
) {
|
|
137
|
+
return record;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async stats(): Promise<SegmentStoreStats> {
|
|
144
|
+
let bytes = 0;
|
|
145
|
+
let rowsSegments = 0;
|
|
146
|
+
let sqliteSegments = 0;
|
|
147
|
+
for (const { record } of this.#entries.values()) {
|
|
148
|
+
bytes += record.byteLength;
|
|
149
|
+
if (record.mediaType === 'sqlite') sqliteSegments += 1;
|
|
150
|
+
else rowsSegments += 1;
|
|
151
|
+
}
|
|
152
|
+
return { count: this.#entries.size, bytes, rowsSegments, sqliteSegments };
|
|
153
|
+
}
|
|
154
|
+
}
|