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.
Files changed (690) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/package.json +4 -3
  3. package/src/async/jobs/abortable-delay.ts +18 -0
  4. package/src/async/jobs/claims.ts +52 -0
  5. package/src/async/jobs/cron.ts +179 -0
  6. package/src/async/jobs/errors.ts +56 -0
  7. package/src/async/jobs/exclusion.ts +117 -0
  8. package/src/async/jobs/execute.ts +219 -0
  9. package/src/async/jobs/index.ts +10 -0
  10. package/src/async/jobs/listener.ts +135 -0
  11. package/src/async/jobs/namespace.ts +20 -0
  12. package/src/async/jobs/queue-door.ts +44 -0
  13. package/src/async/jobs/queue.ts +1012 -0
  14. package/src/async/jobs/run-script.ts +67 -0
  15. package/src/async/jobs/scheduler.ts +218 -0
  16. package/src/async/jobs/schedules-table.ts +37 -0
  17. package/src/async/jobs/serialize-error.ts +48 -0
  18. package/src/async/jobs/table.ts +191 -0
  19. package/src/async/pipeline/define.ts +53 -0
  20. package/src/async/pipeline/errors.ts +35 -0
  21. package/src/async/pipeline/execute.ts +53 -0
  22. package/src/async/pipeline/index.ts +13 -0
  23. package/src/async/pipeline/namespace.ts +12 -0
  24. package/src/async/pipeline/resume.ts +67 -0
  25. package/src/async/pipeline/run-steps.ts +98 -0
  26. package/src/async/pipeline/types.ts +57 -0
  27. package/src/async/state-machine/define.ts +64 -0
  28. package/src/async/state-machine/errors.ts +29 -0
  29. package/src/async/state-machine/index.ts +3 -0
  30. package/src/async/state-machine/namespace.ts +12 -0
  31. package/src/async/state-machine/transition.ts +90 -0
  32. package/src/async/state-machine/types.ts +37 -0
  33. package/src/async/steps/errors.ts +31 -0
  34. package/src/async/steps/graph.ts +1214 -0
  35. package/src/async/steps/hash.ts +40 -0
  36. package/src/async/steps/index.ts +7 -0
  37. package/src/async/steps/namespace.ts +7 -0
  38. package/src/async/steps/table.ts +97 -0
  39. package/src/async/steps/types.ts +318 -0
  40. package/src/audit/chain/index.ts +9 -0
  41. package/src/audit/chain/install.ts +113 -0
  42. package/src/audit/chain/retire.ts +52 -0
  43. package/src/audit/chain/verify.ts +257 -0
  44. package/src/audit/query/cursor.ts +37 -0
  45. package/src/audit/query/index.ts +9 -0
  46. package/src/audit/query/query.ts +223 -0
  47. package/src/audit/schema/audit-record-fields.ts +68 -0
  48. package/src/audit/schema/audit-record.ts +23 -0
  49. package/src/auth/auth/audit.ts +31 -0
  50. package/src/auth/auth/chain.ts +84 -0
  51. package/src/auth/auth/cookie.ts +136 -0
  52. package/src/auth/auth/email-links.ts +311 -0
  53. package/src/auth/auth/guard.ts +128 -0
  54. package/src/auth/auth/index.ts +18 -0
  55. package/src/auth/auth/multi-org.ts +337 -0
  56. package/src/auth/auth/namespace.ts +34 -0
  57. package/src/auth/auth/parse-expiry.ts +13 -0
  58. package/src/auth/auth/passwords.ts +110 -0
  59. package/src/auth/auth/schema.ts +110 -0
  60. package/src/auth/auth/sessions.ts +565 -0
  61. package/src/auth/auth/sign-in.ts +156 -0
  62. package/src/auth/auth/signing-keys.ts +69 -0
  63. package/src/auth/auth/types.ts +26 -0
  64. package/src/auth/auth/uuid.ts +10 -0
  65. package/src/auth/rbac/cache.ts +55 -0
  66. package/src/auth/rbac/check.ts +30 -0
  67. package/src/auth/rbac/create.ts +35 -0
  68. package/src/auth/rbac/index.ts +5 -0
  69. package/src/auth/rbac/middleware.ts +20 -0
  70. package/src/auth/rbac/namespace.ts +15 -0
  71. package/src/auth/rbac/resolve.ts +31 -0
  72. package/src/auth/rbac/schema.sql +31 -0
  73. package/src/auth/rbac/seed.ts +67 -0
  74. package/src/auth/rbac/tables.ts +32 -0
  75. package/src/auth/rbac/types.ts +65 -0
  76. package/src/auth/tenant/extract.ts +33 -0
  77. package/src/auth/tenant/in-tenant.ts +49 -0
  78. package/src/auth/tenant/index.ts +7 -0
  79. package/src/auth/tenant/namespace.ts +23 -0
  80. package/src/auth/tenant/propagate.ts +20 -0
  81. package/src/auth/tenant/rls.ts +120 -0
  82. package/src/auth/tenant/scope.ts +33 -0
  83. package/src/auth/tenant/scoped-db.ts +581 -0
  84. package/src/auth/tenant/types.ts +14 -0
  85. package/src/auth/tenant/validate.ts +27 -0
  86. package/src/cli/commands/add.ts +158 -0
  87. package/src/cli/commands/alerts.ts +98 -0
  88. package/src/cli/commands/check.ts +1418 -0
  89. package/src/cli/commands/codemod.ts +78 -0
  90. package/src/cli/commands/db.ts +356 -0
  91. package/src/cli/commands/dev.ts +101 -0
  92. package/src/cli/commands/generate.ts +75 -0
  93. package/src/cli/commands/init.ts +36 -0
  94. package/src/cli/commands/install.ts +28 -0
  95. package/src/cli/commands/lint.ts +62 -0
  96. package/src/cli/commands/migrate.ts +132 -0
  97. package/src/cli/commands/openapi.ts +63 -0
  98. package/src/cli/commands/remove.ts +72 -0
  99. package/src/cli/commands/run.ts +50 -0
  100. package/src/cli/commands/scope.ts +54 -0
  101. package/src/cli/commands/serve.ts +68 -0
  102. package/src/cli/commands/shard.ts +31 -0
  103. package/src/cli/commands/shared/config-pipework-version.ts +28 -0
  104. package/src/cli/commands/shared/find-config.ts +22 -0
  105. package/src/cli/commands/shared/load-config.ts +35 -0
  106. package/src/cli/commands/shared/pnpm-install.ts +95 -0
  107. package/src/cli/commands/shared/report-removed.ts +8 -0
  108. package/src/cli/commands/sync.ts +32 -0
  109. package/src/cli/commands/test.ts +307 -0
  110. package/src/cli/commands/upgrade.ts +48 -0
  111. package/src/cli/dev-bootstrap.ts +24 -0
  112. package/src/cli/errors.ts +10 -0
  113. package/src/cli/index.ts +303 -0
  114. package/src/cli/output.ts +17 -0
  115. package/src/cli/port.ts +15 -0
  116. package/src/cli/surface-kinds.ts +20 -0
  117. package/src/client/index.ts +4 -0
  118. package/src/client/poll.ts +130 -0
  119. package/src/client/report-fault.ts +119 -0
  120. package/src/core/config/app-pool.ts +19 -0
  121. package/src/core/config/aws-env.ts +29 -0
  122. package/src/core/config/base-dir.ts +24 -0
  123. package/src/core/config/discover.ts +64 -0
  124. package/src/core/config/env-resolve.ts +87 -0
  125. package/src/core/config/env-types.ts +116 -0
  126. package/src/core/config/env.ts +55 -0
  127. package/src/core/config/errors.ts +9 -0
  128. package/src/core/config/import-config.ts +40 -0
  129. package/src/core/config/index.ts +8 -0
  130. package/src/core/config/load.ts +417 -0
  131. package/src/core/config/namespace.ts +14 -0
  132. package/src/core/config/resolve.ts +195 -0
  133. package/src/core/config/schema.ts +488 -0
  134. package/src/core/config/statement-observer.ts +48 -0
  135. package/src/core/config/ts-inline-hooks.ts +75 -0
  136. package/src/core/config/ts-register.ts +4 -0
  137. package/src/core/config/ts-resolve-hooks.ts +101 -0
  138. package/src/core/errors/base.ts +49 -0
  139. package/src/core/errors/http.ts +146 -0
  140. package/src/core/errors/index.ts +2 -0
  141. package/src/core/errors/namespace.ts +31 -0
  142. package/src/core/lifecycle/drain.ts +33 -0
  143. package/src/core/lifecycle/health.ts +72 -0
  144. package/src/core/lifecycle/index.ts +4 -0
  145. package/src/core/lifecycle/namespace.ts +7 -0
  146. package/src/core/lifecycle/startup.ts +102 -0
  147. package/src/core/lifecycle/types.ts +36 -0
  148. package/src/core/logging/context.ts +60 -0
  149. package/src/core/logging/error-chain.ts +68 -0
  150. package/src/core/logging/index.ts +5 -0
  151. package/src/core/logging/logger.ts +65 -0
  152. package/src/core/logging/namespace.ts +16 -0
  153. package/src/core/logging/proxy.ts +22 -0
  154. package/src/core/logging/redact-match.ts +24 -0
  155. package/src/core/logging/types.ts +47 -0
  156. package/src/core/pipework.ts +566 -0
  157. package/src/core/runtime/broker.ts +69 -0
  158. package/src/core/surface/http.ts +133 -0
  159. package/src/core/surface/index.ts +11 -0
  160. package/src/core/surface/job-timeout.ts +40 -0
  161. package/src/core/surface/namespace.ts +13 -0
  162. package/src/core/surface/script.ts +33 -0
  163. package/src/core/surface/start.ts +142 -0
  164. package/src/core/surface/types.ts +225 -0
  165. package/src/core/surface/validate.ts +88 -0
  166. package/src/core/surface/worker.ts +528 -0
  167. package/src/core/validation/connectivity.ts +49 -0
  168. package/src/core/validation/domain.ts +99 -0
  169. package/src/core/validation/index.ts +5 -0
  170. package/src/core/validation/queue-tables.ts +312 -0
  171. package/src/core/validation/rls-role.ts +138 -0
  172. package/src/core/validation/startup.ts +51 -0
  173. package/src/core/validation/surfaces.ts +65 -0
  174. package/src/core/validation/types.ts +25 -0
  175. package/src/data/db/advisory-lock.ts +55 -0
  176. package/src/data/db/aggregates.ts +172 -0
  177. package/src/data/db/array-elements.ts +111 -0
  178. package/src/data/db/bulk-set.ts +53 -0
  179. package/src/data/db/col/index.ts +14 -0
  180. package/src/data/db/composed.ts +53 -0
  181. package/src/data/db/db.ts +276 -0
  182. package/src/data/db/excluded.ts +16 -0
  183. package/src/data/db/expressions.ts +473 -0
  184. package/src/data/db/filter.ts +90 -0
  185. package/src/data/db/function-source.ts +114 -0
  186. package/src/data/db/identifiers.ts +16 -0
  187. package/src/data/db/idx/index.ts +9 -0
  188. package/src/data/db/in-list.ts +49 -0
  189. package/src/data/db/index.ts +9 -0
  190. package/src/data/db/insert-split.ts +137 -0
  191. package/src/data/db/instrumentation.ts +82 -0
  192. package/src/data/db/maintenance.ts +28 -0
  193. package/src/data/db/namespace.ts +107 -0
  194. package/src/data/db/owner-labels.ts +9 -0
  195. package/src/data/db/pool.ts +187 -0
  196. package/src/data/db/query-label.ts +13 -0
  197. package/src/data/db/query-watch.ts +116 -0
  198. package/src/data/db/raw-client-warning.ts +37 -0
  199. package/src/data/db/readonly.ts +23 -0
  200. package/src/data/db/reservation.ts +151 -0
  201. package/src/data/db/schema-features.ts +14 -0
  202. package/src/data/db/serializable.ts +83 -0
  203. package/src/data/db/sql.ts +1 -0
  204. package/src/data/db/timeouts.ts +76 -0
  205. package/src/data/db/types.ts +18 -0
  206. package/src/data/db/unbound.ts +33 -0
  207. package/src/data/db/values.ts +29 -0
  208. package/src/data/domain/brand.ts +15 -0
  209. package/src/data/domain/build-factory.ts +193 -0
  210. package/src/data/domain/build-schema.ts +161 -0
  211. package/src/data/domain/build-table.ts +355 -0
  212. package/src/data/domain/define.ts +239 -0
  213. package/src/data/domain/external-registry.ts +34 -0
  214. package/src/data/domain/external.ts +77 -0
  215. package/src/data/domain/field.ts +279 -0
  216. package/src/data/domain/index.ts +13 -0
  217. package/src/data/domain/naming.ts +6 -0
  218. package/src/data/domain/projections.ts +57 -0
  219. package/src/data/domain/trace-safe-projection.ts +31 -0
  220. package/src/data/domain/traits.ts +108 -0
  221. package/src/data/domain/types.ts +289 -0
  222. package/src/data/jsonb/composed.ts +18 -0
  223. package/src/data/jsonb/index.ts +1 -0
  224. package/src/data/jsonb/namespace.ts +30 -0
  225. package/src/data/jsonb/query.ts +86 -0
  226. package/src/data/migrate/append-only-generate.ts +47 -0
  227. package/src/data/migrate/applied.ts +47 -0
  228. package/src/data/migrate/apply.ts +309 -0
  229. package/src/data/migrate/check.ts +119 -0
  230. package/src/data/migrate/diff.ts +357 -0
  231. package/src/data/migrate/door-generate.ts +130 -0
  232. package/src/data/migrate/framework-rls.ts +58 -0
  233. package/src/data/migrate/generate.ts +201 -0
  234. package/src/data/migrate/history.ts +215 -0
  235. package/src/data/migrate/index.ts +9 -0
  236. package/src/data/migrate/internal-definitions.ts +175 -0
  237. package/src/data/migrate/post-process.ts +73 -0
  238. package/src/data/migrate/pragma.ts +73 -0
  239. package/src/data/migrate/provision-framework.ts +147 -0
  240. package/src/data/migrate/rls-generate.ts +61 -0
  241. package/src/data/migrate/run.ts +124 -0
  242. package/src/data/migrate/safety.ts +167 -0
  243. package/src/data/migrate/snapshot.ts +368 -0
  244. package/src/data/migrate/sql-emit.ts +392 -0
  245. package/src/data/migrate/statements.ts +312 -0
  246. package/src/data/query/alias.ts +126 -0
  247. package/src/data/query/batch.ts +8 -0
  248. package/src/data/query/cache/core/cache.ts +78 -0
  249. package/src/data/query/cache/core/index.ts +1 -0
  250. package/src/data/query/cache/core/types.ts +29 -0
  251. package/src/data/query/cache/readme.md +230 -0
  252. package/src/data/query/casing.ts +76 -0
  253. package/src/data/query/collation.ts +11 -0
  254. package/src/data/query/column-builder.ts +370 -0
  255. package/src/data/query/column.ts +150 -0
  256. package/src/data/query/entity.ts +42 -0
  257. package/src/data/query/errors.ts +33 -0
  258. package/src/data/query/index.ts +14 -0
  259. package/src/data/query/logger.ts +47 -0
  260. package/src/data/query/operations.ts +45 -0
  261. package/src/data/query/pg-core/alias.ts +12 -0
  262. package/src/data/query/pg-core/checks.ts +32 -0
  263. package/src/data/query/pg-core/columns/all.ts +71 -0
  264. package/src/data/query/pg-core/columns/bigint.ts +110 -0
  265. package/src/data/query/pg-core/columns/bigserial.ts +128 -0
  266. package/src/data/query/pg-core/columns/boolean.ts +43 -0
  267. package/src/data/query/pg-core/columns/char.ts +85 -0
  268. package/src/data/query/pg-core/columns/cidr.ts +43 -0
  269. package/src/data/query/pg-core/columns/common.ts +366 -0
  270. package/src/data/query/pg-core/columns/custom.ts +232 -0
  271. package/src/data/query/pg-core/columns/date.common.ts +15 -0
  272. package/src/data/query/pg-core/columns/date.ts +112 -0
  273. package/src/data/query/pg-core/columns/double-precision.ts +55 -0
  274. package/src/data/query/pg-core/columns/enum.ts +201 -0
  275. package/src/data/query/pg-core/columns/index.ts +35 -0
  276. package/src/data/query/pg-core/columns/inet.ts +43 -0
  277. package/src/data/query/pg-core/columns/int.common.ts +57 -0
  278. package/src/data/query/pg-core/columns/integer.ts +53 -0
  279. package/src/data/query/pg-core/columns/interval.ts +83 -0
  280. package/src/data/query/pg-core/columns/json.ts +58 -0
  281. package/src/data/query/pg-core/columns/jsonb.ts +56 -0
  282. package/src/data/query/pg-core/columns/line.ts +117 -0
  283. package/src/data/query/pg-core/columns/macaddr.ts +43 -0
  284. package/src/data/query/pg-core/columns/macaddr8.ts +43 -0
  285. package/src/data/query/pg-core/columns/numeric.ts +227 -0
  286. package/src/data/query/pg-core/columns/point.ts +127 -0
  287. package/src/data/query/pg-core/columns/postgis_extension/geometry.ts +119 -0
  288. package/src/data/query/pg-core/columns/postgis_extension/utils.ts +47 -0
  289. package/src/data/query/pg-core/columns/real.ts +58 -0
  290. package/src/data/query/pg-core/columns/serial.ts +55 -0
  291. package/src/data/query/pg-core/columns/smallint.ts +53 -0
  292. package/src/data/query/pg-core/columns/smallserial.ts +60 -0
  293. package/src/data/query/pg-core/columns/text.ts +67 -0
  294. package/src/data/query/pg-core/columns/time.ts +72 -0
  295. package/src/data/query/pg-core/columns/timestamp.ts +163 -0
  296. package/src/data/query/pg-core/columns/uuid.ts +51 -0
  297. package/src/data/query/pg-core/columns/varchar.ts +89 -0
  298. package/src/data/query/pg-core/columns/vector_extension/bit.ts +68 -0
  299. package/src/data/query/pg-core/columns/vector_extension/halfvec.ts +80 -0
  300. package/src/data/query/pg-core/columns/vector_extension/sparsevec.ts +67 -0
  301. package/src/data/query/pg-core/columns/vector_extension/vector.ts +80 -0
  302. package/src/data/query/pg-core/db.ts +674 -0
  303. package/src/data/query/pg-core/dialect.ts +1404 -0
  304. package/src/data/query/pg-core/expressions.ts +25 -0
  305. package/src/data/query/pg-core/foreign-keys.ts +130 -0
  306. package/src/data/query/pg-core/index.ts +21 -0
  307. package/src/data/query/pg-core/indexes.ts +276 -0
  308. package/src/data/query/pg-core/policies.ts +56 -0
  309. package/src/data/query/pg-core/primary-keys.ts +62 -0
  310. package/src/data/query/pg-core/query-builders/count.ts +86 -0
  311. package/src/data/query/pg-core/query-builders/delete.ts +293 -0
  312. package/src/data/query/pg-core/query-builders/index.ts +7 -0
  313. package/src/data/query/pg-core/query-builders/insert.ts +452 -0
  314. package/src/data/query/pg-core/query-builders/query-builder.ts +123 -0
  315. package/src/data/query/pg-core/query-builders/query.ts +157 -0
  316. package/src/data/query/pg-core/query-builders/raw.ts +49 -0
  317. package/src/data/query/pg-core/query-builders/refresh-materialized-view.ts +108 -0
  318. package/src/data/query/pg-core/query-builders/select.ts +1346 -0
  319. package/src/data/query/pg-core/query-builders/select.types.ts +437 -0
  320. package/src/data/query/pg-core/query-builders/update.ts +626 -0
  321. package/src/data/query/pg-core/roles.ts +41 -0
  322. package/src/data/query/pg-core/schema.ts +72 -0
  323. package/src/data/query/pg-core/sequence.ts +41 -0
  324. package/src/data/query/pg-core/session.ts +292 -0
  325. package/src/data/query/pg-core/subquery.ts +46 -0
  326. package/src/data/query/pg-core/table.ts +252 -0
  327. package/src/data/query/pg-core/unique-constraint.ts +73 -0
  328. package/src/data/query/pg-core/utils/array.ts +95 -0
  329. package/src/data/query/pg-core/utils/index.ts +1 -0
  330. package/src/data/query/pg-core/utils.ts +104 -0
  331. package/src/data/query/pg-core/view-base.ts +14 -0
  332. package/src/data/query/pg-core/view-common.ts +1 -0
  333. package/src/data/query/pg-core/view.ts +435 -0
  334. package/src/data/query/pg-core/with-builder.ts +41 -0
  335. package/src/data/query/postgres-js/README.md +46 -0
  336. package/src/data/query/postgres-js/array-parser.ts +45 -0
  337. package/src/data/query/postgres-js/driver-error-boundary.ts +149 -0
  338. package/src/data/query/postgres-js/driver.ts +163 -0
  339. package/src/data/query/postgres-js/index.ts +2 -0
  340. package/src/data/query/postgres-js/session.ts +234 -0
  341. package/src/data/query/primary-key.ts +11 -0
  342. package/src/data/query/query-builders/query-builder.ts +19 -0
  343. package/src/data/query/query-builders/select.types.ts +175 -0
  344. package/src/data/query/query-promise.ts +35 -0
  345. package/src/data/query/relations.ts +725 -0
  346. package/src/data/query/runnable-query.ts +12 -0
  347. package/src/data/query/selection-proxy.ts +121 -0
  348. package/src/data/query/session.ts +8 -0
  349. package/src/data/query/sql/expressions/conditions.ts +741 -0
  350. package/src/data/query/sql/expressions/index.ts +2 -0
  351. package/src/data/query/sql/expressions/select.ts +45 -0
  352. package/src/data/query/sql/functions/aggregate.ts +129 -0
  353. package/src/data/query/sql/functions/index.ts +2 -0
  354. package/src/data/query/sql/functions/vector.ts +178 -0
  355. package/src/data/query/sql/index.ts +3 -0
  356. package/src/data/query/sql/sql.ts +794 -0
  357. package/src/data/query/subquery.ts +53 -0
  358. package/src/data/query/table.ts +208 -0
  359. package/src/data/query/table.utils.ts +2 -0
  360. package/src/data/query/tracing-utils.ts +3 -0
  361. package/src/data/query/tracing.ts +11 -0
  362. package/src/data/query/utils.ts +357 -0
  363. package/src/data/query/version.ts +4 -0
  364. package/src/data/query/view-common.ts +1 -0
  365. package/src/data/schema/branded.ts +13 -0
  366. package/src/data/schema/generated/coerce.ts +5 -0
  367. package/src/data/schema/generated/combinator.ts +6 -0
  368. package/src/data/schema/generated/encoding.ts +5 -0
  369. package/src/data/schema/generated/error.ts +6 -0
  370. package/src/data/schema/generated/format.ts +5 -0
  371. package/src/data/schema/generated/type-constructor.ts +10 -0
  372. package/src/data/schema/generated/type.ts +6 -0
  373. package/src/data/schema/index.ts +6 -0
  374. package/src/data/schema/json-schema.ts +33 -0
  375. package/src/data/schema/namespace.ts +55 -0
  376. package/src/data/schema/parse.ts +39 -0
  377. package/src/data/schema/types.ts +39 -0
  378. package/src/data/temporal/append-only.ts +134 -0
  379. package/src/data/temporal/close.ts +27 -0
  380. package/src/data/temporal/columns.ts +10 -0
  381. package/src/data/temporal/definition-queries.ts +70 -0
  382. package/src/data/temporal/errors.ts +10 -0
  383. package/src/data/temporal/get-current.ts +22 -0
  384. package/src/data/temporal/index.ts +9 -0
  385. package/src/data/temporal/namespace.ts +36 -0
  386. package/src/data/temporal/query.ts +25 -0
  387. package/src/data/temporal/resolve.ts +17 -0
  388. package/src/data/temporal/revise.ts +67 -0
  389. package/src/data/temporal/types.ts +22 -0
  390. package/src/data/valve/artifact.ts +33 -0
  391. package/src/data/valve/contract-diff.ts +21 -0
  392. package/src/data/valve/cross.ts +57 -0
  393. package/src/data/valve/crossing-ledger.ts +50 -0
  394. package/src/data/valve/decision.ts +44 -0
  395. package/src/data/valve/durable-crossing.ts +52 -0
  396. package/src/data/valve/execute-crossing.ts +77 -0
  397. package/src/data/valve/faucet.ts +56 -0
  398. package/src/data/valve/gate.ts +114 -0
  399. package/src/data/valve/graph.ts +77 -0
  400. package/src/data/valve/index.ts +53 -0
  401. package/src/data/valve/namespace.ts +57 -0
  402. package/src/data/valve/registry.ts +50 -0
  403. package/src/data/valve/schema/valve-crossing-fields.ts +23 -0
  404. package/src/data/valve/schema/valve-crossing.ts +9 -0
  405. package/src/data/valve/supply.ts +154 -0
  406. package/src/data/valve/types.ts +143 -0
  407. package/src/data/vector/columns.ts +27 -0
  408. package/src/data/vector/index.ts +4 -0
  409. package/src/data/vector/namespace.ts +33 -0
  410. package/src/data/vector/query.ts +85 -0
  411. package/src/data/vector/validate.ts +16 -0
  412. package/src/data/write/audit/actor.ts +15 -0
  413. package/src/data/write/audit/audit-columns.ts +18 -0
  414. package/src/data/write/audit/audit-select.ts +111 -0
  415. package/src/data/write/audit/bound-transaction.ts +14 -0
  416. package/src/data/write/audit/cte-compile.ts +32 -0
  417. package/src/data/write/audit/decode-returning.ts +47 -0
  418. package/src/data/write/audit/final-select.ts +43 -0
  419. package/src/data/write/audit/infra-audit.ts +36 -0
  420. package/src/data/write/audit/primary-key.ts +65 -0
  421. package/src/data/write/audit/projection.ts +41 -0
  422. package/src/data/write/audit/read-touches.ts +86 -0
  423. package/src/data/write/audit/touch-match.ts +78 -0
  424. package/src/data/write/audit/verb-delete.ts +62 -0
  425. package/src/data/write/audit/verb-insert.ts +36 -0
  426. package/src/data/write/audit/verb-select.ts +47 -0
  427. package/src/data/write/audit/verb-update.ts +60 -0
  428. package/src/data/write/audit/verb-upsert.ts +104 -0
  429. package/src/data/write/conflict.ts +43 -0
  430. package/src/data/write/delete.ts +38 -0
  431. package/src/data/write/execute.ts +243 -0
  432. package/src/data/write/index.ts +11 -0
  433. package/src/data/write/insert.ts +63 -0
  434. package/src/data/write/state.ts +43 -0
  435. package/src/data/write/update.ts +54 -0
  436. package/src/data/write/upsert.ts +58 -0
  437. package/src/data/write/values.ts +19 -0
  438. package/src/index.ts +230 -0
  439. package/src/infra/access-links/code.ts +70 -0
  440. package/src/infra/access-links/handle.ts +892 -0
  441. package/src/infra/access-links/index.ts +9 -0
  442. package/src/infra/access-links/namespace.ts +30 -0
  443. package/src/infra/access-links/person-check.ts +177 -0
  444. package/src/infra/access-links/schema.ts +71 -0
  445. package/src/infra/alerts/async-sources.ts +231 -0
  446. package/src/infra/alerts/audit.ts +36 -0
  447. package/src/infra/alerts/beat.ts +123 -0
  448. package/src/infra/alerts/client-faults.ts +111 -0
  449. package/src/infra/alerts/faults.ts +156 -0
  450. package/src/infra/alerts/handle.ts +778 -0
  451. package/src/infra/alerts/http.ts +192 -0
  452. package/src/infra/alerts/index.ts +12 -0
  453. package/src/infra/alerts/infra-sources.ts +180 -0
  454. package/src/infra/alerts/namespace.ts +81 -0
  455. package/src/infra/alerts/redact.ts +21 -0
  456. package/src/infra/alerts/request-faults.ts +41 -0
  457. package/src/infra/alerts/schema.ts +124 -0
  458. package/src/infra/alerts/sinks.ts +125 -0
  459. package/src/infra/alerts/source-options.ts +26 -0
  460. package/src/infra/alerts/sources.ts +503 -0
  461. package/src/infra/alerts/subsystem-sources.ts +137 -0
  462. package/src/infra/audit/emit.ts +87 -0
  463. package/src/infra/audit/index.ts +2 -0
  464. package/src/infra/audit/namespace.ts +22 -0
  465. package/src/infra/audit/schema.sql +35 -0
  466. package/src/infra/audit/types.ts +18 -0
  467. package/src/infra/aws/credentials.ts +147 -0
  468. package/src/infra/aws/sigv4.ts +140 -0
  469. package/src/infra/cache/create.ts +58 -0
  470. package/src/infra/cache/entry.ts +81 -0
  471. package/src/infra/cache/index.ts +4 -0
  472. package/src/infra/cache/namespace.ts +10 -0
  473. package/src/infra/cache/tenant.ts +93 -0
  474. package/src/infra/cache/types.ts +24 -0
  475. package/src/infra/crawl/audit.ts +35 -0
  476. package/src/infra/crawl/errors.ts +25 -0
  477. package/src/infra/crawl/handle.ts +693 -0
  478. package/src/infra/crawl/index.ts +9 -0
  479. package/src/infra/crawl/links.ts +160 -0
  480. package/src/infra/crawl/namespace.ts +36 -0
  481. package/src/infra/crawl/robots.ts +100 -0
  482. package/src/infra/crawl/schema.ts +89 -0
  483. package/src/infra/credit-line/handle.ts +883 -0
  484. package/src/infra/credit-line/index.ts +6 -0
  485. package/src/infra/credit-line/namespace.ts +7 -0
  486. package/src/infra/credit-line/schema.ts +96 -0
  487. package/src/infra/credits/handle.ts +706 -0
  488. package/src/infra/credits/index.ts +5 -0
  489. package/src/infra/credits/namespace.ts +7 -0
  490. package/src/infra/credits/schema.ts +83 -0
  491. package/src/infra/email/audit.ts +36 -0
  492. package/src/infra/email/inbound.ts +622 -0
  493. package/src/infra/email/index.ts +11 -0
  494. package/src/infra/email/mail.ts +517 -0
  495. package/src/infra/email/mime.ts +447 -0
  496. package/src/infra/email/namespace.ts +22 -0
  497. package/src/infra/email/providers.ts +111 -0
  498. package/src/infra/email/schema.ts +96 -0
  499. package/src/infra/email/sns.ts +200 -0
  500. package/src/infra/email/unsubscribe.ts +44 -0
  501. package/src/infra/fetch/address.ts +88 -0
  502. package/src/infra/fetch/connect-retry.ts +87 -0
  503. package/src/infra/fetch/handle.ts +329 -0
  504. package/src/infra/fetch/index.ts +7 -0
  505. package/src/infra/fetch/namespace.ts +70 -0
  506. package/src/infra/idempotency/index.ts +3 -0
  507. package/src/infra/idempotency/middleware.ts +87 -0
  508. package/src/infra/idempotency/store.ts +92 -0
  509. package/src/infra/idempotency/types.ts +30 -0
  510. package/src/infra/join-requests/handle.ts +312 -0
  511. package/src/infra/join-requests/index.ts +2 -0
  512. package/src/infra/join-requests/namespace.ts +7 -0
  513. package/src/infra/join-requests/schema.ts +33 -0
  514. package/src/infra/outbox/core.ts +165 -0
  515. package/src/infra/quota/errors.ts +32 -0
  516. package/src/infra/quota/handle.ts +215 -0
  517. package/src/infra/quota/index.ts +5 -0
  518. package/src/infra/quota/namespace.ts +7 -0
  519. package/src/infra/quota/schema.ts +15 -0
  520. package/src/infra/storage/backend.ts +34 -0
  521. package/src/infra/storage/handle.ts +513 -0
  522. package/src/infra/storage/index.ts +9 -0
  523. package/src/infra/storage/local.ts +104 -0
  524. package/src/infra/storage/namespace.ts +13 -0
  525. package/src/infra/storage/s3.ts +257 -0
  526. package/src/infra/storage/schema.ts +24 -0
  527. package/src/infra/support/handle.ts +854 -0
  528. package/src/infra/support/http.ts +229 -0
  529. package/src/infra/support/index.ts +7 -0
  530. package/src/infra/support/namespace.ts +12 -0
  531. package/src/infra/support/schema.ts +96 -0
  532. package/src/infra/webhook/inbound.ts +45 -0
  533. package/src/infra/webhook/index.ts +5 -0
  534. package/src/infra/webhook/namespace.ts +24 -0
  535. package/src/infra/webhook/outbound.ts +315 -0
  536. package/src/infra/webhook/sign.ts +32 -0
  537. package/src/infra/webhook/verify.ts +82 -0
  538. package/src/invariants/assert.ts +26 -0
  539. package/src/invariants/index.ts +1 -0
  540. package/src/lint/config.ts +56 -0
  541. package/src/lint/doctrine.ts +163 -0
  542. package/src/lint/include.ts +97 -0
  543. package/src/lint/index.ts +3 -0
  544. package/src/lint/preset.ts +10 -0
  545. package/src/lint/resolver.ts +218 -0
  546. package/src/lint/rules/no-reexports.ts +46 -0
  547. package/src/request/behavior/audited.ts +85 -0
  548. package/src/request/behavior/cached.ts +62 -0
  549. package/src/request/behavior/compose.ts +28 -0
  550. package/src/request/behavior/index.ts +5 -0
  551. package/src/request/behavior/namespace.ts +16 -0
  552. package/src/request/behavior/types.ts +26 -0
  553. package/src/request/behavior/versioned.ts +54 -0
  554. package/src/request/context/create.ts +103 -0
  555. package/src/request/context/guard.ts +49 -0
  556. package/src/request/context/index.ts +4 -0
  557. package/src/request/context/run-in-transaction.ts +200 -0
  558. package/src/request/context/store.ts +28 -0
  559. package/src/request/context/types.ts +50 -0
  560. package/src/request/di/builder.ts +535 -0
  561. package/src/request/di/index.ts +8 -0
  562. package/src/request/di/resolve.ts +271 -0
  563. package/src/request/di/types.ts +262 -0
  564. package/src/request/fitting/namespace.ts +7 -0
  565. package/src/request/fixture/batch.ts +71 -0
  566. package/src/request/fixture/builder.ts +26 -0
  567. package/src/request/fixture/errors.ts +10 -0
  568. package/src/request/fixture/index.ts +8 -0
  569. package/src/request/fixture/namespace.ts +23 -0
  570. package/src/request/fixture/paginate.ts +44 -0
  571. package/src/request/fixture/to-handlers.ts +260 -0
  572. package/src/request/fixture/types.ts +79 -0
  573. package/src/request/flow/act-as.ts +78 -0
  574. package/src/request/flow/namespace.ts +17 -0
  575. package/src/request/http/error-step.ts +42 -0
  576. package/src/request/http/file.ts +141 -0
  577. package/src/request/http/index.ts +4 -0
  578. package/src/request/http/middleware.ts +141 -0
  579. package/src/request/http/namespace.ts +5 -0
  580. package/src/request/http/rate-limit-classes.ts +170 -0
  581. package/src/request/http/response.ts +82 -0
  582. package/src/request/http/server.ts +916 -0
  583. package/src/request/http/sniff.ts +261 -0
  584. package/src/request/http/types.ts +250 -0
  585. package/src/request/http/upload.ts +284 -0
  586. package/src/request/internal/text.ts +6 -0
  587. package/src/request/openapi/generate.ts +205 -0
  588. package/src/request/openapi/index.ts +2 -0
  589. package/src/request/openapi/namespace.ts +7 -0
  590. package/src/test/auth.ts +13 -0
  591. package/src/test/auto-setup.ts +45 -0
  592. package/src/test/context.ts +91 -0
  593. package/src/test/crawl-fixture.ts +157 -0
  594. package/src/test/discover-fork.ts +17 -0
  595. package/src/test/fingerprint.ts +135 -0
  596. package/src/test/globals.d.ts +7 -0
  597. package/src/test/index.ts +19 -0
  598. package/src/test/namespace.ts +87 -0
  599. package/src/test/plugin.ts +189 -0
  600. package/src/test/progress.ts +185 -0
  601. package/src/test/reap-after-run.ts +28 -0
  602. package/src/test/reap.ts +286 -0
  603. package/src/test/reset.ts +253 -0
  604. package/src/test/savepoints.ts +172 -0
  605. package/src/test/setup.ts +1422 -0
  606. package/src/test/system-channel.ts +50 -0
  607. package/src/test/vitest-plugin.ts +142 -0
  608. package/src/test/vitest-workspace.ts +507 -0
  609. package/src/test/vitest.ts +333 -0
  610. package/src/test/watch.ts +105 -0
  611. package/src/trace/capture/bounded-serializer.ts +146 -0
  612. package/src/trace/cardinality/analyze.ts +173 -0
  613. package/src/trace/cardinality/branch-context.ts +214 -0
  614. package/src/trace/cardinality/check.ts +33 -0
  615. package/src/trace/cardinality/classify-edge.ts +64 -0
  616. package/src/trace/cardinality/structural-max.ts +107 -0
  617. package/src/trace/check/coverage-check.ts +188 -0
  618. package/src/trace/check/flow-check.ts +103 -0
  619. package/src/trace/check/flow-step-site.ts +234 -0
  620. package/src/trace/check/io-pattern.ts +116 -0
  621. package/src/trace/codemod/add-cardinality.ts +152 -0
  622. package/src/trace/codemod/run.ts +80 -0
  623. package/src/trace/entry/child-trace.ts +21 -0
  624. package/src/trace/entry/close-trace.ts +87 -0
  625. package/src/trace/entry/finalize-trace.ts +28 -0
  626. package/src/trace/entry/open-trace.ts +138 -0
  627. package/src/trace/entry/parent-trace.ts +20 -0
  628. package/src/trace/entry/parse-traceparent.ts +39 -0
  629. package/src/trace/entry/process-start.ts +38 -0
  630. package/src/trace/entry/trace-context.ts +26 -0
  631. package/src/trace/entry/tracing-enabled.ts +10 -0
  632. package/src/trace/external/record.ts +195 -0
  633. package/src/trace/external/report.ts +66 -0
  634. package/src/trace/namespace.ts +19 -0
  635. package/src/trace/partition/day.ts +47 -0
  636. package/src/trace/partition/index.ts +14 -0
  637. package/src/trace/partition/partition-name.ts +23 -0
  638. package/src/trace/partition/plan.ts +82 -0
  639. package/src/trace/partition/schedule.ts +26 -0
  640. package/src/trace/partition/startup-hook.ts +39 -0
  641. package/src/trace/partition/sync.ts +154 -0
  642. package/src/trace/partition/tables.ts +53 -0
  643. package/src/trace/read/tree.ts +83 -0
  644. package/src/trace/retain/copy-on-error.ts +76 -0
  645. package/src/trace/runtime/expire-stale-traces.ts +54 -0
  646. package/src/trace/runtime/flow-step.ts +147 -0
  647. package/src/trace/runtime/flush-steps.ts +31 -0
  648. package/src/trace/runtime/pending-writes.ts +54 -0
  649. package/src/trace/runtime/step-buffer.ts +298 -0
  650. package/src/trace/runtime/step-error.ts +21 -0
  651. package/src/trace/runtime/step-meta.ts +55 -0
  652. package/src/trace/runtime/thenable.ts +12 -0
  653. package/src/trace/runtime/truncate-trace.ts +62 -0
  654. package/src/trace/schema/trace-fields.ts +52 -0
  655. package/src/trace/schema/trace-retained.ts +22 -0
  656. package/src/trace/schema/trace-step-fields.ts +44 -0
  657. package/src/trace/schema/trace-step-retained.ts +25 -0
  658. package/src/trace/schema/trace-step.ts +18 -0
  659. package/src/trace/schema/trace.ts +12 -0
  660. package/src/trace/transformer/apply.ts +79 -0
  661. package/src/trace/transformer/build-meta-literal.ts +30 -0
  662. package/src/trace/transformer/find-flow-step-sites.ts +85 -0
  663. package/src/trace/transformer/inject-flow-step-import.ts +39 -0
  664. package/src/trace/transformer/transform-error.ts +14 -0
  665. package/src/trace/transformer/transform-flow-steps.ts +123 -0
  666. package/src/trace/transformer/wrap-function-declaration.ts +62 -0
  667. package/src/trace/transformer/wrap-variable-declaration.ts +67 -0
  668. package/src/workspace/affected.ts +110 -0
  669. package/src/workspace/changed-files.ts +163 -0
  670. package/src/workspace/check-deps.ts +213 -0
  671. package/src/workspace/checksum.ts +20 -0
  672. package/src/workspace/dependency-graph.ts +67 -0
  673. package/src/workspace/detect-pipework-copies.ts +93 -0
  674. package/src/workspace/discover.ts +206 -0
  675. package/src/workspace/generate.ts +401 -0
  676. package/src/workspace/index.ts +7 -0
  677. package/src/workspace/module-imports-pipework.ts +39 -0
  678. package/src/workspace/module-package-name.ts +12 -0
  679. package/src/workspace/scrub-git-env.ts +23 -0
  680. package/src/workspace/source-paths.ts +36 -0
  681. package/src/workspace/sync.ts +182 -0
  682. package/dist/REFERENCE.md +0 -1477
  683. package/dist/infra/access-links/rate-limit.d.ts +0 -10
  684. package/dist/infra/access-links/rate-limit.d.ts.map +0 -1
  685. package/dist/infra/access-links/rate-limit.js +0 -28
  686. package/dist/infra/access-links/rate-limit.js.map +0 -1
  687. package/dist/infra/email/sigv4.d.ts +0 -24
  688. package/dist/infra/email/sigv4.d.ts.map +0 -1
  689. package/dist/infra/email/sigv4.js +0 -55
  690. package/dist/infra/email/sigv4.js.map +0 -1
