@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,1236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RED PHASE: PostgresDO Decomposition Tests
|
|
3
|
+
* Task: postgres-an18.1 - [RED] Add tests for decomposed concerns
|
|
4
|
+
*
|
|
5
|
+
* These tests define the expected architecture for decomposed concerns.
|
|
6
|
+
* Tests will fail until the decomposition is complete (GREEN phase).
|
|
7
|
+
*
|
|
8
|
+
* The PostgresDO class currently has multiple concerns mixed together.
|
|
9
|
+
* After decomposition, each concern should be:
|
|
10
|
+
* 1. Independently testable
|
|
11
|
+
* 2. Independently instantiable (without DO context)
|
|
12
|
+
* 3. Composable through dependency injection
|
|
13
|
+
* 4. Single responsibility
|
|
14
|
+
*
|
|
15
|
+
* Expected Architecture After Decomposition:
|
|
16
|
+
* ==========================================
|
|
17
|
+
*
|
|
18
|
+
* PostgresDO (Orchestrator)
|
|
19
|
+
* |-- DOAuthConcern (authentication handling)
|
|
20
|
+
* |-- QueryExecutionConcern (query execution & transformation)
|
|
21
|
+
* |-- CDCConcern (change data capture & WAL)
|
|
22
|
+
* |-- StorageOrchestrationConcern (tiered storage management)
|
|
23
|
+
*
|
|
24
|
+
* Each concern should implement a well-defined interface and be
|
|
25
|
+
* injectable into PostgresDO for testing and modularity.
|
|
26
|
+
*/
|
|
27
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
28
|
+
import {
|
|
29
|
+
createMockPGlite,
|
|
30
|
+
createMockDurableObjectState,
|
|
31
|
+
} from '../__tests__/utils'
|
|
32
|
+
|
|
33
|
+
// Mock cloudflare:workers before importing modules that depend on it
|
|
34
|
+
vi.mock('cloudflare:workers', () => ({
|
|
35
|
+
DurableObject: class DurableObject {
|
|
36
|
+
ctx: unknown
|
|
37
|
+
env: unknown
|
|
38
|
+
constructor(ctx: unknown, env: unknown) {
|
|
39
|
+
this.ctx = ctx
|
|
40
|
+
this.env = env
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
}))
|
|
44
|
+
|
|
45
|
+
// Mock WASM and data imports that Vite can't handle in test environment
|
|
46
|
+
vi.mock('../pglite-assets/pglite.wasm', () => ({ default: {} }))
|
|
47
|
+
vi.mock('../pglite-assets/pglite.data', () => ({ default: {} }))
|
|
48
|
+
|
|
49
|
+
// Mock the workers-pglite module to avoid WASM dependencies
|
|
50
|
+
vi.mock('../pglite/workers-pglite', () => ({
|
|
51
|
+
createWorkersPGLite: vi.fn(),
|
|
52
|
+
WorkersPGLite: class {},
|
|
53
|
+
}))
|
|
54
|
+
|
|
55
|
+
import type { Env, PostgresConfig } from './types'
|
|
56
|
+
|
|
57
|
+
// Local wrapper to match existing test expectations (uses shared utility)
|
|
58
|
+
const createMockState = () => createMockDurableObjectState({
|
|
59
|
+
id: 'test-do-id',
|
|
60
|
+
name: 'test-database',
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// Mock Env
|
|
64
|
+
const createMockEnv = (): Env => ({
|
|
65
|
+
POSTGRES_DO: {} as DurableObjectNamespace,
|
|
66
|
+
POSTGRES_DEFAULT_DB: 'postgres',
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// =============================================================================
|
|
70
|
+
// DECOMPOSED CONCERN INTERFACES
|
|
71
|
+
// =============================================================================
|
|
72
|
+
// These interfaces define the contract that each decomposed concern must fulfill.
|
|
73
|
+
// They serve as documentation for the expected architecture.
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Authentication Concern Interface
|
|
77
|
+
*
|
|
78
|
+
* Handles all authentication-related operations:
|
|
79
|
+
* - Token validation
|
|
80
|
+
* - User verification
|
|
81
|
+
* - Request authentication
|
|
82
|
+
* - Token caching
|
|
83
|
+
*/
|
|
84
|
+
interface IAuthConcern {
|
|
85
|
+
/** Validate a bearer token */
|
|
86
|
+
validateToken(token: string): Promise<{
|
|
87
|
+
valid: boolean
|
|
88
|
+
user?: { id: string; email?: string }
|
|
89
|
+
error?: string
|
|
90
|
+
}>
|
|
91
|
+
/** Authenticate a request and return user or throw */
|
|
92
|
+
authenticateRequest(request: Request): Promise<{ id: string; email?: string } | null>
|
|
93
|
+
/** Check if authentication is enabled */
|
|
94
|
+
isEnabled(): boolean
|
|
95
|
+
/** Set user ID for user-scoped databases */
|
|
96
|
+
setUserId(userId: string): void
|
|
97
|
+
/** Get configured user ID */
|
|
98
|
+
getUserId(): string | undefined
|
|
99
|
+
/** Clear the token cache */
|
|
100
|
+
clearCache(): void
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Query Execution Concern Interface
|
|
105
|
+
*
|
|
106
|
+
* Handles all query execution operations:
|
|
107
|
+
* - Single query execution
|
|
108
|
+
* - Batch query execution
|
|
109
|
+
* - SQL transformation (case preservation)
|
|
110
|
+
* - Query statistics
|
|
111
|
+
*/
|
|
112
|
+
interface IQueryExecutionConcern {
|
|
113
|
+
/** Execute a single query */
|
|
114
|
+
executeQuery<T>(request: {
|
|
115
|
+
sql: string
|
|
116
|
+
params?: unknown[]
|
|
117
|
+
preserveCase?: boolean
|
|
118
|
+
}): Promise<{
|
|
119
|
+
rows: T[]
|
|
120
|
+
fields: { name: string; dataTypeID: number }[]
|
|
121
|
+
rowCount: number
|
|
122
|
+
durationMs: number
|
|
123
|
+
}>
|
|
124
|
+
/** Execute a batch of queries */
|
|
125
|
+
executeBatch(request: {
|
|
126
|
+
queries: Array<{ sql: string; params?: unknown[] }>
|
|
127
|
+
transaction?: boolean
|
|
128
|
+
}): Promise<{
|
|
129
|
+
results: Array<{
|
|
130
|
+
rows: unknown[]
|
|
131
|
+
fields: { name: string; dataTypeID: number }[]
|
|
132
|
+
rowCount: number
|
|
133
|
+
durationMs: number
|
|
134
|
+
}>
|
|
135
|
+
durationMs: number
|
|
136
|
+
}>
|
|
137
|
+
/** Get query statistics */
|
|
138
|
+
getStats(): {
|
|
139
|
+
queryCount: number
|
|
140
|
+
successCount: number
|
|
141
|
+
errorCount: number
|
|
142
|
+
totalDurationMs: number
|
|
143
|
+
avgDurationMs: number
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* CDC (Change Data Capture) Concern Interface
|
|
149
|
+
*
|
|
150
|
+
* Handles all change data capture operations:
|
|
151
|
+
* - WAL entry capture
|
|
152
|
+
* - WAL buffer management
|
|
153
|
+
* - Change event broadcasting
|
|
154
|
+
* - Replication state tracking
|
|
155
|
+
*/
|
|
156
|
+
interface ICDCConcern {
|
|
157
|
+
/** Check if CDC/WAL is enabled */
|
|
158
|
+
isEnabled(): boolean
|
|
159
|
+
/** Enable/disable CDC */
|
|
160
|
+
setEnabled(enabled: boolean): void
|
|
161
|
+
/** Capture a write operation */
|
|
162
|
+
captureChange(operation: {
|
|
163
|
+
sql: string
|
|
164
|
+
table: string
|
|
165
|
+
operation: 'INSERT' | 'UPDATE' | 'DELETE'
|
|
166
|
+
oldRow?: Record<string, unknown>
|
|
167
|
+
newRow?: Record<string, unknown>
|
|
168
|
+
}): { lsn: bigint; timestamp: number } | null
|
|
169
|
+
/** Get current LSN (Log Sequence Number) */
|
|
170
|
+
getCurrentLsn(): bigint
|
|
171
|
+
/** Flush buffered changes to storage */
|
|
172
|
+
flush(): Promise<{ entriesFlushed: number; newLsn: bigint }>
|
|
173
|
+
/** Read entries from storage since a given LSN */
|
|
174
|
+
readEntries(fromLsn: bigint, limit?: number): Promise<Array<{
|
|
175
|
+
lsn: bigint
|
|
176
|
+
table: string
|
|
177
|
+
operation: string
|
|
178
|
+
timestamp: number
|
|
179
|
+
}>>
|
|
180
|
+
/** Add listener for change events */
|
|
181
|
+
onEntry(listener: (entry: { lsn: bigint; table: string; operation: string }) => void): () => void
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Storage Orchestration Concern Interface
|
|
186
|
+
*
|
|
187
|
+
* Handles tiered storage management:
|
|
188
|
+
* - Hot/warm/cold tier coordination
|
|
189
|
+
* - Page promotion/demotion
|
|
190
|
+
* - Storage statistics
|
|
191
|
+
* - Health monitoring
|
|
192
|
+
*/
|
|
193
|
+
interface IStorageOrchestrationConcern {
|
|
194
|
+
/** Read a page from the best available tier */
|
|
195
|
+
read(key: string): Promise<Uint8Array | null>
|
|
196
|
+
/** Write a page to the appropriate tier */
|
|
197
|
+
write(key: string, data: Uint8Array, options?: { tier?: 'hot' | 'warm' | 'cold' }): Promise<void>
|
|
198
|
+
/** Delete a page from all tiers */
|
|
199
|
+
delete(key: string): Promise<void>
|
|
200
|
+
/** Get the current tier of a page */
|
|
201
|
+
getTier(key: string): 'hot' | 'warm' | 'cold' | null
|
|
202
|
+
/** Promote a page to a hotter tier */
|
|
203
|
+
promote(key: string, targetTier: 'hot' | 'warm'): Promise<void>
|
|
204
|
+
/** Demote a page to a colder tier */
|
|
205
|
+
demote(key: string, targetTier: 'warm' | 'cold'): Promise<void>
|
|
206
|
+
/** Get storage statistics */
|
|
207
|
+
getStats(): {
|
|
208
|
+
hotSize: number
|
|
209
|
+
warmSize: number
|
|
210
|
+
coldSize: number
|
|
211
|
+
hitRate: number
|
|
212
|
+
promotions: number
|
|
213
|
+
demotions: number
|
|
214
|
+
}
|
|
215
|
+
/** Check tier health */
|
|
216
|
+
getTierHealth(tier: 'hot' | 'warm' | 'cold'): {
|
|
217
|
+
healthy: boolean
|
|
218
|
+
lastError?: string
|
|
219
|
+
latencyMs?: number
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// =============================================================================
|
|
224
|
+
// TEST: AUTHENTICATION CONCERN ISOLATION
|
|
225
|
+
// =============================================================================
|
|
226
|
+
|
|
227
|
+
describe('Authentication Concern Decomposition', () => {
|
|
228
|
+
describe('Independent Instantiation', () => {
|
|
229
|
+
it('should be creatable without PostgresDO context', async () => {
|
|
230
|
+
// RED: This test will fail until we export a standalone AuthConcern class
|
|
231
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
232
|
+
|
|
233
|
+
const concern = new AuthConcern({
|
|
234
|
+
enabled: true,
|
|
235
|
+
oauthUrl: 'https://oauth.do',
|
|
236
|
+
tokenCacheTTL: 60000,
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
expect(concern).toBeDefined()
|
|
240
|
+
expect(concern.isEnabled()).toBe(true)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it('should work with custom token validator', async () => {
|
|
244
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
245
|
+
|
|
246
|
+
const customValidator = vi.fn().mockResolvedValue({
|
|
247
|
+
valid: true,
|
|
248
|
+
user: { id: 'user-123', email: 'test@example.com' },
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
const concern = new AuthConcern({
|
|
252
|
+
enabled: true,
|
|
253
|
+
validateToken: customValidator,
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
const result = await concern.validateToken('test-token')
|
|
257
|
+
|
|
258
|
+
expect(customValidator).toHaveBeenCalledWith('test-token')
|
|
259
|
+
expect(result.valid).toBe(true)
|
|
260
|
+
expect(result.user?.id).toBe('user-123')
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
it('should be injectable into PostgresDO', async () => {
|
|
264
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
265
|
+
const { PostgresDO } = await import('./do')
|
|
266
|
+
|
|
267
|
+
const mockAuthConcern = new AuthConcern({
|
|
268
|
+
enabled: true,
|
|
269
|
+
validateToken: vi.fn().mockResolvedValue({
|
|
270
|
+
valid: true,
|
|
271
|
+
user: { id: 'injected-user' },
|
|
272
|
+
}),
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
const state = createMockState()
|
|
276
|
+
const env = createMockEnv()
|
|
277
|
+
|
|
278
|
+
// RED: PostgresDO should accept injected concerns
|
|
279
|
+
const doo = new PostgresDO(state as any, env, {
|
|
280
|
+
database: 'test',
|
|
281
|
+
concerns: {
|
|
282
|
+
auth: mockAuthConcern,
|
|
283
|
+
},
|
|
284
|
+
} as PostgresConfig)
|
|
285
|
+
|
|
286
|
+
// The injected concern should be used
|
|
287
|
+
const user = await doo.authenticateRequest(
|
|
288
|
+
new Request('http://test.com', {
|
|
289
|
+
headers: { Authorization: 'Bearer test-token' },
|
|
290
|
+
})
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
expect(user?.id).toBe('injected-user')
|
|
294
|
+
})
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
describe('Interface Compliance', () => {
|
|
298
|
+
it('should implement IAuthConcern interface', async () => {
|
|
299
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
300
|
+
|
|
301
|
+
const concern = new AuthConcern({ enabled: true })
|
|
302
|
+
|
|
303
|
+
// Verify all interface methods exist
|
|
304
|
+
expect(typeof concern.validateToken).toBe('function')
|
|
305
|
+
expect(typeof concern.authenticateRequest).toBe('function')
|
|
306
|
+
expect(typeof concern.isEnabled).toBe('function')
|
|
307
|
+
expect(typeof concern.setUserId).toBe('function')
|
|
308
|
+
expect(typeof concern.getUserId).toBe('function')
|
|
309
|
+
expect(typeof concern.clearCache).toBe('function')
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
it('should maintain user ID state independently', async () => {
|
|
313
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
314
|
+
|
|
315
|
+
const concern = new AuthConcern({ enabled: true })
|
|
316
|
+
|
|
317
|
+
expect(concern.getUserId()).toBeUndefined()
|
|
318
|
+
|
|
319
|
+
concern.setUserId('user-456')
|
|
320
|
+
expect(concern.getUserId()).toBe('user-456')
|
|
321
|
+
})
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
describe('Testability', () => {
|
|
325
|
+
it('should allow mocking token validation for tests', async () => {
|
|
326
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
327
|
+
|
|
328
|
+
const mockValidator = vi.fn()
|
|
329
|
+
.mockResolvedValueOnce({ valid: true, user: { id: 'user-1' } })
|
|
330
|
+
.mockResolvedValueOnce({ valid: false, error: 'Token expired' })
|
|
331
|
+
|
|
332
|
+
const concern = new AuthConcern({
|
|
333
|
+
enabled: true,
|
|
334
|
+
validateToken: mockValidator,
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
const result1 = await concern.validateToken('token-1')
|
|
338
|
+
expect(result1.valid).toBe(true)
|
|
339
|
+
|
|
340
|
+
const result2 = await concern.validateToken('token-2')
|
|
341
|
+
expect(result2.valid).toBe(false)
|
|
342
|
+
expect(result2.error).toBe('Token expired')
|
|
343
|
+
})
|
|
344
|
+
})
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
// =============================================================================
|
|
348
|
+
// TEST: QUERY EXECUTION CONCERN ISOLATION
|
|
349
|
+
// =============================================================================
|
|
350
|
+
|
|
351
|
+
describe('Query Execution Concern Decomposition', () => {
|
|
352
|
+
describe('Independent Instantiation', () => {
|
|
353
|
+
it('should be creatable without PostgresDO context', async () => {
|
|
354
|
+
// RED: This test will fail until we export a standalone QueryExecutionConcern
|
|
355
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
356
|
+
|
|
357
|
+
const mockPGlite = createMockPGlite()
|
|
358
|
+
mockPGlite.query.mockResolvedValue({
|
|
359
|
+
rows: [{ id: 1 }],
|
|
360
|
+
fields: [{ name: 'id', dataTypeID: 23 }],
|
|
361
|
+
affectedRows: 1,
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
const concern = new QueryExecutionConcern({
|
|
365
|
+
getPGlite: () => mockPGlite,
|
|
366
|
+
preserveCase: false,
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
expect(concern).toBeDefined()
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
it('should execute queries independently', async () => {
|
|
373
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
374
|
+
|
|
375
|
+
const mockPGlite = createMockPGlite()
|
|
376
|
+
mockPGlite.query.mockResolvedValue({
|
|
377
|
+
rows: [{ id: 1, name: 'Alice' }],
|
|
378
|
+
fields: [
|
|
379
|
+
{ name: 'id', dataTypeID: 23 },
|
|
380
|
+
{ name: 'name', dataTypeID: 25 },
|
|
381
|
+
],
|
|
382
|
+
affectedRows: 1,
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
const concern = new QueryExecutionConcern({
|
|
386
|
+
getPGlite: () => mockPGlite,
|
|
387
|
+
preserveCase: false,
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
const result = await concern.executeQuery({
|
|
391
|
+
sql: 'SELECT * FROM users WHERE id = $1',
|
|
392
|
+
params: [1],
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
expect(result.rows).toEqual([{ id: 1, name: 'Alice' }])
|
|
396
|
+
expect(result.rowCount).toBe(1)
|
|
397
|
+
expect(mockPGlite.query).toHaveBeenCalledWith(
|
|
398
|
+
'SELECT * FROM users WHERE id = $1',
|
|
399
|
+
[1]
|
|
400
|
+
)
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
it('should be injectable into PostgresDO', async () => {
|
|
404
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
405
|
+
const { PostgresDO } = await import('./do')
|
|
406
|
+
|
|
407
|
+
const mockPGlite = createMockPGlite()
|
|
408
|
+
mockPGlite.query.mockResolvedValue({
|
|
409
|
+
rows: [{ result: 42 }],
|
|
410
|
+
fields: [{ name: 'result', dataTypeID: 23 }],
|
|
411
|
+
affectedRows: 1,
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
const mockQueryConcern = new QueryExecutionConcern({
|
|
415
|
+
getPGlite: () => mockPGlite,
|
|
416
|
+
preserveCase: false,
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
const state = createMockState()
|
|
420
|
+
const env = createMockEnv()
|
|
421
|
+
|
|
422
|
+
// RED: PostgresDO should accept injected concerns
|
|
423
|
+
const doo = new PostgresDO(state as any, env, {
|
|
424
|
+
database: 'test',
|
|
425
|
+
concerns: {
|
|
426
|
+
queryExecution: mockQueryConcern,
|
|
427
|
+
},
|
|
428
|
+
} as PostgresConfig)
|
|
429
|
+
|
|
430
|
+
const result = await doo.executeQuery({ sql: 'SELECT 42' })
|
|
431
|
+
expect(result.rows).toEqual([{ result: 42 }])
|
|
432
|
+
})
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
describe('Interface Compliance', () => {
|
|
436
|
+
it('should implement IQueryExecutionConcern interface', async () => {
|
|
437
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
438
|
+
|
|
439
|
+
const mockPGlite = createMockPGlite()
|
|
440
|
+
const concern = new QueryExecutionConcern({
|
|
441
|
+
getPGlite: () => mockPGlite,
|
|
442
|
+
preserveCase: false,
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
// Verify all interface methods exist
|
|
446
|
+
expect(typeof concern.executeQuery).toBe('function')
|
|
447
|
+
expect(typeof concern.executeBatch).toBe('function')
|
|
448
|
+
expect(typeof concern.getStats).toBe('function')
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
it('should track query statistics', async () => {
|
|
452
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
453
|
+
|
|
454
|
+
const mockPGlite = createMockPGlite()
|
|
455
|
+
mockPGlite.query.mockResolvedValue({
|
|
456
|
+
rows: [],
|
|
457
|
+
fields: [],
|
|
458
|
+
affectedRows: 0,
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
const concern = new QueryExecutionConcern({
|
|
462
|
+
getPGlite: () => mockPGlite,
|
|
463
|
+
preserveCase: false,
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
await concern.executeQuery({ sql: 'SELECT 1' })
|
|
467
|
+
await concern.executeQuery({ sql: 'SELECT 2' })
|
|
468
|
+
mockPGlite.query.mockRejectedValueOnce(new Error('Syntax error'))
|
|
469
|
+
await concern.executeQuery({ sql: 'INVALID' }).catch(() => {})
|
|
470
|
+
|
|
471
|
+
const stats = concern.getStats()
|
|
472
|
+
expect(stats.queryCount).toBe(3)
|
|
473
|
+
expect(stats.successCount).toBe(2)
|
|
474
|
+
expect(stats.errorCount).toBe(1)
|
|
475
|
+
})
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
describe('SQL Transformation', () => {
|
|
479
|
+
it('should apply case preservation when configured', async () => {
|
|
480
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
481
|
+
|
|
482
|
+
const mockPGlite = createMockPGlite()
|
|
483
|
+
mockPGlite.query.mockResolvedValue({
|
|
484
|
+
rows: [],
|
|
485
|
+
fields: [],
|
|
486
|
+
affectedRows: 0,
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
const concern = new QueryExecutionConcern({
|
|
490
|
+
getPGlite: () => mockPGlite,
|
|
491
|
+
preserveCase: true,
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
await concern.executeQuery({ sql: 'SELECT userId FROM users' })
|
|
495
|
+
|
|
496
|
+
// Should have transformed to quote identifiers
|
|
497
|
+
const calledSql = mockPGlite.query.mock.calls[0]?.[0] as string
|
|
498
|
+
expect(calledSql).toContain('"userId"')
|
|
499
|
+
})
|
|
500
|
+
|
|
501
|
+
it('should allow per-query case preservation override', async () => {
|
|
502
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
503
|
+
|
|
504
|
+
const mockPGlite = createMockPGlite()
|
|
505
|
+
mockPGlite.query.mockResolvedValue({
|
|
506
|
+
rows: [],
|
|
507
|
+
fields: [],
|
|
508
|
+
affectedRows: 0,
|
|
509
|
+
})
|
|
510
|
+
|
|
511
|
+
const concern = new QueryExecutionConcern({
|
|
512
|
+
getPGlite: () => mockPGlite,
|
|
513
|
+
preserveCase: false, // Default off
|
|
514
|
+
})
|
|
515
|
+
|
|
516
|
+
// Override for this specific query
|
|
517
|
+
await concern.executeQuery({
|
|
518
|
+
sql: 'SELECT userId FROM users',
|
|
519
|
+
preserveCase: true,
|
|
520
|
+
})
|
|
521
|
+
|
|
522
|
+
const calledSql = mockPGlite.query.mock.calls[0]?.[0] as string
|
|
523
|
+
expect(calledSql).toContain('"userId"')
|
|
524
|
+
})
|
|
525
|
+
})
|
|
526
|
+
|
|
527
|
+
describe('Batch Execution', () => {
|
|
528
|
+
it('should execute batch with transaction support', async () => {
|
|
529
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
530
|
+
|
|
531
|
+
const mockPGlite = createMockPGlite()
|
|
532
|
+
const executedQueries: string[] = []
|
|
533
|
+
mockPGlite.query.mockImplementation((sql: string) => {
|
|
534
|
+
executedQueries.push(sql)
|
|
535
|
+
return Promise.resolve({ rows: [], fields: [], affectedRows: 0 })
|
|
536
|
+
})
|
|
537
|
+
|
|
538
|
+
const concern = new QueryExecutionConcern({
|
|
539
|
+
getPGlite: () => mockPGlite,
|
|
540
|
+
preserveCase: false,
|
|
541
|
+
})
|
|
542
|
+
|
|
543
|
+
await concern.executeBatch({
|
|
544
|
+
queries: [
|
|
545
|
+
{ sql: 'INSERT INTO users (name) VALUES ($1)', params: ['Alice'] },
|
|
546
|
+
{ sql: 'INSERT INTO logs (msg) VALUES ($1)', params: ['User added'] },
|
|
547
|
+
],
|
|
548
|
+
transaction: true,
|
|
549
|
+
})
|
|
550
|
+
|
|
551
|
+
expect(executedQueries[0]).toBe('BEGIN')
|
|
552
|
+
expect(executedQueries[executedQueries.length - 1]).toBe('COMMIT')
|
|
553
|
+
})
|
|
554
|
+
|
|
555
|
+
it('should rollback transaction on error', async () => {
|
|
556
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
557
|
+
|
|
558
|
+
const mockPGlite = createMockPGlite()
|
|
559
|
+
const executedQueries: string[] = []
|
|
560
|
+
mockPGlite.query.mockImplementation((sql: string) => {
|
|
561
|
+
executedQueries.push(sql)
|
|
562
|
+
if (sql.includes('INSERT INTO logs')) {
|
|
563
|
+
return Promise.reject(new Error('Constraint violation'))
|
|
564
|
+
}
|
|
565
|
+
return Promise.resolve({ rows: [], fields: [], affectedRows: 0 })
|
|
566
|
+
})
|
|
567
|
+
|
|
568
|
+
const concern = new QueryExecutionConcern({
|
|
569
|
+
getPGlite: () => mockPGlite,
|
|
570
|
+
preserveCase: false,
|
|
571
|
+
})
|
|
572
|
+
|
|
573
|
+
await expect(concern.executeBatch({
|
|
574
|
+
queries: [
|
|
575
|
+
{ sql: 'INSERT INTO users (name) VALUES ($1)', params: ['Alice'] },
|
|
576
|
+
{ sql: 'INSERT INTO logs (msg) VALUES ($1)', params: ['User added'] },
|
|
577
|
+
],
|
|
578
|
+
transaction: true,
|
|
579
|
+
})).rejects.toThrow('Constraint violation')
|
|
580
|
+
|
|
581
|
+
expect(executedQueries).toContain('ROLLBACK')
|
|
582
|
+
})
|
|
583
|
+
})
|
|
584
|
+
})
|
|
585
|
+
|
|
586
|
+
// =============================================================================
|
|
587
|
+
// TEST: CDC (CHANGE DATA CAPTURE) CONCERN ISOLATION
|
|
588
|
+
// =============================================================================
|
|
589
|
+
|
|
590
|
+
describe('CDC Concern Decomposition', () => {
|
|
591
|
+
describe('Independent Instantiation', () => {
|
|
592
|
+
it('should be creatable without PostgresDO context', async () => {
|
|
593
|
+
// RED: This test will fail until we export a standalone CDCConcern
|
|
594
|
+
const { CDCConcern } = await import('./concerns/cdc-concern')
|
|
595
|
+
|
|
596
|
+
const mockStorage = {
|
|
597
|
+
get: vi.fn(),
|
|
598
|
+
put: vi.fn(),
|
|
599
|
+
list: vi.fn().mockResolvedValue(new Map()),
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const concern = new CDCConcern({
|
|
603
|
+
storage: mockStorage,
|
|
604
|
+
enabled: true,
|
|
605
|
+
})
|
|
606
|
+
|
|
607
|
+
expect(concern).toBeDefined()
|
|
608
|
+
expect(concern.isEnabled()).toBe(true)
|
|
609
|
+
})
|
|
610
|
+
|
|
611
|
+
it('should capture changes independently', async () => {
|
|
612
|
+
const { CDCConcern } = await import('./concerns/cdc-concern')
|
|
613
|
+
|
|
614
|
+
const mockStorage = {
|
|
615
|
+
get: vi.fn(),
|
|
616
|
+
put: vi.fn(),
|
|
617
|
+
list: vi.fn().mockResolvedValue(new Map()),
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const concern = new CDCConcern({
|
|
621
|
+
storage: mockStorage,
|
|
622
|
+
enabled: true,
|
|
623
|
+
})
|
|
624
|
+
|
|
625
|
+
const result = concern.captureChange({
|
|
626
|
+
sql: 'INSERT INTO users (name) VALUES ($1)',
|
|
627
|
+
table: 'users',
|
|
628
|
+
operation: 'INSERT',
|
|
629
|
+
newRow: { id: 1, name: 'Alice' },
|
|
630
|
+
})
|
|
631
|
+
|
|
632
|
+
expect(result).not.toBeNull()
|
|
633
|
+
expect(result?.lsn).toBeGreaterThan(0n)
|
|
634
|
+
expect(typeof result?.timestamp).toBe('number')
|
|
635
|
+
})
|
|
636
|
+
|
|
637
|
+
it('should be injectable into PostgresDO', async () => {
|
|
638
|
+
const { CDCConcern } = await import('./concerns/cdc-concern')
|
|
639
|
+
const { PostgresDO } = await import('./do')
|
|
640
|
+
|
|
641
|
+
const mockStorage = {
|
|
642
|
+
get: vi.fn(),
|
|
643
|
+
put: vi.fn(),
|
|
644
|
+
list: vi.fn().mockResolvedValue(new Map()),
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
const mockCDCConcern = new CDCConcern({
|
|
648
|
+
storage: mockStorage,
|
|
649
|
+
enabled: true,
|
|
650
|
+
})
|
|
651
|
+
|
|
652
|
+
const state = createMockState()
|
|
653
|
+
const env = createMockEnv()
|
|
654
|
+
|
|
655
|
+
// RED: PostgresDO should accept injected concerns
|
|
656
|
+
const doo = new PostgresDO(state as any, env, {
|
|
657
|
+
database: 'test',
|
|
658
|
+
concerns: {
|
|
659
|
+
cdc: mockCDCConcern,
|
|
660
|
+
},
|
|
661
|
+
} as PostgresConfig)
|
|
662
|
+
|
|
663
|
+
expect(doo.isWALEnabled()).toBe(true)
|
|
664
|
+
})
|
|
665
|
+
})
|
|
666
|
+
|
|
667
|
+
describe('Interface Compliance', () => {
|
|
668
|
+
it('should implement ICDCConcern interface', async () => {
|
|
669
|
+
const { CDCConcern } = await import('./concerns/cdc-concern')
|
|
670
|
+
|
|
671
|
+
const mockStorage = {
|
|
672
|
+
get: vi.fn(),
|
|
673
|
+
put: vi.fn(),
|
|
674
|
+
list: vi.fn().mockResolvedValue(new Map()),
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
const concern = new CDCConcern({
|
|
678
|
+
storage: mockStorage,
|
|
679
|
+
enabled: true,
|
|
680
|
+
})
|
|
681
|
+
|
|
682
|
+
// Verify all interface methods exist
|
|
683
|
+
expect(typeof concern.isEnabled).toBe('function')
|
|
684
|
+
expect(typeof concern.setEnabled).toBe('function')
|
|
685
|
+
expect(typeof concern.captureChange).toBe('function')
|
|
686
|
+
expect(typeof concern.getCurrentLsn).toBe('function')
|
|
687
|
+
expect(typeof concern.flush).toBe('function')
|
|
688
|
+
expect(typeof concern.readEntries).toBe('function')
|
|
689
|
+
expect(typeof concern.onEntry).toBe('function')
|
|
690
|
+
})
|
|
691
|
+
})
|
|
692
|
+
|
|
693
|
+
describe('LSN Management', () => {
|
|
694
|
+
it('should increment LSN for each captured change', async () => {
|
|
695
|
+
const { CDCConcern } = await import('./concerns/cdc-concern')
|
|
696
|
+
|
|
697
|
+
const mockStorage = {
|
|
698
|
+
get: vi.fn(),
|
|
699
|
+
put: vi.fn(),
|
|
700
|
+
list: vi.fn().mockResolvedValue(new Map()),
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
const concern = new CDCConcern({
|
|
704
|
+
storage: mockStorage,
|
|
705
|
+
enabled: true,
|
|
706
|
+
})
|
|
707
|
+
|
|
708
|
+
const result1 = concern.captureChange({
|
|
709
|
+
sql: 'INSERT INTO users (name) VALUES ($1)',
|
|
710
|
+
table: 'users',
|
|
711
|
+
operation: 'INSERT',
|
|
712
|
+
newRow: { id: 1 },
|
|
713
|
+
})
|
|
714
|
+
|
|
715
|
+
const result2 = concern.captureChange({
|
|
716
|
+
sql: 'UPDATE users SET name = $1 WHERE id = $2',
|
|
717
|
+
table: 'users',
|
|
718
|
+
operation: 'UPDATE',
|
|
719
|
+
oldRow: { id: 1, name: 'Alice' },
|
|
720
|
+
newRow: { id: 1, name: 'Bob' },
|
|
721
|
+
})
|
|
722
|
+
|
|
723
|
+
expect(result2!.lsn).toBeGreaterThan(result1!.lsn)
|
|
724
|
+
})
|
|
725
|
+
|
|
726
|
+
it('should persist LSN to storage on flush', async () => {
|
|
727
|
+
const { CDCConcern } = await import('./concerns/cdc-concern')
|
|
728
|
+
|
|
729
|
+
const mockStorage = {
|
|
730
|
+
get: vi.fn(),
|
|
731
|
+
put: vi.fn(),
|
|
732
|
+
list: vi.fn().mockResolvedValue(new Map()),
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
const concern = new CDCConcern({
|
|
736
|
+
storage: mockStorage,
|
|
737
|
+
enabled: true,
|
|
738
|
+
})
|
|
739
|
+
|
|
740
|
+
concern.captureChange({
|
|
741
|
+
sql: 'INSERT INTO users (name) VALUES ($1)',
|
|
742
|
+
table: 'users',
|
|
743
|
+
operation: 'INSERT',
|
|
744
|
+
newRow: { id: 1 },
|
|
745
|
+
})
|
|
746
|
+
|
|
747
|
+
await concern.flush()
|
|
748
|
+
|
|
749
|
+
// Storage should have been called to persist LSN
|
|
750
|
+
expect(mockStorage.put).toHaveBeenCalled()
|
|
751
|
+
})
|
|
752
|
+
})
|
|
753
|
+
|
|
754
|
+
describe('Event Broadcasting', () => {
|
|
755
|
+
it('should notify listeners on captured changes', async () => {
|
|
756
|
+
const { CDCConcern } = await import('./concerns/cdc-concern')
|
|
757
|
+
|
|
758
|
+
const mockStorage = {
|
|
759
|
+
get: vi.fn(),
|
|
760
|
+
put: vi.fn(),
|
|
761
|
+
list: vi.fn().mockResolvedValue(new Map()),
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
const concern = new CDCConcern({
|
|
765
|
+
storage: mockStorage,
|
|
766
|
+
enabled: true,
|
|
767
|
+
})
|
|
768
|
+
|
|
769
|
+
const listener = vi.fn()
|
|
770
|
+
const unsubscribe = concern.onEntry(listener)
|
|
771
|
+
|
|
772
|
+
concern.captureChange({
|
|
773
|
+
sql: 'INSERT INTO users (name) VALUES ($1)',
|
|
774
|
+
table: 'users',
|
|
775
|
+
operation: 'INSERT',
|
|
776
|
+
newRow: { id: 1 },
|
|
777
|
+
})
|
|
778
|
+
|
|
779
|
+
expect(listener).toHaveBeenCalledWith(
|
|
780
|
+
expect.objectContaining({
|
|
781
|
+
table: 'users',
|
|
782
|
+
operation: 'INSERT',
|
|
783
|
+
})
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
// Cleanup
|
|
787
|
+
unsubscribe()
|
|
788
|
+
})
|
|
789
|
+
|
|
790
|
+
it('should allow unsubscribing from events', async () => {
|
|
791
|
+
const { CDCConcern } = await import('./concerns/cdc-concern')
|
|
792
|
+
|
|
793
|
+
const mockStorage = {
|
|
794
|
+
get: vi.fn(),
|
|
795
|
+
put: vi.fn(),
|
|
796
|
+
list: vi.fn().mockResolvedValue(new Map()),
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
const concern = new CDCConcern({
|
|
800
|
+
storage: mockStorage,
|
|
801
|
+
enabled: true,
|
|
802
|
+
})
|
|
803
|
+
|
|
804
|
+
const listener = vi.fn()
|
|
805
|
+
const unsubscribe = concern.onEntry(listener)
|
|
806
|
+
|
|
807
|
+
unsubscribe()
|
|
808
|
+
|
|
809
|
+
concern.captureChange({
|
|
810
|
+
sql: 'INSERT INTO users (name) VALUES ($1)',
|
|
811
|
+
table: 'users',
|
|
812
|
+
operation: 'INSERT',
|
|
813
|
+
newRow: { id: 1 },
|
|
814
|
+
})
|
|
815
|
+
|
|
816
|
+
expect(listener).not.toHaveBeenCalled()
|
|
817
|
+
})
|
|
818
|
+
})
|
|
819
|
+
})
|
|
820
|
+
|
|
821
|
+
// =============================================================================
|
|
822
|
+
// TEST: STORAGE ORCHESTRATION CONCERN ISOLATION
|
|
823
|
+
// =============================================================================
|
|
824
|
+
|
|
825
|
+
describe('Storage Orchestration Concern Decomposition', () => {
|
|
826
|
+
describe('Independent Instantiation', () => {
|
|
827
|
+
it('should be creatable without PostgresDO context', async () => {
|
|
828
|
+
// RED: This test will fail until we export a standalone StorageOrchestrationConcern
|
|
829
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
830
|
+
|
|
831
|
+
const mockCacheLayer = {
|
|
832
|
+
get: vi.fn(),
|
|
833
|
+
put: vi.fn(),
|
|
834
|
+
delete: vi.fn(),
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
const mockR2Layer = {
|
|
838
|
+
get: vi.fn(),
|
|
839
|
+
put: vi.fn(),
|
|
840
|
+
delete: vi.fn(),
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
const mockDOStorage = {
|
|
844
|
+
get: vi.fn(),
|
|
845
|
+
put: vi.fn(),
|
|
846
|
+
delete: vi.fn(),
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
const concern = new StorageOrchestrationConcern({
|
|
850
|
+
hotLayer: mockCacheLayer,
|
|
851
|
+
warmLayer: mockDOStorage,
|
|
852
|
+
coldLayer: mockR2Layer,
|
|
853
|
+
})
|
|
854
|
+
|
|
855
|
+
expect(concern).toBeDefined()
|
|
856
|
+
})
|
|
857
|
+
|
|
858
|
+
it('should read from tiers in priority order', async () => {
|
|
859
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
860
|
+
|
|
861
|
+
const mockCacheLayer = {
|
|
862
|
+
get: vi.fn().mockResolvedValue(null), // Miss
|
|
863
|
+
put: vi.fn(),
|
|
864
|
+
delete: vi.fn(),
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
const mockDOStorage = {
|
|
868
|
+
get: vi.fn().mockResolvedValue(new Uint8Array([1, 2, 3])), // Hit
|
|
869
|
+
put: vi.fn(),
|
|
870
|
+
delete: vi.fn(),
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
const mockR2Layer = {
|
|
874
|
+
get: vi.fn(),
|
|
875
|
+
put: vi.fn(),
|
|
876
|
+
delete: vi.fn(),
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
const concern = new StorageOrchestrationConcern({
|
|
880
|
+
hotLayer: mockCacheLayer,
|
|
881
|
+
warmLayer: mockDOStorage,
|
|
882
|
+
coldLayer: mockR2Layer,
|
|
883
|
+
})
|
|
884
|
+
|
|
885
|
+
const result = await concern.read('page-1')
|
|
886
|
+
|
|
887
|
+
expect(result).toEqual(new Uint8Array([1, 2, 3]))
|
|
888
|
+
expect(mockCacheLayer.get).toHaveBeenCalledWith('page-1')
|
|
889
|
+
expect(mockDOStorage.get).toHaveBeenCalledWith('page-1')
|
|
890
|
+
expect(mockR2Layer.get).not.toHaveBeenCalled() // Should not fall through after warm hit
|
|
891
|
+
})
|
|
892
|
+
|
|
893
|
+
it('should be injectable into PostgresDO', async () => {
|
|
894
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
895
|
+
const { PostgresDO } = await import('./do')
|
|
896
|
+
|
|
897
|
+
const mockCacheLayer = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
898
|
+
const mockDOStorage = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
899
|
+
const mockR2Layer = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
900
|
+
|
|
901
|
+
const mockStorageConcern = new StorageOrchestrationConcern({
|
|
902
|
+
hotLayer: mockCacheLayer,
|
|
903
|
+
warmLayer: mockDOStorage,
|
|
904
|
+
coldLayer: mockR2Layer,
|
|
905
|
+
})
|
|
906
|
+
|
|
907
|
+
const state = createMockState()
|
|
908
|
+
const env = createMockEnv()
|
|
909
|
+
|
|
910
|
+
// RED: PostgresDO should accept injected concerns
|
|
911
|
+
const doo = new PostgresDO(state as any, env, {
|
|
912
|
+
database: 'test',
|
|
913
|
+
concerns: {
|
|
914
|
+
storageOrchestration: mockStorageConcern,
|
|
915
|
+
},
|
|
916
|
+
} as PostgresConfig)
|
|
917
|
+
|
|
918
|
+
// Should use injected storage orchestration
|
|
919
|
+
expect(doo).toBeDefined()
|
|
920
|
+
})
|
|
921
|
+
})
|
|
922
|
+
|
|
923
|
+
describe('Interface Compliance', () => {
|
|
924
|
+
it('should implement IStorageOrchestrationConcern interface', async () => {
|
|
925
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
926
|
+
|
|
927
|
+
const concern = new StorageOrchestrationConcern({
|
|
928
|
+
hotLayer: { get: vi.fn(), put: vi.fn(), delete: vi.fn() },
|
|
929
|
+
warmLayer: { get: vi.fn(), put: vi.fn(), delete: vi.fn() },
|
|
930
|
+
coldLayer: { get: vi.fn(), put: vi.fn(), delete: vi.fn() },
|
|
931
|
+
})
|
|
932
|
+
|
|
933
|
+
// Verify all interface methods exist
|
|
934
|
+
expect(typeof concern.read).toBe('function')
|
|
935
|
+
expect(typeof concern.write).toBe('function')
|
|
936
|
+
expect(typeof concern.delete).toBe('function')
|
|
937
|
+
expect(typeof concern.getTier).toBe('function')
|
|
938
|
+
expect(typeof concern.promote).toBe('function')
|
|
939
|
+
expect(typeof concern.demote).toBe('function')
|
|
940
|
+
expect(typeof concern.getStats).toBe('function')
|
|
941
|
+
expect(typeof concern.getTierHealth).toBe('function')
|
|
942
|
+
})
|
|
943
|
+
})
|
|
944
|
+
|
|
945
|
+
describe('Tiered Storage Operations', () => {
|
|
946
|
+
it('should track which tier contains a page', async () => {
|
|
947
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
948
|
+
|
|
949
|
+
const mockCacheLayer = {
|
|
950
|
+
get: vi.fn(),
|
|
951
|
+
put: vi.fn(),
|
|
952
|
+
delete: vi.fn(),
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
const mockDOStorage = {
|
|
956
|
+
get: vi.fn(),
|
|
957
|
+
put: vi.fn(),
|
|
958
|
+
delete: vi.fn(),
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
const mockR2Layer = {
|
|
962
|
+
get: vi.fn(),
|
|
963
|
+
put: vi.fn(),
|
|
964
|
+
delete: vi.fn(),
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
const concern = new StorageOrchestrationConcern({
|
|
968
|
+
hotLayer: mockCacheLayer,
|
|
969
|
+
warmLayer: mockDOStorage,
|
|
970
|
+
coldLayer: mockR2Layer,
|
|
971
|
+
})
|
|
972
|
+
|
|
973
|
+
await concern.write('page-1', new Uint8Array([1, 2, 3]), { tier: 'warm' })
|
|
974
|
+
|
|
975
|
+
const tier = concern.getTier('page-1')
|
|
976
|
+
expect(tier).toBe('warm')
|
|
977
|
+
})
|
|
978
|
+
|
|
979
|
+
it('should promote pages from cold to warm', async () => {
|
|
980
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
981
|
+
|
|
982
|
+
const mockCacheLayer = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
983
|
+
const mockDOStorage = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
984
|
+
const mockR2Layer = {
|
|
985
|
+
get: vi.fn().mockResolvedValue(new Uint8Array([1, 2, 3])),
|
|
986
|
+
put: vi.fn(),
|
|
987
|
+
delete: vi.fn(),
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
const concern = new StorageOrchestrationConcern({
|
|
991
|
+
hotLayer: mockCacheLayer,
|
|
992
|
+
warmLayer: mockDOStorage,
|
|
993
|
+
coldLayer: mockR2Layer,
|
|
994
|
+
})
|
|
995
|
+
|
|
996
|
+
// Simulate page in cold tier
|
|
997
|
+
await concern.write('page-1', new Uint8Array([1, 2, 3]), { tier: 'cold' })
|
|
998
|
+
|
|
999
|
+
// Promote to warm
|
|
1000
|
+
await concern.promote('page-1', 'warm')
|
|
1001
|
+
|
|
1002
|
+
expect(mockR2Layer.get).toHaveBeenCalledWith('page-1')
|
|
1003
|
+
expect(mockDOStorage.put).toHaveBeenCalled()
|
|
1004
|
+
})
|
|
1005
|
+
|
|
1006
|
+
it('should demote pages from hot to warm', async () => {
|
|
1007
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
1008
|
+
|
|
1009
|
+
const mockCacheLayer = {
|
|
1010
|
+
get: vi.fn().mockResolvedValue(new Uint8Array([1, 2, 3])),
|
|
1011
|
+
put: vi.fn(),
|
|
1012
|
+
delete: vi.fn(),
|
|
1013
|
+
}
|
|
1014
|
+
const mockDOStorage = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
1015
|
+
const mockR2Layer = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
1016
|
+
|
|
1017
|
+
const concern = new StorageOrchestrationConcern({
|
|
1018
|
+
hotLayer: mockCacheLayer,
|
|
1019
|
+
warmLayer: mockDOStorage,
|
|
1020
|
+
coldLayer: mockR2Layer,
|
|
1021
|
+
})
|
|
1022
|
+
|
|
1023
|
+
// Simulate page in hot tier
|
|
1024
|
+
await concern.write('page-1', new Uint8Array([1, 2, 3]), { tier: 'hot' })
|
|
1025
|
+
|
|
1026
|
+
// Demote to warm
|
|
1027
|
+
await concern.demote('page-1', 'warm')
|
|
1028
|
+
|
|
1029
|
+
expect(mockCacheLayer.delete).toHaveBeenCalledWith('page-1')
|
|
1030
|
+
expect(mockDOStorage.put).toHaveBeenCalled()
|
|
1031
|
+
})
|
|
1032
|
+
})
|
|
1033
|
+
|
|
1034
|
+
describe('Statistics and Health', () => {
|
|
1035
|
+
it('should track storage statistics', async () => {
|
|
1036
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
1037
|
+
|
|
1038
|
+
const mockCacheLayer = {
|
|
1039
|
+
get: vi.fn().mockResolvedValue(null),
|
|
1040
|
+
put: vi.fn(),
|
|
1041
|
+
delete: vi.fn(),
|
|
1042
|
+
}
|
|
1043
|
+
const mockDOStorage = {
|
|
1044
|
+
get: vi.fn().mockResolvedValue(new Uint8Array([1, 2, 3])),
|
|
1045
|
+
put: vi.fn(),
|
|
1046
|
+
delete: vi.fn(),
|
|
1047
|
+
}
|
|
1048
|
+
const mockR2Layer = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
1049
|
+
|
|
1050
|
+
const concern = new StorageOrchestrationConcern({
|
|
1051
|
+
hotLayer: mockCacheLayer,
|
|
1052
|
+
warmLayer: mockDOStorage,
|
|
1053
|
+
coldLayer: mockR2Layer,
|
|
1054
|
+
})
|
|
1055
|
+
|
|
1056
|
+
// Perform some operations
|
|
1057
|
+
await concern.read('page-1') // Miss hot, hit warm
|
|
1058
|
+
await concern.read('page-2') // Miss hot, miss warm (hypothetically)
|
|
1059
|
+
|
|
1060
|
+
const stats = concern.getStats()
|
|
1061
|
+
expect(typeof stats.hotSize).toBe('number')
|
|
1062
|
+
expect(typeof stats.warmSize).toBe('number')
|
|
1063
|
+
expect(typeof stats.coldSize).toBe('number')
|
|
1064
|
+
expect(typeof stats.hitRate).toBe('number')
|
|
1065
|
+
})
|
|
1066
|
+
|
|
1067
|
+
it('should report tier health status', async () => {
|
|
1068
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
1069
|
+
|
|
1070
|
+
const mockCacheLayer = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
1071
|
+
const mockDOStorage = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
1072
|
+
const mockR2Layer = { get: vi.fn(), put: vi.fn(), delete: vi.fn() }
|
|
1073
|
+
|
|
1074
|
+
const concern = new StorageOrchestrationConcern({
|
|
1075
|
+
hotLayer: mockCacheLayer,
|
|
1076
|
+
warmLayer: mockDOStorage,
|
|
1077
|
+
coldLayer: mockR2Layer,
|
|
1078
|
+
})
|
|
1079
|
+
|
|
1080
|
+
const hotHealth = concern.getTierHealth('hot')
|
|
1081
|
+
const warmHealth = concern.getTierHealth('warm')
|
|
1082
|
+
const coldHealth = concern.getTierHealth('cold')
|
|
1083
|
+
|
|
1084
|
+
expect(hotHealth).toHaveProperty('healthy')
|
|
1085
|
+
expect(warmHealth).toHaveProperty('healthy')
|
|
1086
|
+
expect(coldHealth).toHaveProperty('healthy')
|
|
1087
|
+
})
|
|
1088
|
+
})
|
|
1089
|
+
})
|
|
1090
|
+
|
|
1091
|
+
// =============================================================================
|
|
1092
|
+
// TEST: POSTGRESQL DO CONCERN COMPOSITION
|
|
1093
|
+
// =============================================================================
|
|
1094
|
+
|
|
1095
|
+
describe('PostgresDO Concern Composition', () => {
|
|
1096
|
+
describe('Concern Injection', () => {
|
|
1097
|
+
it('should accept all concerns via config', async () => {
|
|
1098
|
+
const { PostgresDO } = await import('./do')
|
|
1099
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
1100
|
+
const { QueryExecutionConcern } = await import('./concerns/query-execution-concern')
|
|
1101
|
+
const { CDCConcern } = await import('./concerns/cdc-concern')
|
|
1102
|
+
const { StorageOrchestrationConcern } = await import('./concerns/storage-orchestration-concern')
|
|
1103
|
+
|
|
1104
|
+
const mockPGlite = createMockPGlite()
|
|
1105
|
+
const mockStorage = { get: vi.fn(), put: vi.fn(), list: vi.fn().mockResolvedValue(new Map()) }
|
|
1106
|
+
|
|
1107
|
+
const concerns = {
|
|
1108
|
+
auth: new AuthConcern({ enabled: true }),
|
|
1109
|
+
queryExecution: new QueryExecutionConcern({
|
|
1110
|
+
getPGlite: () => mockPGlite,
|
|
1111
|
+
preserveCase: false,
|
|
1112
|
+
}),
|
|
1113
|
+
cdc: new CDCConcern({ storage: mockStorage, enabled: true }),
|
|
1114
|
+
storageOrchestration: new StorageOrchestrationConcern({
|
|
1115
|
+
hotLayer: { get: vi.fn(), put: vi.fn(), delete: vi.fn() },
|
|
1116
|
+
warmLayer: { get: vi.fn(), put: vi.fn(), delete: vi.fn() },
|
|
1117
|
+
coldLayer: { get: vi.fn(), put: vi.fn(), delete: vi.fn() },
|
|
1118
|
+
}),
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
const state = createMockState()
|
|
1122
|
+
const env = createMockEnv()
|
|
1123
|
+
|
|
1124
|
+
// RED: PostgresDO should accept concerns in config
|
|
1125
|
+
const doo = new PostgresDO(state as any, env, {
|
|
1126
|
+
database: 'test',
|
|
1127
|
+
concerns,
|
|
1128
|
+
} as PostgresConfig)
|
|
1129
|
+
|
|
1130
|
+
expect(doo).toBeDefined()
|
|
1131
|
+
})
|
|
1132
|
+
|
|
1133
|
+
it('should use default concerns when not injected', async () => {
|
|
1134
|
+
const { PostgresDO } = await import('./do')
|
|
1135
|
+
|
|
1136
|
+
const state = createMockState()
|
|
1137
|
+
const env = createMockEnv()
|
|
1138
|
+
|
|
1139
|
+
// Without concerns, should use internal defaults
|
|
1140
|
+
const doo = new PostgresDO(state as any, env, {
|
|
1141
|
+
database: 'test',
|
|
1142
|
+
})
|
|
1143
|
+
|
|
1144
|
+
// Should work with default concerns
|
|
1145
|
+
expect(doo.getAuthConfig()).toBeDefined()
|
|
1146
|
+
expect(doo.getWALConfig).toBeDefined()
|
|
1147
|
+
})
|
|
1148
|
+
|
|
1149
|
+
it('should allow partial concern injection', async () => {
|
|
1150
|
+
const { PostgresDO } = await import('./do')
|
|
1151
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
1152
|
+
|
|
1153
|
+
const state = createMockState()
|
|
1154
|
+
const env = createMockEnv()
|
|
1155
|
+
|
|
1156
|
+
// Only inject auth concern, use defaults for others
|
|
1157
|
+
const doo = new PostgresDO(state as any, env, {
|
|
1158
|
+
database: 'test',
|
|
1159
|
+
concerns: {
|
|
1160
|
+
auth: new AuthConcern({ enabled: true, oauthUrl: 'https://custom-oauth.com' }),
|
|
1161
|
+
},
|
|
1162
|
+
} as PostgresConfig)
|
|
1163
|
+
|
|
1164
|
+
const authConfig = doo.getAuthConfig()
|
|
1165
|
+
expect(authConfig.oauthUrl).toBe('https://custom-oauth.com')
|
|
1166
|
+
})
|
|
1167
|
+
})
|
|
1168
|
+
|
|
1169
|
+
describe('Concern Isolation Verification', () => {
|
|
1170
|
+
it('should not leak concern state between instances', async () => {
|
|
1171
|
+
const { PostgresDO } = await import('./do')
|
|
1172
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
1173
|
+
|
|
1174
|
+
const state1 = createMockState()
|
|
1175
|
+
const state2 = createMockState()
|
|
1176
|
+
const env = createMockEnv()
|
|
1177
|
+
|
|
1178
|
+
const auth1 = new AuthConcern({ enabled: true })
|
|
1179
|
+
const auth2 = new AuthConcern({ enabled: true })
|
|
1180
|
+
|
|
1181
|
+
const doo1 = new PostgresDO(state1 as any, env, {
|
|
1182
|
+
database: 'test1',
|
|
1183
|
+
concerns: { auth: auth1 },
|
|
1184
|
+
} as PostgresConfig)
|
|
1185
|
+
|
|
1186
|
+
const doo2 = new PostgresDO(state2 as any, env, {
|
|
1187
|
+
database: 'test2',
|
|
1188
|
+
concerns: { auth: auth2 },
|
|
1189
|
+
} as PostgresConfig)
|
|
1190
|
+
|
|
1191
|
+
// Set different user IDs
|
|
1192
|
+
doo1.setUserId('user-1')
|
|
1193
|
+
doo2.setUserId('user-2')
|
|
1194
|
+
|
|
1195
|
+
// State should be isolated
|
|
1196
|
+
expect(doo1.getUserId()).toBe('user-1')
|
|
1197
|
+
expect(doo2.getUserId()).toBe('user-2')
|
|
1198
|
+
})
|
|
1199
|
+
|
|
1200
|
+
it('should allow replacing concerns at runtime', async () => {
|
|
1201
|
+
const { PostgresDO } = await import('./do')
|
|
1202
|
+
const { AuthConcern } = await import('./concerns/auth-concern')
|
|
1203
|
+
|
|
1204
|
+
const state = createMockState()
|
|
1205
|
+
const env = createMockEnv()
|
|
1206
|
+
|
|
1207
|
+
const initialAuth = new AuthConcern({
|
|
1208
|
+
enabled: true,
|
|
1209
|
+
validateToken: vi.fn().mockResolvedValue({ valid: true, user: { id: 'initial' } }),
|
|
1210
|
+
})
|
|
1211
|
+
|
|
1212
|
+
const doo = new PostgresDO(state as any, env, {
|
|
1213
|
+
database: 'test',
|
|
1214
|
+
concerns: { auth: initialAuth },
|
|
1215
|
+
} as PostgresConfig)
|
|
1216
|
+
|
|
1217
|
+
// RED: Should be able to replace concerns
|
|
1218
|
+
const newAuth = new AuthConcern({
|
|
1219
|
+
enabled: true,
|
|
1220
|
+
validateToken: vi.fn().mockResolvedValue({ valid: true, user: { id: 'replaced' } }),
|
|
1221
|
+
})
|
|
1222
|
+
|
|
1223
|
+
// setConcern method should exist
|
|
1224
|
+
expect(typeof (doo as any).setConcern).toBe('function')
|
|
1225
|
+
;(doo as any).setConcern('auth', newAuth)
|
|
1226
|
+
|
|
1227
|
+
const user = await doo.authenticateRequest(
|
|
1228
|
+
new Request('http://test.com', {
|
|
1229
|
+
headers: { Authorization: 'Bearer token' },
|
|
1230
|
+
})
|
|
1231
|
+
)
|
|
1232
|
+
|
|
1233
|
+
expect(user?.id).toBe('replaced')
|
|
1234
|
+
})
|
|
1235
|
+
})
|
|
1236
|
+
})
|