pipework 0.251.0 → 0.252.1
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/CHANGELOG.md +11 -0
- package/dist/core/config/load.d.ts +2 -0
- package/dist/core/config/load.d.ts.map +1 -1
- package/dist/core/config/load.js +1 -0
- package/dist/core/config/load.js.map +1 -1
- package/dist/core/config/namespace.d.ts +1 -0
- package/dist/core/config/namespace.d.ts.map +1 -1
- package/dist/core/config/schema.d.ts +2 -0
- package/dist/core/config/schema.d.ts.map +1 -1
- package/dist/core/config/schema.js +1 -0
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/surface/types.d.ts +1 -0
- package/dist/core/surface/types.d.ts.map +1 -1
- package/dist/data/db/namespace.d.ts +3 -0
- package/dist/data/db/namespace.d.ts.map +1 -1
- package/dist/data/db/namespace.js +3 -0
- package/dist/data/db/namespace.js.map +1 -1
- package/dist/data/db/pool.d.ts.map +1 -1
- package/dist/data/db/pool.js +6 -1
- package/dist/data/db/pool.js.map +1 -1
- package/dist/data/db/query-label.d.ts +5 -0
- package/dist/data/db/query-label.d.ts.map +1 -0
- package/dist/data/db/query-label.js +11 -0
- package/dist/data/db/query-label.js.map +1 -0
- package/dist/data/db/query-watch.d.ts +21 -0
- package/dist/data/db/query-watch.d.ts.map +1 -0
- package/dist/data/db/query-watch.js +90 -0
- package/dist/data/db/query-watch.js.map +1 -0
- package/dist/data/query/postgres-js/driver.js +1 -1
- package/dist/data/query/postgres-js/driver.js.map +1 -1
- package/dist/data/query/postgres-js/session.d.ts +5 -1
- package/dist/data/query/postgres-js/session.d.ts.map +1 -1
- package/dist/data/query/postgres-js/session.js +16 -11
- package/dist/data/query/postgres-js/session.js.map +1 -1
- package/dist/data/query/utils.d.ts +2 -0
- package/dist/data/query/utils.d.ts.map +1 -1
- package/dist/data/query/utils.js.map +1 -1
- package/dist/infra/credits/schema.d.ts +1 -1
- package/dist/test/plugin.d.ts.map +1 -1
- package/dist/test/plugin.js +10 -4
- package/dist/test/plugin.js.map +1 -1
- package/package.json +4 -3
- package/src/async/jobs/abortable-delay.ts +18 -0
- package/src/async/jobs/claims.ts +52 -0
- package/src/async/jobs/cron.ts +179 -0
- package/src/async/jobs/errors.ts +56 -0
- package/src/async/jobs/exclusion.ts +117 -0
- package/src/async/jobs/execute.ts +219 -0
- package/src/async/jobs/index.ts +10 -0
- package/src/async/jobs/listener.ts +135 -0
- package/src/async/jobs/namespace.ts +20 -0
- package/src/async/jobs/queue-door.ts +44 -0
- package/src/async/jobs/queue.ts +1012 -0
- package/src/async/jobs/run-script.ts +67 -0
- package/src/async/jobs/scheduler.ts +218 -0
- package/src/async/jobs/schedules-table.ts +37 -0
- package/src/async/jobs/serialize-error.ts +48 -0
- package/src/async/jobs/table.ts +191 -0
- package/src/async/pipeline/define.ts +53 -0
- package/src/async/pipeline/errors.ts +35 -0
- package/src/async/pipeline/execute.ts +53 -0
- package/src/async/pipeline/index.ts +13 -0
- package/src/async/pipeline/namespace.ts +12 -0
- package/src/async/pipeline/resume.ts +67 -0
- package/src/async/pipeline/run-steps.ts +98 -0
- package/src/async/pipeline/types.ts +57 -0
- package/src/async/state-machine/define.ts +64 -0
- package/src/async/state-machine/errors.ts +29 -0
- package/src/async/state-machine/index.ts +3 -0
- package/src/async/state-machine/namespace.ts +12 -0
- package/src/async/state-machine/transition.ts +90 -0
- package/src/async/state-machine/types.ts +37 -0
- package/src/async/steps/errors.ts +31 -0
- package/src/async/steps/graph.ts +1214 -0
- package/src/async/steps/hash.ts +40 -0
- package/src/async/steps/index.ts +7 -0
- package/src/async/steps/namespace.ts +7 -0
- package/src/async/steps/table.ts +97 -0
- package/src/async/steps/types.ts +318 -0
- package/src/audit/chain/index.ts +9 -0
- package/src/audit/chain/install.ts +113 -0
- package/src/audit/chain/retire.ts +52 -0
- package/src/audit/chain/verify.ts +257 -0
- package/src/audit/query/cursor.ts +37 -0
- package/src/audit/query/index.ts +9 -0
- package/src/audit/query/query.ts +223 -0
- package/src/audit/schema/audit-record-fields.ts +68 -0
- package/src/audit/schema/audit-record.ts +23 -0
- package/src/auth/auth/audit.ts +31 -0
- package/src/auth/auth/chain.ts +84 -0
- package/src/auth/auth/cookie.ts +136 -0
- package/src/auth/auth/email-links.ts +311 -0
- package/src/auth/auth/guard.ts +128 -0
- package/src/auth/auth/index.ts +18 -0
- package/src/auth/auth/multi-org.ts +337 -0
- package/src/auth/auth/namespace.ts +34 -0
- package/src/auth/auth/parse-expiry.ts +13 -0
- package/src/auth/auth/passwords.ts +110 -0
- package/src/auth/auth/schema.ts +110 -0
- package/src/auth/auth/sessions.ts +565 -0
- package/src/auth/auth/sign-in.ts +156 -0
- package/src/auth/auth/signing-keys.ts +69 -0
- package/src/auth/auth/types.ts +26 -0
- package/src/auth/auth/uuid.ts +10 -0
- package/src/auth/rbac/cache.ts +55 -0
- package/src/auth/rbac/check.ts +30 -0
- package/src/auth/rbac/create.ts +35 -0
- package/src/auth/rbac/index.ts +5 -0
- package/src/auth/rbac/middleware.ts +20 -0
- package/src/auth/rbac/namespace.ts +15 -0
- package/src/auth/rbac/resolve.ts +31 -0
- package/src/auth/rbac/schema.sql +31 -0
- package/src/auth/rbac/seed.ts +67 -0
- package/src/auth/rbac/tables.ts +32 -0
- package/src/auth/rbac/types.ts +65 -0
- package/src/auth/tenant/extract.ts +33 -0
- package/src/auth/tenant/in-tenant.ts +49 -0
- package/src/auth/tenant/index.ts +7 -0
- package/src/auth/tenant/namespace.ts +23 -0
- package/src/auth/tenant/propagate.ts +20 -0
- package/src/auth/tenant/rls.ts +120 -0
- package/src/auth/tenant/scope.ts +33 -0
- package/src/auth/tenant/scoped-db.ts +581 -0
- package/src/auth/tenant/types.ts +14 -0
- package/src/auth/tenant/validate.ts +27 -0
- package/src/cli/commands/add.ts +158 -0
- package/src/cli/commands/alerts.ts +98 -0
- package/src/cli/commands/check.ts +1418 -0
- package/src/cli/commands/codemod.ts +78 -0
- package/src/cli/commands/db.ts +356 -0
- package/src/cli/commands/dev.ts +101 -0
- package/src/cli/commands/generate.ts +75 -0
- package/src/cli/commands/init.ts +36 -0
- package/src/cli/commands/install.ts +28 -0
- package/src/cli/commands/lint.ts +62 -0
- package/src/cli/commands/migrate.ts +132 -0
- package/src/cli/commands/openapi.ts +63 -0
- package/src/cli/commands/remove.ts +72 -0
- package/src/cli/commands/run.ts +50 -0
- package/src/cli/commands/scope.ts +54 -0
- package/src/cli/commands/serve.ts +68 -0
- package/src/cli/commands/shard.ts +31 -0
- package/src/cli/commands/shared/config-pipework-version.ts +28 -0
- package/src/cli/commands/shared/find-config.ts +22 -0
- package/src/cli/commands/shared/load-config.ts +35 -0
- package/src/cli/commands/shared/pnpm-install.ts +95 -0
- package/src/cli/commands/shared/report-removed.ts +8 -0
- package/src/cli/commands/sync.ts +32 -0
- package/src/cli/commands/test.ts +307 -0
- package/src/cli/commands/upgrade.ts +48 -0
- package/src/cli/dev-bootstrap.ts +24 -0
- package/src/cli/errors.ts +10 -0
- package/src/cli/index.ts +303 -0
- package/src/cli/output.ts +17 -0
- package/src/cli/port.ts +15 -0
- package/src/cli/surface-kinds.ts +20 -0
- package/src/client/index.ts +4 -0
- package/src/client/poll.ts +130 -0
- package/src/client/report-fault.ts +119 -0
- package/src/core/config/app-pool.ts +19 -0
- package/src/core/config/aws-env.ts +29 -0
- package/src/core/config/base-dir.ts +24 -0
- package/src/core/config/discover.ts +64 -0
- package/src/core/config/env-resolve.ts +87 -0
- package/src/core/config/env-types.ts +116 -0
- package/src/core/config/env.ts +55 -0
- package/src/core/config/errors.ts +9 -0
- package/src/core/config/import-config.ts +40 -0
- package/src/core/config/index.ts +8 -0
- package/src/core/config/load.ts +417 -0
- package/src/core/config/namespace.ts +14 -0
- package/src/core/config/resolve.ts +195 -0
- package/src/core/config/schema.ts +488 -0
- package/src/core/config/statement-observer.ts +48 -0
- package/src/core/config/ts-inline-hooks.ts +75 -0
- package/src/core/config/ts-register.ts +4 -0
- package/src/core/config/ts-resolve-hooks.ts +101 -0
- package/src/core/errors/base.ts +49 -0
- package/src/core/errors/http.ts +146 -0
- package/src/core/errors/index.ts +2 -0
- package/src/core/errors/namespace.ts +31 -0
- package/src/core/lifecycle/drain.ts +33 -0
- package/src/core/lifecycle/health.ts +72 -0
- package/src/core/lifecycle/index.ts +4 -0
- package/src/core/lifecycle/namespace.ts +7 -0
- package/src/core/lifecycle/startup.ts +102 -0
- package/src/core/lifecycle/types.ts +36 -0
- package/src/core/logging/context.ts +60 -0
- package/src/core/logging/error-chain.ts +68 -0
- package/src/core/logging/index.ts +5 -0
- package/src/core/logging/logger.ts +65 -0
- package/src/core/logging/namespace.ts +16 -0
- package/src/core/logging/proxy.ts +22 -0
- package/src/core/logging/redact-match.ts +24 -0
- package/src/core/logging/types.ts +47 -0
- package/src/core/pipework.ts +566 -0
- package/src/core/runtime/broker.ts +69 -0
- package/src/core/surface/http.ts +133 -0
- package/src/core/surface/index.ts +11 -0
- package/src/core/surface/job-timeout.ts +40 -0
- package/src/core/surface/namespace.ts +13 -0
- package/src/core/surface/script.ts +33 -0
- package/src/core/surface/start.ts +142 -0
- package/src/core/surface/types.ts +225 -0
- package/src/core/surface/validate.ts +88 -0
- package/src/core/surface/worker.ts +528 -0
- package/src/core/validation/connectivity.ts +49 -0
- package/src/core/validation/domain.ts +99 -0
- package/src/core/validation/index.ts +5 -0
- package/src/core/validation/queue-tables.ts +312 -0
- package/src/core/validation/rls-role.ts +138 -0
- package/src/core/validation/startup.ts +51 -0
- package/src/core/validation/surfaces.ts +65 -0
- package/src/core/validation/types.ts +25 -0
- package/src/data/db/advisory-lock.ts +55 -0
- package/src/data/db/aggregates.ts +172 -0
- package/src/data/db/array-elements.ts +111 -0
- package/src/data/db/bulk-set.ts +53 -0
- package/src/data/db/col/index.ts +14 -0
- package/src/data/db/composed.ts +53 -0
- package/src/data/db/db.ts +276 -0
- package/src/data/db/excluded.ts +16 -0
- package/src/data/db/expressions.ts +473 -0
- package/src/data/db/filter.ts +90 -0
- package/src/data/db/function-source.ts +114 -0
- package/src/data/db/identifiers.ts +16 -0
- package/src/data/db/idx/index.ts +9 -0
- package/src/data/db/in-list.ts +49 -0
- package/src/data/db/index.ts +9 -0
- package/src/data/db/insert-split.ts +137 -0
- package/src/data/db/instrumentation.ts +82 -0
- package/src/data/db/maintenance.ts +28 -0
- package/src/data/db/namespace.ts +107 -0
- package/src/data/db/owner-labels.ts +9 -0
- package/src/data/db/pool.ts +187 -0
- package/src/data/db/query-label.ts +13 -0
- package/src/data/db/query-watch.ts +116 -0
- package/src/data/db/raw-client-warning.ts +37 -0
- package/src/data/db/readonly.ts +23 -0
- package/src/data/db/reservation.ts +151 -0
- package/src/data/db/schema-features.ts +14 -0
- package/src/data/db/serializable.ts +83 -0
- package/src/data/db/sql.ts +1 -0
- package/src/data/db/timeouts.ts +76 -0
- package/src/data/db/types.ts +18 -0
- package/src/data/db/unbound.ts +33 -0
- package/src/data/db/values.ts +29 -0
- package/src/data/domain/brand.ts +15 -0
- package/src/data/domain/build-factory.ts +193 -0
- package/src/data/domain/build-schema.ts +161 -0
- package/src/data/domain/build-table.ts +355 -0
- package/src/data/domain/define.ts +239 -0
- package/src/data/domain/external-registry.ts +34 -0
- package/src/data/domain/external.ts +77 -0
- package/src/data/domain/field.ts +279 -0
- package/src/data/domain/index.ts +13 -0
- package/src/data/domain/naming.ts +6 -0
- package/src/data/domain/projections.ts +57 -0
- package/src/data/domain/trace-safe-projection.ts +31 -0
- package/src/data/domain/traits.ts +108 -0
- package/src/data/domain/types.ts +289 -0
- package/src/data/jsonb/composed.ts +18 -0
- package/src/data/jsonb/index.ts +1 -0
- package/src/data/jsonb/namespace.ts +30 -0
- package/src/data/jsonb/query.ts +86 -0
- package/src/data/migrate/append-only-generate.ts +47 -0
- package/src/data/migrate/applied.ts +47 -0
- package/src/data/migrate/apply.ts +309 -0
- package/src/data/migrate/check.ts +119 -0
- package/src/data/migrate/diff.ts +357 -0
- package/src/data/migrate/door-generate.ts +130 -0
- package/src/data/migrate/framework-rls.ts +58 -0
- package/src/data/migrate/generate.ts +201 -0
- package/src/data/migrate/history.ts +215 -0
- package/src/data/migrate/index.ts +9 -0
- package/src/data/migrate/internal-definitions.ts +175 -0
- package/src/data/migrate/post-process.ts +73 -0
- package/src/data/migrate/pragma.ts +73 -0
- package/src/data/migrate/provision-framework.ts +147 -0
- package/src/data/migrate/rls-generate.ts +61 -0
- package/src/data/migrate/run.ts +124 -0
- package/src/data/migrate/safety.ts +167 -0
- package/src/data/migrate/snapshot.ts +368 -0
- package/src/data/migrate/sql-emit.ts +392 -0
- package/src/data/migrate/statements.ts +312 -0
- package/src/data/query/alias.ts +126 -0
- package/src/data/query/batch.ts +8 -0
- package/src/data/query/cache/core/cache.ts +78 -0
- package/src/data/query/cache/core/index.ts +1 -0
- package/src/data/query/cache/core/types.ts +29 -0
- package/src/data/query/cache/readme.md +230 -0
- package/src/data/query/casing.ts +76 -0
- package/src/data/query/collation.ts +11 -0
- package/src/data/query/column-builder.ts +370 -0
- package/src/data/query/column.ts +150 -0
- package/src/data/query/entity.ts +42 -0
- package/src/data/query/errors.ts +33 -0
- package/src/data/query/index.ts +14 -0
- package/src/data/query/logger.ts +47 -0
- package/src/data/query/operations.ts +45 -0
- package/src/data/query/pg-core/alias.ts +12 -0
- package/src/data/query/pg-core/checks.ts +32 -0
- package/src/data/query/pg-core/columns/all.ts +71 -0
- package/src/data/query/pg-core/columns/bigint.ts +110 -0
- package/src/data/query/pg-core/columns/bigserial.ts +128 -0
- package/src/data/query/pg-core/columns/boolean.ts +43 -0
- package/src/data/query/pg-core/columns/char.ts +85 -0
- package/src/data/query/pg-core/columns/cidr.ts +43 -0
- package/src/data/query/pg-core/columns/common.ts +366 -0
- package/src/data/query/pg-core/columns/custom.ts +232 -0
- package/src/data/query/pg-core/columns/date.common.ts +15 -0
- package/src/data/query/pg-core/columns/date.ts +112 -0
- package/src/data/query/pg-core/columns/double-precision.ts +55 -0
- package/src/data/query/pg-core/columns/enum.ts +201 -0
- package/src/data/query/pg-core/columns/index.ts +35 -0
- package/src/data/query/pg-core/columns/inet.ts +43 -0
- package/src/data/query/pg-core/columns/int.common.ts +57 -0
- package/src/data/query/pg-core/columns/integer.ts +53 -0
- package/src/data/query/pg-core/columns/interval.ts +83 -0
- package/src/data/query/pg-core/columns/json.ts +58 -0
- package/src/data/query/pg-core/columns/jsonb.ts +56 -0
- package/src/data/query/pg-core/columns/line.ts +117 -0
- package/src/data/query/pg-core/columns/macaddr.ts +43 -0
- package/src/data/query/pg-core/columns/macaddr8.ts +43 -0
- package/src/data/query/pg-core/columns/numeric.ts +227 -0
- package/src/data/query/pg-core/columns/point.ts +127 -0
- package/src/data/query/pg-core/columns/postgis_extension/geometry.ts +119 -0
- package/src/data/query/pg-core/columns/postgis_extension/utils.ts +47 -0
- package/src/data/query/pg-core/columns/real.ts +58 -0
- package/src/data/query/pg-core/columns/serial.ts +55 -0
- package/src/data/query/pg-core/columns/smallint.ts +53 -0
- package/src/data/query/pg-core/columns/smallserial.ts +60 -0
- package/src/data/query/pg-core/columns/text.ts +67 -0
- package/src/data/query/pg-core/columns/time.ts +72 -0
- package/src/data/query/pg-core/columns/timestamp.ts +163 -0
- package/src/data/query/pg-core/columns/uuid.ts +51 -0
- package/src/data/query/pg-core/columns/varchar.ts +89 -0
- package/src/data/query/pg-core/columns/vector_extension/bit.ts +68 -0
- package/src/data/query/pg-core/columns/vector_extension/halfvec.ts +80 -0
- package/src/data/query/pg-core/columns/vector_extension/sparsevec.ts +67 -0
- package/src/data/query/pg-core/columns/vector_extension/vector.ts +80 -0
- package/src/data/query/pg-core/db.ts +674 -0
- package/src/data/query/pg-core/dialect.ts +1404 -0
- package/src/data/query/pg-core/expressions.ts +25 -0
- package/src/data/query/pg-core/foreign-keys.ts +130 -0
- package/src/data/query/pg-core/index.ts +21 -0
- package/src/data/query/pg-core/indexes.ts +276 -0
- package/src/data/query/pg-core/policies.ts +56 -0
- package/src/data/query/pg-core/primary-keys.ts +62 -0
- package/src/data/query/pg-core/query-builders/count.ts +86 -0
- package/src/data/query/pg-core/query-builders/delete.ts +293 -0
- package/src/data/query/pg-core/query-builders/index.ts +7 -0
- package/src/data/query/pg-core/query-builders/insert.ts +452 -0
- package/src/data/query/pg-core/query-builders/query-builder.ts +123 -0
- package/src/data/query/pg-core/query-builders/query.ts +157 -0
- package/src/data/query/pg-core/query-builders/raw.ts +49 -0
- package/src/data/query/pg-core/query-builders/refresh-materialized-view.ts +108 -0
- package/src/data/query/pg-core/query-builders/select.ts +1346 -0
- package/src/data/query/pg-core/query-builders/select.types.ts +437 -0
- package/src/data/query/pg-core/query-builders/update.ts +626 -0
- package/src/data/query/pg-core/roles.ts +41 -0
- package/src/data/query/pg-core/schema.ts +72 -0
- package/src/data/query/pg-core/sequence.ts +41 -0
- package/src/data/query/pg-core/session.ts +292 -0
- package/src/data/query/pg-core/subquery.ts +46 -0
- package/src/data/query/pg-core/table.ts +252 -0
- package/src/data/query/pg-core/unique-constraint.ts +73 -0
- package/src/data/query/pg-core/utils/array.ts +95 -0
- package/src/data/query/pg-core/utils/index.ts +1 -0
- package/src/data/query/pg-core/utils.ts +104 -0
- package/src/data/query/pg-core/view-base.ts +14 -0
- package/src/data/query/pg-core/view-common.ts +1 -0
- package/src/data/query/pg-core/view.ts +435 -0
- package/src/data/query/pg-core/with-builder.ts +41 -0
- package/src/data/query/postgres-js/README.md +46 -0
- package/src/data/query/postgres-js/array-parser.ts +45 -0
- package/src/data/query/postgres-js/driver-error-boundary.ts +149 -0
- package/src/data/query/postgres-js/driver.ts +163 -0
- package/src/data/query/postgres-js/index.ts +2 -0
- package/src/data/query/postgres-js/session.ts +234 -0
- package/src/data/query/primary-key.ts +11 -0
- package/src/data/query/query-builders/query-builder.ts +19 -0
- package/src/data/query/query-builders/select.types.ts +175 -0
- package/src/data/query/query-promise.ts +35 -0
- package/src/data/query/relations.ts +725 -0
- package/src/data/query/runnable-query.ts +12 -0
- package/src/data/query/selection-proxy.ts +121 -0
- package/src/data/query/session.ts +8 -0
- package/src/data/query/sql/expressions/conditions.ts +741 -0
- package/src/data/query/sql/expressions/index.ts +2 -0
- package/src/data/query/sql/expressions/select.ts +45 -0
- package/src/data/query/sql/functions/aggregate.ts +129 -0
- package/src/data/query/sql/functions/index.ts +2 -0
- package/src/data/query/sql/functions/vector.ts +178 -0
- package/src/data/query/sql/index.ts +3 -0
- package/src/data/query/sql/sql.ts +794 -0
- package/src/data/query/subquery.ts +53 -0
- package/src/data/query/table.ts +208 -0
- package/src/data/query/table.utils.ts +2 -0
- package/src/data/query/tracing-utils.ts +3 -0
- package/src/data/query/tracing.ts +11 -0
- package/src/data/query/utils.ts +357 -0
- package/src/data/query/version.ts +4 -0
- package/src/data/query/view-common.ts +1 -0
- package/src/data/schema/branded.ts +13 -0
- package/src/data/schema/generated/coerce.ts +5 -0
- package/src/data/schema/generated/combinator.ts +6 -0
- package/src/data/schema/generated/encoding.ts +5 -0
- package/src/data/schema/generated/error.ts +6 -0
- package/src/data/schema/generated/format.ts +5 -0
- package/src/data/schema/generated/type-constructor.ts +10 -0
- package/src/data/schema/generated/type.ts +6 -0
- package/src/data/schema/index.ts +6 -0
- package/src/data/schema/json-schema.ts +33 -0
- package/src/data/schema/namespace.ts +55 -0
- package/src/data/schema/parse.ts +39 -0
- package/src/data/schema/types.ts +39 -0
- package/src/data/temporal/append-only.ts +134 -0
- package/src/data/temporal/close.ts +27 -0
- package/src/data/temporal/columns.ts +10 -0
- package/src/data/temporal/definition-queries.ts +70 -0
- package/src/data/temporal/errors.ts +10 -0
- package/src/data/temporal/get-current.ts +22 -0
- package/src/data/temporal/index.ts +9 -0
- package/src/data/temporal/namespace.ts +36 -0
- package/src/data/temporal/query.ts +25 -0
- package/src/data/temporal/resolve.ts +17 -0
- package/src/data/temporal/revise.ts +67 -0
- package/src/data/temporal/types.ts +22 -0
- package/src/data/valve/artifact.ts +33 -0
- package/src/data/valve/contract-diff.ts +21 -0
- package/src/data/valve/cross.ts +57 -0
- package/src/data/valve/crossing-ledger.ts +50 -0
- package/src/data/valve/decision.ts +44 -0
- package/src/data/valve/durable-crossing.ts +52 -0
- package/src/data/valve/execute-crossing.ts +77 -0
- package/src/data/valve/faucet.ts +56 -0
- package/src/data/valve/gate.ts +114 -0
- package/src/data/valve/graph.ts +77 -0
- package/src/data/valve/index.ts +53 -0
- package/src/data/valve/namespace.ts +57 -0
- package/src/data/valve/registry.ts +50 -0
- package/src/data/valve/schema/valve-crossing-fields.ts +23 -0
- package/src/data/valve/schema/valve-crossing.ts +9 -0
- package/src/data/valve/supply.ts +154 -0
- package/src/data/valve/types.ts +143 -0
- package/src/data/vector/columns.ts +27 -0
- package/src/data/vector/index.ts +4 -0
- package/src/data/vector/namespace.ts +33 -0
- package/src/data/vector/query.ts +85 -0
- package/src/data/vector/validate.ts +16 -0
- package/src/data/write/audit/actor.ts +15 -0
- package/src/data/write/audit/audit-columns.ts +18 -0
- package/src/data/write/audit/audit-select.ts +111 -0
- package/src/data/write/audit/bound-transaction.ts +14 -0
- package/src/data/write/audit/cte-compile.ts +32 -0
- package/src/data/write/audit/decode-returning.ts +47 -0
- package/src/data/write/audit/final-select.ts +43 -0
- package/src/data/write/audit/infra-audit.ts +36 -0
- package/src/data/write/audit/primary-key.ts +65 -0
- package/src/data/write/audit/projection.ts +41 -0
- package/src/data/write/audit/read-touches.ts +86 -0
- package/src/data/write/audit/touch-match.ts +78 -0
- package/src/data/write/audit/verb-delete.ts +62 -0
- package/src/data/write/audit/verb-insert.ts +36 -0
- package/src/data/write/audit/verb-select.ts +47 -0
- package/src/data/write/audit/verb-update.ts +60 -0
- package/src/data/write/audit/verb-upsert.ts +104 -0
- package/src/data/write/conflict.ts +43 -0
- package/src/data/write/delete.ts +38 -0
- package/src/data/write/execute.ts +243 -0
- package/src/data/write/index.ts +11 -0
- package/src/data/write/insert.ts +63 -0
- package/src/data/write/state.ts +43 -0
- package/src/data/write/update.ts +54 -0
- package/src/data/write/upsert.ts +58 -0
- package/src/data/write/values.ts +19 -0
- package/src/index.ts +230 -0
- package/src/infra/access-links/code.ts +70 -0
- package/src/infra/access-links/handle.ts +892 -0
- package/src/infra/access-links/index.ts +9 -0
- package/src/infra/access-links/namespace.ts +30 -0
- package/src/infra/access-links/person-check.ts +177 -0
- package/src/infra/access-links/schema.ts +71 -0
- package/src/infra/alerts/async-sources.ts +231 -0
- package/src/infra/alerts/audit.ts +36 -0
- package/src/infra/alerts/beat.ts +123 -0
- package/src/infra/alerts/client-faults.ts +111 -0
- package/src/infra/alerts/faults.ts +156 -0
- package/src/infra/alerts/handle.ts +778 -0
- package/src/infra/alerts/http.ts +192 -0
- package/src/infra/alerts/index.ts +12 -0
- package/src/infra/alerts/infra-sources.ts +180 -0
- package/src/infra/alerts/namespace.ts +81 -0
- package/src/infra/alerts/redact.ts +21 -0
- package/src/infra/alerts/request-faults.ts +41 -0
- package/src/infra/alerts/schema.ts +124 -0
- package/src/infra/alerts/sinks.ts +125 -0
- package/src/infra/alerts/source-options.ts +26 -0
- package/src/infra/alerts/sources.ts +503 -0
- package/src/infra/alerts/subsystem-sources.ts +137 -0
- package/src/infra/audit/emit.ts +87 -0
- package/src/infra/audit/index.ts +2 -0
- package/src/infra/audit/namespace.ts +22 -0
- package/src/infra/audit/schema.sql +35 -0
- package/src/infra/audit/types.ts +18 -0
- package/src/infra/aws/credentials.ts +147 -0
- package/src/infra/aws/sigv4.ts +140 -0
- package/src/infra/cache/create.ts +58 -0
- package/src/infra/cache/entry.ts +81 -0
- package/src/infra/cache/index.ts +4 -0
- package/src/infra/cache/namespace.ts +10 -0
- package/src/infra/cache/tenant.ts +93 -0
- package/src/infra/cache/types.ts +24 -0
- package/src/infra/crawl/audit.ts +35 -0
- package/src/infra/crawl/errors.ts +25 -0
- package/src/infra/crawl/handle.ts +693 -0
- package/src/infra/crawl/index.ts +9 -0
- package/src/infra/crawl/links.ts +160 -0
- package/src/infra/crawl/namespace.ts +36 -0
- package/src/infra/crawl/robots.ts +100 -0
- package/src/infra/crawl/schema.ts +89 -0
- package/src/infra/credit-line/handle.ts +883 -0
- package/src/infra/credit-line/index.ts +6 -0
- package/src/infra/credit-line/namespace.ts +7 -0
- package/src/infra/credit-line/schema.ts +96 -0
- package/src/infra/credits/handle.ts +706 -0
- package/src/infra/credits/index.ts +5 -0
- package/src/infra/credits/namespace.ts +7 -0
- package/src/infra/credits/schema.ts +83 -0
- package/src/infra/email/audit.ts +36 -0
- package/src/infra/email/inbound.ts +622 -0
- package/src/infra/email/index.ts +11 -0
- package/src/infra/email/mail.ts +517 -0
- package/src/infra/email/mime.ts +447 -0
- package/src/infra/email/namespace.ts +22 -0
- package/src/infra/email/providers.ts +111 -0
- package/src/infra/email/schema.ts +96 -0
- package/src/infra/email/sns.ts +200 -0
- package/src/infra/email/unsubscribe.ts +44 -0
- package/src/infra/fetch/address.ts +88 -0
- package/src/infra/fetch/connect-retry.ts +87 -0
- package/src/infra/fetch/handle.ts +329 -0
- package/src/infra/fetch/index.ts +7 -0
- package/src/infra/fetch/namespace.ts +70 -0
- package/src/infra/idempotency/index.ts +3 -0
- package/src/infra/idempotency/middleware.ts +87 -0
- package/src/infra/idempotency/store.ts +92 -0
- package/src/infra/idempotency/types.ts +30 -0
- package/src/infra/join-requests/handle.ts +312 -0
- package/src/infra/join-requests/index.ts +2 -0
- package/src/infra/join-requests/namespace.ts +7 -0
- package/src/infra/join-requests/schema.ts +33 -0
- package/src/infra/outbox/core.ts +165 -0
- package/src/infra/quota/errors.ts +32 -0
- package/src/infra/quota/handle.ts +215 -0
- package/src/infra/quota/index.ts +5 -0
- package/src/infra/quota/namespace.ts +7 -0
- package/src/infra/quota/schema.ts +15 -0
- package/src/infra/storage/backend.ts +34 -0
- package/src/infra/storage/handle.ts +513 -0
- package/src/infra/storage/index.ts +9 -0
- package/src/infra/storage/local.ts +104 -0
- package/src/infra/storage/namespace.ts +13 -0
- package/src/infra/storage/s3.ts +257 -0
- package/src/infra/storage/schema.ts +24 -0
- package/src/infra/support/handle.ts +854 -0
- package/src/infra/support/http.ts +229 -0
- package/src/infra/support/index.ts +7 -0
- package/src/infra/support/namespace.ts +12 -0
- package/src/infra/support/schema.ts +96 -0
- package/src/infra/webhook/inbound.ts +45 -0
- package/src/infra/webhook/index.ts +5 -0
- package/src/infra/webhook/namespace.ts +24 -0
- package/src/infra/webhook/outbound.ts +315 -0
- package/src/infra/webhook/sign.ts +32 -0
- package/src/infra/webhook/verify.ts +82 -0
- package/src/invariants/assert.ts +26 -0
- package/src/invariants/index.ts +1 -0
- package/src/lint/config.ts +56 -0
- package/src/lint/doctrine.ts +163 -0
- package/src/lint/include.ts +97 -0
- package/src/lint/index.ts +3 -0
- package/src/lint/preset.ts +10 -0
- package/src/lint/resolver.ts +218 -0
- package/src/lint/rules/no-reexports.ts +46 -0
- package/src/request/behavior/audited.ts +85 -0
- package/src/request/behavior/cached.ts +62 -0
- package/src/request/behavior/compose.ts +28 -0
- package/src/request/behavior/index.ts +5 -0
- package/src/request/behavior/namespace.ts +16 -0
- package/src/request/behavior/types.ts +26 -0
- package/src/request/behavior/versioned.ts +54 -0
- package/src/request/context/create.ts +103 -0
- package/src/request/context/guard.ts +49 -0
- package/src/request/context/index.ts +4 -0
- package/src/request/context/run-in-transaction.ts +200 -0
- package/src/request/context/store.ts +28 -0
- package/src/request/context/types.ts +50 -0
- package/src/request/di/builder.ts +535 -0
- package/src/request/di/index.ts +8 -0
- package/src/request/di/resolve.ts +271 -0
- package/src/request/di/types.ts +262 -0
- package/src/request/fitting/namespace.ts +7 -0
- package/src/request/fixture/batch.ts +71 -0
- package/src/request/fixture/builder.ts +26 -0
- package/src/request/fixture/errors.ts +10 -0
- package/src/request/fixture/index.ts +8 -0
- package/src/request/fixture/namespace.ts +23 -0
- package/src/request/fixture/paginate.ts +44 -0
- package/src/request/fixture/to-handlers.ts +260 -0
- package/src/request/fixture/types.ts +79 -0
- package/src/request/flow/act-as.ts +78 -0
- package/src/request/flow/namespace.ts +17 -0
- package/src/request/http/error-step.ts +42 -0
- package/src/request/http/file.ts +141 -0
- package/src/request/http/index.ts +4 -0
- package/src/request/http/middleware.ts +141 -0
- package/src/request/http/namespace.ts +5 -0
- package/src/request/http/rate-limit-classes.ts +170 -0
- package/src/request/http/response.ts +82 -0
- package/src/request/http/server.ts +916 -0
- package/src/request/http/sniff.ts +261 -0
- package/src/request/http/types.ts +250 -0
- package/src/request/http/upload.ts +284 -0
- package/src/request/internal/text.ts +6 -0
- package/src/request/openapi/generate.ts +205 -0
- package/src/request/openapi/index.ts +2 -0
- package/src/request/openapi/namespace.ts +7 -0
- package/src/test/auth.ts +13 -0
- package/src/test/auto-setup.ts +45 -0
- package/src/test/context.ts +91 -0
- package/src/test/crawl-fixture.ts +157 -0
- package/src/test/discover-fork.ts +17 -0
- package/src/test/fingerprint.ts +135 -0
- package/src/test/globals.d.ts +7 -0
- package/src/test/index.ts +19 -0
- package/src/test/namespace.ts +87 -0
- package/src/test/plugin.ts +189 -0
- package/src/test/progress.ts +185 -0
- package/src/test/reap-after-run.ts +28 -0
- package/src/test/reap.ts +286 -0
- package/src/test/reset.ts +253 -0
- package/src/test/savepoints.ts +172 -0
- package/src/test/setup.ts +1422 -0
- package/src/test/system-channel.ts +50 -0
- package/src/test/vitest-plugin.ts +142 -0
- package/src/test/vitest-workspace.ts +507 -0
- package/src/test/vitest.ts +333 -0
- package/src/test/watch.ts +105 -0
- package/src/trace/capture/bounded-serializer.ts +146 -0
- package/src/trace/cardinality/analyze.ts +173 -0
- package/src/trace/cardinality/branch-context.ts +214 -0
- package/src/trace/cardinality/check.ts +33 -0
- package/src/trace/cardinality/classify-edge.ts +64 -0
- package/src/trace/cardinality/structural-max.ts +107 -0
- package/src/trace/check/coverage-check.ts +188 -0
- package/src/trace/check/flow-check.ts +103 -0
- package/src/trace/check/flow-step-site.ts +234 -0
- package/src/trace/check/io-pattern.ts +116 -0
- package/src/trace/codemod/add-cardinality.ts +152 -0
- package/src/trace/codemod/run.ts +80 -0
- package/src/trace/entry/child-trace.ts +21 -0
- package/src/trace/entry/close-trace.ts +87 -0
- package/src/trace/entry/finalize-trace.ts +28 -0
- package/src/trace/entry/open-trace.ts +138 -0
- package/src/trace/entry/parent-trace.ts +20 -0
- package/src/trace/entry/parse-traceparent.ts +39 -0
- package/src/trace/entry/process-start.ts +38 -0
- package/src/trace/entry/trace-context.ts +26 -0
- package/src/trace/entry/tracing-enabled.ts +10 -0
- package/src/trace/external/record.ts +195 -0
- package/src/trace/external/report.ts +66 -0
- package/src/trace/namespace.ts +19 -0
- package/src/trace/partition/day.ts +47 -0
- package/src/trace/partition/index.ts +14 -0
- package/src/trace/partition/partition-name.ts +23 -0
- package/src/trace/partition/plan.ts +82 -0
- package/src/trace/partition/schedule.ts +26 -0
- package/src/trace/partition/startup-hook.ts +39 -0
- package/src/trace/partition/sync.ts +154 -0
- package/src/trace/partition/tables.ts +53 -0
- package/src/trace/read/tree.ts +83 -0
- package/src/trace/retain/copy-on-error.ts +76 -0
- package/src/trace/runtime/expire-stale-traces.ts +54 -0
- package/src/trace/runtime/flow-step.ts +147 -0
- package/src/trace/runtime/flush-steps.ts +31 -0
- package/src/trace/runtime/pending-writes.ts +54 -0
- package/src/trace/runtime/step-buffer.ts +298 -0
- package/src/trace/runtime/step-error.ts +21 -0
- package/src/trace/runtime/step-meta.ts +55 -0
- package/src/trace/runtime/thenable.ts +12 -0
- package/src/trace/runtime/truncate-trace.ts +62 -0
- package/src/trace/schema/trace-fields.ts +52 -0
- package/src/trace/schema/trace-retained.ts +22 -0
- package/src/trace/schema/trace-step-fields.ts +44 -0
- package/src/trace/schema/trace-step-retained.ts +25 -0
- package/src/trace/schema/trace-step.ts +18 -0
- package/src/trace/schema/trace.ts +12 -0
- package/src/trace/transformer/apply.ts +79 -0
- package/src/trace/transformer/build-meta-literal.ts +30 -0
- package/src/trace/transformer/find-flow-step-sites.ts +85 -0
- package/src/trace/transformer/inject-flow-step-import.ts +39 -0
- package/src/trace/transformer/transform-error.ts +14 -0
- package/src/trace/transformer/transform-flow-steps.ts +123 -0
- package/src/trace/transformer/wrap-function-declaration.ts +62 -0
- package/src/trace/transformer/wrap-variable-declaration.ts +67 -0
- package/src/workspace/affected.ts +110 -0
- package/src/workspace/changed-files.ts +163 -0
- package/src/workspace/check-deps.ts +213 -0
- package/src/workspace/checksum.ts +20 -0
- package/src/workspace/dependency-graph.ts +67 -0
- package/src/workspace/detect-pipework-copies.ts +93 -0
- package/src/workspace/discover.ts +206 -0
- package/src/workspace/generate.ts +401 -0
- package/src/workspace/index.ts +7 -0
- package/src/workspace/module-imports-pipework.ts +39 -0
- package/src/workspace/module-package-name.ts +12 -0
- package/src/workspace/scrub-git-env.ts +23 -0
- package/src/workspace/source-paths.ts +36 -0
- package/src/workspace/sync.ts +182 -0
- package/dist/REFERENCE.md +0 -1477
- package/dist/infra/access-links/rate-limit.d.ts +0 -10
- package/dist/infra/access-links/rate-limit.d.ts.map +0 -1
- package/dist/infra/access-links/rate-limit.js +0 -28
- package/dist/infra/access-links/rate-limit.js.map +0 -1
- package/dist/infra/email/sigv4.d.ts +0 -24
- package/dist/infra/email/sigv4.d.ts.map +0 -1
- package/dist/infra/email/sigv4.js +0 -55
- package/dist/infra/email/sigv4.js.map +0 -1
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { join, resolve } from 'node:path'
|
|
3
|
+
import { pathToFileURL } from 'node:url'
|
|
4
|
+
import { glob } from 'node:fs/promises'
|
|
5
|
+
import type { ResolvedDatabase, ResolvedDoor } from '../../core/config/load.js'
|
|
6
|
+
import { ConfigError } from '../../core/config/errors.js'
|
|
7
|
+
import { postProcessMigration } from './post-process.js'
|
|
8
|
+
import { diffDoors, doorSnapshots } from './door-generate.js'
|
|
9
|
+
import { generateRlsStatements } from './rls-generate.js'
|
|
10
|
+
import { generateAppendOnlyStatements } from './append-only-generate.js'
|
|
11
|
+
import { definitions } from '../domain/index.js'
|
|
12
|
+
import { buildSnapshot } from './snapshot.js'
|
|
13
|
+
import { deltaPath, listMigrations, readFoldedSnapshot, snapshotDelta } from './history.js'
|
|
14
|
+
import { diffSnapshots, diffOpTableName } from './diff.js'
|
|
15
|
+
import { emitSQL } from './sql-emit.js'
|
|
16
|
+
import { PARTITIONED_TRACE_TABLE_NAMES } from '../../trace/partition/tables.js'
|
|
17
|
+
import { AUTH_TABLE_NAMES } from '../../auth/auth/schema.js'
|
|
18
|
+
import { EMAIL_TABLE_NAMES } from '../../infra/email/schema.js'
|
|
19
|
+
import { SCHEDULE_TABLE_NAMES } from '../../async/jobs/schedules-table.js'
|
|
20
|
+
|
|
21
|
+
// Schema files are import()ed below. They may already be in Node's ESM module
|
|
22
|
+
// cache because `discoverInstance` transitively pulled them in (any surface or
|
|
23
|
+
// handler that imports a defined table loads the schema file along with it).
|
|
24
|
+
// A second evaluation would call pipe.define() again and crash on the registry
|
|
25
|
+
// duplicate-name guard, so we rely on the cache: previously-loaded files
|
|
26
|
+
// resolve to their cached exports (define() has already populated the registry
|
|
27
|
+
// from that first load); files reached only by the glob are evaluated fresh.
|
|
28
|
+
|
|
29
|
+
export interface GenerateResult {
|
|
30
|
+
database: string
|
|
31
|
+
migrationFile: string | null
|
|
32
|
+
snapshotFile: string | null
|
|
33
|
+
statements: number
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function generateForDatabase(
|
|
37
|
+
dbConfig: ResolvedDatabase,
|
|
38
|
+
migrationName?: string,
|
|
39
|
+
internalDefinitions?: () => Promise<Record<string, unknown>>,
|
|
40
|
+
doors: readonly ResolvedDoor[] | (() => readonly ResolvedDoor[]) = [],
|
|
41
|
+
): Promise<GenerateResult> {
|
|
42
|
+
if (dbConfig.schema === undefined) {
|
|
43
|
+
throw new ConfigError(
|
|
44
|
+
`Database "${dbConfig.name}" has no schema path configured.`,
|
|
45
|
+
`Add a schema path to your database config:\n\n` +
|
|
46
|
+
` databases: {\n` +
|
|
47
|
+
` ${dbConfig.name}: {\n` +
|
|
48
|
+
` url: '...',\n` +
|
|
49
|
+
` schema: './src/db/schema.ts', // <-- add this\n` +
|
|
50
|
+
` migrations: '...',\n` +
|
|
51
|
+
` },\n` +
|
|
52
|
+
` }\n`,
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (dbConfig.migrations === undefined) {
|
|
57
|
+
throw new ConfigError(
|
|
58
|
+
`Database "${dbConfig.name}" has no migrations path configured.`,
|
|
59
|
+
`Add a migrations path to your database config:\n\n` +
|
|
60
|
+
` databases: {\n` +
|
|
61
|
+
` ${dbConfig.name}: {\n` +
|
|
62
|
+
` url: '...',\n` +
|
|
63
|
+
` schema: '...',\n` +
|
|
64
|
+
` migrations: './migrations/${dbConfig.name}', // <-- add this\n` +
|
|
65
|
+
` },\n` +
|
|
66
|
+
` }\n`,
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const schemaFiles = await resolveSchemaFiles(dbConfig.schema, dbConfig.baseDir)
|
|
71
|
+
|
|
72
|
+
if (schemaFiles.length === 0) {
|
|
73
|
+
const patterns = Array.isArray(dbConfig.schema) ? dbConfig.schema.join(', ') : dbConfig.schema
|
|
74
|
+
throw new ConfigError(
|
|
75
|
+
`No schema files found for database "${dbConfig.name}".`,
|
|
76
|
+
`Pattern(s): ${patterns}\n\n Check the "schema" path in your database config.`,
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ResolvedDatabase.migrations is absolute (resolved against baseDir at
|
|
81
|
+
// config-load time) — cwd plays no part.
|
|
82
|
+
const migrationsDir = dbConfig.migrations
|
|
83
|
+
const metaDir = join(migrationsDir, 'meta')
|
|
84
|
+
|
|
85
|
+
mkdirSync(metaDir, { recursive: true })
|
|
86
|
+
|
|
87
|
+
const imports: Record<string, unknown> = {}
|
|
88
|
+
for (const file of schemaFiles) {
|
|
89
|
+
const url = pathToFileURL(file).href
|
|
90
|
+
const mod: Record<string, unknown> = await import(url)
|
|
91
|
+
for (const [key, value] of Object.entries(mod)) {
|
|
92
|
+
imports[key] = value
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// A thunk, invoked only AFTER the schema-file import loop: queue tables
|
|
97
|
+
// register at createQueue() time, and a queue module reached only by the
|
|
98
|
+
// schema glob registers during the loop above. Materializing the internal
|
|
99
|
+
// definitions before the imports (as the CLI once did) silently dropped
|
|
100
|
+
// those queues from the migration (D2, subseam audit 2026-07-16).
|
|
101
|
+
if (internalDefinitions !== undefined) {
|
|
102
|
+
for (const [key, value] of Object.entries(await internalDefinitions())) {
|
|
103
|
+
imports[key] = value
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const prevSnapshot = readFoldedSnapshot(migrationsDir)
|
|
108
|
+
const currentSnapshot = buildSnapshot(imports, prevSnapshot.id)
|
|
109
|
+
// Doors are not tables, so the table diff never sees them: their policies are
|
|
110
|
+
// diffed against the doors the previous snapshot recorded.
|
|
111
|
+
const currentDoors = doorSnapshots(typeof doors === 'function' ? doors() : doors, dbConfig.rls?.platformRole, definitions())
|
|
112
|
+
const doorStatements = diffDoors(prevSnapshot.doors, currentDoors)
|
|
113
|
+
if (Object.keys(currentDoors).length > 0 || prevSnapshot.doors !== undefined) currentSnapshot.doors = currentDoors
|
|
114
|
+
const ops = diffSnapshots(prevSnapshot, currentSnapshot)
|
|
115
|
+
// Framework-owned partitioned tables (the trace family) stay in the snapshot
|
|
116
|
+
// but are never emitted into an application migration: they are PARTITION BY
|
|
117
|
+
// RANGE, and a bare CREATE TABLE leaves a partitioned table that rejects every
|
|
118
|
+
// insert with "no partition found". pipework provisions them — parent plus day
|
|
119
|
+
// partitions — itself. Issue #313.
|
|
120
|
+
const emittableOps = ops.filter(op => !PARTITIONED_TRACE_TABLE_NAMES.has(diffOpTableName(op)))
|
|
121
|
+
const statements = emitSQL(emittableOps).map(idempotentAuthTable)
|
|
122
|
+
|
|
123
|
+
if (statements.length === 0 && doorStatements.length === 0) {
|
|
124
|
+
return {
|
|
125
|
+
database: dbConfig.name,
|
|
126
|
+
migrationFile: null,
|
|
127
|
+
snapshotFile: null,
|
|
128
|
+
statements: 0,
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const tag = freeTag(migrationsDir, migrationName)
|
|
133
|
+
|
|
134
|
+
const joined = statements.map(s => s + ';').join('\n')
|
|
135
|
+
const withTenantRls = dbConfig.rls !== undefined
|
|
136
|
+
? generateRlsStatements(joined, definitions(), dbConfig.rls.sessionVar, dbConfig.rls.force)
|
|
137
|
+
: joined
|
|
138
|
+
// After the tenant policies: a door's policy goes on a table that is row-secured by then.
|
|
139
|
+
const withRls = doorStatements.length > 0
|
|
140
|
+
? `${withTenantRls}${withTenantRls === '' ? '' : '\n\n'}${doorStatements.map(s => s + ';').join('\n')}`
|
|
141
|
+
: withTenantRls
|
|
142
|
+
const withAppendOnly = generateAppendOnlyStatements(withRls, definitions())
|
|
143
|
+
const sqlContent = postProcessMigration(withAppendOnly)
|
|
144
|
+
const migrationFile = join(migrationsDir, `${tag}.sql`)
|
|
145
|
+
writeFileSync(migrationFile, sqlContent, 'utf-8')
|
|
146
|
+
|
|
147
|
+
const snapshotFile = deltaPath(migrationsDir, tag)
|
|
148
|
+
writeFileSync(snapshotFile, JSON.stringify(snapshotDelta(prevSnapshot, currentSnapshot), null, 2), 'utf-8')
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
database: dbConfig.name,
|
|
152
|
+
migrationFile,
|
|
153
|
+
snapshotFile,
|
|
154
|
+
statements: statements.length + doorStatements.length,
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// The session, org, email and schedules tables predate their definitions: apps
|
|
159
|
+
// copied them by hand from SQL files. Their CREATE statements are IF NOT EXISTS so the first
|
|
160
|
+
// generated migration applies over those tables.
|
|
161
|
+
const AUTH_CREATE_RE = /^CREATE\s+(TABLE|(?:UNIQUE\s+)?INDEX)\s+("(?:[^"]|"")+")(\s+ON\s+"([^"]+)")?/
|
|
162
|
+
|
|
163
|
+
export function idempotentAuthTable(statement: string): string {
|
|
164
|
+
const m = AUTH_CREATE_RE.exec(statement)
|
|
165
|
+
if (m === null) return statement
|
|
166
|
+
const table = m[1] === 'TABLE' ? m[2]!.slice(1, -1) : m[4]
|
|
167
|
+
if (table === undefined || !(AUTH_TABLE_NAMES.has(table) || EMAIL_TABLE_NAMES.has(table) || SCHEDULE_TABLE_NAMES.has(table))) return statement
|
|
168
|
+
return statement.replace(AUTH_CREATE_RE, (_all, kind: string, name: string, on: string | undefined) =>
|
|
169
|
+
`CREATE ${kind} IF NOT EXISTS ${name}${on ?? ''}`)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** `YYYYMMDDHHMMSS[_slug]` from the UTC clock, moved forward a second at a time until no migration holds that timestamp. */
|
|
173
|
+
function freeTag(migrationsDir: string, name?: string): string {
|
|
174
|
+
const taken = new Set(listMigrations(migrationsDir).map(m => m.tag.slice(0, 14)))
|
|
175
|
+
const slug = name === undefined ? '' : name.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '')
|
|
176
|
+
const at = new Date()
|
|
177
|
+
at.setUTCMilliseconds(0)
|
|
178
|
+
for (;;) {
|
|
179
|
+
const stamp = at.toISOString().replace(/\D/g, '').slice(0, 14)
|
|
180
|
+
if (!taken.has(stamp)) return slug === '' ? stamp : `${stamp}_${slug}`
|
|
181
|
+
at.setTime(at.getTime() + 1000)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function resolveSchemaFiles(schema: string | string[], baseDir: string): Promise<string[]> {
|
|
186
|
+
const patterns = Array.isArray(schema) ? schema : [schema]
|
|
187
|
+
const files: string[] = []
|
|
188
|
+
|
|
189
|
+
for (const pattern of patterns) {
|
|
190
|
+
const abs = resolve(baseDir, pattern)
|
|
191
|
+
if (!pattern.includes('*')) {
|
|
192
|
+
if (existsSync(abs)) files.push(abs)
|
|
193
|
+
} else {
|
|
194
|
+
for await (const match of glob(pattern, { cwd: baseDir })) {
|
|
195
|
+
files.push(resolve(baseDir, match))
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return [...new Set(files)].sort()
|
|
201
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { EMPTY_SNAPSHOT, type PwSnapshot, type PwTableSnapshot, type PwPartitionSnapshot } from './snapshot.js'
|
|
4
|
+
import type { DoorSnapshot } from './door-generate.js'
|
|
5
|
+
|
|
6
|
+
export interface MigrationEntry {
|
|
7
|
+
tag: string
|
|
8
|
+
when: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const LEGACY_TAG = /^\d{4}(_|$)/
|
|
12
|
+
const TIMESTAMP_TAG = /^\d{14}(_|$)/
|
|
13
|
+
|
|
14
|
+
type Sub<K extends keyof PwTableSnapshot> = Record<string, NonNullable<PwTableSnapshot[K]> extends Record<string, infer V> ? V | null : never>
|
|
15
|
+
|
|
16
|
+
export interface TableDelta {
|
|
17
|
+
name: string
|
|
18
|
+
schema: string
|
|
19
|
+
partitionBy: PwPartitionSnapshot | null
|
|
20
|
+
columns: Sub<'columns'>
|
|
21
|
+
indexes: Sub<'indexes'>
|
|
22
|
+
foreignKeys: Sub<'foreignKeys'>
|
|
23
|
+
checks: Sub<'checks'>
|
|
24
|
+
uniqueConstraints: Sub<'uniqueConstraints'>
|
|
25
|
+
compositePrimaryKeys: Sub<'compositePrimaryKeys'>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SnapshotDelta {
|
|
29
|
+
version: 'pw1-delta'
|
|
30
|
+
tables: Record<string, TableDelta | null>
|
|
31
|
+
doors?: Record<string, DoorSnapshot | null>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const MAP_KEYS = ['columns', 'indexes', 'foreignKeys', 'checks', 'uniqueConstraints', 'compositePrimaryKeys'] as const
|
|
35
|
+
|
|
36
|
+
function readLegacyJournal(folder: string): { tag: string; when: number }[] | null {
|
|
37
|
+
const path = join(folder, 'meta', '_journal.json')
|
|
38
|
+
if (!existsSync(path)) return null
|
|
39
|
+
const journal = JSON.parse(readFileSync(path, 'utf-8')) as { entries?: { tag: string; when: number }[] }
|
|
40
|
+
return journal.entries ?? []
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The folder's migrations in apply order: legacy `NNNN` tags by index, then timestamp tags by time. */
|
|
44
|
+
export function listMigrations(folder: string): MigrationEntry[] {
|
|
45
|
+
if (!existsSync(folder)) return []
|
|
46
|
+
const tags = readdirSync(folder, { withFileTypes: true })
|
|
47
|
+
.filter(e => e.isFile() && e.name.endsWith('.sql'))
|
|
48
|
+
.map(e => e.name.slice(0, -'.sql'.length))
|
|
49
|
+
|
|
50
|
+
const legacy: string[] = []
|
|
51
|
+
const stamped: string[] = []
|
|
52
|
+
for (const tag of tags) {
|
|
53
|
+
if (TIMESTAMP_TAG.test(tag)) stamped.push(tag)
|
|
54
|
+
else if (LEGACY_TAG.test(tag)) legacy.push(tag)
|
|
55
|
+
else {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Migration file "${tag}.sql" in ${folder} is not named like a migration. ` +
|
|
58
|
+
`Expected "NNNN_name.sql" (legacy index) or "YYYYMMDDHHMMSS_name.sql" (UTC timestamp).`,
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const byText = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0)
|
|
63
|
+
legacy.sort((a, b) => Number(a.slice(0, 4)) - Number(b.slice(0, 4)) || byText(a, b))
|
|
64
|
+
stamped.sort((a, b) => byText(a.slice(0, 14), b.slice(0, 14)) || byText(a, b))
|
|
65
|
+
|
|
66
|
+
const journal = readLegacyJournal(folder)
|
|
67
|
+
if (journal !== null) {
|
|
68
|
+
for (const entry of journal) {
|
|
69
|
+
const path = `${folder}/${entry.tag}.sql`
|
|
70
|
+
if (!existsSync(path)) throw new Error(`Missing migration file: ${path}`)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const journalWhen = new Map((journal ?? []).map(e => [e.tag, e.when]))
|
|
74
|
+
|
|
75
|
+
return [
|
|
76
|
+
...legacy.map(tag => ({ tag, when: journalWhen.get(tag) ?? Number(tag.slice(0, 4)) })),
|
|
77
|
+
...stamped.map(tag => ({ tag, when: timestampMillis(tag) })),
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function timestampMillis(tag: string): number {
|
|
82
|
+
const p = (from: number, to: number): number => Number(tag.slice(from, to))
|
|
83
|
+
return Date.UTC(p(0, 4), p(4, 6) - 1, p(6, 8), p(8, 10), p(10, 12), p(12, 14))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function isTimestampTag(tag: string): boolean {
|
|
87
|
+
return TIMESTAMP_TAG.test(tag)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function deltaPath(folder: string, tag: string): string {
|
|
91
|
+
return join(folder, 'meta', `${tag}.delta.json`)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function stable(value: unknown): string {
|
|
95
|
+
return JSON.stringify(value, (_key, v: unknown) => {
|
|
96
|
+
if (v !== null && typeof v === 'object' && !Array.isArray(v)) {
|
|
97
|
+
return Object.fromEntries(Object.entries(v).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)))
|
|
98
|
+
}
|
|
99
|
+
return v
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function same(a: unknown, b: unknown): boolean {
|
|
104
|
+
return stable(a) === stable(b)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function diffMap<V>(prev: Record<string, V>, next: Record<string, V>): Record<string, V | null> {
|
|
108
|
+
const out: Record<string, V | null> = {}
|
|
109
|
+
for (const [key, value] of Object.entries(next)) {
|
|
110
|
+
if (!(key in prev) || !same(prev[key], value)) out[key] = value
|
|
111
|
+
}
|
|
112
|
+
for (const key of Object.keys(prev)) {
|
|
113
|
+
if (!(key in next)) out[key] = null
|
|
114
|
+
}
|
|
115
|
+
return out
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The element-level change from one snapshot to the next; only changed tables, elements and doors appear. */
|
|
119
|
+
export function snapshotDelta(prev: PwSnapshot, next: PwSnapshot): SnapshotDelta {
|
|
120
|
+
const tables: Record<string, TableDelta | null> = {}
|
|
121
|
+
for (const [key, table] of Object.entries(next.tables)) {
|
|
122
|
+
const before = prev.tables[key]
|
|
123
|
+
const empty = before === undefined
|
|
124
|
+
const delta = {
|
|
125
|
+
name: table.name,
|
|
126
|
+
schema: table.schema,
|
|
127
|
+
partitionBy: table.partitionBy ?? null,
|
|
128
|
+
columns: diffMap(before?.columns ?? {}, table.columns),
|
|
129
|
+
indexes: diffMap(before?.indexes ?? {}, table.indexes),
|
|
130
|
+
foreignKeys: diffMap(before?.foreignKeys ?? {}, table.foreignKeys),
|
|
131
|
+
checks: diffMap(before?.checks ?? {}, table.checks),
|
|
132
|
+
uniqueConstraints: diffMap(before?.uniqueConstraints ?? {}, table.uniqueConstraints),
|
|
133
|
+
compositePrimaryKeys: diffMap(before?.compositePrimaryKeys ?? {}, table.compositePrimaryKeys),
|
|
134
|
+
} as TableDelta
|
|
135
|
+
const changed = empty
|
|
136
|
+
|| before.name !== table.name
|
|
137
|
+
|| before.schema !== table.schema
|
|
138
|
+
|| !same(before.partitionBy ?? null, delta.partitionBy)
|
|
139
|
+
|| MAP_KEYS.some(k => Object.keys(delta[k]).length > 0)
|
|
140
|
+
if (changed) tables[key] = delta
|
|
141
|
+
}
|
|
142
|
+
for (const key of Object.keys(prev.tables)) {
|
|
143
|
+
if (!(key in next.tables)) tables[key] = null
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const delta: SnapshotDelta = { version: 'pw1-delta', tables }
|
|
147
|
+
if (next.doors !== undefined || prev.doors !== undefined) {
|
|
148
|
+
const doors = diffMap<DoorSnapshot>(prev.doors ?? {}, next.doors ?? {})
|
|
149
|
+
if (Object.keys(doors).length > 0) delta.doors = doors
|
|
150
|
+
}
|
|
151
|
+
return delta
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function applyMap<V>(base: Record<string, V>, changes: Record<string, V | null>): Record<string, V> {
|
|
155
|
+
const out: Record<string, V> = { ...base }
|
|
156
|
+
for (const [key, value] of Object.entries(changes)) {
|
|
157
|
+
if (value === null) delete out[key]
|
|
158
|
+
else out[key] = value
|
|
159
|
+
}
|
|
160
|
+
return out
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** `snap` with `delta` applied. Pure: the input is not modified. */
|
|
164
|
+
export function applyDelta(snap: PwSnapshot, delta: SnapshotDelta): PwSnapshot {
|
|
165
|
+
const tables: Record<string, PwTableSnapshot> = { ...snap.tables }
|
|
166
|
+
for (const [key, change] of Object.entries(delta.tables)) {
|
|
167
|
+
if (change === null) {
|
|
168
|
+
delete tables[key]
|
|
169
|
+
continue
|
|
170
|
+
}
|
|
171
|
+
const base = tables[key]
|
|
172
|
+
tables[key] = {
|
|
173
|
+
name: change.name,
|
|
174
|
+
schema: change.schema,
|
|
175
|
+
columns: applyMap(base?.columns ?? {}, change.columns),
|
|
176
|
+
indexes: applyMap(base?.indexes ?? {}, change.indexes),
|
|
177
|
+
foreignKeys: applyMap(base?.foreignKeys ?? {}, change.foreignKeys),
|
|
178
|
+
checks: applyMap(base?.checks ?? {}, change.checks),
|
|
179
|
+
uniqueConstraints: applyMap(base?.uniqueConstraints ?? {}, change.uniqueConstraints),
|
|
180
|
+
compositePrimaryKeys: applyMap(base?.compositePrimaryKeys ?? {}, change.compositePrimaryKeys),
|
|
181
|
+
partitionBy: change.partitionBy ?? undefined,
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const result: PwSnapshot = { ...snap, tables }
|
|
185
|
+
if (delta.doors !== undefined) {
|
|
186
|
+
result.doors = applyMap<DoorSnapshot>(snap.doors ?? {}, delta.doors) as NonNullable<PwSnapshot['doors']>
|
|
187
|
+
}
|
|
188
|
+
return result
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** The schema as of every migration in the folder: the legacy snapshot, then each timestamp migration's delta. */
|
|
192
|
+
export function readFoldedSnapshot(folder: string): PwSnapshot {
|
|
193
|
+
let snap = readLegacySnapshot(folder)
|
|
194
|
+
for (const { tag } of listMigrations(folder)) {
|
|
195
|
+
if (!isTimestampTag(tag)) continue
|
|
196
|
+
const path = deltaPath(folder, tag)
|
|
197
|
+
if (!existsSync(path)) {
|
|
198
|
+
throw new Error(`Missing snapshot delta ${path} for migration ${tag}.sql; the delta is written beside the migration by \`pipework generate\` and is committed with it.`)
|
|
199
|
+
}
|
|
200
|
+
snap = applyDelta(snap, JSON.parse(readFileSync(path, 'utf-8')) as SnapshotDelta)
|
|
201
|
+
}
|
|
202
|
+
return snap
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function readLegacySnapshot(folder: string): PwSnapshot {
|
|
206
|
+
const journal = readLegacyJournal(folder)
|
|
207
|
+
if (journal === null || journal.length === 0) return EMPTY_SNAPSHOT
|
|
208
|
+
const last = journal[journal.length - 1] as { idx?: number }
|
|
209
|
+
const idx = last.idx ?? journal.length - 1
|
|
210
|
+
const path = join(folder, 'meta', `${String(idx).padStart(4, '0')}_snapshot.json`)
|
|
211
|
+
if (!existsSync(path)) return EMPTY_SNAPSHOT
|
|
212
|
+
const raw = JSON.parse(readFileSync(path, 'utf-8')) as { version?: string }
|
|
213
|
+
if (raw.version === '7') return EMPTY_SNAPSHOT
|
|
214
|
+
return raw as PwSnapshot
|
|
215
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { migrateAll, migrateOne, UnsafeMigrationError, type MigrateResult, type MigrateOptions } from './run.js'
|
|
2
|
+
export { checkMigrations, formatCheckResult, type MigrationCheckResult, type FileHazards, type MigrationHazard, type Severity } from './check.js'
|
|
3
|
+
export { hasPragma, PRAGMA_FOR, type PragmaKind } from './pragma.js'
|
|
4
|
+
export { readAppliedState, type AppliedState } from './applied.js'
|
|
5
|
+
export { analyzeSQL } from './safety.js'
|
|
6
|
+
export { generateForDatabase, type GenerateResult } from './generate.js'
|
|
7
|
+
export { postProcessMigration } from './post-process.js'
|
|
8
|
+
export { generateRlsStatements } from './rls-generate.js'
|
|
9
|
+
export { generateAppendOnlyStatements } from './append-only-generate.js'
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// Pipework ships table DEFINITIONS for its own substrate — `trace`,
|
|
2
|
+
// `trace_step`, `trace_retained`, `trace_step_retained`, `audit_record` — but
|
|
3
|
+
// the migration generator only sees the consumer's `schema.ts` exports. Without
|
|
4
|
+
// this loader, enabling `trace: {}` or `audit: {}` in a blueprint produces a
|
|
5
|
+
// runtime crash on the first traced operation because the tables never reached
|
|
6
|
+
// the consumer's database. Loading is gated by the blueprint flags and by
|
|
7
|
+
// `isDefaultDatabase` because trace/audit always write to the default db.
|
|
8
|
+
|
|
9
|
+
import type { Blueprint } from '../../core/config/schema.js'
|
|
10
|
+
|
|
11
|
+
export async function loadInternalDefinitions(
|
|
12
|
+
blueprint: Blueprint,
|
|
13
|
+
options: { isDefaultDatabase: boolean },
|
|
14
|
+
): Promise<Record<string, unknown>> {
|
|
15
|
+
if (!options.isDefaultDatabase) return {}
|
|
16
|
+
|
|
17
|
+
const result: Record<string, unknown> = {}
|
|
18
|
+
|
|
19
|
+
if (blueprint.trace !== undefined) {
|
|
20
|
+
const { trace } = await import('../../trace/schema/trace.js')
|
|
21
|
+
const { traceStep } = await import('../../trace/schema/trace-step.js')
|
|
22
|
+
const { traceRetained } = await import('../../trace/schema/trace-retained.js')
|
|
23
|
+
const { traceStepRetained } = await import('../../trace/schema/trace-step-retained.js')
|
|
24
|
+
result['__pipework_trace'] = trace
|
|
25
|
+
result['__pipework_trace_step'] = traceStep
|
|
26
|
+
result['__pipework_trace_retained'] = traceRetained
|
|
27
|
+
result['__pipework_trace_step_retained'] = traceStepRetained
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (blueprint.audit !== undefined) {
|
|
31
|
+
const { auditRecord } = await import('../../audit/schema/audit-record.js')
|
|
32
|
+
result['__pipework_audit_record'] = auditRecord
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (blueprint.valve !== undefined) {
|
|
36
|
+
const { valveCrossing } = await import('../valve/schema/valve-crossing.js')
|
|
37
|
+
result['__pipework_valve_crossing'] = valveCrossing
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (blueprint.accessLinks !== undefined) {
|
|
41
|
+
const { accessLinkCode, accessLink, accessLinkUse, accessLinkCheckSpent, accessLinkMiss } = await import('../../infra/access-links/schema.js')
|
|
42
|
+
result['__pipework_access_link_code'] = accessLinkCode
|
|
43
|
+
result['__pipework_access_link'] = accessLink
|
|
44
|
+
result['__pipework_access_link_use'] = accessLinkUse
|
|
45
|
+
result['__pipework_access_link_check_spent'] = accessLinkCheckSpent
|
|
46
|
+
result['__pipework_access_link_miss'] = accessLinkMiss
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (blueprint.joinRequests !== undefined) {
|
|
50
|
+
const { joinRequest } = await import('../../infra/join-requests/schema.js')
|
|
51
|
+
result['__pipework_join_request'] = joinRequest
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (blueprint.credits !== undefined) {
|
|
55
|
+
const { creditGrant, creditReservation, creditDraw, creditLedger, creditAccount } = await import('../../infra/credits/schema.js')
|
|
56
|
+
result['__pipework_credit_grant'] = creditGrant
|
|
57
|
+
result['__pipework_credit_reservation'] = creditReservation
|
|
58
|
+
result['__pipework_credit_draw'] = creditDraw
|
|
59
|
+
result['__pipework_credit_ledger'] = creditLedger
|
|
60
|
+
result['__pipework_credit_account'] = creditAccount
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (blueprint.creditLine !== undefined) {
|
|
64
|
+
const {
|
|
65
|
+
creditLine, creditLineReservation, creditLineEntry, creditLinePayment, creditLinePaymentApplication, creditLineAuthorization,
|
|
66
|
+
} = await import('../../infra/credit-line/schema.js')
|
|
67
|
+
result['__pipework_credit_line'] = creditLine
|
|
68
|
+
result['__pipework_credit_line_reservation'] = creditLineReservation
|
|
69
|
+
result['__pipework_credit_line_entry'] = creditLineEntry
|
|
70
|
+
result['__pipework_credit_line_payment'] = creditLinePayment
|
|
71
|
+
result['__pipework_credit_line_payment_application'] = creditLinePaymentApplication
|
|
72
|
+
result['__pipework_credit_line_authorization'] = creditLineAuthorization
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (blueprint.quota !== undefined) {
|
|
76
|
+
const { outboundQuota } = await import('../../infra/quota/schema.js')
|
|
77
|
+
result['__pipework_outbound_quota'] = outboundQuota
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (blueprint.storage !== undefined) {
|
|
81
|
+
const { storageFile } = await import('../../infra/storage/schema.js')
|
|
82
|
+
result['__pipework_storage_file'] = storageFile
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (blueprint.crawl !== undefined) {
|
|
86
|
+
const { crawls, crawlUrls, crawlHosts, crawlResources } = await import('../../infra/crawl/schema.js')
|
|
87
|
+
result['__pipework_crawl'] = crawls
|
|
88
|
+
result['__pipework_crawl_url'] = crawlUrls
|
|
89
|
+
result['__pipework_crawl_host'] = crawlHosts
|
|
90
|
+
result['__pipework_crawl_resource'] = crawlResources
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (blueprint.alerts !== undefined) {
|
|
94
|
+
const { alerts, alertOccurrences, alertDeliveries, alertSourceState, unitFaults, loopBeats, faults } = await import('../../infra/alerts/schema.js')
|
|
95
|
+
result['__pipework_alerts'] = alerts
|
|
96
|
+
result['__pipework_alert_occurrences'] = alertOccurrences
|
|
97
|
+
result['__pipework_alert_deliveries'] = alertDeliveries
|
|
98
|
+
result['__pipework_alert_source_state'] = alertSourceState
|
|
99
|
+
result['__pipework_unit_faults'] = unitFaults
|
|
100
|
+
result['__pipework_loop_beats'] = loopBeats
|
|
101
|
+
result['__pipework_faults'] = faults
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (blueprint.support !== undefined) {
|
|
105
|
+
const { supportTicket, supportMessage, supportLink, supportEventDelivery } = await import('../../infra/support/schema.js')
|
|
106
|
+
result['__pipework_support_ticket'] = supportTicket
|
|
107
|
+
result['__pipework_support_message'] = supportMessage
|
|
108
|
+
result['__pipework_support_link'] = supportLink
|
|
109
|
+
result['__pipework_support_event_delivery'] = supportEventDelivery
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (blueprint.sessions !== undefined) {
|
|
113
|
+
const { refreshTokens, authVersions } = await import('../../auth/auth/schema.js')
|
|
114
|
+
result['__pipework_refresh_tokens'] = refreshTokens
|
|
115
|
+
result['__pipework_auth_versions'] = authVersions
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (blueprint.orgs !== undefined) {
|
|
119
|
+
const { userOrgs } = await import('../../auth/auth/schema.js')
|
|
120
|
+
result['__pipework_user_orgs'] = userOrgs
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (blueprint.passwords !== undefined) {
|
|
124
|
+
const { signinAttempts } = await import('../../auth/auth/schema.js')
|
|
125
|
+
result['__pipework_signin_attempts'] = signinAttempts
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (blueprint.guards !== undefined) {
|
|
129
|
+
const { guardAttempts } = await import('../../auth/auth/schema.js')
|
|
130
|
+
result['__pipework_guard_attempts'] = guardAttempts
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (blueprint.emailLinks !== undefined) {
|
|
134
|
+
const { emailLinks, emailLinkRequests } = await import('../../auth/auth/schema.js')
|
|
135
|
+
result['__pipework_email_links'] = emailLinks
|
|
136
|
+
result['__pipework_email_link_requests'] = emailLinkRequests
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (blueprint.rateLimits !== undefined) {
|
|
140
|
+
const { rateLimitCounts } = await import('../../request/http/rate-limit-classes.js')
|
|
141
|
+
result['__pipework_rate_limit_counts'] = rateLimitCounts
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (blueprint.email !== undefined) {
|
|
145
|
+
const { emailMessages, emailSuppressions, emailInbound, emailUnsubscribes } = await import('../../infra/email/schema.js')
|
|
146
|
+
result['__pipework_email_messages'] = emailMessages
|
|
147
|
+
result['__pipework_email_suppressions'] = emailSuppressions
|
|
148
|
+
result['__pipework_email_inbound'] = emailInbound
|
|
149
|
+
result['__pipework_email_unsubscribes'] = emailUnsubscribes
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Queue tables register at createQueue() time (worker surfaces create their
|
|
153
|
+
// queue at construction, so config discovery populates the registry before
|
|
154
|
+
// generate snapshots). No blueprint flag — presence in the registry means a
|
|
155
|
+
// queue is in use. Like trace/audit, queue tables are only emitted into the
|
|
156
|
+
// default database's migrations.
|
|
157
|
+
const { queueDefinitions } = await import('../../async/jobs/table.js')
|
|
158
|
+
for (const [name, definition] of queueDefinitions()) {
|
|
159
|
+
result[`__pipework_queue_${name}`] = definition
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Registered when a step graph is defined.
|
|
163
|
+
const { stepDefinitions } = await import('../../async/steps/table.js')
|
|
164
|
+
for (const [name, definition] of stepDefinitions()) {
|
|
165
|
+
result[`__pipework_${name}`] = definition
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Registered when a worker surface declaring schedules is constructed.
|
|
169
|
+
const { schedulesDefinitions } = await import('../../async/jobs/schedules-table.js')
|
|
170
|
+
for (const [name, definition] of schedulesDefinitions()) {
|
|
171
|
+
result[`__pipework_${name}`] = definition
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return result
|
|
175
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { stripComments, codeStartOffset } from './statements.js'
|
|
2
|
+
|
|
3
|
+
const CREATE_INDEX_RE = /\bCREATE\s+(UNIQUE\s+)?INDEX\b(?!\s+CONCURRENTLY)/i
|
|
4
|
+
const CONCURRENTLY_RE = /\bCONCURRENTLY\b/i
|
|
5
|
+
|
|
6
|
+
const NO_TRANSACTION_PRAGMA = '-- pipework:no-transaction'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Transform unsafe migration SQL emitted by the diff/sql-emit pipeline into
|
|
10
|
+
* safe SQL.
|
|
11
|
+
*
|
|
12
|
+
* `CREATE INDEX` → `CREATE INDEX CONCURRENTLY`, and the
|
|
13
|
+
* `-- pipework:no-transaction` pragma is prepended so the runner applies the
|
|
14
|
+
* migration outside a transaction (CONCURRENTLY cannot run inside one).
|
|
15
|
+
*
|
|
16
|
+
* Foreign-key safety (`NOT VALID` + `VALIDATE CONSTRAINT`) is decided upstream
|
|
17
|
+
* in `emitSQL`: Postgres rejects `NOT VALID` foreign keys on partitioned
|
|
18
|
+
* tables, and only the op metadata knows which tables are partitioned. A
|
|
19
|
+
* text-level pass here cannot tell, so it must not touch foreign keys. Issue #312.
|
|
20
|
+
*/
|
|
21
|
+
export function postProcessMigration(sql: string): string {
|
|
22
|
+
const parts = sql.split(';')
|
|
23
|
+
const trailing = parts[parts.length - 1]
|
|
24
|
+
const rawStatements = parts.slice(0, -1)
|
|
25
|
+
|
|
26
|
+
const outputStatements: string[] = []
|
|
27
|
+
let hasConcurrently = false
|
|
28
|
+
|
|
29
|
+
for (const raw of rawStatements) {
|
|
30
|
+
// Match against the SQL with comments removed, not against the raw
|
|
31
|
+
// fragment. A statement and the comment above it share a `;`-fragment, so
|
|
32
|
+
// skipping fragments that *start with* `--` skipped the statement too and
|
|
33
|
+
// a commented CREATE INDEX silently kept its exclusive lock (#334).
|
|
34
|
+
// Comment text is equally unable to fake a match it should not have.
|
|
35
|
+
const code = stripComments(raw)
|
|
36
|
+
if (code.trim().length === 0) {
|
|
37
|
+
outputStatements.push(raw)
|
|
38
|
+
continue
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (CREATE_INDEX_RE.test(code)) {
|
|
42
|
+
// Rewrite only from where the SQL actually starts, so a leading comment
|
|
43
|
+
// that happens to say "CREATE INDEX" is not the thing rewritten.
|
|
44
|
+
const offset = codeStartOffset(raw)
|
|
45
|
+
const rewritten =
|
|
46
|
+
raw.slice(0, offset) +
|
|
47
|
+
raw.slice(offset).replace(/\b(CREATE\s+(?:UNIQUE\s+)?)(INDEX)\b/i, '$1$2 CONCURRENTLY')
|
|
48
|
+
outputStatements.push(rewritten)
|
|
49
|
+
hasConcurrently = true
|
|
50
|
+
continue
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (CONCURRENTLY_RE.test(code)) {
|
|
54
|
+
hasConcurrently = true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
outputStatements.push(raw)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let result = outputStatements.join(';') + ';'
|
|
61
|
+
|
|
62
|
+
if (trailing !== undefined && trailing.trim().length > 0) {
|
|
63
|
+
result += trailing
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (hasConcurrently) {
|
|
67
|
+
result = result.startsWith(NO_TRANSACTION_PRAGMA)
|
|
68
|
+
? result
|
|
69
|
+
: `${NO_TRANSACTION_PRAGMA}\n${result}`
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result
|
|
73
|
+
}
|