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,116 @@
1
+ import postgres from 'postgres'
2
+ import { getLogger } from '../../core/logging/logger.js'
3
+ import { currentQueryLabel } from './query-label.js'
4
+ import type { StatementWatch } from '../query/postgres-js/session.js'
5
+
6
+ const LABEL_SQL_CHARS = 120
7
+ const SAMPLE_TIMEOUT_MS = 2_000
8
+ const PG_TRUNCATED_QUERY_LENGTH = 1_000
9
+
10
+ interface BackendSample {
11
+ pid: number | null
12
+ state: string | null
13
+ waitEventType: string | null
14
+ waitEvent: string | null
15
+ }
16
+
17
+ const UNKNOWN_BACKEND: BackendSample = { pid: null, state: null, waitEventType: null, waitEvent: null }
18
+
19
+ /** What a pool's watch needs: where it logs, how slow is slow, and how to reach the server for a wait-event sample. */
20
+ export interface StatementWatchOptions {
21
+ readonly database: string
22
+ readonly url: string
23
+ readonly slowQueryMs: number
24
+ /** Undefined: no timer is ever created. */
25
+ readonly inFlightQueryMs: number | undefined
26
+ }
27
+
28
+ export interface StatementWatchHandle {
29
+ readonly watch: StatementWatch
30
+ close(): Promise<void>
31
+ }
32
+
33
+ function labelFor(sqlText: string): string {
34
+ return currentQueryLabel() ?? sqlText.replace(/\s+/g, ' ').trim().slice(0, LABEL_SQL_CHARS)
35
+ }
36
+
37
+ /**
38
+ * Wraps each statement of one database's pool: a `query:slow` warning when it settles past
39
+ * `slowQueryMs`, and, when `inFlightQueryMs` is set, a `query:in-flight` warning at every
40
+ * multiple of it while the statement is still outstanding. Backend details are read over a
41
+ * dedicated connection, never the statement's own and never the app pool.
42
+ */
43
+ export function createStatementWatch(options: StatementWatchOptions): StatementWatchHandle {
44
+ const { database, url, slowQueryMs, inFlightQueryMs } = options
45
+ let sampler: postgres.Sql | undefined
46
+ let sampling = false
47
+ let closed = false
48
+
49
+ function sampleBackend(sqlText: string, startedMs: number): Promise<BackendSample> {
50
+ if (sampling || closed) return Promise.resolve(UNKNOWN_BACKEND)
51
+ sampling = true
52
+ sampler ??= postgres(url, { max: 1, idle_timeout: 3, onnotice: () => {}, connect_timeout: 5 })
53
+ const client = sampler
54
+ const run = client.unsafe<Array<{ pid: number; state: string | null; wait_event_type: string | null; wait_event: string | null }>>(
55
+ `SELECT pid, state, wait_event_type, wait_event FROM pg_stat_activity
56
+ WHERE datname = current_database() AND pid <> pg_backend_pid() AND state <> 'idle'
57
+ AND (query = $1 OR (length(query) >= ${String(PG_TRUNCATED_QUERY_LENGTH)} AND left($1, length(query)) = query))
58
+ ORDER BY abs(extract(epoch FROM query_start) - $2::float8) LIMIT 1`,
59
+ [sqlText, startedMs / 1000],
60
+ ).then(rows => {
61
+ const row = rows[0]
62
+ return row === undefined
63
+ ? UNKNOWN_BACKEND
64
+ : { pid: row.pid, state: row.state, waitEventType: row.wait_event_type, waitEvent: row.wait_event }
65
+ })
66
+ void run.then(() => { sampling = false }, () => { sampling = false })
67
+ let timer: NodeJS.Timeout | undefined
68
+ const timeout = new Promise<BackendSample>(resolve => {
69
+ timer = setTimeout(() => { resolve(UNKNOWN_BACKEND) }, SAMPLE_TIMEOUT_MS)
70
+ timer.unref()
71
+ })
72
+ return Promise.race([run, timeout]).catch(() => UNKNOWN_BACKEND).finally(() => { clearTimeout(timer) })
73
+ }
74
+
75
+ const watch: StatementWatch = async <T>(sqlText: string, run: () => Promise<T>): Promise<T> => {
76
+ const startedMs = Date.now()
77
+ let interval: NodeJS.Timeout | undefined
78
+ let settled = false
79
+ if (inFlightQueryMs !== undefined) {
80
+ const log = getLogger()
81
+ const label = labelFor(sqlText)
82
+ interval = setInterval(() => {
83
+ const elapsedS = Math.round((Date.now() - startedMs) / 100) / 10
84
+ void sampleBackend(sqlText, startedMs).then(backend => {
85
+ if (settled) return
86
+ log.warn({
87
+ label, elapsedS, database,
88
+ pid: backend.pid, state: backend.state,
89
+ waitEventType: backend.waitEventType, waitEvent: backend.waitEvent,
90
+ }, 'query:in-flight')
91
+ })
92
+ }, inFlightQueryMs)
93
+ interval.unref()
94
+ }
95
+ try {
96
+ return await run()
97
+ } finally {
98
+ settled = true
99
+ if (interval !== undefined) clearInterval(interval)
100
+ const durationMs = Date.now() - startedMs
101
+ if (slowQueryMs > 0 && durationMs > slowQueryMs) {
102
+ getLogger().warn({ label: labelFor(sqlText), durationMs, database }, 'query:slow')
103
+ }
104
+ }
105
+ }
106
+
107
+ return {
108
+ watch,
109
+ async close() {
110
+ closed = true
111
+ const client = sampler
112
+ sampler = undefined
113
+ if (client) await client.end({ timeout: 1 }).catch(() => {})
114
+ },
115
+ }
116
+ }
@@ -0,0 +1,37 @@
1
+ import { getBaseLogger } from '../../core/logging/logger.js'
2
+
3
+ const warned = new Set<string>()
4
+
5
+ /**
6
+ * Announces the one place a statement observer does not carry its
7
+ * error-sanitization guarantee.
8
+ *
9
+ * `ManagedConnection.client` is the sanctioned raw-driver door, and it stays
10
+ * raw on purpose — queries issued through it bypass the driver error boundary,
11
+ * so on an observed connection their errors serialize the bind parameters
12
+ * postgres.js attached. Everything reached through `.drizzle` (which is every
13
+ * `pipe()` call, every `pipe.*` write, every transaction and savepoint) is
14
+ * inside the boundary and unaffected.
15
+ *
16
+ * Warns once per database name: this is a design fact about the code holding
17
+ * the connection, not a per-query event, and repeating it would train people to
18
+ * filter it out.
19
+ */
20
+ export function warnRawClientIsUnsanitized(database: string): void {
21
+ if (warned.has(database)) return
22
+ warned.add(database)
23
+
24
+ getBaseLogger().warn(
25
+ { database },
26
+ '[pipework] raw .client read on a connection with observability.onStatement configured. ' +
27
+ 'Queries issued through .client bypass pipework\'s driver error boundary, so their errors ' +
28
+ 'serialize bind parameters (postgres.js marks query/parameters/args enumerable whenever its ' +
29
+ 'debug hook is installed). Use connection.drizzle — or pipe() inside a managed context — to ' +
30
+ 'stay inside the boundary. This warning is logged once per database.',
31
+ )
32
+ }
33
+
34
+ /** Test seam: forget which databases have already warned. */
35
+ export function _resetRawClientWarnings(): void {
36
+ warned.clear()
37
+ }
@@ -0,0 +1,23 @@
1
+ import type { Column } from '../query/column.js'
2
+ import type { Placeholder, SQL } from '../query/sql/sql.js'
3
+
4
+ /**
5
+ * A value type widened to also accept the readonly form of every tuple, array
6
+ * and plain object inside it, for parameters that are read and never changed.
7
+ * Dates, SQL, placeholders, columns, functions, maps, sets, regular expressions,
8
+ * typed arrays and primitives pass through; unions distribute.
9
+ *
10
+ * The result is the original type or its widened form, so anything the plain
11
+ * type accepted is still accepted (including a value typed by an unresolved
12
+ * generic such as `T['$inferInsert']`). The widening stops after a fixed number
13
+ * of levels, so wide nested json columns cannot exhaust instantiation depth.
14
+ */
15
+ export type AcceptReadonly<V> = V | Widen<V, []>
16
+
17
+ type Widen<V, D extends unknown[]> =
18
+ unknown extends V ? V
19
+ : D['length'] extends 4 ? V
20
+ : V extends Date | SQL | Placeholder | Column | Map<unknown, unknown> | Set<unknown> | RegExp | ArrayBufferView | ((...args: never[]) => unknown) ? V
21
+ : V extends readonly unknown[] ? Readonly<{ [I in keyof V]: Widen<V[I], [...D, unknown]> }>
22
+ : V extends object ? { [K in keyof V]: Widen<V[K], [...D, unknown]> }
23
+ : V
@@ -0,0 +1,151 @@
1
+ import { randomUUID } from 'node:crypto'
2
+ import postgres from 'postgres'
3
+ import { getBaseLogger } from '../../core/logging/index.js'
4
+
5
+ /**
6
+ * What this process has reserved on each Postgres server, published to the
7
+ * server itself: one presence connection per server whose `application_name`
8
+ * is `pipework:<id>:<reservation>`, plus pool connections tagged
9
+ * `pipework:<id>`. The session is the liveness signal: a dead process's
10
+ * presence row leaves pg_stat_activity with its connection.
11
+ */
12
+ export interface ReservationPublisher {
13
+ readonly id: string
14
+ /** application_name for a publishing pool's connections. */
15
+ readonly poolTag: string
16
+ /** Adds `max` to the reservation on the URL's server; the returned function subtracts it (once). */
17
+ reserve(url: string, max: number): () => void
18
+ /** Settles when every publication started so far has landed. */
19
+ settled(): Promise<void>
20
+ /** Ends every presence connection. */
21
+ closeAll(): Promise<void>
22
+ }
23
+
24
+ interface ServerEntry {
25
+ url: string
26
+ reservation: number
27
+ client: postgres.Sql | undefined
28
+ chain: Promise<void>
29
+ }
30
+
31
+ export function serverKey(url: string): string {
32
+ const parsed = new URL(url)
33
+ return `${parsed.hostname}:${parsed.port === '' ? '5432' : parsed.port}`
34
+ }
35
+
36
+ export function createReservationPublisher(): ReservationPublisher {
37
+ const id = randomUUID()
38
+ const servers = new Map<string, ServerEntry>()
39
+ const name = (reservation: number): string => `pipework:${id}:${String(reservation)}`
40
+
41
+ const publish = (entry: ServerEntry): void => {
42
+ entry.chain = entry.chain.then(async () => {
43
+ try {
44
+ if (entry.reservation <= 0) {
45
+ const client = entry.client
46
+ entry.client = undefined
47
+ if (client) await client.end({ timeout: 5 })
48
+ return
49
+ }
50
+ const value = name(entry.reservation)
51
+ if (!entry.client) {
52
+ entry.client = postgres(entry.url, {
53
+ max: 1,
54
+ idle_timeout: 0,
55
+ onnotice: () => {},
56
+ connection: { application_name: value },
57
+ })
58
+ }
59
+ // A reconnect re-sends the startup packet; keep it current.
60
+ entry.client.options.connection['application_name'] = value
61
+ await entry.client.unsafe('SELECT set_config(\'application_name\', $1, false)', [value])
62
+ } catch (err) {
63
+ getBaseLogger().warn({ err }, 'Could not publish the connection reservation')
64
+ }
65
+ })
66
+ }
67
+
68
+ return {
69
+ id,
70
+ poolTag: `pipework:${id}`,
71
+ reserve(url, max) {
72
+ const key = serverKey(url)
73
+ let entry = servers.get(key)
74
+ if (!entry) {
75
+ entry = { url, reservation: 0, client: undefined, chain: Promise.resolve() }
76
+ servers.set(key, entry)
77
+ }
78
+ const target = entry
79
+ target.reservation += max
80
+ publish(target)
81
+ let released = false
82
+ return () => {
83
+ if (released) return
84
+ released = true
85
+ target.reservation -= max
86
+ publish(target)
87
+ }
88
+ },
89
+ async settled() {
90
+ await Promise.all([...servers.values()].map(e => e.chain))
91
+ },
92
+ async closeAll() {
93
+ for (const entry of servers.values()) {
94
+ entry.reservation = 0
95
+ publish(entry)
96
+ }
97
+ await this.settled()
98
+ },
99
+ }
100
+ }
101
+
102
+ export interface ConnectionBudget {
103
+ /** The server's `max_connections`. */
104
+ readonly maxConnections: number
105
+ /** `superuser_reserved_connections` plus `reserved_connections` (PG16+; 0 before). */
106
+ readonly reserved: number
107
+ /** Client backends open now, across the whole server, plus other roles' background workers that the reading role cannot tell apart. */
108
+ readonly held: number
109
+ /** For every other live publishing pipework process on this server: its reservation minus the connections it holds (never below 0), summed. */
110
+ readonly othersUnopened: number
111
+ /** `maxConnections - reserved - held - othersUnopened`. */
112
+ readonly free: number
113
+ }
114
+
115
+ const PRESENCE = /^pipework:([0-9a-f-]{36}):(\d+)$/
116
+ const POOL_TAG = /^pipework:([0-9a-f-]{36})$/
117
+
118
+ export const BUDGET_QUERY = `
119
+ SELECT current_setting('max_connections')::int AS max_connections,
120
+ current_setting('superuser_reserved_connections')::int + coalesce(current_setting('reserved_connections', true)::int, 0) AS reserved,
121
+ (SELECT count(*)::int FROM pg_stat_activity WHERE datid IS NOT NULL AND (backend_type = 'client backend' OR backend_type IS NULL)) AS held,
122
+ coalesce((SELECT array_agg(application_name::text) FROM pg_stat_activity WHERE application_name LIKE 'pipework:%'), '{}') AS names`
123
+
124
+ export function computeBudget(
125
+ row: { max_connections: number; reserved: number; held: number; names: readonly string[] },
126
+ ownId: string,
127
+ ): ConnectionBudget {
128
+ const reservation = new Map<string, number>()
129
+ const holding = new Map<string, number>()
130
+ for (const n of row.names) {
131
+ const presence = PRESENCE.exec(n)
132
+ if (presence) {
133
+ reservation.set(presence[1]!, Number(presence[2]))
134
+ continue
135
+ }
136
+ const pool = POOL_TAG.exec(n)
137
+ if (pool) holding.set(pool[1]!, (holding.get(pool[1]!) ?? 0) + 1)
138
+ }
139
+ let othersUnopened = 0
140
+ for (const [pid, reserved] of reservation) {
141
+ if (pid === ownId) continue
142
+ othersUnopened += Math.max(0, reserved - (holding.get(pid) ?? 0))
143
+ }
144
+ return {
145
+ maxConnections: row.max_connections,
146
+ reserved: row.reserved,
147
+ held: row.held,
148
+ othersUnopened,
149
+ free: row.max_connections - row.reserved - row.held - othersUnopened,
150
+ }
151
+ }
@@ -0,0 +1,14 @@
1
+ // Schema-level features — manual layer (wrappable)
2
+ // e.g., `table` could auto-inject tenant_id columns for tenant-scoped tables.
3
+
4
+ export {
5
+ pgTable as table,
6
+ pgView as view,
7
+ pgMaterializedView as materializedView,
8
+ pgSchema,
9
+ pgSequence as sequence,
10
+ pgPolicy as policy,
11
+ pgRole as role,
12
+ pgTableCreator as tableCreator,
13
+ withReplicas,
14
+ } from '../query/pg-core/index.js'
@@ -0,0 +1,83 @@
1
+ import type { DB } from './types.js'
2
+
3
+ /** Retry policy for {@link serializable}: how many attempts on a serialization failure / deadlock, and the base backoff between them. */
4
+ export interface SerializableOptions {
5
+ readonly maxAttempts?: number
6
+ readonly backoffMs?: number
7
+ }
8
+
9
+ const PG_SERIALIZATION_FAILURE = '40001'
10
+ const PG_DEADLOCK_DETECTED = '40P01'
11
+ const PG_SET_TRANSACTION_AFTER_QUERY = '25001'
12
+
13
+ /** The Postgres SQLSTATE carried by an error (or by its cause), or undefined for a non-Postgres error. */
14
+ export function pgErrorCode(err: unknown): unknown {
15
+ if (typeof err !== 'object' || err === null) return undefined
16
+ if ('code' in err) return (err as { code: unknown }).code
17
+ if ('cause' in err) return pgErrorCode((err as { cause: unknown }).cause)
18
+ return undefined
19
+ }
20
+
21
+ /** True for Postgres serialization failures (40001) and deadlocks (40P01) — errors a retry can resolve. */
22
+ export function isTransientConcurrencyError(err: unknown): boolean {
23
+ const code = pgErrorCode(err)
24
+ return code === PG_SERIALIZATION_FAILURE || code === PG_DEADLOCK_DETECTED
25
+ }
26
+
27
+ // Only a postgres.js transaction client exposes savepoint(), so its presence
28
+ // on the session's client means this db already sits inside an open
29
+ // transaction — a drizzle transaction object included.
30
+ function insideTransaction(db: unknown): boolean {
31
+ const session = (db as { session?: { client?: { savepoint?: unknown } } }).session
32
+ return typeof session?.client?.savepoint === 'function'
33
+ }
34
+
35
+ function nestedSerializableError(cause?: unknown): Error {
36
+ return new Error(
37
+ '[pipework] serializable() cannot run inside an open transaction.\n\n' +
38
+ ' Postgres refuses to raise the isolation level of a transaction that has\n' +
39
+ ' already run a query (25001), and a nested transaction is a savepoint that\n' +
40
+ ' inherits the outer, weaker level. Open the SERIALIZABLE transaction at the\n' +
41
+ ' outermost level instead of inside another one.\n',
42
+ cause !== undefined ? { cause } : undefined,
43
+ )
44
+ }
45
+
46
+ /** Runs `fn` in a SERIALIZABLE transaction, retrying on serialization failures (40001) and deadlocks (40P01) with exponential backoff. */
47
+ export async function serializable<T>(
48
+ db: DB,
49
+ fn: (tx: DB) => Promise<T>,
50
+ options?: SerializableOptions,
51
+ ): Promise<T> {
52
+ const maxAttempts = options?.maxAttempts ?? 3
53
+ const backoffMs = options?.backoffMs ?? 50
54
+
55
+ if (maxAttempts < 1) {
56
+ throw new Error(
57
+ '[pipework] serializable() requires maxAttempts >= 1.\n\n' +
58
+ ' pipe.serializable(db, fn) — default 3 attempts\n' +
59
+ ' pipe.serializable(db, fn, { maxAttempts: 5 }) — custom attempts\n',
60
+ )
61
+ }
62
+
63
+ if (insideTransaction(db)) throw nestedSerializableError()
64
+
65
+ let lastError: unknown
66
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
67
+ if (attempt > 0) {
68
+ await new Promise<void>(resolve => setTimeout(resolve, backoffMs * 2 ** (attempt - 1)))
69
+ }
70
+ try {
71
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- drizzle's transaction generic requires concrete schema types; the DB alias erases them
72
+ return await (db as any).transaction(fn, { isolationLevel: 'serializable' })
73
+ } catch (err) {
74
+ if (pgErrorCode(err) === PG_SET_TRANSACTION_AFTER_QUERY) throw nestedSerializableError(err)
75
+ if (isTransientConcurrencyError(err) && attempt < maxAttempts - 1) {
76
+ lastError = err
77
+ continue
78
+ }
79
+ throw err
80
+ }
81
+ }
82
+ throw lastError
83
+ }
@@ -0,0 +1 @@
1
+ export { sql } from '../query/index.js'
@@ -0,0 +1,76 @@
1
+ import { sql } from './sql.js'
2
+ import { pgErrorCode } from './serializable.js'
3
+ import type { DB } from './types.js'
4
+ import { unscopedExecutor } from '../../auth/tenant/scoped-db.js'
5
+
6
+ const PG_QUERY_CANCELED = '57014'
7
+ const PG_LOCK_NOT_AVAILABLE = '55P03'
8
+
9
+ /** Which timeouts {@link withTimeouts} sets; each a positive integer number of milliseconds. */
10
+ export interface TimeoutOptions {
11
+ readonly statementTimeoutMs?: number
12
+ readonly lockTimeoutMs?: number
13
+ }
14
+
15
+ /** A statement was cancelled by Postgres for running past the statement timeout a {@link withTimeouts} call set. `cause` is the driver error. */
16
+ export class StatementTimeoutError extends Error {
17
+ constructor(readonly statementTimeoutMs: number, cause: unknown) {
18
+ super(`[pipework] a statement ran past the ${statementTimeoutMs} ms statement timeout set by withTimeouts`, { cause })
19
+ this.name = 'StatementTimeoutError'
20
+ }
21
+ }
22
+
23
+ /** A statement gave up waiting for a lock past the lock timeout a {@link withTimeouts} call set. `cause` is the driver error. */
24
+ export class LockTimeoutError extends Error {
25
+ constructor(readonly lockTimeoutMs: number, cause: unknown) {
26
+ super(`[pipework] a statement waited past the ${lockTimeoutMs} ms lock timeout set by withTimeouts`, { cause })
27
+ this.name = 'LockTimeoutError'
28
+ }
29
+ }
30
+
31
+ function positiveInteger(name: string, value: number | undefined): void {
32
+ if (value === undefined) return
33
+ if (!Number.isSafeInteger(value) || value <= 0) {
34
+ throw new Error(
35
+ `[pipework] withTimeouts: ${name} must be a positive integer number of milliseconds, got ${String(value)}.\n\n` +
36
+ ' Fix: pipe.withTimeouts(db, { statementTimeoutMs: 5000, lockTimeoutMs: 1000 }, fn)\n',
37
+ )
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Sets `statement_timeout` and/or `lock_timeout` for the current transaction in one statement, then runs `fn`.
43
+ * `db` is the transaction-bound DB the caller already has (`pipe(name)` inside a flow, or a `tx`).
44
+ *
45
+ * The settings hold until the transaction ends, as `SET LOCAL` does; nothing is restored after `fn`, so statements
46
+ * after it in the same transaction keep the timeouts. Outside a transaction `set_config(..., true)` has no
47
+ * effect, so call this only inside one.
48
+ *
49
+ * A statement Postgres cancels for a timeout this call set rejects with {@link StatementTimeoutError} (SQLSTATE 57014)
50
+ * or {@link LockTimeoutError} (55P03), the driver error as `cause`. Any other error passes through unchanged.
51
+ */
52
+ export async function withTimeouts<T>(db: DB, options: TimeoutOptions, fn: () => Promise<T>): Promise<T> {
53
+ const { statementTimeoutMs, lockTimeoutMs } = options
54
+ if (statementTimeoutMs === undefined && lockTimeoutMs === undefined) {
55
+ throw new Error(
56
+ '[pipework] withTimeouts: give statementTimeoutMs, lockTimeoutMs, or both.\n\n' +
57
+ ' Fix: pipe.withTimeouts(db, { statementTimeoutMs: 5000 }, fn)\n',
58
+ )
59
+ }
60
+ positiveInteger('statementTimeoutMs', statementTimeoutMs)
61
+ positiveInteger('lockTimeoutMs', lockTimeoutMs)
62
+
63
+ const settings = []
64
+ if (statementTimeoutMs !== undefined) settings.push(sql`set_config('statement_timeout', ${`${statementTimeoutMs}ms`}, true)`)
65
+ if (lockTimeoutMs !== undefined) settings.push(sql`set_config('lock_timeout', ${`${lockTimeoutMs}ms`}, true)`)
66
+ await unscopedExecutor(db).db.execute(sql`SELECT ${sql.join(settings, sql`, `)}`)
67
+
68
+ try {
69
+ return await fn()
70
+ } catch (err) {
71
+ const code = pgErrorCode(err)
72
+ if (code === PG_QUERY_CANCELED && statementTimeoutMs !== undefined) throw new StatementTimeoutError(statementTimeoutMs, err)
73
+ if (code === PG_LOCK_NOT_AVAILABLE && lockTimeoutMs !== undefined) throw new LockTimeoutError(lockTimeoutMs, err)
74
+ throw err
75
+ }
76
+ }
@@ -0,0 +1,18 @@
1
+ import type { SQL as _SQL } from '../query/index.js'
2
+ import type { PgTable, PgColumn } from '../query/pg-core/index.js'
3
+
4
+ /** Drizzle database instance — use pipe() to get one inside a managed context. */
5
+ export type { PostgresJsDatabase as DB } from '../query/postgres-js/index.js'
6
+ /** SQL expression type — created by pipe.sql template tag or query operators. */
7
+ export type SQL<T = unknown> = _SQL<T>
8
+ /** Drizzle table definition type — created by schema.table(). */
9
+ export type Table = PgTable
10
+ /** Drizzle column type — created by schema.col.* builders. */
11
+ export type Column = PgColumn
12
+
13
+ /** Options for pipe.transaction(). Nested transactions (savepoints) inherit the outer transaction's isolation level — isolationLevel is silently dropped when nested. */
14
+ export interface TransactionConfig {
15
+ isolationLevel?: 'read uncommitted' | 'read committed' | 'repeatable read' | 'serializable'
16
+ accessMode?: 'read only' | 'read write'
17
+ deferrable?: boolean
18
+ }
@@ -0,0 +1,33 @@
1
+ import type { DB } from './index.js'
2
+ import type { Flow } from '../../request/context/types.js'
3
+ import type { ResolvedDatabase } from '../../core/config/load.js'
4
+
5
+ /**
6
+ * The database handle for a Flow with no bound transaction on `dbName`: the
7
+ * pooled connection.
8
+ *
9
+ * On a platform-mode database that connection is the platform role, which sees
10
+ * no tenant row until the tenant setting is set, and the setting can only be
11
+ * set for a transaction. A builder from `pipe()` runs lazily on the handle it
12
+ * was built from, with nothing wrapping the statement, so there is no per-statement
13
+ * place to set it (src/data/query/postgres-js/session.ts sends each statement on
14
+ * the pool client). A Flow with a tenant is therefore refused here, naming the fix;
15
+ * a Flow with no tenant gets the connection as is and tenant tables return nothing.
16
+ * Under a test connection override the test's own connection is used.
17
+ */
18
+ export function unboundDb(ctx: Flow, dbName: string, dbConfig: ResolvedDatabase, caller: string): DB {
19
+ if (
20
+ dbConfig.rls?.platformRole !== undefined
21
+ && ctx.tenant !== null
22
+ && !ctx.instance.pool.isOverridden(dbName)
23
+ ) {
24
+ throw new Error(
25
+ `[pipework] ${caller} has no transaction bound for database "${dbName}", and this Flow has a tenant.\n\n` +
26
+ ` "${dbName}" is in platform mode (rls.platformRole): its pooled connection is the platform role, which\n` +
27
+ ' sees no tenant row, and the tenant setting can only be set per transaction.\n' +
28
+ ' Fix: run the code in a request or job (each binds a tenant-scoped transaction), or wrap it in\n' +
29
+ ' pipe.transaction(async (tx) => { ... }).\n',
30
+ )
31
+ }
32
+ return ctx.instance.pool.getOrCreate(dbConfig).drizzle
33
+ }
@@ -0,0 +1,29 @@
1
+ import { sql } from './sql.js'
2
+ import type { SQL } from './types.js'
3
+
4
+ type PgCastType = 'uuid' | 'text' | 'integer' | 'bigint' | 'boolean' | 'jsonb' | 'timestamptz' | 'timestamp' | 'date' | 'numeric' | 'real' | 'double precision' | 'smallint' | 'interval'
5
+
6
+ /** One column of a typed `VALUES` clause: its name and the PostgreSQL type each value in that column is cast to. See {@link values}. */
7
+ export interface ValueColumnDef {
8
+ readonly name: string
9
+ readonly type: PgCastType
10
+ }
11
+
12
+ /** Produces a typed VALUES clause: `(VALUES ($1::uuid, $2::text), ($3::uuid, $4::text))`. Each value is cast to its declared type. JSONB values are JSON-stringified and Dates sent as ISO text, as a column does on insert; null is SQL NULL. */
13
+ export function values(rows: ReadonlyArray<readonly unknown[]>, columns: readonly ValueColumnDef[]): SQL {
14
+ if (rows.length === 0) throw new Error('[pipework] values() requires at least one row')
15
+ if (columns.length === 0) throw new Error('[pipework] values() requires at least one column definition')
16
+
17
+ const valueRows: SQL[] = rows.map(row => {
18
+ const cells = columns.map((col, i) => {
19
+ const val = row[i]
20
+ if (val === null || val === undefined) return sql`${null}::${sql.raw(col.type)}`
21
+ if (col.type === 'jsonb') return sql`${JSON.stringify(val)}::jsonb`
22
+ const bound = val instanceof Date ? val.toISOString() : val
23
+ return sql`${bound as string | number | boolean | bigint}::${sql.raw(col.type)}`
24
+ })
25
+ return sql`(${sql.join(cells, sql`, `)})`
26
+ })
27
+
28
+ return sql`(VALUES ${sql.join(valueRows, sql`, `)})`
29
+ }
@@ -0,0 +1,15 @@
1
+ declare const __brand: unique symbol
2
+
3
+ /** Phantom brand marker — attaches a nominal tag to a base type. */
4
+ export type Brand<B extends string> = { readonly [__brand]: B }
5
+
6
+ /** Nominal type — `Branded<string, 'UserId'>` is not assignable to `Branded<string, 'PostId'>`. */
7
+ export type Branded<T, B extends string> = T & Brand<B>
8
+
9
+ /** Extracts the phantom output type from a FieldDescriptor. */
10
+ export type InferFieldOutput<F> = F extends { readonly _output?: infer O } ? O : unknown
11
+
12
+ /** Projects field output types into a readonly record — used for DomainDefinition.Select. */
13
+ export type InferSelect<T extends Record<string, { readonly _output?: unknown }>> = {
14
+ readonly [K in keyof T]: InferFieldOutput<T[K]>
15
+ }