@@ -0,0 +1,333 @@
1
+ import { beforeAll, afterAll, beforeEach, afterEach } from 'vitest'
2
+ import type { DB } from '../data/db/index.js'
3
+ import type { Blueprint } from '../core/config/index.js'
4
+ import type { Manifold } from '../core/pipework.js'
5
+ import type { SurfaceContext, TestClient } from '../core/surface/types.js'
6
+ import { createManifold } from '../core/pipework.js'
7
+ import { SETUP_HOOK_TIMEOUT_MS } from './progress.js'
8
+ import { setupTestDatabases, teardownTestDatabases, getTestDatabase } from './setup.js'
9
+ import { settleTraceWritesBounded, TEARDOWN_HOOK_TIMEOUT_MS } from '../trace/runtime/pending-writes.js'
10
+ import { beginTestIsolation, endTestIsolation, createTestContext, createSetupConnection, propagateTestSessionVars, runInContext, type TestContext } from './plugin.js'
11
+ import { describeError } from '../core/logging/error-chain.js'
12
+
13
+ export { type TestContext, type TestDatabaseConnections } from './plugin.js'
14
+
15
+ let _testContext: TestContext | null = null
16
+ let _instance: Manifold | null = null
17
+
18
+ const _setupConnections = new Map<string, { drizzle: DB; close: () => Promise<void> }>()
19
+
20
+ export function _setTestState(instance: Manifold, testContext?: TestContext | null): void {
21
+ _instance = instance
22
+ if (testContext !== undefined) {
23
+ _testContext = testContext
24
+ }
25
+ }
26
+
27
+ export function setupPipeworkTests(configOrInstance: Blueprint | Manifold): Manifold {
28
+ const instance = isInstance(configOrInstance) ? configOrInstance : createManifold(configOrInstance)
29
+ _instance = instance
30
+
31
+ beforeAll(async () => {
32
+ await setupTestDatabases(instance)
33
+ }, SETUP_HOOK_TIMEOUT_MS)
34
+
35
+ afterAll(async () => {
36
+ await teardownAfterAll(instance)
37
+ }, TEARDOWN_HOOK_TIMEOUT_MS)
38
+
39
+ beforeEach(async ({ task }) => {
40
+ _testContext = await beginTestIsolation(instance, task)
41
+ })
42
+
43
+ afterEach(async () => {
44
+ if (_testContext) {
45
+ await endTestIsolation(instance, _testContext)
46
+ _testContext = null
47
+ }
48
+ }, TEARDOWN_HOOK_TIMEOUT_MS)
49
+
50
+ return instance
51
+ }
52
+
53
+ export function useTestDb(name?: string): DB {
54
+ const resolvedName = name
55
+
56
+ function resolve(): DB {
57
+ if (!_testContext || !_instance) {
58
+ throw new Error(
59
+ '[pipework] No test context available.\n\n' +
60
+ ' useTestDb() only works inside test bodies (it, test) and beforeEach/afterEach.\n' +
61
+ ' For beforeAll/afterAll fixture setup, use useSetupDb() instead.\n'
62
+ )
63
+ }
64
+
65
+ const dbName = resolvedName ?? _instance.config.defaultDatabaseName()
66
+ const db = _testContext.db[dbName]
67
+ if (!db) {
68
+ const available = Object.keys(_testContext.db).join(', ')
69
+ throw new Error(
70
+ `[pipework] No test database "${dbName}". Available: ${available}`,
71
+ )
72
+ }
73
+ return db
74
+ }
75
+
76
+ return new Proxy({} as DB, {
77
+ get(_target, prop, receiver) {
78
+ const db = resolve()
79
+ const value: unknown = Reflect.get(db, prop, receiver)
80
+ return typeof value === 'function' ? (value as Function).bind(db) : value
81
+ },
82
+ has(_target, prop) {
83
+ return prop in resolve()
84
+ },
85
+ })
86
+ }
87
+
88
+ export function useSetupDb(name?: string): DB {
89
+ const resolvedName = name
90
+
91
+ function resolve(): DB {
92
+ if (!_instance) {
93
+ throw new Error(
94
+ '[pipework] No test instance available.\n\n' +
95
+ ' Add to your vitest.config.ts:\n' +
96
+ ' test: { setupFiles: [\'pipework/test/setup\'] }\n'
97
+ )
98
+ }
99
+
100
+ const dbName = resolvedName ?? _instance.config.defaultDatabaseName()
101
+
102
+ const existing = _setupConnections.get(dbName)
103
+ if (existing) return existing.drizzle
104
+
105
+ const testDb = getTestDatabase(dbName)
106
+ if (!testDb) {
107
+ throw new Error(
108
+ `[pipework] Test database "${dbName}" is not set up yet.\n\n` +
109
+ ' useSetupDb() requires setupTestDatabases() to have completed.\n' +
110
+ ' Make sure your beforeAll that seeds data runs after the pipework setup.\n'
111
+ )
112
+ }
113
+
114
+ const conn = createSetupConnection(testDb)
115
+ _setupConnections.set(dbName, conn)
116
+ return conn.drizzle
117
+ }
118
+
119
+ return new Proxy({} as DB, {
120
+ get(_target, prop, receiver) {
121
+ const db = resolve()
122
+ const value: unknown = Reflect.get(db, prop, receiver)
123
+ return typeof value === 'function' ? (value as Function).bind(db) : value
124
+ },
125
+ has(_target, prop) {
126
+ return prop in resolve()
127
+ },
128
+ })
129
+ }
130
+
131
+ /**
132
+ * Register a setup connection directly. Internal: the only caller outside this module
133
+ * is the test that proves a close failure is named rather than swallowed (#395), which
134
+ * needs a connection whose `close` rejects.
135
+ */
136
+ export function _registerSetupConnection(database: string, conn: { drizzle: DB; close: () => Promise<void> }): void {
137
+ _setupConnections.set(database, conn)
138
+ }
139
+
140
+ /**
141
+ * Close every connection `useSetupDb()` has opened, and forget them.
142
+ *
143
+ * The harness closes these in `setupPipeworkTests`' own `afterAll`. Under
144
+ * vitest's `sequence.hooks: 'stack'` that hook runs *after* a consumer's
145
+ * setupFile `afterAll`, so a teardown-time observer — one sampling
146
+ * `pg_stat_activity` to name leaked backends, say — sees every setup
147
+ * connection still open and cannot tell them from a real leak. Call this
148
+ * first, then sample: what remains is a true survivor set.
149
+ *
150
+ * Idempotent, and safe to call before the harness's own teardown — that
151
+ * teardown still closes the pool and drops the databases afterwards. A later
152
+ * `useSetupDb()` opens a fresh connection.
153
+ */
154
+ export async function closeSetupConnections(): Promise<void> {
155
+ const failures: Array<{ database: string; cause: unknown }> = []
156
+
157
+ for (const [database, conn] of _setupConnections) {
158
+ try {
159
+ await conn.close()
160
+ } catch (cause: unknown) {
161
+ failures.push({ database, cause })
162
+ }
163
+ }
164
+ // Cleared either way: a connection that would not close must not be handed to a
165
+ // later useSetupDb(). What must not happen is clearing it *quietly* — the backend
166
+ // stays held, and the only later evidence is a foreign pid in pg_stat_activity or
167
+ // a setup hook that times out, both of which read as a test or box fault (#395).
168
+ _setupConnections.clear()
169
+
170
+ if (failures.length > 0) throw new SetupConnectionCloseError(failures)
171
+ }
172
+
173
+ /**
174
+ * A setup connection refused to close.
175
+ *
176
+ * Names every database whose connection would not close and the underlying error,
177
+ * because the backend is still held: the alternative is a leak with no record, found
178
+ * later as an unexplained pid or a hook that never finishes.
179
+ */
180
+ export class SetupConnectionCloseError extends Error {
181
+ readonly failures: ReadonlyArray<{ database: string; cause: unknown }>
182
+
183
+ constructor(failures: ReadonlyArray<{ database: string; cause: unknown }>) {
184
+ const named = failures.map(f => ` ${f.database}: ${messageOf(f.cause)}`).join('\n')
185
+ super(
186
+ `[pipework] ${String(failures.length)} setup connection${failures.length === 1 ? '' : 's'} would not close.\n\n` +
187
+ `${named}\n\n` +
188
+ ' Each backend above is still held by this test process. It is dropped from\n' +
189
+ ' pipework\'s registry regardless, so a later useSetupDb() opens a fresh one —\n' +
190
+ ' but the old backend holds its locks until the process exits.\n',
191
+ )
192
+ this.name = 'SetupConnectionCloseError'
193
+ this.failures = failures
194
+ if (failures.length === 1) this.cause = failures[0]!.cause
195
+ }
196
+ }
197
+
198
+ /**
199
+ * The harness's own `afterAll`: close setup connections, the pool, the databases.
200
+ *
201
+ * A setup connection that will not close must not cost the pool and the databases
202
+ * their teardown — that would trade one leak for many. Every step runs, and the close
203
+ * failure is raised at the end so the file fails by name (#395).
204
+ */
205
+ export async function teardownAfterAll(instance: Manifold): Promise<void> {
206
+ await settleTraceWritesBounded()
207
+ let closeFailure: unknown
208
+ try {
209
+ await closeSetupConnections()
210
+ } catch (err: unknown) {
211
+ closeFailure = err
212
+ }
213
+
214
+ await instance.pool.closeAll()
215
+ await teardownTestDatabases()
216
+
217
+ if (closeFailure !== undefined) throw closeFailure
218
+ }
219
+
220
+ function messageOf(cause: unknown): string {
221
+ return describeError(cause).message
222
+ }
223
+
224
+ export function _isInTestIsolation(): boolean {
225
+ return _testContext !== null
226
+ }
227
+
228
+ /**
229
+ * The manifold the test harness set up: one connection per database with an
230
+ * open transaction, bound into the context for every database name. Nothing a
231
+ * handler writes under it is ever committed, so a test on this instance cannot
232
+ * observe commit boundaries in either direction — transaction-per-request on or
233
+ * off reads the same. A request, a job, `pipe.transaction()`, a `'manual'`
234
+ * checkpoint or any other framework transaction is a savepoint of the test's
235
+ * transaction (isolation-level options are ignored there): the transaction id
236
+ * stays the same, and tenant and other transaction-local settings, and the role,
237
+ * are back to their earlier values once it ends. For commit boundaries, build the venue from `discoverInstance()` and
238
+ * `createServer()` on the package entry instead.
239
+ */
240
+ export function useTestInstance(): Manifold {
241
+ if (!_instance) {
242
+ throw new Error(
243
+ '[pipework] No test instance available.\n\n' +
244
+ ' Add to your vitest.config.ts:\n' +
245
+ ' test: { setupFiles: [\'pipework/test/setup\'] }\n'
246
+ )
247
+ }
248
+ return _instance
249
+ }
250
+
251
+ export interface UseTestClientOptions {
252
+ /** App setup (services, sinks) that runs before the client is made. */
253
+ before?: () => void | Promise<void>
254
+ }
255
+
256
+ /**
257
+ * A test client made in this file's `beforeAll` and closed in its `afterAll`
258
+ * only if it was made, so a failed setup reports only its own error. Replaces
259
+ * the `let client; beforeAll(...); afterAll(() => client.close())` pattern.
260
+ *
261
+ * const client = useTestClient(api, useTestInstance, {
262
+ * before: async () => { await startSinks() },
263
+ * })
264
+ * it('answers', async () => { expect((await client.inject({ url: '/x' })).statusCode).toBe(200) })
265
+ *
266
+ * `inject` throws a `[pipework]` error if the client was not made or is closed.
267
+ */
268
+ export function useTestClient(
269
+ surface: { test(context: SurfaceContext): Promise<TestClient> },
270
+ context: () => SurfaceContext = useTestInstance,
271
+ options: UseTestClientOptions = {},
272
+ ): TestClient {
273
+ let made: TestClient | undefined
274
+ let closed = false
275
+
276
+ beforeAll(async () => {
277
+ await options.before?.()
278
+ made = await surface.test(context())
279
+ })
280
+
281
+ const close = async (): Promise<void> => {
282
+ if (!made || closed) return
283
+ closed = true
284
+ await made.close()
285
+ }
286
+
287
+ afterAll(close)
288
+
289
+ return {
290
+ async inject(opts) {
291
+ if (closed) {
292
+ throw new Error('[pipework] The test client is closed: inject() ran after close() or afterAll.')
293
+ }
294
+ if (!made) {
295
+ throw new Error('[pipework] The test client was not made: setup failed or the call ran before beforeAll. See the setup error above.')
296
+ }
297
+ return await made.inject(opts)
298
+ },
299
+ close,
300
+ }
301
+ }
302
+
303
+ export interface WithFlowOptions {
304
+ auth?: unknown
305
+ tenant?: string | null
306
+ }
307
+
308
+ export function withFlow<T>(fn: () => T): Promise<Awaited<T>>
309
+ export function withFlow<T>(options: WithFlowOptions, fn: () => T): Promise<Awaited<T>>
310
+ export async function withFlow<T>(fnOrOptions: (() => T) | WithFlowOptions, maybeFn?: () => T): Promise<Awaited<T>> {
311
+ if (!_testContext || !_instance) {
312
+ throw new Error(
313
+ '[pipework] No test context available.\n\n' +
314
+ ' Add to your vitest.config.ts:\n' +
315
+ ' test: { setupFiles: [\'pipework/test/setup\'] }\n'
316
+ )
317
+ }
318
+
319
+ const options = typeof fnOrOptions === 'function' ? {} : fnOrOptions
320
+ const fn = typeof fnOrOptions === 'function' ? fnOrOptions : maybeFn!
321
+
322
+ const ctx = createTestContext(_instance, _testContext, options.auth, options.tenant)
323
+
324
+ if (options.tenant != null) {
325
+ await propagateTestSessionVars(_instance, _testContext, options.tenant)
326
+ }
327
+
328
+ return await runInContext(ctx, fn) as Awaited<T>
329
+ }
330
+
331
+ function isInstance(v: Blueprint | Manifold): v is Manifold {
332
+ return 'pool' in v && 'config' in v
333
+ }
@@ -0,0 +1,105 @@
1
+ import { readFile } from 'node:fs/promises'
2
+ import postgres from 'postgres'
3
+ import { getAdminUrl } from './reap.js'
4
+
5
+ /** Prefix for the one stderr line written when a test is 2/3 of the way to its timeout. */
6
+ export const TEST_WATCH_LOG_PREFIX = 'pipework:test-watch'
7
+
8
+ const QUERY_MAX_CHARS = 200
9
+ const WATCH_FRACTION = 2 / 3
10
+ const WATCH_QUERY_TIMEOUT_MS = 5_000
11
+
12
+ export interface TestWatchTarget {
13
+ /** The test's full name, suites included. */
14
+ name: string
15
+ /** The effective timeout of the test in ms; 0 or less disables the watch. */
16
+ timeoutMs: number
17
+ /** Per-test databases whose backends are reported, with a URL to reach their server. */
18
+ databases: readonly { database: string; url: string }[]
19
+ }
20
+
21
+ interface BackendRow {
22
+ datname: string
23
+ pid: number
24
+ state: string | null
25
+ wait_event_type: string | null
26
+ wait_event: string | null
27
+ state_s: string | null
28
+ blocked_by: string | null
29
+ query: string | null
30
+ }
31
+
32
+ /**
33
+ * Arms a timer at 2/3 of the test's timeout. On fire it samples pg_stat_activity
34
+ * over its own short-lived connection (the test's is busy) plus the host's load
35
+ * and pressure files, and writes one line. Returns the disarm function; a test
36
+ * that ends first prints nothing. Nothing here may fail or delay the test.
37
+ */
38
+ export function armTestWatch(
39
+ target: TestWatchTarget,
40
+ write: (line: string) => void = line => console.warn(line),
41
+ ): () => void {
42
+ if (!(target.timeoutMs > 0)) return () => {}
43
+ const timer = setTimeout(() => {
44
+ void sampleLine(target).then(write, () => {})
45
+ }, Math.floor(target.timeoutMs * WATCH_FRACTION))
46
+ timer.unref()
47
+ return () => clearTimeout(timer)
48
+ }
49
+
50
+ async function sampleLine(target: TestWatchTarget): Promise<string> {
51
+ const parts: string[] = [`${TEST_WATCH_LOG_PREFIX} test=${JSON.stringify(target.name)} timeout_ms=${String(target.timeoutMs)}`]
52
+ const urls = new Map<string, string>()
53
+ for (const d of target.databases) urls.set(d.database, d.url)
54
+ const byServer = new Map<string, string[]>()
55
+ for (const [database, url] of urls) {
56
+ const admin = getAdminUrl(url)
57
+ byServer.set(admin, [...(byServer.get(admin) ?? []), database])
58
+ }
59
+ for (const [adminUrl, names] of byServer) {
60
+ try {
61
+ parts.push(...(await backends(adminUrl, names)))
62
+ } catch (error) {
63
+ parts.push(`watch-error=${oneLine(error instanceof Error ? error.message : String(error), 120)}`)
64
+ }
65
+ }
66
+ for (const [label, path] of [['loadavg', '/proc/loadavg'], ['pressure_io', '/proc/pressure/io'], ['pressure_cpu', '/proc/pressure/cpu']] as const) {
67
+ try {
68
+ parts.push(`${label}=${JSON.stringify(oneLine((await readFile(path, 'utf8')).trim(), 200))}`)
69
+ } catch {
70
+ // absent (non-Linux, or no PSI): skip silently
71
+ }
72
+ }
73
+ return parts.join(' ')
74
+ }
75
+
76
+ async function backends(adminUrl: string, databases: string[]): Promise<string[]> {
77
+ const client = postgres(adminUrl, { max: 1, onnotice: () => {}, connect_timeout: 5 })
78
+ try {
79
+ const rows = await Promise.race([
80
+ client<BackendRow[]>`
81
+ SELECT datname, pid, state, wait_event_type, wait_event,
82
+ round(extract(epoch FROM (now() - state_change))::numeric, 1)::text AS state_s,
83
+ pg_blocking_pids(pid)::text AS blocked_by, query
84
+ FROM pg_stat_activity
85
+ WHERE datname = ANY(${databases}) AND pid <> pg_backend_pid()
86
+ ORDER BY datname, pid`,
87
+ new Promise<never>((_, reject) => {
88
+ setTimeout(() => reject(new Error('pg_stat_activity query timed out')), WATCH_QUERY_TIMEOUT_MS).unref()
89
+ }),
90
+ ])
91
+ if (rows.length === 0) return [`backends(${databases.join(',')})=none`]
92
+ return rows.map(r =>
93
+ `backend[db=${r.datname} pid=${String(r.pid)} state=${r.state ?? '-'} ` +
94
+ `wait=${r.wait_event_type ?? '-'}/${r.wait_event ?? '-'} in_state_s=${r.state_s ?? '-'} ` +
95
+ `blocked_by=${r.blocked_by ?? '{}'} query=${JSON.stringify(oneLine(r.query ?? '', QUERY_MAX_CHARS))}]`,
96
+ )
97
+ } finally {
98
+ void client.end({ timeout: 1 }).catch(() => {})
99
+ }
100
+ }
101
+
102
+ function oneLine(text: string, max: number): string {
103
+ const flat = text.replace(/\s+/g, ' ')
104
+ return flat.length > max ? `${flat.slice(0, max)}...` : flat
105
+ }
@@ -0,0 +1,146 @@
1
+ // The bounded serializer is the last safety net on trace input capture: it
2
+ // turns an arbitrary captured value into something JSON-safe, size-bounded, and
3
+ // redacted before it lands in `trace_step.captured_inputs`.
4
+ //
5
+ // "Safe" means it never throws and never blows up the trace row: depth, fan-out
6
+ // and string length are all capped, cycles are broken, and non-JSON primitives
7
+ // (bigint, NaN, Date, functions) are rendered to stable markers or strings.
8
+ // "Redacted" means it runs every key-path through the same redact matcher the
9
+ // logger uses, so a path censored in logs is censored in traces too.
10
+
11
+ import { compileRedactPaths, type RedactMatcher } from '../../core/logging/redact-match.js'
12
+ import { DEFAULT_REDACT_PATHS } from '../../core/logging/index.js'
13
+
14
+ export interface TraceSerializeOptions {
15
+ /** Nested objects/arrays deeper than this are replaced with a marker. */
16
+ readonly maxDepth?: number
17
+ /** Object keys / array items kept per level; the excess is summarized. */
18
+ readonly maxEntries?: number
19
+ /** Strings longer than this are truncated with a marker. */
20
+ readonly maxStringLength?: number
21
+ /** Key-path matcher; matching values are replaced with `[Redacted]`. */
22
+ readonly redact?: RedactMatcher
23
+ }
24
+
25
+ interface ResolvedOptions {
26
+ readonly maxDepth: number
27
+ readonly maxEntries: number
28
+ readonly maxStringLength: number
29
+ readonly redact: RedactMatcher
30
+ }
31
+
32
+ const DEFAULTS = {
33
+ maxDepth: 6,
34
+ maxEntries: 64,
35
+ maxStringLength: 1024,
36
+ redact: compileRedactPaths(DEFAULT_REDACT_PATHS),
37
+ } as const
38
+
39
+ /**
40
+ * Serialize a captured value into a JSON-safe, bounded, redacted form.
41
+ *
42
+ * The result contains only `null`, booleans, finite numbers, strings, plain
43
+ * objects and arrays — safe to write straight into a `jsonb` column. Anything
44
+ * that would break those guarantees is replaced with a `[…]` marker rather than
45
+ * dropped silently, so a reader can tell capture hit a bound.
46
+ */
47
+ export function serializeForTrace(value: unknown, options: TraceSerializeOptions = {}): unknown {
48
+ const resolved: ResolvedOptions = {
49
+ maxDepth: options.maxDepth ?? DEFAULTS.maxDepth,
50
+ maxEntries: options.maxEntries ?? DEFAULTS.maxEntries,
51
+ maxStringLength: options.maxStringLength ?? DEFAULTS.maxStringLength,
52
+ redact: options.redact ?? DEFAULTS.redact,
53
+ }
54
+ return walk(value, 0, [], new WeakSet<object>(), resolved)
55
+ }
56
+
57
+ function walk(
58
+ value: unknown,
59
+ depth: number,
60
+ keyPath: readonly string[],
61
+ seen: WeakSet<object>,
62
+ opts: ResolvedOptions,
63
+ ): unknown {
64
+ if (value === null) return null
65
+
66
+ switch (typeof value) {
67
+ case 'string':
68
+ return boundString(value, opts.maxStringLength)
69
+ case 'number':
70
+ return Number.isFinite(value) ? value : String(value)
71
+ case 'boolean':
72
+ return value
73
+ case 'bigint':
74
+ return value.toString()
75
+ case 'undefined':
76
+ return undefined
77
+ case 'function':
78
+ return '[Function]'
79
+ case 'symbol':
80
+ return value.toString()
81
+ }
82
+
83
+ if (value instanceof Date) return value.toISOString()
84
+
85
+ if (depth >= opts.maxDepth) return '[Pruned: max depth]'
86
+ if (seen.has(value)) return '[Circular]'
87
+ seen.add(value)
88
+ const result = Array.isArray(value)
89
+ ? walkArray(value, depth, keyPath, seen, opts)
90
+ : walkObject(value as Record<string, unknown>, depth, keyPath, seen, opts)
91
+ seen.delete(value)
92
+ return result
93
+ }
94
+
95
+ function walkArray(
96
+ value: readonly unknown[],
97
+ depth: number,
98
+ keyPath: readonly string[],
99
+ seen: WeakSet<object>,
100
+ opts: ResolvedOptions,
101
+ ): unknown[] {
102
+ const out: unknown[] = []
103
+ for (const item of value.slice(0, opts.maxEntries)) {
104
+ // Arrays are transparent to the redact key-path: an item carries its
105
+ // parent's path, not an index segment. This makes redaction match by
106
+ // object-key nesting and, where it differs from pino, errs toward
107
+ // redacting more — the safe direction for a capture net.
108
+ const serialized = walk(item, depth + 1, keyPath, seen, opts)
109
+ // JSON arrays cannot carry holes; an undefined slot becomes null.
110
+ out.push(serialized === undefined ? null : serialized)
111
+ }
112
+ if (value.length > opts.maxEntries) {
113
+ out.push(`[Pruned: ${value.length - opts.maxEntries} more items]`)
114
+ }
115
+ return out
116
+ }
117
+
118
+ function walkObject(
119
+ value: Record<string, unknown>,
120
+ depth: number,
121
+ keyPath: readonly string[],
122
+ seen: WeakSet<object>,
123
+ opts: ResolvedOptions,
124
+ ): Record<string, unknown> {
125
+ const out: Record<string, unknown> = {}
126
+ const entries = Object.entries(value)
127
+ for (const [key, raw] of entries.slice(0, opts.maxEntries)) {
128
+ const path = [...keyPath, key]
129
+ if (opts.redact(path)) {
130
+ out[key] = '[Redacted]'
131
+ continue
132
+ }
133
+ const serialized = walk(raw, depth + 1, path, seen, opts)
134
+ // An undefined property is absent in JSON; drop it rather than emit a hole.
135
+ if (serialized !== undefined) out[key] = serialized
136
+ }
137
+ if (entries.length > opts.maxEntries) {
138
+ out['[Pruned]'] = `${entries.length - opts.maxEntries} more keys`
139
+ }
140
+ return out
141
+ }
142
+
143
+ function boundString(value: string, max: number): string {
144
+ if (value.length <= max) return value
145
+ return `${value.slice(0, max)}[Truncated: ${value.length - max} chars]`
146
+ }