@dotdo/postgres 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 +868 -0
- package/dist/cdc/change-stream.d.ts +44 -0
- package/dist/cdc/change-stream.d.ts.map +1 -0
- package/dist/cdc/change-stream.js +95 -0
- package/dist/cdc/change-stream.js.map +1 -0
- package/dist/cdc/filter.d.ts +58 -0
- package/dist/cdc/filter.d.ts.map +1 -0
- package/dist/cdc/filter.js +520 -0
- package/dist/cdc/filter.js.map +1 -0
- package/dist/cdc/index.d.ts +47 -0
- package/dist/cdc/index.d.ts.map +1 -0
- package/dist/cdc/index.js +50 -0
- package/dist/cdc/index.js.map +1 -0
- package/dist/cdc/resume-token.d.ts +60 -0
- package/dist/cdc/resume-token.d.ts.map +1 -0
- package/dist/cdc/resume-token.js +228 -0
- package/dist/cdc/resume-token.js.map +1 -0
- package/dist/cdc/transport/index.d.ts +7 -0
- package/dist/cdc/transport/index.d.ts.map +1 -0
- package/dist/cdc/transport/index.js +7 -0
- package/dist/cdc/transport/index.js.map +1 -0
- package/dist/cdc/transport/sse.d.ts +120 -0
- package/dist/cdc/transport/sse.d.ts.map +1 -0
- package/dist/cdc/transport/sse.js +590 -0
- package/dist/cdc/transport/sse.js.map +1 -0
- package/dist/cdc/transport/websocket.d.ts +130 -0
- package/dist/cdc/transport/websocket.d.ts.map +1 -0
- package/dist/cdc/transport/websocket.js +688 -0
- package/dist/cdc/transport/websocket.js.map +1 -0
- package/dist/cdc/types.d.ts +306 -0
- package/dist/cdc/types.d.ts.map +1 -0
- package/dist/cdc/types.js +8 -0
- package/dist/cdc/types.js.map +1 -0
- package/dist/config/index.d.ts +25 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +25 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/memory.d.ts +139 -0
- package/dist/config/memory.d.ts.map +1 -0
- package/dist/config/memory.js +157 -0
- package/dist/config/memory.js.map +1 -0
- package/dist/config/storage.d.ts +157 -0
- package/dist/config/storage.d.ts.map +1 -0
- package/dist/config/storage.js +178 -0
- package/dist/config/storage.js.map +1 -0
- package/dist/config/streaming.d.ts +117 -0
- package/dist/config/streaming.d.ts.map +1 -0
- package/dist/config/streaming.js +132 -0
- package/dist/config/streaming.js.map +1 -0
- package/dist/config/timeouts.d.ts +168 -0
- package/dist/config/timeouts.d.ts.map +1 -0
- package/dist/config/timeouts.js +192 -0
- package/dist/config/timeouts.js.map +1 -0
- package/dist/extensions/config.d.ts +89 -0
- package/dist/extensions/config.d.ts.map +1 -0
- package/dist/extensions/config.js +216 -0
- package/dist/extensions/config.js.map +1 -0
- package/dist/extensions/geo.d.ts +452 -0
- package/dist/extensions/geo.d.ts.map +1 -0
- package/dist/extensions/geo.js +583 -0
- package/dist/extensions/geo.js.map +1 -0
- package/dist/extensions/index.d.ts +167 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +99 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +226 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +456 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/pgmq-lite.d.ts +330 -0
- package/dist/extensions/pgmq-lite.d.ts.map +1 -0
- package/dist/extensions/pgmq-lite.js +648 -0
- package/dist/extensions/pgmq-lite.js.map +1 -0
- package/dist/extensions/plugins.d.ts +260 -0
- package/dist/extensions/plugins.d.ts.map +1 -0
- package/dist/extensions/plugins.js +535 -0
- package/dist/extensions/plugins.js.map +1 -0
- package/dist/extensions/registry.d.ts +93 -0
- package/dist/extensions/registry.d.ts.map +1 -0
- package/dist/extensions/registry.js +182 -0
- package/dist/extensions/registry.js.map +1 -0
- package/dist/extensions/vector.d.ts +106 -0
- package/dist/extensions/vector.d.ts.map +1 -0
- package/dist/extensions/vector.js +129 -0
- package/dist/extensions/vector.js.map +1 -0
- package/dist/iceberg/analytics.d.ts +279 -0
- package/dist/iceberg/analytics.d.ts.map +1 -0
- package/dist/iceberg/analytics.js +448 -0
- package/dist/iceberg/analytics.js.map +1 -0
- package/dist/iceberg/catalog-api.d.ts +39 -0
- package/dist/iceberg/catalog-api.d.ts.map +1 -0
- package/dist/iceberg/catalog-api.js +388 -0
- package/dist/iceberg/catalog-api.js.map +1 -0
- package/dist/iceberg/catalog.d.ts +401 -0
- package/dist/iceberg/catalog.d.ts.map +1 -0
- package/dist/iceberg/catalog.js +677 -0
- package/dist/iceberg/catalog.js.map +1 -0
- package/dist/iceberg/duckdb-wasm.d.ts +447 -0
- package/dist/iceberg/duckdb-wasm.d.ts.map +1 -0
- package/dist/iceberg/duckdb-wasm.js +600 -0
- package/dist/iceberg/duckdb-wasm.js.map +1 -0
- package/dist/iceberg/index.d.ts +92 -0
- package/dist/iceberg/index.d.ts.map +1 -0
- package/dist/iceberg/index.js +119 -0
- package/dist/iceberg/index.js.map +1 -0
- package/dist/iceberg/metadata.d.ts +214 -0
- package/dist/iceberg/metadata.d.ts.map +1 -0
- package/dist/iceberg/metadata.js +535 -0
- package/dist/iceberg/metadata.js.map +1 -0
- package/dist/iceberg/optimizer.d.ts +296 -0
- package/dist/iceberg/optimizer.d.ts.map +1 -0
- package/dist/iceberg/optimizer.js +889 -0
- package/dist/iceberg/optimizer.js.map +1 -0
- package/dist/iceberg/parquet.d.ts +447 -0
- package/dist/iceberg/parquet.d.ts.map +1 -0
- package/dist/iceberg/parquet.js +1225 -0
- package/dist/iceberg/parquet.js.map +1 -0
- package/dist/iceberg/r2-organization.d.ts +422 -0
- package/dist/iceberg/r2-organization.d.ts.map +1 -0
- package/dist/iceberg/r2-organization.js +672 -0
- package/dist/iceberg/r2-organization.js.map +1 -0
- package/dist/iceberg/scheduler-do-example.d.ts +158 -0
- package/dist/iceberg/scheduler-do-example.d.ts.map +1 -0
- package/dist/iceberg/scheduler-do-example.js +261 -0
- package/dist/iceberg/scheduler-do-example.js.map +1 -0
- package/dist/iceberg/scheduler.d.ts +434 -0
- package/dist/iceberg/scheduler.d.ts.map +1 -0
- package/dist/iceberg/scheduler.js +818 -0
- package/dist/iceberg/scheduler.js.map +1 -0
- package/dist/iceberg/schema.d.ts +149 -0
- package/dist/iceberg/schema.d.ts.map +1 -0
- package/dist/iceberg/schema.js +525 -0
- package/dist/iceberg/schema.js.map +1 -0
- package/dist/iceberg/snapshot-manager.d.ts +406 -0
- package/dist/iceberg/snapshot-manager.d.ts.map +1 -0
- package/dist/iceberg/snapshot-manager.js +934 -0
- package/dist/iceberg/snapshot-manager.js.map +1 -0
- package/dist/iceberg/sql-router.d.ts +194 -0
- package/dist/iceberg/sql-router.d.ts.map +1 -0
- package/dist/iceberg/sql-router.js +180 -0
- package/dist/iceberg/sql-router.js.map +1 -0
- package/dist/iceberg/test-fixtures.d.ts +151 -0
- package/dist/iceberg/test-fixtures.d.ts.map +1 -0
- package/dist/iceberg/test-fixtures.js +446 -0
- package/dist/iceberg/test-fixtures.js.map +1 -0
- package/dist/iceberg/time-travel-api.d.ts +102 -0
- package/dist/iceberg/time-travel-api.d.ts.map +1 -0
- package/dist/iceberg/time-travel-api.js +437 -0
- package/dist/iceberg/time-travel-api.js.map +1 -0
- package/dist/iceberg/time-travel.d.ts +293 -0
- package/dist/iceberg/time-travel.d.ts.map +1 -0
- package/dist/iceberg/time-travel.js +689 -0
- package/dist/iceberg/time-travel.js.map +1 -0
- package/dist/iceberg/transformer.d.ts +356 -0
- package/dist/iceberg/transformer.d.ts.map +1 -0
- package/dist/iceberg/transformer.js +770 -0
- package/dist/iceberg/transformer.js.map +1 -0
- package/dist/iceberg/types.d.ts +318 -0
- package/dist/iceberg/types.d.ts.map +1 -0
- package/dist/iceberg/types.js +9 -0
- package/dist/iceberg/types.js.map +1 -0
- package/dist/iceberg/writer.d.ts +144 -0
- package/dist/iceberg/writer.d.ts.map +1 -0
- package/dist/iceberg/writer.js +452 -0
- package/dist/iceberg/writer.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/lineage/index.d.ts +11 -0
- package/dist/lineage/index.d.ts.map +1 -0
- package/dist/lineage/index.js +11 -0
- package/dist/lineage/index.js.map +1 -0
- package/dist/lineage/integration.d.ts +134 -0
- package/dist/lineage/integration.d.ts.map +1 -0
- package/dist/lineage/integration.js +258 -0
- package/dist/lineage/integration.js.map +1 -0
- package/dist/lineage/tracker.d.ts +189 -0
- package/dist/lineage/tracker.d.ts.map +1 -0
- package/dist/lineage/tracker.js +1352 -0
- package/dist/lineage/tracker.js.map +1 -0
- package/dist/lineage/types.d.ts +318 -0
- package/dist/lineage/types.d.ts.map +1 -0
- package/dist/lineage/types.js +9 -0
- package/dist/lineage/types.js.map +1 -0
- package/dist/middleware/index.d.ts +11 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +16 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +397 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +507 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/migration-tooling/external-migration.d.ts +601 -0
- package/dist/migration-tooling/external-migration.d.ts.map +1 -0
- package/dist/migration-tooling/external-migration.js +1612 -0
- package/dist/migration-tooling/external-migration.js.map +1 -0
- package/dist/migration-tooling/index.d.ts +19 -0
- package/dist/migration-tooling/index.d.ts.map +1 -0
- package/dist/migration-tooling/index.js +19 -0
- package/dist/migration-tooling/index.js.map +1 -0
- package/dist/migrations/auto-migrator.d.ts +289 -0
- package/dist/migrations/auto-migrator.d.ts.map +1 -0
- package/dist/migrations/auto-migrator.js +396 -0
- package/dist/migrations/auto-migrator.js.map +1 -0
- package/dist/migrations/bulk-orchestrator.d.ts +403 -0
- package/dist/migrations/bulk-orchestrator.d.ts.map +1 -0
- package/dist/migrations/bulk-orchestrator.js +646 -0
- package/dist/migrations/bulk-orchestrator.js.map +1 -0
- package/dist/migrations/compatibility.d.ts +216 -0
- package/dist/migrations/compatibility.d.ts.map +1 -0
- package/dist/migrations/compatibility.js +651 -0
- package/dist/migrations/compatibility.js.map +1 -0
- package/dist/migrations/do-migrations.d.ts +101 -0
- package/dist/migrations/do-migrations.d.ts.map +1 -0
- package/dist/migrations/do-migrations.js +1060 -0
- package/dist/migrations/do-migrations.js.map +1 -0
- package/dist/migrations/do-migrations.types.d.ts +550 -0
- package/dist/migrations/do-migrations.types.d.ts.map +1 -0
- package/dist/migrations/do-migrations.types.js +15 -0
- package/dist/migrations/do-migrations.types.js.map +1 -0
- package/dist/migrations/drizzle-compat.d.ts +163 -0
- package/dist/migrations/drizzle-compat.d.ts.map +1 -0
- package/dist/migrations/drizzle-compat.js +273 -0
- package/dist/migrations/drizzle-compat.js.map +1 -0
- package/dist/migrations/index.d.ts +109 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +127 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/migration-api.d.ts +161 -0
- package/dist/migrations/migration-api.d.ts.map +1 -0
- package/dist/migrations/migration-api.js +499 -0
- package/dist/migrations/migration-api.js.map +1 -0
- package/dist/migrations/progress-tracker-do.d.ts +195 -0
- package/dist/migrations/progress-tracker-do.d.ts.map +1 -0
- package/dist/migrations/progress-tracker-do.js +339 -0
- package/dist/migrations/progress-tracker-do.js.map +1 -0
- package/dist/migrations/progress-tracker-kv.d.ts +103 -0
- package/dist/migrations/progress-tracker-kv.d.ts.map +1 -0
- package/dist/migrations/progress-tracker-kv.js +231 -0
- package/dist/migrations/progress-tracker-kv.js.map +1 -0
- package/dist/migrations/progress-tracker.d.ts +320 -0
- package/dist/migrations/progress-tracker.d.ts.map +1 -0
- package/dist/migrations/progress-tracker.js +443 -0
- package/dist/migrations/progress-tracker.js.map +1 -0
- package/dist/migrations/registry.d.ts +231 -0
- package/dist/migrations/registry.d.ts.map +1 -0
- package/dist/migrations/registry.js +376 -0
- package/dist/migrations/registry.js.map +1 -0
- package/dist/migrations/runner.d.ts +197 -0
- package/dist/migrations/runner.d.ts.map +1 -0
- package/dist/migrations/runner.js +1167 -0
- package/dist/migrations/runner.js.map +1 -0
- package/dist/migrations/schema-generator.d.ts +111 -0
- package/dist/migrations/schema-generator.d.ts.map +1 -0
- package/dist/migrations/schema-generator.js +335 -0
- package/dist/migrations/schema-generator.js.map +1 -0
- package/dist/migrations/testing.d.ts +321 -0
- package/dist/migrations/testing.d.ts.map +1 -0
- package/dist/migrations/testing.js +645 -0
- package/dist/migrations/testing.js.map +1 -0
- package/dist/migrations/types.d.ts +503 -0
- package/dist/migrations/types.d.ts.map +1 -0
- package/dist/migrations/types.js +11 -0
- package/dist/migrations/types.js.map +1 -0
- package/dist/migrations/validator.d.ts +215 -0
- package/dist/migrations/validator.d.ts.map +1 -0
- package/dist/migrations/validator.js +494 -0
- package/dist/migrations/validator.js.map +1 -0
- package/dist/observability/alerting.d.ts +116 -0
- package/dist/observability/alerting.d.ts.map +1 -0
- package/dist/observability/alerting.js +353 -0
- package/dist/observability/alerting.js.map +1 -0
- package/dist/observability/analytics-engine.d.ts +357 -0
- package/dist/observability/analytics-engine.d.ts.map +1 -0
- package/dist/observability/analytics-engine.js +430 -0
- package/dist/observability/analytics-engine.js.map +1 -0
- package/dist/observability/cost-metrics.d.ts +269 -0
- package/dist/observability/cost-metrics.d.ts.map +1 -0
- package/dist/observability/cost-metrics.js +560 -0
- package/dist/observability/cost-metrics.js.map +1 -0
- package/dist/observability/cross-do-tracing.d.ts +305 -0
- package/dist/observability/cross-do-tracing.d.ts.map +1 -0
- package/dist/observability/cross-do-tracing.js +431 -0
- package/dist/observability/cross-do-tracing.js.map +1 -0
- package/dist/observability/error-rate-collector.d.ts +163 -0
- package/dist/observability/error-rate-collector.d.ts.map +1 -0
- package/dist/observability/error-rate-collector.js +306 -0
- package/dist/observability/error-rate-collector.js.map +1 -0
- package/dist/observability/exporters.d.ts +231 -0
- package/dist/observability/exporters.d.ts.map +1 -0
- package/dist/observability/exporters.js +479 -0
- package/dist/observability/exporters.js.map +1 -0
- package/dist/observability/health-check.d.ts +106 -0
- package/dist/observability/health-check.d.ts.map +1 -0
- package/dist/observability/health-check.js +243 -0
- package/dist/observability/health-check.js.map +1 -0
- package/dist/observability/index.d.ts +297 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +455 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/instrumentation.d.ts +222 -0
- package/dist/observability/instrumentation.d.ts.map +1 -0
- package/dist/observability/instrumentation.js +532 -0
- package/dist/observability/instrumentation.js.map +1 -0
- package/dist/observability/memory-metrics.d.ts +227 -0
- package/dist/observability/memory-metrics.d.ts.map +1 -0
- package/dist/observability/memory-metrics.js +688 -0
- package/dist/observability/memory-metrics.js.map +1 -0
- package/dist/observability/metrics-endpoint.d.ts +91 -0
- package/dist/observability/metrics-endpoint.d.ts.map +1 -0
- package/dist/observability/metrics-endpoint.js +246 -0
- package/dist/observability/metrics-endpoint.js.map +1 -0
- package/dist/observability/metrics.d.ts +88 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +253 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/observability-features.d.ts +488 -0
- package/dist/observability/observability-features.d.ts.map +1 -0
- package/dist/observability/observability-features.js +773 -0
- package/dist/observability/observability-features.js.map +1 -0
- package/dist/observability/prometheus.d.ts +39 -0
- package/dist/observability/prometheus.d.ts.map +1 -0
- package/dist/observability/prometheus.js +120 -0
- package/dist/observability/prometheus.js.map +1 -0
- package/dist/observability/propagation.d.ts +126 -0
- package/dist/observability/propagation.d.ts.map +1 -0
- package/dist/observability/propagation.js +234 -0
- package/dist/observability/propagation.js.map +1 -0
- package/dist/observability/query-latency.d.ts +243 -0
- package/dist/observability/query-latency.d.ts.map +1 -0
- package/dist/observability/query-latency.js +292 -0
- package/dist/observability/query-latency.js.map +1 -0
- package/dist/observability/query-performance.d.ts +169 -0
- package/dist/observability/query-performance.d.ts.map +1 -0
- package/dist/observability/query-performance.js +290 -0
- package/dist/observability/query-performance.js.map +1 -0
- package/dist/observability/storage-tier-metrics.d.ts +174 -0
- package/dist/observability/storage-tier-metrics.d.ts.map +1 -0
- package/dist/observability/storage-tier-metrics.js +306 -0
- package/dist/observability/storage-tier-metrics.js.map +1 -0
- package/dist/observability/tier-cost-optimizer.d.ts +155 -0
- package/dist/observability/tier-cost-optimizer.d.ts.map +1 -0
- package/dist/observability/tier-cost-optimizer.js +536 -0
- package/dist/observability/tier-cost-optimizer.js.map +1 -0
- package/dist/observability/tracer.d.ts +149 -0
- package/dist/observability/tracer.d.ts.map +1 -0
- package/dist/observability/tracer.js +435 -0
- package/dist/observability/tracer.js.map +1 -0
- package/dist/observability/types.d.ts +402 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/observability/types.js +103 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/pglite/workers-pglite.d.ts +138 -0
- package/dist/pglite/workers-pglite.d.ts.map +1 -0
- package/dist/pglite/workers-pglite.js +143 -0
- package/dist/pglite/workers-pglite.js.map +1 -0
- package/dist/pglite-assets/pglite.data +0 -0
- package/dist/pglite-assets/pglite.wasm +0 -0
- package/dist/playground/index.d.ts +52 -0
- package/dist/playground/index.d.ts.map +1 -0
- package/dist/playground/index.js +55 -0
- package/dist/playground/index.js.map +1 -0
- package/dist/playground/keyboard-shortcuts.d.ts +116 -0
- package/dist/playground/keyboard-shortcuts.d.ts.map +1 -0
- package/dist/playground/keyboard-shortcuts.js +588 -0
- package/dist/playground/keyboard-shortcuts.js.map +1 -0
- package/dist/playground/playground.d.ts +82 -0
- package/dist/playground/playground.d.ts.map +1 -0
- package/dist/playground/playground.js +271 -0
- package/dist/playground/playground.js.map +1 -0
- package/dist/playground/query-executor.d.ts +115 -0
- package/dist/playground/query-executor.d.ts.map +1 -0
- package/dist/playground/query-executor.js +558 -0
- package/dist/playground/query-executor.js.map +1 -0
- package/dist/playground/query-history.d.ts +92 -0
- package/dist/playground/query-history.d.ts.map +1 -0
- package/dist/playground/query-history.js +259 -0
- package/dist/playground/query-history.js.map +1 -0
- package/dist/playground/result-formatter.d.ts +59 -0
- package/dist/playground/result-formatter.d.ts.map +1 -0
- package/dist/playground/result-formatter.js +341 -0
- package/dist/playground/result-formatter.js.map +1 -0
- package/dist/playground/sample-datasets.d.ts +77 -0
- package/dist/playground/sample-datasets.d.ts.map +1 -0
- package/dist/playground/sample-datasets.js +641 -0
- package/dist/playground/sample-datasets.js.map +1 -0
- package/dist/playground/sample-queries.d.ts +73 -0
- package/dist/playground/sample-queries.d.ts.map +1 -0
- package/dist/playground/sample-queries.js +1095 -0
- package/dist/playground/sample-queries.js.map +1 -0
- package/dist/playground/schema-explorer.d.ts +55 -0
- package/dist/playground/schema-explorer.d.ts.map +1 -0
- package/dist/playground/schema-explorer.js +473 -0
- package/dist/playground/schema-explorer.js.map +1 -0
- package/dist/playground/types.d.ts +430 -0
- package/dist/playground/types.d.ts.map +1 -0
- package/dist/playground/types.js +10 -0
- package/dist/playground/types.js.map +1 -0
- package/dist/readonly/cache-reader.d.ts +145 -0
- package/dist/readonly/cache-reader.d.ts.map +1 -0
- package/dist/readonly/cache-reader.js +198 -0
- package/dist/readonly/cache-reader.js.map +1 -0
- package/dist/readonly/config.d.ts +74 -0
- package/dist/readonly/config.d.ts.map +1 -0
- package/dist/readonly/config.js +67 -0
- package/dist/readonly/config.js.map +1 -0
- package/dist/readonly/index.d.ts +22 -0
- package/dist/readonly/index.d.ts.map +1 -0
- package/dist/readonly/index.js +17 -0
- package/dist/readonly/index.js.map +1 -0
- package/dist/readonly/pglite-wrapper.d.ts +82 -0
- package/dist/readonly/pglite-wrapper.d.ts.map +1 -0
- package/dist/readonly/pglite-wrapper.js +123 -0
- package/dist/readonly/pglite-wrapper.js.map +1 -0
- package/dist/readonly/worker.d.ts +142 -0
- package/dist/readonly/worker.d.ts.map +1 -0
- package/dist/readonly/worker.js +187 -0
- package/dist/readonly/worker.js.map +1 -0
- package/dist/readonly/write-blocker.d.ts +47 -0
- package/dist/readonly/write-blocker.d.ts.map +1 -0
- package/dist/readonly/write-blocker.js +136 -0
- package/dist/readonly/write-blocker.js.map +1 -0
- package/dist/recovery/disaster-recovery.d.ts +326 -0
- package/dist/recovery/disaster-recovery.d.ts.map +1 -0
- package/dist/recovery/disaster-recovery.js +799 -0
- package/dist/recovery/disaster-recovery.js.map +1 -0
- package/dist/recovery/index.d.ts +12 -0
- package/dist/recovery/index.d.ts.map +1 -0
- package/dist/recovery/index.js +12 -0
- package/dist/recovery/index.js.map +1 -0
- package/dist/recovery/parquet-parser.d.ts +321 -0
- package/dist/recovery/parquet-parser.d.ts.map +1 -0
- package/dist/recovery/parquet-parser.js +797 -0
- package/dist/recovery/parquet-parser.js.map +1 -0
- package/dist/retention/index.d.ts +50 -0
- package/dist/retention/index.d.ts.map +1 -0
- package/dist/retention/index.js +50 -0
- package/dist/retention/index.js.map +1 -0
- package/dist/retention/policy.d.ts +344 -0
- package/dist/retention/policy.d.ts.map +1 -0
- package/dist/retention/policy.js +472 -0
- package/dist/retention/policy.js.map +1 -0
- package/dist/retention/purger.d.ts +187 -0
- package/dist/retention/purger.d.ts.map +1 -0
- package/dist/retention/purger.js +411 -0
- package/dist/retention/purger.js.map +1 -0
- package/dist/rls/auth-integration.d.ts +280 -0
- package/dist/rls/auth-integration.d.ts.map +1 -0
- package/dist/rls/auth-integration.js +399 -0
- package/dist/rls/auth-integration.js.map +1 -0
- package/dist/rls/generator.d.ts +249 -0
- package/dist/rls/generator.d.ts.map +1 -0
- package/dist/rls/generator.js +495 -0
- package/dist/rls/generator.js.map +1 -0
- package/dist/rls/index.d.ts +26 -0
- package/dist/rls/index.d.ts.map +1 -0
- package/dist/rls/index.js +58 -0
- package/dist/rls/index.js.map +1 -0
- package/dist/rls/policy.d.ts +116 -0
- package/dist/rls/policy.d.ts.map +1 -0
- package/dist/rls/policy.js +77 -0
- package/dist/rls/policy.js.map +1 -0
- package/dist/rls/validator.d.ts +155 -0
- package/dist/rls/validator.d.ts.map +1 -0
- package/dist/rls/validator.js +792 -0
- package/dist/rls/validator.js.map +1 -0
- package/dist/routing/adaptive-router.d.ts +317 -0
- package/dist/routing/adaptive-router.d.ts.map +1 -0
- package/dist/routing/adaptive-router.js +554 -0
- package/dist/routing/adaptive-router.js.map +1 -0
- package/dist/routing/circuit-breaker.d.ts +339 -0
- package/dist/routing/circuit-breaker.d.ts.map +1 -0
- package/dist/routing/circuit-breaker.js +620 -0
- package/dist/routing/circuit-breaker.js.map +1 -0
- package/dist/routing/cost-metrics.d.ts +133 -0
- package/dist/routing/cost-metrics.d.ts.map +1 -0
- package/dist/routing/cost-metrics.js +259 -0
- package/dist/routing/cost-metrics.js.map +1 -0
- package/dist/routing/do-connection-pool.d.ts +243 -0
- package/dist/routing/do-connection-pool.d.ts.map +1 -0
- package/dist/routing/do-connection-pool.js +572 -0
- package/dist/routing/do-connection-pool.js.map +1 -0
- package/dist/routing/index.d.ts +59 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +59 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/query-complexity-estimator.d.ts +73 -0
- package/dist/routing/query-complexity-estimator.d.ts.map +1 -0
- package/dist/routing/query-complexity-estimator.js +327 -0
- package/dist/routing/query-complexity-estimator.js.map +1 -0
- package/dist/routing/request-coalescing.d.ts +178 -0
- package/dist/routing/request-coalescing.d.ts.map +1 -0
- package/dist/routing/request-coalescing.js +325 -0
- package/dist/routing/request-coalescing.js.map +1 -0
- package/dist/routing/runtime-router.d.ts +107 -0
- package/dist/routing/runtime-router.d.ts.map +1 -0
- package/dist/routing/runtime-router.js +246 -0
- package/dist/routing/runtime-router.js.map +1 -0
- package/dist/routing/tenant-router.d.ts +848 -0
- package/dist/routing/tenant-router.d.ts.map +1 -0
- package/dist/routing/tenant-router.js +1056 -0
- package/dist/routing/tenant-router.js.map +1 -0
- package/dist/routing/websocket-pool.d.ts +119 -0
- package/dist/routing/websocket-pool.d.ts.map +1 -0
- package/dist/routing/websocket-pool.js +436 -0
- package/dist/routing/websocket-pool.js.map +1 -0
- package/dist/storage/cache-layer.d.ts +159 -0
- package/dist/storage/cache-layer.d.ts.map +1 -0
- package/dist/storage/cache-layer.js +245 -0
- package/dist/storage/cache-layer.js.map +1 -0
- package/dist/storage/cost-aware-tiering.d.ts +258 -0
- package/dist/storage/cost-aware-tiering.d.ts.map +1 -0
- package/dist/storage/cost-aware-tiering.js +526 -0
- package/dist/storage/cost-aware-tiering.js.map +1 -0
- package/dist/storage/index.d.ts +87 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +78 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/interfaces.d.ts +856 -0
- package/dist/storage/interfaces.d.ts.map +1 -0
- package/dist/storage/interfaces.js +69 -0
- package/dist/storage/interfaces.js.map +1 -0
- package/dist/storage/r2-layer.d.ts +226 -0
- package/dist/storage/r2-layer.d.ts.map +1 -0
- package/dist/storage/r2-layer.js +307 -0
- package/dist/storage/r2-layer.js.map +1 -0
- package/dist/storage/r2-overflow.d.ts +344 -0
- package/dist/storage/r2-overflow.d.ts.map +1 -0
- package/dist/storage/r2-overflow.js +730 -0
- package/dist/storage/r2-overflow.js.map +1 -0
- package/dist/storage/r2-page-vfs.d.ts +374 -0
- package/dist/storage/r2-page-vfs.d.ts.map +1 -0
- package/dist/storage/r2-page-vfs.js +754 -0
- package/dist/storage/r2-page-vfs.js.map +1 -0
- package/dist/storage/swr-cache.d.ts +181 -0
- package/dist/storage/swr-cache.d.ts.map +1 -0
- package/dist/storage/swr-cache.js +295 -0
- package/dist/storage/swr-cache.js.map +1 -0
- package/dist/storage/tiered-orchestrator.d.ts +951 -0
- package/dist/storage/tiered-orchestrator.d.ts.map +1 -0
- package/dist/storage/tiered-orchestrator.js +1731 -0
- package/dist/storage/tiered-orchestrator.js.map +1 -0
- package/dist/storage/tiered-vfs-swr.d.ts +279 -0
- package/dist/storage/tiered-vfs-swr.d.ts.map +1 -0
- package/dist/storage/tiered-vfs-swr.js +584 -0
- package/dist/storage/tiered-vfs-swr.js.map +1 -0
- package/dist/storage/tiered-vfs.d.ts +405 -0
- package/dist/storage/tiered-vfs.d.ts.map +1 -0
- package/dist/storage/tiered-vfs.js +833 -0
- package/dist/storage/tiered-vfs.js.map +1 -0
- package/dist/streaming/backpressure-controller.d.ts +173 -0
- package/dist/streaming/backpressure-controller.d.ts.map +1 -0
- package/dist/streaming/backpressure-controller.js +344 -0
- package/dist/streaming/backpressure-controller.js.map +1 -0
- package/dist/streaming/buffer-pool.d.ts +241 -0
- package/dist/streaming/buffer-pool.d.ts.map +1 -0
- package/dist/streaming/buffer-pool.js +381 -0
- package/dist/streaming/buffer-pool.js.map +1 -0
- package/dist/streaming/cdc-iceberg-connector.d.ts +272 -0
- package/dist/streaming/cdc-iceberg-connector.d.ts.map +1 -0
- package/dist/streaming/cdc-iceberg-connector.js +408 -0
- package/dist/streaming/cdc-iceberg-connector.js.map +1 -0
- package/dist/streaming/index.d.ts +111 -0
- package/dist/streaming/index.d.ts.map +1 -0
- package/dist/streaming/index.js +128 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/streaming/live-cdc-stream.d.ts +400 -0
- package/dist/streaming/live-cdc-stream.d.ts.map +1 -0
- package/dist/streaming/live-cdc-stream.js +703 -0
- package/dist/streaming/live-cdc-stream.js.map +1 -0
- package/dist/streaming/memory-bounded-stream.d.ts +207 -0
- package/dist/streaming/memory-bounded-stream.d.ts.map +1 -0
- package/dist/streaming/memory-bounded-stream.js +340 -0
- package/dist/streaming/memory-bounded-stream.js.map +1 -0
- package/dist/streaming/query-streamer.d.ts +379 -0
- package/dist/streaming/query-streamer.d.ts.map +1 -0
- package/dist/streaming/query-streamer.js +495 -0
- package/dist/streaming/query-streamer.js.map +1 -0
- package/dist/streaming/response-streaming.d.ts +203 -0
- package/dist/streaming/response-streaming.d.ts.map +1 -0
- package/dist/streaming/response-streaming.js +449 -0
- package/dist/streaming/response-streaming.js.map +1 -0
- package/dist/types/branded.d.ts +859 -0
- package/dist/types/branded.d.ts.map +1 -0
- package/dist/types/branded.js +891 -0
- package/dist/types/branded.js.map +1 -0
- package/dist/types/utilities.d.ts +757 -0
- package/dist/types/utilities.d.ts.map +1 -0
- package/dist/types/utilities.js +447 -0
- package/dist/types/utilities.js.map +1 -0
- package/dist/wal/replay-engine.d.ts +344 -0
- package/dist/wal/replay-engine.d.ts.map +1 -0
- package/dist/wal/replay-engine.js +975 -0
- package/dist/wal/replay-engine.js.map +1 -0
- package/dist/worker/__mocks__/capnweb.d.ts +13 -0
- package/dist/worker/__mocks__/capnweb.d.ts.map +1 -0
- package/dist/worker/__mocks__/capnweb.js +15 -0
- package/dist/worker/__mocks__/capnweb.js.map +1 -0
- package/dist/worker/__mocks__/cloudflare-workers.d.ts +31 -0
- package/dist/worker/__mocks__/cloudflare-workers.d.ts.map +1 -0
- package/dist/worker/__mocks__/cloudflare-workers.js +33 -0
- package/dist/worker/__mocks__/cloudflare-workers.js.map +1 -0
- package/dist/worker/__mocks__/pglite.data.d.ts +3 -0
- package/dist/worker/__mocks__/pglite.data.d.ts.map +1 -0
- package/dist/worker/__mocks__/pglite.data.js +20 -0
- package/dist/worker/__mocks__/pglite.data.js.map +1 -0
- package/dist/worker/__mocks__/pglite.wasm.d.ts +3 -0
- package/dist/worker/__mocks__/pglite.wasm.d.ts.map +1 -0
- package/dist/worker/__mocks__/pglite.wasm.js +30 -0
- package/dist/worker/__mocks__/pglite.wasm.js.map +1 -0
- package/dist/worker/auth-rate-limiter.d.ts +270 -0
- package/dist/worker/auth-rate-limiter.d.ts.map +1 -0
- package/dist/worker/auth-rate-limiter.js +332 -0
- package/dist/worker/auth-rate-limiter.js.map +1 -0
- package/dist/worker/auth.d.ts +345 -0
- package/dist/worker/auth.d.ts.map +1 -0
- package/dist/worker/auth.js +837 -0
- package/dist/worker/auth.js.map +1 -0
- package/dist/worker/cdc-backpressure.d.ts +338 -0
- package/dist/worker/cdc-backpressure.d.ts.map +1 -0
- package/dist/worker/cdc-backpressure.js +619 -0
- package/dist/worker/cdc-backpressure.js.map +1 -0
- package/dist/worker/cdc-sse.d.ts +277 -0
- package/dist/worker/cdc-sse.d.ts.map +1 -0
- package/dist/worker/cdc-sse.js +528 -0
- package/dist/worker/cdc-sse.js.map +1 -0
- package/dist/worker/cdc-websocket.d.ts +252 -0
- package/dist/worker/cdc-websocket.d.ts.map +1 -0
- package/dist/worker/cdc-websocket.js +940 -0
- package/dist/worker/cdc-websocket.js.map +1 -0
- package/dist/worker/cdc.d.ts +95 -0
- package/dist/worker/cdc.d.ts.map +1 -0
- package/dist/worker/cdc.js +211 -0
- package/dist/worker/cdc.js.map +1 -0
- package/dist/worker/concerns/auth-concern.d.ts +50 -0
- package/dist/worker/concerns/auth-concern.d.ts.map +1 -0
- package/dist/worker/concerns/auth-concern.js +131 -0
- package/dist/worker/concerns/auth-concern.js.map +1 -0
- package/dist/worker/concerns/cdc-concern.d.ts +99 -0
- package/dist/worker/concerns/cdc-concern.d.ts.map +1 -0
- package/dist/worker/concerns/cdc-concern.js +137 -0
- package/dist/worker/concerns/cdc-concern.js.map +1 -0
- package/dist/worker/concerns/index.d.ts +22 -0
- package/dist/worker/concerns/index.d.ts.map +1 -0
- package/dist/worker/concerns/index.js +13 -0
- package/dist/worker/concerns/index.js.map +1 -0
- package/dist/worker/concerns/query-execution-concern.d.ts +104 -0
- package/dist/worker/concerns/query-execution-concern.d.ts.map +1 -0
- package/dist/worker/concerns/query-execution-concern.js +95 -0
- package/dist/worker/concerns/query-execution-concern.js.map +1 -0
- package/dist/worker/concerns/storage-orchestration-concern.d.ts +78 -0
- package/dist/worker/concerns/storage-orchestration-concern.d.ts.map +1 -0
- package/dist/worker/concerns/storage-orchestration-concern.js +240 -0
- package/dist/worker/concerns/storage-orchestration-concern.js.map +1 -0
- package/dist/worker/do-auth-manager.d.ts +108 -0
- package/dist/worker/do-auth-manager.d.ts.map +1 -0
- package/dist/worker/do-auth-manager.js +212 -0
- package/dist/worker/do-auth-manager.js.map +1 -0
- package/dist/worker/do-pglite-manager.d.ts +137 -0
- package/dist/worker/do-pglite-manager.d.ts.map +1 -0
- package/dist/worker/do-pglite-manager.js +228 -0
- package/dist/worker/do-pglite-manager.js.map +1 -0
- package/dist/worker/do.d.ts +556 -0
- package/dist/worker/do.d.ts.map +1 -0
- package/dist/worker/do.js +1441 -0
- package/dist/worker/do.js.map +1 -0
- package/dist/worker/entry.d.ts +23 -0
- package/dist/worker/entry.d.ts.map +1 -0
- package/dist/worker/entry.js +362 -0
- package/dist/worker/entry.js.map +1 -0
- package/dist/worker/errors.d.ts +106 -0
- package/dist/worker/errors.d.ts.map +1 -0
- package/dist/worker/errors.js +178 -0
- package/dist/worker/errors.js.map +1 -0
- package/dist/worker/health-check-manager.d.ts +141 -0
- package/dist/worker/health-check-manager.d.ts.map +1 -0
- package/dist/worker/health-check-manager.js +145 -0
- package/dist/worker/health-check-manager.js.map +1 -0
- package/dist/worker/index.d.ts +60 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +67 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/memory-pressure.d.ts +892 -0
- package/dist/worker/memory-pressure.d.ts.map +1 -0
- package/dist/worker/memory-pressure.js +1990 -0
- package/dist/worker/memory-pressure.js.map +1 -0
- package/dist/worker/migration-manager.d.ts +153 -0
- package/dist/worker/migration-manager.d.ts.map +1 -0
- package/dist/worker/migration-manager.js +461 -0
- package/dist/worker/migration-manager.js.map +1 -0
- package/dist/worker/plugin-manager.d.ts +147 -0
- package/dist/worker/plugin-manager.d.ts.map +1 -0
- package/dist/worker/plugin-manager.js +408 -0
- package/dist/worker/plugin-manager.js.map +1 -0
- package/dist/worker/proxy.d.ts +330 -0
- package/dist/worker/proxy.d.ts.map +1 -0
- package/dist/worker/proxy.js +504 -0
- package/dist/worker/proxy.js.map +1 -0
- package/dist/worker/query-execution-manager.d.ts +107 -0
- package/dist/worker/query-execution-manager.d.ts.map +1 -0
- package/dist/worker/query-execution-manager.js +155 -0
- package/dist/worker/query-execution-manager.js.map +1 -0
- package/dist/worker/query-executor.d.ts +163 -0
- package/dist/worker/query-executor.d.ts.map +1 -0
- package/dist/worker/query-executor.js +413 -0
- package/dist/worker/query-executor.js.map +1 -0
- package/dist/worker/query-stats-manager.d.ts +117 -0
- package/dist/worker/query-stats-manager.d.ts.map +1 -0
- package/dist/worker/query-stats-manager.js +162 -0
- package/dist/worker/query-stats-manager.js.map +1 -0
- package/dist/worker/result-handler.d.ts +192 -0
- package/dist/worker/result-handler.d.ts.map +1 -0
- package/dist/worker/result-handler.js +346 -0
- package/dist/worker/result-handler.js.map +1 -0
- package/dist/worker/routes.d.ts +135 -0
- package/dist/worker/routes.d.ts.map +1 -0
- package/dist/worker/routes.js +460 -0
- package/dist/worker/routes.js.map +1 -0
- package/dist/worker/rpc-methods-manager.d.ts +142 -0
- package/dist/worker/rpc-methods-manager.d.ts.map +1 -0
- package/dist/worker/rpc-methods-manager.js +195 -0
- package/dist/worker/rpc-methods-manager.js.map +1 -0
- package/dist/worker/rpc.d.ts +259 -0
- package/dist/worker/rpc.d.ts.map +1 -0
- package/dist/worker/rpc.js +398 -0
- package/dist/worker/rpc.js.map +1 -0
- package/dist/worker/schema-version.d.ts +209 -0
- package/dist/worker/schema-version.d.ts.map +1 -0
- package/dist/worker/schema-version.js +450 -0
- package/dist/worker/schema-version.js.map +1 -0
- package/dist/worker/session-manager.d.ts +282 -0
- package/dist/worker/session-manager.d.ts.map +1 -0
- package/dist/worker/session-manager.js +523 -0
- package/dist/worker/session-manager.js.map +1 -0
- package/dist/worker/shutdown-manager.d.ts +188 -0
- package/dist/worker/shutdown-manager.d.ts.map +1 -0
- package/dist/worker/shutdown-manager.js +347 -0
- package/dist/worker/shutdown-manager.js.map +1 -0
- package/dist/worker/sql-transform.d.ts +61 -0
- package/dist/worker/sql-transform.d.ts.map +1 -0
- package/dist/worker/sql-transform.js +312 -0
- package/dist/worker/sql-transform.js.map +1 -0
- package/dist/worker/types.d.ts +738 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/types.js +6 -0
- package/dist/worker/types.js.map +1 -0
- package/dist/worker/user-routes.d.ts +76 -0
- package/dist/worker/user-routes.d.ts.map +1 -0
- package/dist/worker/user-routes.js +188 -0
- package/dist/worker/user-routes.js.map +1 -0
- package/dist/worker/wal-facade.d.ts +138 -0
- package/dist/worker/wal-facade.d.ts.map +1 -0
- package/dist/worker/wal-facade.js +184 -0
- package/dist/worker/wal-facade.js.map +1 -0
- package/dist/worker/wal-r2.d.ts +271 -0
- package/dist/worker/wal-r2.d.ts.map +1 -0
- package/dist/worker/wal-r2.js +689 -0
- package/dist/worker/wal-r2.js.map +1 -0
- package/dist/worker/wal-replay.d.ts +361 -0
- package/dist/worker/wal-replay.d.ts.map +1 -0
- package/dist/worker/wal-replay.js +628 -0
- package/dist/worker/wal-replay.js.map +1 -0
- package/dist/worker/wal-retention.d.ts +389 -0
- package/dist/worker/wal-retention.d.ts.map +1 -0
- package/dist/worker/wal-retention.js +763 -0
- package/dist/worker/wal-retention.js.map +1 -0
- package/dist/worker/wal.d.ts +278 -0
- package/dist/worker/wal.d.ts.map +1 -0
- package/dist/worker/wal.js +467 -0
- package/dist/worker/wal.js.map +1 -0
- package/dist/worker/websocket.d.ts +85 -0
- package/dist/worker/websocket.d.ts.map +1 -0
- package/dist/worker/websocket.js +227 -0
- package/dist/worker/websocket.js.map +1 -0
- package/package.json +108 -0
- package/src/cdc/change-stream.ts +137 -0
- package/src/cdc/filter.ts +646 -0
- package/src/cdc/index.ts +112 -0
- package/src/cdc/resume-token.ts +280 -0
- package/src/cdc/transport/index.ts +7 -0
- package/src/cdc/transport/sse.ts +723 -0
- package/src/cdc/transport/websocket.ts +873 -0
- package/src/cdc/types.ts +346 -0
- package/src/config/index.ts +25 -0
- package/src/config/memory.ts +177 -0
- package/src/config/storage.ts +204 -0
- package/src/config/streaming.ts +147 -0
- package/src/config/timeouts.ts +221 -0
- package/src/extensions/config.test.ts +187 -0
- package/src/extensions/config.ts +278 -0
- package/src/extensions/geo.test.ts +455 -0
- package/src/extensions/geo.ts +858 -0
- package/src/extensions/index.test.ts +259 -0
- package/src/extensions/index.ts +227 -0
- package/src/extensions/loader.test.ts +555 -0
- package/src/extensions/loader.ts +588 -0
- package/src/extensions/pgmq-lite.test.ts +727 -0
- package/src/extensions/pgmq-lite.ts +770 -0
- package/src/extensions/plugins.test.ts +528 -0
- package/src/extensions/plugins.ts +718 -0
- package/src/extensions/registry.test.ts +202 -0
- package/src/extensions/registry.ts +267 -0
- package/src/extensions/vector.test.ts +195 -0
- package/src/extensions/vector.ts +217 -0
- package/src/iceberg/SCHEDULER.md +580 -0
- package/src/iceberg/analytics.test.ts +703 -0
- package/src/iceberg/analytics.ts +727 -0
- package/src/iceberg/catalog-api.test.ts +838 -0
- package/src/iceberg/catalog-api.ts +520 -0
- package/src/iceberg/catalog.test.ts +680 -0
- package/src/iceberg/catalog.ts +1007 -0
- package/src/iceberg/iceberg.test.ts +705 -0
- package/src/iceberg/index.ts +406 -0
- package/src/iceberg/metadata.test.ts +632 -0
- package/src/iceberg/metadata.ts +649 -0
- package/src/iceberg/optimizer.test.ts +868 -0
- package/src/iceberg/optimizer.ts +1287 -0
- package/src/iceberg/parquet.test.ts +899 -0
- package/src/iceberg/parquet.ts +1640 -0
- package/src/iceberg/r2-organization.test.ts +615 -0
- package/src/iceberg/r2-organization.ts +951 -0
- package/src/iceberg/scheduler-do-example.ts +364 -0
- package/src/iceberg/scheduler.test.ts +861 -0
- package/src/iceberg/scheduler.ts +1201 -0
- package/src/iceberg/schema.test.ts +547 -0
- package/src/iceberg/schema.ts +616 -0
- package/src/iceberg/snapshot-manager.test.ts +919 -0
- package/src/iceberg/snapshot-manager.ts +1369 -0
- package/src/iceberg/sql-router.test.ts +334 -0
- package/src/iceberg/sql-router.ts +337 -0
- package/src/iceberg/test-fixtures.ts +605 -0
- package/src/iceberg/time-travel-api.test.ts +1029 -0
- package/src/iceberg/time-travel-api.ts +731 -0
- package/src/iceberg/time-travel.test.ts +1218 -0
- package/src/iceberg/time-travel.ts +1052 -0
- package/src/iceberg/transformer.test.ts +689 -0
- package/src/iceberg/transformer.ts +1029 -0
- package/src/iceberg/types.ts +373 -0
- package/src/iceberg/writer.test.ts +716 -0
- package/src/iceberg/writer.ts +590 -0
- package/src/index.ts +212 -0
- package/src/lineage/index.ts +42 -0
- package/src/lineage/integration.ts +334 -0
- package/src/lineage/tracker.ts +1618 -0
- package/src/lineage/types.ts +354 -0
- package/src/middleware/index.ts +36 -0
- package/src/middleware/rate-limit-concurrent.test.ts +794 -0
- package/src/middleware/rate-limit.test.ts +1568 -0
- package/src/middleware/rate-limit.ts +840 -0
- package/src/migration-tooling/external-migration.test.ts +1864 -0
- package/src/migration-tooling/external-migration.ts +2355 -0
- package/src/migration-tooling/index.ts +19 -0
- package/src/migrations/ARCHITECTURE.md +474 -0
- package/src/migrations/PROGRESS_TRACKING.md +485 -0
- package/src/migrations/auto-migrator.test.ts +732 -0
- package/src/migrations/auto-migrator.ts +531 -0
- package/src/migrations/bulk-orchestrator.test.ts +801 -0
- package/src/migrations/bulk-orchestrator.ts +1039 -0
- package/src/migrations/compatibility.test.ts +958 -0
- package/src/migrations/compatibility.ts +902 -0
- package/src/migrations/do-migrations.test.ts +2620 -0
- package/src/migrations/do-migrations.ts +1289 -0
- package/src/migrations/do-migrations.types.ts +715 -0
- package/src/migrations/drizzle-compat.test.ts +210 -0
- package/src/migrations/drizzle-compat.ts +337 -0
- package/src/migrations/index.ts +334 -0
- package/src/migrations/migration-api.test.ts +438 -0
- package/src/migrations/migration-api.ts +704 -0
- package/src/migrations/progress-tracker-do.ts +518 -0
- package/src/migrations/progress-tracker-kv.ts +305 -0
- package/src/migrations/progress-tracker.test.ts +937 -0
- package/src/migrations/progress-tracker.ts +665 -0
- package/src/migrations/registry.test.ts +331 -0
- package/src/migrations/registry.ts +468 -0
- package/src/migrations/rollback.test.ts +644 -0
- package/src/migrations/runner.test.ts +807 -0
- package/src/migrations/runner.test.ts.backup +759 -0
- package/src/migrations/runner.ts +1459 -0
- package/src/migrations/schema-generator.test.ts +649 -0
- package/src/migrations/schema-generator.ts +513 -0
- package/src/migrations/testing.ts +1037 -0
- package/src/migrations/types.ts +573 -0
- package/src/migrations/validator.test.ts +660 -0
- package/src/migrations/validator.ts +741 -0
- package/src/observability/alerting.test.ts +1133 -0
- package/src/observability/alerting.ts +455 -0
- package/src/observability/analytics-engine.ts +733 -0
- package/src/observability/cost-metrics.ts +804 -0
- package/src/observability/cross-do-tracing.test.ts +516 -0
- package/src/observability/cross-do-tracing.ts +588 -0
- package/src/observability/dashboards/postgres-do-overview.json +1656 -0
- package/src/observability/error-rate-collector.test.ts +977 -0
- package/src/observability/error-rate-collector.ts +518 -0
- package/src/observability/exporters.test.ts +365 -0
- package/src/observability/exporters.ts +650 -0
- package/src/observability/health-check.test.ts +353 -0
- package/src/observability/health-check.ts +341 -0
- package/src/observability/index.test.ts +298 -0
- package/src/observability/index.ts +885 -0
- package/src/observability/instrumentation.test.ts +428 -0
- package/src/observability/instrumentation.ts +788 -0
- package/src/observability/memory-metrics.test.ts +355 -0
- package/src/observability/memory-metrics.ts +990 -0
- package/src/observability/metrics-endpoint.test.ts +402 -0
- package/src/observability/metrics-endpoint.ts +374 -0
- package/src/observability/metrics.test.ts +291 -0
- package/src/observability/metrics.ts +315 -0
- package/src/observability/observability-features.ts +1296 -0
- package/src/observability/prometheus.test.ts +292 -0
- package/src/observability/prometheus.ts +170 -0
- package/src/observability/propagation.test.ts +417 -0
- package/src/observability/propagation.ts +294 -0
- package/src/observability/query-latency.ts +586 -0
- package/src/observability/query-performance.test.ts +406 -0
- package/src/observability/query-performance.ts +491 -0
- package/src/observability/storage-tier-metrics.test.ts +633 -0
- package/src/observability/storage-tier-metrics.ts +570 -0
- package/src/observability/tier-cost-optimizer.ts +740 -0
- package/src/observability/tracer.test.ts +346 -0
- package/src/observability/tracer.ts +585 -0
- package/src/observability/types.test.ts +726 -0
- package/src/observability/types.ts +434 -0
- package/src/pglite/auto-demotion.test.ts +477 -0
- package/src/pglite/auto-demotion.ts +385 -0
- package/src/pglite/auto-promotion.test.ts +824 -0
- package/src/pglite/auto-promotion.ts +547 -0
- package/src/pglite/cache-layer.test.ts +469 -0
- package/src/pglite/cache-layer.ts +271 -0
- package/src/pglite/cold-start-manager.ts +1260 -0
- package/src/pglite/cold-start-optimizer.test.ts +937 -0
- package/src/pglite/cold-start-optimizer.ts +1895 -0
- package/src/pglite/dovfs-adapter.ts +1122 -0
- package/src/pglite/dovfs.ts +1258 -0
- package/src/pglite/etag-cache.test.ts +844 -0
- package/src/pglite/etag-cache.ts +526 -0
- package/src/pglite/index.ts +442 -0
- package/src/pglite/init.test.ts +455 -0
- package/src/pglite/init.ts +574 -0
- package/src/pglite/lifecycle.test.ts +599 -0
- package/src/pglite/lifecycle.ts +704 -0
- package/src/pglite/parallel-loader.test.ts +586 -0
- package/src/pglite/parallel-loader.ts +481 -0
- package/src/pglite/production-pglite.test.ts +666 -0
- package/src/pglite/production-pglite.ts +537 -0
- package/src/pglite/query-executor.ts +614 -0
- package/src/pglite/r2-layer.test.ts +501 -0
- package/src/pglite/r2-layer.ts +322 -0
- package/src/pglite/tiered-init.test.ts +725 -0
- package/src/pglite/tiered-init.ts +556 -0
- package/src/pglite/tiered-vfs.test.ts +726 -0
- package/src/pglite/tiered-vfs.ts +33 -0
- package/src/pglite/tiering-stats.test.ts +531 -0
- package/src/pglite/tiering-stats.ts +407 -0
- package/src/pglite/transaction-hooks.ts +343 -0
- package/src/pglite/warm-loader.test.ts +1701 -0
- package/src/pglite/warm-loader.ts +528 -0
- package/src/pglite/workers-pglite.ts +224 -0
- package/src/pglite-assets/pglite.data +0 -0
- package/src/pglite-assets/pglite.wasm +0 -0
- package/src/pglite.d.ts +47 -0
- package/src/playground/index.ts +137 -0
- package/src/playground/keyboard-shortcuts.ts +677 -0
- package/src/playground/playground.ts +323 -0
- package/src/playground/query-executor.ts +669 -0
- package/src/playground/query-history.ts +328 -0
- package/src/playground/result-formatter.ts +420 -0
- package/src/playground/sample-datasets.ts +674 -0
- package/src/playground/sample-queries.ts +1168 -0
- package/src/playground/schema-explorer.ts +558 -0
- package/src/playground/types.ts +518 -0
- package/src/readonly/cache-reader.test.ts +460 -0
- package/src/readonly/cache-reader.ts +313 -0
- package/src/readonly/config.test.ts +187 -0
- package/src/readonly/config.ts +128 -0
- package/src/readonly/index.ts +50 -0
- package/src/readonly/pglite-wrapper.test.ts +278 -0
- package/src/readonly/pglite-wrapper.ts +184 -0
- package/src/readonly/worker.test.ts +533 -0
- package/src/readonly/worker.ts +341 -0
- package/src/readonly/write-blocker.test.ts +459 -0
- package/src/readonly/write-blocker.ts +175 -0
- package/src/recovery/disaster-recovery.test.ts +618 -0
- package/src/recovery/disaster-recovery.ts +1181 -0
- package/src/recovery/index.ts +43 -0
- package/src/recovery/parquet-parser.ts +974 -0
- package/src/retention/index.ts +74 -0
- package/src/retention/policy.test.ts +571 -0
- package/src/retention/policy.ts +774 -0
- package/src/retention/purger.test.ts +465 -0
- package/src/retention/purger.ts +558 -0
- package/src/rls/auth-integration.test.ts +752 -0
- package/src/rls/auth-integration.ts +533 -0
- package/src/rls/generator.test.ts +829 -0
- package/src/rls/generator.ts +573 -0
- package/src/rls/index.ts +128 -0
- package/src/rls/policy.ts +208 -0
- package/src/rls/rls.test.ts +1071 -0
- package/src/rls/validator.test.ts +930 -0
- package/src/rls/validator.ts +895 -0
- package/src/routing/adaptive-router.test.ts +884 -0
- package/src/routing/adaptive-router.ts +845 -0
- package/src/routing/circuit-breaker.test.ts +1505 -0
- package/src/routing/circuit-breaker.ts +852 -0
- package/src/routing/cost-metrics.test.ts +565 -0
- package/src/routing/cost-metrics.ts +408 -0
- package/src/routing/do-connection-pool.test.ts +1109 -0
- package/src/routing/do-connection-pool.ts +828 -0
- package/src/routing/index.ts +158 -0
- package/src/routing/query-complexity-estimator.test.ts +356 -0
- package/src/routing/query-complexity-estimator.ts +444 -0
- package/src/routing/request-coalescing.test.ts +738 -0
- package/src/routing/request-coalescing.ts +475 -0
- package/src/routing/runtime-router.test.ts +436 -0
- package/src/routing/runtime-router.ts +357 -0
- package/src/routing/tenant-router.test.ts +2493 -0
- package/src/routing/tenant-router.ts +1908 -0
- package/src/routing/websocket-pool.test.ts +551 -0
- package/src/routing/websocket-pool.ts +577 -0
- package/src/storage/access-pattern-tracker.test.ts +874 -0
- package/src/storage/cache-layer.test.ts +560 -0
- package/src/storage/cache-layer.ts +328 -0
- package/src/storage/cost-aware-tiering.test.ts +652 -0
- package/src/storage/cost-aware-tiering.ts +794 -0
- package/src/storage/do-sqlite-blobs.test.ts +937 -0
- package/src/storage/index.ts +272 -0
- package/src/storage/interfaces.ts +974 -0
- package/src/storage/r2-layer.test.ts +653 -0
- package/src/storage/r2-layer.ts +434 -0
- package/src/storage/r2-overflow.ts +920 -0
- package/src/storage/r2-page-vfs.test.ts +2348 -0
- package/src/storage/r2-page-vfs.ts +1054 -0
- package/src/storage/swr-cache.test.ts +832 -0
- package/src/storage/swr-cache.ts +398 -0
- package/src/storage/swr-tiered-integration.test.ts +617 -0
- package/src/storage/tiered-orchestrator.test.ts +2441 -0
- package/src/storage/tiered-orchestrator.ts +2081 -0
- package/src/storage/tiered-vfs-swr.test.ts +736 -0
- package/src/storage/tiered-vfs-swr.ts +735 -0
- package/src/storage/tiered-vfs.test.ts +793 -0
- package/src/storage/tiered-vfs.ts +1082 -0
- package/src/streaming/backpressure-controller.ts +452 -0
- package/src/streaming/buffer-pool.ts +484 -0
- package/src/streaming/cdc-iceberg-connector.ts +605 -0
- package/src/streaming/index.ts +225 -0
- package/src/streaming/live-cdc-stream.ts +985 -0
- package/src/streaming/memory-bounded-stream.ts +443 -0
- package/src/streaming/query-streamer.ts +662 -0
- package/src/streaming/response-streaming.ts +557 -0
- package/src/types/branded.ts +1075 -0
- package/src/types/branded.ts.backup +273 -0
- package/src/types/utilities.ts +1023 -0
- package/src/types/wasm.d.ts +30 -0
- package/src/validation/typed-errors.test.ts +420 -0
- package/src/wal/replay-engine.ts +1264 -0
- package/src/worker/__mocks__/capnweb.ts +15 -0
- package/src/worker/__mocks__/pglite.data.ts +22 -0
- package/src/worker/__mocks__/pglite.wasm.ts +33 -0
- package/src/worker/auth-rate-limiter.test.ts +272 -0
- package/src/worker/auth-rate-limiter.ts +448 -0
- package/src/worker/auth.security-red.test.ts +1236 -0
- package/src/worker/auth.security.test.ts +822 -0
- package/src/worker/auth.test.ts +469 -0
- package/src/worker/auth.ts +1104 -0
- package/src/worker/cdc-backpressure.test.ts +726 -0
- package/src/worker/cdc-backpressure.ts +866 -0
- package/src/worker/cdc-sse.test.ts +780 -0
- package/src/worker/cdc-sse.ts +728 -0
- package/src/worker/cdc-websocket.ts +1229 -0
- package/src/worker/cdc-ws.test.ts +1009 -0
- package/src/worker/cdc.test.ts +327 -0
- package/src/worker/cdc.ts +289 -0
- package/src/worker/concerns/auth-concern.ts +179 -0
- package/src/worker/concerns/cdc-concern.ts +247 -0
- package/src/worker/concerns/index.ts +58 -0
- package/src/worker/concerns/query-execution-concern.ts +194 -0
- package/src/worker/concerns/storage-orchestration-concern.ts +373 -0
- package/src/worker/discriminated-types.test.ts +280 -0
- package/src/worker/do-auth-manager.ts +257 -0
- package/src/worker/do-decomposition.test.ts +1236 -0
- package/src/worker/do-pglite-manager.ts +302 -0
- package/src/worker/do.test.ts +2254 -0
- package/src/worker/do.ts +1878 -0
- package/src/worker/entry.ts +417 -0
- package/src/worker/errors.ts +285 -0
- package/src/worker/health-check-manager.test.ts +261 -0
- package/src/worker/health-check-manager.ts +231 -0
- package/src/worker/index.ts +389 -0
- package/src/worker/memory-pressure.test.ts +1460 -0
- package/src/worker/memory-pressure.ts +2650 -0
- package/src/worker/migration-manager.ts +582 -0
- package/src/worker/neon-compat.test.ts +332 -0
- package/src/worker/plugin-manager.ts +485 -0
- package/src/worker/postgres.do-rpc.d.ts +76 -0
- package/src/worker/proxy.ts +694 -0
- package/src/worker/query-execution-manager.test.ts +303 -0
- package/src/worker/query-execution-manager.ts +219 -0
- package/src/worker/query-executor.test.ts +282 -0
- package/src/worker/query-executor.ts +560 -0
- package/src/worker/query-stats-manager.ts +229 -0
- package/src/worker/result-handler.test.ts +364 -0
- package/src/worker/result-handler.ts +510 -0
- package/src/worker/routes.test.ts +795 -0
- package/src/worker/routes.ts +650 -0
- package/src/worker/rpc-methods-manager.test.ts +326 -0
- package/src/worker/rpc-methods-manager.ts +276 -0
- package/src/worker/rpc.ts +524 -0
- package/src/worker/schema-version.ts +605 -0
- package/src/worker/session-manager.test.ts +506 -0
- package/src/worker/session-manager.ts +732 -0
- package/src/worker/shutdown-manager.ts +469 -0
- package/src/worker/sql-transform.test.ts +286 -0
- package/src/worker/sql-transform.ts +368 -0
- package/src/worker/supabase-compat.test.ts +621 -0
- package/src/worker/types.test.ts +292 -0
- package/src/worker/types.ts +873 -0
- package/src/worker/user-routes.test.ts +703 -0
- package/src/worker/user-routes.ts +303 -0
- package/src/worker/wal-facade.ts +235 -0
- package/src/worker/wal-r2.test.ts +570 -0
- package/src/worker/wal-r2.ts +930 -0
- package/src/worker/wal-replay.test.ts +845 -0
- package/src/worker/wal-replay.ts +897 -0
- package/src/worker/wal-retention.test.ts +758 -0
- package/src/worker/wal-retention.ts +1075 -0
- package/src/worker/wal.test.ts +618 -0
- package/src/worker/wal.ts +697 -0
- package/src/worker/websocket.test.ts +296 -0
- package/src/worker/websocket.ts +284 -0
|
@@ -0,0 +1,1258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOVFS - Durable Object Virtual File System
|
|
3
|
+
*
|
|
4
|
+
* A SQLite VFS implementation using Cloudflare Durable Objects storage.
|
|
5
|
+
* Designed for 2MB blob chunk storage with CRC32 integrity verification.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Constants
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
/** Default chunk size: 2MB */
|
|
13
|
+
export const DEFAULT_CHUNK_SIZE = 2 * 1024 * 1024
|
|
14
|
+
|
|
15
|
+
// SQLite Lock Levels
|
|
16
|
+
export const SQLITE_LOCK_NONE = 0
|
|
17
|
+
export const SQLITE_LOCK_SHARED = 1
|
|
18
|
+
export const SQLITE_LOCK_RESERVED = 2
|
|
19
|
+
export const SQLITE_LOCK_PENDING = 3
|
|
20
|
+
export const SQLITE_LOCK_EXCLUSIVE = 4
|
|
21
|
+
|
|
22
|
+
// SQLite Return Codes
|
|
23
|
+
export const SQLITE_OK = 0
|
|
24
|
+
export const SQLITE_ERROR = 1
|
|
25
|
+
export const SQLITE_BUSY = 5
|
|
26
|
+
export const SQLITE_IOERR = 10
|
|
27
|
+
export const SQLITE_NOTFOUND = 12
|
|
28
|
+
export const SQLITE_FULL = 13
|
|
29
|
+
export const SQLITE_CANTOPEN = 14
|
|
30
|
+
|
|
31
|
+
// SQLite Open Flags
|
|
32
|
+
export const SQLITE_OPEN_READONLY = 0x00000001
|
|
33
|
+
export const SQLITE_OPEN_READWRITE = 0x00000002
|
|
34
|
+
export const SQLITE_OPEN_CREATE = 0x00000004
|
|
35
|
+
export const SQLITE_OPEN_MAIN_DB = 0x00000100
|
|
36
|
+
export const SQLITE_OPEN_TEMP_DB = 0x00000200
|
|
37
|
+
export const SQLITE_OPEN_MAIN_JOURNAL = 0x00000800
|
|
38
|
+
export const SQLITE_OPEN_WAL = 0x00080000
|
|
39
|
+
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Types and Interfaces
|
|
42
|
+
// ============================================================================
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Metadata for a single chunk of file data
|
|
46
|
+
*/
|
|
47
|
+
export interface ChunkMetadata {
|
|
48
|
+
/** Zero-based index of this chunk */
|
|
49
|
+
chunkIndex: number
|
|
50
|
+
/** Size of data in this chunk (may be less than CHUNK_SIZE for last chunk) */
|
|
51
|
+
size: number
|
|
52
|
+
/** CRC32 checksum of chunk data */
|
|
53
|
+
crc32: number
|
|
54
|
+
/** Timestamp when chunk was last modified */
|
|
55
|
+
timestamp: number
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Metadata for a file stored in DOVFS
|
|
60
|
+
*/
|
|
61
|
+
export interface FileMetadata {
|
|
62
|
+
/** Full path of the file */
|
|
63
|
+
path: string
|
|
64
|
+
/** Total file size in bytes */
|
|
65
|
+
size: number
|
|
66
|
+
/** Number of chunks this file spans */
|
|
67
|
+
chunkCount: number
|
|
68
|
+
/** Creation timestamp */
|
|
69
|
+
created: number
|
|
70
|
+
/** Last modification timestamp */
|
|
71
|
+
modified: number
|
|
72
|
+
/** Current lock level */
|
|
73
|
+
lockLevel: number
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Storage interface compatible with Durable Object storage
|
|
78
|
+
*/
|
|
79
|
+
export interface DOVFSStorage {
|
|
80
|
+
get<T = unknown>(key: string): Promise<T | undefined>
|
|
81
|
+
get<T = unknown>(keys: string[]): Promise<Map<string, T>>
|
|
82
|
+
put<T>(key: string, value: T): Promise<void>
|
|
83
|
+
put<T>(entries: Record<string, T>): Promise<void>
|
|
84
|
+
delete(key: string): Promise<boolean>
|
|
85
|
+
delete(keys: string[]): Promise<number>
|
|
86
|
+
list<T = unknown>(options?: { prefix?: string; start?: string; end?: string; limit?: number }): Promise<Map<string, T>>
|
|
87
|
+
transaction<T>(closure: (txn: DOVFSStorage) => Promise<T>): Promise<T>
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// Factory Functions
|
|
92
|
+
// ============================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Creates a ChunkMetadata object with validation
|
|
96
|
+
*/
|
|
97
|
+
export function createChunkMetadata(data: {
|
|
98
|
+
chunkIndex: number
|
|
99
|
+
size: number
|
|
100
|
+
crc32: number
|
|
101
|
+
timestamp: number
|
|
102
|
+
}): ChunkMetadata {
|
|
103
|
+
return {
|
|
104
|
+
chunkIndex: data.chunkIndex,
|
|
105
|
+
size: data.size,
|
|
106
|
+
crc32: data.crc32,
|
|
107
|
+
timestamp: data.timestamp,
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Creates a FileMetadata object with validation
|
|
113
|
+
*/
|
|
114
|
+
export function createFileMetadata(data: {
|
|
115
|
+
path: string
|
|
116
|
+
size: number
|
|
117
|
+
chunkCount: number
|
|
118
|
+
created: number
|
|
119
|
+
modified: number
|
|
120
|
+
lockLevel: number
|
|
121
|
+
}): FileMetadata {
|
|
122
|
+
return {
|
|
123
|
+
path: data.path,
|
|
124
|
+
size: data.size,
|
|
125
|
+
chunkCount: data.chunkCount,
|
|
126
|
+
created: data.created,
|
|
127
|
+
modified: data.modified,
|
|
128
|
+
lockLevel: data.lockLevel,
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Type guard to check if an object implements DOVFSStorage interface
|
|
134
|
+
*/
|
|
135
|
+
export function isDOVFSStorage(obj: unknown): obj is DOVFSStorage {
|
|
136
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
137
|
+
return false
|
|
138
|
+
}
|
|
139
|
+
const storage = obj as Record<string, unknown>
|
|
140
|
+
return (
|
|
141
|
+
typeof storage.get === 'function' &&
|
|
142
|
+
typeof storage.put === 'function' &&
|
|
143
|
+
typeof storage.delete === 'function' &&
|
|
144
|
+
typeof storage.list === 'function' &&
|
|
145
|
+
typeof storage.transaction === 'function'
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ============================================================================
|
|
150
|
+
// CRC32 Implementation
|
|
151
|
+
// ============================================================================
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* CRC32 lookup table using IEEE polynomial (0xEDB88320)
|
|
155
|
+
* Pre-computed for performance
|
|
156
|
+
*/
|
|
157
|
+
export const CRC32_TABLE: Uint32Array = (() => {
|
|
158
|
+
const table = new Uint32Array(256)
|
|
159
|
+
for (let i = 0; i < 256; i++) {
|
|
160
|
+
let crc = i
|
|
161
|
+
for (let j = 0; j < 8; j++) {
|
|
162
|
+
crc = crc & 1 ? (crc >>> 1) ^ 0xEDB88320 : crc >>> 1
|
|
163
|
+
}
|
|
164
|
+
table[i] = crc >>> 0
|
|
165
|
+
}
|
|
166
|
+
return table
|
|
167
|
+
})()
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Compute CRC32 checksum for given data
|
|
171
|
+
* Uses IEEE polynomial (0xEDB88320) - same as zlib/gzip
|
|
172
|
+
*
|
|
173
|
+
* @param data - The data to compute checksum for
|
|
174
|
+
* @returns CRC32 checksum as unsigned 32-bit integer
|
|
175
|
+
*/
|
|
176
|
+
export function crc32(data: Uint8Array): number {
|
|
177
|
+
if (data.length === 0) {
|
|
178
|
+
return 0x00000000
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let crc = 0xFFFFFFFF
|
|
182
|
+
|
|
183
|
+
for (let i = 0; i < data.length; i++) {
|
|
184
|
+
const byte = data[i]
|
|
185
|
+
crc = (crc >>> 8) ^ CRC32_TABLE[(crc ^ byte) & 0xFF]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return (crc ^ 0xFFFFFFFF) >>> 0
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Verify data integrity by comparing computed CRC32 with expected checksum
|
|
193
|
+
*
|
|
194
|
+
* @param data - The data to verify
|
|
195
|
+
* @param expectedCrc - The expected CRC32 checksum
|
|
196
|
+
* @returns true if checksum matches, false otherwise
|
|
197
|
+
*/
|
|
198
|
+
export function verifyCRC32(data: Uint8Array, expectedCrc: number): boolean {
|
|
199
|
+
return crc32(data) === expectedCrc
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ============================================================================
|
|
203
|
+
// DOVFSFile Class - SQLite VFS File Operations
|
|
204
|
+
// ============================================================================
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Storage key prefixes for organizing data in Durable Object storage
|
|
208
|
+
*/
|
|
209
|
+
const KEY_PREFIX = {
|
|
210
|
+
FILE_META: 'file:',
|
|
211
|
+
CHUNK_DATA: 'chunk:',
|
|
212
|
+
CHUNK_META: 'chunk:',
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* DOVFSFile implements SQLite VFS file operations using Durable Object storage.
|
|
217
|
+
* Data is stored in 2MB chunks with CRC32 integrity verification.
|
|
218
|
+
*/
|
|
219
|
+
export class DOVFSFile {
|
|
220
|
+
private storage: DOVFSStorage
|
|
221
|
+
private _path: string
|
|
222
|
+
private flags: number
|
|
223
|
+
private chunkSize: number
|
|
224
|
+
private _isOpen: boolean = false
|
|
225
|
+
private _size: number = 0
|
|
226
|
+
private _lockLevel: number = SQLITE_LOCK_NONE
|
|
227
|
+
private metadata: FileMetadata | null = null
|
|
228
|
+
|
|
229
|
+
// In-memory cache for pending writes
|
|
230
|
+
private dirtyChunks: Map<number, Uint8Array> = new Map()
|
|
231
|
+
|
|
232
|
+
constructor(
|
|
233
|
+
storage: DOVFSStorage,
|
|
234
|
+
path: string,
|
|
235
|
+
flags: number,
|
|
236
|
+
chunkSize: number = DEFAULT_CHUNK_SIZE
|
|
237
|
+
) {
|
|
238
|
+
this.storage = storage
|
|
239
|
+
this._path = path
|
|
240
|
+
this.flags = flags
|
|
241
|
+
this.chunkSize = chunkSize
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** File path */
|
|
245
|
+
get path(): string {
|
|
246
|
+
return this._path
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Whether file is currently open */
|
|
250
|
+
get isOpen(): boolean {
|
|
251
|
+
return this._isOpen
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** Whether file was opened read-only */
|
|
255
|
+
get isReadOnly(): boolean {
|
|
256
|
+
return (this.flags & SQLITE_OPEN_READONLY) !== 0
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Current file size in bytes */
|
|
260
|
+
get size(): number {
|
|
261
|
+
return this._size
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** Current lock level */
|
|
265
|
+
get lockLevel(): number {
|
|
266
|
+
return this._lockLevel
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Storage key for file metadata
|
|
271
|
+
*/
|
|
272
|
+
private fileMetaKey(): string {
|
|
273
|
+
return `${KEY_PREFIX.FILE_META}${this._path}`
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Storage key for chunk data
|
|
278
|
+
*/
|
|
279
|
+
private chunkDataKey(chunkIndex: number): string {
|
|
280
|
+
return `${KEY_PREFIX.CHUNK_DATA}${this._path}:${chunkIndex}:data`
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Storage key for chunk metadata
|
|
285
|
+
*/
|
|
286
|
+
private chunkMetaKey(chunkIndex: number): string {
|
|
287
|
+
return `${KEY_PREFIX.CHUNK_META}${this._path}:${chunkIndex}:meta`
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Calculate which chunk contains the given offset
|
|
292
|
+
*/
|
|
293
|
+
private chunkIndexForOffset(offset: number): number {
|
|
294
|
+
return Math.floor(offset / this.chunkSize)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Calculate offset within a chunk
|
|
299
|
+
*/
|
|
300
|
+
private offsetWithinChunk(offset: number): number {
|
|
301
|
+
return offset % this.chunkSize
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Last error that occurred during file operations */
|
|
305
|
+
private _lastError: Error | null = null
|
|
306
|
+
|
|
307
|
+
/** Get the last error that occurred during file operations */
|
|
308
|
+
get lastError(): Error | null {
|
|
309
|
+
return this._lastError
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* xOpen - Open a file
|
|
314
|
+
*/
|
|
315
|
+
async xOpen(): Promise<number> {
|
|
316
|
+
try {
|
|
317
|
+
// Check if file already exists
|
|
318
|
+
const existingMeta = await this.storage.get<FileMetadata>(this.fileMetaKey())
|
|
319
|
+
|
|
320
|
+
if (existingMeta) {
|
|
321
|
+
// File exists - load metadata
|
|
322
|
+
this.metadata = existingMeta
|
|
323
|
+
this._size = existingMeta.size
|
|
324
|
+
this._lockLevel = existingMeta.lockLevel
|
|
325
|
+
this._isOpen = true
|
|
326
|
+
return SQLITE_OK
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// File doesn't exist
|
|
330
|
+
if (!(this.flags & SQLITE_OPEN_CREATE)) {
|
|
331
|
+
// Can't create - return error
|
|
332
|
+
return SQLITE_CANTOPEN
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Create new file
|
|
336
|
+
const now = Date.now()
|
|
337
|
+
this.metadata = createFileMetadata({
|
|
338
|
+
path: this._path,
|
|
339
|
+
size: 0,
|
|
340
|
+
chunkCount: 0,
|
|
341
|
+
created: now,
|
|
342
|
+
modified: now,
|
|
343
|
+
lockLevel: SQLITE_LOCK_NONE,
|
|
344
|
+
})
|
|
345
|
+
this._size = 0
|
|
346
|
+
this._lockLevel = SQLITE_LOCK_NONE
|
|
347
|
+
|
|
348
|
+
// Store file metadata
|
|
349
|
+
await this.storage.put(this.fileMetaKey(), this.metadata)
|
|
350
|
+
|
|
351
|
+
this._isOpen = true
|
|
352
|
+
return SQLITE_OK
|
|
353
|
+
} catch (err) {
|
|
354
|
+
this._lastError = err instanceof Error ? err : new Error(String(err))
|
|
355
|
+
return SQLITE_IOERR
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* xClose - Close a file
|
|
361
|
+
*/
|
|
362
|
+
async xClose(): Promise<number> {
|
|
363
|
+
if (!this._isOpen) {
|
|
364
|
+
return SQLITE_OK
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
try {
|
|
368
|
+
// Flush any pending writes
|
|
369
|
+
await this.xSync(0)
|
|
370
|
+
|
|
371
|
+
this._isOpen = false
|
|
372
|
+
this.dirtyChunks.clear()
|
|
373
|
+
return SQLITE_OK
|
|
374
|
+
} catch (err) {
|
|
375
|
+
this._lastError = err instanceof Error ? err : new Error(String(err))
|
|
376
|
+
return SQLITE_IOERR
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* xRead - Read data from file
|
|
382
|
+
*/
|
|
383
|
+
async xRead(buffer: Uint8Array, offset: number): Promise<number> {
|
|
384
|
+
const bytesToRead = buffer.length
|
|
385
|
+
|
|
386
|
+
// Check if read would go beyond file size
|
|
387
|
+
if (offset + bytesToRead > this._size) {
|
|
388
|
+
return SQLITE_IOERR
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
try {
|
|
392
|
+
let bytesRead = 0
|
|
393
|
+
let currentOffset = offset
|
|
394
|
+
|
|
395
|
+
while (bytesRead < bytesToRead) {
|
|
396
|
+
const chunkIndex = this.chunkIndexForOffset(currentOffset)
|
|
397
|
+
const offsetInChunk = this.offsetWithinChunk(currentOffset)
|
|
398
|
+
const bytesAvailableInChunk = this.chunkSize - offsetInChunk
|
|
399
|
+
const bytesToReadFromChunk = Math.min(bytesAvailableInChunk, bytesToRead - bytesRead)
|
|
400
|
+
|
|
401
|
+
// Check dirty chunks first (uncommitted writes)
|
|
402
|
+
let chunkData = this.dirtyChunks.get(chunkIndex)
|
|
403
|
+
|
|
404
|
+
if (!chunkData) {
|
|
405
|
+
// Load from storage
|
|
406
|
+
const storedData = await this.storage.get<Uint8Array>(this.chunkDataKey(chunkIndex))
|
|
407
|
+
if (storedData) {
|
|
408
|
+
chunkData = storedData
|
|
409
|
+
} else {
|
|
410
|
+
// Chunk doesn't exist - return zeros
|
|
411
|
+
chunkData = new Uint8Array(this.chunkSize)
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Copy data to buffer
|
|
416
|
+
buffer.set(
|
|
417
|
+
chunkData.subarray(offsetInChunk, offsetInChunk + bytesToReadFromChunk),
|
|
418
|
+
bytesRead
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
bytesRead += bytesToReadFromChunk
|
|
422
|
+
currentOffset += bytesToReadFromChunk
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return SQLITE_OK
|
|
426
|
+
} catch (err) {
|
|
427
|
+
this._lastError = err instanceof Error ? err : new Error(String(err))
|
|
428
|
+
return SQLITE_IOERR
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* xWrite - Write data to file
|
|
434
|
+
*/
|
|
435
|
+
async xWrite(data: Uint8Array, offset: number): Promise<number> {
|
|
436
|
+
if (this.isReadOnly) {
|
|
437
|
+
return SQLITE_IOERR
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
try {
|
|
441
|
+
let bytesWritten = 0
|
|
442
|
+
let currentOffset = offset
|
|
443
|
+
|
|
444
|
+
while (bytesWritten < data.length) {
|
|
445
|
+
const chunkIndex = this.chunkIndexForOffset(currentOffset)
|
|
446
|
+
const offsetInChunk = this.offsetWithinChunk(currentOffset)
|
|
447
|
+
const bytesAvailableInChunk = this.chunkSize - offsetInChunk
|
|
448
|
+
const bytesToWriteToChunk = Math.min(bytesAvailableInChunk, data.length - bytesWritten)
|
|
449
|
+
|
|
450
|
+
// Get or create chunk
|
|
451
|
+
let chunkData = this.dirtyChunks.get(chunkIndex)
|
|
452
|
+
|
|
453
|
+
if (!chunkData) {
|
|
454
|
+
// Try to load existing chunk from storage
|
|
455
|
+
const storedData = await this.storage.get<Uint8Array>(this.chunkDataKey(chunkIndex))
|
|
456
|
+
if (storedData) {
|
|
457
|
+
// Make a copy for modification
|
|
458
|
+
chunkData = new Uint8Array(this.chunkSize)
|
|
459
|
+
chunkData.set(storedData)
|
|
460
|
+
} else {
|
|
461
|
+
chunkData = new Uint8Array(this.chunkSize)
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Write data to chunk
|
|
466
|
+
chunkData.set(
|
|
467
|
+
data.subarray(bytesWritten, bytesWritten + bytesToWriteToChunk),
|
|
468
|
+
offsetInChunk
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
// Mark chunk as dirty
|
|
472
|
+
this.dirtyChunks.set(chunkIndex, chunkData)
|
|
473
|
+
|
|
474
|
+
bytesWritten += bytesToWriteToChunk
|
|
475
|
+
currentOffset += bytesToWriteToChunk
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Update file size if we wrote beyond current size
|
|
479
|
+
const newEnd = offset + data.length
|
|
480
|
+
if (newEnd > this._size) {
|
|
481
|
+
this._size = newEnd
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return SQLITE_OK
|
|
485
|
+
} catch (err) {
|
|
486
|
+
this._lastError = err instanceof Error ? err : new Error(String(err))
|
|
487
|
+
return SQLITE_IOERR
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* xSync - Flush pending writes to storage
|
|
493
|
+
*/
|
|
494
|
+
async xSync(_flags: number): Promise<number> {
|
|
495
|
+
if (this.dirtyChunks.size === 0) {
|
|
496
|
+
return SQLITE_OK
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
try {
|
|
500
|
+
await this.storage.transaction(async (txn) => {
|
|
501
|
+
// Write all dirty chunks
|
|
502
|
+
for (const [chunkIndex, chunkData] of this.dirtyChunks) {
|
|
503
|
+
// Calculate actual size of this chunk
|
|
504
|
+
const chunkStart = chunkIndex * this.chunkSize
|
|
505
|
+
const chunkEnd = Math.min(chunkStart + this.chunkSize, this._size)
|
|
506
|
+
const actualSize = Math.max(0, chunkEnd - chunkStart)
|
|
507
|
+
|
|
508
|
+
// Get the actual data (trimmed to actual size for CRC)
|
|
509
|
+
const actualData = chunkData.subarray(0, actualSize)
|
|
510
|
+
const checksum = crc32(actualData)
|
|
511
|
+
|
|
512
|
+
// Store chunk data
|
|
513
|
+
await txn.put(this.chunkDataKey(chunkIndex), chunkData)
|
|
514
|
+
|
|
515
|
+
// Store chunk metadata
|
|
516
|
+
const chunkMeta = createChunkMetadata({
|
|
517
|
+
chunkIndex,
|
|
518
|
+
size: actualSize,
|
|
519
|
+
crc32: checksum,
|
|
520
|
+
timestamp: Date.now(),
|
|
521
|
+
})
|
|
522
|
+
await txn.put(this.chunkMetaKey(chunkIndex), chunkMeta)
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Update file metadata
|
|
526
|
+
const chunkCount = Math.ceil(this._size / this.chunkSize)
|
|
527
|
+
if (this.metadata) {
|
|
528
|
+
this.metadata.size = this._size
|
|
529
|
+
this.metadata.chunkCount = chunkCount
|
|
530
|
+
this.metadata.modified = Date.now()
|
|
531
|
+
await txn.put(this.fileMetaKey(), this.metadata)
|
|
532
|
+
}
|
|
533
|
+
})
|
|
534
|
+
|
|
535
|
+
// Clear dirty chunks after successful sync
|
|
536
|
+
this.dirtyChunks.clear()
|
|
537
|
+
|
|
538
|
+
return SQLITE_OK
|
|
539
|
+
} catch (err) {
|
|
540
|
+
this._lastError = err instanceof Error ? err : new Error(String(err))
|
|
541
|
+
return SQLITE_IOERR
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* xFileSize - Get current file size
|
|
547
|
+
*/
|
|
548
|
+
async xFileSize(): Promise<number> {
|
|
549
|
+
return this._size
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* xTruncate - Truncate file to specified size
|
|
554
|
+
*/
|
|
555
|
+
async xTruncate(size: number): Promise<number> {
|
|
556
|
+
if (this.isReadOnly) {
|
|
557
|
+
return SQLITE_IOERR
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
try {
|
|
561
|
+
const oldChunkCount = Math.ceil(this._size / this.chunkSize)
|
|
562
|
+
const newChunkCount = Math.ceil(size / this.chunkSize)
|
|
563
|
+
|
|
564
|
+
// Remove chunks beyond new size
|
|
565
|
+
if (newChunkCount < oldChunkCount) {
|
|
566
|
+
const keysToDelete: string[] = []
|
|
567
|
+
for (let i = newChunkCount; i < oldChunkCount; i++) {
|
|
568
|
+
keysToDelete.push(this.chunkDataKey(i))
|
|
569
|
+
keysToDelete.push(this.chunkMetaKey(i))
|
|
570
|
+
this.dirtyChunks.delete(i)
|
|
571
|
+
}
|
|
572
|
+
if (keysToDelete.length > 0) {
|
|
573
|
+
await this.storage.delete(keysToDelete)
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// Update last chunk if needed (truncate within chunk)
|
|
578
|
+
if (newChunkCount > 0 && size > 0) {
|
|
579
|
+
const lastChunkIndex = newChunkCount - 1
|
|
580
|
+
const sizeInLastChunk = size - lastChunkIndex * this.chunkSize
|
|
581
|
+
|
|
582
|
+
// If we have a dirty chunk, truncate it
|
|
583
|
+
const dirtyChunk = this.dirtyChunks.get(lastChunkIndex)
|
|
584
|
+
if (dirtyChunk && sizeInLastChunk < this.chunkSize) {
|
|
585
|
+
// Zero out bytes beyond new size
|
|
586
|
+
dirtyChunk.fill(0, sizeInLastChunk)
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
this._size = size
|
|
591
|
+
|
|
592
|
+
return SQLITE_OK
|
|
593
|
+
} catch (err) {
|
|
594
|
+
this._lastError = err instanceof Error ? err : new Error(String(err))
|
|
595
|
+
return SQLITE_IOERR
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* xLock - Acquire a file lock
|
|
601
|
+
*/
|
|
602
|
+
async xLock(level: number): Promise<number> {
|
|
603
|
+
if (level <= this._lockLevel) {
|
|
604
|
+
return SQLITE_OK
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
this._lockLevel = level
|
|
608
|
+
return SQLITE_OK
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* xUnlock - Release a file lock
|
|
613
|
+
*/
|
|
614
|
+
async xUnlock(level: number): Promise<number> {
|
|
615
|
+
if (level >= this._lockLevel) {
|
|
616
|
+
return SQLITE_OK
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
this._lockLevel = level
|
|
620
|
+
return SQLITE_OK
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* xCheckReservedLock - Check if another connection has reserved lock
|
|
625
|
+
*/
|
|
626
|
+
async xCheckReservedLock(): Promise<{ result: number; reserved: boolean }> {
|
|
627
|
+
// In single-process mode, we always have the lock
|
|
628
|
+
return { result: SQLITE_OK, reserved: false }
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// ============================================================================
|
|
633
|
+
// DOVFSLockManager Class - Multi-connection Lock Management
|
|
634
|
+
// ============================================================================
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Lock state for a single connection to a file
|
|
638
|
+
*/
|
|
639
|
+
interface ConnectionLock {
|
|
640
|
+
connectionId: string
|
|
641
|
+
level: number
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Lock state for a single file
|
|
646
|
+
*/
|
|
647
|
+
interface FileLockState {
|
|
648
|
+
locks: Map<string, number> // connectionId -> lock level
|
|
649
|
+
exclusiveHolder: string | null
|
|
650
|
+
reservedHolder: string | null
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* DOVFSLockManager manages SQLite locking semantics across multiple connections.
|
|
655
|
+
*
|
|
656
|
+
* SQLite Lock Levels (in order):
|
|
657
|
+
* - NONE (0): No lock held
|
|
658
|
+
* - SHARED (1): Read lock - multiple readers allowed
|
|
659
|
+
* - RESERVED (2): Writer intending to write - only one allowed, readers can still read
|
|
660
|
+
* - PENDING (3): Writer waiting for readers to finish
|
|
661
|
+
* - EXCLUSIVE (4): Write lock - no other locks allowed
|
|
662
|
+
*/
|
|
663
|
+
export class DOVFSLockManager {
|
|
664
|
+
private fileLocks: Map<string, FileLockState> = new Map()
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* Get or create lock state for a file
|
|
668
|
+
*/
|
|
669
|
+
private getFileLockState(path: string): FileLockState {
|
|
670
|
+
let state = this.fileLocks.get(path)
|
|
671
|
+
if (!state) {
|
|
672
|
+
state = {
|
|
673
|
+
locks: new Map(),
|
|
674
|
+
exclusiveHolder: null,
|
|
675
|
+
reservedHolder: null,
|
|
676
|
+
}
|
|
677
|
+
this.fileLocks.set(path, state)
|
|
678
|
+
}
|
|
679
|
+
return state
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Acquire a lock at the specified level
|
|
684
|
+
*/
|
|
685
|
+
async acquireLock(path: string, connectionId: string, level: number): Promise<number> {
|
|
686
|
+
const state = this.getFileLockState(path)
|
|
687
|
+
const currentLevel = state.locks.get(connectionId) ?? SQLITE_LOCK_NONE
|
|
688
|
+
|
|
689
|
+
// Already at or above requested level
|
|
690
|
+
if (currentLevel >= level) {
|
|
691
|
+
return SQLITE_OK
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Check if lock can be acquired
|
|
695
|
+
switch (level) {
|
|
696
|
+
case SQLITE_LOCK_NONE:
|
|
697
|
+
// Always succeeds
|
|
698
|
+
break
|
|
699
|
+
|
|
700
|
+
case SQLITE_LOCK_SHARED:
|
|
701
|
+
// Blocked if another connection has exclusive
|
|
702
|
+
if (state.exclusiveHolder && state.exclusiveHolder !== connectionId) {
|
|
703
|
+
return SQLITE_BUSY
|
|
704
|
+
}
|
|
705
|
+
// Blocked if another connection has pending lock waiting for us
|
|
706
|
+
break
|
|
707
|
+
|
|
708
|
+
case SQLITE_LOCK_RESERVED:
|
|
709
|
+
// Only one connection can have reserved lock
|
|
710
|
+
if (state.reservedHolder && state.reservedHolder !== connectionId) {
|
|
711
|
+
return SQLITE_BUSY
|
|
712
|
+
}
|
|
713
|
+
// Blocked if another has exclusive
|
|
714
|
+
if (state.exclusiveHolder && state.exclusiveHolder !== connectionId) {
|
|
715
|
+
return SQLITE_BUSY
|
|
716
|
+
}
|
|
717
|
+
state.reservedHolder = connectionId
|
|
718
|
+
break
|
|
719
|
+
|
|
720
|
+
case SQLITE_LOCK_PENDING:
|
|
721
|
+
case SQLITE_LOCK_EXCLUSIVE:
|
|
722
|
+
// Need reserved first
|
|
723
|
+
if (state.reservedHolder !== connectionId) {
|
|
724
|
+
// Try to get reserved first
|
|
725
|
+
if (state.reservedHolder) {
|
|
726
|
+
return SQLITE_BUSY
|
|
727
|
+
}
|
|
728
|
+
state.reservedHolder = connectionId
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// For exclusive, need all other shared locks to be released
|
|
732
|
+
let otherSharedCount = 0
|
|
733
|
+
for (const [connId, lockLevel] of state.locks) {
|
|
734
|
+
if (connId !== connectionId && lockLevel >= SQLITE_LOCK_SHARED) {
|
|
735
|
+
otherSharedCount++
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
if (otherSharedCount > 0) {
|
|
739
|
+
return SQLITE_BUSY
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
if (level === SQLITE_LOCK_EXCLUSIVE) {
|
|
743
|
+
state.exclusiveHolder = connectionId
|
|
744
|
+
}
|
|
745
|
+
break
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Grant the lock
|
|
749
|
+
state.locks.set(connectionId, level)
|
|
750
|
+
return SQLITE_OK
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Release lock to specified level
|
|
755
|
+
*/
|
|
756
|
+
async releaseLock(path: string, connectionId: string, level: number): Promise<number> {
|
|
757
|
+
const state = this.getFileLockState(path)
|
|
758
|
+
const currentLevel = state.locks.get(connectionId) ?? SQLITE_LOCK_NONE
|
|
759
|
+
|
|
760
|
+
// Already at or below requested level
|
|
761
|
+
if (currentLevel <= level) {
|
|
762
|
+
return SQLITE_OK
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Clear exclusive if we're releasing below exclusive
|
|
766
|
+
if (level < SQLITE_LOCK_EXCLUSIVE && state.exclusiveHolder === connectionId) {
|
|
767
|
+
state.exclusiveHolder = null
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// Clear reserved if we're releasing below reserved
|
|
771
|
+
if (level < SQLITE_LOCK_RESERVED && state.reservedHolder === connectionId) {
|
|
772
|
+
state.reservedHolder = null
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// Update or remove lock
|
|
776
|
+
if (level === SQLITE_LOCK_NONE) {
|
|
777
|
+
state.locks.delete(connectionId)
|
|
778
|
+
} else {
|
|
779
|
+
state.locks.set(connectionId, level)
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
return SQLITE_OK
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Check if another connection holds a reserved (or higher) lock
|
|
787
|
+
*/
|
|
788
|
+
hasReservedLock(path: string, connectionId: string): boolean {
|
|
789
|
+
const state = this.fileLocks.get(path)
|
|
790
|
+
if (!state) {
|
|
791
|
+
return false
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// Check if anyone other than us has reserved or higher
|
|
795
|
+
if (state.reservedHolder && state.reservedHolder !== connectionId) {
|
|
796
|
+
return true
|
|
797
|
+
}
|
|
798
|
+
if (state.exclusiveHolder && state.exclusiveHolder !== connectionId) {
|
|
799
|
+
return true
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
return false
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* Get current lock level for a connection
|
|
807
|
+
*/
|
|
808
|
+
getLockLevel(path: string, connectionId: string): number {
|
|
809
|
+
const state = this.fileLocks.get(path)
|
|
810
|
+
if (!state) {
|
|
811
|
+
return SQLITE_LOCK_NONE
|
|
812
|
+
}
|
|
813
|
+
return state.locks.get(connectionId) ?? SQLITE_LOCK_NONE
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Clear all locks for a connection (e.g., on disconnect)
|
|
818
|
+
*/
|
|
819
|
+
clearConnectionLocks(connectionId: string): void {
|
|
820
|
+
for (const [path, state] of this.fileLocks) {
|
|
821
|
+
if (state.locks.has(connectionId)) {
|
|
822
|
+
this.releaseLock(path, connectionId, SQLITE_LOCK_NONE)
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// ============================================================================
|
|
829
|
+
// DOVFS Class - Main VFS Interface
|
|
830
|
+
// ============================================================================
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* DOVFS - Durable Object Virtual File System
|
|
834
|
+
*
|
|
835
|
+
* Main VFS class that implements SQLite VFS operations using Durable Object storage.
|
|
836
|
+
* This class provides the SQLite-compatible VFS interface.
|
|
837
|
+
*/
|
|
838
|
+
export class DOVFS {
|
|
839
|
+
private storage: DOVFSStorage
|
|
840
|
+
private _name: string = 'dovfs'
|
|
841
|
+
private chunkSize: number
|
|
842
|
+
|
|
843
|
+
constructor(storage: DOVFSStorage, chunkSize: number = DEFAULT_CHUNK_SIZE) {
|
|
844
|
+
this.storage = storage
|
|
845
|
+
this.chunkSize = chunkSize
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/** VFS name */
|
|
849
|
+
get name(): string {
|
|
850
|
+
return this._name
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* Open a file
|
|
855
|
+
*/
|
|
856
|
+
async xOpen(path: string, flags: number): Promise<{ result: number; file: DOVFSFile | null }> {
|
|
857
|
+
const file = new DOVFSFile(this.storage, path, flags, this.chunkSize)
|
|
858
|
+
const result = await file.xOpen()
|
|
859
|
+
if (result !== SQLITE_OK) {
|
|
860
|
+
return { result, file: null }
|
|
861
|
+
}
|
|
862
|
+
return { result: SQLITE_OK, file }
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* xAccess - Check if a file exists
|
|
867
|
+
*/
|
|
868
|
+
async xAccess(path: string): Promise<{ result: number; exists: boolean }> {
|
|
869
|
+
try {
|
|
870
|
+
const metaKey = `file:${path}`
|
|
871
|
+
const metadata = await this.storage.get(metaKey)
|
|
872
|
+
return { result: SQLITE_OK, exists: metadata !== undefined }
|
|
873
|
+
} catch {
|
|
874
|
+
return { result: SQLITE_IOERR, exists: false }
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* xDelete - Delete a file and all its chunks
|
|
880
|
+
*/
|
|
881
|
+
async xDelete(path: string): Promise<number> {
|
|
882
|
+
try {
|
|
883
|
+
const metaKey = `file:${path}`
|
|
884
|
+
const metadata = await this.storage.get<FileMetadata>(metaKey)
|
|
885
|
+
|
|
886
|
+
if (!metadata) {
|
|
887
|
+
// File doesn't exist - success (idempotent)
|
|
888
|
+
return SQLITE_OK
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// Delete all chunks
|
|
892
|
+
const chunkKeys: string[] = []
|
|
893
|
+
for (let i = 0; i < metadata.chunkCount; i++) {
|
|
894
|
+
chunkKeys.push(`chunk:${path}:${i}:data`)
|
|
895
|
+
chunkKeys.push(`chunk:${path}:${i}:meta`)
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// Also search for any additional chunk keys (in case chunkCount is stale)
|
|
899
|
+
const allChunks = await this.storage.list({ prefix: `chunk:${path}:` })
|
|
900
|
+
for (const key of allChunks.keys()) {
|
|
901
|
+
if (!chunkKeys.includes(key)) {
|
|
902
|
+
chunkKeys.push(key)
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// Delete chunks and file metadata
|
|
907
|
+
if (chunkKeys.length > 0) {
|
|
908
|
+
await this.storage.delete(chunkKeys)
|
|
909
|
+
}
|
|
910
|
+
await this.storage.delete(metaKey)
|
|
911
|
+
|
|
912
|
+
return SQLITE_OK
|
|
913
|
+
} catch {
|
|
914
|
+
return SQLITE_IOERR
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* xFullPathname - Get full pathname from relative path
|
|
920
|
+
*/
|
|
921
|
+
async xFullPathname(path: string): Promise<{ result: number; fullPath: string }> {
|
|
922
|
+
// Normalize the path
|
|
923
|
+
let fullPath = path
|
|
924
|
+
|
|
925
|
+
// Add leading slash if missing
|
|
926
|
+
if (!fullPath.startsWith('/')) {
|
|
927
|
+
fullPath = '/' + fullPath
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// Resolve .. and .
|
|
931
|
+
const parts = fullPath.split('/').filter(p => p !== '')
|
|
932
|
+
const resolved: string[] = []
|
|
933
|
+
for (const part of parts) {
|
|
934
|
+
if (part === '..') {
|
|
935
|
+
resolved.pop()
|
|
936
|
+
} else if (part !== '.') {
|
|
937
|
+
resolved.push(part)
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
return { result: SQLITE_OK, fullPath: '/' + resolved.join('/') }
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* List all files in the VFS
|
|
946
|
+
* @throws If storage access fails
|
|
947
|
+
*/
|
|
948
|
+
async listFiles(prefix?: string): Promise<string[]> {
|
|
949
|
+
const allFiles = await this.storage.list<FileMetadata>({ prefix: 'file:' })
|
|
950
|
+
const files: string[] = []
|
|
951
|
+
|
|
952
|
+
for (const [, metadata] of allFiles) {
|
|
953
|
+
const path = metadata.path
|
|
954
|
+
if (!prefix || path.startsWith(prefix)) {
|
|
955
|
+
files.push(path)
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
return files
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Get file information
|
|
964
|
+
* @throws If storage access fails
|
|
965
|
+
*/
|
|
966
|
+
async getFileInfo(path: string): Promise<FileMetadata | null> {
|
|
967
|
+
const metaKey = `file:${path}`
|
|
968
|
+
const metadata = await this.storage.get<FileMetadata>(metaKey)
|
|
969
|
+
return metadata ?? null
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* xRandomness - Get random bytes
|
|
974
|
+
*/
|
|
975
|
+
async xRandomness(buffer: Uint8Array): Promise<void> {
|
|
976
|
+
// Use crypto.getRandomValues if available (browsers, CF Workers)
|
|
977
|
+
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
|
978
|
+
crypto.getRandomValues(buffer)
|
|
979
|
+
} else {
|
|
980
|
+
// Fallback: simple PRNG (not cryptographically secure)
|
|
981
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
982
|
+
buffer[i] = Math.floor(Math.random() * 256)
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
/**
|
|
988
|
+
* xSleep - Sleep for specified microseconds
|
|
989
|
+
*/
|
|
990
|
+
async xSleep(microseconds: number): Promise<number> {
|
|
991
|
+
const ms = Math.floor(microseconds / 1000)
|
|
992
|
+
await new Promise(resolve => setTimeout(resolve, ms))
|
|
993
|
+
return SQLITE_OK
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* xCurrentTime - Get current time as Julian day number
|
|
998
|
+
*/
|
|
999
|
+
async xCurrentTime(): Promise<number> {
|
|
1000
|
+
// Julian day calculation
|
|
1001
|
+
// Julian day 0 = January 1, 4713 BC
|
|
1002
|
+
// Unix epoch (Jan 1, 1970) = Julian day 2440587.5
|
|
1003
|
+
const now = Date.now()
|
|
1004
|
+
const unixDays = now / (24 * 60 * 60 * 1000)
|
|
1005
|
+
const julianDay = unixDays + 2440587.5
|
|
1006
|
+
return julianDay
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* Get storage statistics
|
|
1011
|
+
*/
|
|
1012
|
+
async getStorageStats(): Promise<{
|
|
1013
|
+
fileCount: number
|
|
1014
|
+
totalSize: number
|
|
1015
|
+
totalChunks: number
|
|
1016
|
+
}> {
|
|
1017
|
+
let fileCount = 0
|
|
1018
|
+
let totalSize = 0
|
|
1019
|
+
let totalChunks = 0
|
|
1020
|
+
|
|
1021
|
+
const files = await this.storage.list<FileMetadata>({ prefix: 'file:' })
|
|
1022
|
+
for (const [, metadata] of files) {
|
|
1023
|
+
fileCount++
|
|
1024
|
+
totalSize += metadata.size
|
|
1025
|
+
totalChunks += metadata.chunkCount
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
return { fileCount, totalSize, totalChunks }
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
// ============================================================================
|
|
1033
|
+
// Utility Functions
|
|
1034
|
+
// ============================================================================
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* Copy a file to a new location
|
|
1038
|
+
*/
|
|
1039
|
+
export async function copyFile(
|
|
1040
|
+
storage: DOVFSStorage,
|
|
1041
|
+
sourcePath: string,
|
|
1042
|
+
destPath: string,
|
|
1043
|
+
chunkSize: number = DEFAULT_CHUNK_SIZE
|
|
1044
|
+
): Promise<number> {
|
|
1045
|
+
try {
|
|
1046
|
+
// Get source file metadata
|
|
1047
|
+
const sourceMetaKey = `file:${sourcePath}`
|
|
1048
|
+
const sourceMeta = await storage.get<FileMetadata>(sourceMetaKey)
|
|
1049
|
+
|
|
1050
|
+
if (!sourceMeta) {
|
|
1051
|
+
return SQLITE_NOTFOUND
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// Read all source data
|
|
1055
|
+
const sourceFile = new DOVFSFile(storage, sourcePath, SQLITE_OPEN_READONLY, chunkSize)
|
|
1056
|
+
const result = await sourceFile.xOpen()
|
|
1057
|
+
if (result !== SQLITE_OK) {
|
|
1058
|
+
return result
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
const data = new Uint8Array(sourceMeta.size)
|
|
1062
|
+
if (sourceMeta.size > 0) {
|
|
1063
|
+
const readResult = await sourceFile.xRead(data, 0)
|
|
1064
|
+
if (readResult !== SQLITE_OK) {
|
|
1065
|
+
await sourceFile.xClose()
|
|
1066
|
+
return readResult
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
await sourceFile.xClose()
|
|
1070
|
+
|
|
1071
|
+
// Write to destination
|
|
1072
|
+
const destFile = new DOVFSFile(storage, destPath, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, chunkSize)
|
|
1073
|
+
const openResult = await destFile.xOpen()
|
|
1074
|
+
if (openResult !== SQLITE_OK) {
|
|
1075
|
+
return openResult
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
if (data.length > 0) {
|
|
1079
|
+
const writeResult = await destFile.xWrite(data, 0)
|
|
1080
|
+
if (writeResult !== SQLITE_OK) {
|
|
1081
|
+
await destFile.xClose()
|
|
1082
|
+
return writeResult
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
await destFile.xClose()
|
|
1087
|
+
return SQLITE_OK
|
|
1088
|
+
} catch {
|
|
1089
|
+
return SQLITE_IOERR
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
/**
|
|
1094
|
+
* Export a file to a Uint8Array
|
|
1095
|
+
*/
|
|
1096
|
+
export async function exportFile(
|
|
1097
|
+
storage: DOVFSStorage,
|
|
1098
|
+
path: string,
|
|
1099
|
+
chunkSize: number = DEFAULT_CHUNK_SIZE
|
|
1100
|
+
): Promise<Uint8Array | null> {
|
|
1101
|
+
try {
|
|
1102
|
+
const metaKey = `file:${path}`
|
|
1103
|
+
const metadata = await storage.get<FileMetadata>(metaKey)
|
|
1104
|
+
|
|
1105
|
+
if (!metadata) {
|
|
1106
|
+
return null
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
const file = new DOVFSFile(storage, path, SQLITE_OPEN_READONLY, chunkSize)
|
|
1110
|
+
const result = await file.xOpen()
|
|
1111
|
+
if (result !== SQLITE_OK) {
|
|
1112
|
+
return null
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
const data = new Uint8Array(metadata.size)
|
|
1116
|
+
if (metadata.size > 0) {
|
|
1117
|
+
const readResult = await file.xRead(data, 0)
|
|
1118
|
+
if (readResult !== SQLITE_OK) {
|
|
1119
|
+
await file.xClose()
|
|
1120
|
+
return null
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
await file.xClose()
|
|
1125
|
+
return data
|
|
1126
|
+
} catch {
|
|
1127
|
+
return null
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Import a Uint8Array to a file
|
|
1133
|
+
*/
|
|
1134
|
+
export async function importFile(
|
|
1135
|
+
storage: DOVFSStorage,
|
|
1136
|
+
path: string,
|
|
1137
|
+
data: Uint8Array,
|
|
1138
|
+
chunkSize: number = DEFAULT_CHUNK_SIZE
|
|
1139
|
+
): Promise<number> {
|
|
1140
|
+
try {
|
|
1141
|
+
// Delete existing file if present
|
|
1142
|
+
const vfs = new DOVFS(storage, chunkSize)
|
|
1143
|
+
await vfs.xDelete(path)
|
|
1144
|
+
|
|
1145
|
+
// Create and write new file
|
|
1146
|
+
const file = new DOVFSFile(storage, path, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, chunkSize)
|
|
1147
|
+
const openResult = await file.xOpen()
|
|
1148
|
+
if (openResult !== SQLITE_OK) {
|
|
1149
|
+
return openResult
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
if (data.length > 0) {
|
|
1153
|
+
const writeResult = await file.xWrite(data, 0)
|
|
1154
|
+
if (writeResult !== SQLITE_OK) {
|
|
1155
|
+
await file.xClose()
|
|
1156
|
+
return writeResult
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
await file.xClose()
|
|
1161
|
+
return SQLITE_OK
|
|
1162
|
+
} catch {
|
|
1163
|
+
return SQLITE_IOERR
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* Get the range of chunks that an operation spans
|
|
1169
|
+
*/
|
|
1170
|
+
export function getChunkRange(
|
|
1171
|
+
offset: number,
|
|
1172
|
+
length: number,
|
|
1173
|
+
chunkSize: number
|
|
1174
|
+
): { startChunk: number; endChunk: number } {
|
|
1175
|
+
const startChunk = Math.floor(offset / chunkSize)
|
|
1176
|
+
const endOffset = offset + length - 1
|
|
1177
|
+
const endChunk = Math.floor(endOffset / chunkSize)
|
|
1178
|
+
return { startChunk, endChunk }
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
/**
|
|
1182
|
+
* Calculate the number of chunks needed for a file of given size
|
|
1183
|
+
*/
|
|
1184
|
+
export function calculateChunkCount(fileSize: number, chunkSize: number): number {
|
|
1185
|
+
if (fileSize === 0) return 0
|
|
1186
|
+
return Math.ceil(fileSize / chunkSize)
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
/**
|
|
1190
|
+
* Sanitize and normalize a file path
|
|
1191
|
+
*/
|
|
1192
|
+
export function sanitizePath(path: string): string {
|
|
1193
|
+
if (!path) return '/'
|
|
1194
|
+
|
|
1195
|
+
// Add leading slash if missing
|
|
1196
|
+
let normalized = path.startsWith('/') ? path : '/' + path
|
|
1197
|
+
|
|
1198
|
+
// Split into parts and resolve . and ..
|
|
1199
|
+
const parts = normalized.split('/').filter(p => p !== '' && p !== '.')
|
|
1200
|
+
const resolved: string[] = []
|
|
1201
|
+
|
|
1202
|
+
for (const part of parts) {
|
|
1203
|
+
if (part === '..') {
|
|
1204
|
+
resolved.pop()
|
|
1205
|
+
} else {
|
|
1206
|
+
resolved.push(part)
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
return '/' + resolved.join('/')
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* Validate a chunk size
|
|
1215
|
+
*/
|
|
1216
|
+
export function validateChunkSize(chunkSize: number): boolean {
|
|
1217
|
+
const MIN_CHUNK_SIZE = 512 // 512 bytes minimum
|
|
1218
|
+
const MAX_CHUNK_SIZE = 16 * 1024 * 1024 // 16 MB maximum
|
|
1219
|
+
|
|
1220
|
+
return chunkSize >= MIN_CHUNK_SIZE && chunkSize <= MAX_CHUNK_SIZE
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
/**
|
|
1224
|
+
* Format a byte size for human reading
|
|
1225
|
+
*/
|
|
1226
|
+
export function formatStorageSize(bytes: number): string {
|
|
1227
|
+
if (bytes === 0) return '0 B'
|
|
1228
|
+
|
|
1229
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB']
|
|
1230
|
+
let unitIndex = 0
|
|
1231
|
+
|
|
1232
|
+
while (bytes >= 1024 && unitIndex < units.length - 1) {
|
|
1233
|
+
bytes /= 1024
|
|
1234
|
+
unitIndex++
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
if (unitIndex === 0) {
|
|
1238
|
+
return `${bytes} ${units[unitIndex]}`
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
return `${bytes.toFixed(2)} ${units[unitIndex]}`
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/**
|
|
1245
|
+
* Custom error class for DOVFS errors
|
|
1246
|
+
*/
|
|
1247
|
+
export interface DOVFSError extends Error {
|
|
1248
|
+
code: number
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
/**
|
|
1252
|
+
* Create a DOVFS error with code and message
|
|
1253
|
+
*/
|
|
1254
|
+
export function createDOVFSError(code: number, message: string): DOVFSError {
|
|
1255
|
+
const error = new Error(`DOVFS Error (${code}): ${message}`) as DOVFSError
|
|
1256
|
+
error.code = code
|
|
1257
|
+
return error
|
|
1258
|
+
}
|