@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,840 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiting Middleware for Cloudflare Workers
|
|
3
|
+
* Task: postgres-k06 - Add rate limiting middleware to Worker entry points
|
|
4
|
+
*
|
|
5
|
+
* Implements sliding window rate limiting using DO storage or KV.
|
|
6
|
+
* Supports rate limiting by IP, user, or custom key.
|
|
7
|
+
*/
|
|
8
|
+
import type { MiddlewareHandler } from 'hono'
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Types
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Generic storage backend interface for rate limit data.
|
|
16
|
+
*
|
|
17
|
+
* @typeParam T - The type of data stored (defaults to RateLimitWindow for backwards compatibility)
|
|
18
|
+
*/
|
|
19
|
+
export interface GenericRateLimitStorage<T = RateLimitWindow> {
|
|
20
|
+
/**
|
|
21
|
+
* Get the stored data for a key
|
|
22
|
+
*/
|
|
23
|
+
get(key: string): Promise<T | null>
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Store data for a key
|
|
27
|
+
*/
|
|
28
|
+
set(key: string, data: T, ttlMs: number): Promise<void>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Storage backend interface for rate limit data.
|
|
33
|
+
* This is the default storage interface for sliding window rate limiting.
|
|
34
|
+
*/
|
|
35
|
+
export interface RateLimitStorage extends GenericRateLimitStorage<RateLimitWindow> {}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Sliding window data structure
|
|
39
|
+
*/
|
|
40
|
+
export interface RateLimitWindow {
|
|
41
|
+
/** Request counts per sub-window */
|
|
42
|
+
counts: number[]
|
|
43
|
+
/** Timestamp of the start of the current window (ms) */
|
|
44
|
+
windowStart: number
|
|
45
|
+
/** Total requests in the current window */
|
|
46
|
+
total: number
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Rate limit key extraction modes
|
|
51
|
+
*/
|
|
52
|
+
export type RateLimitKeyMode = 'ip' | 'user' | 'custom'
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Rate limit options
|
|
56
|
+
*/
|
|
57
|
+
export interface RateLimitOptions {
|
|
58
|
+
/**
|
|
59
|
+
* Maximum number of requests allowed in the window
|
|
60
|
+
* @default 60
|
|
61
|
+
*/
|
|
62
|
+
requests?: number
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Window duration in milliseconds
|
|
66
|
+
* @default 60000 (1 minute)
|
|
67
|
+
*/
|
|
68
|
+
windowMs?: number
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Number of sub-windows for sliding window algorithm
|
|
72
|
+
* More sub-windows = more accuracy but more storage
|
|
73
|
+
* @default 10
|
|
74
|
+
*/
|
|
75
|
+
subWindows?: number
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Key extraction mode
|
|
79
|
+
* - 'ip': Rate limit by client IP address
|
|
80
|
+
* - 'user': Rate limit by user ID from request context
|
|
81
|
+
* - 'custom': Use custom key extractor function
|
|
82
|
+
* @default 'ip'
|
|
83
|
+
*/
|
|
84
|
+
keyMode?: RateLimitKeyMode
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Custom key extractor function
|
|
88
|
+
* Required when keyMode is 'custom'
|
|
89
|
+
*/
|
|
90
|
+
keyExtractor?: (c: HonoContext) => string | null
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Key prefix for storage
|
|
94
|
+
* @default 'ratelimit:'
|
|
95
|
+
*/
|
|
96
|
+
keyPrefix?: string
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Header to extract IP from (e.g., 'CF-Connecting-IP', 'X-Forwarded-For')
|
|
100
|
+
* @default 'CF-Connecting-IP'
|
|
101
|
+
*/
|
|
102
|
+
ipHeader?: string
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Header or context key for user ID
|
|
106
|
+
* @default 'X-User-ID'
|
|
107
|
+
*/
|
|
108
|
+
userHeader?: string
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Whether to skip rate limiting for certain requests
|
|
112
|
+
*/
|
|
113
|
+
skip?: (c: HonoContext) => boolean | Promise<boolean>
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Custom response handler when rate limit is exceeded
|
|
117
|
+
*/
|
|
118
|
+
onRateLimited?: (c: HonoContext, info: RateLimitInfo) => Response | Promise<Response>
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Storage backend (DO storage or KV)
|
|
122
|
+
* If not provided, will use in-memory storage (not recommended for production)
|
|
123
|
+
*/
|
|
124
|
+
storage?: RateLimitStorage
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Rate limit status information
|
|
129
|
+
*/
|
|
130
|
+
export interface RateLimitInfo {
|
|
131
|
+
/** Total requests allowed in window */
|
|
132
|
+
limit: number
|
|
133
|
+
/** Remaining requests in current window */
|
|
134
|
+
remaining: number
|
|
135
|
+
/** Time in seconds until the rate limit resets */
|
|
136
|
+
resetAfterSeconds: number
|
|
137
|
+
/** Whether the request was rate limited */
|
|
138
|
+
limited: boolean
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Hono context interface (minimal)
|
|
143
|
+
*/
|
|
144
|
+
interface HonoContext {
|
|
145
|
+
req: {
|
|
146
|
+
header(name: string): string | undefined
|
|
147
|
+
raw: Request
|
|
148
|
+
}
|
|
149
|
+
header(name: string, value: string): void
|
|
150
|
+
json(data: unknown, status?: number): Response
|
|
151
|
+
set(key: string, value: unknown): void
|
|
152
|
+
get(key: string): unknown
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ============================================================================
|
|
156
|
+
// Storage Implementations
|
|
157
|
+
// ============================================================================
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Generic in-memory storage for rate limiting (for testing/development only).
|
|
161
|
+
*
|
|
162
|
+
* @typeParam T - The type of data stored
|
|
163
|
+
*/
|
|
164
|
+
export class GenericInMemoryStorage<T> implements GenericRateLimitStorage<T> {
|
|
165
|
+
private store = new Map<string, { data: T; expiresAt: number }>()
|
|
166
|
+
|
|
167
|
+
async get(key: string): Promise<T | null> {
|
|
168
|
+
const entry = this.store.get(key)
|
|
169
|
+
if (!entry) return null
|
|
170
|
+
if (Date.now() > entry.expiresAt) {
|
|
171
|
+
this.store.delete(key)
|
|
172
|
+
return null
|
|
173
|
+
}
|
|
174
|
+
return entry.data
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async set(key: string, data: T, ttlMs: number): Promise<void> {
|
|
178
|
+
this.store.set(key, {
|
|
179
|
+
data,
|
|
180
|
+
expiresAt: Date.now() + ttlMs,
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Clear all entries (for testing) */
|
|
185
|
+
clear(): void {
|
|
186
|
+
this.store.clear()
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* In-memory storage for rate limiting (for testing/development only).
|
|
192
|
+
* Alias for GenericInMemoryStorage<RateLimitWindow> for backwards compatibility.
|
|
193
|
+
*/
|
|
194
|
+
export class InMemoryRateLimitStorage extends GenericInMemoryStorage<RateLimitWindow> implements RateLimitStorage {}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* In-memory storage for token bucket rate limiting (for testing/development only).
|
|
198
|
+
*/
|
|
199
|
+
export class InMemoryTokenBucketStorage extends GenericInMemoryStorage<TokenBucket> implements TokenBucketStorage {}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Generic Durable Object storage adapter for rate limiting.
|
|
203
|
+
*
|
|
204
|
+
* @typeParam T - The type of data stored
|
|
205
|
+
*/
|
|
206
|
+
export class GenericDOStorage<T> implements GenericRateLimitStorage<T> {
|
|
207
|
+
constructor(private storage: DurableObjectStorage) {}
|
|
208
|
+
|
|
209
|
+
async get(key: string): Promise<T | null> {
|
|
210
|
+
const data = await this.storage.get<T>(key)
|
|
211
|
+
return data ?? null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async set(key: string, data: T, _ttlMs: number): Promise<void> {
|
|
215
|
+
// Use alarm for TTL cleanup
|
|
216
|
+
await this.storage.put(key, data)
|
|
217
|
+
// Schedule cleanup - DO storage doesn't have native TTL
|
|
218
|
+
// The sliding window algorithm handles stale data naturally
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Durable Object storage adapter for rate limiting.
|
|
224
|
+
* Alias for GenericDOStorage<RateLimitWindow> for backwards compatibility.
|
|
225
|
+
*/
|
|
226
|
+
export class DurableObjectRateLimitStorage extends GenericDOStorage<RateLimitWindow> implements RateLimitStorage {}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Durable Object storage adapter for token bucket rate limiting.
|
|
230
|
+
*/
|
|
231
|
+
export class DurableObjectTokenBucketStorage extends GenericDOStorage<TokenBucket> implements TokenBucketStorage {}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Generic KV storage adapter for rate limiting.
|
|
235
|
+
*
|
|
236
|
+
* @typeParam T - The type of data stored
|
|
237
|
+
*/
|
|
238
|
+
export class GenericKVStorage<T> implements GenericRateLimitStorage<T> {
|
|
239
|
+
constructor(private kv: KVNamespace) {}
|
|
240
|
+
|
|
241
|
+
async get(key: string): Promise<T | null> {
|
|
242
|
+
const data = await this.kv.get<T>(key, 'json')
|
|
243
|
+
return data ?? null
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async set(key: string, data: T, ttlMs: number): Promise<void> {
|
|
247
|
+
// KV TTL is in seconds, minimum 60 seconds
|
|
248
|
+
const ttlSeconds = Math.max(60, Math.ceil(ttlMs / 1000))
|
|
249
|
+
await this.kv.put(key, JSON.stringify(data), { expirationTtl: ttlSeconds })
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* KV storage adapter for rate limiting.
|
|
255
|
+
* Alias for GenericKVStorage<RateLimitWindow> for backwards compatibility.
|
|
256
|
+
*/
|
|
257
|
+
export class KVRateLimitStorage extends GenericKVStorage<RateLimitWindow> implements RateLimitStorage {}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* KV storage adapter for token bucket rate limiting.
|
|
261
|
+
*/
|
|
262
|
+
export class KVTokenBucketStorage extends GenericKVStorage<TokenBucket> implements TokenBucketStorage {}
|
|
263
|
+
|
|
264
|
+
// ============================================================================
|
|
265
|
+
// Sliding Window Algorithm
|
|
266
|
+
// ============================================================================
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Sliding window rate limiter implementation
|
|
270
|
+
*
|
|
271
|
+
* Uses a sliding window log algorithm with sub-windows for efficiency:
|
|
272
|
+
* - Divides the main window into N sub-windows
|
|
273
|
+
* - Each sub-window tracks request counts
|
|
274
|
+
* - Calculates weighted sum based on current position in window
|
|
275
|
+
* - More accurate than fixed window, more efficient than per-request logging
|
|
276
|
+
*/
|
|
277
|
+
export class SlidingWindowRateLimiter {
|
|
278
|
+
private requests: number
|
|
279
|
+
private windowMs: number
|
|
280
|
+
private subWindows: number
|
|
281
|
+
private subWindowMs: number
|
|
282
|
+
private storage: RateLimitStorage
|
|
283
|
+
|
|
284
|
+
constructor(options: Required<Pick<RateLimitOptions, 'requests' | 'windowMs' | 'subWindows' | 'storage'>>) {
|
|
285
|
+
this.requests = options.requests
|
|
286
|
+
this.windowMs = options.windowMs
|
|
287
|
+
this.subWindows = options.subWindows
|
|
288
|
+
this.subWindowMs = options.windowMs / options.subWindows
|
|
289
|
+
this.storage = options.storage
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Check if a request should be rate limited
|
|
294
|
+
*/
|
|
295
|
+
async check(key: string): Promise<RateLimitInfo> {
|
|
296
|
+
const now = Date.now()
|
|
297
|
+
const currentWindow = await this.storage.get(key)
|
|
298
|
+
|
|
299
|
+
// Initialize or rotate window
|
|
300
|
+
let window = this.rotateWindow(currentWindow, now)
|
|
301
|
+
|
|
302
|
+
// Calculate weighted request count using sliding window
|
|
303
|
+
const weightedCount = this.calculateWeightedCount(window, now)
|
|
304
|
+
|
|
305
|
+
// Check if rate limited - we need to check if adding this request would exceed
|
|
306
|
+
// The current count + 1 (this request) must not exceed the limit
|
|
307
|
+
const limited = weightedCount + 1 > this.requests
|
|
308
|
+
|
|
309
|
+
if (!limited) {
|
|
310
|
+
// Increment current sub-window
|
|
311
|
+
const currentSubWindowIndex = this.getCurrentSubWindowIndex(window, now)
|
|
312
|
+
window.counts[currentSubWindowIndex]!++
|
|
313
|
+
window.total++
|
|
314
|
+
|
|
315
|
+
// Save updated window
|
|
316
|
+
await this.storage.set(key, window, this.windowMs * 2)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Calculate time until reset
|
|
320
|
+
const windowEnd = window.windowStart + this.windowMs
|
|
321
|
+
const resetAfterSeconds = Math.max(0, Math.ceil((windowEnd - now) / 1000))
|
|
322
|
+
|
|
323
|
+
// Remaining is: limit - (current weighted count + this request if allowed)
|
|
324
|
+
const currentCount = limited ? Math.ceil(weightedCount) : Math.ceil(weightedCount) + 1
|
|
325
|
+
|
|
326
|
+
return {
|
|
327
|
+
limit: this.requests,
|
|
328
|
+
remaining: Math.max(0, this.requests - currentCount),
|
|
329
|
+
resetAfterSeconds,
|
|
330
|
+
limited,
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Rotate window if needed (handles time progression)
|
|
336
|
+
*/
|
|
337
|
+
private rotateWindow(existing: RateLimitWindow | null, now: number): RateLimitWindow {
|
|
338
|
+
if (!existing) {
|
|
339
|
+
// Create new window
|
|
340
|
+
return {
|
|
341
|
+
counts: new Array(this.subWindows).fill(0),
|
|
342
|
+
windowStart: now - (now % this.subWindowMs),
|
|
343
|
+
total: 0,
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const windowAge = now - existing.windowStart
|
|
348
|
+
const subWindowsElapsed = Math.floor(windowAge / this.subWindowMs)
|
|
349
|
+
|
|
350
|
+
if (subWindowsElapsed >= this.subWindows) {
|
|
351
|
+
// Entire window has elapsed, start fresh
|
|
352
|
+
return {
|
|
353
|
+
counts: new Array(this.subWindows).fill(0),
|
|
354
|
+
windowStart: now - (now % this.subWindowMs),
|
|
355
|
+
total: 0,
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (subWindowsElapsed > 0) {
|
|
360
|
+
// Rotate: shift out old sub-windows, add new ones
|
|
361
|
+
const newCounts = new Array(this.subWindows).fill(0)
|
|
362
|
+
for (let i = 0; i < this.subWindows - subWindowsElapsed; i++) {
|
|
363
|
+
newCounts[i] = existing.counts[i + subWindowsElapsed]
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return {
|
|
367
|
+
counts: newCounts,
|
|
368
|
+
windowStart: existing.windowStart + subWindowsElapsed * this.subWindowMs,
|
|
369
|
+
total: newCounts.reduce((a, b) => a + b, 0),
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return existing
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Calculate weighted request count using sliding window
|
|
378
|
+
*
|
|
379
|
+
* For a proper sliding window, we count all requests in all sub-windows.
|
|
380
|
+
* The sliding window effect is achieved through the rotation logic which
|
|
381
|
+
* removes old sub-windows as time passes.
|
|
382
|
+
*/
|
|
383
|
+
private calculateWeightedCount(window: RateLimitWindow, _now: number): number {
|
|
384
|
+
// Simply sum all requests in all sub-windows
|
|
385
|
+
// The rotation logic already handles removing expired sub-windows
|
|
386
|
+
return window.total
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Get the current sub-window index
|
|
391
|
+
*/
|
|
392
|
+
private getCurrentSubWindowIndex(window: RateLimitWindow, now: number): number {
|
|
393
|
+
const elapsed = now - window.windowStart
|
|
394
|
+
return Math.min(this.subWindows - 1, Math.floor(elapsed / this.subWindowMs))
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// ============================================================================
|
|
399
|
+
// Middleware Factory
|
|
400
|
+
// ============================================================================
|
|
401
|
+
|
|
402
|
+
/** Default rate limit options */
|
|
403
|
+
const DEFAULT_OPTIONS: Required<Omit<RateLimitOptions, 'keyExtractor' | 'skip' | 'onRateLimited' | 'storage'>> = {
|
|
404
|
+
requests: 60,
|
|
405
|
+
windowMs: 60000,
|
|
406
|
+
subWindows: 10,
|
|
407
|
+
keyMode: 'ip',
|
|
408
|
+
keyPrefix: 'ratelimit:',
|
|
409
|
+
ipHeader: 'CF-Connecting-IP',
|
|
410
|
+
userHeader: 'X-User-ID',
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Extract client IP from request
|
|
415
|
+
*/
|
|
416
|
+
function extractIP(c: HonoContext, header: string): string {
|
|
417
|
+
const ip = c.req.header(header) ?? c.req.header('X-Forwarded-For')?.split(',')[0]?.trim() ?? 'unknown'
|
|
418
|
+
return ip
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Extract user ID from request
|
|
423
|
+
*/
|
|
424
|
+
function extractUser(c: HonoContext, header: string): string | null {
|
|
425
|
+
return c.req.header(header) ?? null
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Create default rate limited response
|
|
430
|
+
*/
|
|
431
|
+
function createRateLimitedResponse(c: HonoContext, info: RateLimitInfo): Response {
|
|
432
|
+
return c.json(
|
|
433
|
+
{
|
|
434
|
+
error: true,
|
|
435
|
+
code: 'RATE_LIMITED',
|
|
436
|
+
message: 'Too many requests. Please try again later.',
|
|
437
|
+
retryAfter: info.resetAfterSeconds,
|
|
438
|
+
},
|
|
439
|
+
429
|
|
440
|
+
)
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Create rate limiting middleware for Hono
|
|
445
|
+
*
|
|
446
|
+
* @example
|
|
447
|
+
* ```typescript
|
|
448
|
+
* import { Hono } from 'hono'
|
|
449
|
+
* import { rateLimit, KVRateLimitStorage } from '@dotdo/postgres/middleware'
|
|
450
|
+
*
|
|
451
|
+
* const app = new Hono<{ Bindings: { RATE_LIMIT_KV: KVNamespace } }>()
|
|
452
|
+
*
|
|
453
|
+
* // Rate limit by IP: 100 requests per minute
|
|
454
|
+
* app.use('*', rateLimit({
|
|
455
|
+
* requests: 100,
|
|
456
|
+
* windowMs: 60000,
|
|
457
|
+
* storage: new KVRateLimitStorage(env.RATE_LIMIT_KV),
|
|
458
|
+
* }))
|
|
459
|
+
*
|
|
460
|
+
* // Rate limit by user: 1000 requests per minute
|
|
461
|
+
* app.use('/api/*', rateLimit({
|
|
462
|
+
* requests: 1000,
|
|
463
|
+
* windowMs: 60000,
|
|
464
|
+
* keyMode: 'user',
|
|
465
|
+
* userHeader: 'Authorization',
|
|
466
|
+
* }))
|
|
467
|
+
* ```
|
|
468
|
+
*/
|
|
469
|
+
export function rateLimit(options: RateLimitOptions = {}): MiddlewareHandler {
|
|
470
|
+
const opts = {
|
|
471
|
+
...DEFAULT_OPTIONS,
|
|
472
|
+
...options,
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Use in-memory storage if none provided (not recommended for production)
|
|
476
|
+
const storage = opts.storage ?? new InMemoryRateLimitStorage()
|
|
477
|
+
|
|
478
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
479
|
+
requests: opts.requests,
|
|
480
|
+
windowMs: opts.windowMs,
|
|
481
|
+
subWindows: opts.subWindows,
|
|
482
|
+
storage,
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
return async (c, next) => {
|
|
486
|
+
// Check if should skip rate limiting
|
|
487
|
+
if (options.skip) {
|
|
488
|
+
const shouldSkip = await options.skip(c as HonoContext)
|
|
489
|
+
if (shouldSkip) {
|
|
490
|
+
return next()
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Extract rate limit key
|
|
495
|
+
let key: string | null = null
|
|
496
|
+
switch (opts.keyMode) {
|
|
497
|
+
case 'ip':
|
|
498
|
+
key = extractIP(c as HonoContext, opts.ipHeader)
|
|
499
|
+
break
|
|
500
|
+
case 'user':
|
|
501
|
+
key = extractUser(c as HonoContext, opts.userHeader)
|
|
502
|
+
break
|
|
503
|
+
case 'custom':
|
|
504
|
+
if (options.keyExtractor) {
|
|
505
|
+
key = options.keyExtractor(c as HonoContext)
|
|
506
|
+
}
|
|
507
|
+
break
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// If no key could be extracted, skip rate limiting
|
|
511
|
+
if (!key) {
|
|
512
|
+
return next()
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Add prefix to key
|
|
516
|
+
const fullKey = `${opts.keyPrefix}${key}`
|
|
517
|
+
|
|
518
|
+
// Check rate limit
|
|
519
|
+
const info = await limiter.check(fullKey)
|
|
520
|
+
|
|
521
|
+
// Set rate limit headers
|
|
522
|
+
c.header('X-RateLimit-Limit', String(info.limit))
|
|
523
|
+
c.header('X-RateLimit-Remaining', String(info.remaining))
|
|
524
|
+
c.header('X-RateLimit-Reset', String(info.resetAfterSeconds))
|
|
525
|
+
|
|
526
|
+
// Store rate limit info in context for downstream use
|
|
527
|
+
c.set('rateLimitInfo', info)
|
|
528
|
+
|
|
529
|
+
if (info.limited) {
|
|
530
|
+
// Set Retry-After header (required for 429 responses)
|
|
531
|
+
c.header('Retry-After', String(info.resetAfterSeconds))
|
|
532
|
+
|
|
533
|
+
// Return rate limited response
|
|
534
|
+
if (options.onRateLimited) {
|
|
535
|
+
return options.onRateLimited(c as HonoContext, info)
|
|
536
|
+
}
|
|
537
|
+
return createRateLimitedResponse(c as HonoContext, info)
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
return next()
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Create rate limit middleware with Durable Object storage
|
|
546
|
+
*/
|
|
547
|
+
export function rateLimitWithDO(
|
|
548
|
+
storage: DurableObjectStorage,
|
|
549
|
+
options: Omit<RateLimitOptions, 'storage'> = {}
|
|
550
|
+
): MiddlewareHandler {
|
|
551
|
+
return rateLimit({
|
|
552
|
+
...options,
|
|
553
|
+
storage: new DurableObjectRateLimitStorage(storage),
|
|
554
|
+
})
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Create rate limit middleware with KV storage
|
|
559
|
+
*/
|
|
560
|
+
export function rateLimitWithKV(
|
|
561
|
+
kv: KVNamespace,
|
|
562
|
+
options: Omit<RateLimitOptions, 'storage'> = {}
|
|
563
|
+
): MiddlewareHandler {
|
|
564
|
+
return rateLimit({
|
|
565
|
+
...options,
|
|
566
|
+
storage: new KVRateLimitStorage(kv),
|
|
567
|
+
})
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// ============================================================================
|
|
571
|
+
// Token Bucket Algorithm (Alternative)
|
|
572
|
+
// ============================================================================
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Token bucket data structure
|
|
576
|
+
*/
|
|
577
|
+
export interface TokenBucket {
|
|
578
|
+
/** Current number of tokens */
|
|
579
|
+
tokens: number
|
|
580
|
+
/** Last refill timestamp (ms) */
|
|
581
|
+
lastRefill: number
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Token bucket options
|
|
586
|
+
*/
|
|
587
|
+
export interface TokenBucketOptions {
|
|
588
|
+
/**
|
|
589
|
+
* Maximum tokens in the bucket (burst capacity)
|
|
590
|
+
* @default 10
|
|
591
|
+
*/
|
|
592
|
+
bucketSize?: number
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Tokens added per second (refill rate)
|
|
596
|
+
* @default 1
|
|
597
|
+
*/
|
|
598
|
+
tokensPerSecond?: number
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Tokens consumed per request
|
|
602
|
+
* @default 1
|
|
603
|
+
*/
|
|
604
|
+
tokensPerRequest?: number
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Key extraction mode
|
|
608
|
+
* @default 'ip'
|
|
609
|
+
*/
|
|
610
|
+
keyMode?: RateLimitKeyMode
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Custom key extractor
|
|
614
|
+
*/
|
|
615
|
+
keyExtractor?: (c: HonoContext) => string | null
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Key prefix for storage
|
|
619
|
+
* @default 'tokenbucket:'
|
|
620
|
+
*/
|
|
621
|
+
keyPrefix?: string
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Header to extract IP from
|
|
625
|
+
* @default 'CF-Connecting-IP'
|
|
626
|
+
*/
|
|
627
|
+
ipHeader?: string
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Header for user ID
|
|
631
|
+
* @default 'X-User-ID'
|
|
632
|
+
*/
|
|
633
|
+
userHeader?: string
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Skip function
|
|
637
|
+
*/
|
|
638
|
+
skip?: (c: HonoContext) => boolean | Promise<boolean>
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Custom response handler
|
|
642
|
+
*/
|
|
643
|
+
onRateLimited?: (c: HonoContext, info: TokenBucketInfo) => Response | Promise<Response>
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Storage backend for token bucket data.
|
|
647
|
+
* Use TokenBucketStorage implementations (InMemoryTokenBucketStorage, DurableObjectTokenBucketStorage, KVTokenBucketStorage)
|
|
648
|
+
* for type-safe storage, or GenericRateLimitStorage<TokenBucket> for custom implementations.
|
|
649
|
+
*/
|
|
650
|
+
storage?: TokenBucketStorage
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Token bucket status information
|
|
655
|
+
*/
|
|
656
|
+
export interface TokenBucketInfo {
|
|
657
|
+
/** Maximum tokens (bucket size) */
|
|
658
|
+
bucketSize: number
|
|
659
|
+
/** Current available tokens */
|
|
660
|
+
tokens: number
|
|
661
|
+
/** Tokens consumed per request */
|
|
662
|
+
tokensPerRequest: number
|
|
663
|
+
/** Seconds until bucket is full */
|
|
664
|
+
refillsInSeconds: number
|
|
665
|
+
/** Whether the request was rate limited */
|
|
666
|
+
limited: boolean
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Token bucket storage type
|
|
671
|
+
*/
|
|
672
|
+
export type TokenBucketStorage = GenericRateLimitStorage<TokenBucket>
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Token bucket rate limiter implementation
|
|
676
|
+
*
|
|
677
|
+
* Classic token bucket algorithm:
|
|
678
|
+
* - Bucket starts full with N tokens
|
|
679
|
+
* - Each request consumes tokens
|
|
680
|
+
* - Tokens are added at a constant rate
|
|
681
|
+
* - Allows bursts up to bucket size
|
|
682
|
+
*/
|
|
683
|
+
export class TokenBucketRateLimiter {
|
|
684
|
+
private bucketSize: number
|
|
685
|
+
private tokensPerSecond: number
|
|
686
|
+
private tokensPerRequest: number
|
|
687
|
+
private storage: TokenBucketStorage
|
|
688
|
+
|
|
689
|
+
constructor(options: Required<Pick<TokenBucketOptions, 'bucketSize' | 'tokensPerSecond' | 'tokensPerRequest'>> & { storage: TokenBucketStorage }) {
|
|
690
|
+
this.bucketSize = options.bucketSize
|
|
691
|
+
this.tokensPerSecond = options.tokensPerSecond
|
|
692
|
+
this.tokensPerRequest = options.tokensPerRequest
|
|
693
|
+
this.storage = options.storage
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Check if a request should be rate limited
|
|
698
|
+
*/
|
|
699
|
+
async check(key: string): Promise<TokenBucketInfo> {
|
|
700
|
+
const now = Date.now()
|
|
701
|
+
const existing = await this.storage.get(key)
|
|
702
|
+
|
|
703
|
+
let bucket: TokenBucket
|
|
704
|
+
if (existing) {
|
|
705
|
+
// Refill tokens based on time elapsed
|
|
706
|
+
const elapsed = (now - existing.lastRefill) / 1000
|
|
707
|
+
const refilled = elapsed * this.tokensPerSecond
|
|
708
|
+
bucket = {
|
|
709
|
+
tokens: Math.min(this.bucketSize, existing.tokens + refilled),
|
|
710
|
+
lastRefill: now,
|
|
711
|
+
}
|
|
712
|
+
} else {
|
|
713
|
+
// New bucket starts full
|
|
714
|
+
bucket = {
|
|
715
|
+
tokens: this.bucketSize,
|
|
716
|
+
lastRefill: now,
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const limited = bucket.tokens < this.tokensPerRequest
|
|
721
|
+
|
|
722
|
+
if (!limited) {
|
|
723
|
+
// Consume tokens
|
|
724
|
+
bucket.tokens -= this.tokensPerRequest
|
|
725
|
+
await this.storage.set(key, bucket, 3600000) // 1 hour TTL
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Calculate time until bucket is full
|
|
729
|
+
const tokensNeeded = this.bucketSize - bucket.tokens
|
|
730
|
+
const refillsInSeconds = Math.ceil(tokensNeeded / this.tokensPerSecond)
|
|
731
|
+
|
|
732
|
+
return {
|
|
733
|
+
bucketSize: this.bucketSize,
|
|
734
|
+
tokens: Math.floor(bucket.tokens),
|
|
735
|
+
tokensPerRequest: this.tokensPerRequest,
|
|
736
|
+
refillsInSeconds,
|
|
737
|
+
limited,
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/** Default token bucket options */
|
|
743
|
+
const DEFAULT_TOKEN_BUCKET_OPTIONS: Required<Omit<TokenBucketOptions, 'keyExtractor' | 'skip' | 'onRateLimited' | 'storage'>> = {
|
|
744
|
+
bucketSize: 10,
|
|
745
|
+
tokensPerSecond: 1,
|
|
746
|
+
tokensPerRequest: 1,
|
|
747
|
+
keyMode: 'ip',
|
|
748
|
+
keyPrefix: 'tokenbucket:',
|
|
749
|
+
ipHeader: 'CF-Connecting-IP',
|
|
750
|
+
userHeader: 'X-User-ID',
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Create token bucket rate limiting middleware
|
|
755
|
+
*
|
|
756
|
+
* @example
|
|
757
|
+
* ```typescript
|
|
758
|
+
* import { tokenBucket, KVRateLimitStorage } from '@dotdo/postgres/middleware'
|
|
759
|
+
*
|
|
760
|
+
* // Allow bursts of 10 requests, refill at 1/second
|
|
761
|
+
* app.use('*', tokenBucket({
|
|
762
|
+
* bucketSize: 10,
|
|
763
|
+
* tokensPerSecond: 1,
|
|
764
|
+
* storage: new KVRateLimitStorage(env.RATE_LIMIT_KV),
|
|
765
|
+
* }))
|
|
766
|
+
* ```
|
|
767
|
+
*/
|
|
768
|
+
export function tokenBucket(options: TokenBucketOptions = {}): MiddlewareHandler {
|
|
769
|
+
const opts = {
|
|
770
|
+
...DEFAULT_TOKEN_BUCKET_OPTIONS,
|
|
771
|
+
...options,
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// Use provided token bucket storage or default in-memory storage
|
|
775
|
+
const storage: TokenBucketStorage = opts.storage ?? new InMemoryTokenBucketStorage()
|
|
776
|
+
|
|
777
|
+
const limiter = new TokenBucketRateLimiter({
|
|
778
|
+
bucketSize: opts.bucketSize,
|
|
779
|
+
tokensPerSecond: opts.tokensPerSecond,
|
|
780
|
+
tokensPerRequest: opts.tokensPerRequest,
|
|
781
|
+
storage,
|
|
782
|
+
})
|
|
783
|
+
|
|
784
|
+
return async (c, next) => {
|
|
785
|
+
if (options.skip) {
|
|
786
|
+
const shouldSkip = await options.skip(c as HonoContext)
|
|
787
|
+
if (shouldSkip) {
|
|
788
|
+
return next()
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
let key: string | null = null
|
|
793
|
+
switch (opts.keyMode) {
|
|
794
|
+
case 'ip':
|
|
795
|
+
key = extractIP(c as HonoContext, opts.ipHeader)
|
|
796
|
+
break
|
|
797
|
+
case 'user':
|
|
798
|
+
key = extractUser(c as HonoContext, opts.userHeader)
|
|
799
|
+
break
|
|
800
|
+
case 'custom':
|
|
801
|
+
if (options.keyExtractor) {
|
|
802
|
+
key = options.keyExtractor(c as HonoContext)
|
|
803
|
+
}
|
|
804
|
+
break
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
if (!key) {
|
|
808
|
+
return next()
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
const fullKey = `${opts.keyPrefix}${key}`
|
|
812
|
+
const info = await limiter.check(fullKey)
|
|
813
|
+
|
|
814
|
+
c.header('X-RateLimit-Limit', String(info.bucketSize))
|
|
815
|
+
c.header('X-RateLimit-Remaining', String(info.tokens))
|
|
816
|
+
c.header('X-RateLimit-Reset', String(info.refillsInSeconds))
|
|
817
|
+
|
|
818
|
+
c.set('tokenBucketInfo', info)
|
|
819
|
+
|
|
820
|
+
if (info.limited) {
|
|
821
|
+
c.header('Retry-After', String(Math.ceil(info.tokensPerRequest / opts.tokensPerSecond)))
|
|
822
|
+
|
|
823
|
+
if (options.onRateLimited) {
|
|
824
|
+
return options.onRateLimited(c as HonoContext, info)
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
return c.json(
|
|
828
|
+
{
|
|
829
|
+
error: true,
|
|
830
|
+
code: 'RATE_LIMITED',
|
|
831
|
+
message: 'Too many requests. Please try again later.',
|
|
832
|
+
retryAfter: Math.ceil(info.tokensPerRequest / opts.tokensPerSecond),
|
|
833
|
+
},
|
|
834
|
+
429
|
|
835
|
+
)
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
return next()
|
|
839
|
+
}
|
|
840
|
+
}
|