@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
package/src/worker/do.ts
ADDED
|
@@ -0,0 +1,1878 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgresDO - Durable Object for PostgreSQL with PGlite
|
|
3
|
+
*
|
|
4
|
+
* A Cloudflare Durable Object providing a complete PostgreSQL database running
|
|
5
|
+
* in WebAssembly via PGlite. Each DO instance maintains isolated persistent storage.
|
|
6
|
+
*
|
|
7
|
+
* ## Architecture
|
|
8
|
+
*
|
|
9
|
+
* PostgresDO orchestrates specialized managers for separation of concerns:
|
|
10
|
+
*
|
|
11
|
+
* | Manager | Responsibility |
|
|
12
|
+
* |---------|---------------|
|
|
13
|
+
* | ShutdownManager | Graceful shutdown, query tracking, connection draining |
|
|
14
|
+
* | PluginManager | Plugin/extension lifecycle (vector, postgis, etc.) |
|
|
15
|
+
* | DOAuthManager | Authentication via oauth.do integration |
|
|
16
|
+
* | QueryStatsManager | Query execution statistics and metrics |
|
|
17
|
+
* | PGLiteManager | PGlite instance lifecycle and initialization |
|
|
18
|
+
* | MigrationManager | Schema migrations with version tracking |
|
|
19
|
+
* | DOWALFacade | Write-Ahead Log capture for CDC/replication |
|
|
20
|
+
* | MemoryPressureManager | OOM protection and memory monitoring |
|
|
21
|
+
*
|
|
22
|
+
* ## Key Features
|
|
23
|
+
*
|
|
24
|
+
* - Native RPC support (extends cloudflare:workers DurableObject)
|
|
25
|
+
* - Promise pipelining for N+1 query elimination
|
|
26
|
+
* - Lazy initialization - PGlite created on first use
|
|
27
|
+
* - Auto-migrations on startup or on-demand
|
|
28
|
+
* - Graceful shutdown with configurable timeout
|
|
29
|
+
* - Memory protection - auto-unload extensions under pressure
|
|
30
|
+
*
|
|
31
|
+
* ## WASM Requirements
|
|
32
|
+
*
|
|
33
|
+
* In Cloudflare Workers, PGLite requires pre-compiled WASM modules via static imports.
|
|
34
|
+
* Uses @dotdo/pglite fork with trampoline-enabled build for Workers compatibility.
|
|
35
|
+
*
|
|
36
|
+
* @module worker/do
|
|
37
|
+
*/
|
|
38
|
+
import { DurableObject } from 'cloudflare:workers'
|
|
39
|
+
import type {
|
|
40
|
+
Env,
|
|
41
|
+
QueryRequest,
|
|
42
|
+
QueryResponse,
|
|
43
|
+
QueryResultRow,
|
|
44
|
+
PostgresConfig,
|
|
45
|
+
BatchRequest,
|
|
46
|
+
BatchResponse,
|
|
47
|
+
QueryField,
|
|
48
|
+
MigrationInput,
|
|
49
|
+
MigrationResult,
|
|
50
|
+
MigrationProgressEvent,
|
|
51
|
+
BatchMigrationResult,
|
|
52
|
+
MigrationState,
|
|
53
|
+
MigrationStrategy,
|
|
54
|
+
SchemaVersion,
|
|
55
|
+
VersionComparison,
|
|
56
|
+
PluginValue,
|
|
57
|
+
MemoryPressureConfig,
|
|
58
|
+
MemoryPressureLevel,
|
|
59
|
+
MemoryPressureEvent,
|
|
60
|
+
MemoryPressureListener,
|
|
61
|
+
MemoryStats,
|
|
62
|
+
MemoryPressureActionResult,
|
|
63
|
+
} from './types'
|
|
64
|
+
|
|
65
|
+
/** DO storage key for migration state */
|
|
66
|
+
const MIGRATION_STATE_KEY = '__postgres_migration_state__'
|
|
67
|
+
|
|
68
|
+
import {
|
|
69
|
+
PostgresRpcApi,
|
|
70
|
+
TransactionRpcApi,
|
|
71
|
+
type RpcQueryResult,
|
|
72
|
+
type RpcBatchQuery,
|
|
73
|
+
type RpcBatchResult,
|
|
74
|
+
type RpcTransactionOptions,
|
|
75
|
+
} from './rpc'
|
|
76
|
+
import { preserveCase } from './sql-transform'
|
|
77
|
+
import type { AuthenticatedUser, TokenValidationResult } from './auth'
|
|
78
|
+
import { NotInitializedError, ShutdownError } from './errors'
|
|
79
|
+
import { SchemaVersionManager, type MigrationEventListener } from './schema-version'
|
|
80
|
+
import { MigrationManager } from './migration-manager'
|
|
81
|
+
import {
|
|
82
|
+
DOWALFacade,
|
|
83
|
+
type WALConfig,
|
|
84
|
+
type WALEntry,
|
|
85
|
+
type WALBufferStats,
|
|
86
|
+
type WALEventListener,
|
|
87
|
+
type WALFlushListener,
|
|
88
|
+
type WALFlushResult,
|
|
89
|
+
} from './wal-facade'
|
|
90
|
+
import {
|
|
91
|
+
type PluginName,
|
|
92
|
+
} from '../extensions/plugins'
|
|
93
|
+
import { MemoryPressureManager, createMemoryPressureManager } from './memory-pressure'
|
|
94
|
+
|
|
95
|
+
// Import modular managers
|
|
96
|
+
import {
|
|
97
|
+
ShutdownManager,
|
|
98
|
+
type ShutdownStatus,
|
|
99
|
+
type ShutdownConfig,
|
|
100
|
+
type ShutdownEventType,
|
|
101
|
+
type ShutdownEvent,
|
|
102
|
+
type ShutdownEventListener,
|
|
103
|
+
} from './shutdown-manager'
|
|
104
|
+
import { PluginManager } from './plugin-manager'
|
|
105
|
+
import { DOAuthManager, type DOAuthConfig } from './do-auth-manager'
|
|
106
|
+
import { QueryStatsManager, type QueryStats } from './query-stats-manager'
|
|
107
|
+
import { PGLiteManager, type PGliteLike } from './do-pglite-manager'
|
|
108
|
+
|
|
109
|
+
// Re-export manager classes for external use
|
|
110
|
+
export { MigrationManager } from './migration-manager'
|
|
111
|
+
export { DOWALFacade } from './wal-facade'
|
|
112
|
+
|
|
113
|
+
// Re-export WorkersPGLite for external use
|
|
114
|
+
export { WorkersPGLite, createWorkersPGLite } from '../pglite/workers-pglite'
|
|
115
|
+
export type { WorkersPGLiteLike, WorkersPGLiteOptions } from '../pglite/workers-pglite'
|
|
116
|
+
|
|
117
|
+
// Re-export types from shutdown-manager (backward compatibility)
|
|
118
|
+
export type {
|
|
119
|
+
ShutdownStatus,
|
|
120
|
+
ShutdownEventType,
|
|
121
|
+
ShutdownEvent,
|
|
122
|
+
ShutdownEventListener,
|
|
123
|
+
ShutdownConfig,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Authentication configuration for PostgresDO
|
|
128
|
+
* Re-exported for backward compatibility
|
|
129
|
+
*/
|
|
130
|
+
export type PostgresDOAuthConfig = DOAuthConfig
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Extended Env with auth configuration
|
|
134
|
+
*/
|
|
135
|
+
interface AuthEnv extends Env {
|
|
136
|
+
OAUTH_URL?: string
|
|
137
|
+
OAUTH_ENABLED?: string
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* PostgresDO Durable Object
|
|
142
|
+
*
|
|
143
|
+
* Extends DurableObject from cloudflare:workers to enable native RPC support.
|
|
144
|
+
* All public methods are automatically exposed as RPC endpoints, enabling:
|
|
145
|
+
*
|
|
146
|
+
* - Magic map support for N+1 query elimination
|
|
147
|
+
* - Promise pipelining for efficient RPC
|
|
148
|
+
* - Direct Worker-to-DO communication without HTTP overhead
|
|
149
|
+
*
|
|
150
|
+
* ## Native RPC Usage (Worker-to-DO)
|
|
151
|
+
* ```typescript
|
|
152
|
+
* // In your Worker
|
|
153
|
+
* const id = env.POSTGRES_DO.idFromName('my-db')
|
|
154
|
+
* const stub = env.POSTGRES_DO.get(id)
|
|
155
|
+
*
|
|
156
|
+
* // Call RPC methods directly on the stub
|
|
157
|
+
* const result = await stub.rpcQuery('SELECT * FROM users')
|
|
158
|
+
* const tx = await stub.rpcTransaction()
|
|
159
|
+
* await tx.query('INSERT INTO users (name) VALUES ($1)', ['Alice'])
|
|
160
|
+
* await tx.commit()
|
|
161
|
+
* ```
|
|
162
|
+
*
|
|
163
|
+
* ## Promise Pipelining
|
|
164
|
+
* ```typescript
|
|
165
|
+
* const user = stub.rpcQueryOne('SELECT * FROM users WHERE id = $1', [1])
|
|
166
|
+
* const orders = stub.rpcQuery('SELECT * FROM orders WHERE user_id = $1', [user.id])
|
|
167
|
+
* const [userData, orderData] = await Promise.all([user, orders])
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export class PostgresDO extends DurableObject<Env> {
|
|
171
|
+
// Note: ctx and env are inherited from DurableObject<Env>
|
|
172
|
+
private _authEnv: AuthEnv | null = null
|
|
173
|
+
private config: PostgresConfig
|
|
174
|
+
|
|
175
|
+
// Modular managers
|
|
176
|
+
private shutdownManager: ShutdownManager
|
|
177
|
+
private pluginManager: PluginManager
|
|
178
|
+
private authManager: DOAuthManager
|
|
179
|
+
private statsManager: QueryStatsManager
|
|
180
|
+
private pgliteManager: PGLiteManager
|
|
181
|
+
|
|
182
|
+
// Injected concerns for dependency injection and testing
|
|
183
|
+
private injectedAuthConcern: unknown = null
|
|
184
|
+
private injectedQueryExecutionConcern: unknown = null
|
|
185
|
+
private injectedCDCConcern: unknown = null
|
|
186
|
+
// @ts-expect-error - Kept for future use in storage orchestration
|
|
187
|
+
private injectedStorageOrchestrationConcern: unknown = null
|
|
188
|
+
|
|
189
|
+
// Migration manager for schema migrations
|
|
190
|
+
private migrationManager: MigrationManager | null = null
|
|
191
|
+
private migrated = false
|
|
192
|
+
private migratePromise: Promise<BatchMigrationResult | null> | null = null
|
|
193
|
+
|
|
194
|
+
// PGLite initialization promise for deduplication
|
|
195
|
+
private initPGlitePromise: Promise<void> | null = null
|
|
196
|
+
|
|
197
|
+
// WAL facade for change capture
|
|
198
|
+
private walFacade: DOWALFacade | null = null
|
|
199
|
+
private walConfig: WALConfig = {}
|
|
200
|
+
private walInitPromise: Promise<void> | null = null
|
|
201
|
+
|
|
202
|
+
// Memory pressure manager for OOM protection
|
|
203
|
+
private memoryPressureManager: MemoryPressureManager | null = null
|
|
204
|
+
private memoryPressureConfig: MemoryPressureConfig = {}
|
|
205
|
+
|
|
206
|
+
constructor(
|
|
207
|
+
ctx: DurableObjectState,
|
|
208
|
+
env: Env,
|
|
209
|
+
config?: PostgresConfig,
|
|
210
|
+
authConfig?: PostgresDOAuthConfig,
|
|
211
|
+
walConfig?: WALConfig,
|
|
212
|
+
memoryPressureConfig?: MemoryPressureConfig
|
|
213
|
+
) {
|
|
214
|
+
super(ctx, env)
|
|
215
|
+
this._authEnv = env as AuthEnv
|
|
216
|
+
this.config = config ?? {
|
|
217
|
+
database: env.POSTGRES_DEFAULT_DB ?? 'postgres',
|
|
218
|
+
preserveCase: false,
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Initialize modular managers
|
|
222
|
+
this.shutdownManager = new ShutdownManager({
|
|
223
|
+
gracePeriodMs: 30000,
|
|
224
|
+
drainCheckIntervalMs: 100,
|
|
225
|
+
closeTimeoutMs: 5000,
|
|
226
|
+
maxListeners: 100,
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
this.pluginManager = new PluginManager({
|
|
230
|
+
...(this.config.plugins !== undefined && { plugins: this.config.plugins }),
|
|
231
|
+
...(this.config.debug !== undefined && { debug: this.config.debug }),
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
this.authManager = new DOAuthManager(
|
|
235
|
+
authConfig ?? {
|
|
236
|
+
enabled: (env as AuthEnv).OAUTH_ENABLED === 'true',
|
|
237
|
+
oauthUrl: (env as AuthEnv).OAUTH_URL || 'https://oauth.do',
|
|
238
|
+
tokenCacheTTL: 60000,
|
|
239
|
+
allowAnonymous: false,
|
|
240
|
+
}
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
this.statsManager = new QueryStatsManager()
|
|
244
|
+
|
|
245
|
+
this.pgliteManager = new PGLiteManager({
|
|
246
|
+
database: this.config.database,
|
|
247
|
+
...(this.config.debug !== undefined && { debug: this.config.debug }),
|
|
248
|
+
...(this.config.plugins !== undefined && { plugins: this.config.plugins }),
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
this.walConfig = walConfig ?? {}
|
|
252
|
+
this.memoryPressureConfig = memoryPressureConfig ?? {}
|
|
253
|
+
|
|
254
|
+
// Initialize migration manager (executor set later after PGlite init)
|
|
255
|
+
this.migrationManager = new MigrationManager(ctx.storage, null, {
|
|
256
|
+
...(this.config.migrations !== undefined && { migrations: this.config.migrations }),
|
|
257
|
+
...(this.config.debug !== undefined && { debug: this.config.debug }),
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
// Initialize WAL facade
|
|
261
|
+
this.walFacade = new DOWALFacade(ctx, this.walConfig)
|
|
262
|
+
|
|
263
|
+
// Initialize memory pressure manager
|
|
264
|
+
this.memoryPressureManager = createMemoryPressureManager(this.memoryPressureConfig)
|
|
265
|
+
|
|
266
|
+
// Handle injected concerns from config
|
|
267
|
+
if (this.config.concerns) {
|
|
268
|
+
this.injectedAuthConcern = this.config.concerns.auth ?? null
|
|
269
|
+
this.injectedQueryExecutionConcern = this.config.concerns.queryExecution ?? null
|
|
270
|
+
this.injectedCDCConcern = this.config.concerns.cdc ?? null
|
|
271
|
+
this.injectedStorageOrchestrationConcern = this.config.concerns.storageOrchestration ?? null
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// ============================================================
|
|
276
|
+
// Concern Injection Methods
|
|
277
|
+
// ============================================================
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Set or replace a concern at runtime
|
|
281
|
+
* Used for testing and dynamic concern injection
|
|
282
|
+
*/
|
|
283
|
+
setConcern(
|
|
284
|
+
name: 'auth' | 'queryExecution' | 'cdc' | 'storageOrchestration',
|
|
285
|
+
concern: unknown
|
|
286
|
+
): void {
|
|
287
|
+
switch (name) {
|
|
288
|
+
case 'auth':
|
|
289
|
+
this.injectedAuthConcern = concern
|
|
290
|
+
break
|
|
291
|
+
case 'queryExecution':
|
|
292
|
+
this.injectedQueryExecutionConcern = concern
|
|
293
|
+
break
|
|
294
|
+
case 'cdc':
|
|
295
|
+
this.injectedCDCConcern = concern
|
|
296
|
+
break
|
|
297
|
+
case 'storageOrchestration':
|
|
298
|
+
this.injectedStorageOrchestrationConcern = concern
|
|
299
|
+
break
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ============================================================
|
|
304
|
+
// State and Configuration Methods
|
|
305
|
+
// ============================================================
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Get the DurableObject state
|
|
309
|
+
*/
|
|
310
|
+
getState(): DurableObjectState {
|
|
311
|
+
return this.ctx
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Get the environment
|
|
316
|
+
*/
|
|
317
|
+
getEnv(): Env {
|
|
318
|
+
return this.env
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Get the environment as AuthEnv (for OAuth-related properties)
|
|
323
|
+
*/
|
|
324
|
+
getAuthEnv(): AuthEnv {
|
|
325
|
+
return this._authEnv ?? (this.env as AuthEnv)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Check if PGlite is initialized
|
|
330
|
+
*/
|
|
331
|
+
isInitialized(): boolean {
|
|
332
|
+
return this.pgliteManager.isInitialized()
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Get current configuration
|
|
337
|
+
*/
|
|
338
|
+
getConfig(): PostgresConfig {
|
|
339
|
+
return { ...this.config }
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Get query statistics
|
|
344
|
+
*/
|
|
345
|
+
getStats(): QueryStats {
|
|
346
|
+
return this.statsManager.getStats()
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Get uptime in milliseconds
|
|
351
|
+
*/
|
|
352
|
+
getUptime(): number {
|
|
353
|
+
return this.statsManager.getUptime()
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// ============================================================
|
|
357
|
+
// Authentication Methods (delegated to DOAuthManager or injected concern)
|
|
358
|
+
// ============================================================
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Get authentication configuration
|
|
362
|
+
*/
|
|
363
|
+
getAuthConfig(): PostgresDOAuthConfig {
|
|
364
|
+
// Use injected auth concern if available
|
|
365
|
+
if (
|
|
366
|
+
this.injectedAuthConcern &&
|
|
367
|
+
typeof (this.injectedAuthConcern as { getConfig?: () => PostgresDOAuthConfig }).getConfig ===
|
|
368
|
+
'function'
|
|
369
|
+
) {
|
|
370
|
+
return (this.injectedAuthConcern as { getConfig: () => PostgresDOAuthConfig }).getConfig()
|
|
371
|
+
}
|
|
372
|
+
return this.authManager.getConfig()
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Set the user ID for this DO instance (for user-scoped access)
|
|
377
|
+
*/
|
|
378
|
+
setUserId(userId: string): void {
|
|
379
|
+
// Use injected auth concern if available
|
|
380
|
+
if (
|
|
381
|
+
this.injectedAuthConcern &&
|
|
382
|
+
typeof (this.injectedAuthConcern as { setUserId?: (id: string) => void }).setUserId ===
|
|
383
|
+
'function'
|
|
384
|
+
) {
|
|
385
|
+
;(this.injectedAuthConcern as { setUserId: (id: string) => void }).setUserId(userId)
|
|
386
|
+
return
|
|
387
|
+
}
|
|
388
|
+
this.authManager.setUserId(userId)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Get the user ID for this DO instance
|
|
393
|
+
*/
|
|
394
|
+
getUserId(): string | undefined {
|
|
395
|
+
// Use injected auth concern if available
|
|
396
|
+
if (
|
|
397
|
+
this.injectedAuthConcern &&
|
|
398
|
+
typeof (this.injectedAuthConcern as { getUserId?: () => string | undefined }).getUserId ===
|
|
399
|
+
'function'
|
|
400
|
+
) {
|
|
401
|
+
return (this.injectedAuthConcern as { getUserId: () => string | undefined }).getUserId()
|
|
402
|
+
}
|
|
403
|
+
return this.authManager.getUserId()
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Validate a bearer token using oauth.do
|
|
408
|
+
*/
|
|
409
|
+
async validateToken(token: string): Promise<TokenValidationResult> {
|
|
410
|
+
// Use injected auth concern if available
|
|
411
|
+
if (
|
|
412
|
+
this.injectedAuthConcern &&
|
|
413
|
+
typeof (
|
|
414
|
+
this.injectedAuthConcern as { validateToken?: (t: string) => Promise<TokenValidationResult> }
|
|
415
|
+
).validateToken === 'function'
|
|
416
|
+
) {
|
|
417
|
+
return (
|
|
418
|
+
this.injectedAuthConcern as { validateToken: (t: string) => Promise<TokenValidationResult> }
|
|
419
|
+
).validateToken(token)
|
|
420
|
+
}
|
|
421
|
+
return this.authManager.validateToken(token)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Authenticate a request and return the user
|
|
426
|
+
* Returns null if authentication fails or is not required
|
|
427
|
+
*/
|
|
428
|
+
async authenticateRequest(request: Request): Promise<AuthenticatedUser | null> {
|
|
429
|
+
// Use injected auth concern if available
|
|
430
|
+
if (
|
|
431
|
+
this.injectedAuthConcern &&
|
|
432
|
+
typeof (
|
|
433
|
+
this.injectedAuthConcern as {
|
|
434
|
+
authenticateRequest?: (r: Request) => Promise<AuthenticatedUser | null>
|
|
435
|
+
}
|
|
436
|
+
).authenticateRequest === 'function'
|
|
437
|
+
) {
|
|
438
|
+
return (
|
|
439
|
+
this.injectedAuthConcern as {
|
|
440
|
+
authenticateRequest: (r: Request) => Promise<AuthenticatedUser | null>
|
|
441
|
+
}
|
|
442
|
+
).authenticateRequest(request)
|
|
443
|
+
}
|
|
444
|
+
return this.authManager.authenticateRequest(request)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// ============================================================
|
|
448
|
+
// WAL (Write-Ahead Log) Methods (delegated to DOWALFacade)
|
|
449
|
+
// ============================================================
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Get the WAL facade instance
|
|
453
|
+
*/
|
|
454
|
+
getWALFacade(): DOWALFacade {
|
|
455
|
+
if (!this.walFacade) {
|
|
456
|
+
this.walFacade = new DOWALFacade(this.ctx, this.walConfig)
|
|
457
|
+
}
|
|
458
|
+
return this.walFacade
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Initialize the WAL manager (restores LSN from storage)
|
|
463
|
+
*/
|
|
464
|
+
async initWAL(): Promise<void> {
|
|
465
|
+
if (this.walInitPromise) return this.walInitPromise
|
|
466
|
+
this.walInitPromise = this.getWALFacade().initialize()
|
|
467
|
+
return this.walInitPromise
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Check if WAL capture is enabled
|
|
472
|
+
*/
|
|
473
|
+
isWALEnabled(): boolean {
|
|
474
|
+
// Use injected CDC concern if available
|
|
475
|
+
if (
|
|
476
|
+
this.injectedCDCConcern &&
|
|
477
|
+
typeof (this.injectedCDCConcern as { isEnabled?: () => boolean }).isEnabled === 'function'
|
|
478
|
+
) {
|
|
479
|
+
return (this.injectedCDCConcern as { isEnabled: () => boolean }).isEnabled()
|
|
480
|
+
}
|
|
481
|
+
return this.getWALFacade().isEnabled()
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Enable or disable WAL capture
|
|
486
|
+
*/
|
|
487
|
+
setWALEnabled(enabled: boolean): void {
|
|
488
|
+
this.getWALFacade().setEnabled(enabled)
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Get WAL configuration
|
|
493
|
+
*/
|
|
494
|
+
getWALConfig(): WALConfig {
|
|
495
|
+
return this.getWALFacade().getConfig()
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Update WAL configuration
|
|
500
|
+
*/
|
|
501
|
+
setWALConfig(config: Partial<WALConfig>): void {
|
|
502
|
+
this.getWALFacade().setConfig(config)
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Get WAL buffer statistics
|
|
507
|
+
*/
|
|
508
|
+
getWALStats(): WALBufferStats {
|
|
509
|
+
return this.getWALFacade().getStats()
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Get current WAL LSN (Log Sequence Number)
|
|
514
|
+
*/
|
|
515
|
+
getWALCurrentLsn(): bigint {
|
|
516
|
+
return this.getWALFacade().getCurrentLsn()
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Add a listener for WAL entries
|
|
521
|
+
*/
|
|
522
|
+
onWALEntry(listener: WALEventListener): () => void {
|
|
523
|
+
return this.getWALFacade().onEntry(listener)
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Add a listener for WAL flush events
|
|
528
|
+
*/
|
|
529
|
+
onWALFlush(listener: WALFlushListener): () => void {
|
|
530
|
+
return this.getWALFacade().onFlush(listener)
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Flush WAL buffer to storage
|
|
535
|
+
*/
|
|
536
|
+
async flushWAL(): Promise<WALFlushResult> {
|
|
537
|
+
return this.getWALFacade().flush()
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Get buffered WAL entries (without flushing)
|
|
542
|
+
*/
|
|
543
|
+
getWALBuffer(): WALEntry[] {
|
|
544
|
+
return this.getWALFacade().getBufferedEntries()
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Read WAL entries from storage
|
|
549
|
+
*/
|
|
550
|
+
async readWALFromStorage(fromLsn: bigint, limit?: number): Promise<WALEntry[]> {
|
|
551
|
+
return this.getWALFacade().readFromStorage(fromLsn, limit)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Capture a write operation to WAL
|
|
556
|
+
*/
|
|
557
|
+
private captureWAL(
|
|
558
|
+
sql: string,
|
|
559
|
+
result: {
|
|
560
|
+
rows?: Record<string, unknown>[]
|
|
561
|
+
affectedRows?: number
|
|
562
|
+
}
|
|
563
|
+
): WALEntry | null {
|
|
564
|
+
const walFacade = this.getWALFacade()
|
|
565
|
+
if (!walFacade.isEnabled()) {
|
|
566
|
+
return null
|
|
567
|
+
}
|
|
568
|
+
return walFacade.capture(sql, result)
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// ============================================================
|
|
572
|
+
// Memory Pressure Methods (delegated to MemoryPressureManager)
|
|
573
|
+
// ============================================================
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Get the memory pressure manager instance
|
|
577
|
+
*/
|
|
578
|
+
getMemoryPressureManager(): MemoryPressureManager {
|
|
579
|
+
if (!this.memoryPressureManager) {
|
|
580
|
+
this.memoryPressureManager = createMemoryPressureManager(this.memoryPressureConfig)
|
|
581
|
+
}
|
|
582
|
+
return this.memoryPressureManager
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Get current memory statistics
|
|
587
|
+
*/
|
|
588
|
+
getMemoryStats(): MemoryStats {
|
|
589
|
+
return this.getMemoryPressureManager().getMemoryStats()
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Get current memory pressure level
|
|
594
|
+
*/
|
|
595
|
+
getMemoryPressureLevel(): MemoryPressureLevel {
|
|
596
|
+
return this.getMemoryPressureManager().getPressureLevel()
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Check if memory pressure is at or above a certain level
|
|
601
|
+
*/
|
|
602
|
+
isMemoryPressureAtOrAbove(level: MemoryPressureLevel): boolean {
|
|
603
|
+
return this.getMemoryPressureManager().isPressureAtOrAbove(level)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Get memory pressure configuration
|
|
608
|
+
*/
|
|
609
|
+
getMemoryPressureConfig(): MemoryPressureConfig {
|
|
610
|
+
return this.getMemoryPressureManager().getConfig()
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Update memory pressure configuration
|
|
615
|
+
*/
|
|
616
|
+
setMemoryPressureConfig(config: Partial<MemoryPressureConfig>): void {
|
|
617
|
+
this.getMemoryPressureManager().setConfig(config)
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Add a listener for memory pressure events
|
|
622
|
+
*/
|
|
623
|
+
onMemoryPressure(listener: MemoryPressureListener): () => void {
|
|
624
|
+
return this.getMemoryPressureManager().onPressureChange(listener)
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Get the number of memory pressure listeners
|
|
629
|
+
*/
|
|
630
|
+
getMemoryPressureListenerCount(): number {
|
|
631
|
+
return this.getMemoryPressureManager().getListenerCount()
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Start periodic memory pressure monitoring
|
|
636
|
+
*/
|
|
637
|
+
startMemoryMonitoring(): void {
|
|
638
|
+
const manager = this.getMemoryPressureManager()
|
|
639
|
+
const pglite = this.pgliteManager.getInstanceOrNull()
|
|
640
|
+
if (pglite) {
|
|
641
|
+
manager.setPGlite(pglite)
|
|
642
|
+
}
|
|
643
|
+
manager.startMonitoring()
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Stop periodic memory pressure monitoring
|
|
648
|
+
*/
|
|
649
|
+
stopMemoryMonitoring(): void {
|
|
650
|
+
this.getMemoryPressureManager().stopMonitoring()
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Manually check memory pressure and take action if needed
|
|
655
|
+
*/
|
|
656
|
+
async checkMemoryPressure(): Promise<MemoryPressureEvent | null> {
|
|
657
|
+
return this.getMemoryPressureManager().checkMemoryPressure()
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Manually unload the least important extension to free memory
|
|
662
|
+
*/
|
|
663
|
+
async unloadExtensionForMemory(): Promise<MemoryPressureActionResult> {
|
|
664
|
+
const manager = this.getMemoryPressureManager()
|
|
665
|
+
const pglite = this.pgliteManager.getInstanceOrNull()
|
|
666
|
+
if (pglite) {
|
|
667
|
+
manager.setPGlite(pglite)
|
|
668
|
+
}
|
|
669
|
+
return manager.unloadLeastImportantExtension()
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Get list of extensions that have been unloaded due to memory pressure
|
|
674
|
+
*/
|
|
675
|
+
getUnloadedExtensions(): string[] {
|
|
676
|
+
return this.getMemoryPressureManager().getUnloadedExtensions()
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Check if an extension was unloaded due to memory pressure
|
|
681
|
+
*/
|
|
682
|
+
wasExtensionUnloaded(extensionName: string): boolean {
|
|
683
|
+
return this.getMemoryPressureManager().wasExtensionUnloaded(extensionName)
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// ============================================================
|
|
687
|
+
// Shutdown Methods (delegated to ShutdownManager)
|
|
688
|
+
// ============================================================
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Check if PGLite is responsive by running a simple query
|
|
692
|
+
*/
|
|
693
|
+
async checkLiveness(): Promise<boolean> {
|
|
694
|
+
return this.pgliteManager.checkLiveness()
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Get current shutdown status
|
|
699
|
+
*/
|
|
700
|
+
getShutdownStatus(): ShutdownStatus {
|
|
701
|
+
return this.shutdownManager.getStatus()
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Check if the DO is shutting down (draining or shutdown)
|
|
706
|
+
*/
|
|
707
|
+
isShuttingDown(): boolean {
|
|
708
|
+
return this.shutdownManager.isShuttingDown()
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Get the number of active queries
|
|
713
|
+
*/
|
|
714
|
+
getActiveQueryCount(): number {
|
|
715
|
+
return this.shutdownManager.getActiveQueryCount()
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* Get active query info (for monitoring)
|
|
720
|
+
*/
|
|
721
|
+
getActiveQueries(): Array<{ id: string; sql: string; durationMs: number }> {
|
|
722
|
+
return this.shutdownManager.getActiveQueries()
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Configure shutdown behavior
|
|
727
|
+
*/
|
|
728
|
+
setShutdownConfig(config: Partial<ShutdownConfig>): void {
|
|
729
|
+
this.shutdownManager.setConfig(config)
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Get shutdown configuration
|
|
734
|
+
*/
|
|
735
|
+
getShutdownConfig(): ShutdownConfig {
|
|
736
|
+
return this.shutdownManager.getConfig()
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Get the current number of shutdown event listeners
|
|
741
|
+
*/
|
|
742
|
+
getShutdownListenerCount(): number {
|
|
743
|
+
return this.shutdownManager.getListenerCount()
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Add a shutdown event listener
|
|
748
|
+
*/
|
|
749
|
+
onShutdownEvent(listener: ShutdownEventListener): () => void {
|
|
750
|
+
return this.shutdownManager.onShutdownEvent(listener)
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Initiate graceful shutdown
|
|
755
|
+
*/
|
|
756
|
+
async shutdown(config?: Partial<ShutdownConfig>): Promise<void> {
|
|
757
|
+
const pglite = this.pgliteManager.getInstanceOrNull()
|
|
758
|
+
|
|
759
|
+
// Create a WebSocket state adapter for the shutdown manager
|
|
760
|
+
const wsState = {
|
|
761
|
+
getWebSockets: () => {
|
|
762
|
+
try {
|
|
763
|
+
return this.ctx.getWebSockets()
|
|
764
|
+
} catch {
|
|
765
|
+
return []
|
|
766
|
+
}
|
|
767
|
+
},
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
await this.shutdownManager.shutdown(pglite, wsState, config)
|
|
771
|
+
|
|
772
|
+
// Stop memory monitoring
|
|
773
|
+
if (this.memoryPressureManager) {
|
|
774
|
+
this.memoryPressureManager.dispose()
|
|
775
|
+
this.memoryPressureManager = null
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// Reset PGLite manager
|
|
779
|
+
this.pgliteManager.reset()
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// ============================================================
|
|
783
|
+
// Migration Methods (delegated to MigrationManager)
|
|
784
|
+
// ============================================================
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Get the migration manager instance
|
|
788
|
+
*/
|
|
789
|
+
getMigrationManager(): MigrationManager {
|
|
790
|
+
if (!this.migrationManager) {
|
|
791
|
+
this.migrationManager = new MigrationManager(
|
|
792
|
+
this.ctx.storage,
|
|
793
|
+
this.pgliteManager.getInstanceOrNull(),
|
|
794
|
+
{
|
|
795
|
+
...(this.config.migrations !== undefined && { migrations: this.config.migrations }),
|
|
796
|
+
...(this.config.debug !== undefined && { debug: this.config.debug }),
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
}
|
|
800
|
+
return this.migrationManager
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* Get the current schema version from DO storage
|
|
805
|
+
*/
|
|
806
|
+
async getSchemaVersion(): Promise<number> {
|
|
807
|
+
return this.getMigrationManager().getSchemaVersion()
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
/**
|
|
811
|
+
* Check if this is a fresh database (no schema version set)
|
|
812
|
+
*/
|
|
813
|
+
async isFreshDatabase(): Promise<boolean> {
|
|
814
|
+
return this.getMigrationManager().isFreshDatabase()
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* Check if migrations have been applied this session
|
|
819
|
+
*/
|
|
820
|
+
isMigrated(): boolean {
|
|
821
|
+
return this.migrated
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Get the schema version manager
|
|
826
|
+
*/
|
|
827
|
+
getSchemaVersionManager(): SchemaVersionManager | null {
|
|
828
|
+
return this.getMigrationManager().getSchemaVersionManager()
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Get full schema version details including migration history
|
|
833
|
+
*/
|
|
834
|
+
async getSchemaVersionDetails(): Promise<SchemaVersion> {
|
|
835
|
+
if (!this.isInitialized()) {
|
|
836
|
+
await this.initPGlite()
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
const manager = this.getSchemaVersionManager()
|
|
840
|
+
if (!manager) {
|
|
841
|
+
throw new NotInitializedError('getting schema version details')
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
return manager.getSchemaVersion()
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* Compare current schema version against a target version
|
|
849
|
+
*/
|
|
850
|
+
async compareSchemaVersion(targetVersion: number): Promise<VersionComparison> {
|
|
851
|
+
if (!this.isInitialized()) {
|
|
852
|
+
await this.initPGlite()
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
const manager = this.getSchemaVersionManager()
|
|
856
|
+
if (!manager) {
|
|
857
|
+
throw new NotInitializedError('comparing schema version')
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
return manager.compareVersion(targetVersion)
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Check if a specific migration has been applied
|
|
865
|
+
*/
|
|
866
|
+
async isMigrationApplied(migrationId: string): Promise<boolean> {
|
|
867
|
+
if (!this.isInitialized()) {
|
|
868
|
+
await this.initPGlite()
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
const manager = this.getSchemaVersionManager()
|
|
872
|
+
if (!manager) {
|
|
873
|
+
throw new NotInitializedError('checking migration status')
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
return manager.isMigrationApplied(migrationId)
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* Add a listener for migration events
|
|
881
|
+
*/
|
|
882
|
+
onMigrationEvent(listener: MigrationEventListener): () => void {
|
|
883
|
+
const manager = this.getSchemaVersionManager()
|
|
884
|
+
if (manager) {
|
|
885
|
+
return manager.onMigrationEvent(listener)
|
|
886
|
+
}
|
|
887
|
+
return () => {}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Run a single migration
|
|
892
|
+
* @internal
|
|
893
|
+
*/
|
|
894
|
+
private async runSingleMigration(
|
|
895
|
+
migration: MigrationInput,
|
|
896
|
+
index: number,
|
|
897
|
+
total: number,
|
|
898
|
+
onProgress?: (event: MigrationProgressEvent) => void
|
|
899
|
+
): Promise<MigrationResult> {
|
|
900
|
+
const startTime = performance.now()
|
|
901
|
+
const pglite = this.pgliteManager.getInstance()
|
|
902
|
+
|
|
903
|
+
onProgress?.({
|
|
904
|
+
migration,
|
|
905
|
+
index,
|
|
906
|
+
total,
|
|
907
|
+
phase: 'starting',
|
|
908
|
+
})
|
|
909
|
+
|
|
910
|
+
try {
|
|
911
|
+
const currentVersion = await this.getSchemaVersion()
|
|
912
|
+
if (migration.version <= currentVersion) {
|
|
913
|
+
return {
|
|
914
|
+
success: true,
|
|
915
|
+
id: migration.id,
|
|
916
|
+
executionTimeMs: 0,
|
|
917
|
+
skipped: true,
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
onProgress?.({
|
|
922
|
+
migration,
|
|
923
|
+
index,
|
|
924
|
+
total,
|
|
925
|
+
phase: 'executing',
|
|
926
|
+
})
|
|
927
|
+
|
|
928
|
+
await pglite.query('BEGIN')
|
|
929
|
+
try {
|
|
930
|
+
if (pglite.exec) {
|
|
931
|
+
await pglite.exec(migration.sql)
|
|
932
|
+
} else {
|
|
933
|
+
const statements = migration.sql
|
|
934
|
+
.split(';')
|
|
935
|
+
.map((s) => s.trim())
|
|
936
|
+
.filter((s) => s.length > 0)
|
|
937
|
+
for (const stmt of statements) {
|
|
938
|
+
await pglite.query(stmt)
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
await this.getMigrationManager().setSchemaVersion(migration.version)
|
|
943
|
+
await pglite.query('COMMIT')
|
|
944
|
+
} catch (error) {
|
|
945
|
+
await pglite.query('ROLLBACK')
|
|
946
|
+
throw error
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
const executionTimeMs = performance.now() - startTime
|
|
950
|
+
|
|
951
|
+
onProgress?.({
|
|
952
|
+
migration,
|
|
953
|
+
index,
|
|
954
|
+
total,
|
|
955
|
+
phase: 'completed',
|
|
956
|
+
durationMs: executionTimeMs,
|
|
957
|
+
})
|
|
958
|
+
|
|
959
|
+
return {
|
|
960
|
+
success: true,
|
|
961
|
+
id: migration.id,
|
|
962
|
+
executionTimeMs,
|
|
963
|
+
}
|
|
964
|
+
} catch (error) {
|
|
965
|
+
const executionTimeMs = performance.now() - startTime
|
|
966
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
|
967
|
+
|
|
968
|
+
onProgress?.({
|
|
969
|
+
migration,
|
|
970
|
+
index,
|
|
971
|
+
total,
|
|
972
|
+
phase: 'failed',
|
|
973
|
+
durationMs: executionTimeMs,
|
|
974
|
+
error: errorMessage,
|
|
975
|
+
})
|
|
976
|
+
|
|
977
|
+
return {
|
|
978
|
+
success: false,
|
|
979
|
+
id: migration.id,
|
|
980
|
+
executionTimeMs,
|
|
981
|
+
error: errorMessage,
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Run all pending migrations in sequence
|
|
988
|
+
*/
|
|
989
|
+
async runMigrations(
|
|
990
|
+
migrations: MigrationInput[],
|
|
991
|
+
onProgress?: (event: MigrationProgressEvent) => void
|
|
992
|
+
): Promise<BatchMigrationResult> {
|
|
993
|
+
const startTime = performance.now()
|
|
994
|
+
const fromVersion = await this.getSchemaVersion()
|
|
995
|
+
|
|
996
|
+
const sortedMigrations = [...migrations].sort((a, b) => a.version - b.version)
|
|
997
|
+
const pendingMigrations = sortedMigrations.filter((m) => m.version > fromVersion)
|
|
998
|
+
|
|
999
|
+
if (pendingMigrations.length === 0) {
|
|
1000
|
+
return {
|
|
1001
|
+
success: true,
|
|
1002
|
+
fromVersion,
|
|
1003
|
+
toVersion: fromVersion,
|
|
1004
|
+
durationMs: 0,
|
|
1005
|
+
results: [],
|
|
1006
|
+
migrationsRun: 0,
|
|
1007
|
+
migrationsSkipped: sortedMigrations.length,
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
const results: MigrationResult[] = []
|
|
1012
|
+
let migrationsRun = 0
|
|
1013
|
+
let migrationsSkipped = sortedMigrations.length - pendingMigrations.length
|
|
1014
|
+
|
|
1015
|
+
for (let i = 0; i < pendingMigrations.length; i++) {
|
|
1016
|
+
const migration = pendingMigrations[i]
|
|
1017
|
+
if (!migration) continue
|
|
1018
|
+
const result = await this.runSingleMigration(migration, i, pendingMigrations.length, onProgress)
|
|
1019
|
+
results.push(result)
|
|
1020
|
+
|
|
1021
|
+
if (result.skipped) {
|
|
1022
|
+
migrationsSkipped++
|
|
1023
|
+
} else if (result.success) {
|
|
1024
|
+
migrationsRun++
|
|
1025
|
+
} else {
|
|
1026
|
+
const durationMs = performance.now() - startTime
|
|
1027
|
+
const toVersion = await this.getSchemaVersion()
|
|
1028
|
+
|
|
1029
|
+
return {
|
|
1030
|
+
success: false,
|
|
1031
|
+
fromVersion,
|
|
1032
|
+
toVersion,
|
|
1033
|
+
durationMs,
|
|
1034
|
+
results,
|
|
1035
|
+
migrationsRun,
|
|
1036
|
+
migrationsSkipped,
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
const durationMs = performance.now() - startTime
|
|
1042
|
+
const toVersion = await this.getSchemaVersion()
|
|
1043
|
+
|
|
1044
|
+
return {
|
|
1045
|
+
success: true,
|
|
1046
|
+
fromVersion,
|
|
1047
|
+
toVersion,
|
|
1048
|
+
durationMs,
|
|
1049
|
+
results,
|
|
1050
|
+
migrationsRun,
|
|
1051
|
+
migrationsSkipped,
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Ensure database is migrated to latest version
|
|
1057
|
+
*/
|
|
1058
|
+
async ensureMigrated(): Promise<BatchMigrationResult | null> {
|
|
1059
|
+
if (this.migrated) {
|
|
1060
|
+
return null
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
const migrations = this.config.migrations?.migrations
|
|
1064
|
+
if (!migrations || migrations.length === 0) {
|
|
1065
|
+
this.migrated = true
|
|
1066
|
+
return null
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
if (this.migratePromise) {
|
|
1070
|
+
return this.migratePromise
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
if (!this.pgliteManager.getInstanceOrNull()) {
|
|
1074
|
+
throw new NotInitializedError('running migrations')
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
this.migratePromise = this.performMigrations()
|
|
1078
|
+
|
|
1079
|
+
try {
|
|
1080
|
+
const result = await this.migratePromise
|
|
1081
|
+
this.migrated = result!.success
|
|
1082
|
+
return result!
|
|
1083
|
+
} finally {
|
|
1084
|
+
this.migratePromise = null
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/**
|
|
1089
|
+
* Internal migration implementation
|
|
1090
|
+
*/
|
|
1091
|
+
private async performMigrations(): Promise<BatchMigrationResult> {
|
|
1092
|
+
const migrationConfig = this.config.migrations!
|
|
1093
|
+
const migrations = migrationConfig.migrations
|
|
1094
|
+
const onProgress = migrationConfig.onProgress
|
|
1095
|
+
|
|
1096
|
+
return this.runMigrations(migrations, onProgress)
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// ============================================================
|
|
1100
|
+
// Plugin Management Methods (delegated to PluginManager)
|
|
1101
|
+
// ============================================================
|
|
1102
|
+
|
|
1103
|
+
/**
|
|
1104
|
+
* Get the last plugin load result (for diagnostics)
|
|
1105
|
+
*/
|
|
1106
|
+
getLastPluginLoadResult() {
|
|
1107
|
+
return this.pluginManager.getLastLoadResult()
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* List all available plugins with their status
|
|
1112
|
+
*/
|
|
1113
|
+
async listPlugins(): Promise<import('./types').PluginStatus[]> {
|
|
1114
|
+
if (!this.isInitialized()) {
|
|
1115
|
+
await this.initPGlite()
|
|
1116
|
+
}
|
|
1117
|
+
return this.pluginManager.listPlugins(this.pgliteManager.getInstance())
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
/**
|
|
1121
|
+
* Get the status of a specific plugin
|
|
1122
|
+
*/
|
|
1123
|
+
async getPluginStatus(name: PluginName): Promise<import('./types').PluginStatus | null> {
|
|
1124
|
+
if (!this.isInitialized()) {
|
|
1125
|
+
await this.initPGlite()
|
|
1126
|
+
}
|
|
1127
|
+
return this.pluginManager.getPluginStatus(name, this.pgliteManager.getInstance())
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* Enable a plugin for this DO instance
|
|
1132
|
+
*/
|
|
1133
|
+
async enablePlugin(
|
|
1134
|
+
name: PluginName,
|
|
1135
|
+
autoCreate: boolean = false
|
|
1136
|
+
): Promise<import('./types').PluginToggleResponse> {
|
|
1137
|
+
if (!this.isInitialized()) {
|
|
1138
|
+
await this.initPGlite()
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
// Update config
|
|
1142
|
+
if (!this.config.plugins) {
|
|
1143
|
+
this.config.plugins = {}
|
|
1144
|
+
}
|
|
1145
|
+
;(this.config.plugins as Record<string, PluginValue>)[name] = { enabled: true, autoCreate }
|
|
1146
|
+
|
|
1147
|
+
return this.pluginManager.enablePlugin(name, this.pgliteManager.getInstance(), autoCreate)
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* Disable a plugin for this DO instance
|
|
1152
|
+
*/
|
|
1153
|
+
async disablePlugin(name: PluginName): Promise<import('./types').PluginToggleResponse> {
|
|
1154
|
+
if (this.config.plugins) {
|
|
1155
|
+
;(this.config.plugins as Record<string, PluginValue>)[name] = false
|
|
1156
|
+
}
|
|
1157
|
+
return this.pluginManager.disablePlugin(name)
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/**
|
|
1161
|
+
* Create an extension in the database
|
|
1162
|
+
*/
|
|
1163
|
+
async createExtension(name: PluginName): Promise<import('./types').PluginToggleResponse> {
|
|
1164
|
+
if (!this.isInitialized()) {
|
|
1165
|
+
await this.initPGlite()
|
|
1166
|
+
}
|
|
1167
|
+
return this.pluginManager.createExtension(name, this.pgliteManager.getInstance())
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Drop an extension from the database
|
|
1172
|
+
*/
|
|
1173
|
+
async dropExtension(
|
|
1174
|
+
name: PluginName,
|
|
1175
|
+
cascade: boolean = false
|
|
1176
|
+
): Promise<import('./types').PluginToggleResponse> {
|
|
1177
|
+
if (!this.isInitialized()) {
|
|
1178
|
+
await this.initPGlite()
|
|
1179
|
+
}
|
|
1180
|
+
return this.pluginManager.dropExtension(name, this.pgliteManager.getInstance(), cascade)
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
// ============================================================
|
|
1184
|
+
// Migration Strategy Methods
|
|
1185
|
+
// ============================================================
|
|
1186
|
+
|
|
1187
|
+
/**
|
|
1188
|
+
* Get the migration strategy from configuration
|
|
1189
|
+
*/
|
|
1190
|
+
getMigrationStrategy(): MigrationStrategy {
|
|
1191
|
+
return this.config.migrations?.strategy ?? 'on-create'
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
/**
|
|
1195
|
+
* Get the current migration state from DO storage
|
|
1196
|
+
*/
|
|
1197
|
+
async getMigrationState(): Promise<MigrationState | null> {
|
|
1198
|
+
return (await this.ctx.storage.get<MigrationState>(MIGRATION_STATE_KEY)) ?? null
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* Update the migration state in DO storage
|
|
1203
|
+
*/
|
|
1204
|
+
private async setMigrationState(state: MigrationState): Promise<void> {
|
|
1205
|
+
await this.ctx.storage.put(MIGRATION_STATE_KEY, state)
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Check if migrations need to run (for lazy migration strategy)
|
|
1210
|
+
*/
|
|
1211
|
+
async needsLazyMigration(): Promise<boolean> {
|
|
1212
|
+
const strategy = this.getMigrationStrategy()
|
|
1213
|
+
if (strategy !== 'on-demand') {
|
|
1214
|
+
return false
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
const migrations = this.config.migrations?.migrations
|
|
1218
|
+
if (!migrations || migrations.length === 0) {
|
|
1219
|
+
return false
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
if (this.migrated) {
|
|
1223
|
+
return false
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
const migrationState = await this.getMigrationState()
|
|
1227
|
+
|
|
1228
|
+
if (!migrationState) {
|
|
1229
|
+
return true
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
if (migrationState.status === 'completed') {
|
|
1233
|
+
const highestVersion = Math.max(...migrations.map((m) => m.version))
|
|
1234
|
+
return migrationState.version < highestVersion
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
return migrationState.status !== 'in-progress'
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
/**
|
|
1241
|
+
* Run lazy migrations (on-demand strategy)
|
|
1242
|
+
*/
|
|
1243
|
+
private async runLazyMigrations(): Promise<BatchMigrationResult | null> {
|
|
1244
|
+
if (this.migrated) {
|
|
1245
|
+
return null
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
const migrations = this.config.migrations?.migrations
|
|
1249
|
+
if (!migrations || migrations.length === 0) {
|
|
1250
|
+
this.migrated = true
|
|
1251
|
+
return null
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
await this.setMigrationState({
|
|
1255
|
+
status: 'in-progress',
|
|
1256
|
+
version: await this.getSchemaVersion(),
|
|
1257
|
+
lastAttemptAt: new Date().toISOString(),
|
|
1258
|
+
})
|
|
1259
|
+
|
|
1260
|
+
const startTime = performance.now()
|
|
1261
|
+
|
|
1262
|
+
try {
|
|
1263
|
+
const result = await this.runMigrations(migrations, this.config.migrations?.onProgress)
|
|
1264
|
+
|
|
1265
|
+
const durationMs = Math.round(performance.now() - startTime)
|
|
1266
|
+
|
|
1267
|
+
if (result.success) {
|
|
1268
|
+
this.migrated = true
|
|
1269
|
+
await this.setMigrationState({
|
|
1270
|
+
status: 'completed',
|
|
1271
|
+
version: result.toVersion,
|
|
1272
|
+
lastAttemptAt: new Date().toISOString(),
|
|
1273
|
+
durationMs,
|
|
1274
|
+
})
|
|
1275
|
+
} else {
|
|
1276
|
+
const failedMigration = result.results.find((r) => !r.success)
|
|
1277
|
+
await this.setMigrationState({
|
|
1278
|
+
status: 'failed',
|
|
1279
|
+
version: result.toVersion,
|
|
1280
|
+
lastAttemptAt: new Date().toISOString(),
|
|
1281
|
+
error: failedMigration?.error ?? 'Unknown error',
|
|
1282
|
+
durationMs,
|
|
1283
|
+
})
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
return result
|
|
1287
|
+
} catch (error) {
|
|
1288
|
+
const durationMs = Math.round(performance.now() - startTime)
|
|
1289
|
+
await this.setMigrationState({
|
|
1290
|
+
status: 'failed',
|
|
1291
|
+
version: await this.getSchemaVersion(),
|
|
1292
|
+
lastAttemptAt: new Date().toISOString(),
|
|
1293
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1294
|
+
durationMs,
|
|
1295
|
+
})
|
|
1296
|
+
throw error
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
/**
|
|
1301
|
+
* Ensure migrations have run (for on-demand strategy)
|
|
1302
|
+
*/
|
|
1303
|
+
async ensureMigratedForQuery(): Promise<BatchMigrationResult | null> {
|
|
1304
|
+
if (!(await this.needsLazyMigration())) {
|
|
1305
|
+
return null
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
if (this.migratePromise) {
|
|
1309
|
+
return this.migratePromise
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
this.migratePromise = this.runLazyMigrations()
|
|
1313
|
+
|
|
1314
|
+
try {
|
|
1315
|
+
return await this.migratePromise
|
|
1316
|
+
} finally {
|
|
1317
|
+
this.migratePromise = null
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// ============================================================
|
|
1322
|
+
// PGLite Initialization
|
|
1323
|
+
// ============================================================
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
* Get enabled plugins from configuration
|
|
1327
|
+
*/
|
|
1328
|
+
protected async getEnabledPluginExtensions(): Promise<Record<string, unknown>> {
|
|
1329
|
+
return this.pluginManager.loadEnabledExtensions()
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
/**
|
|
1333
|
+
* Get the PGLite manager (for testing)
|
|
1334
|
+
*/
|
|
1335
|
+
getPGLiteManager(): PGLiteManager {
|
|
1336
|
+
return this.pgliteManager
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
/**
|
|
1340
|
+
* Create a PGlite instance (overridable for testing)
|
|
1341
|
+
* When mocked in tests, this should return the mock PGlite instance
|
|
1342
|
+
*/
|
|
1343
|
+
protected async createPGliteInstance(): Promise<PGliteLike> {
|
|
1344
|
+
await this.pgliteManager.initialize()
|
|
1345
|
+
return this.pgliteManager.getInstance()
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
/**
|
|
1349
|
+
* Run auto-create SQL for plugins that have autoCreate enabled
|
|
1350
|
+
*/
|
|
1351
|
+
protected async runPluginAutoCreate(): Promise<void> {
|
|
1352
|
+
const pglite = this.pgliteManager.getInstanceOrNull()
|
|
1353
|
+
if (!pglite) return
|
|
1354
|
+
await this.pluginManager.runAutoCreate(pglite)
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
/**
|
|
1358
|
+
* Initialize PGlite and run auto-migrations if configured
|
|
1359
|
+
* Safe to call multiple times - concurrent calls return the same promise
|
|
1360
|
+
*/
|
|
1361
|
+
async initPGlite(): Promise<void> {
|
|
1362
|
+
if (this.isInitialized()) {
|
|
1363
|
+
return
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// Return existing promise if initialization is already in progress
|
|
1367
|
+
if (this.initPGlitePromise) {
|
|
1368
|
+
return this.initPGlitePromise
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
// Create and store the initialization promise
|
|
1372
|
+
this.initPGlitePromise = this.ctx.blockConcurrencyWhile(async () => {
|
|
1373
|
+
if (this.isInitialized()) {
|
|
1374
|
+
return
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
// Use createPGliteInstance which can be mocked in tests
|
|
1378
|
+
const pglite = await this.createPGliteInstance()
|
|
1379
|
+
// Inject the instance into the manager if it was created externally (e.g., by a mock)
|
|
1380
|
+
if (!this.pgliteManager.isInitialized()) {
|
|
1381
|
+
this.pgliteManager.injectInstance(pglite)
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
// Run auto-create for plugins
|
|
1385
|
+
await this.runPluginAutoCreate()
|
|
1386
|
+
|
|
1387
|
+
// Determine migration strategy
|
|
1388
|
+
const strategy = this.getMigrationStrategy()
|
|
1389
|
+
|
|
1390
|
+
// Only run migrations on init if strategy is 'on-create' (default)
|
|
1391
|
+
if (strategy === 'on-create') {
|
|
1392
|
+
const shouldAutoMigrate = this.config.migrations?.autoMigrate !== false
|
|
1393
|
+
if (shouldAutoMigrate && this.config.migrations?.migrations?.length) {
|
|
1394
|
+
const result = await this.ensureMigrated()
|
|
1395
|
+
if (result && !result.success) {
|
|
1396
|
+
console.error(
|
|
1397
|
+
`[PostgresDO] Auto-migration failed: ${result.results.find((r) => !r.success)?.error}`
|
|
1398
|
+
)
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
// Set PGlite reference on memory pressure manager for extension unloading
|
|
1404
|
+
const pgliteForMemory = this.pgliteManager.getInstanceOrNull()
|
|
1405
|
+
if (this.memoryPressureManager && pgliteForMemory) {
|
|
1406
|
+
this.memoryPressureManager.setPGlite(pgliteForMemory)
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
// Start memory monitoring if enabled (default: enabled)
|
|
1410
|
+
if (this.memoryPressureConfig.enabled !== false) {
|
|
1411
|
+
this.getMemoryPressureManager().startMonitoring()
|
|
1412
|
+
}
|
|
1413
|
+
})
|
|
1414
|
+
|
|
1415
|
+
await this.initPGlitePromise
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
// ============================================================
|
|
1419
|
+
// Query Execution
|
|
1420
|
+
// ============================================================
|
|
1421
|
+
|
|
1422
|
+
/**
|
|
1423
|
+
* Execute a single query
|
|
1424
|
+
*/
|
|
1425
|
+
async executeQuery<T extends QueryResultRow = QueryResultRow>(
|
|
1426
|
+
request: QueryRequest
|
|
1427
|
+
): Promise<QueryResponse<T>> {
|
|
1428
|
+
if (this.shutdownManager.getStatus() === 'shutdown') {
|
|
1429
|
+
throw new ShutdownError()
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
// Use injected query execution concern if available
|
|
1433
|
+
if (
|
|
1434
|
+
this.injectedQueryExecutionConcern &&
|
|
1435
|
+
typeof (
|
|
1436
|
+
this.injectedQueryExecutionConcern as {
|
|
1437
|
+
executeQuery?: (
|
|
1438
|
+
r: QueryRequest
|
|
1439
|
+
) => Promise<{
|
|
1440
|
+
rows: T[]
|
|
1441
|
+
fields: { name: string; dataTypeID: number }[]
|
|
1442
|
+
rowCount: number
|
|
1443
|
+
durationMs: number
|
|
1444
|
+
}>
|
|
1445
|
+
}
|
|
1446
|
+
).executeQuery === 'function'
|
|
1447
|
+
) {
|
|
1448
|
+
const result = await (
|
|
1449
|
+
this.injectedQueryExecutionConcern as {
|
|
1450
|
+
executeQuery: (
|
|
1451
|
+
r: QueryRequest
|
|
1452
|
+
) => Promise<{
|
|
1453
|
+
rows: T[]
|
|
1454
|
+
fields: { name: string; dataTypeID: number }[]
|
|
1455
|
+
rowCount: number
|
|
1456
|
+
durationMs: number
|
|
1457
|
+
}>
|
|
1458
|
+
}
|
|
1459
|
+
).executeQuery(request)
|
|
1460
|
+
return {
|
|
1461
|
+
rows: result.rows,
|
|
1462
|
+
fields: result.fields as QueryField[],
|
|
1463
|
+
rowCount: result.rowCount,
|
|
1464
|
+
durationMs: result.durationMs,
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
if (!this.isInitialized()) {
|
|
1469
|
+
await this.initPGlite()
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
await this.ensureMigratedForQuery()
|
|
1473
|
+
|
|
1474
|
+
const queryId = this.shutdownManager.trackQuery(request.sql)
|
|
1475
|
+
const startTime = performance.now()
|
|
1476
|
+
|
|
1477
|
+
try {
|
|
1478
|
+
let sql = request.sql
|
|
1479
|
+
if (request.preserveCase ?? this.config.preserveCase) {
|
|
1480
|
+
sql = preserveCase(sql)
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
const pglite = this.pgliteManager.getInstance()
|
|
1484
|
+
const result = await pglite.query<T>(sql, request.params)
|
|
1485
|
+
const durationMs = performance.now() - startTime
|
|
1486
|
+
|
|
1487
|
+
this.captureWAL(sql, {
|
|
1488
|
+
rows: result.rows as Record<string, unknown>[],
|
|
1489
|
+
...(result.affectedRows !== undefined && { affectedRows: result.affectedRows }),
|
|
1490
|
+
})
|
|
1491
|
+
|
|
1492
|
+
this.statsManager.recordQuery(durationMs, true)
|
|
1493
|
+
|
|
1494
|
+
return {
|
|
1495
|
+
rows: result.rows,
|
|
1496
|
+
fields: result.fields as QueryField[],
|
|
1497
|
+
rowCount: result.affectedRows ?? result.rows.length,
|
|
1498
|
+
durationMs,
|
|
1499
|
+
}
|
|
1500
|
+
} catch (error) {
|
|
1501
|
+
const durationMs = performance.now() - startTime
|
|
1502
|
+
this.statsManager.recordQuery(durationMs, false)
|
|
1503
|
+
throw error
|
|
1504
|
+
} finally {
|
|
1505
|
+
this.shutdownManager.untrackQuery(queryId)
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
/**
|
|
1510
|
+
* Execute a batch of queries
|
|
1511
|
+
*/
|
|
1512
|
+
async executeBatch(request: BatchRequest): Promise<BatchResponse> {
|
|
1513
|
+
if (!this.isInitialized()) {
|
|
1514
|
+
await this.initPGlite()
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
const startTime = performance.now()
|
|
1518
|
+
const results: QueryResponse[] = []
|
|
1519
|
+
const pglite = this.pgliteManager.getInstance()
|
|
1520
|
+
|
|
1521
|
+
if (request.transaction) {
|
|
1522
|
+
await pglite.query('BEGIN')
|
|
1523
|
+
try {
|
|
1524
|
+
for (const query of request.queries) {
|
|
1525
|
+
const result = await this.executeQuery(query)
|
|
1526
|
+
results.push(result)
|
|
1527
|
+
}
|
|
1528
|
+
await pglite.query('COMMIT')
|
|
1529
|
+
} catch (error) {
|
|
1530
|
+
await pglite.query('ROLLBACK')
|
|
1531
|
+
throw error
|
|
1532
|
+
}
|
|
1533
|
+
} else {
|
|
1534
|
+
for (const query of request.queries) {
|
|
1535
|
+
const result = await this.executeQuery(query)
|
|
1536
|
+
results.push(result)
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
const durationMs = performance.now() - startTime
|
|
1541
|
+
|
|
1542
|
+
return {
|
|
1543
|
+
results,
|
|
1544
|
+
durationMs,
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
/**
|
|
1549
|
+
* Handle incoming fetch requests
|
|
1550
|
+
*/
|
|
1551
|
+
override async fetch(request: Request): Promise<Response> {
|
|
1552
|
+
const url = new URL(request.url)
|
|
1553
|
+
|
|
1554
|
+
if (url.pathname === '/ping') {
|
|
1555
|
+
return new Response('pong', { status: 200 })
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
return new Response('Not Found', { status: 404 })
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
// ============================================================
|
|
1562
|
+
// RPC Methods
|
|
1563
|
+
// ============================================================
|
|
1564
|
+
|
|
1565
|
+
/**
|
|
1566
|
+
* RPC: Execute a SQL query
|
|
1567
|
+
*/
|
|
1568
|
+
async rpcQuery<T extends QueryResultRow = QueryResultRow>(
|
|
1569
|
+
sql: string,
|
|
1570
|
+
params?: unknown[]
|
|
1571
|
+
): Promise<RpcQueryResult<T>> {
|
|
1572
|
+
if (!this.isInitialized()) {
|
|
1573
|
+
await this.initPGlite()
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
await this.ensureMigratedForQuery()
|
|
1577
|
+
|
|
1578
|
+
const startTime = performance.now()
|
|
1579
|
+
|
|
1580
|
+
let finalSql = sql
|
|
1581
|
+
if (this.config.preserveCase) {
|
|
1582
|
+
finalSql = preserveCase(sql)
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
const pglite = this.pgliteManager.getInstance()
|
|
1586
|
+
const result = await pglite.query<T>(finalSql, params)
|
|
1587
|
+
const durationMs = performance.now() - startTime
|
|
1588
|
+
|
|
1589
|
+
this.statsManager.recordQuery(durationMs, true)
|
|
1590
|
+
|
|
1591
|
+
return {
|
|
1592
|
+
rows: result.rows,
|
|
1593
|
+
fields: result.fields as QueryField[],
|
|
1594
|
+
rowCount: result.affectedRows ?? result.rows.length,
|
|
1595
|
+
durationMs,
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
/**
|
|
1600
|
+
* RPC: Execute a SQL query and return only the first row
|
|
1601
|
+
*/
|
|
1602
|
+
async rpcQueryOne<T extends QueryResultRow = QueryResultRow>(
|
|
1603
|
+
sql: string,
|
|
1604
|
+
params?: unknown[]
|
|
1605
|
+
): Promise<T | null> {
|
|
1606
|
+
const result = await this.rpcQuery<T>(sql, params)
|
|
1607
|
+
return result.rows[0] ?? null
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
/**
|
|
1611
|
+
* RPC: Execute a query and return a scalar value
|
|
1612
|
+
*/
|
|
1613
|
+
async rpcQueryScalar<T = unknown>(sql: string, params?: unknown[]): Promise<T | null> {
|
|
1614
|
+
const result = await this.rpcQuery(sql, params)
|
|
1615
|
+
const row = result.rows[0]
|
|
1616
|
+
if (!row) return null
|
|
1617
|
+
|
|
1618
|
+
const firstKey = Object.keys(row)[0]
|
|
1619
|
+
return (firstKey ? row[firstKey] : null) as T
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
/**
|
|
1623
|
+
* RPC: Execute a batch of queries
|
|
1624
|
+
*/
|
|
1625
|
+
async rpcBatch(queries: RpcBatchQuery[]): Promise<RpcBatchResult> {
|
|
1626
|
+
if (!this.isInitialized()) {
|
|
1627
|
+
await this.initPGlite()
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
const startTime = performance.now()
|
|
1631
|
+
const results: RpcQueryResult[] = []
|
|
1632
|
+
|
|
1633
|
+
for (const query of queries) {
|
|
1634
|
+
const result = await this.rpcQuery(query.sql, query.params)
|
|
1635
|
+
results.push(result)
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
return {
|
|
1639
|
+
results,
|
|
1640
|
+
durationMs: performance.now() - startTime,
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
/**
|
|
1645
|
+
* RPC: Execute a batch of queries within a transaction
|
|
1646
|
+
*/
|
|
1647
|
+
async rpcBatchTransaction(queries: RpcBatchQuery[]): Promise<RpcBatchResult> {
|
|
1648
|
+
if (!this.isInitialized()) {
|
|
1649
|
+
await this.initPGlite()
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
const startTime = performance.now()
|
|
1653
|
+
const results: RpcQueryResult[] = []
|
|
1654
|
+
const pglite = this.pgliteManager.getInstance()
|
|
1655
|
+
|
|
1656
|
+
await pglite.query('BEGIN')
|
|
1657
|
+
|
|
1658
|
+
try {
|
|
1659
|
+
for (const query of queries) {
|
|
1660
|
+
const result = await this.rpcQuery(query.sql, query.params)
|
|
1661
|
+
results.push(result)
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
await pglite.query('COMMIT')
|
|
1665
|
+
} catch (error) {
|
|
1666
|
+
await pglite.query('ROLLBACK')
|
|
1667
|
+
throw error
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
return {
|
|
1671
|
+
results,
|
|
1672
|
+
durationMs: performance.now() - startTime,
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
/**
|
|
1677
|
+
* RPC: Start a transaction and return a TransactionRpcApi
|
|
1678
|
+
*/
|
|
1679
|
+
async rpcTransaction(options?: RpcTransactionOptions): Promise<TransactionRpcApi> {
|
|
1680
|
+
if (!this.isInitialized()) {
|
|
1681
|
+
await this.initPGlite()
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
let beginSql = 'BEGIN'
|
|
1685
|
+
|
|
1686
|
+
if (options?.isolationLevel) {
|
|
1687
|
+
beginSql += ` ISOLATION LEVEL ${options.isolationLevel}`
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
if (options?.readOnly) {
|
|
1691
|
+
beginSql += ' READ ONLY'
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
const pglite = this.pgliteManager.getInstance()
|
|
1695
|
+
await pglite.query(beginSql)
|
|
1696
|
+
|
|
1697
|
+
return new TransactionRpcApi(pglite)
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
/**
|
|
1701
|
+
* RPC: Execute a SQL statement that doesn't return rows
|
|
1702
|
+
*/
|
|
1703
|
+
async rpcExecute(
|
|
1704
|
+
sql: string,
|
|
1705
|
+
params?: unknown[]
|
|
1706
|
+
): Promise<{ rowCount: number; durationMs: number }> {
|
|
1707
|
+
const result = await this.rpcQuery(sql, params)
|
|
1708
|
+
return {
|
|
1709
|
+
rowCount: result.rowCount,
|
|
1710
|
+
durationMs: result.durationMs,
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
/**
|
|
1715
|
+
* RPC: Get the PostgresRpcApi instance
|
|
1716
|
+
*/
|
|
1717
|
+
async getRpcApi(): Promise<PostgresRpcApi> {
|
|
1718
|
+
if (!this.isInitialized()) {
|
|
1719
|
+
await this.initPGlite()
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
return new PostgresRpcApi(this.pgliteManager.getInstance(), this.config.database)
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
/**
|
|
1726
|
+
* RPC: Health check
|
|
1727
|
+
*/
|
|
1728
|
+
async rpcPing(): Promise<{ ok: true; durationMs: number }> {
|
|
1729
|
+
if (!this.isInitialized()) {
|
|
1730
|
+
await this.initPGlite()
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
const startTime = performance.now()
|
|
1734
|
+
const pglite = this.pgliteManager.getInstance()
|
|
1735
|
+
await pglite.query('SELECT 1')
|
|
1736
|
+
|
|
1737
|
+
return {
|
|
1738
|
+
ok: true,
|
|
1739
|
+
durationMs: performance.now() - startTime,
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
/**
|
|
1744
|
+
* RPC: Get database version
|
|
1745
|
+
*/
|
|
1746
|
+
async rpcVersion(): Promise<string> {
|
|
1747
|
+
const result = await this.rpcQueryScalar<string>('SELECT version()')
|
|
1748
|
+
return result ?? 'unknown'
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
/**
|
|
1752
|
+
* RPC: List all tables in the public schema
|
|
1753
|
+
*/
|
|
1754
|
+
async rpcListTables(): Promise<string[]> {
|
|
1755
|
+
const result = await this.rpcQuery<{ tablename: string }>(
|
|
1756
|
+
`SELECT tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename`
|
|
1757
|
+
)
|
|
1758
|
+
return result.rows.map((r) => r.tablename)
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
/**
|
|
1762
|
+
* RPC: Get table schema information
|
|
1763
|
+
*/
|
|
1764
|
+
async rpcDescribeTable(tableName: string): Promise<
|
|
1765
|
+
Array<{
|
|
1766
|
+
column_name: string
|
|
1767
|
+
data_type: string
|
|
1768
|
+
is_nullable: boolean
|
|
1769
|
+
column_default: string | null
|
|
1770
|
+
}>
|
|
1771
|
+
> {
|
|
1772
|
+
const result = await this.rpcQuery<{
|
|
1773
|
+
column_name: string
|
|
1774
|
+
data_type: string
|
|
1775
|
+
is_nullable: string
|
|
1776
|
+
column_default: string | null
|
|
1777
|
+
}>(
|
|
1778
|
+
`SELECT column_name, data_type, is_nullable, column_default
|
|
1779
|
+
FROM information_schema.columns
|
|
1780
|
+
WHERE table_schema = 'public' AND table_name = $1
|
|
1781
|
+
ORDER BY ordinal_position`,
|
|
1782
|
+
[tableName]
|
|
1783
|
+
)
|
|
1784
|
+
|
|
1785
|
+
return result.rows.map((r) => ({
|
|
1786
|
+
column_name: r.column_name,
|
|
1787
|
+
data_type: r.data_type,
|
|
1788
|
+
is_nullable: r.is_nullable === 'YES',
|
|
1789
|
+
column_default: r.column_default,
|
|
1790
|
+
}))
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
/**
|
|
1794
|
+
* RPC: Get database statistics
|
|
1795
|
+
*/
|
|
1796
|
+
async rpcGetStats(): Promise<{
|
|
1797
|
+
queryCount: number
|
|
1798
|
+
totalDurationMs: number
|
|
1799
|
+
avgDurationMs: number
|
|
1800
|
+
lastQueryAt: Date | null
|
|
1801
|
+
uptime: number
|
|
1802
|
+
shutdownStatus: ShutdownStatus
|
|
1803
|
+
}> {
|
|
1804
|
+
const stats = this.statsManager.getStats()
|
|
1805
|
+
return {
|
|
1806
|
+
queryCount: stats.queryCount,
|
|
1807
|
+
totalDurationMs: stats.totalDurationMs,
|
|
1808
|
+
avgDurationMs: stats.avgDurationMs,
|
|
1809
|
+
lastQueryAt: stats.lastQueryAt ?? null,
|
|
1810
|
+
uptime: this.getUptime(),
|
|
1811
|
+
shutdownStatus: this.shutdownManager.getStatus(),
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
// ============================================================
|
|
1817
|
+
// Factory Functions
|
|
1818
|
+
// ============================================================
|
|
1819
|
+
|
|
1820
|
+
/**
|
|
1821
|
+
* Factory function to create PostgresDO with custom configuration
|
|
1822
|
+
*/
|
|
1823
|
+
export function createPostgresDO(
|
|
1824
|
+
config: PostgresConfig,
|
|
1825
|
+
authConfig?: PostgresDOAuthConfig,
|
|
1826
|
+
walConfig?: WALConfig,
|
|
1827
|
+
memoryPressureConfig?: MemoryPressureConfig
|
|
1828
|
+
): typeof PostgresDO {
|
|
1829
|
+
return class extends PostgresDO {
|
|
1830
|
+
constructor(state: DurableObjectState, env: Env) {
|
|
1831
|
+
super(state, env, config, authConfig, walConfig, memoryPressureConfig)
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
/**
|
|
1837
|
+
* Factory function to create an authenticated PostgresDO for user-scoped databases
|
|
1838
|
+
*/
|
|
1839
|
+
export function createAuthenticatedPostgresDO(
|
|
1840
|
+
config: PostgresConfig,
|
|
1841
|
+
authConfig: Omit<PostgresDOAuthConfig, 'enabled'> = {},
|
|
1842
|
+
walConfig?: WALConfig,
|
|
1843
|
+
memoryPressureConfig?: MemoryPressureConfig
|
|
1844
|
+
): typeof PostgresDO {
|
|
1845
|
+
return createPostgresDO(
|
|
1846
|
+
config,
|
|
1847
|
+
{
|
|
1848
|
+
...authConfig,
|
|
1849
|
+
enabled: true,
|
|
1850
|
+
},
|
|
1851
|
+
walConfig,
|
|
1852
|
+
memoryPressureConfig
|
|
1853
|
+
)
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
/**
|
|
1857
|
+
* Factory function to create PostgresDO with WAL capture enabled
|
|
1858
|
+
*/
|
|
1859
|
+
export function createPostgresDOWithWAL(
|
|
1860
|
+
config: PostgresConfig,
|
|
1861
|
+
walConfig: WALConfig = { enabled: true },
|
|
1862
|
+
authConfig?: PostgresDOAuthConfig,
|
|
1863
|
+
memoryPressureConfig?: MemoryPressureConfig
|
|
1864
|
+
): typeof PostgresDO {
|
|
1865
|
+
return createPostgresDO(config, authConfig, { enabled: true, ...walConfig }, memoryPressureConfig)
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
/**
|
|
1869
|
+
* Factory function to create PostgresDO with memory pressure protection enabled
|
|
1870
|
+
*/
|
|
1871
|
+
export function createPostgresDOWithMemoryProtection(
|
|
1872
|
+
config: PostgresConfig,
|
|
1873
|
+
memoryPressureConfig: MemoryPressureConfig = { enabled: true, autoUnloadExtensions: true },
|
|
1874
|
+
authConfig?: PostgresDOAuthConfig,
|
|
1875
|
+
walConfig?: WALConfig
|
|
1876
|
+
): typeof PostgresDO {
|
|
1877
|
+
return createPostgresDO(config, authConfig, walConfig, { enabled: true, ...memoryPressureConfig })
|
|
1878
|
+
}
|