@dotdo/postgres 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +868 -0
- package/dist/cdc/change-stream.d.ts +44 -0
- package/dist/cdc/change-stream.d.ts.map +1 -0
- package/dist/cdc/change-stream.js +95 -0
- package/dist/cdc/change-stream.js.map +1 -0
- package/dist/cdc/filter.d.ts +58 -0
- package/dist/cdc/filter.d.ts.map +1 -0
- package/dist/cdc/filter.js +520 -0
- package/dist/cdc/filter.js.map +1 -0
- package/dist/cdc/index.d.ts +47 -0
- package/dist/cdc/index.d.ts.map +1 -0
- package/dist/cdc/index.js +50 -0
- package/dist/cdc/index.js.map +1 -0
- package/dist/cdc/resume-token.d.ts +60 -0
- package/dist/cdc/resume-token.d.ts.map +1 -0
- package/dist/cdc/resume-token.js +228 -0
- package/dist/cdc/resume-token.js.map +1 -0
- package/dist/cdc/transport/index.d.ts +7 -0
- package/dist/cdc/transport/index.d.ts.map +1 -0
- package/dist/cdc/transport/index.js +7 -0
- package/dist/cdc/transport/index.js.map +1 -0
- package/dist/cdc/transport/sse.d.ts +120 -0
- package/dist/cdc/transport/sse.d.ts.map +1 -0
- package/dist/cdc/transport/sse.js +590 -0
- package/dist/cdc/transport/sse.js.map +1 -0
- package/dist/cdc/transport/websocket.d.ts +130 -0
- package/dist/cdc/transport/websocket.d.ts.map +1 -0
- package/dist/cdc/transport/websocket.js +688 -0
- package/dist/cdc/transport/websocket.js.map +1 -0
- package/dist/cdc/types.d.ts +306 -0
- package/dist/cdc/types.d.ts.map +1 -0
- package/dist/cdc/types.js +8 -0
- package/dist/cdc/types.js.map +1 -0
- package/dist/config/index.d.ts +25 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +25 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/memory.d.ts +139 -0
- package/dist/config/memory.d.ts.map +1 -0
- package/dist/config/memory.js +157 -0
- package/dist/config/memory.js.map +1 -0
- package/dist/config/storage.d.ts +157 -0
- package/dist/config/storage.d.ts.map +1 -0
- package/dist/config/storage.js +178 -0
- package/dist/config/storage.js.map +1 -0
- package/dist/config/streaming.d.ts +117 -0
- package/dist/config/streaming.d.ts.map +1 -0
- package/dist/config/streaming.js +132 -0
- package/dist/config/streaming.js.map +1 -0
- package/dist/config/timeouts.d.ts +168 -0
- package/dist/config/timeouts.d.ts.map +1 -0
- package/dist/config/timeouts.js +192 -0
- package/dist/config/timeouts.js.map +1 -0
- package/dist/extensions/config.d.ts +89 -0
- package/dist/extensions/config.d.ts.map +1 -0
- package/dist/extensions/config.js +216 -0
- package/dist/extensions/config.js.map +1 -0
- package/dist/extensions/geo.d.ts +452 -0
- package/dist/extensions/geo.d.ts.map +1 -0
- package/dist/extensions/geo.js +583 -0
- package/dist/extensions/geo.js.map +1 -0
- package/dist/extensions/index.d.ts +167 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +99 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +226 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +456 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/pgmq-lite.d.ts +330 -0
- package/dist/extensions/pgmq-lite.d.ts.map +1 -0
- package/dist/extensions/pgmq-lite.js +648 -0
- package/dist/extensions/pgmq-lite.js.map +1 -0
- package/dist/extensions/plugins.d.ts +260 -0
- package/dist/extensions/plugins.d.ts.map +1 -0
- package/dist/extensions/plugins.js +535 -0
- package/dist/extensions/plugins.js.map +1 -0
- package/dist/extensions/registry.d.ts +93 -0
- package/dist/extensions/registry.d.ts.map +1 -0
- package/dist/extensions/registry.js +182 -0
- package/dist/extensions/registry.js.map +1 -0
- package/dist/extensions/vector.d.ts +106 -0
- package/dist/extensions/vector.d.ts.map +1 -0
- package/dist/extensions/vector.js +129 -0
- package/dist/extensions/vector.js.map +1 -0
- package/dist/iceberg/analytics.d.ts +279 -0
- package/dist/iceberg/analytics.d.ts.map +1 -0
- package/dist/iceberg/analytics.js +448 -0
- package/dist/iceberg/analytics.js.map +1 -0
- package/dist/iceberg/catalog-api.d.ts +39 -0
- package/dist/iceberg/catalog-api.d.ts.map +1 -0
- package/dist/iceberg/catalog-api.js +388 -0
- package/dist/iceberg/catalog-api.js.map +1 -0
- package/dist/iceberg/catalog.d.ts +401 -0
- package/dist/iceberg/catalog.d.ts.map +1 -0
- package/dist/iceberg/catalog.js +677 -0
- package/dist/iceberg/catalog.js.map +1 -0
- package/dist/iceberg/duckdb-wasm.d.ts +447 -0
- package/dist/iceberg/duckdb-wasm.d.ts.map +1 -0
- package/dist/iceberg/duckdb-wasm.js +600 -0
- package/dist/iceberg/duckdb-wasm.js.map +1 -0
- package/dist/iceberg/index.d.ts +92 -0
- package/dist/iceberg/index.d.ts.map +1 -0
- package/dist/iceberg/index.js +119 -0
- package/dist/iceberg/index.js.map +1 -0
- package/dist/iceberg/metadata.d.ts +214 -0
- package/dist/iceberg/metadata.d.ts.map +1 -0
- package/dist/iceberg/metadata.js +535 -0
- package/dist/iceberg/metadata.js.map +1 -0
- package/dist/iceberg/optimizer.d.ts +296 -0
- package/dist/iceberg/optimizer.d.ts.map +1 -0
- package/dist/iceberg/optimizer.js +889 -0
- package/dist/iceberg/optimizer.js.map +1 -0
- package/dist/iceberg/parquet.d.ts +447 -0
- package/dist/iceberg/parquet.d.ts.map +1 -0
- package/dist/iceberg/parquet.js +1225 -0
- package/dist/iceberg/parquet.js.map +1 -0
- package/dist/iceberg/r2-organization.d.ts +422 -0
- package/dist/iceberg/r2-organization.d.ts.map +1 -0
- package/dist/iceberg/r2-organization.js +672 -0
- package/dist/iceberg/r2-organization.js.map +1 -0
- package/dist/iceberg/scheduler-do-example.d.ts +158 -0
- package/dist/iceberg/scheduler-do-example.d.ts.map +1 -0
- package/dist/iceberg/scheduler-do-example.js +261 -0
- package/dist/iceberg/scheduler-do-example.js.map +1 -0
- package/dist/iceberg/scheduler.d.ts +434 -0
- package/dist/iceberg/scheduler.d.ts.map +1 -0
- package/dist/iceberg/scheduler.js +818 -0
- package/dist/iceberg/scheduler.js.map +1 -0
- package/dist/iceberg/schema.d.ts +149 -0
- package/dist/iceberg/schema.d.ts.map +1 -0
- package/dist/iceberg/schema.js +525 -0
- package/dist/iceberg/schema.js.map +1 -0
- package/dist/iceberg/snapshot-manager.d.ts +406 -0
- package/dist/iceberg/snapshot-manager.d.ts.map +1 -0
- package/dist/iceberg/snapshot-manager.js +934 -0
- package/dist/iceberg/snapshot-manager.js.map +1 -0
- package/dist/iceberg/sql-router.d.ts +194 -0
- package/dist/iceberg/sql-router.d.ts.map +1 -0
- package/dist/iceberg/sql-router.js +180 -0
- package/dist/iceberg/sql-router.js.map +1 -0
- package/dist/iceberg/test-fixtures.d.ts +151 -0
- package/dist/iceberg/test-fixtures.d.ts.map +1 -0
- package/dist/iceberg/test-fixtures.js +446 -0
- package/dist/iceberg/test-fixtures.js.map +1 -0
- package/dist/iceberg/time-travel-api.d.ts +102 -0
- package/dist/iceberg/time-travel-api.d.ts.map +1 -0
- package/dist/iceberg/time-travel-api.js +437 -0
- package/dist/iceberg/time-travel-api.js.map +1 -0
- package/dist/iceberg/time-travel.d.ts +293 -0
- package/dist/iceberg/time-travel.d.ts.map +1 -0
- package/dist/iceberg/time-travel.js +689 -0
- package/dist/iceberg/time-travel.js.map +1 -0
- package/dist/iceberg/transformer.d.ts +356 -0
- package/dist/iceberg/transformer.d.ts.map +1 -0
- package/dist/iceberg/transformer.js +770 -0
- package/dist/iceberg/transformer.js.map +1 -0
- package/dist/iceberg/types.d.ts +318 -0
- package/dist/iceberg/types.d.ts.map +1 -0
- package/dist/iceberg/types.js +9 -0
- package/dist/iceberg/types.js.map +1 -0
- package/dist/iceberg/writer.d.ts +144 -0
- package/dist/iceberg/writer.d.ts.map +1 -0
- package/dist/iceberg/writer.js +452 -0
- package/dist/iceberg/writer.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/lineage/index.d.ts +11 -0
- package/dist/lineage/index.d.ts.map +1 -0
- package/dist/lineage/index.js +11 -0
- package/dist/lineage/index.js.map +1 -0
- package/dist/lineage/integration.d.ts +134 -0
- package/dist/lineage/integration.d.ts.map +1 -0
- package/dist/lineage/integration.js +258 -0
- package/dist/lineage/integration.js.map +1 -0
- package/dist/lineage/tracker.d.ts +189 -0
- package/dist/lineage/tracker.d.ts.map +1 -0
- package/dist/lineage/tracker.js +1352 -0
- package/dist/lineage/tracker.js.map +1 -0
- package/dist/lineage/types.d.ts +318 -0
- package/dist/lineage/types.d.ts.map +1 -0
- package/dist/lineage/types.js +9 -0
- package/dist/lineage/types.js.map +1 -0
- package/dist/middleware/index.d.ts +11 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +16 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +397 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +507 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/migration-tooling/external-migration.d.ts +601 -0
- package/dist/migration-tooling/external-migration.d.ts.map +1 -0
- package/dist/migration-tooling/external-migration.js +1612 -0
- package/dist/migration-tooling/external-migration.js.map +1 -0
- package/dist/migration-tooling/index.d.ts +19 -0
- package/dist/migration-tooling/index.d.ts.map +1 -0
- package/dist/migration-tooling/index.js +19 -0
- package/dist/migration-tooling/index.js.map +1 -0
- package/dist/migrations/auto-migrator.d.ts +289 -0
- package/dist/migrations/auto-migrator.d.ts.map +1 -0
- package/dist/migrations/auto-migrator.js +396 -0
- package/dist/migrations/auto-migrator.js.map +1 -0
- package/dist/migrations/bulk-orchestrator.d.ts +403 -0
- package/dist/migrations/bulk-orchestrator.d.ts.map +1 -0
- package/dist/migrations/bulk-orchestrator.js +646 -0
- package/dist/migrations/bulk-orchestrator.js.map +1 -0
- package/dist/migrations/compatibility.d.ts +216 -0
- package/dist/migrations/compatibility.d.ts.map +1 -0
- package/dist/migrations/compatibility.js +651 -0
- package/dist/migrations/compatibility.js.map +1 -0
- package/dist/migrations/do-migrations.d.ts +101 -0
- package/dist/migrations/do-migrations.d.ts.map +1 -0
- package/dist/migrations/do-migrations.js +1060 -0
- package/dist/migrations/do-migrations.js.map +1 -0
- package/dist/migrations/do-migrations.types.d.ts +550 -0
- package/dist/migrations/do-migrations.types.d.ts.map +1 -0
- package/dist/migrations/do-migrations.types.js +15 -0
- package/dist/migrations/do-migrations.types.js.map +1 -0
- package/dist/migrations/drizzle-compat.d.ts +163 -0
- package/dist/migrations/drizzle-compat.d.ts.map +1 -0
- package/dist/migrations/drizzle-compat.js +273 -0
- package/dist/migrations/drizzle-compat.js.map +1 -0
- package/dist/migrations/index.d.ts +109 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +127 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/migration-api.d.ts +161 -0
- package/dist/migrations/migration-api.d.ts.map +1 -0
- package/dist/migrations/migration-api.js +499 -0
- package/dist/migrations/migration-api.js.map +1 -0
- package/dist/migrations/progress-tracker-do.d.ts +195 -0
- package/dist/migrations/progress-tracker-do.d.ts.map +1 -0
- package/dist/migrations/progress-tracker-do.js +339 -0
- package/dist/migrations/progress-tracker-do.js.map +1 -0
- package/dist/migrations/progress-tracker-kv.d.ts +103 -0
- package/dist/migrations/progress-tracker-kv.d.ts.map +1 -0
- package/dist/migrations/progress-tracker-kv.js +231 -0
- package/dist/migrations/progress-tracker-kv.js.map +1 -0
- package/dist/migrations/progress-tracker.d.ts +320 -0
- package/dist/migrations/progress-tracker.d.ts.map +1 -0
- package/dist/migrations/progress-tracker.js +443 -0
- package/dist/migrations/progress-tracker.js.map +1 -0
- package/dist/migrations/registry.d.ts +231 -0
- package/dist/migrations/registry.d.ts.map +1 -0
- package/dist/migrations/registry.js +376 -0
- package/dist/migrations/registry.js.map +1 -0
- package/dist/migrations/runner.d.ts +197 -0
- package/dist/migrations/runner.d.ts.map +1 -0
- package/dist/migrations/runner.js +1167 -0
- package/dist/migrations/runner.js.map +1 -0
- package/dist/migrations/schema-generator.d.ts +111 -0
- package/dist/migrations/schema-generator.d.ts.map +1 -0
- package/dist/migrations/schema-generator.js +335 -0
- package/dist/migrations/schema-generator.js.map +1 -0
- package/dist/migrations/testing.d.ts +321 -0
- package/dist/migrations/testing.d.ts.map +1 -0
- package/dist/migrations/testing.js +645 -0
- package/dist/migrations/testing.js.map +1 -0
- package/dist/migrations/types.d.ts +503 -0
- package/dist/migrations/types.d.ts.map +1 -0
- package/dist/migrations/types.js +11 -0
- package/dist/migrations/types.js.map +1 -0
- package/dist/migrations/validator.d.ts +215 -0
- package/dist/migrations/validator.d.ts.map +1 -0
- package/dist/migrations/validator.js +494 -0
- package/dist/migrations/validator.js.map +1 -0
- package/dist/observability/alerting.d.ts +116 -0
- package/dist/observability/alerting.d.ts.map +1 -0
- package/dist/observability/alerting.js +353 -0
- package/dist/observability/alerting.js.map +1 -0
- package/dist/observability/analytics-engine.d.ts +357 -0
- package/dist/observability/analytics-engine.d.ts.map +1 -0
- package/dist/observability/analytics-engine.js +430 -0
- package/dist/observability/analytics-engine.js.map +1 -0
- package/dist/observability/cost-metrics.d.ts +269 -0
- package/dist/observability/cost-metrics.d.ts.map +1 -0
- package/dist/observability/cost-metrics.js +560 -0
- package/dist/observability/cost-metrics.js.map +1 -0
- package/dist/observability/cross-do-tracing.d.ts +305 -0
- package/dist/observability/cross-do-tracing.d.ts.map +1 -0
- package/dist/observability/cross-do-tracing.js +431 -0
- package/dist/observability/cross-do-tracing.js.map +1 -0
- package/dist/observability/error-rate-collector.d.ts +163 -0
- package/dist/observability/error-rate-collector.d.ts.map +1 -0
- package/dist/observability/error-rate-collector.js +306 -0
- package/dist/observability/error-rate-collector.js.map +1 -0
- package/dist/observability/exporters.d.ts +231 -0
- package/dist/observability/exporters.d.ts.map +1 -0
- package/dist/observability/exporters.js +479 -0
- package/dist/observability/exporters.js.map +1 -0
- package/dist/observability/health-check.d.ts +106 -0
- package/dist/observability/health-check.d.ts.map +1 -0
- package/dist/observability/health-check.js +243 -0
- package/dist/observability/health-check.js.map +1 -0
- package/dist/observability/index.d.ts +297 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +455 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/instrumentation.d.ts +222 -0
- package/dist/observability/instrumentation.d.ts.map +1 -0
- package/dist/observability/instrumentation.js +532 -0
- package/dist/observability/instrumentation.js.map +1 -0
- package/dist/observability/memory-metrics.d.ts +227 -0
- package/dist/observability/memory-metrics.d.ts.map +1 -0
- package/dist/observability/memory-metrics.js +688 -0
- package/dist/observability/memory-metrics.js.map +1 -0
- package/dist/observability/metrics-endpoint.d.ts +91 -0
- package/dist/observability/metrics-endpoint.d.ts.map +1 -0
- package/dist/observability/metrics-endpoint.js +246 -0
- package/dist/observability/metrics-endpoint.js.map +1 -0
- package/dist/observability/metrics.d.ts +88 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +253 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/observability-features.d.ts +488 -0
- package/dist/observability/observability-features.d.ts.map +1 -0
- package/dist/observability/observability-features.js +773 -0
- package/dist/observability/observability-features.js.map +1 -0
- package/dist/observability/prometheus.d.ts +39 -0
- package/dist/observability/prometheus.d.ts.map +1 -0
- package/dist/observability/prometheus.js +120 -0
- package/dist/observability/prometheus.js.map +1 -0
- package/dist/observability/propagation.d.ts +126 -0
- package/dist/observability/propagation.d.ts.map +1 -0
- package/dist/observability/propagation.js +234 -0
- package/dist/observability/propagation.js.map +1 -0
- package/dist/observability/query-latency.d.ts +243 -0
- package/dist/observability/query-latency.d.ts.map +1 -0
- package/dist/observability/query-latency.js +292 -0
- package/dist/observability/query-latency.js.map +1 -0
- package/dist/observability/query-performance.d.ts +169 -0
- package/dist/observability/query-performance.d.ts.map +1 -0
- package/dist/observability/query-performance.js +290 -0
- package/dist/observability/query-performance.js.map +1 -0
- package/dist/observability/storage-tier-metrics.d.ts +174 -0
- package/dist/observability/storage-tier-metrics.d.ts.map +1 -0
- package/dist/observability/storage-tier-metrics.js +306 -0
- package/dist/observability/storage-tier-metrics.js.map +1 -0
- package/dist/observability/tier-cost-optimizer.d.ts +155 -0
- package/dist/observability/tier-cost-optimizer.d.ts.map +1 -0
- package/dist/observability/tier-cost-optimizer.js +536 -0
- package/dist/observability/tier-cost-optimizer.js.map +1 -0
- package/dist/observability/tracer.d.ts +149 -0
- package/dist/observability/tracer.d.ts.map +1 -0
- package/dist/observability/tracer.js +435 -0
- package/dist/observability/tracer.js.map +1 -0
- package/dist/observability/types.d.ts +402 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/observability/types.js +103 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/pglite/workers-pglite.d.ts +138 -0
- package/dist/pglite/workers-pglite.d.ts.map +1 -0
- package/dist/pglite/workers-pglite.js +143 -0
- package/dist/pglite/workers-pglite.js.map +1 -0
- package/dist/pglite-assets/pglite.data +0 -0
- package/dist/pglite-assets/pglite.wasm +0 -0
- package/dist/playground/index.d.ts +52 -0
- package/dist/playground/index.d.ts.map +1 -0
- package/dist/playground/index.js +55 -0
- package/dist/playground/index.js.map +1 -0
- package/dist/playground/keyboard-shortcuts.d.ts +116 -0
- package/dist/playground/keyboard-shortcuts.d.ts.map +1 -0
- package/dist/playground/keyboard-shortcuts.js +588 -0
- package/dist/playground/keyboard-shortcuts.js.map +1 -0
- package/dist/playground/playground.d.ts +82 -0
- package/dist/playground/playground.d.ts.map +1 -0
- package/dist/playground/playground.js +271 -0
- package/dist/playground/playground.js.map +1 -0
- package/dist/playground/query-executor.d.ts +115 -0
- package/dist/playground/query-executor.d.ts.map +1 -0
- package/dist/playground/query-executor.js +558 -0
- package/dist/playground/query-executor.js.map +1 -0
- package/dist/playground/query-history.d.ts +92 -0
- package/dist/playground/query-history.d.ts.map +1 -0
- package/dist/playground/query-history.js +259 -0
- package/dist/playground/query-history.js.map +1 -0
- package/dist/playground/result-formatter.d.ts +59 -0
- package/dist/playground/result-formatter.d.ts.map +1 -0
- package/dist/playground/result-formatter.js +341 -0
- package/dist/playground/result-formatter.js.map +1 -0
- package/dist/playground/sample-datasets.d.ts +77 -0
- package/dist/playground/sample-datasets.d.ts.map +1 -0
- package/dist/playground/sample-datasets.js +641 -0
- package/dist/playground/sample-datasets.js.map +1 -0
- package/dist/playground/sample-queries.d.ts +73 -0
- package/dist/playground/sample-queries.d.ts.map +1 -0
- package/dist/playground/sample-queries.js +1095 -0
- package/dist/playground/sample-queries.js.map +1 -0
- package/dist/playground/schema-explorer.d.ts +55 -0
- package/dist/playground/schema-explorer.d.ts.map +1 -0
- package/dist/playground/schema-explorer.js +473 -0
- package/dist/playground/schema-explorer.js.map +1 -0
- package/dist/playground/types.d.ts +430 -0
- package/dist/playground/types.d.ts.map +1 -0
- package/dist/playground/types.js +10 -0
- package/dist/playground/types.js.map +1 -0
- package/dist/readonly/cache-reader.d.ts +145 -0
- package/dist/readonly/cache-reader.d.ts.map +1 -0
- package/dist/readonly/cache-reader.js +198 -0
- package/dist/readonly/cache-reader.js.map +1 -0
- package/dist/readonly/config.d.ts +74 -0
- package/dist/readonly/config.d.ts.map +1 -0
- package/dist/readonly/config.js +67 -0
- package/dist/readonly/config.js.map +1 -0
- package/dist/readonly/index.d.ts +22 -0
- package/dist/readonly/index.d.ts.map +1 -0
- package/dist/readonly/index.js +17 -0
- package/dist/readonly/index.js.map +1 -0
- package/dist/readonly/pglite-wrapper.d.ts +82 -0
- package/dist/readonly/pglite-wrapper.d.ts.map +1 -0
- package/dist/readonly/pglite-wrapper.js +123 -0
- package/dist/readonly/pglite-wrapper.js.map +1 -0
- package/dist/readonly/worker.d.ts +142 -0
- package/dist/readonly/worker.d.ts.map +1 -0
- package/dist/readonly/worker.js +187 -0
- package/dist/readonly/worker.js.map +1 -0
- package/dist/readonly/write-blocker.d.ts +47 -0
- package/dist/readonly/write-blocker.d.ts.map +1 -0
- package/dist/readonly/write-blocker.js +136 -0
- package/dist/readonly/write-blocker.js.map +1 -0
- package/dist/recovery/disaster-recovery.d.ts +326 -0
- package/dist/recovery/disaster-recovery.d.ts.map +1 -0
- package/dist/recovery/disaster-recovery.js +799 -0
- package/dist/recovery/disaster-recovery.js.map +1 -0
- package/dist/recovery/index.d.ts +12 -0
- package/dist/recovery/index.d.ts.map +1 -0
- package/dist/recovery/index.js +12 -0
- package/dist/recovery/index.js.map +1 -0
- package/dist/recovery/parquet-parser.d.ts +321 -0
- package/dist/recovery/parquet-parser.d.ts.map +1 -0
- package/dist/recovery/parquet-parser.js +797 -0
- package/dist/recovery/parquet-parser.js.map +1 -0
- package/dist/retention/index.d.ts +50 -0
- package/dist/retention/index.d.ts.map +1 -0
- package/dist/retention/index.js +50 -0
- package/dist/retention/index.js.map +1 -0
- package/dist/retention/policy.d.ts +344 -0
- package/dist/retention/policy.d.ts.map +1 -0
- package/dist/retention/policy.js +472 -0
- package/dist/retention/policy.js.map +1 -0
- package/dist/retention/purger.d.ts +187 -0
- package/dist/retention/purger.d.ts.map +1 -0
- package/dist/retention/purger.js +411 -0
- package/dist/retention/purger.js.map +1 -0
- package/dist/rls/auth-integration.d.ts +280 -0
- package/dist/rls/auth-integration.d.ts.map +1 -0
- package/dist/rls/auth-integration.js +399 -0
- package/dist/rls/auth-integration.js.map +1 -0
- package/dist/rls/generator.d.ts +249 -0
- package/dist/rls/generator.d.ts.map +1 -0
- package/dist/rls/generator.js +495 -0
- package/dist/rls/generator.js.map +1 -0
- package/dist/rls/index.d.ts +26 -0
- package/dist/rls/index.d.ts.map +1 -0
- package/dist/rls/index.js +58 -0
- package/dist/rls/index.js.map +1 -0
- package/dist/rls/policy.d.ts +116 -0
- package/dist/rls/policy.d.ts.map +1 -0
- package/dist/rls/policy.js +77 -0
- package/dist/rls/policy.js.map +1 -0
- package/dist/rls/validator.d.ts +155 -0
- package/dist/rls/validator.d.ts.map +1 -0
- package/dist/rls/validator.js +792 -0
- package/dist/rls/validator.js.map +1 -0
- package/dist/routing/adaptive-router.d.ts +317 -0
- package/dist/routing/adaptive-router.d.ts.map +1 -0
- package/dist/routing/adaptive-router.js +554 -0
- package/dist/routing/adaptive-router.js.map +1 -0
- package/dist/routing/circuit-breaker.d.ts +339 -0
- package/dist/routing/circuit-breaker.d.ts.map +1 -0
- package/dist/routing/circuit-breaker.js +620 -0
- package/dist/routing/circuit-breaker.js.map +1 -0
- package/dist/routing/cost-metrics.d.ts +133 -0
- package/dist/routing/cost-metrics.d.ts.map +1 -0
- package/dist/routing/cost-metrics.js +259 -0
- package/dist/routing/cost-metrics.js.map +1 -0
- package/dist/routing/do-connection-pool.d.ts +243 -0
- package/dist/routing/do-connection-pool.d.ts.map +1 -0
- package/dist/routing/do-connection-pool.js +572 -0
- package/dist/routing/do-connection-pool.js.map +1 -0
- package/dist/routing/index.d.ts +59 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +59 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/query-complexity-estimator.d.ts +73 -0
- package/dist/routing/query-complexity-estimator.d.ts.map +1 -0
- package/dist/routing/query-complexity-estimator.js +327 -0
- package/dist/routing/query-complexity-estimator.js.map +1 -0
- package/dist/routing/request-coalescing.d.ts +178 -0
- package/dist/routing/request-coalescing.d.ts.map +1 -0
- package/dist/routing/request-coalescing.js +325 -0
- package/dist/routing/request-coalescing.js.map +1 -0
- package/dist/routing/runtime-router.d.ts +107 -0
- package/dist/routing/runtime-router.d.ts.map +1 -0
- package/dist/routing/runtime-router.js +246 -0
- package/dist/routing/runtime-router.js.map +1 -0
- package/dist/routing/tenant-router.d.ts +848 -0
- package/dist/routing/tenant-router.d.ts.map +1 -0
- package/dist/routing/tenant-router.js +1056 -0
- package/dist/routing/tenant-router.js.map +1 -0
- package/dist/routing/websocket-pool.d.ts +119 -0
- package/dist/routing/websocket-pool.d.ts.map +1 -0
- package/dist/routing/websocket-pool.js +436 -0
- package/dist/routing/websocket-pool.js.map +1 -0
- package/dist/storage/cache-layer.d.ts +159 -0
- package/dist/storage/cache-layer.d.ts.map +1 -0
- package/dist/storage/cache-layer.js +245 -0
- package/dist/storage/cache-layer.js.map +1 -0
- package/dist/storage/cost-aware-tiering.d.ts +258 -0
- package/dist/storage/cost-aware-tiering.d.ts.map +1 -0
- package/dist/storage/cost-aware-tiering.js +526 -0
- package/dist/storage/cost-aware-tiering.js.map +1 -0
- package/dist/storage/index.d.ts +87 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +78 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/interfaces.d.ts +856 -0
- package/dist/storage/interfaces.d.ts.map +1 -0
- package/dist/storage/interfaces.js +69 -0
- package/dist/storage/interfaces.js.map +1 -0
- package/dist/storage/r2-layer.d.ts +226 -0
- package/dist/storage/r2-layer.d.ts.map +1 -0
- package/dist/storage/r2-layer.js +307 -0
- package/dist/storage/r2-layer.js.map +1 -0
- package/dist/storage/r2-overflow.d.ts +344 -0
- package/dist/storage/r2-overflow.d.ts.map +1 -0
- package/dist/storage/r2-overflow.js +730 -0
- package/dist/storage/r2-overflow.js.map +1 -0
- package/dist/storage/r2-page-vfs.d.ts +374 -0
- package/dist/storage/r2-page-vfs.d.ts.map +1 -0
- package/dist/storage/r2-page-vfs.js +754 -0
- package/dist/storage/r2-page-vfs.js.map +1 -0
- package/dist/storage/swr-cache.d.ts +181 -0
- package/dist/storage/swr-cache.d.ts.map +1 -0
- package/dist/storage/swr-cache.js +295 -0
- package/dist/storage/swr-cache.js.map +1 -0
- package/dist/storage/tiered-orchestrator.d.ts +951 -0
- package/dist/storage/tiered-orchestrator.d.ts.map +1 -0
- package/dist/storage/tiered-orchestrator.js +1731 -0
- package/dist/storage/tiered-orchestrator.js.map +1 -0
- package/dist/storage/tiered-vfs-swr.d.ts +279 -0
- package/dist/storage/tiered-vfs-swr.d.ts.map +1 -0
- package/dist/storage/tiered-vfs-swr.js +584 -0
- package/dist/storage/tiered-vfs-swr.js.map +1 -0
- package/dist/storage/tiered-vfs.d.ts +405 -0
- package/dist/storage/tiered-vfs.d.ts.map +1 -0
- package/dist/storage/tiered-vfs.js +833 -0
- package/dist/storage/tiered-vfs.js.map +1 -0
- package/dist/streaming/backpressure-controller.d.ts +173 -0
- package/dist/streaming/backpressure-controller.d.ts.map +1 -0
- package/dist/streaming/backpressure-controller.js +344 -0
- package/dist/streaming/backpressure-controller.js.map +1 -0
- package/dist/streaming/buffer-pool.d.ts +241 -0
- package/dist/streaming/buffer-pool.d.ts.map +1 -0
- package/dist/streaming/buffer-pool.js +381 -0
- package/dist/streaming/buffer-pool.js.map +1 -0
- package/dist/streaming/cdc-iceberg-connector.d.ts +272 -0
- package/dist/streaming/cdc-iceberg-connector.d.ts.map +1 -0
- package/dist/streaming/cdc-iceberg-connector.js +408 -0
- package/dist/streaming/cdc-iceberg-connector.js.map +1 -0
- package/dist/streaming/index.d.ts +111 -0
- package/dist/streaming/index.d.ts.map +1 -0
- package/dist/streaming/index.js +128 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/streaming/live-cdc-stream.d.ts +400 -0
- package/dist/streaming/live-cdc-stream.d.ts.map +1 -0
- package/dist/streaming/live-cdc-stream.js +703 -0
- package/dist/streaming/live-cdc-stream.js.map +1 -0
- package/dist/streaming/memory-bounded-stream.d.ts +207 -0
- package/dist/streaming/memory-bounded-stream.d.ts.map +1 -0
- package/dist/streaming/memory-bounded-stream.js +340 -0
- package/dist/streaming/memory-bounded-stream.js.map +1 -0
- package/dist/streaming/query-streamer.d.ts +379 -0
- package/dist/streaming/query-streamer.d.ts.map +1 -0
- package/dist/streaming/query-streamer.js +495 -0
- package/dist/streaming/query-streamer.js.map +1 -0
- package/dist/streaming/response-streaming.d.ts +203 -0
- package/dist/streaming/response-streaming.d.ts.map +1 -0
- package/dist/streaming/response-streaming.js +449 -0
- package/dist/streaming/response-streaming.js.map +1 -0
- package/dist/types/branded.d.ts +859 -0
- package/dist/types/branded.d.ts.map +1 -0
- package/dist/types/branded.js +891 -0
- package/dist/types/branded.js.map +1 -0
- package/dist/types/utilities.d.ts +757 -0
- package/dist/types/utilities.d.ts.map +1 -0
- package/dist/types/utilities.js +447 -0
- package/dist/types/utilities.js.map +1 -0
- package/dist/wal/replay-engine.d.ts +344 -0
- package/dist/wal/replay-engine.d.ts.map +1 -0
- package/dist/wal/replay-engine.js +975 -0
- package/dist/wal/replay-engine.js.map +1 -0
- package/dist/worker/__mocks__/capnweb.d.ts +13 -0
- package/dist/worker/__mocks__/capnweb.d.ts.map +1 -0
- package/dist/worker/__mocks__/capnweb.js +15 -0
- package/dist/worker/__mocks__/capnweb.js.map +1 -0
- package/dist/worker/__mocks__/cloudflare-workers.d.ts +31 -0
- package/dist/worker/__mocks__/cloudflare-workers.d.ts.map +1 -0
- package/dist/worker/__mocks__/cloudflare-workers.js +33 -0
- package/dist/worker/__mocks__/cloudflare-workers.js.map +1 -0
- package/dist/worker/__mocks__/pglite.data.d.ts +3 -0
- package/dist/worker/__mocks__/pglite.data.d.ts.map +1 -0
- package/dist/worker/__mocks__/pglite.data.js +20 -0
- package/dist/worker/__mocks__/pglite.data.js.map +1 -0
- package/dist/worker/__mocks__/pglite.wasm.d.ts +3 -0
- package/dist/worker/__mocks__/pglite.wasm.d.ts.map +1 -0
- package/dist/worker/__mocks__/pglite.wasm.js +30 -0
- package/dist/worker/__mocks__/pglite.wasm.js.map +1 -0
- package/dist/worker/auth-rate-limiter.d.ts +270 -0
- package/dist/worker/auth-rate-limiter.d.ts.map +1 -0
- package/dist/worker/auth-rate-limiter.js +332 -0
- package/dist/worker/auth-rate-limiter.js.map +1 -0
- package/dist/worker/auth.d.ts +345 -0
- package/dist/worker/auth.d.ts.map +1 -0
- package/dist/worker/auth.js +837 -0
- package/dist/worker/auth.js.map +1 -0
- package/dist/worker/cdc-backpressure.d.ts +338 -0
- package/dist/worker/cdc-backpressure.d.ts.map +1 -0
- package/dist/worker/cdc-backpressure.js +619 -0
- package/dist/worker/cdc-backpressure.js.map +1 -0
- package/dist/worker/cdc-sse.d.ts +277 -0
- package/dist/worker/cdc-sse.d.ts.map +1 -0
- package/dist/worker/cdc-sse.js +528 -0
- package/dist/worker/cdc-sse.js.map +1 -0
- package/dist/worker/cdc-websocket.d.ts +252 -0
- package/dist/worker/cdc-websocket.d.ts.map +1 -0
- package/dist/worker/cdc-websocket.js +940 -0
- package/dist/worker/cdc-websocket.js.map +1 -0
- package/dist/worker/cdc.d.ts +95 -0
- package/dist/worker/cdc.d.ts.map +1 -0
- package/dist/worker/cdc.js +211 -0
- package/dist/worker/cdc.js.map +1 -0
- package/dist/worker/concerns/auth-concern.d.ts +50 -0
- package/dist/worker/concerns/auth-concern.d.ts.map +1 -0
- package/dist/worker/concerns/auth-concern.js +131 -0
- package/dist/worker/concerns/auth-concern.js.map +1 -0
- package/dist/worker/concerns/cdc-concern.d.ts +99 -0
- package/dist/worker/concerns/cdc-concern.d.ts.map +1 -0
- package/dist/worker/concerns/cdc-concern.js +137 -0
- package/dist/worker/concerns/cdc-concern.js.map +1 -0
- package/dist/worker/concerns/index.d.ts +22 -0
- package/dist/worker/concerns/index.d.ts.map +1 -0
- package/dist/worker/concerns/index.js +13 -0
- package/dist/worker/concerns/index.js.map +1 -0
- package/dist/worker/concerns/query-execution-concern.d.ts +104 -0
- package/dist/worker/concerns/query-execution-concern.d.ts.map +1 -0
- package/dist/worker/concerns/query-execution-concern.js +95 -0
- package/dist/worker/concerns/query-execution-concern.js.map +1 -0
- package/dist/worker/concerns/storage-orchestration-concern.d.ts +78 -0
- package/dist/worker/concerns/storage-orchestration-concern.d.ts.map +1 -0
- package/dist/worker/concerns/storage-orchestration-concern.js +240 -0
- package/dist/worker/concerns/storage-orchestration-concern.js.map +1 -0
- package/dist/worker/do-auth-manager.d.ts +108 -0
- package/dist/worker/do-auth-manager.d.ts.map +1 -0
- package/dist/worker/do-auth-manager.js +212 -0
- package/dist/worker/do-auth-manager.js.map +1 -0
- package/dist/worker/do-pglite-manager.d.ts +137 -0
- package/dist/worker/do-pglite-manager.d.ts.map +1 -0
- package/dist/worker/do-pglite-manager.js +228 -0
- package/dist/worker/do-pglite-manager.js.map +1 -0
- package/dist/worker/do.d.ts +556 -0
- package/dist/worker/do.d.ts.map +1 -0
- package/dist/worker/do.js +1441 -0
- package/dist/worker/do.js.map +1 -0
- package/dist/worker/entry.d.ts +23 -0
- package/dist/worker/entry.d.ts.map +1 -0
- package/dist/worker/entry.js +362 -0
- package/dist/worker/entry.js.map +1 -0
- package/dist/worker/errors.d.ts +106 -0
- package/dist/worker/errors.d.ts.map +1 -0
- package/dist/worker/errors.js +178 -0
- package/dist/worker/errors.js.map +1 -0
- package/dist/worker/health-check-manager.d.ts +141 -0
- package/dist/worker/health-check-manager.d.ts.map +1 -0
- package/dist/worker/health-check-manager.js +145 -0
- package/dist/worker/health-check-manager.js.map +1 -0
- package/dist/worker/index.d.ts +60 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +67 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/memory-pressure.d.ts +892 -0
- package/dist/worker/memory-pressure.d.ts.map +1 -0
- package/dist/worker/memory-pressure.js +1990 -0
- package/dist/worker/memory-pressure.js.map +1 -0
- package/dist/worker/migration-manager.d.ts +153 -0
- package/dist/worker/migration-manager.d.ts.map +1 -0
- package/dist/worker/migration-manager.js +461 -0
- package/dist/worker/migration-manager.js.map +1 -0
- package/dist/worker/plugin-manager.d.ts +147 -0
- package/dist/worker/plugin-manager.d.ts.map +1 -0
- package/dist/worker/plugin-manager.js +408 -0
- package/dist/worker/plugin-manager.js.map +1 -0
- package/dist/worker/proxy.d.ts +330 -0
- package/dist/worker/proxy.d.ts.map +1 -0
- package/dist/worker/proxy.js +504 -0
- package/dist/worker/proxy.js.map +1 -0
- package/dist/worker/query-execution-manager.d.ts +107 -0
- package/dist/worker/query-execution-manager.d.ts.map +1 -0
- package/dist/worker/query-execution-manager.js +155 -0
- package/dist/worker/query-execution-manager.js.map +1 -0
- package/dist/worker/query-executor.d.ts +163 -0
- package/dist/worker/query-executor.d.ts.map +1 -0
- package/dist/worker/query-executor.js +413 -0
- package/dist/worker/query-executor.js.map +1 -0
- package/dist/worker/query-stats-manager.d.ts +117 -0
- package/dist/worker/query-stats-manager.d.ts.map +1 -0
- package/dist/worker/query-stats-manager.js +162 -0
- package/dist/worker/query-stats-manager.js.map +1 -0
- package/dist/worker/result-handler.d.ts +192 -0
- package/dist/worker/result-handler.d.ts.map +1 -0
- package/dist/worker/result-handler.js +346 -0
- package/dist/worker/result-handler.js.map +1 -0
- package/dist/worker/routes.d.ts +135 -0
- package/dist/worker/routes.d.ts.map +1 -0
- package/dist/worker/routes.js +460 -0
- package/dist/worker/routes.js.map +1 -0
- package/dist/worker/rpc-methods-manager.d.ts +142 -0
- package/dist/worker/rpc-methods-manager.d.ts.map +1 -0
- package/dist/worker/rpc-methods-manager.js +195 -0
- package/dist/worker/rpc-methods-manager.js.map +1 -0
- package/dist/worker/rpc.d.ts +259 -0
- package/dist/worker/rpc.d.ts.map +1 -0
- package/dist/worker/rpc.js +398 -0
- package/dist/worker/rpc.js.map +1 -0
- package/dist/worker/schema-version.d.ts +209 -0
- package/dist/worker/schema-version.d.ts.map +1 -0
- package/dist/worker/schema-version.js +450 -0
- package/dist/worker/schema-version.js.map +1 -0
- package/dist/worker/session-manager.d.ts +282 -0
- package/dist/worker/session-manager.d.ts.map +1 -0
- package/dist/worker/session-manager.js +523 -0
- package/dist/worker/session-manager.js.map +1 -0
- package/dist/worker/shutdown-manager.d.ts +188 -0
- package/dist/worker/shutdown-manager.d.ts.map +1 -0
- package/dist/worker/shutdown-manager.js +347 -0
- package/dist/worker/shutdown-manager.js.map +1 -0
- package/dist/worker/sql-transform.d.ts +61 -0
- package/dist/worker/sql-transform.d.ts.map +1 -0
- package/dist/worker/sql-transform.js +312 -0
- package/dist/worker/sql-transform.js.map +1 -0
- package/dist/worker/types.d.ts +738 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/types.js +6 -0
- package/dist/worker/types.js.map +1 -0
- package/dist/worker/user-routes.d.ts +76 -0
- package/dist/worker/user-routes.d.ts.map +1 -0
- package/dist/worker/user-routes.js +188 -0
- package/dist/worker/user-routes.js.map +1 -0
- package/dist/worker/wal-facade.d.ts +138 -0
- package/dist/worker/wal-facade.d.ts.map +1 -0
- package/dist/worker/wal-facade.js +184 -0
- package/dist/worker/wal-facade.js.map +1 -0
- package/dist/worker/wal-r2.d.ts +271 -0
- package/dist/worker/wal-r2.d.ts.map +1 -0
- package/dist/worker/wal-r2.js +689 -0
- package/dist/worker/wal-r2.js.map +1 -0
- package/dist/worker/wal-replay.d.ts +361 -0
- package/dist/worker/wal-replay.d.ts.map +1 -0
- package/dist/worker/wal-replay.js +628 -0
- package/dist/worker/wal-replay.js.map +1 -0
- package/dist/worker/wal-retention.d.ts +389 -0
- package/dist/worker/wal-retention.d.ts.map +1 -0
- package/dist/worker/wal-retention.js +763 -0
- package/dist/worker/wal-retention.js.map +1 -0
- package/dist/worker/wal.d.ts +278 -0
- package/dist/worker/wal.d.ts.map +1 -0
- package/dist/worker/wal.js +467 -0
- package/dist/worker/wal.js.map +1 -0
- package/dist/worker/websocket.d.ts +85 -0
- package/dist/worker/websocket.d.ts.map +1 -0
- package/dist/worker/websocket.js +227 -0
- package/dist/worker/websocket.js.map +1 -0
- package/package.json +108 -0
- package/src/cdc/change-stream.ts +137 -0
- package/src/cdc/filter.ts +646 -0
- package/src/cdc/index.ts +112 -0
- package/src/cdc/resume-token.ts +280 -0
- package/src/cdc/transport/index.ts +7 -0
- package/src/cdc/transport/sse.ts +723 -0
- package/src/cdc/transport/websocket.ts +873 -0
- package/src/cdc/types.ts +346 -0
- package/src/config/index.ts +25 -0
- package/src/config/memory.ts +177 -0
- package/src/config/storage.ts +204 -0
- package/src/config/streaming.ts +147 -0
- package/src/config/timeouts.ts +221 -0
- package/src/extensions/config.test.ts +187 -0
- package/src/extensions/config.ts +278 -0
- package/src/extensions/geo.test.ts +455 -0
- package/src/extensions/geo.ts +858 -0
- package/src/extensions/index.test.ts +259 -0
- package/src/extensions/index.ts +227 -0
- package/src/extensions/loader.test.ts +555 -0
- package/src/extensions/loader.ts +588 -0
- package/src/extensions/pgmq-lite.test.ts +727 -0
- package/src/extensions/pgmq-lite.ts +770 -0
- package/src/extensions/plugins.test.ts +528 -0
- package/src/extensions/plugins.ts +718 -0
- package/src/extensions/registry.test.ts +202 -0
- package/src/extensions/registry.ts +267 -0
- package/src/extensions/vector.test.ts +195 -0
- package/src/extensions/vector.ts +217 -0
- package/src/iceberg/SCHEDULER.md +580 -0
- package/src/iceberg/analytics.test.ts +703 -0
- package/src/iceberg/analytics.ts +727 -0
- package/src/iceberg/catalog-api.test.ts +838 -0
- package/src/iceberg/catalog-api.ts +520 -0
- package/src/iceberg/catalog.test.ts +680 -0
- package/src/iceberg/catalog.ts +1007 -0
- package/src/iceberg/iceberg.test.ts +705 -0
- package/src/iceberg/index.ts +406 -0
- package/src/iceberg/metadata.test.ts +632 -0
- package/src/iceberg/metadata.ts +649 -0
- package/src/iceberg/optimizer.test.ts +868 -0
- package/src/iceberg/optimizer.ts +1287 -0
- package/src/iceberg/parquet.test.ts +899 -0
- package/src/iceberg/parquet.ts +1640 -0
- package/src/iceberg/r2-organization.test.ts +615 -0
- package/src/iceberg/r2-organization.ts +951 -0
- package/src/iceberg/scheduler-do-example.ts +364 -0
- package/src/iceberg/scheduler.test.ts +861 -0
- package/src/iceberg/scheduler.ts +1201 -0
- package/src/iceberg/schema.test.ts +547 -0
- package/src/iceberg/schema.ts +616 -0
- package/src/iceberg/snapshot-manager.test.ts +919 -0
- package/src/iceberg/snapshot-manager.ts +1369 -0
- package/src/iceberg/sql-router.test.ts +334 -0
- package/src/iceberg/sql-router.ts +337 -0
- package/src/iceberg/test-fixtures.ts +605 -0
- package/src/iceberg/time-travel-api.test.ts +1029 -0
- package/src/iceberg/time-travel-api.ts +731 -0
- package/src/iceberg/time-travel.test.ts +1218 -0
- package/src/iceberg/time-travel.ts +1052 -0
- package/src/iceberg/transformer.test.ts +689 -0
- package/src/iceberg/transformer.ts +1029 -0
- package/src/iceberg/types.ts +373 -0
- package/src/iceberg/writer.test.ts +716 -0
- package/src/iceberg/writer.ts +590 -0
- package/src/index.ts +212 -0
- package/src/lineage/index.ts +42 -0
- package/src/lineage/integration.ts +334 -0
- package/src/lineage/tracker.ts +1618 -0
- package/src/lineage/types.ts +354 -0
- package/src/middleware/index.ts +36 -0
- package/src/middleware/rate-limit-concurrent.test.ts +794 -0
- package/src/middleware/rate-limit.test.ts +1568 -0
- package/src/middleware/rate-limit.ts +840 -0
- package/src/migration-tooling/external-migration.test.ts +1864 -0
- package/src/migration-tooling/external-migration.ts +2355 -0
- package/src/migration-tooling/index.ts +19 -0
- package/src/migrations/ARCHITECTURE.md +474 -0
- package/src/migrations/PROGRESS_TRACKING.md +485 -0
- package/src/migrations/auto-migrator.test.ts +732 -0
- package/src/migrations/auto-migrator.ts +531 -0
- package/src/migrations/bulk-orchestrator.test.ts +801 -0
- package/src/migrations/bulk-orchestrator.ts +1039 -0
- package/src/migrations/compatibility.test.ts +958 -0
- package/src/migrations/compatibility.ts +902 -0
- package/src/migrations/do-migrations.test.ts +2620 -0
- package/src/migrations/do-migrations.ts +1289 -0
- package/src/migrations/do-migrations.types.ts +715 -0
- package/src/migrations/drizzle-compat.test.ts +210 -0
- package/src/migrations/drizzle-compat.ts +337 -0
- package/src/migrations/index.ts +334 -0
- package/src/migrations/migration-api.test.ts +438 -0
- package/src/migrations/migration-api.ts +704 -0
- package/src/migrations/progress-tracker-do.ts +518 -0
- package/src/migrations/progress-tracker-kv.ts +305 -0
- package/src/migrations/progress-tracker.test.ts +937 -0
- package/src/migrations/progress-tracker.ts +665 -0
- package/src/migrations/registry.test.ts +331 -0
- package/src/migrations/registry.ts +468 -0
- package/src/migrations/rollback.test.ts +644 -0
- package/src/migrations/runner.test.ts +807 -0
- package/src/migrations/runner.test.ts.backup +759 -0
- package/src/migrations/runner.ts +1459 -0
- package/src/migrations/schema-generator.test.ts +649 -0
- package/src/migrations/schema-generator.ts +513 -0
- package/src/migrations/testing.ts +1037 -0
- package/src/migrations/types.ts +573 -0
- package/src/migrations/validator.test.ts +660 -0
- package/src/migrations/validator.ts +741 -0
- package/src/observability/alerting.test.ts +1133 -0
- package/src/observability/alerting.ts +455 -0
- package/src/observability/analytics-engine.ts +733 -0
- package/src/observability/cost-metrics.ts +804 -0
- package/src/observability/cross-do-tracing.test.ts +516 -0
- package/src/observability/cross-do-tracing.ts +588 -0
- package/src/observability/dashboards/postgres-do-overview.json +1656 -0
- package/src/observability/error-rate-collector.test.ts +977 -0
- package/src/observability/error-rate-collector.ts +518 -0
- package/src/observability/exporters.test.ts +365 -0
- package/src/observability/exporters.ts +650 -0
- package/src/observability/health-check.test.ts +353 -0
- package/src/observability/health-check.ts +341 -0
- package/src/observability/index.test.ts +298 -0
- package/src/observability/index.ts +885 -0
- package/src/observability/instrumentation.test.ts +428 -0
- package/src/observability/instrumentation.ts +788 -0
- package/src/observability/memory-metrics.test.ts +355 -0
- package/src/observability/memory-metrics.ts +990 -0
- package/src/observability/metrics-endpoint.test.ts +402 -0
- package/src/observability/metrics-endpoint.ts +374 -0
- package/src/observability/metrics.test.ts +291 -0
- package/src/observability/metrics.ts +315 -0
- package/src/observability/observability-features.ts +1296 -0
- package/src/observability/prometheus.test.ts +292 -0
- package/src/observability/prometheus.ts +170 -0
- package/src/observability/propagation.test.ts +417 -0
- package/src/observability/propagation.ts +294 -0
- package/src/observability/query-latency.ts +586 -0
- package/src/observability/query-performance.test.ts +406 -0
- package/src/observability/query-performance.ts +491 -0
- package/src/observability/storage-tier-metrics.test.ts +633 -0
- package/src/observability/storage-tier-metrics.ts +570 -0
- package/src/observability/tier-cost-optimizer.ts +740 -0
- package/src/observability/tracer.test.ts +346 -0
- package/src/observability/tracer.ts +585 -0
- package/src/observability/types.test.ts +726 -0
- package/src/observability/types.ts +434 -0
- package/src/pglite/auto-demotion.test.ts +477 -0
- package/src/pglite/auto-demotion.ts +385 -0
- package/src/pglite/auto-promotion.test.ts +824 -0
- package/src/pglite/auto-promotion.ts +547 -0
- package/src/pglite/cache-layer.test.ts +469 -0
- package/src/pglite/cache-layer.ts +271 -0
- package/src/pglite/cold-start-manager.ts +1260 -0
- package/src/pglite/cold-start-optimizer.test.ts +937 -0
- package/src/pglite/cold-start-optimizer.ts +1895 -0
- package/src/pglite/dovfs-adapter.ts +1122 -0
- package/src/pglite/dovfs.ts +1258 -0
- package/src/pglite/etag-cache.test.ts +844 -0
- package/src/pglite/etag-cache.ts +526 -0
- package/src/pglite/index.ts +442 -0
- package/src/pglite/init.test.ts +455 -0
- package/src/pglite/init.ts +574 -0
- package/src/pglite/lifecycle.test.ts +599 -0
- package/src/pglite/lifecycle.ts +704 -0
- package/src/pglite/parallel-loader.test.ts +586 -0
- package/src/pglite/parallel-loader.ts +481 -0
- package/src/pglite/production-pglite.test.ts +666 -0
- package/src/pglite/production-pglite.ts +537 -0
- package/src/pglite/query-executor.ts +614 -0
- package/src/pglite/r2-layer.test.ts +501 -0
- package/src/pglite/r2-layer.ts +322 -0
- package/src/pglite/tiered-init.test.ts +725 -0
- package/src/pglite/tiered-init.ts +556 -0
- package/src/pglite/tiered-vfs.test.ts +726 -0
- package/src/pglite/tiered-vfs.ts +33 -0
- package/src/pglite/tiering-stats.test.ts +531 -0
- package/src/pglite/tiering-stats.ts +407 -0
- package/src/pglite/transaction-hooks.ts +343 -0
- package/src/pglite/warm-loader.test.ts +1701 -0
- package/src/pglite/warm-loader.ts +528 -0
- package/src/pglite/workers-pglite.ts +224 -0
- package/src/pglite-assets/pglite.data +0 -0
- package/src/pglite-assets/pglite.wasm +0 -0
- package/src/pglite.d.ts +47 -0
- package/src/playground/index.ts +137 -0
- package/src/playground/keyboard-shortcuts.ts +677 -0
- package/src/playground/playground.ts +323 -0
- package/src/playground/query-executor.ts +669 -0
- package/src/playground/query-history.ts +328 -0
- package/src/playground/result-formatter.ts +420 -0
- package/src/playground/sample-datasets.ts +674 -0
- package/src/playground/sample-queries.ts +1168 -0
- package/src/playground/schema-explorer.ts +558 -0
- package/src/playground/types.ts +518 -0
- package/src/readonly/cache-reader.test.ts +460 -0
- package/src/readonly/cache-reader.ts +313 -0
- package/src/readonly/config.test.ts +187 -0
- package/src/readonly/config.ts +128 -0
- package/src/readonly/index.ts +50 -0
- package/src/readonly/pglite-wrapper.test.ts +278 -0
- package/src/readonly/pglite-wrapper.ts +184 -0
- package/src/readonly/worker.test.ts +533 -0
- package/src/readonly/worker.ts +341 -0
- package/src/readonly/write-blocker.test.ts +459 -0
- package/src/readonly/write-blocker.ts +175 -0
- package/src/recovery/disaster-recovery.test.ts +618 -0
- package/src/recovery/disaster-recovery.ts +1181 -0
- package/src/recovery/index.ts +43 -0
- package/src/recovery/parquet-parser.ts +974 -0
- package/src/retention/index.ts +74 -0
- package/src/retention/policy.test.ts +571 -0
- package/src/retention/policy.ts +774 -0
- package/src/retention/purger.test.ts +465 -0
- package/src/retention/purger.ts +558 -0
- package/src/rls/auth-integration.test.ts +752 -0
- package/src/rls/auth-integration.ts +533 -0
- package/src/rls/generator.test.ts +829 -0
- package/src/rls/generator.ts +573 -0
- package/src/rls/index.ts +128 -0
- package/src/rls/policy.ts +208 -0
- package/src/rls/rls.test.ts +1071 -0
- package/src/rls/validator.test.ts +930 -0
- package/src/rls/validator.ts +895 -0
- package/src/routing/adaptive-router.test.ts +884 -0
- package/src/routing/adaptive-router.ts +845 -0
- package/src/routing/circuit-breaker.test.ts +1505 -0
- package/src/routing/circuit-breaker.ts +852 -0
- package/src/routing/cost-metrics.test.ts +565 -0
- package/src/routing/cost-metrics.ts +408 -0
- package/src/routing/do-connection-pool.test.ts +1109 -0
- package/src/routing/do-connection-pool.ts +828 -0
- package/src/routing/index.ts +158 -0
- package/src/routing/query-complexity-estimator.test.ts +356 -0
- package/src/routing/query-complexity-estimator.ts +444 -0
- package/src/routing/request-coalescing.test.ts +738 -0
- package/src/routing/request-coalescing.ts +475 -0
- package/src/routing/runtime-router.test.ts +436 -0
- package/src/routing/runtime-router.ts +357 -0
- package/src/routing/tenant-router.test.ts +2493 -0
- package/src/routing/tenant-router.ts +1908 -0
- package/src/routing/websocket-pool.test.ts +551 -0
- package/src/routing/websocket-pool.ts +577 -0
- package/src/storage/access-pattern-tracker.test.ts +874 -0
- package/src/storage/cache-layer.test.ts +560 -0
- package/src/storage/cache-layer.ts +328 -0
- package/src/storage/cost-aware-tiering.test.ts +652 -0
- package/src/storage/cost-aware-tiering.ts +794 -0
- package/src/storage/do-sqlite-blobs.test.ts +937 -0
- package/src/storage/index.ts +272 -0
- package/src/storage/interfaces.ts +974 -0
- package/src/storage/r2-layer.test.ts +653 -0
- package/src/storage/r2-layer.ts +434 -0
- package/src/storage/r2-overflow.ts +920 -0
- package/src/storage/r2-page-vfs.test.ts +2348 -0
- package/src/storage/r2-page-vfs.ts +1054 -0
- package/src/storage/swr-cache.test.ts +832 -0
- package/src/storage/swr-cache.ts +398 -0
- package/src/storage/swr-tiered-integration.test.ts +617 -0
- package/src/storage/tiered-orchestrator.test.ts +2441 -0
- package/src/storage/tiered-orchestrator.ts +2081 -0
- package/src/storage/tiered-vfs-swr.test.ts +736 -0
- package/src/storage/tiered-vfs-swr.ts +735 -0
- package/src/storage/tiered-vfs.test.ts +793 -0
- package/src/storage/tiered-vfs.ts +1082 -0
- package/src/streaming/backpressure-controller.ts +452 -0
- package/src/streaming/buffer-pool.ts +484 -0
- package/src/streaming/cdc-iceberg-connector.ts +605 -0
- package/src/streaming/index.ts +225 -0
- package/src/streaming/live-cdc-stream.ts +985 -0
- package/src/streaming/memory-bounded-stream.ts +443 -0
- package/src/streaming/query-streamer.ts +662 -0
- package/src/streaming/response-streaming.ts +557 -0
- package/src/types/branded.ts +1075 -0
- package/src/types/branded.ts.backup +273 -0
- package/src/types/utilities.ts +1023 -0
- package/src/types/wasm.d.ts +30 -0
- package/src/validation/typed-errors.test.ts +420 -0
- package/src/wal/replay-engine.ts +1264 -0
- package/src/worker/__mocks__/capnweb.ts +15 -0
- package/src/worker/__mocks__/pglite.data.ts +22 -0
- package/src/worker/__mocks__/pglite.wasm.ts +33 -0
- package/src/worker/auth-rate-limiter.test.ts +272 -0
- package/src/worker/auth-rate-limiter.ts +448 -0
- package/src/worker/auth.security-red.test.ts +1236 -0
- package/src/worker/auth.security.test.ts +822 -0
- package/src/worker/auth.test.ts +469 -0
- package/src/worker/auth.ts +1104 -0
- package/src/worker/cdc-backpressure.test.ts +726 -0
- package/src/worker/cdc-backpressure.ts +866 -0
- package/src/worker/cdc-sse.test.ts +780 -0
- package/src/worker/cdc-sse.ts +728 -0
- package/src/worker/cdc-websocket.ts +1229 -0
- package/src/worker/cdc-ws.test.ts +1009 -0
- package/src/worker/cdc.test.ts +327 -0
- package/src/worker/cdc.ts +289 -0
- package/src/worker/concerns/auth-concern.ts +179 -0
- package/src/worker/concerns/cdc-concern.ts +247 -0
- package/src/worker/concerns/index.ts +58 -0
- package/src/worker/concerns/query-execution-concern.ts +194 -0
- package/src/worker/concerns/storage-orchestration-concern.ts +373 -0
- package/src/worker/discriminated-types.test.ts +280 -0
- package/src/worker/do-auth-manager.ts +257 -0
- package/src/worker/do-decomposition.test.ts +1236 -0
- package/src/worker/do-pglite-manager.ts +302 -0
- package/src/worker/do.test.ts +2254 -0
- package/src/worker/do.ts +1878 -0
- package/src/worker/entry.ts +417 -0
- package/src/worker/errors.ts +285 -0
- package/src/worker/health-check-manager.test.ts +261 -0
- package/src/worker/health-check-manager.ts +231 -0
- package/src/worker/index.ts +389 -0
- package/src/worker/memory-pressure.test.ts +1460 -0
- package/src/worker/memory-pressure.ts +2650 -0
- package/src/worker/migration-manager.ts +582 -0
- package/src/worker/neon-compat.test.ts +332 -0
- package/src/worker/plugin-manager.ts +485 -0
- package/src/worker/postgres.do-rpc.d.ts +76 -0
- package/src/worker/proxy.ts +694 -0
- package/src/worker/query-execution-manager.test.ts +303 -0
- package/src/worker/query-execution-manager.ts +219 -0
- package/src/worker/query-executor.test.ts +282 -0
- package/src/worker/query-executor.ts +560 -0
- package/src/worker/query-stats-manager.ts +229 -0
- package/src/worker/result-handler.test.ts +364 -0
- package/src/worker/result-handler.ts +510 -0
- package/src/worker/routes.test.ts +795 -0
- package/src/worker/routes.ts +650 -0
- package/src/worker/rpc-methods-manager.test.ts +326 -0
- package/src/worker/rpc-methods-manager.ts +276 -0
- package/src/worker/rpc.ts +524 -0
- package/src/worker/schema-version.ts +605 -0
- package/src/worker/session-manager.test.ts +506 -0
- package/src/worker/session-manager.ts +732 -0
- package/src/worker/shutdown-manager.ts +469 -0
- package/src/worker/sql-transform.test.ts +286 -0
- package/src/worker/sql-transform.ts +368 -0
- package/src/worker/supabase-compat.test.ts +621 -0
- package/src/worker/types.test.ts +292 -0
- package/src/worker/types.ts +873 -0
- package/src/worker/user-routes.test.ts +703 -0
- package/src/worker/user-routes.ts +303 -0
- package/src/worker/wal-facade.ts +235 -0
- package/src/worker/wal-r2.test.ts +570 -0
- package/src/worker/wal-r2.ts +930 -0
- package/src/worker/wal-replay.test.ts +845 -0
- package/src/worker/wal-replay.ts +897 -0
- package/src/worker/wal-retention.test.ts +758 -0
- package/src/worker/wal-retention.ts +1075 -0
- package/src/worker/wal.test.ts +618 -0
- package/src/worker/wal.ts +697 -0
- package/src/worker/websocket.test.ts +296 -0
- package/src/worker/websocket.ts +284 -0
|
@@ -0,0 +1,1459 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration Runner
|
|
3
|
+
*
|
|
4
|
+
* Executes migrations against a PGLite database instance.
|
|
5
|
+
* Designed for postgres.do's unique multi-database model where
|
|
6
|
+
* each user gets their own Durable Object database.
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - Auto-migration on first connection to new databases
|
|
10
|
+
* - Idempotent execution (safe to run multiple times)
|
|
11
|
+
* - Transaction-based migrations with automatic rollback on failure
|
|
12
|
+
* - Advisory locks to prevent concurrent migrations
|
|
13
|
+
* - Checksum validation to detect modified migrations
|
|
14
|
+
*
|
|
15
|
+
* @module migrations/runner
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type {
|
|
19
|
+
Migration,
|
|
20
|
+
MigrationResult,
|
|
21
|
+
BatchMigrationResult,
|
|
22
|
+
MigrationProgressEvent,
|
|
23
|
+
MigrationRunnerConfig,
|
|
24
|
+
MigrationEventListener,
|
|
25
|
+
MigrationEvent,
|
|
26
|
+
MigrationRecord,
|
|
27
|
+
SchemaVersion,
|
|
28
|
+
VersionComparison,
|
|
29
|
+
QueryExecutor,
|
|
30
|
+
MigrationLock,
|
|
31
|
+
RollbackOptions,
|
|
32
|
+
RollbackResult,
|
|
33
|
+
BatchRollbackResult,
|
|
34
|
+
RollbackEvent,
|
|
35
|
+
RollbackEventListener,
|
|
36
|
+
RollbackHistoryRecord,
|
|
37
|
+
} from './types'
|
|
38
|
+
import type { MigrationRegistry } from './registry'
|
|
39
|
+
import { MigrationError } from '@dotdo/postgres-shared/errors'
|
|
40
|
+
import { createLogger, LogLevel, type ILogger } from '@dotdo/postgres-shared'
|
|
41
|
+
|
|
42
|
+
export { MigrationError }
|
|
43
|
+
|
|
44
|
+
// Re-export RollbackProgressEvent for external use
|
|
45
|
+
export type { RollbackProgressEvent } from './types'
|
|
46
|
+
|
|
47
|
+
// Module-level logger for MigrationRunner
|
|
48
|
+
// Level is DEBUG because the debug config flag gates whether log() is called at all.
|
|
49
|
+
// The logger just provides structured output - the filtering happens at call site.
|
|
50
|
+
const runnerLogger: ILogger = createLogger({
|
|
51
|
+
level: LogLevel.DEBUG,
|
|
52
|
+
prefix: '[MigrationRunner]',
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Default runner configuration
|
|
57
|
+
*/
|
|
58
|
+
const DEFAULT_CONFIG: Required<Omit<MigrationRunnerConfig, 'onProgress'>> = {
|
|
59
|
+
tableName: '_migrations',
|
|
60
|
+
schema: 'public',
|
|
61
|
+
autoMigrate: true,
|
|
62
|
+
migrationTimeoutMs: 30000,
|
|
63
|
+
useLocking: true,
|
|
64
|
+
lockTimeoutMs: 5000,
|
|
65
|
+
debug: false,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* SQL for creating the migrations table
|
|
70
|
+
*/
|
|
71
|
+
const CREATE_MIGRATIONS_TABLE_SQL = (tableName: string, schema: string) => `
|
|
72
|
+
CREATE TABLE IF NOT EXISTS "${schema}"."${tableName}" (
|
|
73
|
+
id TEXT PRIMARY KEY,
|
|
74
|
+
name TEXT NOT NULL,
|
|
75
|
+
version INTEGER NOT NULL UNIQUE,
|
|
76
|
+
checksum TEXT NOT NULL,
|
|
77
|
+
applied_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
78
|
+
execution_time_ms INTEGER NOT NULL DEFAULT 0,
|
|
79
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'applied', 'failed', 'rolled_back'))
|
|
80
|
+
);
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_version ON "${schema}"."${tableName}" (version);
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_status ON "${schema}"."${tableName}" (status);
|
|
83
|
+
`
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* SQL for creating the rollback history table
|
|
87
|
+
*/
|
|
88
|
+
const CREATE_ROLLBACK_HISTORY_TABLE_SQL = (tableName: string, schema: string) => `
|
|
89
|
+
CREATE TABLE IF NOT EXISTS "${schema}"."${tableName}_rollback_history" (
|
|
90
|
+
rollback_id TEXT PRIMARY KEY,
|
|
91
|
+
migration_id TEXT NOT NULL,
|
|
92
|
+
version INTEGER NOT NULL,
|
|
93
|
+
rolled_back_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
94
|
+
execution_time_ms INTEGER NOT NULL DEFAULT 0,
|
|
95
|
+
previous_status TEXT NOT NULL,
|
|
96
|
+
initiated_by TEXT,
|
|
97
|
+
reason TEXT
|
|
98
|
+
);
|
|
99
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_rollback_history_migration ON "${schema}"."${tableName}_rollback_history" (migration_id);
|
|
100
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_rollback_history_version ON "${schema}"."${tableName}_rollback_history" (version);
|
|
101
|
+
`
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Generate a unique rollback ID
|
|
105
|
+
*/
|
|
106
|
+
function generateRollbackId(): string {
|
|
107
|
+
const timestamp = Date.now().toString(36)
|
|
108
|
+
const random = Math.random().toString(36).substring(2, 8)
|
|
109
|
+
return `rollback_${timestamp}_${random}`
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Calculate SHA-256 checksum for migration content
|
|
114
|
+
*/
|
|
115
|
+
async function calculateChecksum(content: string): Promise<string> {
|
|
116
|
+
const encoder = new TextEncoder()
|
|
117
|
+
const data = encoder.encode(content)
|
|
118
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data)
|
|
119
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer))
|
|
120
|
+
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Generate a unique lock ID
|
|
125
|
+
*/
|
|
126
|
+
function generateLockId(): string {
|
|
127
|
+
const timestamp = Date.now().toString(36)
|
|
128
|
+
const random = Math.random().toString(36).substring(2, 8)
|
|
129
|
+
return `lock_${timestamp}_${random}`
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Migration Runner
|
|
134
|
+
*
|
|
135
|
+
* Executes migrations against a database instance.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* // Create a runner with a registry
|
|
140
|
+
* const runner = new MigrationRunner(pglite, registry, {
|
|
141
|
+
* autoMigrate: true,
|
|
142
|
+
* onProgress: (event) => console.log(event),
|
|
143
|
+
* })
|
|
144
|
+
*
|
|
145
|
+
* // Initialize (creates migrations table)
|
|
146
|
+
* await runner.initialize()
|
|
147
|
+
*
|
|
148
|
+
* // Run all pending migrations
|
|
149
|
+
* const result = await runner.migrate()
|
|
150
|
+
*
|
|
151
|
+
* // Get current schema version
|
|
152
|
+
* const version = await runner.getSchemaVersion()
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
/** Concrete config type without undefined values */
|
|
156
|
+
interface ResolvedMigrationRunnerConfig {
|
|
157
|
+
tableName: string
|
|
158
|
+
schema: string
|
|
159
|
+
autoMigrate: boolean
|
|
160
|
+
migrationTimeoutMs: number
|
|
161
|
+
useLocking: boolean
|
|
162
|
+
lockTimeoutMs: number
|
|
163
|
+
debug: boolean
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export class MigrationRunner {
|
|
167
|
+
private executor: QueryExecutor
|
|
168
|
+
private registry: MigrationRegistry
|
|
169
|
+
private config: ResolvedMigrationRunnerConfig
|
|
170
|
+
private onProgress: ((event: MigrationProgressEvent) => void) | undefined
|
|
171
|
+
private initialized = false
|
|
172
|
+
private listeners: MigrationEventListener[] = []
|
|
173
|
+
private rollbackListeners: RollbackEventListener[] = []
|
|
174
|
+
private currentLock: MigrationLock | null = null
|
|
175
|
+
|
|
176
|
+
constructor(
|
|
177
|
+
executor: QueryExecutor,
|
|
178
|
+
registry: MigrationRegistry,
|
|
179
|
+
config: MigrationRunnerConfig = {}
|
|
180
|
+
) {
|
|
181
|
+
this.executor = executor
|
|
182
|
+
this.registry = registry
|
|
183
|
+
// Type assertions needed because MigrationRunnerConfig has explicit `| undefined` in property types
|
|
184
|
+
// which isn't narrowed away by `??` operator even when defaults are provided
|
|
185
|
+
this.config = {
|
|
186
|
+
tableName: (config.tableName ?? DEFAULT_CONFIG.tableName) as string,
|
|
187
|
+
schema: (config.schema ?? DEFAULT_CONFIG.schema) as string,
|
|
188
|
+
autoMigrate: (config.autoMigrate ?? DEFAULT_CONFIG.autoMigrate) as boolean,
|
|
189
|
+
migrationTimeoutMs: (config.migrationTimeoutMs ?? DEFAULT_CONFIG.migrationTimeoutMs) as number,
|
|
190
|
+
useLocking: (config.useLocking ?? DEFAULT_CONFIG.useLocking) as boolean,
|
|
191
|
+
lockTimeoutMs: (config.lockTimeoutMs ?? DEFAULT_CONFIG.lockTimeoutMs) as number,
|
|
192
|
+
debug: (config.debug ?? DEFAULT_CONFIG.debug) as boolean,
|
|
193
|
+
}
|
|
194
|
+
this.onProgress = config.onProgress
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Log debug message
|
|
199
|
+
*/
|
|
200
|
+
private log(message: string, ...args: unknown[]): void {
|
|
201
|
+
if (this.config.debug) {
|
|
202
|
+
runnerLogger.debug(message, args.length > 0 ? { args } : undefined)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Emit a migration event
|
|
208
|
+
*/
|
|
209
|
+
private async emitEvent(event: Omit<MigrationEvent, 'timestamp'>): Promise<void> {
|
|
210
|
+
const fullEvent: MigrationEvent = {
|
|
211
|
+
...event,
|
|
212
|
+
timestamp: new Date(),
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
for (const listener of this.listeners) {
|
|
216
|
+
try {
|
|
217
|
+
await listener(fullEvent)
|
|
218
|
+
} catch (error) {
|
|
219
|
+
runnerLogger.error('Event listener error', {
|
|
220
|
+
error: error instanceof Error ? error.message : String(error),
|
|
221
|
+
})
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Add an event listener
|
|
228
|
+
*/
|
|
229
|
+
onEvent(listener: MigrationEventListener): () => void {
|
|
230
|
+
this.listeners.push(listener)
|
|
231
|
+
return () => {
|
|
232
|
+
const index = this.listeners.indexOf(listener)
|
|
233
|
+
if (index >= 0) {
|
|
234
|
+
this.listeners.splice(index, 1)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Emit a rollback event
|
|
241
|
+
*/
|
|
242
|
+
private async emitRollbackEvent(event: Omit<RollbackEvent, 'timestamp'>): Promise<void> {
|
|
243
|
+
const fullEvent: RollbackEvent = {
|
|
244
|
+
...event,
|
|
245
|
+
timestamp: new Date(),
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
for (const listener of this.rollbackListeners) {
|
|
249
|
+
try {
|
|
250
|
+
await listener(fullEvent)
|
|
251
|
+
} catch (error) {
|
|
252
|
+
runnerLogger.error('Rollback event listener error', {
|
|
253
|
+
error: error instanceof Error ? error.message : String(error),
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Add a rollback event listener
|
|
261
|
+
*/
|
|
262
|
+
onRollbackEvent(listener: RollbackEventListener): () => void {
|
|
263
|
+
this.rollbackListeners.push(listener)
|
|
264
|
+
return () => {
|
|
265
|
+
const index = this.rollbackListeners.indexOf(listener)
|
|
266
|
+
if (index >= 0) {
|
|
267
|
+
this.rollbackListeners.splice(index, 1)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Get the full qualified table name
|
|
274
|
+
*/
|
|
275
|
+
private getTableName(): string {
|
|
276
|
+
return `"${this.config.schema}"."${this.config.tableName}"`
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Initialize the migration runner
|
|
281
|
+
*
|
|
282
|
+
* Creates the migrations table and rollback history table if they don't exist.
|
|
283
|
+
* Safe to call multiple times.
|
|
284
|
+
*/
|
|
285
|
+
async initialize(): Promise<void> {
|
|
286
|
+
if (this.initialized) {
|
|
287
|
+
return
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
this.log('Initializing migrations table')
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
await this.executor.query(
|
|
294
|
+
CREATE_MIGRATIONS_TABLE_SQL(this.config.tableName, this.config.schema)
|
|
295
|
+
)
|
|
296
|
+
await this.executor.query(
|
|
297
|
+
CREATE_ROLLBACK_HISTORY_TABLE_SQL(this.config.tableName, this.config.schema)
|
|
298
|
+
)
|
|
299
|
+
this.initialized = true
|
|
300
|
+
await this.emitEvent({ type: 'table_created' })
|
|
301
|
+
this.log('Migrations table ready')
|
|
302
|
+
} catch (error) {
|
|
303
|
+
this.log('Error creating migrations table:', error)
|
|
304
|
+
throw error
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Get the rollback history table name
|
|
310
|
+
*/
|
|
311
|
+
private getRollbackHistoryTableName(): string {
|
|
312
|
+
return `"${this.config.schema}"."${this.config.tableName}_rollback_history"`
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Acquire a migration lock
|
|
317
|
+
*
|
|
318
|
+
* Uses PostgreSQL advisory locks to prevent concurrent migrations.
|
|
319
|
+
* This is important in Cloudflare Workers where multiple requests
|
|
320
|
+
* might hit the same DO simultaneously.
|
|
321
|
+
*/
|
|
322
|
+
private async acquireLock(): Promise<boolean> {
|
|
323
|
+
if (!this.config.useLocking) {
|
|
324
|
+
return true
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const lockId = generateLockId()
|
|
328
|
+
const lockKey = 12345 // Fixed lock key for migrations
|
|
329
|
+
|
|
330
|
+
try {
|
|
331
|
+
// Try to acquire an exclusive session-level advisory lock
|
|
332
|
+
const result = await this.executor.query<{ pg_try_advisory_lock: boolean }>(
|
|
333
|
+
`SELECT pg_try_advisory_lock($1)`,
|
|
334
|
+
[lockKey]
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
if (result.rows[0]?.pg_try_advisory_lock) {
|
|
338
|
+
this.currentLock = {
|
|
339
|
+
acquired: true,
|
|
340
|
+
lockId,
|
|
341
|
+
acquiredAt: new Date(),
|
|
342
|
+
expiresAt: new Date(Date.now() + this.config.lockTimeoutMs),
|
|
343
|
+
}
|
|
344
|
+
await this.emitEvent({ type: 'lock_acquired', lock: this.currentLock })
|
|
345
|
+
this.log('Lock acquired:', lockId)
|
|
346
|
+
return true
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return false
|
|
350
|
+
} catch (error) {
|
|
351
|
+
// PGLite might not support advisory locks, continue without locking
|
|
352
|
+
this.log('Advisory lock not available, continuing without lock')
|
|
353
|
+
return true
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Release the migration lock
|
|
359
|
+
*/
|
|
360
|
+
private async releaseLock(): Promise<void> {
|
|
361
|
+
if (!this.config.useLocking || !this.currentLock?.acquired) {
|
|
362
|
+
return
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const lockKey = 12345
|
|
366
|
+
|
|
367
|
+
try {
|
|
368
|
+
await this.executor.query(`SELECT pg_advisory_unlock($1)`, [lockKey])
|
|
369
|
+
await this.emitEvent({ type: 'lock_released', lock: this.currentLock })
|
|
370
|
+
this.log('Lock released:', this.currentLock.lockId)
|
|
371
|
+
} catch {
|
|
372
|
+
// Ignore unlock errors
|
|
373
|
+
} finally {
|
|
374
|
+
this.currentLock = null
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Get the current schema version and all migration records
|
|
380
|
+
*/
|
|
381
|
+
async getSchemaVersion(): Promise<SchemaVersion> {
|
|
382
|
+
await this.initialize()
|
|
383
|
+
|
|
384
|
+
const result = await this.executor.query<MigrationRecord>(
|
|
385
|
+
`SELECT id, name, version, checksum,
|
|
386
|
+
applied_at::text as applied_at,
|
|
387
|
+
execution_time_ms, status
|
|
388
|
+
FROM ${this.getTableName()}
|
|
389
|
+
ORDER BY version ASC`
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
const migrations = result.rows
|
|
393
|
+
const appliedMigrations = migrations.filter((m) => m.status === 'applied')
|
|
394
|
+
|
|
395
|
+
const currentVersion =
|
|
396
|
+
appliedMigrations.length > 0
|
|
397
|
+
? Math.max(...appliedMigrations.map((m) => m.version))
|
|
398
|
+
: 0
|
|
399
|
+
|
|
400
|
+
const lastApplied = appliedMigrations.reduce<MigrationRecord | null>(
|
|
401
|
+
(latest, m) => (!latest || m.applied_at > latest.applied_at ? m : latest),
|
|
402
|
+
null
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
currentVersion,
|
|
407
|
+
appliedCount: appliedMigrations.length,
|
|
408
|
+
lastMigrationAt: lastApplied?.applied_at ?? null,
|
|
409
|
+
migrations,
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Compare current schema version against the registry
|
|
415
|
+
*/
|
|
416
|
+
async compareVersion(): Promise<VersionComparison> {
|
|
417
|
+
const schemaVersion = await this.getSchemaVersion()
|
|
418
|
+
const targetVersion = this.registry.getLatestVersion()
|
|
419
|
+
|
|
420
|
+
const appliedVersions = new Set(
|
|
421
|
+
schemaVersion.migrations
|
|
422
|
+
.filter((m) => m.status === 'applied')
|
|
423
|
+
.map((m) => m.version)
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
// Find missing versions
|
|
427
|
+
const missingVersions: number[] = []
|
|
428
|
+
for (const version of this.registry.getMigrationVersions()) {
|
|
429
|
+
if (!appliedVersions.has(version)) {
|
|
430
|
+
missingVersions.push(version)
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return {
|
|
435
|
+
current: schemaVersion.currentVersion,
|
|
436
|
+
target: targetVersion,
|
|
437
|
+
needsMigration: missingVersions.length > 0,
|
|
438
|
+
pendingCount: missingVersions.length,
|
|
439
|
+
missingVersions,
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Get a migration record by ID
|
|
445
|
+
*/
|
|
446
|
+
async getMigrationRecord(id: string): Promise<MigrationRecord | null> {
|
|
447
|
+
await this.initialize()
|
|
448
|
+
|
|
449
|
+
const result = await this.executor.query<MigrationRecord>(
|
|
450
|
+
`SELECT id, name, version, checksum,
|
|
451
|
+
applied_at::text as applied_at,
|
|
452
|
+
execution_time_ms, status
|
|
453
|
+
FROM ${this.getTableName()}
|
|
454
|
+
WHERE id = $1`,
|
|
455
|
+
[id]
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
return result.rows[0] ?? null
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Check if a migration has been applied
|
|
463
|
+
*/
|
|
464
|
+
async isMigrationApplied(id: string): Promise<boolean> {
|
|
465
|
+
const record = await this.getMigrationRecord(id)
|
|
466
|
+
return record?.status === 'applied'
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Apply a single migration
|
|
471
|
+
*/
|
|
472
|
+
private async applyMigration(
|
|
473
|
+
migration: Migration,
|
|
474
|
+
index: number,
|
|
475
|
+
total: number
|
|
476
|
+
): Promise<MigrationResult> {
|
|
477
|
+
const checksum = await calculateChecksum(migration.up)
|
|
478
|
+
const existing = await this.getMigrationRecord(migration.id)
|
|
479
|
+
|
|
480
|
+
// Check if already applied
|
|
481
|
+
if (existing && existing.status === 'applied') {
|
|
482
|
+
// Validate checksum
|
|
483
|
+
if (existing.checksum !== checksum) {
|
|
484
|
+
const error = `Migration checksum mismatch. Expected: ${existing.checksum}, Got: ${checksum}. This may indicate the migration content has changed.`
|
|
485
|
+
this.log(`Migration ${migration.id} checksum mismatch`)
|
|
486
|
+
return {
|
|
487
|
+
success: false,
|
|
488
|
+
id: migration.id,
|
|
489
|
+
executionTimeMs: 0,
|
|
490
|
+
error,
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Already applied, skip
|
|
495
|
+
this.onProgress?.({
|
|
496
|
+
migration,
|
|
497
|
+
index,
|
|
498
|
+
total,
|
|
499
|
+
phase: 'skipped',
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
await this.emitEvent({
|
|
503
|
+
type: 'migration_skipped',
|
|
504
|
+
migration,
|
|
505
|
+
})
|
|
506
|
+
|
|
507
|
+
return {
|
|
508
|
+
success: true,
|
|
509
|
+
id: migration.id,
|
|
510
|
+
executionTimeMs: 0,
|
|
511
|
+
skipped: true,
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Emit start events
|
|
516
|
+
this.onProgress?.({
|
|
517
|
+
migration,
|
|
518
|
+
index,
|
|
519
|
+
total,
|
|
520
|
+
phase: 'starting',
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
await this.emitEvent({
|
|
524
|
+
type: 'migration_started',
|
|
525
|
+
migration,
|
|
526
|
+
})
|
|
527
|
+
|
|
528
|
+
const startTime = performance.now()
|
|
529
|
+
|
|
530
|
+
try {
|
|
531
|
+
// Begin transaction if migration is transactional
|
|
532
|
+
if (migration.transactional !== false) {
|
|
533
|
+
await this.executor.query('BEGIN')
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Execute migration SQL
|
|
537
|
+
this.onProgress?.({
|
|
538
|
+
migration,
|
|
539
|
+
index,
|
|
540
|
+
total,
|
|
541
|
+
phase: 'executing',
|
|
542
|
+
})
|
|
543
|
+
|
|
544
|
+
await this.executor.query(migration.up)
|
|
545
|
+
|
|
546
|
+
// Record the migration
|
|
547
|
+
await this.executor.query(
|
|
548
|
+
`INSERT INTO ${this.getTableName()} (id, name, version, checksum, execution_time_ms, status)
|
|
549
|
+
VALUES ($1, $2, $3, $4, $5, 'applied')
|
|
550
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
551
|
+
status = 'applied',
|
|
552
|
+
execution_time_ms = $5,
|
|
553
|
+
applied_at = CURRENT_TIMESTAMP`,
|
|
554
|
+
[
|
|
555
|
+
migration.id,
|
|
556
|
+
migration.name,
|
|
557
|
+
migration.version,
|
|
558
|
+
checksum,
|
|
559
|
+
Math.round(performance.now() - startTime),
|
|
560
|
+
]
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
// Commit transaction
|
|
564
|
+
if (migration.transactional !== false) {
|
|
565
|
+
await this.executor.query('COMMIT')
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const executionTimeMs = Math.round(performance.now() - startTime)
|
|
569
|
+
|
|
570
|
+
const result: MigrationResult = {
|
|
571
|
+
success: true,
|
|
572
|
+
id: migration.id,
|
|
573
|
+
executionTimeMs,
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// Emit completion events
|
|
577
|
+
this.onProgress?.({
|
|
578
|
+
migration,
|
|
579
|
+
index,
|
|
580
|
+
total,
|
|
581
|
+
phase: 'completed',
|
|
582
|
+
durationMs: executionTimeMs,
|
|
583
|
+
})
|
|
584
|
+
|
|
585
|
+
await this.emitEvent({
|
|
586
|
+
type: 'migration_completed',
|
|
587
|
+
migration,
|
|
588
|
+
result,
|
|
589
|
+
})
|
|
590
|
+
|
|
591
|
+
this.log(`Migration ${migration.id} applied in ${executionTimeMs}ms`)
|
|
592
|
+
|
|
593
|
+
return result
|
|
594
|
+
} catch (error) {
|
|
595
|
+
// Rollback on failure
|
|
596
|
+
if (migration.transactional !== false) {
|
|
597
|
+
try {
|
|
598
|
+
await this.executor.query('ROLLBACK')
|
|
599
|
+
} catch {
|
|
600
|
+
// Ignore rollback errors
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const executionTimeMs = Math.round(performance.now() - startTime)
|
|
605
|
+
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
606
|
+
|
|
607
|
+
// Record failed migration
|
|
608
|
+
try {
|
|
609
|
+
await this.executor.query(
|
|
610
|
+
`INSERT INTO ${this.getTableName()} (id, name, version, checksum, execution_time_ms, status)
|
|
611
|
+
VALUES ($1, $2, $3, $4, $5, 'failed')
|
|
612
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
613
|
+
status = 'failed',
|
|
614
|
+
execution_time_ms = $5,
|
|
615
|
+
applied_at = CURRENT_TIMESTAMP`,
|
|
616
|
+
[migration.id, migration.name, migration.version, checksum, executionTimeMs]
|
|
617
|
+
)
|
|
618
|
+
} catch {
|
|
619
|
+
// Ignore recording errors
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const result: MigrationResult = {
|
|
623
|
+
success: false,
|
|
624
|
+
id: migration.id,
|
|
625
|
+
executionTimeMs,
|
|
626
|
+
error: errorMessage,
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Emit failure events
|
|
630
|
+
this.onProgress?.({
|
|
631
|
+
migration,
|
|
632
|
+
index,
|
|
633
|
+
total,
|
|
634
|
+
phase: 'failed',
|
|
635
|
+
durationMs: executionTimeMs,
|
|
636
|
+
error: errorMessage,
|
|
637
|
+
})
|
|
638
|
+
|
|
639
|
+
await this.emitEvent({
|
|
640
|
+
type: 'migration_failed',
|
|
641
|
+
migration,
|
|
642
|
+
result,
|
|
643
|
+
error: error instanceof Error ? error : new Error(errorMessage),
|
|
644
|
+
})
|
|
645
|
+
|
|
646
|
+
this.log(`Migration ${migration.id} failed:`, errorMessage)
|
|
647
|
+
|
|
648
|
+
return result
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Run all pending migrations
|
|
654
|
+
*
|
|
655
|
+
* This is the main entry point for migration execution.
|
|
656
|
+
* Migrations are run in version order, stopping on first failure.
|
|
657
|
+
*/
|
|
658
|
+
async migrate(): Promise<BatchMigrationResult> {
|
|
659
|
+
await this.initialize()
|
|
660
|
+
|
|
661
|
+
// Acquire lock
|
|
662
|
+
const lockAcquired = await this.acquireLock()
|
|
663
|
+
if (!lockAcquired) {
|
|
664
|
+
throw new MigrationError('Failed to acquire migration lock - another migration may be in progress')
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
try {
|
|
668
|
+
const startVersion = (await this.getSchemaVersion()).currentVersion
|
|
669
|
+
const startTime = performance.now()
|
|
670
|
+
|
|
671
|
+
// Get pending migrations
|
|
672
|
+
const comparison = await this.compareVersion()
|
|
673
|
+
if (!comparison.needsMigration) {
|
|
674
|
+
return {
|
|
675
|
+
success: true,
|
|
676
|
+
fromVersion: startVersion,
|
|
677
|
+
toVersion: startVersion,
|
|
678
|
+
durationMs: 0,
|
|
679
|
+
results: [],
|
|
680
|
+
migrationsRun: 0,
|
|
681
|
+
migrationsSkipped: 0,
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Get migrations to run
|
|
686
|
+
const pendingMigrations = this.registry
|
|
687
|
+
.getMigrations()
|
|
688
|
+
.filter((m) => comparison.missingVersions.includes(m.version))
|
|
689
|
+
|
|
690
|
+
await this.emitEvent({
|
|
691
|
+
type: 'batch_started',
|
|
692
|
+
metadata: {
|
|
693
|
+
count: pendingMigrations.length,
|
|
694
|
+
versions: pendingMigrations.map((m) => m.version),
|
|
695
|
+
},
|
|
696
|
+
})
|
|
697
|
+
|
|
698
|
+
// Run migrations
|
|
699
|
+
const results: MigrationResult[] = []
|
|
700
|
+
let migrationsRun = 0
|
|
701
|
+
let migrationsSkipped = 0
|
|
702
|
+
|
|
703
|
+
for (let i = 0; i < pendingMigrations.length; i++) {
|
|
704
|
+
const migration = pendingMigrations[i]
|
|
705
|
+
if (!migration) continue
|
|
706
|
+
const result = await this.applyMigration(migration, i, pendingMigrations.length)
|
|
707
|
+
results.push(result)
|
|
708
|
+
|
|
709
|
+
if (result.skipped) {
|
|
710
|
+
migrationsSkipped++
|
|
711
|
+
} else if (result.success) {
|
|
712
|
+
migrationsRun++
|
|
713
|
+
} else {
|
|
714
|
+
// Stop on failure
|
|
715
|
+
break
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const durationMs = Math.round(performance.now() - startTime)
|
|
720
|
+
const endVersion = (await this.getSchemaVersion()).currentVersion
|
|
721
|
+
const success = results.every((r) => r.success)
|
|
722
|
+
|
|
723
|
+
const batchResult: BatchMigrationResult = {
|
|
724
|
+
success,
|
|
725
|
+
fromVersion: startVersion,
|
|
726
|
+
toVersion: endVersion,
|
|
727
|
+
durationMs,
|
|
728
|
+
results,
|
|
729
|
+
migrationsRun,
|
|
730
|
+
migrationsSkipped,
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
await this.emitEvent({
|
|
734
|
+
type: success ? 'batch_completed' : 'batch_failed',
|
|
735
|
+
batchResult,
|
|
736
|
+
})
|
|
737
|
+
|
|
738
|
+
return batchResult
|
|
739
|
+
} finally {
|
|
740
|
+
await this.releaseLock()
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Migrate up to a specific version
|
|
746
|
+
*/
|
|
747
|
+
async migrateToVersion(targetVersion: number): Promise<BatchMigrationResult> {
|
|
748
|
+
await this.initialize()
|
|
749
|
+
|
|
750
|
+
const lockAcquired = await this.acquireLock()
|
|
751
|
+
if (!lockAcquired) {
|
|
752
|
+
throw new MigrationError('Failed to acquire migration lock')
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
try {
|
|
756
|
+
const schemaVersion = await this.getSchemaVersion()
|
|
757
|
+
const startVersion = schemaVersion.currentVersion
|
|
758
|
+
const startTime = performance.now()
|
|
759
|
+
|
|
760
|
+
// Get migrations up to target version that haven't been applied
|
|
761
|
+
const appliedIds = new Set(
|
|
762
|
+
schemaVersion.migrations
|
|
763
|
+
.filter((m) => m.status === 'applied')
|
|
764
|
+
.map((m) => m.id)
|
|
765
|
+
)
|
|
766
|
+
|
|
767
|
+
const migrationsToRun = this.registry
|
|
768
|
+
.getMigrationsUpTo(targetVersion)
|
|
769
|
+
.filter((m) => !appliedIds.has(m.id))
|
|
770
|
+
|
|
771
|
+
if (migrationsToRun.length === 0) {
|
|
772
|
+
return {
|
|
773
|
+
success: true,
|
|
774
|
+
fromVersion: startVersion,
|
|
775
|
+
toVersion: startVersion,
|
|
776
|
+
durationMs: 0,
|
|
777
|
+
results: [],
|
|
778
|
+
migrationsRun: 0,
|
|
779
|
+
migrationsSkipped: 0,
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// Run migrations
|
|
784
|
+
const results: MigrationResult[] = []
|
|
785
|
+
let migrationsRun = 0
|
|
786
|
+
let migrationsSkipped = 0
|
|
787
|
+
|
|
788
|
+
for (let i = 0; i < migrationsToRun.length; i++) {
|
|
789
|
+
const migration = migrationsToRun[i]
|
|
790
|
+
if (!migration) continue
|
|
791
|
+
const result = await this.applyMigration(migration, i, migrationsToRun.length)
|
|
792
|
+
results.push(result)
|
|
793
|
+
|
|
794
|
+
if (result.skipped) {
|
|
795
|
+
migrationsSkipped++
|
|
796
|
+
} else if (result.success) {
|
|
797
|
+
migrationsRun++
|
|
798
|
+
} else {
|
|
799
|
+
break
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
const durationMs = Math.round(performance.now() - startTime)
|
|
804
|
+
const endVersion = (await this.getSchemaVersion()).currentVersion
|
|
805
|
+
|
|
806
|
+
return {
|
|
807
|
+
success: results.every((r) => r.success),
|
|
808
|
+
fromVersion: startVersion,
|
|
809
|
+
toVersion: endVersion,
|
|
810
|
+
durationMs,
|
|
811
|
+
results,
|
|
812
|
+
migrationsRun,
|
|
813
|
+
migrationsSkipped,
|
|
814
|
+
}
|
|
815
|
+
} finally {
|
|
816
|
+
await this.releaseLock()
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Check if a migration is reversible
|
|
822
|
+
*
|
|
823
|
+
* A migration is reversible if:
|
|
824
|
+
* 1. It has down SQL defined
|
|
825
|
+
* 2. isReversible is not explicitly set to false
|
|
826
|
+
*/
|
|
827
|
+
isReversible(migration: Migration): boolean {
|
|
828
|
+
if (!migration.down) {
|
|
829
|
+
return false
|
|
830
|
+
}
|
|
831
|
+
// If isReversible is explicitly set, use that value
|
|
832
|
+
// Otherwise, default to true if down SQL exists
|
|
833
|
+
return migration.isReversible !== false
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* Record a rollback in the history table
|
|
838
|
+
*/
|
|
839
|
+
private async recordRollbackHistory(
|
|
840
|
+
rollbackId: string,
|
|
841
|
+
migration: Migration,
|
|
842
|
+
previousStatus: string,
|
|
843
|
+
executionTimeMs: number,
|
|
844
|
+
reason?: string
|
|
845
|
+
): Promise<void> {
|
|
846
|
+
try {
|
|
847
|
+
await this.executor.query(
|
|
848
|
+
`INSERT INTO ${this.getRollbackHistoryTableName()}
|
|
849
|
+
(rollback_id, migration_id, version, execution_time_ms, previous_status, reason)
|
|
850
|
+
VALUES ($1, $2, $3, $4, $5, $6)`,
|
|
851
|
+
[rollbackId, migration.id, migration.version, executionTimeMs, previousStatus, reason ?? null]
|
|
852
|
+
)
|
|
853
|
+
} catch (error) {
|
|
854
|
+
this.log('Failed to record rollback history:', error)
|
|
855
|
+
// Don't throw - history recording is non-critical
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Get rollback history
|
|
861
|
+
*/
|
|
862
|
+
async getRollbackHistory(): Promise<RollbackHistoryRecord[]> {
|
|
863
|
+
await this.initialize()
|
|
864
|
+
|
|
865
|
+
const result = await this.executor.query<RollbackHistoryRecord>(
|
|
866
|
+
`SELECT rollback_id, migration_id, version,
|
|
867
|
+
rolled_back_at::text as rolled_back_at,
|
|
868
|
+
execution_time_ms, previous_status, initiated_by, reason
|
|
869
|
+
FROM ${this.getRollbackHistoryTableName()}
|
|
870
|
+
ORDER BY rolled_back_at DESC`
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
return result.rows
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Plan a rollback operation
|
|
878
|
+
*
|
|
879
|
+
* Returns what would be rolled back without making changes.
|
|
880
|
+
* Useful for dry-run mode.
|
|
881
|
+
*/
|
|
882
|
+
async planRollback(options: RollbackOptions): Promise<{
|
|
883
|
+
migrations: Migration[]
|
|
884
|
+
blockers: Array<{ id: string; version: number; reason: string }>
|
|
885
|
+
}> {
|
|
886
|
+
await this.initialize()
|
|
887
|
+
|
|
888
|
+
const schemaVersion = await this.getSchemaVersion()
|
|
889
|
+
const { toVersion, force = false } = options
|
|
890
|
+
|
|
891
|
+
// Get migrations to rollback (in reverse order)
|
|
892
|
+
const recordsToRollback = schemaVersion.migrations
|
|
893
|
+
.filter((m) => m.status === 'applied' && m.version > toVersion)
|
|
894
|
+
.sort((a, b) => b.version - a.version)
|
|
895
|
+
|
|
896
|
+
const migrations: Migration[] = []
|
|
897
|
+
const blockers: Array<{ id: string; version: number; reason: string }> = []
|
|
898
|
+
|
|
899
|
+
for (const record of recordsToRollback) {
|
|
900
|
+
const migration = this.registry.getMigration(record.id)
|
|
901
|
+
|
|
902
|
+
if (!migration) {
|
|
903
|
+
blockers.push({
|
|
904
|
+
id: record.id,
|
|
905
|
+
version: record.version,
|
|
906
|
+
reason: 'Migration not found in registry',
|
|
907
|
+
})
|
|
908
|
+
continue
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
if (!migration.down) {
|
|
912
|
+
blockers.push({
|
|
913
|
+
id: migration.id,
|
|
914
|
+
version: migration.version,
|
|
915
|
+
reason: 'No down SQL defined',
|
|
916
|
+
})
|
|
917
|
+
if (!force) continue
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
if (!this.isReversible(migration) && !force) {
|
|
921
|
+
blockers.push({
|
|
922
|
+
id: migration.id,
|
|
923
|
+
version: migration.version,
|
|
924
|
+
reason: 'Migration marked as non-reversible',
|
|
925
|
+
})
|
|
926
|
+
continue
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
migrations.push(migration)
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
return { migrations, blockers }
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* Rollback the last migration
|
|
937
|
+
*
|
|
938
|
+
* Enhanced version with dry-run and force support.
|
|
939
|
+
*
|
|
940
|
+
* @param options Optional rollback options
|
|
941
|
+
*/
|
|
942
|
+
async rollbackLast(options: { dryRun?: boolean; force?: boolean; reason?: string } = {}): Promise<RollbackResult | null> {
|
|
943
|
+
await this.initialize()
|
|
944
|
+
|
|
945
|
+
const { dryRun = false, force = false, reason } = options
|
|
946
|
+
|
|
947
|
+
const schemaVersion = await this.getSchemaVersion()
|
|
948
|
+
const lastApplied = schemaVersion.migrations
|
|
949
|
+
.filter((m) => m.status === 'applied')
|
|
950
|
+
.sort((a, b) => b.version - a.version)[0]
|
|
951
|
+
|
|
952
|
+
if (!lastApplied) {
|
|
953
|
+
this.log('No migrations to rollback')
|
|
954
|
+
return null
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
const migration = this.registry.getMigration(lastApplied.id)
|
|
958
|
+
if (!migration) {
|
|
959
|
+
throw new MigrationError(`Migration ${lastApplied.id} not found in registry`)
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
if (!migration.down) {
|
|
963
|
+
throw new MigrationError(`Migration ${lastApplied.id} has no rollback SQL defined`)
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
if (!this.isReversible(migration) && !force) {
|
|
967
|
+
throw new MigrationError(
|
|
968
|
+
`Migration ${lastApplied.id} is marked as non-reversible. Use force=true to override.`
|
|
969
|
+
)
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// Dry run - return what would happen without making changes
|
|
973
|
+
if (dryRun) {
|
|
974
|
+
return {
|
|
975
|
+
success: true,
|
|
976
|
+
id: migration.id,
|
|
977
|
+
version: migration.version,
|
|
978
|
+
executionTimeMs: 0,
|
|
979
|
+
isDryRun: true,
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
const lockAcquired = await this.acquireLock()
|
|
984
|
+
if (!lockAcquired) {
|
|
985
|
+
throw new MigrationError('Failed to acquire migration lock')
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
const rollbackId = generateRollbackId()
|
|
989
|
+
const startTime = performance.now()
|
|
990
|
+
|
|
991
|
+
try {
|
|
992
|
+
await this.emitRollbackEvent({
|
|
993
|
+
type: 'rollback_started',
|
|
994
|
+
migration,
|
|
995
|
+
})
|
|
996
|
+
|
|
997
|
+
// Execute rollback
|
|
998
|
+
await this.executor.query('BEGIN')
|
|
999
|
+
|
|
1000
|
+
try {
|
|
1001
|
+
await this.executor.query(migration.down)
|
|
1002
|
+
|
|
1003
|
+
// Update migration status
|
|
1004
|
+
await this.executor.query(
|
|
1005
|
+
`UPDATE ${this.getTableName()}
|
|
1006
|
+
SET status = 'rolled_back', applied_at = CURRENT_TIMESTAMP
|
|
1007
|
+
WHERE id = $1`,
|
|
1008
|
+
[migration.id]
|
|
1009
|
+
)
|
|
1010
|
+
|
|
1011
|
+
await this.executor.query('COMMIT')
|
|
1012
|
+
|
|
1013
|
+
const executionTimeMs = Math.round(performance.now() - startTime)
|
|
1014
|
+
|
|
1015
|
+
// Record in history
|
|
1016
|
+
await this.recordRollbackHistory(
|
|
1017
|
+
rollbackId,
|
|
1018
|
+
migration,
|
|
1019
|
+
lastApplied.status,
|
|
1020
|
+
executionTimeMs,
|
|
1021
|
+
reason
|
|
1022
|
+
)
|
|
1023
|
+
|
|
1024
|
+
const result: RollbackResult = {
|
|
1025
|
+
success: true,
|
|
1026
|
+
id: migration.id,
|
|
1027
|
+
version: migration.version,
|
|
1028
|
+
executionTimeMs,
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
await this.emitEvent({
|
|
1032
|
+
type: 'migration_rolled_back',
|
|
1033
|
+
migration,
|
|
1034
|
+
})
|
|
1035
|
+
|
|
1036
|
+
await this.emitRollbackEvent({
|
|
1037
|
+
type: 'rollback_completed',
|
|
1038
|
+
migration,
|
|
1039
|
+
result,
|
|
1040
|
+
})
|
|
1041
|
+
|
|
1042
|
+
this.log(`Rolled back migration ${migration.id} in ${executionTimeMs}ms`)
|
|
1043
|
+
|
|
1044
|
+
return result
|
|
1045
|
+
} catch (error) {
|
|
1046
|
+
await this.executor.query('ROLLBACK')
|
|
1047
|
+
|
|
1048
|
+
const executionTimeMs = Math.round(performance.now() - startTime)
|
|
1049
|
+
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
1050
|
+
|
|
1051
|
+
const result: RollbackResult = {
|
|
1052
|
+
success: false,
|
|
1053
|
+
id: migration.id,
|
|
1054
|
+
version: migration.version,
|
|
1055
|
+
executionTimeMs,
|
|
1056
|
+
error: errorMessage,
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
await this.emitRollbackEvent({
|
|
1060
|
+
type: 'rollback_failed',
|
|
1061
|
+
migration,
|
|
1062
|
+
result,
|
|
1063
|
+
error: error instanceof Error ? error : new Error(errorMessage),
|
|
1064
|
+
})
|
|
1065
|
+
|
|
1066
|
+
throw new MigrationError(
|
|
1067
|
+
`Rollback failed for migration ${migration.id}: ${errorMessage}`,
|
|
1068
|
+
{
|
|
1069
|
+
migrationId: migration.id,
|
|
1070
|
+
phase: 'rollback',
|
|
1071
|
+
cause: error instanceof Error ? error : undefined,
|
|
1072
|
+
}
|
|
1073
|
+
)
|
|
1074
|
+
}
|
|
1075
|
+
} finally {
|
|
1076
|
+
await this.releaseLock()
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* Rollback to a specific version
|
|
1082
|
+
*
|
|
1083
|
+
* Enhanced version with dry-run, force mode, and comprehensive error handling.
|
|
1084
|
+
* Rolls back all migrations after the specified version in reverse order.
|
|
1085
|
+
*
|
|
1086
|
+
* @param options Rollback options including target version, dry-run, and force flags
|
|
1087
|
+
*/
|
|
1088
|
+
async rollback(options: RollbackOptions): Promise<BatchRollbackResult> {
|
|
1089
|
+
await this.initialize()
|
|
1090
|
+
|
|
1091
|
+
const { toVersion, dryRun = false, force = false, onProgress } = options
|
|
1092
|
+
|
|
1093
|
+
const lockAcquired = await this.acquireLock()
|
|
1094
|
+
if (!lockAcquired) {
|
|
1095
|
+
throw new MigrationError('Failed to acquire migration lock')
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
try {
|
|
1099
|
+
const schemaVersion = await this.getSchemaVersion()
|
|
1100
|
+
const startVersion = schemaVersion.currentVersion
|
|
1101
|
+
const startTime = performance.now()
|
|
1102
|
+
|
|
1103
|
+
// Already at or below target version
|
|
1104
|
+
if (startVersion <= toVersion) {
|
|
1105
|
+
return {
|
|
1106
|
+
success: true,
|
|
1107
|
+
fromVersion: startVersion,
|
|
1108
|
+
toVersion: startVersion,
|
|
1109
|
+
durationMs: 0,
|
|
1110
|
+
results: [],
|
|
1111
|
+
rolledBackCount: 0,
|
|
1112
|
+
skippedCount: 0,
|
|
1113
|
+
isDryRun: dryRun,
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
// Plan the rollback
|
|
1118
|
+
const { migrations: migrationsToRollback, blockers } = await this.planRollback(options)
|
|
1119
|
+
|
|
1120
|
+
// If there are blockers and not forcing, report them
|
|
1121
|
+
if (blockers.length > 0 && !force) {
|
|
1122
|
+
return {
|
|
1123
|
+
success: false,
|
|
1124
|
+
fromVersion: startVersion,
|
|
1125
|
+
toVersion: startVersion,
|
|
1126
|
+
durationMs: 0,
|
|
1127
|
+
results: [],
|
|
1128
|
+
rolledBackCount: 0,
|
|
1129
|
+
skippedCount: blockers.length,
|
|
1130
|
+
isDryRun: dryRun,
|
|
1131
|
+
blockedBy: blockers,
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
await this.emitRollbackEvent({
|
|
1136
|
+
type: 'batch_rollback_started',
|
|
1137
|
+
options,
|
|
1138
|
+
metadata: {
|
|
1139
|
+
count: migrationsToRollback.length,
|
|
1140
|
+
versions: migrationsToRollback.map((m) => m.version),
|
|
1141
|
+
},
|
|
1142
|
+
})
|
|
1143
|
+
|
|
1144
|
+
const results: RollbackResult[] = []
|
|
1145
|
+
let rolledBackCount = 0
|
|
1146
|
+
let skippedCount = 0
|
|
1147
|
+
const rollbackId = generateRollbackId()
|
|
1148
|
+
|
|
1149
|
+
for (let i = 0; i < migrationsToRollback.length; i++) {
|
|
1150
|
+
const migration = migrationsToRollback[i]
|
|
1151
|
+
if (!migration) continue
|
|
1152
|
+
|
|
1153
|
+
const record = schemaVersion.migrations.find((m) => m.id === migration.id)
|
|
1154
|
+
|
|
1155
|
+
// Emit progress
|
|
1156
|
+
onProgress?.({
|
|
1157
|
+
migration,
|
|
1158
|
+
index: i,
|
|
1159
|
+
total: migrationsToRollback.length,
|
|
1160
|
+
phase: 'starting',
|
|
1161
|
+
isDryRun: dryRun,
|
|
1162
|
+
})
|
|
1163
|
+
|
|
1164
|
+
// Check if migration can be rolled back
|
|
1165
|
+
if (!migration.down) {
|
|
1166
|
+
const result: RollbackResult = {
|
|
1167
|
+
success: false,
|
|
1168
|
+
id: migration.id,
|
|
1169
|
+
version: migration.version,
|
|
1170
|
+
executionTimeMs: 0,
|
|
1171
|
+
skipped: true,
|
|
1172
|
+
skipReason: 'no_down_sql',
|
|
1173
|
+
}
|
|
1174
|
+
results.push(result)
|
|
1175
|
+
skippedCount++
|
|
1176
|
+
|
|
1177
|
+
onProgress?.({
|
|
1178
|
+
migration,
|
|
1179
|
+
index: i,
|
|
1180
|
+
total: migrationsToRollback.length,
|
|
1181
|
+
phase: 'skipped',
|
|
1182
|
+
isDryRun: dryRun,
|
|
1183
|
+
})
|
|
1184
|
+
|
|
1185
|
+
await this.emitRollbackEvent({
|
|
1186
|
+
type: 'rollback_skipped',
|
|
1187
|
+
migration,
|
|
1188
|
+
result,
|
|
1189
|
+
})
|
|
1190
|
+
|
|
1191
|
+
if (!force) {
|
|
1192
|
+
// Stop on non-reversible migration unless forcing
|
|
1193
|
+
break
|
|
1194
|
+
}
|
|
1195
|
+
continue
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
if (!this.isReversible(migration) && !force) {
|
|
1199
|
+
const result: RollbackResult = {
|
|
1200
|
+
success: false,
|
|
1201
|
+
id: migration.id,
|
|
1202
|
+
version: migration.version,
|
|
1203
|
+
executionTimeMs: 0,
|
|
1204
|
+
skipped: true,
|
|
1205
|
+
skipReason: 'non_reversible',
|
|
1206
|
+
}
|
|
1207
|
+
results.push(result)
|
|
1208
|
+
skippedCount++
|
|
1209
|
+
|
|
1210
|
+
onProgress?.({
|
|
1211
|
+
migration,
|
|
1212
|
+
index: i,
|
|
1213
|
+
total: migrationsToRollback.length,
|
|
1214
|
+
phase: 'skipped',
|
|
1215
|
+
isDryRun: dryRun,
|
|
1216
|
+
})
|
|
1217
|
+
|
|
1218
|
+
await this.emitRollbackEvent({
|
|
1219
|
+
type: 'rollback_skipped',
|
|
1220
|
+
migration,
|
|
1221
|
+
result,
|
|
1222
|
+
})
|
|
1223
|
+
|
|
1224
|
+
break
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// Dry run - just record what would happen
|
|
1228
|
+
if (dryRun) {
|
|
1229
|
+
const result: RollbackResult = {
|
|
1230
|
+
success: true,
|
|
1231
|
+
id: migration.id,
|
|
1232
|
+
version: migration.version,
|
|
1233
|
+
executionTimeMs: 0,
|
|
1234
|
+
isDryRun: true,
|
|
1235
|
+
}
|
|
1236
|
+
results.push(result)
|
|
1237
|
+
rolledBackCount++
|
|
1238
|
+
|
|
1239
|
+
onProgress?.({
|
|
1240
|
+
migration,
|
|
1241
|
+
index: i,
|
|
1242
|
+
total: migrationsToRollback.length,
|
|
1243
|
+
phase: 'completed',
|
|
1244
|
+
durationMs: 0,
|
|
1245
|
+
isDryRun: true,
|
|
1246
|
+
})
|
|
1247
|
+
|
|
1248
|
+
continue
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
// Execute the rollback
|
|
1252
|
+
const migrationStartTime = performance.now()
|
|
1253
|
+
|
|
1254
|
+
onProgress?.({
|
|
1255
|
+
migration,
|
|
1256
|
+
index: i,
|
|
1257
|
+
total: migrationsToRollback.length,
|
|
1258
|
+
phase: 'executing',
|
|
1259
|
+
isDryRun: false,
|
|
1260
|
+
})
|
|
1261
|
+
|
|
1262
|
+
try {
|
|
1263
|
+
await this.executor.query('BEGIN')
|
|
1264
|
+
await this.executor.query(migration.down)
|
|
1265
|
+
await this.executor.query(
|
|
1266
|
+
`UPDATE ${this.getTableName()}
|
|
1267
|
+
SET status = 'rolled_back', applied_at = CURRENT_TIMESTAMP
|
|
1268
|
+
WHERE id = $1`,
|
|
1269
|
+
[migration.id]
|
|
1270
|
+
)
|
|
1271
|
+
await this.executor.query('COMMIT')
|
|
1272
|
+
|
|
1273
|
+
const executionTimeMs = Math.round(performance.now() - migrationStartTime)
|
|
1274
|
+
|
|
1275
|
+
// Record in history
|
|
1276
|
+
await this.recordRollbackHistory(
|
|
1277
|
+
rollbackId,
|
|
1278
|
+
migration,
|
|
1279
|
+
record?.status ?? 'applied',
|
|
1280
|
+
executionTimeMs
|
|
1281
|
+
)
|
|
1282
|
+
|
|
1283
|
+
const result: RollbackResult = {
|
|
1284
|
+
success: true,
|
|
1285
|
+
id: migration.id,
|
|
1286
|
+
version: migration.version,
|
|
1287
|
+
executionTimeMs,
|
|
1288
|
+
}
|
|
1289
|
+
results.push(result)
|
|
1290
|
+
rolledBackCount++
|
|
1291
|
+
|
|
1292
|
+
onProgress?.({
|
|
1293
|
+
migration,
|
|
1294
|
+
index: i,
|
|
1295
|
+
total: migrationsToRollback.length,
|
|
1296
|
+
phase: 'completed',
|
|
1297
|
+
durationMs: executionTimeMs,
|
|
1298
|
+
isDryRun: false,
|
|
1299
|
+
})
|
|
1300
|
+
|
|
1301
|
+
await this.emitEvent({
|
|
1302
|
+
type: 'migration_rolled_back',
|
|
1303
|
+
migration,
|
|
1304
|
+
})
|
|
1305
|
+
|
|
1306
|
+
await this.emitRollbackEvent({
|
|
1307
|
+
type: 'rollback_completed',
|
|
1308
|
+
migration,
|
|
1309
|
+
result,
|
|
1310
|
+
})
|
|
1311
|
+
|
|
1312
|
+
this.log(`Rolled back migration ${migration.id} in ${executionTimeMs}ms`)
|
|
1313
|
+
} catch (error) {
|
|
1314
|
+
try {
|
|
1315
|
+
await this.executor.query('ROLLBACK')
|
|
1316
|
+
} catch {
|
|
1317
|
+
// Ignore rollback errors
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
const executionTimeMs = Math.round(performance.now() - migrationStartTime)
|
|
1321
|
+
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
1322
|
+
|
|
1323
|
+
const result: RollbackResult = {
|
|
1324
|
+
success: false,
|
|
1325
|
+
id: migration.id,
|
|
1326
|
+
version: migration.version,
|
|
1327
|
+
executionTimeMs,
|
|
1328
|
+
error: errorMessage,
|
|
1329
|
+
}
|
|
1330
|
+
results.push(result)
|
|
1331
|
+
|
|
1332
|
+
onProgress?.({
|
|
1333
|
+
migration,
|
|
1334
|
+
index: i,
|
|
1335
|
+
total: migrationsToRollback.length,
|
|
1336
|
+
phase: 'failed',
|
|
1337
|
+
durationMs: executionTimeMs,
|
|
1338
|
+
error: errorMessage,
|
|
1339
|
+
isDryRun: false,
|
|
1340
|
+
})
|
|
1341
|
+
|
|
1342
|
+
await this.emitRollbackEvent({
|
|
1343
|
+
type: 'rollback_failed',
|
|
1344
|
+
migration,
|
|
1345
|
+
result,
|
|
1346
|
+
error: error instanceof Error ? error : new Error(errorMessage),
|
|
1347
|
+
})
|
|
1348
|
+
|
|
1349
|
+
this.log(`Rollback failed for ${migration.id}:`, errorMessage)
|
|
1350
|
+
|
|
1351
|
+
// Stop on failure
|
|
1352
|
+
break
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
const durationMs = Math.round(performance.now() - startTime)
|
|
1357
|
+
const endVersion = dryRun
|
|
1358
|
+
? toVersion
|
|
1359
|
+
: (await this.getSchemaVersion()).currentVersion
|
|
1360
|
+
|
|
1361
|
+
const success = results.every((r) => r.success || r.skipped)
|
|
1362
|
+
|
|
1363
|
+
const batchResult: BatchRollbackResult = {
|
|
1364
|
+
success,
|
|
1365
|
+
fromVersion: startVersion,
|
|
1366
|
+
toVersion: endVersion,
|
|
1367
|
+
durationMs,
|
|
1368
|
+
results,
|
|
1369
|
+
rolledBackCount,
|
|
1370
|
+
skippedCount,
|
|
1371
|
+
isDryRun: dryRun,
|
|
1372
|
+
...(blockers.length > 0 && { blockedBy: blockers }),
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
await this.emitRollbackEvent({
|
|
1376
|
+
type: success ? 'batch_rollback_completed' : 'batch_rollback_failed',
|
|
1377
|
+
batchResult,
|
|
1378
|
+
options,
|
|
1379
|
+
})
|
|
1380
|
+
|
|
1381
|
+
return batchResult
|
|
1382
|
+
} finally {
|
|
1383
|
+
await this.releaseLock()
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
/**
|
|
1388
|
+
* Rollback to a specific version (legacy API)
|
|
1389
|
+
*
|
|
1390
|
+
* @deprecated Use rollback() instead for more options
|
|
1391
|
+
*/
|
|
1392
|
+
async rollbackToVersion(targetVersion: number): Promise<BatchMigrationResult> {
|
|
1393
|
+
const result = await this.rollback({ toVersion: targetVersion })
|
|
1394
|
+
|
|
1395
|
+
// Convert BatchRollbackResult to BatchMigrationResult for backwards compatibility
|
|
1396
|
+
return {
|
|
1397
|
+
success: result.success,
|
|
1398
|
+
fromVersion: result.fromVersion,
|
|
1399
|
+
toVersion: result.toVersion,
|
|
1400
|
+
durationMs: result.durationMs,
|
|
1401
|
+
results: result.results.map((r) => ({
|
|
1402
|
+
success: r.success,
|
|
1403
|
+
id: r.id,
|
|
1404
|
+
executionTimeMs: r.executionTimeMs,
|
|
1405
|
+
error: r.error,
|
|
1406
|
+
skipped: r.skipped,
|
|
1407
|
+
})),
|
|
1408
|
+
migrationsRun: result.rolledBackCount,
|
|
1409
|
+
migrationsSkipped: result.skippedCount,
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
/**
|
|
1414
|
+
* Reset all migrations
|
|
1415
|
+
*
|
|
1416
|
+
* Drops the migrations table and all tracked migrations.
|
|
1417
|
+
* USE WITH CAUTION - this doesn't undo the schema changes!
|
|
1418
|
+
*/
|
|
1419
|
+
async reset(): Promise<void> {
|
|
1420
|
+
this.log('Resetting migrations table')
|
|
1421
|
+
await this.executor.query(`DROP TABLE IF EXISTS ${this.getTableName()} CASCADE`)
|
|
1422
|
+
this.initialized = false
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
/**
|
|
1426
|
+
* Check if the runner has been initialized
|
|
1427
|
+
*/
|
|
1428
|
+
isInitialized(): boolean {
|
|
1429
|
+
return this.initialized
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
/**
|
|
1433
|
+
* Get the registry
|
|
1434
|
+
*/
|
|
1435
|
+
getRegistry(): MigrationRegistry {
|
|
1436
|
+
return this.registry
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
/**
|
|
1441
|
+
* Create a migration runner
|
|
1442
|
+
*
|
|
1443
|
+
* @example
|
|
1444
|
+
* ```typescript
|
|
1445
|
+
* const runner = createMigrationRunner(pglite, registry, {
|
|
1446
|
+
* debug: true,
|
|
1447
|
+
* onProgress: (event) => console.log(event),
|
|
1448
|
+
* })
|
|
1449
|
+
*
|
|
1450
|
+
* await runner.migrate()
|
|
1451
|
+
* ```
|
|
1452
|
+
*/
|
|
1453
|
+
export function createMigrationRunner(
|
|
1454
|
+
executor: QueryExecutor,
|
|
1455
|
+
registry: MigrationRegistry,
|
|
1456
|
+
config: MigrationRunnerConfig = {}
|
|
1457
|
+
): MigrationRunner {
|
|
1458
|
+
return new MigrationRunner(executor, registry, config)
|
|
1459
|
+
}
|