@syncular/server 0.0.6-95 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/dist/auth-leases.d.ts +85 -0
- package/dist/auth-leases.d.ts.map +1 -0
- package/dist/auth-leases.js +368 -0
- package/dist/auth-leases.js.map +1 -0
- package/dist/better-sqlite3.d.ts +22 -0
- package/dist/better-sqlite3.d.ts.map +1 -0
- package/dist/better-sqlite3.js +16 -0
- package/dist/better-sqlite3.js.map +1 -0
- package/dist/blobs/access.d.ts +35 -0
- package/dist/blobs/access.d.ts.map +1 -0
- package/dist/blobs/access.js +149 -0
- package/dist/blobs/access.js.map +1 -0
- package/dist/blobs/adapters/database.d.ts +26 -9
- package/dist/blobs/adapters/database.d.ts.map +1 -1
- package/dist/blobs/adapters/database.js +68 -23
- package/dist/blobs/adapters/database.js.map +1 -1
- package/dist/blobs/index.d.ts +1 -0
- package/dist/blobs/index.d.ts.map +1 -1
- package/dist/blobs/index.js +5 -4
- package/dist/blobs/index.js.map +1 -1
- package/dist/blobs/manager.d.ts +69 -44
- package/dist/blobs/manager.d.ts.map +1 -1
- package/dist/blobs/manager.js +250 -65
- package/dist/blobs/manager.js.map +1 -1
- package/dist/blobs/migrate.d.ts.map +1 -1
- package/dist/blobs/migrate.js +16 -8
- package/dist/blobs/migrate.js.map +1 -1
- package/dist/blobs/types.d.ts +4 -0
- package/dist/blobs/types.d.ts.map +1 -1
- package/dist/bun-sqlite.d.ts +19 -0
- package/dist/bun-sqlite.d.ts.map +1 -0
- package/dist/bun-sqlite.js +19 -0
- package/dist/bun-sqlite.js.map +1 -0
- package/dist/clients.d.ts +1 -0
- package/dist/clients.d.ts.map +1 -1
- package/dist/clients.js.map +1 -1
- package/dist/cloudflare/durable-object.d.ts +93 -0
- package/dist/cloudflare/durable-object.d.ts.map +1 -0
- package/dist/cloudflare/durable-object.js +210 -0
- package/dist/cloudflare/durable-object.js.map +1 -0
- package/dist/cloudflare/index.d.ts +22 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +22 -0
- package/dist/cloudflare/index.js.map +1 -0
- package/dist/cloudflare/r2.d.ts +180 -0
- package/dist/cloudflare/r2.d.ts.map +1 -0
- package/dist/cloudflare/r2.js +258 -0
- package/dist/cloudflare/r2.js.map +1 -0
- package/dist/cloudflare/scope-cache.d.ts +54 -0
- package/dist/cloudflare/scope-cache.d.ts.map +1 -0
- package/dist/cloudflare/scope-cache.js +223 -0
- package/dist/cloudflare/scope-cache.js.map +1 -0
- package/dist/cloudflare/sentry.d.ts +47 -0
- package/dist/cloudflare/sentry.d.ts.map +1 -0
- package/dist/cloudflare/sentry.js +163 -0
- package/dist/cloudflare/sentry.js.map +1 -0
- package/dist/cloudflare/worker.d.ts +46 -0
- package/dist/cloudflare/worker.d.ts.map +1 -0
- package/dist/cloudflare/worker.js +63 -0
- package/dist/cloudflare/worker.js.map +1 -0
- package/dist/commit-integrity.d.ts +38 -0
- package/dist/commit-integrity.d.ts.map +1 -0
- package/dist/commit-integrity.js +260 -0
- package/dist/commit-integrity.js.map +1 -0
- package/dist/compaction.js.map +1 -1
- package/dist/crdt-yjs/index.d.ts +99 -0
- package/dist/crdt-yjs/index.d.ts.map +1 -0
- package/dist/crdt-yjs/index.js +629 -0
- package/dist/crdt-yjs/index.js.map +1 -0
- package/dist/d1.d.ts +13 -0
- package/dist/d1.d.ts.map +1 -0
- package/dist/d1.js +14 -0
- package/dist/d1.js.map +1 -0
- package/dist/dialect/base.d.ts +11 -1
- package/dist/dialect/base.d.ts.map +1 -1
- package/dist/dialect/base.js +43 -6
- package/dist/dialect/base.js.map +1 -1
- package/dist/dialect/helpers.d.ts +6 -0
- package/dist/dialect/helpers.d.ts.map +1 -1
- package/dist/dialect/helpers.js +24 -0
- package/dist/dialect/helpers.js.map +1 -1
- package/dist/dialect/index.js +3 -3
- package/dist/dialect/types.d.ts +40 -0
- package/dist/dialect/types.d.ts.map +1 -1
- package/dist/encrypted-crdt.d.ts +67 -0
- package/dist/encrypted-crdt.d.ts.map +1 -0
- package/dist/encrypted-crdt.js +426 -0
- package/dist/encrypted-crdt.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -0
- package/dist/filesystem/index.d.ts +44 -0
- package/dist/filesystem/index.d.ts.map +1 -0
- package/dist/filesystem/index.js +164 -0
- package/dist/filesystem/index.js.map +1 -0
- package/dist/handlers/collection.d.ts +11 -3
- package/dist/handlers/collection.d.ts.map +1 -1
- package/dist/handlers/collection.js +34 -56
- package/dist/handlers/collection.js.map +1 -1
- package/dist/handlers/create-handler.d.ts +31 -7
- package/dist/handlers/create-handler.d.ts.map +1 -1
- package/dist/handlers/create-handler.js +332 -115
- package/dist/handlers/create-handler.js.map +1 -1
- package/dist/handlers/index.js +3 -3
- package/dist/handlers/types.d.ts +86 -1
- package/dist/handlers/types.d.ts.map +1 -1
- package/dist/helpers/conflict.js.map +1 -1
- package/dist/helpers/emitted-change.js.map +1 -1
- package/dist/helpers/index.d.ts +2 -0
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +6 -4
- package/dist/helpers/index.js.map +1 -1
- package/dist/helpers/paginate.js.map +1 -1
- package/dist/helpers/scope-authorization.d.ts +7 -0
- package/dist/helpers/scope-authorization.d.ts.map +1 -0
- package/dist/helpers/scope-authorization.js +19 -0
- package/dist/helpers/scope-authorization.js.map +1 -0
- package/dist/helpers/scope-commit-index.d.ts +12 -0
- package/dist/helpers/scope-commit-index.d.ts.map +1 -0
- package/dist/helpers/scope-commit-index.js +35 -0
- package/dist/helpers/scope-commit-index.js.map +1 -0
- package/dist/helpers/scope-strings.js.map +1 -1
- package/dist/hono/api-key-auth.d.ts +49 -0
- package/dist/hono/api-key-auth.d.ts.map +1 -0
- package/dist/hono/api-key-auth.js +108 -0
- package/dist/hono/api-key-auth.js.map +1 -0
- package/dist/hono/audit-redaction.d.ts +20 -0
- package/dist/hono/audit-redaction.d.ts.map +1 -0
- package/dist/hono/audit-redaction.js +85 -0
- package/dist/hono/audit-redaction.js.map +1 -0
- package/dist/hono/blobs.d.ts +75 -0
- package/dist/hono/blobs.d.ts.map +1 -0
- package/dist/hono/blobs.js +586 -0
- package/dist/hono/blobs.js.map +1 -0
- package/dist/hono/console/gateway.d.ts +42 -0
- package/dist/hono/console/gateway.d.ts.map +1 -0
- package/dist/hono/console/gateway.js +2158 -0
- package/dist/hono/console/gateway.js.map +1 -0
- package/dist/hono/console/live-auth.d.ts +7 -0
- package/dist/hono/console/live-auth.d.ts.map +1 -0
- package/dist/hono/console/live-auth.js +39 -0
- package/dist/hono/console/live-auth.js.map +1 -0
- package/dist/hono/console/route-descriptor.d.ts +6 -0
- package/dist/hono/console/route-descriptor.d.ts.map +1 -0
- package/dist/hono/console/route-descriptor.js +16 -0
- package/dist/hono/console/route-descriptor.js.map +1 -0
- package/dist/hono/console/routes/api-keys.d.ts +8 -0
- package/dist/hono/console/routes/api-keys.d.ts.map +1 -0
- package/dist/hono/console/routes/api-keys.js +575 -0
- package/dist/hono/console/routes/api-keys.js.map +1 -0
- package/dist/hono/console/routes/clients.d.ts +8 -0
- package/dist/hono/console/routes/clients.d.ts.map +1 -0
- package/dist/hono/console/routes/clients.js +322 -0
- package/dist/hono/console/routes/clients.js.map +1 -0
- package/dist/hono/console/routes/commits.d.ts +8 -0
- package/dist/hono/console/routes/commits.d.ts.map +1 -0
- package/dist/hono/console/routes/commits.js +882 -0
- package/dist/hono/console/routes/commits.js.map +1 -0
- package/dist/hono/console/routes/context.d.ts +188 -0
- package/dist/hono/console/routes/context.d.ts.map +1 -0
- package/dist/hono/console/routes/context.js +633 -0
- package/dist/hono/console/routes/context.js.map +1 -0
- package/dist/hono/console/routes/events.d.ts +8 -0
- package/dist/hono/console/routes/events.d.ts.map +1 -0
- package/dist/hono/console/routes/events.js +501 -0
- package/dist/hono/console/routes/events.js.map +1 -0
- package/dist/hono/console/routes/maintenance.d.ts +8 -0
- package/dist/hono/console/routes/maintenance.d.ts.map +1 -0
- package/dist/hono/console/routes/maintenance.js +341 -0
- package/dist/hono/console/routes/maintenance.js.map +1 -0
- package/dist/hono/console/routes/shared.d.ts +174 -0
- package/dist/hono/console/routes/shared.d.ts.map +1 -0
- package/dist/hono/console/routes/shared.js +583 -0
- package/dist/hono/console/routes/shared.js.map +1 -0
- package/dist/hono/console/routes/stats.d.ts +8 -0
- package/dist/hono/console/routes/stats.d.ts.map +1 -0
- package/dist/hono/console/routes/stats.js +295 -0
- package/dist/hono/console/routes/stats.js.map +1 -0
- package/dist/hono/console/routes/storage.d.ts +8 -0
- package/dist/hono/console/routes/storage.d.ts.map +1 -0
- package/dist/hono/console/routes/storage.js +121 -0
- package/dist/hono/console/routes/storage.js.map +1 -0
- package/dist/hono/console/routes.d.ts +36 -0
- package/dist/hono/console/routes.d.ts.map +1 -0
- package/dist/hono/console/routes.js +112 -0
- package/dist/hono/console/routes.js.map +1 -0
- package/dist/hono/console/schema-errors.d.ts +2 -0
- package/dist/hono/console/schema-errors.d.ts.map +1 -0
- package/dist/hono/console/schema-errors.js +17 -0
- package/dist/hono/console/schema-errors.js.map +1 -0
- package/dist/hono/console/schemas.d.ts +1515 -0
- package/dist/hono/console/schemas.d.ts.map +1 -0
- package/dist/hono/console/schemas.js +661 -0
- package/dist/hono/console/schemas.js.map +1 -0
- package/dist/hono/console/types.d.ts +213 -0
- package/dist/hono/console/types.d.ts.map +1 -0
- package/dist/hono/console/types.js +2 -0
- package/dist/hono/console/types.js.map +1 -0
- package/dist/hono/console/ui.d.ts +38 -0
- package/dist/hono/console/ui.d.ts.map +1 -0
- package/dist/hono/console/ui.js +43 -0
- package/dist/hono/console/ui.js.map +1 -0
- package/dist/hono/create-server.d.ts +71 -0
- package/dist/hono/create-server.d.ts.map +1 -0
- package/dist/hono/create-server.js +121 -0
- package/dist/hono/create-server.js.map +1 -0
- package/dist/hono/errors.d.ts +13 -0
- package/dist/hono/errors.d.ts.map +1 -0
- package/dist/hono/errors.js +21 -0
- package/dist/hono/errors.js.map +1 -0
- package/dist/hono/index.d.ts +20 -0
- package/dist/hono/index.d.ts.map +1 -0
- package/dist/hono/index.js +31 -0
- package/dist/hono/index.js.map +1 -0
- package/dist/hono/openapi.d.ts +72 -0
- package/dist/hono/openapi.d.ts.map +1 -0
- package/dist/hono/openapi.js +99 -0
- package/dist/hono/openapi.js.map +1 -0
- package/dist/hono/proxy/connection-manager.d.ts +78 -0
- package/dist/hono/proxy/connection-manager.d.ts.map +1 -0
- package/dist/hono/proxy/connection-manager.js +251 -0
- package/dist/hono/proxy/connection-manager.js.map +1 -0
- package/dist/hono/proxy/index.d.ts +8 -0
- package/dist/hono/proxy/index.d.ts.map +1 -0
- package/dist/hono/proxy/index.js +8 -0
- package/dist/hono/proxy/index.js.map +1 -0
- package/dist/hono/proxy/routes.d.ts +86 -0
- package/dist/hono/proxy/routes.d.ts.map +1 -0
- package/dist/hono/proxy/routes.js +183 -0
- package/dist/hono/proxy/routes.js.map +1 -0
- package/dist/hono/rate-limit.d.ts +101 -0
- package/dist/hono/rate-limit.d.ts.map +1 -0
- package/dist/hono/rate-limit.js +184 -0
- package/dist/hono/rate-limit.js.map +1 -0
- package/dist/hono/realtime-sync-packs.d.ts +43 -0
- package/dist/hono/realtime-sync-packs.d.ts.map +1 -0
- package/dist/hono/realtime-sync-packs.js +219 -0
- package/dist/hono/realtime-sync-packs.js.map +1 -0
- package/dist/hono/routes/audit.d.ts +12 -0
- package/dist/hono/routes/audit.d.ts.map +1 -0
- package/dist/hono/routes/audit.js +385 -0
- package/dist/hono/routes/audit.js.map +1 -0
- package/dist/hono/routes/auth-leases.d.ts +8 -0
- package/dist/hono/routes/auth-leases.d.ts.map +1 -0
- package/dist/hono/routes/auth-leases.js +88 -0
- package/dist/hono/routes/auth-leases.js.map +1 -0
- package/dist/hono/routes/combined.d.ts +8 -0
- package/dist/hono/routes/combined.d.ts.map +1 -0
- package/dist/hono/routes/combined.js +392 -0
- package/dist/hono/routes/combined.js.map +1 -0
- package/dist/hono/routes/context.d.ts +314 -0
- package/dist/hono/routes/context.d.ts.map +1 -0
- package/dist/hono/routes/context.js +1147 -0
- package/dist/hono/routes/context.js.map +1 -0
- package/dist/hono/routes/health.d.ts +8 -0
- package/dist/hono/routes/health.d.ts.map +1 -0
- package/dist/hono/routes/health.js +16 -0
- package/dist/hono/routes/health.js.map +1 -0
- package/dist/hono/routes/realtime.d.ts +9 -0
- package/dist/hono/routes/realtime.d.ts.map +1 -0
- package/dist/hono/routes/realtime.js +626 -0
- package/dist/hono/routes/realtime.js.map +1 -0
- package/dist/hono/routes/shared.d.ts +689 -0
- package/dist/hono/routes/shared.d.ts.map +1 -0
- package/dist/hono/routes/shared.js +972 -0
- package/dist/hono/routes/shared.js.map +1 -0
- package/dist/hono/routes/snapshots.d.ts +10 -0
- package/dist/hono/routes/snapshots.d.ts.map +1 -0
- package/dist/hono/routes/snapshots.js +281 -0
- package/dist/hono/routes/snapshots.js.map +1 -0
- package/dist/hono/routes.d.ts +19 -0
- package/dist/hono/routes.d.ts.map +1 -0
- package/dist/hono/routes.js +37 -0
- package/dist/hono/routes.js.map +1 -0
- package/dist/hono/validation.d.ts +5 -0
- package/dist/hono/validation.d.ts.map +1 -0
- package/dist/hono/validation.js +47 -0
- package/dist/hono/validation.js.map +1 -0
- package/dist/hono/websocket-origin.d.ts +9 -0
- package/dist/hono/websocket-origin.d.ts.map +1 -0
- package/dist/hono/websocket-origin.js +96 -0
- package/dist/hono/websocket-origin.js.map +1 -0
- package/dist/hono/ws.d.ts +341 -0
- package/dist/hono/ws.d.ts.map +1 -0
- package/dist/hono/ws.js +711 -0
- package/dist/hono/ws.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -18
- package/dist/index.js.map +1 -1
- package/dist/libsql.d.ts +29 -0
- package/dist/libsql.d.ts.map +1 -0
- package/dist/libsql.js +25 -0
- package/dist/libsql.js.map +1 -0
- package/dist/migrate.js.map +1 -1
- package/dist/neon.d.ts +21 -0
- package/dist/neon.d.ts.map +1 -0
- package/dist/neon.js +22 -0
- package/dist/neon.js.map +1 -0
- package/dist/notify.d.ts +30 -0
- package/dist/notify.d.ts.map +1 -1
- package/dist/notify.js +160 -41
- package/dist/notify.js.map +1 -1
- package/dist/pglite.d.ts +37 -0
- package/dist/pglite.d.ts.map +1 -0
- package/dist/pglite.js +37 -0
- package/dist/pglite.js.map +1 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +2 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/types.d.ts +73 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +30 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/postgres/index.d.ts +68 -0
- package/dist/postgres/index.d.ts.map +1 -0
- package/dist/postgres/index.js +924 -0
- package/dist/postgres/index.js.map +1 -0
- package/dist/proxy/collection.d.ts +0 -2
- package/dist/proxy/collection.d.ts.map +1 -1
- package/dist/proxy/collection.js +2 -17
- package/dist/proxy/collection.js.map +1 -1
- package/dist/proxy/handler.d.ts +1 -1
- package/dist/proxy/handler.d.ts.map +1 -1
- package/dist/proxy/handler.js +3 -4
- package/dist/proxy/handler.js.map +1 -1
- package/dist/proxy/index.d.ts +1 -1
- package/dist/proxy/index.d.ts.map +1 -1
- package/dist/proxy/index.js +3 -3
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/mutation-detector.js.map +1 -1
- package/dist/proxy/oplog.d.ts.map +1 -1
- package/dist/proxy/oplog.js +32 -8
- package/dist/proxy/oplog.js.map +1 -1
- package/dist/prune.d.ts +8 -1
- package/dist/prune.d.ts.map +1 -1
- package/dist/prune.js +68 -28
- package/dist/prune.js.map +1 -1
- package/dist/pull.d.ts +31 -0
- package/dist/pull.d.ts.map +1 -1
- package/dist/pull.js +1014 -474
- package/dist/pull.js.map +1 -1
- package/dist/push.d.ts +36 -2
- package/dist/push.d.ts.map +1 -1
- package/dist/push.js +603 -358
- package/dist/push.js.map +1 -1
- package/dist/realtime/in-memory.js.map +1 -1
- package/dist/realtime/index.d.ts +2 -1
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +2 -1
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime/types.d.ts +12 -0
- package/dist/realtime/types.d.ts.map +1 -1
- package/dist/realtime/types.js +13 -1
- package/dist/realtime/types.js.map +1 -1
- package/dist/relay/client-role/forward-engine.d.ts +63 -0
- package/dist/relay/client-role/forward-engine.d.ts.map +1 -0
- package/dist/relay/client-role/forward-engine.js +267 -0
- package/dist/relay/client-role/forward-engine.js.map +1 -0
- package/dist/relay/client-role/index.d.ts +9 -0
- package/dist/relay/client-role/index.d.ts.map +1 -0
- package/dist/relay/client-role/index.js +9 -0
- package/dist/relay/client-role/index.js.map +1 -0
- package/dist/relay/client-role/pull-engine.d.ts +72 -0
- package/dist/relay/client-role/pull-engine.d.ts.map +1 -0
- package/dist/relay/client-role/pull-engine.js +249 -0
- package/dist/relay/client-role/pull-engine.js.map +1 -0
- package/dist/relay/client-role/sequence-mapper.d.ts +65 -0
- package/dist/relay/client-role/sequence-mapper.d.ts.map +1 -0
- package/dist/relay/client-role/sequence-mapper.js +161 -0
- package/dist/relay/client-role/sequence-mapper.js.map +1 -0
- package/dist/relay/evaluation/relay-paths.d.ts +41 -0
- package/dist/relay/evaluation/relay-paths.d.ts.map +1 -0
- package/dist/relay/evaluation/relay-paths.js +504 -0
- package/dist/relay/evaluation/relay-paths.js.map +1 -0
- package/dist/relay/evaluation/rust-boundary.d.ts +47 -0
- package/dist/relay/evaluation/rust-boundary.d.ts.map +1 -0
- package/dist/relay/evaluation/rust-boundary.js +220 -0
- package/dist/relay/evaluation/rust-boundary.js.map +1 -0
- package/dist/relay/index.d.ts +37 -0
- package/dist/relay/index.d.ts.map +1 -0
- package/dist/relay/index.js +44 -0
- package/dist/relay/index.js.map +1 -0
- package/dist/relay/migrate.d.ts +18 -0
- package/dist/relay/migrate.d.ts.map +1 -0
- package/dist/relay/migrate.js +99 -0
- package/dist/relay/migrate.js.map +1 -0
- package/dist/relay/mode-manager.d.ts +60 -0
- package/dist/relay/mode-manager.d.ts.map +1 -0
- package/dist/relay/mode-manager.js +114 -0
- package/dist/relay/mode-manager.js.map +1 -0
- package/dist/relay/realtime.d.ts +90 -0
- package/dist/relay/realtime.d.ts.map +1 -0
- package/dist/relay/realtime.js +147 -0
- package/dist/relay/realtime.js.map +1 -0
- package/dist/relay/relay.d.ts +190 -0
- package/dist/relay/relay.d.ts.map +1 -0
- package/dist/relay/relay.js +320 -0
- package/dist/relay/relay.js.map +1 -0
- package/dist/relay/schema.d.ts +158 -0
- package/dist/relay/schema.d.ts.map +1 -0
- package/dist/relay/schema.js +7 -0
- package/dist/relay/schema.js.map +1 -0
- package/dist/relay/server-role/index.d.ts +56 -0
- package/dist/relay/server-role/index.d.ts.map +1 -0
- package/dist/relay/server-role/index.js +193 -0
- package/dist/relay/server-role/index.js.map +1 -0
- package/dist/relay/server-role/pull.d.ts +27 -0
- package/dist/relay/server-role/pull.d.ts.map +1 -0
- package/dist/relay/server-role/pull.js +24 -0
- package/dist/relay/server-role/pull.js.map +1 -0
- package/dist/relay/server-role/push.d.ts +29 -0
- package/dist/relay/server-role/push.d.ts.map +1 -0
- package/dist/relay/server-role/push.js +122 -0
- package/dist/relay/server-role/push.js.map +1 -0
- package/dist/s3/index.d.ts +83 -0
- package/dist/s3/index.d.ts.map +1 -0
- package/dist/s3/index.js +223 -0
- package/dist/s3/index.js.map +1 -0
- package/dist/schema.d.ts +137 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +1 -0
- package/dist/schema.js.map +1 -1
- package/dist/service-worker/index.d.ts +114 -0
- package/dist/service-worker/index.d.ts.map +1 -0
- package/dist/service-worker/index.js +487 -0
- package/dist/service-worker/index.js.map +1 -0
- package/dist/snapshot-artifacts/sqlite-bun.d.ts +15 -0
- package/dist/snapshot-artifacts/sqlite-bun.d.ts.map +1 -0
- package/dist/snapshot-artifacts/sqlite-bun.js +128 -0
- package/dist/snapshot-artifacts/sqlite-bun.js.map +1 -0
- package/dist/snapshot-artifacts.d.ts +206 -0
- package/dist/snapshot-artifacts.d.ts.map +1 -0
- package/dist/snapshot-artifacts.js +545 -0
- package/dist/snapshot-artifacts.js.map +1 -0
- package/dist/snapshot-chunks/db-metadata.d.ts +18 -0
- package/dist/snapshot-chunks/db-metadata.d.ts.map +1 -1
- package/dist/snapshot-chunks/db-metadata.js +91 -63
- package/dist/snapshot-chunks/db-metadata.js.map +1 -1
- package/dist/snapshot-chunks/index.js +2 -2
- package/dist/snapshot-chunks/types.d.ts +2 -0
- package/dist/snapshot-chunks/types.d.ts.map +1 -1
- package/dist/snapshot-chunks.d.ts +33 -3
- package/dist/snapshot-chunks.d.ts.map +1 -1
- package/dist/snapshot-chunks.js +136 -55
- package/dist/snapshot-chunks.js.map +1 -1
- package/dist/sqlite/index.d.ts +53 -0
- package/dist/sqlite/index.d.ts.map +1 -0
- package/dist/sqlite/index.js +795 -0
- package/dist/sqlite/index.js.map +1 -0
- package/dist/sqlite3.d.ts +22 -0
- package/dist/sqlite3.d.ts.map +1 -0
- package/dist/sqlite3.js +99 -0
- package/dist/sqlite3.js.map +1 -0
- package/dist/stats.d.ts +8 -0
- package/dist/stats.d.ts.map +1 -1
- package/dist/stats.js +45 -13
- package/dist/stats.js.map +1 -1
- package/dist/subscriptions/cache.d.ts +3 -0
- package/dist/subscriptions/cache.d.ts.map +1 -1
- package/dist/subscriptions/cache.js +44 -0
- package/dist/subscriptions/cache.js.map +1 -1
- package/dist/subscriptions/index.js +2 -2
- package/dist/subscriptions/resolve.d.ts +3 -1
- package/dist/subscriptions/resolve.d.ts.map +1 -1
- package/dist/subscriptions/resolve.js +91 -52
- package/dist/subscriptions/resolve.js.map +1 -1
- package/dist/sync.d.ts +3 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +9 -5
- package/dist/sync.js.map +1 -1
- package/package.json +297 -8
- package/src/auth-leases.ts +649 -0
- package/src/better-sqlite3.ts +35 -0
- package/src/blobs/access.ts +244 -0
- package/src/blobs/adapters/database.ts +125 -43
- package/src/blobs/index.ts +1 -0
- package/src/blobs/manager.ts +366 -65
- package/src/blobs/migrate.ts +16 -8
- package/src/blobs/types.ts +4 -0
- package/src/bun-sqlite-ambient.d.ts +19 -0
- package/src/bun-sqlite.ts +27 -0
- package/src/clients.ts +1 -0
- package/src/cloudflare/durable-object.ts +289 -0
- package/src/cloudflare/index.ts +22 -0
- package/src/cloudflare/r2.ts +526 -0
- package/src/cloudflare/scope-cache.ts +341 -0
- package/src/cloudflare/sentry.ts +230 -0
- package/src/cloudflare/worker.ts +77 -0
- package/src/commit-integrity.ts +371 -0
- package/src/crdt-yjs/index.ts +931 -0
- package/src/d1.ts +16 -0
- package/src/dialect/base.ts +71 -5
- package/src/dialect/helpers.ts +31 -0
- package/src/dialect/types.ts +47 -0
- package/src/encrypted-crdt.ts +786 -0
- package/src/errors.ts +22 -0
- package/src/filesystem/index.ts +262 -0
- package/src/handlers/collection.ts +78 -78
- package/src/handlers/create-handler.ts +540 -147
- package/src/handlers/types.ts +116 -0
- package/src/helpers/index.ts +2 -0
- package/src/helpers/scope-authorization.ts +27 -0
- package/src/helpers/scope-commit-index.ts +52 -0
- package/src/hono/api-key-auth.ts +177 -0
- package/src/hono/audit-redaction.ts +135 -0
- package/src/hono/blobs.ts +851 -0
- package/src/hono/console/gateway.ts +3046 -0
- package/src/hono/console/live-auth.ts +46 -0
- package/src/hono/console/route-descriptor.ts +22 -0
- package/src/hono/console/routes/api-keys.ts +721 -0
- package/src/hono/console/routes/clients.ts +447 -0
- package/src/hono/console/routes/commits.ts +1137 -0
- package/src/hono/console/routes/context.ts +956 -0
- package/src/hono/console/routes/events.ts +669 -0
- package/src/hono/console/routes/maintenance.ts +461 -0
- package/src/hono/console/routes/shared.ts +816 -0
- package/src/hono/console/routes/stats.ts +392 -0
- package/src/hono/console/routes/storage.ts +159 -0
- package/src/hono/console/routes.ts +146 -0
- package/src/hono/console/schema-errors.ts +23 -0
- package/src/hono/console/schemas.ts +914 -0
- package/src/hono/console/types.ts +223 -0
- package/src/hono/console/ui.ts +100 -0
- package/src/hono/create-server.ts +230 -0
- package/src/hono/errors.ts +50 -0
- package/src/hono/index.ts +54 -0
- package/src/hono/openapi.ts +139 -0
- package/src/hono/proxy/connection-manager.ts +340 -0
- package/src/hono/proxy/index.ts +8 -0
- package/src/hono/proxy/routes.ts +272 -0
- package/src/hono/rate-limit.ts +319 -0
- package/src/hono/realtime-sync-packs.ts +354 -0
- package/src/hono/routes/audit.ts +499 -0
- package/src/hono/routes/auth-leases.ts +119 -0
- package/src/hono/routes/combined.ts +583 -0
- package/src/hono/routes/context.ts +1629 -0
- package/src/hono/routes/health.ts +26 -0
- package/src/hono/routes/realtime.ts +808 -0
- package/src/hono/routes/shared.ts +1626 -0
- package/src/hono/routes/snapshots.ts +345 -0
- package/src/hono/routes.ts +68 -0
- package/src/hono/validation.ts +81 -0
- package/src/hono/websocket-origin.ts +131 -0
- package/src/hono/ws.ts +1134 -0
- package/src/index.ts +6 -0
- package/src/libsql.ts +51 -0
- package/src/neon.ts +28 -0
- package/src/notify.ts +224 -44
- package/src/pglite.ts +68 -0
- package/src/plugins/index.ts +1 -0
- package/src/plugins/types.ts +144 -0
- package/src/postgres/index.ts +1291 -0
- package/src/proxy/collection.ts +5 -27
- package/src/proxy/handler.ts +2 -2
- package/src/proxy/index.ts +0 -2
- package/src/proxy/oplog.ts +41 -10
- package/src/prune.ts +137 -36
- package/src/pull.ts +1504 -591
- package/src/push.ts +881 -443
- package/src/realtime/index.ts +2 -0
- package/src/realtime/types.ts +35 -0
- package/src/relay/bun-types.d.ts +50 -0
- package/src/relay/client-role/forward-engine.ts +355 -0
- package/src/relay/client-role/index.ts +9 -0
- package/src/relay/client-role/pull-engine.ts +329 -0
- package/src/relay/client-role/sequence-mapper.ts +201 -0
- package/src/relay/evaluation/relay-paths.ts +699 -0
- package/src/relay/evaluation/rust-boundary.ts +464 -0
- package/src/relay/index.ts +50 -0
- package/src/relay/migrate.ts +113 -0
- package/src/relay/mode-manager.ts +142 -0
- package/src/relay/realtime.ts +207 -0
- package/src/relay/relay.ts +431 -0
- package/src/relay/schema.ts +171 -0
- package/src/relay/server-role/index.ts +338 -0
- package/src/relay/server-role/pull.ts +43 -0
- package/src/relay/server-role/push.ts +164 -0
- package/src/s3/index.ts +346 -0
- package/src/schema.ts +141 -1
- package/src/service-worker/index.ts +773 -0
- package/src/snapshot-artifacts/sqlite-bun.ts +168 -0
- package/src/snapshot-artifacts.ts +896 -0
- package/src/snapshot-chunks/db-metadata.ts +131 -72
- package/src/snapshot-chunks/types.ts +2 -0
- package/src/snapshot-chunks.ts +194 -70
- package/src/sqlite/index.ts +1064 -0
- package/src/sqlite3.ts +137 -0
- package/src/stats.ts +76 -13
- package/src/subscriptions/cache.ts +58 -0
- package/src/subscriptions/resolve.ts +99 -58
- package/src/sync.ts +16 -6
- package/src/blobs/adapters/database.test.ts +0 -67
- package/src/notify.test.ts +0 -520
- package/src/proxy/handler.test.ts +0 -126
- package/src/proxy/mutation-detector.test.ts +0 -71
- package/src/snapshot-chunks/db-metadata.test.ts +0 -172
- package/src/subscriptions/resolve.test.ts +0 -180
package/src/blobs/manager.ts
CHANGED
|
@@ -30,19 +30,66 @@ export interface BlobManagerOptions<
|
|
|
30
30
|
defaultExpiresIn?: number;
|
|
31
31
|
/** How long incomplete uploads are kept before cleanup. Default: 86400 (24 hours) */
|
|
32
32
|
uploadTtlSeconds?: number;
|
|
33
|
+
/** Optional cleanup throughput tuning knobs. */
|
|
34
|
+
cleanupTuning?: BlobCleanupTuning;
|
|
33
35
|
}
|
|
34
36
|
|
|
37
|
+
export interface BlobCleanupTuning {
|
|
38
|
+
/** Cleanup select/delete batch size. Default: 250 */
|
|
39
|
+
batchSize?: number;
|
|
40
|
+
/** Max concurrent storage deletes during cleanup. Default: 8 */
|
|
41
|
+
storageDeleteConcurrency?: number;
|
|
42
|
+
/** Max concurrent reference checks for completed uploads. Default: 16 */
|
|
43
|
+
referenceCheckConcurrency?: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const BLOB_CLEANUP_TUNING_PRESETS = {
|
|
47
|
+
server: {
|
|
48
|
+
batchSize: 500,
|
|
49
|
+
storageDeleteConcurrency: 16,
|
|
50
|
+
referenceCheckConcurrency: 24,
|
|
51
|
+
},
|
|
52
|
+
edge: {
|
|
53
|
+
batchSize: 100,
|
|
54
|
+
storageDeleteConcurrency: 4,
|
|
55
|
+
referenceCheckConcurrency: 8,
|
|
56
|
+
},
|
|
57
|
+
} as const satisfies Record<'server' | 'edge', Required<BlobCleanupTuning>>;
|
|
58
|
+
|
|
35
59
|
export interface InitiateUploadOptions {
|
|
36
60
|
hash: string;
|
|
37
61
|
size: number;
|
|
38
62
|
mimeType: string;
|
|
39
63
|
actorId: string;
|
|
64
|
+
partitionId?: string;
|
|
40
65
|
}
|
|
41
66
|
|
|
42
67
|
export interface GetDownloadUrlOptions {
|
|
43
68
|
hash: string;
|
|
44
69
|
/** Optional: verify actor has access to this blob via a scope check */
|
|
45
70
|
actorId?: string;
|
|
71
|
+
partitionId?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface CompleteUploadOptions {
|
|
75
|
+
/**
|
|
76
|
+
* Optional actor identity to authorize upload completion.
|
|
77
|
+
* When provided, only the initiating actor may mark an upload complete.
|
|
78
|
+
*/
|
|
79
|
+
actorId?: string;
|
|
80
|
+
partitionId?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface BlobUploadRecord {
|
|
84
|
+
partitionId: string;
|
|
85
|
+
hash: string;
|
|
86
|
+
size: number;
|
|
87
|
+
mimeType: string;
|
|
88
|
+
status: 'pending' | 'complete';
|
|
89
|
+
actorId: string;
|
|
90
|
+
createdAt: string;
|
|
91
|
+
expiresAt: string;
|
|
92
|
+
completedAt: string | null;
|
|
46
93
|
}
|
|
47
94
|
|
|
48
95
|
/**
|
|
@@ -56,8 +103,82 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
56
103
|
adapter,
|
|
57
104
|
defaultExpiresIn = 3600,
|
|
58
105
|
uploadTtlSeconds = 86400,
|
|
106
|
+
cleanupTuning,
|
|
59
107
|
} = options;
|
|
60
108
|
|
|
109
|
+
function positiveIntOrDefault(value: number | undefined, fallback: number) {
|
|
110
|
+
if (value === undefined) return fallback;
|
|
111
|
+
if (!Number.isFinite(value)) return fallback;
|
|
112
|
+
const normalized = Math.trunc(value);
|
|
113
|
+
return normalized > 0 ? normalized : fallback;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function resolvePartitionId(partitionId?: string): string {
|
|
117
|
+
return partitionId ?? 'default';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function normalizeBlobSizeValue(value: number | string): number {
|
|
121
|
+
return typeof value === 'number' ? value : Number(value);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function toStoragePartitionOptions(partitionId: string): {
|
|
125
|
+
partitionId?: string;
|
|
126
|
+
} {
|
|
127
|
+
if (partitionId === 'default') return {};
|
|
128
|
+
return { partitionId };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const CLEANUP_BATCH_SIZE = positiveIntOrDefault(
|
|
132
|
+
cleanupTuning?.batchSize,
|
|
133
|
+
250
|
|
134
|
+
);
|
|
135
|
+
const STORAGE_DELETE_CONCURRENCY = positiveIntOrDefault(
|
|
136
|
+
cleanupTuning?.storageDeleteConcurrency,
|
|
137
|
+
8
|
|
138
|
+
);
|
|
139
|
+
const REFERENCE_CHECK_CONCURRENCY = positiveIntOrDefault(
|
|
140
|
+
cleanupTuning?.referenceCheckConcurrency,
|
|
141
|
+
16
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
async function runWithConcurrency<T>(
|
|
145
|
+
items: readonly T[],
|
|
146
|
+
concurrency: number,
|
|
147
|
+
worker: (item: T) => Promise<void>
|
|
148
|
+
): Promise<void> {
|
|
149
|
+
if (items.length === 0) return;
|
|
150
|
+
|
|
151
|
+
const workerCount = Math.max(1, Math.min(concurrency, items.length));
|
|
152
|
+
let nextIndex = 0;
|
|
153
|
+
|
|
154
|
+
async function runWorker(): Promise<void> {
|
|
155
|
+
while (nextIndex < items.length) {
|
|
156
|
+
const index = nextIndex;
|
|
157
|
+
nextIndex += 1;
|
|
158
|
+
const item = items[index];
|
|
159
|
+
if (item === undefined) continue;
|
|
160
|
+
await worker(item);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
await Promise.all(Array.from({ length: workerCount }, () => runWorker()));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function deleteUploadRowsByHashes(
|
|
168
|
+
partitionId: string,
|
|
169
|
+
hashes: readonly string[]
|
|
170
|
+
): Promise<number> {
|
|
171
|
+
if (hashes.length === 0) return 0;
|
|
172
|
+
|
|
173
|
+
const deletedResult = await sql`
|
|
174
|
+
delete from ${sql.table('sync_blob_uploads')}
|
|
175
|
+
where partition_id = ${partitionId}
|
|
176
|
+
and hash in (${sql.join(hashes)})
|
|
177
|
+
`.execute(db);
|
|
178
|
+
|
|
179
|
+
return Number(deletedResult.numAffectedRows ?? 0);
|
|
180
|
+
}
|
|
181
|
+
|
|
61
182
|
return {
|
|
62
183
|
/**
|
|
63
184
|
* Initiate a blob upload.
|
|
@@ -68,6 +189,8 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
68
189
|
opts: InitiateUploadOptions
|
|
69
190
|
): Promise<BlobUploadInitResponse> {
|
|
70
191
|
const { hash, size, mimeType, actorId } = opts;
|
|
192
|
+
const partitionId = resolvePartitionId(opts.partitionId);
|
|
193
|
+
const storagePartitionOptions = toStoragePartitionOptions(partitionId);
|
|
71
194
|
|
|
72
195
|
// Validate hash format
|
|
73
196
|
if (!parseBlobHash(hash)) {
|
|
@@ -75,13 +198,15 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
75
198
|
}
|
|
76
199
|
|
|
77
200
|
// Check if blob already exists (deduplication)
|
|
78
|
-
const exists = await adapter.exists(hash);
|
|
201
|
+
const exists = await adapter.exists(hash, storagePartitionOptions);
|
|
79
202
|
if (exists) {
|
|
80
203
|
// Also check if we have a complete upload record
|
|
81
204
|
const existingResult = await sql<{ status: 'pending' | 'complete' }>`
|
|
82
205
|
select status
|
|
83
206
|
from ${sql.table('sync_blob_uploads')}
|
|
84
|
-
where
|
|
207
|
+
where partition_id = ${partitionId}
|
|
208
|
+
and hash = ${hash}
|
|
209
|
+
and status = 'complete'
|
|
85
210
|
limit 1
|
|
86
211
|
`.execute(db);
|
|
87
212
|
const existing = existingResult.rows[0];
|
|
@@ -98,6 +223,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
98
223
|
|
|
99
224
|
await sql`
|
|
100
225
|
insert into ${sql.table('sync_blob_uploads')} (
|
|
226
|
+
partition_id,
|
|
101
227
|
hash,
|
|
102
228
|
size,
|
|
103
229
|
mime_type,
|
|
@@ -107,6 +233,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
107
233
|
completed_at
|
|
108
234
|
)
|
|
109
235
|
values (
|
|
236
|
+
${partitionId},
|
|
110
237
|
${hash},
|
|
111
238
|
${size},
|
|
112
239
|
${mimeType},
|
|
@@ -115,7 +242,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
115
242
|
${existsExpiresAt},
|
|
116
243
|
${existsCompletedAt}
|
|
117
244
|
)
|
|
118
|
-
on conflict (hash) do nothing
|
|
245
|
+
on conflict (partition_id, hash) do nothing
|
|
119
246
|
`.execute(db);
|
|
120
247
|
|
|
121
248
|
return { exists: true };
|
|
@@ -128,6 +255,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
128
255
|
|
|
129
256
|
await sql`
|
|
130
257
|
insert into ${sql.table('sync_blob_uploads')} (
|
|
258
|
+
partition_id,
|
|
131
259
|
hash,
|
|
132
260
|
size,
|
|
133
261
|
mime_type,
|
|
@@ -137,6 +265,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
137
265
|
completed_at
|
|
138
266
|
)
|
|
139
267
|
values (
|
|
268
|
+
${partitionId},
|
|
140
269
|
${hash},
|
|
141
270
|
${size},
|
|
142
271
|
${mimeType},
|
|
@@ -145,7 +274,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
145
274
|
${expiresAt},
|
|
146
275
|
${null}
|
|
147
276
|
)
|
|
148
|
-
on conflict (hash)
|
|
277
|
+
on conflict (partition_id, hash)
|
|
149
278
|
do update set
|
|
150
279
|
size = ${size},
|
|
151
280
|
mime_type = ${mimeType},
|
|
@@ -158,6 +287,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
158
287
|
// Generate presigned upload URL
|
|
159
288
|
const signed = await adapter.signUpload({
|
|
160
289
|
hash,
|
|
290
|
+
partitionId: storagePartitionOptions.partitionId,
|
|
161
291
|
size,
|
|
162
292
|
mimeType,
|
|
163
293
|
expiresIn: defaultExpiresIn,
|
|
@@ -177,38 +307,57 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
177
307
|
*
|
|
178
308
|
* Verifies the blob exists in storage and marks the upload as complete.
|
|
179
309
|
*/
|
|
180
|
-
async completeUpload(
|
|
310
|
+
async completeUpload(
|
|
311
|
+
hash: string,
|
|
312
|
+
options?: CompleteUploadOptions
|
|
313
|
+
): Promise<BlobUploadCompleteResponse> {
|
|
314
|
+
const partitionId = resolvePartitionId(options?.partitionId);
|
|
315
|
+
const storagePartitionOptions = toStoragePartitionOptions(partitionId);
|
|
316
|
+
|
|
181
317
|
// Validate hash format
|
|
182
318
|
if (!parseBlobHash(hash)) {
|
|
183
|
-
return {
|
|
319
|
+
return {
|
|
320
|
+
ok: false,
|
|
321
|
+
error: 'Invalid blob hash format',
|
|
322
|
+
code: 'blob.invalid_request',
|
|
323
|
+
};
|
|
184
324
|
}
|
|
185
325
|
|
|
186
326
|
// Check upload record exists
|
|
187
327
|
const uploadResult = await sql<{
|
|
188
328
|
hash: string;
|
|
189
|
-
size: number;
|
|
329
|
+
size: number | string;
|
|
190
330
|
mime_type: string;
|
|
191
331
|
status: 'pending' | 'complete';
|
|
332
|
+
actor_id: string;
|
|
192
333
|
created_at: string;
|
|
193
334
|
}>`
|
|
194
|
-
select hash, size, mime_type, status, created_at
|
|
335
|
+
select hash, size, mime_type, status, actor_id, created_at
|
|
195
336
|
from ${sql.table('sync_blob_uploads')}
|
|
196
|
-
where hash = ${hash}
|
|
337
|
+
where partition_id = ${partitionId} and hash = ${hash}
|
|
197
338
|
limit 1
|
|
198
339
|
`.execute(db);
|
|
199
340
|
const upload = uploadResult.rows[0];
|
|
200
341
|
|
|
201
342
|
if (!upload) {
|
|
202
|
-
return { ok: false, error: 'Upload not found' };
|
|
343
|
+
return { ok: false, error: 'Upload not found', code: 'blob.not_found' };
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (
|
|
347
|
+
options?.actorId !== undefined &&
|
|
348
|
+
upload.actor_id !== options.actorId
|
|
349
|
+
) {
|
|
350
|
+
return { ok: false, error: 'Forbidden', code: 'blob.forbidden' };
|
|
203
351
|
}
|
|
204
352
|
|
|
205
353
|
if (upload.status === 'complete') {
|
|
354
|
+
const uploadSize = normalizeBlobSizeValue(upload.size);
|
|
206
355
|
// Already complete - return metadata
|
|
207
356
|
return {
|
|
208
357
|
ok: true,
|
|
209
358
|
metadata: {
|
|
210
359
|
hash: upload.hash,
|
|
211
|
-
size:
|
|
360
|
+
size: uploadSize,
|
|
212
361
|
mimeType: upload.mime_type,
|
|
213
362
|
createdAt: upload.created_at,
|
|
214
363
|
uploadComplete: true,
|
|
@@ -217,18 +366,24 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
217
366
|
}
|
|
218
367
|
|
|
219
368
|
// Verify blob exists in storage
|
|
220
|
-
const exists = await adapter.exists(hash);
|
|
369
|
+
const exists = await adapter.exists(hash, storagePartitionOptions);
|
|
221
370
|
if (!exists) {
|
|
222
|
-
return {
|
|
371
|
+
return {
|
|
372
|
+
ok: false,
|
|
373
|
+
error: 'Blob not found in storage',
|
|
374
|
+
code: 'blob.not_found',
|
|
375
|
+
};
|
|
223
376
|
}
|
|
224
377
|
|
|
225
378
|
// Optionally verify size matches
|
|
379
|
+
const uploadSize = normalizeBlobSizeValue(upload.size);
|
|
226
380
|
if (adapter.getMetadata) {
|
|
227
|
-
const meta = await adapter.getMetadata(hash);
|
|
228
|
-
if (meta && meta.size !==
|
|
381
|
+
const meta = await adapter.getMetadata(hash, storagePartitionOptions);
|
|
382
|
+
if (meta && meta.size !== uploadSize) {
|
|
229
383
|
return {
|
|
230
384
|
ok: false,
|
|
231
|
-
error: `Size mismatch: expected ${
|
|
385
|
+
error: `Size mismatch: expected ${uploadSize}, got ${meta.size}`,
|
|
386
|
+
code: 'blob.size_mismatch',
|
|
232
387
|
};
|
|
233
388
|
}
|
|
234
389
|
}
|
|
@@ -238,14 +393,14 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
238
393
|
await sql`
|
|
239
394
|
update ${sql.table('sync_blob_uploads')}
|
|
240
395
|
set status = 'complete', completed_at = ${completedAt}
|
|
241
|
-
where hash = ${hash}
|
|
396
|
+
where partition_id = ${partitionId} and hash = ${hash}
|
|
242
397
|
`.execute(db);
|
|
243
398
|
|
|
244
399
|
return {
|
|
245
400
|
ok: true,
|
|
246
401
|
metadata: {
|
|
247
402
|
hash: upload.hash,
|
|
248
|
-
size:
|
|
403
|
+
size: uploadSize,
|
|
249
404
|
mimeType: upload.mime_type,
|
|
250
405
|
createdAt: upload.created_at,
|
|
251
406
|
uploadComplete: true,
|
|
@@ -260,6 +415,8 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
260
415
|
opts: GetDownloadUrlOptions
|
|
261
416
|
): Promise<{ url: string; expiresAt: string; metadata: BlobMetadata }> {
|
|
262
417
|
const { hash } = opts;
|
|
418
|
+
const partitionId = resolvePartitionId(opts.partitionId);
|
|
419
|
+
const storagePartitionOptions = toStoragePartitionOptions(partitionId);
|
|
263
420
|
|
|
264
421
|
// Validate hash format
|
|
265
422
|
if (!parseBlobHash(hash)) {
|
|
@@ -269,14 +426,16 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
269
426
|
// Get upload record (must be complete)
|
|
270
427
|
const uploadResult = await sql<{
|
|
271
428
|
hash: string;
|
|
272
|
-
size: number;
|
|
429
|
+
size: number | string;
|
|
273
430
|
mime_type: string;
|
|
274
431
|
status: 'pending' | 'complete';
|
|
275
432
|
created_at: string;
|
|
276
433
|
}>`
|
|
277
434
|
select hash, size, mime_type, status, created_at
|
|
278
435
|
from ${sql.table('sync_blob_uploads')}
|
|
279
|
-
where
|
|
436
|
+
where partition_id = ${partitionId}
|
|
437
|
+
and hash = ${hash}
|
|
438
|
+
and status = 'complete'
|
|
280
439
|
limit 1
|
|
281
440
|
`.execute(db);
|
|
282
441
|
const upload = uploadResult.rows[0];
|
|
@@ -288,6 +447,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
288
447
|
// Generate presigned download URL
|
|
289
448
|
const url = await adapter.signDownload({
|
|
290
449
|
hash,
|
|
450
|
+
partitionId: storagePartitionOptions.partitionId,
|
|
291
451
|
expiresIn: defaultExpiresIn,
|
|
292
452
|
});
|
|
293
453
|
|
|
@@ -300,7 +460,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
300
460
|
expiresAt,
|
|
301
461
|
metadata: {
|
|
302
462
|
hash: upload.hash,
|
|
303
|
-
size: upload.size,
|
|
463
|
+
size: normalizeBlobSizeValue(upload.size),
|
|
304
464
|
mimeType: upload.mime_type,
|
|
305
465
|
createdAt: upload.created_at,
|
|
306
466
|
uploadComplete: true,
|
|
@@ -308,10 +468,70 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
308
468
|
};
|
|
309
469
|
},
|
|
310
470
|
|
|
471
|
+
/**
|
|
472
|
+
* Get upload record for a blob hash, including pending uploads.
|
|
473
|
+
*/
|
|
474
|
+
async getUploadRecord(
|
|
475
|
+
hash: string,
|
|
476
|
+
options?: { partitionId?: string }
|
|
477
|
+
): Promise<BlobUploadRecord | null> {
|
|
478
|
+
const partitionId = resolvePartitionId(options?.partitionId);
|
|
479
|
+
if (!parseBlobHash(hash)) {
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const uploadResult = await sql<{
|
|
484
|
+
partition_id: string;
|
|
485
|
+
hash: string;
|
|
486
|
+
size: number | string;
|
|
487
|
+
mime_type: string;
|
|
488
|
+
status: 'pending' | 'complete';
|
|
489
|
+
actor_id: string;
|
|
490
|
+
created_at: string;
|
|
491
|
+
expires_at: string;
|
|
492
|
+
completed_at: string | null;
|
|
493
|
+
}>`
|
|
494
|
+
select
|
|
495
|
+
partition_id,
|
|
496
|
+
hash,
|
|
497
|
+
size,
|
|
498
|
+
mime_type,
|
|
499
|
+
status,
|
|
500
|
+
actor_id,
|
|
501
|
+
created_at,
|
|
502
|
+
expires_at,
|
|
503
|
+
completed_at
|
|
504
|
+
from ${sql.table('sync_blob_uploads')}
|
|
505
|
+
where partition_id = ${partitionId} and hash = ${hash}
|
|
506
|
+
limit 1
|
|
507
|
+
`.execute(db);
|
|
508
|
+
const upload = uploadResult.rows[0];
|
|
509
|
+
|
|
510
|
+
if (!upload) {
|
|
511
|
+
return null;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
return {
|
|
515
|
+
partitionId: upload.partition_id,
|
|
516
|
+
hash: upload.hash,
|
|
517
|
+
size: normalizeBlobSizeValue(upload.size),
|
|
518
|
+
mimeType: upload.mime_type,
|
|
519
|
+
status: upload.status,
|
|
520
|
+
actorId: upload.actor_id,
|
|
521
|
+
createdAt: upload.created_at,
|
|
522
|
+
expiresAt: upload.expires_at,
|
|
523
|
+
completedAt: upload.completed_at,
|
|
524
|
+
};
|
|
525
|
+
},
|
|
526
|
+
|
|
311
527
|
/**
|
|
312
528
|
* Get blob metadata without generating a download URL.
|
|
313
529
|
*/
|
|
314
|
-
async getMetadata(
|
|
530
|
+
async getMetadata(
|
|
531
|
+
hash: string,
|
|
532
|
+
options?: { partitionId?: string }
|
|
533
|
+
): Promise<BlobMetadata | null> {
|
|
534
|
+
const partitionId = resolvePartitionId(options?.partitionId);
|
|
315
535
|
// Validate hash format
|
|
316
536
|
if (!parseBlobHash(hash)) {
|
|
317
537
|
return null;
|
|
@@ -319,14 +539,16 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
319
539
|
|
|
320
540
|
const uploadResult = await sql<{
|
|
321
541
|
hash: string;
|
|
322
|
-
size: number;
|
|
542
|
+
size: number | string;
|
|
323
543
|
mime_type: string;
|
|
324
544
|
status: 'pending' | 'complete';
|
|
325
545
|
created_at: string;
|
|
326
546
|
}>`
|
|
327
547
|
select hash, size, mime_type, status, created_at
|
|
328
548
|
from ${sql.table('sync_blob_uploads')}
|
|
329
|
-
where
|
|
549
|
+
where partition_id = ${partitionId}
|
|
550
|
+
and hash = ${hash}
|
|
551
|
+
and status = 'complete'
|
|
330
552
|
limit 1
|
|
331
553
|
`.execute(db);
|
|
332
554
|
const upload = uploadResult.rows[0];
|
|
@@ -337,7 +559,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
337
559
|
|
|
338
560
|
return {
|
|
339
561
|
hash: upload.hash,
|
|
340
|
-
size: upload.size,
|
|
562
|
+
size: normalizeBlobSizeValue(upload.size),
|
|
341
563
|
mimeType: upload.mime_type,
|
|
342
564
|
createdAt: upload.created_at,
|
|
343
565
|
uploadComplete: true,
|
|
@@ -347,13 +569,19 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
347
569
|
/**
|
|
348
570
|
* Check if a blob exists and is complete.
|
|
349
571
|
*/
|
|
350
|
-
async exists(
|
|
572
|
+
async exists(
|
|
573
|
+
hash: string,
|
|
574
|
+
options?: { partitionId?: string }
|
|
575
|
+
): Promise<boolean> {
|
|
576
|
+
const partitionId = resolvePartitionId(options?.partitionId);
|
|
351
577
|
if (!parseBlobHash(hash)) return false;
|
|
352
578
|
|
|
353
579
|
const rowResult = await sql<{ hash: string }>`
|
|
354
580
|
select hash
|
|
355
581
|
from ${sql.table('sync_blob_uploads')}
|
|
356
|
-
where
|
|
582
|
+
where partition_id = ${partitionId}
|
|
583
|
+
and hash = ${hash}
|
|
584
|
+
and status = 'complete'
|
|
357
585
|
limit 1
|
|
358
586
|
`.execute(db);
|
|
359
587
|
|
|
@@ -372,62 +600,131 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
|
|
|
372
600
|
isReferenced?: (hash: string) => Promise<boolean>;
|
|
373
601
|
/** Delete from storage too (not just tracking table) */
|
|
374
602
|
deleteFromStorage?: boolean;
|
|
603
|
+
/** Optional partition filter for cleanup */
|
|
604
|
+
partitionId?: string;
|
|
375
605
|
}): Promise<{ deleted: number }> {
|
|
376
606
|
const now = new Date().toISOString();
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
const expiredResult = await sql<{ hash: string }>`
|
|
380
|
-
select hash
|
|
381
|
-
from ${sql.table('sync_blob_uploads')}
|
|
382
|
-
where status = 'pending' and expires_at < ${now}
|
|
383
|
-
`.execute(db);
|
|
384
|
-
const expired = expiredResult.rows;
|
|
607
|
+
const partitionId = resolvePartitionId(options?.partitionId);
|
|
608
|
+
const storagePartitionOptions = toStoragePartitionOptions(partitionId);
|
|
385
609
|
|
|
386
610
|
let deleted = 0;
|
|
387
611
|
|
|
388
|
-
|
|
612
|
+
// Find and delete expired pending uploads in batches.
|
|
613
|
+
while (true) {
|
|
614
|
+
const expiredResult = await sql<{ hash: string }>`
|
|
615
|
+
select hash
|
|
616
|
+
from ${sql.table('sync_blob_uploads')}
|
|
617
|
+
where partition_id = ${partitionId}
|
|
618
|
+
and status = 'pending'
|
|
619
|
+
and expires_at < ${now}
|
|
620
|
+
order by expires_at asc
|
|
621
|
+
limit ${CLEANUP_BATCH_SIZE}
|
|
622
|
+
`.execute(db);
|
|
623
|
+
const expiredHashes = expiredResult.rows
|
|
624
|
+
.map((row) => row.hash)
|
|
625
|
+
.filter((hash): hash is string => typeof hash === 'string');
|
|
626
|
+
|
|
627
|
+
if (expiredHashes.length === 0) {
|
|
628
|
+
break;
|
|
629
|
+
}
|
|
630
|
+
|
|
389
631
|
if (options?.deleteFromStorage) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
632
|
+
await runWithConcurrency(
|
|
633
|
+
expiredHashes,
|
|
634
|
+
STORAGE_DELETE_CONCURRENCY,
|
|
635
|
+
async (hash) => {
|
|
636
|
+
try {
|
|
637
|
+
await adapter.delete(hash, storagePartitionOptions);
|
|
638
|
+
} catch {
|
|
639
|
+
// Ignore storage errors during cleanup
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
);
|
|
395
643
|
}
|
|
396
644
|
|
|
397
|
-
await
|
|
398
|
-
delete from ${sql.table('sync_blob_uploads')}
|
|
399
|
-
where hash = ${row.hash}
|
|
400
|
-
`.execute(db);
|
|
645
|
+
deleted += await deleteUploadRowsByHashes(partitionId, expiredHashes);
|
|
401
646
|
|
|
402
|
-
|
|
647
|
+
if (expiredHashes.length < CLEANUP_BATCH_SIZE) {
|
|
648
|
+
break;
|
|
649
|
+
}
|
|
403
650
|
}
|
|
404
651
|
|
|
405
652
|
// If reference check provided, also clean up unreferenced complete uploads
|
|
653
|
+
// in batches with bounded parallelism.
|
|
406
654
|
if (options?.isReferenced) {
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
655
|
+
const isReferenced = options.isReferenced;
|
|
656
|
+
let afterHash: string | null = null;
|
|
657
|
+
|
|
658
|
+
while (true) {
|
|
659
|
+
let completeRows: Array<{ hash: string }>;
|
|
660
|
+
if (afterHash === null) {
|
|
661
|
+
const completeResult = await sql<{ hash: string }>`
|
|
662
|
+
select hash
|
|
663
|
+
from ${sql.table('sync_blob_uploads')}
|
|
664
|
+
where partition_id = ${partitionId}
|
|
665
|
+
and status = 'complete'
|
|
666
|
+
order by hash asc
|
|
667
|
+
limit ${CLEANUP_BATCH_SIZE}
|
|
668
|
+
`.execute(db);
|
|
669
|
+
completeRows = completeResult.rows;
|
|
670
|
+
} else {
|
|
671
|
+
const completeResult = await sql<{ hash: string }>`
|
|
672
|
+
select hash
|
|
673
|
+
from ${sql.table('sync_blob_uploads')}
|
|
674
|
+
where partition_id = ${partitionId}
|
|
675
|
+
and status = 'complete'
|
|
676
|
+
and hash > ${afterHash}
|
|
677
|
+
order by hash asc
|
|
678
|
+
limit ${CLEANUP_BATCH_SIZE}
|
|
679
|
+
`.execute(db);
|
|
680
|
+
completeRows = completeResult.rows;
|
|
681
|
+
}
|
|
413
682
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
683
|
+
const completeHashes = completeRows
|
|
684
|
+
.map((row) => row.hash)
|
|
685
|
+
.filter((hash): hash is string => typeof hash === 'string');
|
|
686
|
+
|
|
687
|
+
if (completeHashes.length === 0) {
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
afterHash = completeHashes[completeHashes.length - 1] ?? afterHash;
|
|
692
|
+
|
|
693
|
+
const unreferencedHashes: string[] = [];
|
|
694
|
+
await runWithConcurrency(
|
|
695
|
+
completeHashes,
|
|
696
|
+
REFERENCE_CHECK_CONCURRENCY,
|
|
697
|
+
async (hash) => {
|
|
698
|
+
const referenced = await isReferenced(hash);
|
|
699
|
+
if (!referenced) {
|
|
700
|
+
unreferencedHashes.push(hash);
|
|
422
701
|
}
|
|
423
702
|
}
|
|
703
|
+
);
|
|
424
704
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
705
|
+
if (unreferencedHashes.length > 0) {
|
|
706
|
+
if (options?.deleteFromStorage) {
|
|
707
|
+
await runWithConcurrency(
|
|
708
|
+
unreferencedHashes,
|
|
709
|
+
STORAGE_DELETE_CONCURRENCY,
|
|
710
|
+
async (hash) => {
|
|
711
|
+
try {
|
|
712
|
+
await adapter.delete(hash, storagePartitionOptions);
|
|
713
|
+
} catch {
|
|
714
|
+
// Ignore storage errors during cleanup
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
deleted += await deleteUploadRowsByHashes(
|
|
721
|
+
partitionId,
|
|
722
|
+
unreferencedHashes
|
|
723
|
+
);
|
|
724
|
+
}
|
|
429
725
|
|
|
430
|
-
|
|
726
|
+
if (completeHashes.length < CLEANUP_BATCH_SIZE) {
|
|
727
|
+
break;
|
|
431
728
|
}
|
|
432
729
|
}
|
|
433
730
|
}
|
|
@@ -455,6 +752,8 @@ export interface BlobCleanupSchedulerOptions {
|
|
|
455
752
|
deleteFromStorage?: boolean;
|
|
456
753
|
/** Optional: Check if a blob hash is referenced by any row */
|
|
457
754
|
isReferenced?: (hash: string) => Promise<boolean>;
|
|
755
|
+
/** Optional partition to scope cleanup. Defaults to "default". */
|
|
756
|
+
partitionId?: string;
|
|
458
757
|
/** Optional: Called after each cleanup run */
|
|
459
758
|
onCleanup?: (result: { deleted: number; error?: Error }) => void;
|
|
460
759
|
}
|
|
@@ -499,6 +798,7 @@ export function createBlobCleanupScheduler(
|
|
|
499
798
|
intervalMs = 3600000, // 1 hour
|
|
500
799
|
deleteFromStorage = true,
|
|
501
800
|
isReferenced,
|
|
801
|
+
partitionId,
|
|
502
802
|
onCleanup,
|
|
503
803
|
} = options;
|
|
504
804
|
|
|
@@ -516,6 +816,7 @@ export function createBlobCleanupScheduler(
|
|
|
516
816
|
const result = await blobManager.cleanup({
|
|
517
817
|
deleteFromStorage,
|
|
518
818
|
isReferenced,
|
|
819
|
+
partitionId,
|
|
519
820
|
});
|
|
520
821
|
|
|
521
822
|
onCleanup?.({ deleted: result.deleted });
|