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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.252.1
|
|
4
|
+
|
|
5
|
+
- **Fixed: published sourcemaps point at files that ship** (#894). `src/` is now in the package (and in `pipework-flow-parser` 0.1.1), so every `dist/**/*.map` source resolves; a consumer's `pipework test` no longer prints Vite's "points to missing source files" warning per pipework file, and go-to-definition through the `.d.ts` maps lands on source.
|
|
6
|
+
- **Fixed: `build` starts from an empty `dist/`.** Output of deleted source files (e.g. `infra/email/sigv4`, `infra/access-links/rate-limit`) had been shipping in the package.
|
|
7
|
+
|
|
3
8
|
## 0.252.0
|
|
4
9
|
|
|
5
10
|
- **Added: `observability.inFlightQueryMs`** (#892). While a statement is still running, each multiple of it logs one `query:in-flight` warning in the caller's log context (a job's id and tenant come with it): `label`, `elapsedS`, `database`, and the backend's `pid`, `state`, `waitEventType`/`waitEvent` from `pg_stat_activity`, read over a dedicated one-connection sampler (null when it is busy or slow). Nothing after the statement settles. Unset: no timer per query.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pipework",
|
|
3
|
-
"version": "0.252.
|
|
3
|
+
"version": "0.252.1",
|
|
4
4
|
"description": "TypeScript framework for multi-tenant SaaS applications. PostgreSQL-only.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"types": "./dist/index.d.ts",
|
|
66
66
|
"files": [
|
|
67
67
|
"dist",
|
|
68
|
+
"src",
|
|
68
69
|
"bin",
|
|
69
70
|
"LICENSE",
|
|
70
71
|
"CHANGELOG.md",
|
|
@@ -172,7 +173,7 @@
|
|
|
172
173
|
"pino": "^10.3.1",
|
|
173
174
|
"postgres": "^3.4.9",
|
|
174
175
|
"zod": "^4.4.3",
|
|
175
|
-
"pipework-flow-parser": "0.1.
|
|
176
|
+
"pipework-flow-parser": "0.1.1"
|
|
176
177
|
},
|
|
177
178
|
"peerDependencies": {
|
|
178
179
|
"typescript": "^6.0.0",
|
|
@@ -189,7 +190,7 @@
|
|
|
189
190
|
"vitest": "^4.1.5"
|
|
190
191
|
},
|
|
191
192
|
"scripts": {
|
|
192
|
-
"build": "pnpm --filter pipework-flow-parser build && tsc && cp src/test/globals.d.ts dist/test/globals.d.ts",
|
|
193
|
+
"build": "pnpm --filter pipework-flow-parser build && node -e \"fs.rmSync('dist',{recursive:true,force:true})\" && tsc && cp src/test/globals.d.ts dist/test/globals.d.ts",
|
|
193
194
|
"type-check": "pnpm --filter pipework-flow-parser type-check && tsc --noEmit",
|
|
194
195
|
"lint": "eslint src --max-warnings 0",
|
|
195
196
|
"lint:boundaries": "node scripts/check-boundaries.js",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** setTimeout delay that resolves early when the signal aborts — shutdown must not wait out a backoff or poll interval. */
|
|
2
|
+
export function abortableDelay(ms: number, signal?: AbortSignal): Promise<void> {
|
|
3
|
+
return new Promise<void>((resolve) => {
|
|
4
|
+
if (signal?.aborted === true) {
|
|
5
|
+
resolve()
|
|
6
|
+
return
|
|
7
|
+
}
|
|
8
|
+
const onAbort = (): void => {
|
|
9
|
+
clearTimeout(timer)
|
|
10
|
+
resolve()
|
|
11
|
+
}
|
|
12
|
+
const timer = setTimeout(() => {
|
|
13
|
+
signal?.removeEventListener('abort', onAbort)
|
|
14
|
+
resolve()
|
|
15
|
+
}, ms)
|
|
16
|
+
signal?.addEventListener('abort', onAbort, { once: true })
|
|
17
|
+
})
|
|
18
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// The claim history a queue row keeps in its `claims` jsonb column.
|
|
2
|
+
//
|
|
3
|
+
// claim()'s UPDATE appends an element; every statement that ends a claim closes
|
|
4
|
+
// the last one through closeClaim(), so no release path can overwrite the facts
|
|
5
|
+
// of an earlier claim. Timestamps come from the database's now().
|
|
6
|
+
|
|
7
|
+
import { sql } from '../../data/db/sql.js'
|
|
8
|
+
import type { SQL } from '../../data/db/index.js'
|
|
9
|
+
|
|
10
|
+
export type JobClaimReason = 'completed' | 'failed' | 'shutdown-returned' | 'reaped-stale' | 'later' | 'cancelled'
|
|
11
|
+
|
|
12
|
+
/** One claim of a job. `releasedAt`, `reason` and `progressMark` are null while the claim is held. */
|
|
13
|
+
export interface JobClaim {
|
|
14
|
+
readonly claimedAt: string
|
|
15
|
+
readonly workerId: string
|
|
16
|
+
readonly workerRelease: string | null
|
|
17
|
+
readonly releasedAt: string | null
|
|
18
|
+
readonly reason: JobClaimReason | null
|
|
19
|
+
/** The queue's `progressColumn` value at release; null when none is configured. */
|
|
20
|
+
readonly progressMark: unknown
|
|
21
|
+
/** Why a cancelled claim was cancelled; set only when `reason` is 'cancelled'. */
|
|
22
|
+
readonly cancel?: { readonly reason: string; readonly message: string }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** The SET fragment that appends the claim being made. */
|
|
26
|
+
export function openClaim(workerId: string, release: string | null): SQL {
|
|
27
|
+
return sql`claims = claims || jsonb_build_array(jsonb_build_object(
|
|
28
|
+
'claimedAt', now(), 'workerId', ${workerId}::text, 'workerRelease', ${release}::text,
|
|
29
|
+
'releasedAt', NULL::text, 'reason', NULL::text, 'progressMark', NULL::text))`
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The SET fragment that closes the last claim, when there is one and it is
|
|
34
|
+
* still open. `progressColumn` is the quoted app column recorded as the mark.
|
|
35
|
+
* `extra` is a jsonb object SQL merged into the closed claim.
|
|
36
|
+
*/
|
|
37
|
+
export function closeClaim(reason: JobClaimReason | SQL, progressColumn: string | null, extra?: SQL): SQL {
|
|
38
|
+
const reasonSql = typeof reason === 'string' ? sql`${reason}::text` : reason
|
|
39
|
+
const mark = progressColumn === null ? sql`'null'::jsonb` : sql`to_jsonb(${sql.raw(progressColumn)})`
|
|
40
|
+
return sql`claims = CASE
|
|
41
|
+
WHEN jsonb_array_length(claims) > 0 AND (claims -> -1) ->> 'releasedAt' IS NULL
|
|
42
|
+
THEN jsonb_set(claims, ARRAY[(jsonb_array_length(claims) - 1)::text],
|
|
43
|
+
(claims -> -1) || jsonb_build_object('releasedAt', now(), 'reason', ${reasonSql},
|
|
44
|
+
'progressMark', ${mark})${extra === undefined ? sql`` : sql` || ${extra}`})
|
|
45
|
+
ELSE claims END`
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Reads the column back into claims; anything but an array is no history. */
|
|
49
|
+
export function parseClaims(value: unknown): readonly JobClaim[] {
|
|
50
|
+
const parsed: unknown = typeof value === 'string' ? JSON.parse(value) : value
|
|
51
|
+
return Array.isArray(parsed) ? (parsed as JobClaim[]) : []
|
|
52
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { ValidationError } from '../../core/errors/index.js'
|
|
2
|
+
|
|
3
|
+
/** Parsed cron schedule — arrays of valid minutes, hours, days, months, weekdays. */
|
|
4
|
+
export interface CronSchedule {
|
|
5
|
+
readonly minutes: readonly number[]
|
|
6
|
+
readonly hours: readonly number[]
|
|
7
|
+
readonly daysOfMonth: readonly number[]
|
|
8
|
+
readonly months: readonly number[]
|
|
9
|
+
readonly daysOfWeek: readonly number[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const FIELD_RANGES: readonly [number, number][] = [
|
|
13
|
+
[0, 59], // minute
|
|
14
|
+
[0, 23], // hour
|
|
15
|
+
[1, 31], // day of month
|
|
16
|
+
[1, 12], // month
|
|
17
|
+
[0, 6], // day of week (0=Sun)
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
export function parseCron(expression: string): CronSchedule {
|
|
21
|
+
const parts = expression.trim().split(/\s+/)
|
|
22
|
+
if (parts.length !== 5) {
|
|
23
|
+
throw new ValidationError(
|
|
24
|
+
`Invalid cron expression "${expression}": expected 5 fields (minute hour day month weekday), got ${parts.length}`,
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const [minutes, hours, daysOfMonth, months, daysOfWeek] = parts as [string, string, string, string, string]
|
|
29
|
+
return {
|
|
30
|
+
minutes: parseField(minutes, FIELD_RANGES[0]!, 'minute'),
|
|
31
|
+
hours: parseField(hours, FIELD_RANGES[1]!, 'hour'),
|
|
32
|
+
daysOfMonth: parseField(daysOfMonth, FIELD_RANGES[2]!, 'day-of-month'),
|
|
33
|
+
months: parseField(months, FIELD_RANGES[3]!, 'month'),
|
|
34
|
+
daysOfWeek: parseField(daysOfWeek, FIELD_RANGES[4]!, 'day-of-week'),
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseField(field: string, [min, max]: [number, number], name: string): number[] {
|
|
39
|
+
const values = new Set<number>()
|
|
40
|
+
|
|
41
|
+
for (const part of field.split(',')) {
|
|
42
|
+
const stepMatch = part.match(/^(.+)\/(\d+)$/)
|
|
43
|
+
const step = stepMatch ? parseInt(stepMatch[2]!, 10) : null
|
|
44
|
+
const rangePart = stepMatch ? stepMatch[1]! : part
|
|
45
|
+
|
|
46
|
+
if (step !== null && (step < 1 || step > max)) {
|
|
47
|
+
throw new ValidationError(`Invalid cron ${name}: step "${step}" out of range`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (rangePart === '*') {
|
|
51
|
+
for (let i = min; i <= max; i += (step ?? 1)) {
|
|
52
|
+
values.add(i)
|
|
53
|
+
}
|
|
54
|
+
} else if (rangePart.includes('-')) {
|
|
55
|
+
const [startStr, endStr] = rangePart.split('-') as [string, string]
|
|
56
|
+
const start = parseInt(startStr, 10)
|
|
57
|
+
const end = parseInt(endStr, 10)
|
|
58
|
+
if (Number.isNaN(start) || Number.isNaN(end) || start < min || end > max || start > end) {
|
|
59
|
+
throw new ValidationError(`Invalid cron ${name}: range "${rangePart}" out of bounds (${min}-${max})`)
|
|
60
|
+
}
|
|
61
|
+
for (let i = start; i <= end; i += (step ?? 1)) {
|
|
62
|
+
values.add(i)
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
const val = parseInt(rangePart, 10)
|
|
66
|
+
if (Number.isNaN(val) || val < min || val > max) {
|
|
67
|
+
throw new ValidationError(`Invalid cron ${name}: value "${rangePart}" out of range (${min}-${max})`)
|
|
68
|
+
}
|
|
69
|
+
if (step !== null) {
|
|
70
|
+
for (let i = val; i <= max; i += step) {
|
|
71
|
+
values.add(i)
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
values.add(val)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return [...values].sort((a, b) => a - b)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function nextTick(schedule: CronSchedule, after: Date, timezone?: string): Date {
|
|
83
|
+
const tz = timezone ?? 'UTC'
|
|
84
|
+
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
85
|
+
timeZone: tz,
|
|
86
|
+
year: 'numeric',
|
|
87
|
+
month: '2-digit',
|
|
88
|
+
day: '2-digit',
|
|
89
|
+
hour: '2-digit',
|
|
90
|
+
minute: '2-digit',
|
|
91
|
+
second: '2-digit',
|
|
92
|
+
hour12: false,
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const parts = extractParts(formatter, after)
|
|
96
|
+
let year = parts.year
|
|
97
|
+
let month = parts.month
|
|
98
|
+
let day = parts.day
|
|
99
|
+
let hour = parts.hour
|
|
100
|
+
let minute = parts.minute + 1
|
|
101
|
+
|
|
102
|
+
for (let guard = 0; guard < 5 * 366; guard++) {
|
|
103
|
+
if (minute > 59) { minute = 0; hour++ }
|
|
104
|
+
if (hour > 23) { hour = 0; day++ }
|
|
105
|
+
const dim = getDaysInMonth(year, month)
|
|
106
|
+
if (day > dim) { day = 1; month++ }
|
|
107
|
+
if (month > 12) { month = 1; year++ }
|
|
108
|
+
|
|
109
|
+
if (!schedule.months.includes(month)) {
|
|
110
|
+
month++; day = schedule.daysOfMonth[0]!; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
|
|
111
|
+
continue
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!schedule.daysOfMonth.includes(day)) {
|
|
115
|
+
day++; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const dow = getDayOfWeekForDate(year, month, day)
|
|
120
|
+
if (!schedule.daysOfWeek.includes(dow)) {
|
|
121
|
+
day++; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
|
|
122
|
+
continue
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!schedule.hours.includes(hour)) {
|
|
126
|
+
const nextHour = schedule.hours.find(h => h > hour)
|
|
127
|
+
if (nextHour !== undefined) {
|
|
128
|
+
hour = nextHour; minute = schedule.minutes[0]!
|
|
129
|
+
} else {
|
|
130
|
+
day++; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
|
|
131
|
+
}
|
|
132
|
+
continue
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!schedule.minutes.includes(minute)) {
|
|
136
|
+
const nextMin = schedule.minutes.find(m => m >= minute)
|
|
137
|
+
if (nextMin !== undefined) {
|
|
138
|
+
minute = nextMin
|
|
139
|
+
} else {
|
|
140
|
+
hour++; minute = schedule.minutes[0]!
|
|
141
|
+
}
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return buildDate(tz, year, month, day, hour, minute)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
throw new Error('Could not find next cron tick within search window')
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function extractParts(formatter: Intl.DateTimeFormat, date: Date): { year: number; month: number; day: number; hour: number; minute: number } {
|
|
152
|
+
const resolved = formatter.formatToParts(date)
|
|
153
|
+
const get = (type: Intl.DateTimeFormatPartTypes) => parseInt(resolved.find(p => p.type === type)!.value, 10)
|
|
154
|
+
return { year: get('year'), month: get('month'), day: get('day'), hour: get('hour'), minute: get('minute') }
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function getDayOfWeekForDate(year: number, month: number, day: number): number {
|
|
158
|
+
return new Date(Date.UTC(year, month - 1, day, 12, 0, 0)).getUTCDay()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function getDaysInMonth(year: number, month: number): number {
|
|
162
|
+
return new Date(year, month, 0).getDate()
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function buildDate(tz: string, year: number, month: number, day: number, hour: number, minute: number): Date {
|
|
166
|
+
if (tz === 'UTC') {
|
|
167
|
+
return new Date(Date.UTC(year, month - 1, day, hour, minute, 0, 0))
|
|
168
|
+
}
|
|
169
|
+
const iso = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}T${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:00`
|
|
170
|
+
const formatter = new Intl.DateTimeFormat('en-US', { timeZone: tz, timeZoneName: 'longOffset' })
|
|
171
|
+
const refParts = formatter.formatToParts(new Date(iso + 'Z'))
|
|
172
|
+
const tzPart = refParts.find(p => p.type === 'timeZoneName')?.value ?? '+00:00'
|
|
173
|
+
const offsetMatch = tzPart.match(/GMT([+-]\d{1,2}):?(\d{2})?/)
|
|
174
|
+
if (!offsetMatch) return new Date(iso + 'Z')
|
|
175
|
+
const offsetHours = parseInt(offsetMatch[1]!, 10)
|
|
176
|
+
const offsetMinutes = parseInt(offsetMatch[2] ?? '0', 10)
|
|
177
|
+
const totalOffsetMs = (offsetHours * 60 + (offsetHours < 0 ? -offsetMinutes : offsetMinutes)) * 60_000
|
|
178
|
+
return new Date(new Date(iso + 'Z').getTime() - totalOffsetMs)
|
|
179
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PipeworkError } from '../../core/errors/base.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Thrown by `jobs.execute` when the caller's `signal` aborts before the handler
|
|
5
|
+
* returns. `name` is `'AbortError'` so the standard `err.name === 'AbortError'`
|
|
6
|
+
* check works; `code` stays pipework's `JOB_ABORTED`.
|
|
7
|
+
*
|
|
8
|
+
* Aborting with an `Error` as the reason rejects with that error instead — the
|
|
9
|
+
* worker uses this to keep its own job-timeout message.
|
|
10
|
+
*/
|
|
11
|
+
export class JobAbortedError extends PipeworkError {
|
|
12
|
+
readonly code = 'JOB_ABORTED' as const
|
|
13
|
+
readonly httpStatus = 499 as const
|
|
14
|
+
|
|
15
|
+
constructor(jobLabel: string, reason?: unknown) {
|
|
16
|
+
super(
|
|
17
|
+
`[pipework] Job ${jobLabel} was aborted by its caller's signal.\n\n` +
|
|
18
|
+
' The handler was still running; its transaction was rolled back and its\n' +
|
|
19
|
+
' connection released. An in-flight query was cancelled on the server, but a\n' +
|
|
20
|
+
' handler that ignores the cancellation keeps running until it returns.\n',
|
|
21
|
+
reason === undefined ? { jobLabel } : { jobLabel, reason },
|
|
22
|
+
)
|
|
23
|
+
this.name = 'AbortError'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Thrown by a job handler to end the attempt as "try again later": the job goes
|
|
29
|
+
* back to pending after `delayMs` (the queue's backoff, at least a second, when
|
|
30
|
+
* unset) and the attempt is not counted. Build it with `jobs.later(...)`.
|
|
31
|
+
*/
|
|
32
|
+
export class JobLaterError extends PipeworkError {
|
|
33
|
+
readonly code = 'JOB_LATER' as const
|
|
34
|
+
readonly httpStatus = 503 as const
|
|
35
|
+
readonly delayMs: number | undefined
|
|
36
|
+
|
|
37
|
+
constructor(message: string, opts: { delayMs?: number; cause?: unknown } = {}) {
|
|
38
|
+
super(message, opts.cause === undefined ? {} : { cause: opts.cause })
|
|
39
|
+
this.name = 'JobLaterError'
|
|
40
|
+
this.delayMs = opts.delayMs
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Thrown by a job handler to end the attempt as a final failure: the job is
|
|
46
|
+
* dead-lettered now, whatever attempts remain. Build it with `jobs.permanent(...)`.
|
|
47
|
+
*/
|
|
48
|
+
export class JobPermanentError extends PipeworkError {
|
|
49
|
+
readonly code = 'JOB_PERMANENT' as const
|
|
50
|
+
readonly httpStatus = 500 as const
|
|
51
|
+
|
|
52
|
+
constructor(message: string, opts: { cause?: unknown } = {}) {
|
|
53
|
+
super(message, opts.cause === undefined ? {} : { cause: opts.cause })
|
|
54
|
+
this.name = 'JobPermanentError'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// Cross-job exclusion gate for the claim query.
|
|
2
|
+
//
|
|
3
|
+
// A job "participates" in exclusion when its array column is non-NULL or its
|
|
4
|
+
// blocks-all flag is true. Against the concurrent set R (claimed/running jobs,
|
|
5
|
+
// tenant-scoped when a tenant column is configured), a pending candidate is
|
|
6
|
+
// claimable when:
|
|
7
|
+
// - it does not participate: always claimable, and it never blocks others
|
|
8
|
+
// - it is blocks-all: R contains no participating job
|
|
9
|
+
// - it carries an array: R contains no blocks-all job and no job whose
|
|
10
|
+
// array overlaps (&&) the candidate's
|
|
11
|
+
//
|
|
12
|
+
// Two concurrent workers can evaluate these NOT EXISTS checks against the same
|
|
13
|
+
// MVCC snapshot and both pass (write skew) — the claim query must run under
|
|
14
|
+
// SERIALIZABLE; queue.ts handles that.
|
|
15
|
+
|
|
16
|
+
import { assertValidIdentifier, quoteIdentifier } from '../../data/db/identifiers.js'
|
|
17
|
+
import { QUEUE_BASE_COLUMNS } from './table.js'
|
|
18
|
+
|
|
19
|
+
/** Cross-job exclusion config — names the consumer's conflict columns; the mechanism is pipework's. */
|
|
20
|
+
export interface ExclusionConfig {
|
|
21
|
+
/** Array column — two jobs whose arrays overlap (`&&`) are mutually exclusive. */
|
|
22
|
+
readonly arrayColumn?: string
|
|
23
|
+
/** Element type of `arrayColumn`. Default `'uuid'`. */
|
|
24
|
+
readonly arrayElementType?: 'uuid' | 'text'
|
|
25
|
+
/** Boolean column — a TRUE job is exclusive against every participating job in its scope. */
|
|
26
|
+
readonly blocksAllColumn?: string
|
|
27
|
+
/** Tenant column — exclusion checks compare only jobs with the same tenant value. */
|
|
28
|
+
readonly tenantColumn?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ResolvedExclusion {
|
|
32
|
+
readonly arrayColumn?: string
|
|
33
|
+
readonly arrayElementType: 'uuid' | 'text'
|
|
34
|
+
readonly blocksAllColumn?: string
|
|
35
|
+
readonly tenantColumn?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function resolveExclusion(config: ExclusionConfig | undefined): ResolvedExclusion | undefined {
|
|
39
|
+
if (config === undefined) return undefined
|
|
40
|
+
|
|
41
|
+
if (config.arrayColumn === undefined && config.blocksAllColumn === undefined) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
'[pipework] exclusion requires arrayColumn and/or blocksAllColumn.\n\n' +
|
|
44
|
+
' A tenantColumn alone only scopes checks — it expresses no conflict.\n' +
|
|
45
|
+
" Configure the conflict columns: exclusion: { arrayColumn: 'conflict_keys' }\n" +
|
|
46
|
+
" or exclusion: { blocksAllColumn: 'exclusive' }.\n",
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (config.arrayElementType !== undefined && config.arrayColumn === undefined) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
'[pipework] exclusion.arrayElementType is set but arrayColumn is not.\n\n' +
|
|
53
|
+
' arrayElementType only describes arrayColumn.\n' +
|
|
54
|
+
' Add arrayColumn, or remove arrayElementType.\n',
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const named = [config.arrayColumn, config.blocksAllColumn, config.tenantColumn]
|
|
59
|
+
.filter((c): c is string => c !== undefined)
|
|
60
|
+
for (const column of named) {
|
|
61
|
+
assertValidIdentifier(column, 'exclusion column')
|
|
62
|
+
if (QUEUE_BASE_COLUMNS.has(column)) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`[pipework] exclusion column "${column}" collides with a base queue column.\n\n` +
|
|
65
|
+
` The queue table already owns: ${[...QUEUE_BASE_COLUMNS].join(', ')}\n` +
|
|
66
|
+
' Pick a different column name.\n',
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (new Set(named).size !== named.length) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
'[pipework] exclusion columns must be distinct.\n\n' +
|
|
73
|
+
` Got: arrayColumn=${config.arrayColumn ?? '—'}, blocksAllColumn=${config.blocksAllColumn ?? '—'}, tenantColumn=${config.tenantColumn ?? '—'}\n` +
|
|
74
|
+
' Each role needs its own column.\n',
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
...(config.arrayColumn !== undefined ? { arrayColumn: config.arrayColumn } : {}),
|
|
80
|
+
arrayElementType: config.arrayElementType ?? 'uuid',
|
|
81
|
+
...(config.blocksAllColumn !== undefined ? { blocksAllColumn: config.blocksAllColumn } : {}),
|
|
82
|
+
...(config.tenantColumn !== undefined ? { tenantColumn: config.tenantColumn } : {}),
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The claimability predicate for the claim query's candidate SELECT. Pure
|
|
88
|
+
* identifiers — all quoted, no values — so the result composes as a raw SQL
|
|
89
|
+
* fragment. The candidate row is aliased `candidate`, concurrent rows `r`.
|
|
90
|
+
*/
|
|
91
|
+
export function exclusionClaimClause(tableQ: string, exclusion: ResolvedExclusion): string {
|
|
92
|
+
const arr = exclusion.arrayColumn !== undefined ? quoteIdentifier(exclusion.arrayColumn, 'exclusion column') : undefined
|
|
93
|
+
const blocks = exclusion.blocksAllColumn !== undefined ? quoteIdentifier(exclusion.blocksAllColumn, 'exclusion column') : undefined
|
|
94
|
+
const tenant = exclusion.tenantColumn !== undefined ? quoteIdentifier(exclusion.tenantColumn, 'exclusion column') : undefined
|
|
95
|
+
|
|
96
|
+
const tenantScope = tenant !== undefined ? `r.${tenant} = candidate.${tenant} AND ` : ''
|
|
97
|
+
const noConcurrent = (condition: string): string =>
|
|
98
|
+
`NOT EXISTS (SELECT 1 FROM ${tableQ} r WHERE ${tenantScope}r.status IN ('claimed', 'running') AND ${condition})`
|
|
99
|
+
|
|
100
|
+
if (arr !== undefined && blocks !== undefined) {
|
|
101
|
+
return '(' +
|
|
102
|
+
`(candidate.${blocks} = false AND candidate.${arr} IS NULL)` +
|
|
103
|
+
` OR (candidate.${blocks} = true AND ${noConcurrent(`(r.${arr} IS NOT NULL OR r.${blocks} = true)`)})` +
|
|
104
|
+
` OR (candidate.${blocks} = false AND candidate.${arr} IS NOT NULL` +
|
|
105
|
+
` AND ${noConcurrent(`r.${blocks} = true`)}` +
|
|
106
|
+
` AND ${noConcurrent(`r.${arr} IS NOT NULL AND r.${arr} && candidate.${arr}`)})` +
|
|
107
|
+
')'
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (arr !== undefined) {
|
|
111
|
+
return `(candidate.${arr} IS NULL OR ${noConcurrent(`r.${arr} IS NOT NULL AND r.${arr} && candidate.${arr}`)})`
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// blocks-all only: participation reduces to the flag itself, so a false
|
|
115
|
+
// candidate never conflicts and a true candidate waits for true jobs.
|
|
116
|
+
return `(candidate.${blocks!} = false OR ${noConcurrent(`r.${blocks!} = true`)})`
|
|
117
|
+
}
|