pipework 0.252.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 +5 -0
- 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,103 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import type { Manifold } from '../../core/pipework.js'
|
|
3
|
+
import type { TraceContext } from '../../trace/entry/trace-context.js'
|
|
4
|
+
import type { Flow, RequestMetadata } from './types.js'
|
|
5
|
+
import type { TenantConfig } from '../../auth/tenant/types.js'
|
|
6
|
+
|
|
7
|
+
export interface CreateRequestContextOptions<TAuth = unknown> {
|
|
8
|
+
instance: Manifold
|
|
9
|
+
requestId?: string
|
|
10
|
+
auth?: TAuth | null
|
|
11
|
+
tenant?: string | null
|
|
12
|
+
user?: string | null
|
|
13
|
+
asOf?: string | null
|
|
14
|
+
metadata: RequestMetadata
|
|
15
|
+
trace?: TraceContext | null
|
|
16
|
+
tenantConfig?: TenantConfig | null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createRequestContext<TAuth = unknown>(
|
|
20
|
+
options: CreateRequestContextOptions<TAuth>,
|
|
21
|
+
): Flow<TAuth> {
|
|
22
|
+
return {
|
|
23
|
+
instance: options.instance,
|
|
24
|
+
requestId: options.requestId ?? randomUUID(),
|
|
25
|
+
_nonce: randomUUID(),
|
|
26
|
+
auth: options.auth ?? null,
|
|
27
|
+
tenant: options.tenant ?? null,
|
|
28
|
+
user: options.user ?? null,
|
|
29
|
+
asOf: options.asOf ?? null,
|
|
30
|
+
metadata: options.metadata,
|
|
31
|
+
jobType: null,
|
|
32
|
+
jobAttempt: null,
|
|
33
|
+
jobMaxAttempts: null,
|
|
34
|
+
tenantConfig: options.tenantConfig ?? null,
|
|
35
|
+
transactions: new Map(),
|
|
36
|
+
trace: options.trace ?? null,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface CreateJobContextOptions<TAuth = unknown> {
|
|
41
|
+
instance: Manifold
|
|
42
|
+
jobId?: string
|
|
43
|
+
jobType?: string
|
|
44
|
+
/** 1-based attempt number of the job. */
|
|
45
|
+
attempt?: number
|
|
46
|
+
/** The job's attempt limit. */
|
|
47
|
+
maxAttempts?: number
|
|
48
|
+
auth?: TAuth | null
|
|
49
|
+
tenant?: string | null
|
|
50
|
+
user?: string | null
|
|
51
|
+
asOf?: string | null
|
|
52
|
+
trace?: TraceContext | null
|
|
53
|
+
tenantConfig?: TenantConfig | null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function createJobContext<TAuth = unknown>(
|
|
57
|
+
options: CreateJobContextOptions<TAuth>,
|
|
58
|
+
): Flow<TAuth> {
|
|
59
|
+
return {
|
|
60
|
+
instance: options.instance,
|
|
61
|
+
requestId: options.jobId ?? randomUUID(),
|
|
62
|
+
_nonce: randomUUID(),
|
|
63
|
+
auth: options.auth ?? null,
|
|
64
|
+
tenant: options.tenant ?? null,
|
|
65
|
+
user: options.user ?? null,
|
|
66
|
+
asOf: options.asOf ?? null,
|
|
67
|
+
metadata: null,
|
|
68
|
+
jobType: options.jobType ?? null,
|
|
69
|
+
jobAttempt: options.attempt ?? null,
|
|
70
|
+
jobMaxAttempts: options.maxAttempts ?? null,
|
|
71
|
+
tenantConfig: options.tenantConfig ?? null,
|
|
72
|
+
transactions: new Map(),
|
|
73
|
+
trace: options.trace ?? null,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface CreateTestContextOptions {
|
|
78
|
+
auth?: unknown
|
|
79
|
+
tenant?: string | null | undefined
|
|
80
|
+
user?: string | null | undefined
|
|
81
|
+
asOf?: string | null | undefined
|
|
82
|
+
trace?: TraceContext | null
|
|
83
|
+
tenantConfig?: TenantConfig | null
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function createTestContext(instance: Manifold, requestId?: string, options?: CreateTestContextOptions): Flow {
|
|
87
|
+
return {
|
|
88
|
+
instance,
|
|
89
|
+
requestId: requestId ?? randomUUID(),
|
|
90
|
+
_nonce: randomUUID(),
|
|
91
|
+
auth: options?.auth ?? null,
|
|
92
|
+
tenant: options?.tenant ?? null,
|
|
93
|
+
user: options?.user ?? null,
|
|
94
|
+
asOf: options?.asOf ?? null,
|
|
95
|
+
metadata: null,
|
|
96
|
+
jobType: null,
|
|
97
|
+
jobAttempt: null,
|
|
98
|
+
jobMaxAttempts: null,
|
|
99
|
+
tenantConfig: options?.tenantConfig ?? null,
|
|
100
|
+
transactions: new Map(),
|
|
101
|
+
trace: options?.trace ?? null,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Flow, BoundTransaction } from './types.js'
|
|
2
|
+
import type { DB } from '../../data/db/index.js'
|
|
3
|
+
import { InvariantViolation } from '../../invariants/assert.js'
|
|
4
|
+
|
|
5
|
+
export function verifyTransactionBinding(
|
|
6
|
+
ctx: Flow,
|
|
7
|
+
bound: BoundTransaction,
|
|
8
|
+
dbName: string,
|
|
9
|
+
): void {
|
|
10
|
+
if (bound.nonce !== ctx._nonce) {
|
|
11
|
+
throw new InvariantViolation('context-nonce-mismatch', {
|
|
12
|
+
message:
|
|
13
|
+
`The transaction for database "${dbName}" was created in a different AsyncLocalStorage ` +
|
|
14
|
+
'context than the one currently active. This usually means Node.js swapped async contexts ' +
|
|
15
|
+
'between concurrent requests — a known ALS bug that can cause cross-tenant data leaks.',
|
|
16
|
+
transactionNonce: bound.nonce,
|
|
17
|
+
contextNonce: ctx._nonce,
|
|
18
|
+
database: dbName,
|
|
19
|
+
contextTenant: ctx.tenant,
|
|
20
|
+
requestId: ctx.requestId,
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (bound.tenant !== ctx.tenant) {
|
|
25
|
+
throw new InvariantViolation('tenant-context-mismatch', {
|
|
26
|
+
message:
|
|
27
|
+
`The transaction for database "${dbName}" was created for tenant "${bound.tenant}" ` +
|
|
28
|
+
`but the current context has tenant "${ctx.tenant}". This indicates an AsyncLocalStorage ` +
|
|
29
|
+
'context swap that would cause writes to go to the wrong tenant.\n\n' +
|
|
30
|
+
' In tests, use withFlow({ tenant }, fn) to run tenant-scoped code:\n\n' +
|
|
31
|
+
" import { withFlow, asTenant } from 'pipework/test'\n\n" +
|
|
32
|
+
" withFlow({ auth: asTenant('tenant-1'), tenant: 'tenant-1' }, async () => {\n" +
|
|
33
|
+
' // pipe() and useTestDb() work correctly here\n' +
|
|
34
|
+
' })',
|
|
35
|
+
transactionTenant: bound.tenant,
|
|
36
|
+
contextTenant: ctx.tenant,
|
|
37
|
+
database: dbName,
|
|
38
|
+
requestId: ctx.requestId,
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function bindTransaction(
|
|
44
|
+
ctx: Flow,
|
|
45
|
+
dbName: string,
|
|
46
|
+
drizzle: DB,
|
|
47
|
+
): BoundTransaction {
|
|
48
|
+
return { drizzle, nonce: ctx._nonce, tenant: ctx.tenant }
|
|
49
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { Flow, RequestMetadata, BoundTransaction } from './types.js'
|
|
2
|
+
export { flowStorage, getContext, requireContext, runInContext } from './store.js'
|
|
3
|
+
export { createRequestContext, createJobContext, createTestContext, type CreateRequestContextOptions, type CreateJobContextOptions } from './create.js'
|
|
4
|
+
export { verifyTransactionBinding, bindTransaction } from './guard.js'
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import type { Flow } from './types.js'
|
|
2
|
+
import type { DB, ManagedConnection } from '../../data/db/index.js'
|
|
3
|
+
import type { TenantConfig, TenantContext } from '../../auth/tenant/types.js'
|
|
4
|
+
import { sql } from '../../data/db/sql.js'
|
|
5
|
+
import { propagateTenantLocals } from '../../auth/tenant/index.js'
|
|
6
|
+
import { bindTransaction } from './guard.js'
|
|
7
|
+
import { runInContext } from './store.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Runs `run` inside a database transaction (or one independent transaction per
|
|
11
|
+
* database, when several are involved), with the request/job context's locals
|
|
12
|
+
* propagated via `SET LOCAL` so Postgres-side RLS policies and `current_setting`
|
|
13
|
+
* lookups see the active tenant.
|
|
14
|
+
*
|
|
15
|
+
* The transactions are bound to a child context so `pipe()` and DI resolution
|
|
16
|
+
* pick them up; `run` is invoked inside that child context. This is the single
|
|
17
|
+
* shared path for both the HTTP surface and `jobs.execute` — keep it that way
|
|
18
|
+
* so the two entry points cannot drift in their isolation behaviour.
|
|
19
|
+
*
|
|
20
|
+
* With a `signal`, aborting cancels each transaction's in-flight query on the
|
|
21
|
+
* server (`pg_cancel_backend`), so the query fails, the transaction rolls back
|
|
22
|
+
* and the connection returns to the pool instead of being held to completion.
|
|
23
|
+
*/
|
|
24
|
+
export async function executeInTransaction<T>(
|
|
25
|
+
ctx: Flow,
|
|
26
|
+
databases: readonly string[],
|
|
27
|
+
tenant: TenantConfig | null,
|
|
28
|
+
timeoutMs: number,
|
|
29
|
+
run: () => Promise<T>,
|
|
30
|
+
signal?: AbortSignal,
|
|
31
|
+
): Promise<T> {
|
|
32
|
+
const instance = ctx.instance
|
|
33
|
+
|
|
34
|
+
if (databases.length === 1) {
|
|
35
|
+
const dbName = databases[0]!
|
|
36
|
+
const dbConfig = instance.config.database(dbName)
|
|
37
|
+
const conn = instance.pool.getOrCreate(dbConfig, 'app')
|
|
38
|
+
|
|
39
|
+
return conn.drizzle.transaction(async (tx) => {
|
|
40
|
+
const childCtx: Flow = {
|
|
41
|
+
...ctx,
|
|
42
|
+
transactions: new Map(ctx.transactions),
|
|
43
|
+
}
|
|
44
|
+
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx))
|
|
45
|
+
|
|
46
|
+
await propagateLocals(tx, ctx, tenant)
|
|
47
|
+
|
|
48
|
+
const disarm = await armCancellation(conn, tx, signal)
|
|
49
|
+
try {
|
|
50
|
+
return await runInContext(childCtx, run)
|
|
51
|
+
} finally {
|
|
52
|
+
disarm()
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Multiple databases: nested transactions (each independent)
|
|
58
|
+
const childCtx: Flow = {
|
|
59
|
+
...ctx,
|
|
60
|
+
transactions: new Map(ctx.transactions),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const txPromises: Promise<void>[] = []
|
|
64
|
+
const readyPromises: Promise<void>[] = []
|
|
65
|
+
const disarms: (() => void)[] = []
|
|
66
|
+
const readyDatabases = new Set<string>()
|
|
67
|
+
let releaseAll!: () => void
|
|
68
|
+
let abortAll!: (err: Error) => void
|
|
69
|
+
|
|
70
|
+
const donePromise = new Promise<void>((resolve, reject) => {
|
|
71
|
+
releaseAll = resolve
|
|
72
|
+
abortAll = reject
|
|
73
|
+
})
|
|
74
|
+
donePromise.catch(() => {})
|
|
75
|
+
|
|
76
|
+
for (const dbName of databases) {
|
|
77
|
+
const dbConfig = instance.config.database(dbName)
|
|
78
|
+
const conn = instance.pool.getOrCreate(dbConfig, 'app')
|
|
79
|
+
|
|
80
|
+
let signalReady!: () => void
|
|
81
|
+
readyPromises.push(new Promise<void>(r => { signalReady = r }))
|
|
82
|
+
|
|
83
|
+
txPromises.push(
|
|
84
|
+
conn.drizzle.transaction(async (tx) => {
|
|
85
|
+
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx))
|
|
86
|
+
await propagateLocals(tx, ctx, tenant)
|
|
87
|
+
disarms.push(await armCancellation(conn, tx, signal))
|
|
88
|
+
readyDatabases.add(dbName)
|
|
89
|
+
signalReady()
|
|
90
|
+
await donePromise
|
|
91
|
+
}),
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
96
|
+
const timer = setTimeout(() => {
|
|
97
|
+
const pending = databases.filter(db => !readyDatabases.has(db))
|
|
98
|
+
reject(new Error(
|
|
99
|
+
`[pipework] Multi-database transaction setup timed out after ${timeoutMs}ms.\n\n` +
|
|
100
|
+
` Database(s) that failed to become ready: ${pending.join(', ')}\n` +
|
|
101
|
+
` Database(s) that are ready: ${[...readyDatabases].join(', ') || '(none)'}\n\n` +
|
|
102
|
+
' This usually means one of the databases is unreachable or under heavy load.\n' +
|
|
103
|
+
' You can increase the timeout via createServer({ transactionTimeoutMs }).\n'
|
|
104
|
+
))
|
|
105
|
+
}, timeoutMs)
|
|
106
|
+
timer.unref()
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
const disarmAll = (): void => { for (const disarm of disarms) disarm() }
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
await Promise.race([Promise.all(readyPromises), timeoutPromise])
|
|
113
|
+
} catch (err) {
|
|
114
|
+
abortAll(err instanceof Error ? err : new Error(String(err)))
|
|
115
|
+
await Promise.allSettled(txPromises)
|
|
116
|
+
disarmAll()
|
|
117
|
+
throw err
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
const result = await runInContext(childCtx, run)
|
|
122
|
+
releaseAll()
|
|
123
|
+
await Promise.all(txPromises)
|
|
124
|
+
return result
|
|
125
|
+
} catch (err) {
|
|
126
|
+
abortAll(err instanceof Error ? err : new Error(String(err)))
|
|
127
|
+
await Promise.allSettled(txPromises)
|
|
128
|
+
throw err
|
|
129
|
+
} finally {
|
|
130
|
+
disarmAll()
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Arms server-side cancellation for one transaction: on abort, a separate
|
|
136
|
+
* pooled connection issues `pg_cancel_backend` against the backend this
|
|
137
|
+
* transaction holds, so an in-flight query fails with `query_canceled` and the
|
|
138
|
+
* transaction unwinds. Returns a disarm function — always call it, or the
|
|
139
|
+
* listener outlives the transaction and cancels a backend the pool has since
|
|
140
|
+
* handed to someone else.
|
|
141
|
+
*/
|
|
142
|
+
async function armCancellation(
|
|
143
|
+
conn: ManagedConnection,
|
|
144
|
+
tx: DB,
|
|
145
|
+
signal: AbortSignal | undefined,
|
|
146
|
+
): Promise<() => void> {
|
|
147
|
+
if (signal === undefined) return () => {}
|
|
148
|
+
|
|
149
|
+
const [row] = await tx.execute(sql`SELECT pg_backend_pid() AS pid`)
|
|
150
|
+
const pid = Number((row as { pid?: unknown } | undefined)?.pid)
|
|
151
|
+
if (!Number.isInteger(pid)) return () => {}
|
|
152
|
+
|
|
153
|
+
const cancel = (): void => {
|
|
154
|
+
// Best effort: the backend may already have finished, and a failed cancel
|
|
155
|
+
// must not replace the abort the caller is about to see.
|
|
156
|
+
void conn.drizzle.execute(sql`SELECT pg_cancel_backend(${pid})`).catch(() => {})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (signal.aborted) {
|
|
160
|
+
cancel()
|
|
161
|
+
return () => {}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
signal.addEventListener('abort', cancel, { once: true })
|
|
165
|
+
return () => { signal.removeEventListener('abort', cancel) }
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Propagates context locals onto a transaction via `SET LOCAL`: the request id,
|
|
170
|
+
* the tenant id (`pipework.tenant_id`, read by generated RLS policies), and any
|
|
171
|
+
* custom tenant session variables.
|
|
172
|
+
*/
|
|
173
|
+
export async function propagateLocals(
|
|
174
|
+
tx: DB,
|
|
175
|
+
ctx: Flow,
|
|
176
|
+
tenant: TenantConfig | null,
|
|
177
|
+
): Promise<void> {
|
|
178
|
+
if (ctx.requestId !== '') {
|
|
179
|
+
await tx.execute(sql`SELECT set_config('pipework.request_id', ${ctx.requestId}, true)`)
|
|
180
|
+
}
|
|
181
|
+
if (ctx.tenant !== null) {
|
|
182
|
+
await tx.execute(sql`SELECT set_config('pipework.tenant_id', ${ctx.tenant}, true)`)
|
|
183
|
+
}
|
|
184
|
+
if (ctx.user !== null) {
|
|
185
|
+
await tx.execute(sql`SELECT set_config('pipework.user_id', ${ctx.user}, true)`)
|
|
186
|
+
}
|
|
187
|
+
if (ctx.asOf !== null) {
|
|
188
|
+
await tx.execute(sql`SELECT set_config('pipework.asof', ${ctx.asOf}, true)`)
|
|
189
|
+
}
|
|
190
|
+
if (tenant !== null && tenant.sessionVars !== undefined && ctx.tenant !== null) {
|
|
191
|
+
const tenantCtx: TenantContext = {
|
|
192
|
+
tenant: ctx.tenant,
|
|
193
|
+
requestId: ctx.requestId,
|
|
194
|
+
userId: ctx.auth !== null && typeof ctx.auth === 'object' && 'userId' in ctx.auth
|
|
195
|
+
? (ctx.auth as { userId: string }).userId
|
|
196
|
+
: null,
|
|
197
|
+
}
|
|
198
|
+
await propagateTenantLocals(tx, tenant, tenantCtx)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { runtime } from '../../core/runtime/broker.js'
|
|
2
|
+
import type { Flow } from './types.js'
|
|
3
|
+
|
|
4
|
+
// Pinned to the cross-realm runtime broker, not a fresh module singleton: when a
|
|
5
|
+
// shared leaf library resolves its own physical copy of pipework, both copies must
|
|
6
|
+
// share ONE AsyncLocalStorage or a context entered by one is invisible to pipe() in
|
|
7
|
+
// the other. See src/core/runtime/broker.ts.
|
|
8
|
+
export const flowStorage = runtime().flowStorage
|
|
9
|
+
|
|
10
|
+
export function getContext<TAuth = unknown>(): Flow<TAuth> | undefined {
|
|
11
|
+
return flowStorage.getStore() as Flow<TAuth> | undefined
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function requireContext<TAuth = unknown>(): Flow<TAuth> {
|
|
15
|
+
const ctx = flowStorage.getStore() as Flow<TAuth> | undefined
|
|
16
|
+
if (!ctx) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
'[pipework] No active context. db() must be called within a request handler, job, or test.\n\n' +
|
|
19
|
+
' Hint: If you need a connection outside of a managed context (migrations, seeds),\n' +
|
|
20
|
+
' use instance.pool.getOrCreate(config.database("name")).drizzle instead.\n'
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
return ctx
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function runInContext<T>(ctx: Flow, fn: () => T): T {
|
|
27
|
+
return flowStorage.run(ctx, fn)
|
|
28
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { DB } from '../../data/db/index.js'
|
|
2
|
+
import type { Manifold } from '../../core/pipework.js'
|
|
3
|
+
import type { TenantConfig } from '../../auth/tenant/types.js'
|
|
4
|
+
import type { TraceContext } from '../../trace/entry/trace-context.js'
|
|
5
|
+
|
|
6
|
+
/** A transaction bound to a specific context nonce and tenant — defense-in-depth against ALS context swaps. */
|
|
7
|
+
export interface BoundTransaction {
|
|
8
|
+
readonly drizzle: DB
|
|
9
|
+
readonly nonce: string
|
|
10
|
+
readonly tenant: string | null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** The AsyncLocalStorage context — carries requestId, auth, tenant, active transactions, and a nonce for integrity checks. */
|
|
14
|
+
export interface Flow<TAuth = unknown> {
|
|
15
|
+
readonly instance: Manifold
|
|
16
|
+
readonly requestId: string
|
|
17
|
+
readonly _nonce: string
|
|
18
|
+
readonly auth: TAuth | null
|
|
19
|
+
readonly tenant: string | null
|
|
20
|
+
/** The acting principal's user id — propagated as `pipework.user_id` for user-level RLS. */
|
|
21
|
+
readonly user: string | null
|
|
22
|
+
/** The as-of instant access is evaluated against — propagated as `pipework.asof` for temporal RLS. Null = current. */
|
|
23
|
+
readonly asOf: string | null
|
|
24
|
+
readonly metadata: RequestMetadata | null
|
|
25
|
+
readonly jobType: string | null
|
|
26
|
+
/** The 1-based attempt of the job this Flow runs, counting attempts a lost worker used; null outside a worker-run job. */
|
|
27
|
+
readonly jobAttempt: number | null
|
|
28
|
+
/** The attempt limit of the job this Flow runs; null outside a worker-run job. */
|
|
29
|
+
readonly jobMaxAttempts: number | null
|
|
30
|
+
/**
|
|
31
|
+
* The tenant configuration in force at this entry, or `null` where none is
|
|
32
|
+
* configured. Carried on the context so ANY transaction opened inside it can
|
|
33
|
+
* propagate the same session variables the entry's own transaction does —
|
|
34
|
+
* without it, a transaction opened by `pipe.transaction` propagated nothing
|
|
35
|
+
* and every RLS policy read zero rows.
|
|
36
|
+
*/
|
|
37
|
+
readonly tenantConfig: TenantConfig | null
|
|
38
|
+
readonly transactions: Map<string, BoundTransaction>
|
|
39
|
+
/** The trace opened at this entry, or `null` when the entry ran untraced. */
|
|
40
|
+
readonly trace: TraceContext | null
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** HTTP request metadata stored in a Flow — method, path, trace ID, session ID. */
|
|
44
|
+
export interface RequestMetadata {
|
|
45
|
+
readonly method: string
|
|
46
|
+
readonly path: string
|
|
47
|
+
readonly startedAt: number
|
|
48
|
+
readonly traceId: string
|
|
49
|
+
readonly sessionId: string | null
|
|
50
|
+
}
|