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,23 @@
|
|
|
1
|
+
import { resourceToHandlers } from './to-handlers.js'
|
|
2
|
+
import { MethodNotAllowedError } from './errors.js'
|
|
3
|
+
import { encodeCursor, decodeCursor, buildPage } from './paginate.js'
|
|
4
|
+
import { validateBatchRequest } from './batch.js'
|
|
5
|
+
import { buildResource } from './builder.js'
|
|
6
|
+
|
|
7
|
+
/** REST resource builder namespace — declarative CRUD with cursor pagination and batch operations. */
|
|
8
|
+
export const fixture = {
|
|
9
|
+
/** Converts a Resource into fitted Handler[] that go through the standard handler pipeline. */
|
|
10
|
+
toHandlers: resourceToHandlers,
|
|
11
|
+
/** Builds a Resource from a name, operations map, and builder state — used internally by fitting().fixture(). */
|
|
12
|
+
build: buildResource,
|
|
13
|
+
/** Encodes pagination cursor values into an opaque base64 string. */
|
|
14
|
+
encodeCursor,
|
|
15
|
+
/** Decodes an opaque pagination cursor back into its values. */
|
|
16
|
+
decodeCursor,
|
|
17
|
+
/** Builds a PageResult from rows, limit, and cursor extractor — handles hasMore detection. */
|
|
18
|
+
buildPage,
|
|
19
|
+
/** Validates a batch request body (preview/execute mode, targets, actions). */
|
|
20
|
+
validateBatch: validateBatchRequest,
|
|
21
|
+
/** Thrown when a resource doesn't support the requested HTTP method. */
|
|
22
|
+
MethodNotAllowedError,
|
|
23
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ValidationError } from '../../core/errors/index.js'
|
|
2
|
+
|
|
3
|
+
export interface PageResult<T> {
|
|
4
|
+
readonly items: T[]
|
|
5
|
+
readonly cursor: string | null
|
|
6
|
+
readonly hasMore: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface CursorPaginationParams {
|
|
10
|
+
readonly cursor?: string
|
|
11
|
+
readonly limit: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function encodeCursor(values: readonly unknown[]): string {
|
|
15
|
+
const json = JSON.stringify(values)
|
|
16
|
+
return Buffer.from(json).toString('base64url')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function decodeCursor(cursor: string): unknown[] {
|
|
20
|
+
try {
|
|
21
|
+
const json = Buffer.from(cursor, 'base64url').toString('utf-8')
|
|
22
|
+
const parsed: unknown = JSON.parse(json)
|
|
23
|
+
if (!Array.isArray(parsed)) {
|
|
24
|
+
throw new ValidationError('Invalid cursor: expected encoded array')
|
|
25
|
+
}
|
|
26
|
+
return parsed
|
|
27
|
+
} catch (err) {
|
|
28
|
+
if (err instanceof ValidationError) throw err
|
|
29
|
+
throw new ValidationError('Invalid cursor: malformed or tampered value')
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function buildPage<T>(
|
|
34
|
+
rows: readonly T[],
|
|
35
|
+
limit: number,
|
|
36
|
+
getCursor: (item: T) => string,
|
|
37
|
+
): PageResult<T> {
|
|
38
|
+
const hasMore = rows.length > limit
|
|
39
|
+
const items = hasMore ? rows.slice(0, limit) : [...rows]
|
|
40
|
+
const cursor = hasMore && items.length > 0
|
|
41
|
+
? encodeCursor([getCursor(items[items.length - 1]!)])
|
|
42
|
+
: null
|
|
43
|
+
return { items, cursor, hasMore }
|
|
44
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import type { DB } from '../../data/db/index.js'
|
|
2
|
+
import type { Handler, HandlerMeta, HttpMethod } from '../di/types.js'
|
|
3
|
+
import { DEFAULT_DB } from '../di/types.js'
|
|
4
|
+
import type { Resource, PaginationConfig } from './types.js'
|
|
5
|
+
import { unknown as unknownSchema } from '../../data/schema/generated/type-constructor.js'
|
|
6
|
+
import { requireContext } from '../context/store.js'
|
|
7
|
+
import { NotFoundError } from '../../core/errors/index.js'
|
|
8
|
+
import { MethodNotAllowedError } from './errors.js'
|
|
9
|
+
import { validateBatchRequest } from './batch.js'
|
|
10
|
+
import { singularize } from '../internal/text.js'
|
|
11
|
+
|
|
12
|
+
type AnyHandler = Handler<Record<string, unknown>, unknown>
|
|
13
|
+
|
|
14
|
+
const passthroughSchema = unknownSchema().refine((value) => value !== undefined, 'A request body is required')
|
|
15
|
+
|
|
16
|
+
function makeMeta(
|
|
17
|
+
resource: Resource<unknown>,
|
|
18
|
+
method: HttpMethod,
|
|
19
|
+
path: string,
|
|
20
|
+
overrides?: Partial<HandlerMeta>,
|
|
21
|
+
): HandlerMeta {
|
|
22
|
+
const { database, authRequirement, permission } = resource.meta
|
|
23
|
+
return {
|
|
24
|
+
databases: [database],
|
|
25
|
+
requiresAuth: authRequirement === 'required',
|
|
26
|
+
authRequirement,
|
|
27
|
+
inputSchema: null,
|
|
28
|
+
outputSchemas: new Map(),
|
|
29
|
+
querySchema: null,
|
|
30
|
+
paramsSchema: null,
|
|
31
|
+
route: { method, path },
|
|
32
|
+
isJob: false,
|
|
33
|
+
jobType: null,
|
|
34
|
+
jobRetry: null,
|
|
35
|
+
jobTimeout: null,
|
|
36
|
+
jobTransaction: 'auto',
|
|
37
|
+
permission,
|
|
38
|
+
wantsRequest: false,
|
|
39
|
+
wantsResponse: false,
|
|
40
|
+
wantsRawBody: false,
|
|
41
|
+
...overrides,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function make405(resource: Resource<unknown>, method: HttpMethod, path: string): AnyHandler {
|
|
46
|
+
return {
|
|
47
|
+
meta: makeMeta(resource, method, path, {
|
|
48
|
+
databases: [],
|
|
49
|
+
requiresAuth: false,
|
|
50
|
+
authRequirement: 'none',
|
|
51
|
+
permission: null,
|
|
52
|
+
}),
|
|
53
|
+
execute() {
|
|
54
|
+
return Promise.reject(new MethodNotAllowedError(method, resource.meta.name))
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function depKey(database: string): string {
|
|
60
|
+
return database === DEFAULT_DB ? 'db' : database
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function parsePagination(
|
|
64
|
+
query: Record<string, unknown> | undefined,
|
|
65
|
+
config: PaginationConfig,
|
|
66
|
+
): { limit: number; offset: number } {
|
|
67
|
+
const rawLimit = query?.['limit'] !== undefined ? parseInt(String(query['limit']), 10) : config.defaultLimit
|
|
68
|
+
const limit = Math.min(Math.max(1, Number.isNaN(rawLimit) ? config.defaultLimit : rawLimit), config.maxLimit)
|
|
69
|
+
const rawOffset = query?.['offset'] !== undefined ? parseInt(String(query['offset']), 10) : 0
|
|
70
|
+
const offset = Math.max(0, Number.isNaN(rawOffset) ? 0 : rawOffset)
|
|
71
|
+
return { limit, offset }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function capitalize(s: string): string {
|
|
75
|
+
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
export function resourceToHandlers(resource: Resource<unknown>): AnyHandler[] {
|
|
80
|
+
const handlers: AnyHandler[] = []
|
|
81
|
+
const { name, database, pagination } = resource.meta
|
|
82
|
+
const ops = resource.operations
|
|
83
|
+
const basePath = `/${name}`
|
|
84
|
+
const itemPath = `/${name}/:id`
|
|
85
|
+
const key = depKey(database)
|
|
86
|
+
|
|
87
|
+
// GET /resource — list
|
|
88
|
+
if (ops.listCursor !== undefined && pagination !== null) {
|
|
89
|
+
handlers.push({
|
|
90
|
+
meta: makeMeta(resource, 'GET', basePath, { querySchema: passthroughSchema }),
|
|
91
|
+
async execute(deps) {
|
|
92
|
+
const db = deps[key] as DB
|
|
93
|
+
const auth = deps['auth'] as unknown
|
|
94
|
+
const tenant = requireContext().tenant
|
|
95
|
+
const query = deps['query'] as Record<string, unknown> | undefined
|
|
96
|
+
const rawLimit = query?.['limit'] !== undefined ? parseInt(String(query['limit']), 10) : pagination.defaultLimit
|
|
97
|
+
const limit = Math.min(Math.max(1, Number.isNaN(rawLimit) ? pagination.defaultLimit : rawLimit), pagination.maxLimit)
|
|
98
|
+
const cursor = query?.['cursor'] !== undefined ? String(query['cursor']) : undefined
|
|
99
|
+
const result = await ops.listCursor!(db, auth, tenant, cursor !== undefined ? { cursor, limit } : { limit })
|
|
100
|
+
return { status: 200, body: result }
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
} else if (ops.listPaginated !== undefined && pagination !== null) {
|
|
104
|
+
handlers.push({
|
|
105
|
+
meta: makeMeta(resource, 'GET', basePath, { querySchema: passthroughSchema }),
|
|
106
|
+
async execute(deps) {
|
|
107
|
+
const db = deps[key] as DB
|
|
108
|
+
const auth = deps['auth'] as unknown
|
|
109
|
+
const tenant = requireContext().tenant
|
|
110
|
+
const query = deps['query'] as Record<string, unknown> | undefined
|
|
111
|
+
const { limit, offset } = parsePagination(query, pagination)
|
|
112
|
+
const result = await ops.listPaginated!(db, auth, tenant, { limit, offset })
|
|
113
|
+
return {
|
|
114
|
+
status: 200,
|
|
115
|
+
body: {
|
|
116
|
+
data: result.data,
|
|
117
|
+
pagination: { limit, offset, total: result.total, hasMore: offset + result.data.length < result.total },
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
})
|
|
122
|
+
} else if (ops.list !== undefined) {
|
|
123
|
+
handlers.push({
|
|
124
|
+
meta: makeMeta(resource, 'GET', basePath),
|
|
125
|
+
async execute(deps) {
|
|
126
|
+
const db = deps[key] as DB
|
|
127
|
+
const auth = deps['auth'] as unknown
|
|
128
|
+
const tenant = requireContext().tenant
|
|
129
|
+
const result = await ops.list!(db, auth, tenant)
|
|
130
|
+
return { status: 200, body: result }
|
|
131
|
+
},
|
|
132
|
+
})
|
|
133
|
+
} else {
|
|
134
|
+
handlers.push(make405(resource, 'GET', basePath))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// GET /resource/:id
|
|
138
|
+
if (ops.get !== undefined) {
|
|
139
|
+
handlers.push({
|
|
140
|
+
meta: makeMeta(resource, 'GET', itemPath, { paramsSchema: passthroughSchema }),
|
|
141
|
+
async execute(deps) {
|
|
142
|
+
const db = deps[key] as DB
|
|
143
|
+
const auth = deps['auth'] as unknown
|
|
144
|
+
const tenant = requireContext().tenant
|
|
145
|
+
const params = deps['params'] as Record<string, unknown>
|
|
146
|
+
const id = String(params['id'])
|
|
147
|
+
const result = await ops.get!(db, auth, tenant, id)
|
|
148
|
+
if (result === null || result === undefined) {
|
|
149
|
+
throw new NotFoundError(`${capitalize(singularize(name))} "${id}"`)
|
|
150
|
+
}
|
|
151
|
+
return { status: 200, body: result }
|
|
152
|
+
},
|
|
153
|
+
})
|
|
154
|
+
} else {
|
|
155
|
+
handlers.push(make405(resource, 'GET', itemPath))
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// POST /resource
|
|
159
|
+
if (ops.create !== undefined) {
|
|
160
|
+
handlers.push({
|
|
161
|
+
meta: makeMeta(resource, 'POST', basePath, {
|
|
162
|
+
inputSchema: ops.create.input ?? passthroughSchema,
|
|
163
|
+
}),
|
|
164
|
+
async execute(deps) {
|
|
165
|
+
const db = deps[key] as DB
|
|
166
|
+
const auth = deps['auth'] as unknown
|
|
167
|
+
const tenant = requireContext().tenant
|
|
168
|
+
const input = deps['input']
|
|
169
|
+
const result = await ops.create!.handler(db, auth, tenant, input)
|
|
170
|
+
return { status: 201, body: result }
|
|
171
|
+
},
|
|
172
|
+
})
|
|
173
|
+
} else {
|
|
174
|
+
handlers.push(make405(resource, 'POST', basePath))
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// PUT /resource/:id
|
|
178
|
+
if (ops.update !== undefined) {
|
|
179
|
+
handlers.push({
|
|
180
|
+
meta: makeMeta(resource, 'PUT', itemPath, {
|
|
181
|
+
inputSchema: ops.update.input ?? passthroughSchema,
|
|
182
|
+
paramsSchema: passthroughSchema,
|
|
183
|
+
}),
|
|
184
|
+
async execute(deps) {
|
|
185
|
+
const db = deps[key] as DB
|
|
186
|
+
const auth = deps['auth'] as unknown
|
|
187
|
+
const tenant = requireContext().tenant
|
|
188
|
+
const params = deps['params'] as Record<string, unknown>
|
|
189
|
+
const id = String(params['id'])
|
|
190
|
+
const input = deps['input']
|
|
191
|
+
const result = await ops.update!.handler(db, auth, tenant, id, input)
|
|
192
|
+
if (result === null || result === undefined) {
|
|
193
|
+
throw new NotFoundError(`${capitalize(singularize(name))} "${id}"`)
|
|
194
|
+
}
|
|
195
|
+
return { status: 200, body: result }
|
|
196
|
+
},
|
|
197
|
+
})
|
|
198
|
+
} else {
|
|
199
|
+
handlers.push(make405(resource, 'PUT', itemPath))
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// DELETE /resource/:id
|
|
203
|
+
if (ops.delete !== undefined) {
|
|
204
|
+
handlers.push({
|
|
205
|
+
meta: makeMeta(resource, 'DELETE', itemPath, { paramsSchema: passthroughSchema }),
|
|
206
|
+
async execute(deps) {
|
|
207
|
+
const db = deps[key] as DB
|
|
208
|
+
const auth = deps['auth'] as unknown
|
|
209
|
+
const tenant = requireContext().tenant
|
|
210
|
+
const params = deps['params'] as Record<string, unknown>
|
|
211
|
+
const id = String(params['id'])
|
|
212
|
+
await ops.delete!(db, auth, tenant, id)
|
|
213
|
+
return { status: 204 }
|
|
214
|
+
},
|
|
215
|
+
})
|
|
216
|
+
} else {
|
|
217
|
+
handlers.push(make405(resource, 'DELETE', itemPath))
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (ops.batch !== undefined) {
|
|
221
|
+
const validActions = Object.keys(ops.batch)
|
|
222
|
+
|
|
223
|
+
handlers.push({
|
|
224
|
+
meta: makeMeta(resource, 'POST', `${basePath}/batch/preview`, {
|
|
225
|
+
inputSchema: passthroughSchema,
|
|
226
|
+
}),
|
|
227
|
+
async execute(deps) {
|
|
228
|
+
const db = deps[key] as DB
|
|
229
|
+
const auth = deps['auth'] as unknown
|
|
230
|
+
const tenant = requireContext().tenant
|
|
231
|
+
const input = deps['input']
|
|
232
|
+
const { action, targets } = validateBatchRequest(input, validActions)
|
|
233
|
+
const batchAction = ops.batch![action]!
|
|
234
|
+
if (batchAction.preview === undefined) {
|
|
235
|
+
throw new MethodNotAllowedError('POST', `${name}/batch/preview (action: ${action})`)
|
|
236
|
+
}
|
|
237
|
+
const result = await batchAction.preview(db, auth, tenant, targets)
|
|
238
|
+
return { status: 200, body: result }
|
|
239
|
+
},
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
handlers.push({
|
|
243
|
+
meta: makeMeta(resource, 'POST', `${basePath}/batch`, {
|
|
244
|
+
inputSchema: passthroughSchema,
|
|
245
|
+
}),
|
|
246
|
+
async execute(deps) {
|
|
247
|
+
const db = deps[key] as DB
|
|
248
|
+
const auth = deps['auth'] as unknown
|
|
249
|
+
const tenant = requireContext().tenant
|
|
250
|
+
const input = deps['input']
|
|
251
|
+
const { action, targets } = validateBatchRequest(input, validActions)
|
|
252
|
+
const batchAction = ops.batch![action]!
|
|
253
|
+
const result = await batchAction.execute(db, auth, tenant, targets)
|
|
254
|
+
return { status: 200, body: result }
|
|
255
|
+
},
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return handlers
|
|
260
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Schema } from '../../data/schema/types.js'
|
|
2
|
+
import type { DB } from '../../data/db/index.js'
|
|
3
|
+
import type { AuthRequirement, PermissionMeta } from '../di/types.js'
|
|
4
|
+
|
|
5
|
+
export type ResourceId = string
|
|
6
|
+
|
|
7
|
+
export interface PaginationConfig {
|
|
8
|
+
readonly defaultLimit: number
|
|
9
|
+
readonly maxLimit: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface PaginationParams {
|
|
13
|
+
readonly limit: number
|
|
14
|
+
readonly offset: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface PaginatedResponse<T = unknown> {
|
|
18
|
+
readonly data: T[]
|
|
19
|
+
readonly pagination: {
|
|
20
|
+
readonly limit: number
|
|
21
|
+
readonly offset: number
|
|
22
|
+
readonly total: number
|
|
23
|
+
readonly hasMore: boolean
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ResourceListOp<TAuth> {
|
|
28
|
+
(db: DB, auth: TAuth, tenant: string | null): Promise<readonly unknown[]>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ResourceListPaginatedOp<TAuth> {
|
|
32
|
+
(db: DB, auth: TAuth, tenant: string | null, pagination: PaginationParams): Promise<{ data: readonly unknown[]; total: number }>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ResourceListCursorOp<TAuth> {
|
|
36
|
+
(db: DB, auth: TAuth, tenant: string | null, pagination: import('./paginate.js').CursorPaginationParams): Promise<import('./paginate.js').PageResult<unknown>>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface ResourceGetOp<TAuth> {
|
|
40
|
+
(db: DB, auth: TAuth, tenant: string | null, id: ResourceId): Promise<unknown | null>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface ResourceCreateOp<TAuth> {
|
|
44
|
+
readonly input?: Schema
|
|
45
|
+
readonly handler: (db: DB, auth: TAuth, tenant: string | null, input: unknown) => Promise<unknown>
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ResourceUpdateOp<TAuth> {
|
|
49
|
+
readonly input?: Schema
|
|
50
|
+
readonly handler: (db: DB, auth: TAuth, tenant: string | null, id: ResourceId, input: unknown) => Promise<unknown | null>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ResourceDeleteOp<TAuth> {
|
|
54
|
+
(db: DB, auth: TAuth, tenant: string | null, id: ResourceId): Promise<void>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ResourceOperations<TAuth> {
|
|
58
|
+
readonly list?: ResourceListOp<TAuth>
|
|
59
|
+
readonly listPaginated?: ResourceListPaginatedOp<TAuth>
|
|
60
|
+
readonly listCursor?: ResourceListCursorOp<TAuth>
|
|
61
|
+
readonly get?: ResourceGetOp<TAuth>
|
|
62
|
+
readonly create?: ResourceCreateOp<TAuth>
|
|
63
|
+
readonly update?: ResourceUpdateOp<TAuth>
|
|
64
|
+
readonly delete?: ResourceDeleteOp<TAuth>
|
|
65
|
+
readonly batch?: Record<string, import('./batch.js').BatchAction<TAuth>>
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ResourceMeta {
|
|
69
|
+
readonly name: string
|
|
70
|
+
readonly database: string
|
|
71
|
+
readonly authRequirement: AuthRequirement
|
|
72
|
+
readonly permission: PermissionMeta | null
|
|
73
|
+
readonly pagination: PaginationConfig | null
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface Resource<TAuth> {
|
|
77
|
+
readonly meta: ResourceMeta
|
|
78
|
+
readonly operations: ResourceOperations<TAuth>
|
|
79
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import type { Flow } from '../context/types.js'
|
|
3
|
+
import type { DB } from '../../data/db/index.js'
|
|
4
|
+
import { requireContext, runInContext } from '../context/store.js'
|
|
5
|
+
import { bindTransaction } from '../context/guard.js'
|
|
6
|
+
import { sql } from '../../data/db/sql.js'
|
|
7
|
+
import { propagateLocals } from '../context/run-in-transaction.js'
|
|
8
|
+
import { openChildTrace } from '../../trace/entry/child-trace.js'
|
|
9
|
+
import { finalizeTrace } from '../../trace/entry/finalize-trace.js'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Runs `fn` as `as.tenant` and `as.userId` from a Flow that has no tenant: a
|
|
13
|
+
* sign-up that has just founded a tenant, a public sign-in recording into its
|
|
14
|
+
* org. Row-level security, audit rows (tenant and actor) and the trace all
|
|
15
|
+
* carry that tenant and user.
|
|
16
|
+
*
|
|
17
|
+
* `fn` runs in a savepoint of the request's own transaction, so it commits or
|
|
18
|
+
* rolls back with the request. If `fn` throws, its writes are undone, the
|
|
19
|
+
* request's transaction stays usable and the error is rethrown. When `actAs`
|
|
20
|
+
* returns the Flow and the transaction are tenantless again. A Flow with no
|
|
21
|
+
* transaction on the default database gets a new app-role transaction instead.
|
|
22
|
+
* Refused when the Flow already has a tenant.
|
|
23
|
+
*/
|
|
24
|
+
export async function actAs<T>(
|
|
25
|
+
as: { readonly tenant: string; readonly userId: string },
|
|
26
|
+
fn: () => Promise<T>,
|
|
27
|
+
): Promise<T> {
|
|
28
|
+
const flow = requireContext()
|
|
29
|
+
if (flow.tenant !== null) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`[pipework] flow.actAs runs only in a Flow with no tenant; this Flow is tenant "${flow.tenant}", ` +
|
|
32
|
+
`asked for "${as.tenant}".\n\n` +
|
|
33
|
+
' actAs is for code that has just chosen a tenant (sign-up, a public sign-in). ' +
|
|
34
|
+
'Code already running as a tenant keeps that tenant.\n',
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
const dbName = flow.instance.config.defaultDatabaseName()
|
|
38
|
+
const auth = { userId: as.userId, tenantId: as.tenant }
|
|
39
|
+
const childTrace = openChildTrace(flow, as.tenant, auth)
|
|
40
|
+
const child: Flow = {
|
|
41
|
+
...flow,
|
|
42
|
+
_nonce: randomUUID(),
|
|
43
|
+
tenant: as.tenant,
|
|
44
|
+
user: null,
|
|
45
|
+
auth,
|
|
46
|
+
transactions: new Map(),
|
|
47
|
+
trace: childTrace,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const run = async (tx: DB): Promise<T> => {
|
|
51
|
+
child.transactions.set(dbName, bindTransaction(child, dbName, tx))
|
|
52
|
+
await propagateLocals(tx, child, child.tenantConfig)
|
|
53
|
+
return runInContext(child, fn)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const parentBound = flow.transactions.get(dbName)
|
|
57
|
+
if (parentBound === undefined) {
|
|
58
|
+
const conn = flow.instance.pool.getOrCreate(flow.instance.config.database(dbName), 'app')
|
|
59
|
+
return finalizeTrace(flow.instance, childTrace, conn.drizzle.transaction(run))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const parentTx = parentBound.drizzle
|
|
63
|
+
const names = [
|
|
64
|
+
'pipework.request_id', 'pipework.tenant_id', 'pipework.user_id', 'pipework.asof',
|
|
65
|
+
...Object.keys(flow.tenantConfig?.sessionVars ?? {}),
|
|
66
|
+
]
|
|
67
|
+
const before = new Map<string, string>()
|
|
68
|
+
for (const name of names) {
|
|
69
|
+
const rows = await parentTx.execute(sql`SELECT current_setting(${name}, true) AS value`)
|
|
70
|
+
before.set(name, (rows[0]?.['value'] as string | null | undefined) ?? '')
|
|
71
|
+
}
|
|
72
|
+
const work = parentTx.transaction(run).then(async (value) => {
|
|
73
|
+
// Releasing the savepoint keeps its SET LOCALs; put the request's own back.
|
|
74
|
+
for (const [name, value] of before) await parentTx.execute(sql`SELECT set_config(${name}, ${value}, true)`)
|
|
75
|
+
return value
|
|
76
|
+
})
|
|
77
|
+
return finalizeTrace(flow.instance, childTrace, work)
|
|
78
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { runInContext, requireContext, getContext } from '../context/store.js'
|
|
2
|
+
import { createTestContext } from '../context/create.js'
|
|
3
|
+
import { actAs } from './act-as.js'
|
|
4
|
+
|
|
5
|
+
/** AsyncLocalStorage context namespace — manages request/job/test contexts that carry auth, tenant, transactions. */
|
|
6
|
+
export const flow = {
|
|
7
|
+
/** Executes a function within a Flow context (AsyncLocalStorage). All pipe() calls inside will use this context. */
|
|
8
|
+
run: runInContext,
|
|
9
|
+
/** Returns the current Flow or throws — use in code that must run inside a managed context. */
|
|
10
|
+
require: requireContext,
|
|
11
|
+
/** Returns the current Flow or undefined — use for optional context detection. */
|
|
12
|
+
get: getContext,
|
|
13
|
+
/** Creates a Flow for test isolation with optional auth and tenant overrides. */
|
|
14
|
+
createTest: createTestContext,
|
|
15
|
+
/** Runs `fn` as a tenant and user chosen inside a tenantless Flow (sign-up, a public sign-in): RLS, audit and trace under that tenant, on the request's transaction. */
|
|
16
|
+
actAs,
|
|
17
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import type { Flow } from '../context/index.js'
|
|
3
|
+
import { ValidationError } from '../../core/errors/index.js'
|
|
4
|
+
import { serializeForTrace } from '../../trace/capture/bounded-serializer.js'
|
|
5
|
+
import { projectStepError } from '../../trace/runtime/step-error.js'
|
|
6
|
+
|
|
7
|
+
export interface ErrorStepInfo {
|
|
8
|
+
readonly method: string
|
|
9
|
+
/** The route pattern (`/things/:id`), never the URL. */
|
|
10
|
+
readonly route: string
|
|
11
|
+
readonly status: number
|
|
12
|
+
readonly code: string
|
|
13
|
+
readonly error: unknown
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Records one `http.error` step on the request's trace for an error response:
|
|
18
|
+
* method, route pattern, status, code and, for a ValidationError, each issue's
|
|
19
|
+
* source, path and message. Input values are never recorded. A no-op when the
|
|
20
|
+
* request has no trace (the error came before it opened, or tracing is off).
|
|
21
|
+
*/
|
|
22
|
+
export function recordErrorStep(ctx: Flow | undefined, info: ErrorStepInfo): void {
|
|
23
|
+
const trace = ctx?.trace
|
|
24
|
+
if (trace === undefined || trace === null) return
|
|
25
|
+
const meta: Record<string, unknown> = { method: info.method, route: info.route, status: info.status, code: info.code }
|
|
26
|
+
if (info.error instanceof ValidationError) {
|
|
27
|
+
meta['issues'] = info.error.issues.map(i => ({ source: i.source, path: [...i.path], message: i.message }))
|
|
28
|
+
}
|
|
29
|
+
const now = new Date()
|
|
30
|
+
const { name, message } = projectStepError(info.error)
|
|
31
|
+
trace.buffer.stageExternal({
|
|
32
|
+
id: randomUUID(),
|
|
33
|
+
parentStepId: trace.buffer.openStepId,
|
|
34
|
+
flowStepRef: 'http.error',
|
|
35
|
+
status: 'error',
|
|
36
|
+
startedAt: now,
|
|
37
|
+
completedAt: now,
|
|
38
|
+
durationMicros: 0n,
|
|
39
|
+
capturedInputs: null,
|
|
40
|
+
error: { name, message: serializeForTrace(message) as string, stack: null, detail: serializeForTrace(meta) },
|
|
41
|
+
})
|
|
42
|
+
}
|