pipework 0.251.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 (730) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/core/config/load.d.ts +2 -0
  3. package/dist/core/config/load.d.ts.map +1 -1
  4. package/dist/core/config/load.js +1 -0
  5. package/dist/core/config/load.js.map +1 -1
  6. package/dist/core/config/namespace.d.ts +1 -0
  7. package/dist/core/config/namespace.d.ts.map +1 -1
  8. package/dist/core/config/schema.d.ts +2 -0
  9. package/dist/core/config/schema.d.ts.map +1 -1
  10. package/dist/core/config/schema.js +1 -0
  11. package/dist/core/config/schema.js.map +1 -1
  12. package/dist/core/surface/types.d.ts +1 -0
  13. package/dist/core/surface/types.d.ts.map +1 -1
  14. package/dist/data/db/namespace.d.ts +3 -0
  15. package/dist/data/db/namespace.d.ts.map +1 -1
  16. package/dist/data/db/namespace.js +3 -0
  17. package/dist/data/db/namespace.js.map +1 -1
  18. package/dist/data/db/pool.d.ts.map +1 -1
  19. package/dist/data/db/pool.js +6 -1
  20. package/dist/data/db/pool.js.map +1 -1
  21. package/dist/data/db/query-label.d.ts +5 -0
  22. package/dist/data/db/query-label.d.ts.map +1 -0
  23. package/dist/data/db/query-label.js +11 -0
  24. package/dist/data/db/query-label.js.map +1 -0
  25. package/dist/data/db/query-watch.d.ts +21 -0
  26. package/dist/data/db/query-watch.d.ts.map +1 -0
  27. package/dist/data/db/query-watch.js +90 -0
  28. package/dist/data/db/query-watch.js.map +1 -0
  29. package/dist/data/query/postgres-js/driver.js +1 -1
  30. package/dist/data/query/postgres-js/driver.js.map +1 -1
  31. package/dist/data/query/postgres-js/session.d.ts +5 -1
  32. package/dist/data/query/postgres-js/session.d.ts.map +1 -1
  33. package/dist/data/query/postgres-js/session.js +16 -11
  34. package/dist/data/query/postgres-js/session.js.map +1 -1
  35. package/dist/data/query/utils.d.ts +2 -0
  36. package/dist/data/query/utils.d.ts.map +1 -1
  37. package/dist/data/query/utils.js.map +1 -1
  38. package/dist/infra/credits/schema.d.ts +1 -1
  39. package/dist/test/plugin.d.ts.map +1 -1
  40. package/dist/test/plugin.js +10 -4
  41. package/dist/test/plugin.js.map +1 -1
  42. package/package.json +4 -3
  43. package/src/async/jobs/abortable-delay.ts +18 -0
  44. package/src/async/jobs/claims.ts +52 -0
  45. package/src/async/jobs/cron.ts +179 -0
  46. package/src/async/jobs/errors.ts +56 -0
  47. package/src/async/jobs/exclusion.ts +117 -0
  48. package/src/async/jobs/execute.ts +219 -0
  49. package/src/async/jobs/index.ts +10 -0
  50. package/src/async/jobs/listener.ts +135 -0
  51. package/src/async/jobs/namespace.ts +20 -0
  52. package/src/async/jobs/queue-door.ts +44 -0
  53. package/src/async/jobs/queue.ts +1012 -0
  54. package/src/async/jobs/run-script.ts +67 -0
  55. package/src/async/jobs/scheduler.ts +218 -0
  56. package/src/async/jobs/schedules-table.ts +37 -0
  57. package/src/async/jobs/serialize-error.ts +48 -0
  58. package/src/async/jobs/table.ts +191 -0
  59. package/src/async/pipeline/define.ts +53 -0
  60. package/src/async/pipeline/errors.ts +35 -0
  61. package/src/async/pipeline/execute.ts +53 -0
  62. package/src/async/pipeline/index.ts +13 -0
  63. package/src/async/pipeline/namespace.ts +12 -0
  64. package/src/async/pipeline/resume.ts +67 -0
  65. package/src/async/pipeline/run-steps.ts +98 -0
  66. package/src/async/pipeline/types.ts +57 -0
  67. package/src/async/state-machine/define.ts +64 -0
  68. package/src/async/state-machine/errors.ts +29 -0
  69. package/src/async/state-machine/index.ts +3 -0
  70. package/src/async/state-machine/namespace.ts +12 -0
  71. package/src/async/state-machine/transition.ts +90 -0
  72. package/src/async/state-machine/types.ts +37 -0
  73. package/src/async/steps/errors.ts +31 -0
  74. package/src/async/steps/graph.ts +1214 -0
  75. package/src/async/steps/hash.ts +40 -0
  76. package/src/async/steps/index.ts +7 -0
  77. package/src/async/steps/namespace.ts +7 -0
  78. package/src/async/steps/table.ts +97 -0
  79. package/src/async/steps/types.ts +318 -0
  80. package/src/audit/chain/index.ts +9 -0
  81. package/src/audit/chain/install.ts +113 -0
  82. package/src/audit/chain/retire.ts +52 -0
  83. package/src/audit/chain/verify.ts +257 -0
  84. package/src/audit/query/cursor.ts +37 -0
  85. package/src/audit/query/index.ts +9 -0
  86. package/src/audit/query/query.ts +223 -0
  87. package/src/audit/schema/audit-record-fields.ts +68 -0
  88. package/src/audit/schema/audit-record.ts +23 -0
  89. package/src/auth/auth/audit.ts +31 -0
  90. package/src/auth/auth/chain.ts +84 -0
  91. package/src/auth/auth/cookie.ts +136 -0
  92. package/src/auth/auth/email-links.ts +311 -0
  93. package/src/auth/auth/guard.ts +128 -0
  94. package/src/auth/auth/index.ts +18 -0
  95. package/src/auth/auth/multi-org.ts +337 -0
  96. package/src/auth/auth/namespace.ts +34 -0
  97. package/src/auth/auth/parse-expiry.ts +13 -0
  98. package/src/auth/auth/passwords.ts +110 -0
  99. package/src/auth/auth/schema.ts +110 -0
  100. package/src/auth/auth/sessions.ts +565 -0
  101. package/src/auth/auth/sign-in.ts +156 -0
  102. package/src/auth/auth/signing-keys.ts +69 -0
  103. package/src/auth/auth/types.ts +26 -0
  104. package/src/auth/auth/uuid.ts +10 -0
  105. package/src/auth/rbac/cache.ts +55 -0
  106. package/src/auth/rbac/check.ts +30 -0
  107. package/src/auth/rbac/create.ts +35 -0
  108. package/src/auth/rbac/index.ts +5 -0
  109. package/src/auth/rbac/middleware.ts +20 -0
  110. package/src/auth/rbac/namespace.ts +15 -0
  111. package/src/auth/rbac/resolve.ts +31 -0
  112. package/src/auth/rbac/schema.sql +31 -0
  113. package/src/auth/rbac/seed.ts +67 -0
  114. package/src/auth/rbac/tables.ts +32 -0
  115. package/src/auth/rbac/types.ts +65 -0
  116. package/src/auth/tenant/extract.ts +33 -0
  117. package/src/auth/tenant/in-tenant.ts +49 -0
  118. package/src/auth/tenant/index.ts +7 -0
  119. package/src/auth/tenant/namespace.ts +23 -0
  120. package/src/auth/tenant/propagate.ts +20 -0
  121. package/src/auth/tenant/rls.ts +120 -0
  122. package/src/auth/tenant/scope.ts +33 -0
  123. package/src/auth/tenant/scoped-db.ts +581 -0
  124. package/src/auth/tenant/types.ts +14 -0
  125. package/src/auth/tenant/validate.ts +27 -0
  126. package/src/cli/commands/add.ts +158 -0
  127. package/src/cli/commands/alerts.ts +98 -0
  128. package/src/cli/commands/check.ts +1418 -0
  129. package/src/cli/commands/codemod.ts +78 -0
  130. package/src/cli/commands/db.ts +356 -0
  131. package/src/cli/commands/dev.ts +101 -0
  132. package/src/cli/commands/generate.ts +75 -0
  133. package/src/cli/commands/init.ts +36 -0
  134. package/src/cli/commands/install.ts +28 -0
  135. package/src/cli/commands/lint.ts +62 -0
  136. package/src/cli/commands/migrate.ts +132 -0
  137. package/src/cli/commands/openapi.ts +63 -0
  138. package/src/cli/commands/remove.ts +72 -0
  139. package/src/cli/commands/run.ts +50 -0
  140. package/src/cli/commands/scope.ts +54 -0
  141. package/src/cli/commands/serve.ts +68 -0
  142. package/src/cli/commands/shard.ts +31 -0
  143. package/src/cli/commands/shared/config-pipework-version.ts +28 -0
  144. package/src/cli/commands/shared/find-config.ts +22 -0
  145. package/src/cli/commands/shared/load-config.ts +35 -0
  146. package/src/cli/commands/shared/pnpm-install.ts +95 -0
  147. package/src/cli/commands/shared/report-removed.ts +8 -0
  148. package/src/cli/commands/sync.ts +32 -0
  149. package/src/cli/commands/test.ts +307 -0
  150. package/src/cli/commands/upgrade.ts +48 -0
  151. package/src/cli/dev-bootstrap.ts +24 -0
  152. package/src/cli/errors.ts +10 -0
  153. package/src/cli/index.ts +303 -0
  154. package/src/cli/output.ts +17 -0
  155. package/src/cli/port.ts +15 -0
  156. package/src/cli/surface-kinds.ts +20 -0
  157. package/src/client/index.ts +4 -0
  158. package/src/client/poll.ts +130 -0
  159. package/src/client/report-fault.ts +119 -0
  160. package/src/core/config/app-pool.ts +19 -0
  161. package/src/core/config/aws-env.ts +29 -0
  162. package/src/core/config/base-dir.ts +24 -0
  163. package/src/core/config/discover.ts +64 -0
  164. package/src/core/config/env-resolve.ts +87 -0
  165. package/src/core/config/env-types.ts +116 -0
  166. package/src/core/config/env.ts +55 -0
  167. package/src/core/config/errors.ts +9 -0
  168. package/src/core/config/import-config.ts +40 -0
  169. package/src/core/config/index.ts +8 -0
  170. package/src/core/config/load.ts +417 -0
  171. package/src/core/config/namespace.ts +14 -0
  172. package/src/core/config/resolve.ts +195 -0
  173. package/src/core/config/schema.ts +488 -0
  174. package/src/core/config/statement-observer.ts +48 -0
  175. package/src/core/config/ts-inline-hooks.ts +75 -0
  176. package/src/core/config/ts-register.ts +4 -0
  177. package/src/core/config/ts-resolve-hooks.ts +101 -0
  178. package/src/core/errors/base.ts +49 -0
  179. package/src/core/errors/http.ts +146 -0
  180. package/src/core/errors/index.ts +2 -0
  181. package/src/core/errors/namespace.ts +31 -0
  182. package/src/core/lifecycle/drain.ts +33 -0
  183. package/src/core/lifecycle/health.ts +72 -0
  184. package/src/core/lifecycle/index.ts +4 -0
  185. package/src/core/lifecycle/namespace.ts +7 -0
  186. package/src/core/lifecycle/startup.ts +102 -0
  187. package/src/core/lifecycle/types.ts +36 -0
  188. package/src/core/logging/context.ts +60 -0
  189. package/src/core/logging/error-chain.ts +68 -0
  190. package/src/core/logging/index.ts +5 -0
  191. package/src/core/logging/logger.ts +65 -0
  192. package/src/core/logging/namespace.ts +16 -0
  193. package/src/core/logging/proxy.ts +22 -0
  194. package/src/core/logging/redact-match.ts +24 -0
  195. package/src/core/logging/types.ts +47 -0
  196. package/src/core/pipework.ts +566 -0
  197. package/src/core/runtime/broker.ts +69 -0
  198. package/src/core/surface/http.ts +133 -0
  199. package/src/core/surface/index.ts +11 -0
  200. package/src/core/surface/job-timeout.ts +40 -0
  201. package/src/core/surface/namespace.ts +13 -0
  202. package/src/core/surface/script.ts +33 -0
  203. package/src/core/surface/start.ts +142 -0
  204. package/src/core/surface/types.ts +225 -0
  205. package/src/core/surface/validate.ts +88 -0
  206. package/src/core/surface/worker.ts +528 -0
  207. package/src/core/validation/connectivity.ts +49 -0
  208. package/src/core/validation/domain.ts +99 -0
  209. package/src/core/validation/index.ts +5 -0
  210. package/src/core/validation/queue-tables.ts +312 -0
  211. package/src/core/validation/rls-role.ts +138 -0
  212. package/src/core/validation/startup.ts +51 -0
  213. package/src/core/validation/surfaces.ts +65 -0
  214. package/src/core/validation/types.ts +25 -0
  215. package/src/data/db/advisory-lock.ts +55 -0
  216. package/src/data/db/aggregates.ts +172 -0
  217. package/src/data/db/array-elements.ts +111 -0
  218. package/src/data/db/bulk-set.ts +53 -0
  219. package/src/data/db/col/index.ts +14 -0
  220. package/src/data/db/composed.ts +53 -0
  221. package/src/data/db/db.ts +276 -0
  222. package/src/data/db/excluded.ts +16 -0
  223. package/src/data/db/expressions.ts +473 -0
  224. package/src/data/db/filter.ts +90 -0
  225. package/src/data/db/function-source.ts +114 -0
  226. package/src/data/db/identifiers.ts +16 -0
  227. package/src/data/db/idx/index.ts +9 -0
  228. package/src/data/db/in-list.ts +49 -0
  229. package/src/data/db/index.ts +9 -0
  230. package/src/data/db/insert-split.ts +137 -0
  231. package/src/data/db/instrumentation.ts +82 -0
  232. package/src/data/db/maintenance.ts +28 -0
  233. package/src/data/db/namespace.ts +107 -0
  234. package/src/data/db/owner-labels.ts +9 -0
  235. package/src/data/db/pool.ts +187 -0
  236. package/src/data/db/query-label.ts +13 -0
  237. package/src/data/db/query-watch.ts +116 -0
  238. package/src/data/db/raw-client-warning.ts +37 -0
  239. package/src/data/db/readonly.ts +23 -0
  240. package/src/data/db/reservation.ts +151 -0
  241. package/src/data/db/schema-features.ts +14 -0
  242. package/src/data/db/serializable.ts +83 -0
  243. package/src/data/db/sql.ts +1 -0
  244. package/src/data/db/timeouts.ts +76 -0
  245. package/src/data/db/types.ts +18 -0
  246. package/src/data/db/unbound.ts +33 -0
  247. package/src/data/db/values.ts +29 -0
  248. package/src/data/domain/brand.ts +15 -0
  249. package/src/data/domain/build-factory.ts +193 -0
  250. package/src/data/domain/build-schema.ts +161 -0
  251. package/src/data/domain/build-table.ts +355 -0
  252. package/src/data/domain/define.ts +239 -0
  253. package/src/data/domain/external-registry.ts +34 -0
  254. package/src/data/domain/external.ts +77 -0
  255. package/src/data/domain/field.ts +279 -0
  256. package/src/data/domain/index.ts +13 -0
  257. package/src/data/domain/naming.ts +6 -0
  258. package/src/data/domain/projections.ts +57 -0
  259. package/src/data/domain/trace-safe-projection.ts +31 -0
  260. package/src/data/domain/traits.ts +108 -0
  261. package/src/data/domain/types.ts +289 -0
  262. package/src/data/jsonb/composed.ts +18 -0
  263. package/src/data/jsonb/index.ts +1 -0
  264. package/src/data/jsonb/namespace.ts +30 -0
  265. package/src/data/jsonb/query.ts +86 -0
  266. package/src/data/migrate/append-only-generate.ts +47 -0
  267. package/src/data/migrate/applied.ts +47 -0
  268. package/src/data/migrate/apply.ts +309 -0
  269. package/src/data/migrate/check.ts +119 -0
  270. package/src/data/migrate/diff.ts +357 -0
  271. package/src/data/migrate/door-generate.ts +130 -0
  272. package/src/data/migrate/framework-rls.ts +58 -0
  273. package/src/data/migrate/generate.ts +201 -0
  274. package/src/data/migrate/history.ts +215 -0
  275. package/src/data/migrate/index.ts +9 -0
  276. package/src/data/migrate/internal-definitions.ts +175 -0
  277. package/src/data/migrate/post-process.ts +73 -0
  278. package/src/data/migrate/pragma.ts +73 -0
  279. package/src/data/migrate/provision-framework.ts +147 -0
  280. package/src/data/migrate/rls-generate.ts +61 -0
  281. package/src/data/migrate/run.ts +124 -0
  282. package/src/data/migrate/safety.ts +167 -0
  283. package/src/data/migrate/snapshot.ts +368 -0
  284. package/src/data/migrate/sql-emit.ts +392 -0
  285. package/src/data/migrate/statements.ts +312 -0
  286. package/src/data/query/alias.ts +126 -0
  287. package/src/data/query/batch.ts +8 -0
  288. package/src/data/query/cache/core/cache.ts +78 -0
  289. package/src/data/query/cache/core/index.ts +1 -0
  290. package/src/data/query/cache/core/types.ts +29 -0
  291. package/src/data/query/cache/readme.md +230 -0
  292. package/src/data/query/casing.ts +76 -0
  293. package/src/data/query/collation.ts +11 -0
  294. package/src/data/query/column-builder.ts +370 -0
  295. package/src/data/query/column.ts +150 -0
  296. package/src/data/query/entity.ts +42 -0
  297. package/src/data/query/errors.ts +33 -0
  298. package/src/data/query/index.ts +14 -0
  299. package/src/data/query/logger.ts +47 -0
  300. package/src/data/query/operations.ts +45 -0
  301. package/src/data/query/pg-core/alias.ts +12 -0
  302. package/src/data/query/pg-core/checks.ts +32 -0
  303. package/src/data/query/pg-core/columns/all.ts +71 -0
  304. package/src/data/query/pg-core/columns/bigint.ts +110 -0
  305. package/src/data/query/pg-core/columns/bigserial.ts +128 -0
  306. package/src/data/query/pg-core/columns/boolean.ts +43 -0
  307. package/src/data/query/pg-core/columns/char.ts +85 -0
  308. package/src/data/query/pg-core/columns/cidr.ts +43 -0
  309. package/src/data/query/pg-core/columns/common.ts +366 -0
  310. package/src/data/query/pg-core/columns/custom.ts +232 -0
  311. package/src/data/query/pg-core/columns/date.common.ts +15 -0
  312. package/src/data/query/pg-core/columns/date.ts +112 -0
  313. package/src/data/query/pg-core/columns/double-precision.ts +55 -0
  314. package/src/data/query/pg-core/columns/enum.ts +201 -0
  315. package/src/data/query/pg-core/columns/index.ts +35 -0
  316. package/src/data/query/pg-core/columns/inet.ts +43 -0
  317. package/src/data/query/pg-core/columns/int.common.ts +57 -0
  318. package/src/data/query/pg-core/columns/integer.ts +53 -0
  319. package/src/data/query/pg-core/columns/interval.ts +83 -0
  320. package/src/data/query/pg-core/columns/json.ts +58 -0
  321. package/src/data/query/pg-core/columns/jsonb.ts +56 -0
  322. package/src/data/query/pg-core/columns/line.ts +117 -0
  323. package/src/data/query/pg-core/columns/macaddr.ts +43 -0
  324. package/src/data/query/pg-core/columns/macaddr8.ts +43 -0
  325. package/src/data/query/pg-core/columns/numeric.ts +227 -0
  326. package/src/data/query/pg-core/columns/point.ts +127 -0
  327. package/src/data/query/pg-core/columns/postgis_extension/geometry.ts +119 -0
  328. package/src/data/query/pg-core/columns/postgis_extension/utils.ts +47 -0
  329. package/src/data/query/pg-core/columns/real.ts +58 -0
  330. package/src/data/query/pg-core/columns/serial.ts +55 -0
  331. package/src/data/query/pg-core/columns/smallint.ts +53 -0
  332. package/src/data/query/pg-core/columns/smallserial.ts +60 -0
  333. package/src/data/query/pg-core/columns/text.ts +67 -0
  334. package/src/data/query/pg-core/columns/time.ts +72 -0
  335. package/src/data/query/pg-core/columns/timestamp.ts +163 -0
  336. package/src/data/query/pg-core/columns/uuid.ts +51 -0
  337. package/src/data/query/pg-core/columns/varchar.ts +89 -0
  338. package/src/data/query/pg-core/columns/vector_extension/bit.ts +68 -0
  339. package/src/data/query/pg-core/columns/vector_extension/halfvec.ts +80 -0
  340. package/src/data/query/pg-core/columns/vector_extension/sparsevec.ts +67 -0
  341. package/src/data/query/pg-core/columns/vector_extension/vector.ts +80 -0
  342. package/src/data/query/pg-core/db.ts +674 -0
  343. package/src/data/query/pg-core/dialect.ts +1404 -0
  344. package/src/data/query/pg-core/expressions.ts +25 -0
  345. package/src/data/query/pg-core/foreign-keys.ts +130 -0
  346. package/src/data/query/pg-core/index.ts +21 -0
  347. package/src/data/query/pg-core/indexes.ts +276 -0
  348. package/src/data/query/pg-core/policies.ts +56 -0
  349. package/src/data/query/pg-core/primary-keys.ts +62 -0
  350. package/src/data/query/pg-core/query-builders/count.ts +86 -0
  351. package/src/data/query/pg-core/query-builders/delete.ts +293 -0
  352. package/src/data/query/pg-core/query-builders/index.ts +7 -0
  353. package/src/data/query/pg-core/query-builders/insert.ts +452 -0
  354. package/src/data/query/pg-core/query-builders/query-builder.ts +123 -0
  355. package/src/data/query/pg-core/query-builders/query.ts +157 -0
  356. package/src/data/query/pg-core/query-builders/raw.ts +49 -0
  357. package/src/data/query/pg-core/query-builders/refresh-materialized-view.ts +108 -0
  358. package/src/data/query/pg-core/query-builders/select.ts +1346 -0
  359. package/src/data/query/pg-core/query-builders/select.types.ts +437 -0
  360. package/src/data/query/pg-core/query-builders/update.ts +626 -0
  361. package/src/data/query/pg-core/roles.ts +41 -0
  362. package/src/data/query/pg-core/schema.ts +72 -0
  363. package/src/data/query/pg-core/sequence.ts +41 -0
  364. package/src/data/query/pg-core/session.ts +292 -0
  365. package/src/data/query/pg-core/subquery.ts +46 -0
  366. package/src/data/query/pg-core/table.ts +252 -0
  367. package/src/data/query/pg-core/unique-constraint.ts +73 -0
  368. package/src/data/query/pg-core/utils/array.ts +95 -0
  369. package/src/data/query/pg-core/utils/index.ts +1 -0
  370. package/src/data/query/pg-core/utils.ts +104 -0
  371. package/src/data/query/pg-core/view-base.ts +14 -0
  372. package/src/data/query/pg-core/view-common.ts +1 -0
  373. package/src/data/query/pg-core/view.ts +435 -0
  374. package/src/data/query/pg-core/with-builder.ts +41 -0
  375. package/src/data/query/postgres-js/README.md +46 -0
  376. package/src/data/query/postgres-js/array-parser.ts +45 -0
  377. package/src/data/query/postgres-js/driver-error-boundary.ts +149 -0
  378. package/src/data/query/postgres-js/driver.ts +163 -0
  379. package/src/data/query/postgres-js/index.ts +2 -0
  380. package/src/data/query/postgres-js/session.ts +234 -0
  381. package/src/data/query/primary-key.ts +11 -0
  382. package/src/data/query/query-builders/query-builder.ts +19 -0
  383. package/src/data/query/query-builders/select.types.ts +175 -0
  384. package/src/data/query/query-promise.ts +35 -0
  385. package/src/data/query/relations.ts +725 -0
  386. package/src/data/query/runnable-query.ts +12 -0
  387. package/src/data/query/selection-proxy.ts +121 -0
  388. package/src/data/query/session.ts +8 -0
  389. package/src/data/query/sql/expressions/conditions.ts +741 -0
  390. package/src/data/query/sql/expressions/index.ts +2 -0
  391. package/src/data/query/sql/expressions/select.ts +45 -0
  392. package/src/data/query/sql/functions/aggregate.ts +129 -0
  393. package/src/data/query/sql/functions/index.ts +2 -0
  394. package/src/data/query/sql/functions/vector.ts +178 -0
  395. package/src/data/query/sql/index.ts +3 -0
  396. package/src/data/query/sql/sql.ts +794 -0
  397. package/src/data/query/subquery.ts +53 -0
  398. package/src/data/query/table.ts +208 -0
  399. package/src/data/query/table.utils.ts +2 -0
  400. package/src/data/query/tracing-utils.ts +3 -0
  401. package/src/data/query/tracing.ts +11 -0
  402. package/src/data/query/utils.ts +357 -0
  403. package/src/data/query/version.ts +4 -0
  404. package/src/data/query/view-common.ts +1 -0
  405. package/src/data/schema/branded.ts +13 -0
  406. package/src/data/schema/generated/coerce.ts +5 -0
  407. package/src/data/schema/generated/combinator.ts +6 -0
  408. package/src/data/schema/generated/encoding.ts +5 -0
  409. package/src/data/schema/generated/error.ts +6 -0
  410. package/src/data/schema/generated/format.ts +5 -0
  411. package/src/data/schema/generated/type-constructor.ts +10 -0
  412. package/src/data/schema/generated/type.ts +6 -0
  413. package/src/data/schema/index.ts +6 -0
  414. package/src/data/schema/json-schema.ts +33 -0
  415. package/src/data/schema/namespace.ts +55 -0
  416. package/src/data/schema/parse.ts +39 -0
  417. package/src/data/schema/types.ts +39 -0
  418. package/src/data/temporal/append-only.ts +134 -0
  419. package/src/data/temporal/close.ts +27 -0
  420. package/src/data/temporal/columns.ts +10 -0
  421. package/src/data/temporal/definition-queries.ts +70 -0
  422. package/src/data/temporal/errors.ts +10 -0
  423. package/src/data/temporal/get-current.ts +22 -0
  424. package/src/data/temporal/index.ts +9 -0
  425. package/src/data/temporal/namespace.ts +36 -0
  426. package/src/data/temporal/query.ts +25 -0
  427. package/src/data/temporal/resolve.ts +17 -0
  428. package/src/data/temporal/revise.ts +67 -0
  429. package/src/data/temporal/types.ts +22 -0
  430. package/src/data/valve/artifact.ts +33 -0
  431. package/src/data/valve/contract-diff.ts +21 -0
  432. package/src/data/valve/cross.ts +57 -0
  433. package/src/data/valve/crossing-ledger.ts +50 -0
  434. package/src/data/valve/decision.ts +44 -0
  435. package/src/data/valve/durable-crossing.ts +52 -0
  436. package/src/data/valve/execute-crossing.ts +77 -0
  437. package/src/data/valve/faucet.ts +56 -0
  438. package/src/data/valve/gate.ts +114 -0
  439. package/src/data/valve/graph.ts +77 -0
  440. package/src/data/valve/index.ts +53 -0
  441. package/src/data/valve/namespace.ts +57 -0
  442. package/src/data/valve/registry.ts +50 -0
  443. package/src/data/valve/schema/valve-crossing-fields.ts +23 -0
  444. package/src/data/valve/schema/valve-crossing.ts +9 -0
  445. package/src/data/valve/supply.ts +154 -0
  446. package/src/data/valve/types.ts +143 -0
  447. package/src/data/vector/columns.ts +27 -0
  448. package/src/data/vector/index.ts +4 -0
  449. package/src/data/vector/namespace.ts +33 -0
  450. package/src/data/vector/query.ts +85 -0
  451. package/src/data/vector/validate.ts +16 -0
  452. package/src/data/write/audit/actor.ts +15 -0
  453. package/src/data/write/audit/audit-columns.ts +18 -0
  454. package/src/data/write/audit/audit-select.ts +111 -0
  455. package/src/data/write/audit/bound-transaction.ts +14 -0
  456. package/src/data/write/audit/cte-compile.ts +32 -0
  457. package/src/data/write/audit/decode-returning.ts +47 -0
  458. package/src/data/write/audit/final-select.ts +43 -0
  459. package/src/data/write/audit/infra-audit.ts +36 -0
  460. package/src/data/write/audit/primary-key.ts +65 -0
  461. package/src/data/write/audit/projection.ts +41 -0
  462. package/src/data/write/audit/read-touches.ts +86 -0
  463. package/src/data/write/audit/touch-match.ts +78 -0
  464. package/src/data/write/audit/verb-delete.ts +62 -0
  465. package/src/data/write/audit/verb-insert.ts +36 -0
  466. package/src/data/write/audit/verb-select.ts +47 -0
  467. package/src/data/write/audit/verb-update.ts +60 -0
  468. package/src/data/write/audit/verb-upsert.ts +104 -0
  469. package/src/data/write/conflict.ts +43 -0
  470. package/src/data/write/delete.ts +38 -0
  471. package/src/data/write/execute.ts +243 -0
  472. package/src/data/write/index.ts +11 -0
  473. package/src/data/write/insert.ts +63 -0
  474. package/src/data/write/state.ts +43 -0
  475. package/src/data/write/update.ts +54 -0
  476. package/src/data/write/upsert.ts +58 -0
  477. package/src/data/write/values.ts +19 -0
  478. package/src/index.ts +230 -0
  479. package/src/infra/access-links/code.ts +70 -0
  480. package/src/infra/access-links/handle.ts +892 -0
  481. package/src/infra/access-links/index.ts +9 -0
  482. package/src/infra/access-links/namespace.ts +30 -0
  483. package/src/infra/access-links/person-check.ts +177 -0
  484. package/src/infra/access-links/schema.ts +71 -0
  485. package/src/infra/alerts/async-sources.ts +231 -0
  486. package/src/infra/alerts/audit.ts +36 -0
  487. package/src/infra/alerts/beat.ts +123 -0
  488. package/src/infra/alerts/client-faults.ts +111 -0
  489. package/src/infra/alerts/faults.ts +156 -0
  490. package/src/infra/alerts/handle.ts +778 -0
  491. package/src/infra/alerts/http.ts +192 -0
  492. package/src/infra/alerts/index.ts +12 -0
  493. package/src/infra/alerts/infra-sources.ts +180 -0
  494. package/src/infra/alerts/namespace.ts +81 -0
  495. package/src/infra/alerts/redact.ts +21 -0
  496. package/src/infra/alerts/request-faults.ts +41 -0
  497. package/src/infra/alerts/schema.ts +124 -0
  498. package/src/infra/alerts/sinks.ts +125 -0
  499. package/src/infra/alerts/source-options.ts +26 -0
  500. package/src/infra/alerts/sources.ts +503 -0
  501. package/src/infra/alerts/subsystem-sources.ts +137 -0
  502. package/src/infra/audit/emit.ts +87 -0
  503. package/src/infra/audit/index.ts +2 -0
  504. package/src/infra/audit/namespace.ts +22 -0
  505. package/src/infra/audit/schema.sql +35 -0
  506. package/src/infra/audit/types.ts +18 -0
  507. package/src/infra/aws/credentials.ts +147 -0
  508. package/src/infra/aws/sigv4.ts +140 -0
  509. package/src/infra/cache/create.ts +58 -0
  510. package/src/infra/cache/entry.ts +81 -0
  511. package/src/infra/cache/index.ts +4 -0
  512. package/src/infra/cache/namespace.ts +10 -0
  513. package/src/infra/cache/tenant.ts +93 -0
  514. package/src/infra/cache/types.ts +24 -0
  515. package/src/infra/crawl/audit.ts +35 -0
  516. package/src/infra/crawl/errors.ts +25 -0
  517. package/src/infra/crawl/handle.ts +693 -0
  518. package/src/infra/crawl/index.ts +9 -0
  519. package/src/infra/crawl/links.ts +160 -0
  520. package/src/infra/crawl/namespace.ts +36 -0
  521. package/src/infra/crawl/robots.ts +100 -0
  522. package/src/infra/crawl/schema.ts +89 -0
  523. package/src/infra/credit-line/handle.ts +883 -0
  524. package/src/infra/credit-line/index.ts +6 -0
  525. package/src/infra/credit-line/namespace.ts +7 -0
  526. package/src/infra/credit-line/schema.ts +96 -0
  527. package/src/infra/credits/handle.ts +706 -0
  528. package/src/infra/credits/index.ts +5 -0
  529. package/src/infra/credits/namespace.ts +7 -0
  530. package/src/infra/credits/schema.ts +83 -0
  531. package/src/infra/email/audit.ts +36 -0
  532. package/src/infra/email/inbound.ts +622 -0
  533. package/src/infra/email/index.ts +11 -0
  534. package/src/infra/email/mail.ts +517 -0
  535. package/src/infra/email/mime.ts +447 -0
  536. package/src/infra/email/namespace.ts +22 -0
  537. package/src/infra/email/providers.ts +111 -0
  538. package/src/infra/email/schema.ts +96 -0
  539. package/src/infra/email/sns.ts +200 -0
  540. package/src/infra/email/unsubscribe.ts +44 -0
  541. package/src/infra/fetch/address.ts +88 -0
  542. package/src/infra/fetch/connect-retry.ts +87 -0
  543. package/src/infra/fetch/handle.ts +329 -0
  544. package/src/infra/fetch/index.ts +7 -0
  545. package/src/infra/fetch/namespace.ts +70 -0
  546. package/src/infra/idempotency/index.ts +3 -0
  547. package/src/infra/idempotency/middleware.ts +87 -0
  548. package/src/infra/idempotency/store.ts +92 -0
  549. package/src/infra/idempotency/types.ts +30 -0
  550. package/src/infra/join-requests/handle.ts +312 -0
  551. package/src/infra/join-requests/index.ts +2 -0
  552. package/src/infra/join-requests/namespace.ts +7 -0
  553. package/src/infra/join-requests/schema.ts +33 -0
  554. package/src/infra/outbox/core.ts +165 -0
  555. package/src/infra/quota/errors.ts +32 -0
  556. package/src/infra/quota/handle.ts +215 -0
  557. package/src/infra/quota/index.ts +5 -0
  558. package/src/infra/quota/namespace.ts +7 -0
  559. package/src/infra/quota/schema.ts +15 -0
  560. package/src/infra/storage/backend.ts +34 -0
  561. package/src/infra/storage/handle.ts +513 -0
  562. package/src/infra/storage/index.ts +9 -0
  563. package/src/infra/storage/local.ts +104 -0
  564. package/src/infra/storage/namespace.ts +13 -0
  565. package/src/infra/storage/s3.ts +257 -0
  566. package/src/infra/storage/schema.ts +24 -0
  567. package/src/infra/support/handle.ts +854 -0
  568. package/src/infra/support/http.ts +229 -0
  569. package/src/infra/support/index.ts +7 -0
  570. package/src/infra/support/namespace.ts +12 -0
  571. package/src/infra/support/schema.ts +96 -0
  572. package/src/infra/webhook/inbound.ts +45 -0
  573. package/src/infra/webhook/index.ts +5 -0
  574. package/src/infra/webhook/namespace.ts +24 -0
  575. package/src/infra/webhook/outbound.ts +315 -0
  576. package/src/infra/webhook/sign.ts +32 -0
  577. package/src/infra/webhook/verify.ts +82 -0
  578. package/src/invariants/assert.ts +26 -0
  579. package/src/invariants/index.ts +1 -0
  580. package/src/lint/config.ts +56 -0
  581. package/src/lint/doctrine.ts +163 -0
  582. package/src/lint/include.ts +97 -0
  583. package/src/lint/index.ts +3 -0
  584. package/src/lint/preset.ts +10 -0
  585. package/src/lint/resolver.ts +218 -0
  586. package/src/lint/rules/no-reexports.ts +46 -0
  587. package/src/request/behavior/audited.ts +85 -0
  588. package/src/request/behavior/cached.ts +62 -0
  589. package/src/request/behavior/compose.ts +28 -0
  590. package/src/request/behavior/index.ts +5 -0
  591. package/src/request/behavior/namespace.ts +16 -0
  592. package/src/request/behavior/types.ts +26 -0
  593. package/src/request/behavior/versioned.ts +54 -0
  594. package/src/request/context/create.ts +103 -0
  595. package/src/request/context/guard.ts +49 -0
  596. package/src/request/context/index.ts +4 -0
  597. package/src/request/context/run-in-transaction.ts +200 -0
  598. package/src/request/context/store.ts +28 -0
  599. package/src/request/context/types.ts +50 -0
  600. package/src/request/di/builder.ts +535 -0
  601. package/src/request/di/index.ts +8 -0
  602. package/src/request/di/resolve.ts +271 -0
  603. package/src/request/di/types.ts +262 -0
  604. package/src/request/fitting/namespace.ts +7 -0
  605. package/src/request/fixture/batch.ts +71 -0
  606. package/src/request/fixture/builder.ts +26 -0
  607. package/src/request/fixture/errors.ts +10 -0
  608. package/src/request/fixture/index.ts +8 -0
  609. package/src/request/fixture/namespace.ts +23 -0
  610. package/src/request/fixture/paginate.ts +44 -0
  611. package/src/request/fixture/to-handlers.ts +260 -0
  612. package/src/request/fixture/types.ts +79 -0
  613. package/src/request/flow/act-as.ts +78 -0
  614. package/src/request/flow/namespace.ts +17 -0
  615. package/src/request/http/error-step.ts +42 -0
  616. package/src/request/http/file.ts +141 -0
  617. package/src/request/http/index.ts +4 -0
  618. package/src/request/http/middleware.ts +141 -0
  619. package/src/request/http/namespace.ts +5 -0
  620. package/src/request/http/rate-limit-classes.ts +170 -0
  621. package/src/request/http/response.ts +82 -0
  622. package/src/request/http/server.ts +916 -0
  623. package/src/request/http/sniff.ts +261 -0
  624. package/src/request/http/types.ts +250 -0
  625. package/src/request/http/upload.ts +284 -0
  626. package/src/request/internal/text.ts +6 -0
  627. package/src/request/openapi/generate.ts +205 -0
  628. package/src/request/openapi/index.ts +2 -0
  629. package/src/request/openapi/namespace.ts +7 -0
  630. package/src/test/auth.ts +13 -0
  631. package/src/test/auto-setup.ts +45 -0
  632. package/src/test/context.ts +91 -0
  633. package/src/test/crawl-fixture.ts +157 -0
  634. package/src/test/discover-fork.ts +17 -0
  635. package/src/test/fingerprint.ts +135 -0
  636. package/src/test/globals.d.ts +7 -0
  637. package/src/test/index.ts +19 -0
  638. package/src/test/namespace.ts +87 -0
  639. package/src/test/plugin.ts +189 -0
  640. package/src/test/progress.ts +185 -0
  641. package/src/test/reap-after-run.ts +28 -0
  642. package/src/test/reap.ts +286 -0
  643. package/src/test/reset.ts +253 -0
  644. package/src/test/savepoints.ts +172 -0
  645. package/src/test/setup.ts +1422 -0
  646. package/src/test/system-channel.ts +50 -0
  647. package/src/test/vitest-plugin.ts +142 -0
  648. package/src/test/vitest-workspace.ts +507 -0
  649. package/src/test/vitest.ts +333 -0
  650. package/src/test/watch.ts +105 -0
  651. package/src/trace/capture/bounded-serializer.ts +146 -0
  652. package/src/trace/cardinality/analyze.ts +173 -0
  653. package/src/trace/cardinality/branch-context.ts +214 -0
  654. package/src/trace/cardinality/check.ts +33 -0
  655. package/src/trace/cardinality/classify-edge.ts +64 -0
  656. package/src/trace/cardinality/structural-max.ts +107 -0
  657. package/src/trace/check/coverage-check.ts +188 -0
  658. package/src/trace/check/flow-check.ts +103 -0
  659. package/src/trace/check/flow-step-site.ts +234 -0
  660. package/src/trace/check/io-pattern.ts +116 -0
  661. package/src/trace/codemod/add-cardinality.ts +152 -0
  662. package/src/trace/codemod/run.ts +80 -0
  663. package/src/trace/entry/child-trace.ts +21 -0
  664. package/src/trace/entry/close-trace.ts +87 -0
  665. package/src/trace/entry/finalize-trace.ts +28 -0
  666. package/src/trace/entry/open-trace.ts +138 -0
  667. package/src/trace/entry/parent-trace.ts +20 -0
  668. package/src/trace/entry/parse-traceparent.ts +39 -0
  669. package/src/trace/entry/process-start.ts +38 -0
  670. package/src/trace/entry/trace-context.ts +26 -0
  671. package/src/trace/entry/tracing-enabled.ts +10 -0
  672. package/src/trace/external/record.ts +195 -0
  673. package/src/trace/external/report.ts +66 -0
  674. package/src/trace/namespace.ts +19 -0
  675. package/src/trace/partition/day.ts +47 -0
  676. package/src/trace/partition/index.ts +14 -0
  677. package/src/trace/partition/partition-name.ts +23 -0
  678. package/src/trace/partition/plan.ts +82 -0
  679. package/src/trace/partition/schedule.ts +26 -0
  680. package/src/trace/partition/startup-hook.ts +39 -0
  681. package/src/trace/partition/sync.ts +154 -0
  682. package/src/trace/partition/tables.ts +53 -0
  683. package/src/trace/read/tree.ts +83 -0
  684. package/src/trace/retain/copy-on-error.ts +76 -0
  685. package/src/trace/runtime/expire-stale-traces.ts +54 -0
  686. package/src/trace/runtime/flow-step.ts +147 -0
  687. package/src/trace/runtime/flush-steps.ts +31 -0
  688. package/src/trace/runtime/pending-writes.ts +54 -0
  689. package/src/trace/runtime/step-buffer.ts +298 -0
  690. package/src/trace/runtime/step-error.ts +21 -0
  691. package/src/trace/runtime/step-meta.ts +55 -0
  692. package/src/trace/runtime/thenable.ts +12 -0
  693. package/src/trace/runtime/truncate-trace.ts +62 -0
  694. package/src/trace/schema/trace-fields.ts +52 -0
  695. package/src/trace/schema/trace-retained.ts +22 -0
  696. package/src/trace/schema/trace-step-fields.ts +44 -0
  697. package/src/trace/schema/trace-step-retained.ts +25 -0
  698. package/src/trace/schema/trace-step.ts +18 -0
  699. package/src/trace/schema/trace.ts +12 -0
  700. package/src/trace/transformer/apply.ts +79 -0
  701. package/src/trace/transformer/build-meta-literal.ts +30 -0
  702. package/src/trace/transformer/find-flow-step-sites.ts +85 -0
  703. package/src/trace/transformer/inject-flow-step-import.ts +39 -0
  704. package/src/trace/transformer/transform-error.ts +14 -0
  705. package/src/trace/transformer/transform-flow-steps.ts +123 -0
  706. package/src/trace/transformer/wrap-function-declaration.ts +62 -0
  707. package/src/trace/transformer/wrap-variable-declaration.ts +67 -0
  708. package/src/workspace/affected.ts +110 -0
  709. package/src/workspace/changed-files.ts +163 -0
  710. package/src/workspace/check-deps.ts +213 -0
  711. package/src/workspace/checksum.ts +20 -0
  712. package/src/workspace/dependency-graph.ts +67 -0
  713. package/src/workspace/detect-pipework-copies.ts +93 -0
  714. package/src/workspace/discover.ts +206 -0
  715. package/src/workspace/generate.ts +401 -0
  716. package/src/workspace/index.ts +7 -0
  717. package/src/workspace/module-imports-pipework.ts +39 -0
  718. package/src/workspace/module-package-name.ts +12 -0
  719. package/src/workspace/scrub-git-env.ts +23 -0
  720. package/src/workspace/source-paths.ts +36 -0
  721. package/src/workspace/sync.ts +182 -0
  722. package/dist/REFERENCE.md +0 -1477
  723. package/dist/infra/access-links/rate-limit.d.ts +0 -10
  724. package/dist/infra/access-links/rate-limit.d.ts.map +0 -1
  725. package/dist/infra/access-links/rate-limit.js +0 -28
  726. package/dist/infra/access-links/rate-limit.js.map +0 -1
  727. package/dist/infra/email/sigv4.d.ts +0 -24
  728. package/dist/infra/email/sigv4.d.ts.map +0 -1
  729. package/dist/infra/email/sigv4.js +0 -55
  730. package/dist/infra/email/sigv4.js.map +0 -1
@@ -0,0 +1,179 @@
1
+ import { ValidationError } from '../../core/errors/index.js'
2
+
3
+ /** Parsed cron schedule — arrays of valid minutes, hours, days, months, weekdays. */
4
+ export interface CronSchedule {
5
+ readonly minutes: readonly number[]
6
+ readonly hours: readonly number[]
7
+ readonly daysOfMonth: readonly number[]
8
+ readonly months: readonly number[]
9
+ readonly daysOfWeek: readonly number[]
10
+ }
11
+
12
+ const FIELD_RANGES: readonly [number, number][] = [
13
+ [0, 59], // minute
14
+ [0, 23], // hour
15
+ [1, 31], // day of month
16
+ [1, 12], // month
17
+ [0, 6], // day of week (0=Sun)
18
+ ]
19
+
20
+ export function parseCron(expression: string): CronSchedule {
21
+ const parts = expression.trim().split(/\s+/)
22
+ if (parts.length !== 5) {
23
+ throw new ValidationError(
24
+ `Invalid cron expression "${expression}": expected 5 fields (minute hour day month weekday), got ${parts.length}`,
25
+ )
26
+ }
27
+
28
+ const [minutes, hours, daysOfMonth, months, daysOfWeek] = parts as [string, string, string, string, string]
29
+ return {
30
+ minutes: parseField(minutes, FIELD_RANGES[0]!, 'minute'),
31
+ hours: parseField(hours, FIELD_RANGES[1]!, 'hour'),
32
+ daysOfMonth: parseField(daysOfMonth, FIELD_RANGES[2]!, 'day-of-month'),
33
+ months: parseField(months, FIELD_RANGES[3]!, 'month'),
34
+ daysOfWeek: parseField(daysOfWeek, FIELD_RANGES[4]!, 'day-of-week'),
35
+ }
36
+ }
37
+
38
+ function parseField(field: string, [min, max]: [number, number], name: string): number[] {
39
+ const values = new Set<number>()
40
+
41
+ for (const part of field.split(',')) {
42
+ const stepMatch = part.match(/^(.+)\/(\d+)$/)
43
+ const step = stepMatch ? parseInt(stepMatch[2]!, 10) : null
44
+ const rangePart = stepMatch ? stepMatch[1]! : part
45
+
46
+ if (step !== null && (step < 1 || step > max)) {
47
+ throw new ValidationError(`Invalid cron ${name}: step "${step}" out of range`)
48
+ }
49
+
50
+ if (rangePart === '*') {
51
+ for (let i = min; i <= max; i += (step ?? 1)) {
52
+ values.add(i)
53
+ }
54
+ } else if (rangePart.includes('-')) {
55
+ const [startStr, endStr] = rangePart.split('-') as [string, string]
56
+ const start = parseInt(startStr, 10)
57
+ const end = parseInt(endStr, 10)
58
+ if (Number.isNaN(start) || Number.isNaN(end) || start < min || end > max || start > end) {
59
+ throw new ValidationError(`Invalid cron ${name}: range "${rangePart}" out of bounds (${min}-${max})`)
60
+ }
61
+ for (let i = start; i <= end; i += (step ?? 1)) {
62
+ values.add(i)
63
+ }
64
+ } else {
65
+ const val = parseInt(rangePart, 10)
66
+ if (Number.isNaN(val) || val < min || val > max) {
67
+ throw new ValidationError(`Invalid cron ${name}: value "${rangePart}" out of range (${min}-${max})`)
68
+ }
69
+ if (step !== null) {
70
+ for (let i = val; i <= max; i += step) {
71
+ values.add(i)
72
+ }
73
+ } else {
74
+ values.add(val)
75
+ }
76
+ }
77
+ }
78
+
79
+ return [...values].sort((a, b) => a - b)
80
+ }
81
+
82
+ export function nextTick(schedule: CronSchedule, after: Date, timezone?: string): Date {
83
+ const tz = timezone ?? 'UTC'
84
+ const formatter = new Intl.DateTimeFormat('en-US', {
85
+ timeZone: tz,
86
+ year: 'numeric',
87
+ month: '2-digit',
88
+ day: '2-digit',
89
+ hour: '2-digit',
90
+ minute: '2-digit',
91
+ second: '2-digit',
92
+ hour12: false,
93
+ })
94
+
95
+ const parts = extractParts(formatter, after)
96
+ let year = parts.year
97
+ let month = parts.month
98
+ let day = parts.day
99
+ let hour = parts.hour
100
+ let minute = parts.minute + 1
101
+
102
+ for (let guard = 0; guard < 5 * 366; guard++) {
103
+ if (minute > 59) { minute = 0; hour++ }
104
+ if (hour > 23) { hour = 0; day++ }
105
+ const dim = getDaysInMonth(year, month)
106
+ if (day > dim) { day = 1; month++ }
107
+ if (month > 12) { month = 1; year++ }
108
+
109
+ if (!schedule.months.includes(month)) {
110
+ month++; day = schedule.daysOfMonth[0]!; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
111
+ continue
112
+ }
113
+
114
+ if (!schedule.daysOfMonth.includes(day)) {
115
+ day++; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
116
+ continue
117
+ }
118
+
119
+ const dow = getDayOfWeekForDate(year, month, day)
120
+ if (!schedule.daysOfWeek.includes(dow)) {
121
+ day++; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
122
+ continue
123
+ }
124
+
125
+ if (!schedule.hours.includes(hour)) {
126
+ const nextHour = schedule.hours.find(h => h > hour)
127
+ if (nextHour !== undefined) {
128
+ hour = nextHour; minute = schedule.minutes[0]!
129
+ } else {
130
+ day++; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
131
+ }
132
+ continue
133
+ }
134
+
135
+ if (!schedule.minutes.includes(minute)) {
136
+ const nextMin = schedule.minutes.find(m => m >= minute)
137
+ if (nextMin !== undefined) {
138
+ minute = nextMin
139
+ } else {
140
+ hour++; minute = schedule.minutes[0]!
141
+ }
142
+ continue
143
+ }
144
+
145
+ return buildDate(tz, year, month, day, hour, minute)
146
+ }
147
+
148
+ throw new Error('Could not find next cron tick within search window')
149
+ }
150
+
151
+ function extractParts(formatter: Intl.DateTimeFormat, date: Date): { year: number; month: number; day: number; hour: number; minute: number } {
152
+ const resolved = formatter.formatToParts(date)
153
+ const get = (type: Intl.DateTimeFormatPartTypes) => parseInt(resolved.find(p => p.type === type)!.value, 10)
154
+ return { year: get('year'), month: get('month'), day: get('day'), hour: get('hour'), minute: get('minute') }
155
+ }
156
+
157
+ function getDayOfWeekForDate(year: number, month: number, day: number): number {
158
+ return new Date(Date.UTC(year, month - 1, day, 12, 0, 0)).getUTCDay()
159
+ }
160
+
161
+ function getDaysInMonth(year: number, month: number): number {
162
+ return new Date(year, month, 0).getDate()
163
+ }
164
+
165
+ function buildDate(tz: string, year: number, month: number, day: number, hour: number, minute: number): Date {
166
+ if (tz === 'UTC') {
167
+ return new Date(Date.UTC(year, month - 1, day, hour, minute, 0, 0))
168
+ }
169
+ const iso = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}T${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:00`
170
+ const formatter = new Intl.DateTimeFormat('en-US', { timeZone: tz, timeZoneName: 'longOffset' })
171
+ const refParts = formatter.formatToParts(new Date(iso + 'Z'))
172
+ const tzPart = refParts.find(p => p.type === 'timeZoneName')?.value ?? '+00:00'
173
+ const offsetMatch = tzPart.match(/GMT([+-]\d{1,2}):?(\d{2})?/)
174
+ if (!offsetMatch) return new Date(iso + 'Z')
175
+ const offsetHours = parseInt(offsetMatch[1]!, 10)
176
+ const offsetMinutes = parseInt(offsetMatch[2] ?? '0', 10)
177
+ const totalOffsetMs = (offsetHours * 60 + (offsetHours < 0 ? -offsetMinutes : offsetMinutes)) * 60_000
178
+ return new Date(new Date(iso + 'Z').getTime() - totalOffsetMs)
179
+ }
@@ -0,0 +1,56 @@
1
+ import { PipeworkError } from '../../core/errors/base.js'
2
+
3
+ /**
4
+ * Thrown by `jobs.execute` when the caller's `signal` aborts before the handler
5
+ * returns. `name` is `'AbortError'` so the standard `err.name === 'AbortError'`
6
+ * check works; `code` stays pipework's `JOB_ABORTED`.
7
+ *
8
+ * Aborting with an `Error` as the reason rejects with that error instead — the
9
+ * worker uses this to keep its own job-timeout message.
10
+ */
11
+ export class JobAbortedError extends PipeworkError {
12
+ readonly code = 'JOB_ABORTED' as const
13
+ readonly httpStatus = 499 as const
14
+
15
+ constructor(jobLabel: string, reason?: unknown) {
16
+ super(
17
+ `[pipework] Job ${jobLabel} was aborted by its caller's signal.\n\n` +
18
+ ' The handler was still running; its transaction was rolled back and its\n' +
19
+ ' connection released. An in-flight query was cancelled on the server, but a\n' +
20
+ ' handler that ignores the cancellation keeps running until it returns.\n',
21
+ reason === undefined ? { jobLabel } : { jobLabel, reason },
22
+ )
23
+ this.name = 'AbortError'
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Thrown by a job handler to end the attempt as "try again later": the job goes
29
+ * back to pending after `delayMs` (the queue's backoff, at least a second, when
30
+ * unset) and the attempt is not counted. Build it with `jobs.later(...)`.
31
+ */
32
+ export class JobLaterError extends PipeworkError {
33
+ readonly code = 'JOB_LATER' as const
34
+ readonly httpStatus = 503 as const
35
+ readonly delayMs: number | undefined
36
+
37
+ constructor(message: string, opts: { delayMs?: number; cause?: unknown } = {}) {
38
+ super(message, opts.cause === undefined ? {} : { cause: opts.cause })
39
+ this.name = 'JobLaterError'
40
+ this.delayMs = opts.delayMs
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Thrown by a job handler to end the attempt as a final failure: the job is
46
+ * dead-lettered now, whatever attempts remain. Build it with `jobs.permanent(...)`.
47
+ */
48
+ export class JobPermanentError extends PipeworkError {
49
+ readonly code = 'JOB_PERMANENT' as const
50
+ readonly httpStatus = 500 as const
51
+
52
+ constructor(message: string, opts: { cause?: unknown } = {}) {
53
+ super(message, opts.cause === undefined ? {} : { cause: opts.cause })
54
+ this.name = 'JobPermanentError'
55
+ }
56
+ }
@@ -0,0 +1,117 @@
1
+ // Cross-job exclusion gate for the claim query.
2
+ //
3
+ // A job "participates" in exclusion when its array column is non-NULL or its
4
+ // blocks-all flag is true. Against the concurrent set R (claimed/running jobs,
5
+ // tenant-scoped when a tenant column is configured), a pending candidate is
6
+ // claimable when:
7
+ // - it does not participate: always claimable, and it never blocks others
8
+ // - it is blocks-all: R contains no participating job
9
+ // - it carries an array: R contains no blocks-all job and no job whose
10
+ // array overlaps (&&) the candidate's
11
+ //
12
+ // Two concurrent workers can evaluate these NOT EXISTS checks against the same
13
+ // MVCC snapshot and both pass (write skew) — the claim query must run under
14
+ // SERIALIZABLE; queue.ts handles that.
15
+
16
+ import { assertValidIdentifier, quoteIdentifier } from '../../data/db/identifiers.js'
17
+ import { QUEUE_BASE_COLUMNS } from './table.js'
18
+
19
+ /** Cross-job exclusion config — names the consumer's conflict columns; the mechanism is pipework's. */
20
+ export interface ExclusionConfig {
21
+ /** Array column — two jobs whose arrays overlap (`&&`) are mutually exclusive. */
22
+ readonly arrayColumn?: string
23
+ /** Element type of `arrayColumn`. Default `'uuid'`. */
24
+ readonly arrayElementType?: 'uuid' | 'text'
25
+ /** Boolean column — a TRUE job is exclusive against every participating job in its scope. */
26
+ readonly blocksAllColumn?: string
27
+ /** Tenant column — exclusion checks compare only jobs with the same tenant value. */
28
+ readonly tenantColumn?: string
29
+ }
30
+
31
+ export interface ResolvedExclusion {
32
+ readonly arrayColumn?: string
33
+ readonly arrayElementType: 'uuid' | 'text'
34
+ readonly blocksAllColumn?: string
35
+ readonly tenantColumn?: string
36
+ }
37
+
38
+ export function resolveExclusion(config: ExclusionConfig | undefined): ResolvedExclusion | undefined {
39
+ if (config === undefined) return undefined
40
+
41
+ if (config.arrayColumn === undefined && config.blocksAllColumn === undefined) {
42
+ throw new Error(
43
+ '[pipework] exclusion requires arrayColumn and/or blocksAllColumn.\n\n' +
44
+ ' A tenantColumn alone only scopes checks — it expresses no conflict.\n' +
45
+ " Configure the conflict columns: exclusion: { arrayColumn: 'conflict_keys' }\n" +
46
+ " or exclusion: { blocksAllColumn: 'exclusive' }.\n",
47
+ )
48
+ }
49
+
50
+ if (config.arrayElementType !== undefined && config.arrayColumn === undefined) {
51
+ throw new Error(
52
+ '[pipework] exclusion.arrayElementType is set but arrayColumn is not.\n\n' +
53
+ ' arrayElementType only describes arrayColumn.\n' +
54
+ ' Add arrayColumn, or remove arrayElementType.\n',
55
+ )
56
+ }
57
+
58
+ const named = [config.arrayColumn, config.blocksAllColumn, config.tenantColumn]
59
+ .filter((c): c is string => c !== undefined)
60
+ for (const column of named) {
61
+ assertValidIdentifier(column, 'exclusion column')
62
+ if (QUEUE_BASE_COLUMNS.has(column)) {
63
+ throw new Error(
64
+ `[pipework] exclusion column "${column}" collides with a base queue column.\n\n` +
65
+ ` The queue table already owns: ${[...QUEUE_BASE_COLUMNS].join(', ')}\n` +
66
+ ' Pick a different column name.\n',
67
+ )
68
+ }
69
+ }
70
+ if (new Set(named).size !== named.length) {
71
+ throw new Error(
72
+ '[pipework] exclusion columns must be distinct.\n\n' +
73
+ ` Got: arrayColumn=${config.arrayColumn ?? '—'}, blocksAllColumn=${config.blocksAllColumn ?? '—'}, tenantColumn=${config.tenantColumn ?? '—'}\n` +
74
+ ' Each role needs its own column.\n',
75
+ )
76
+ }
77
+
78
+ return {
79
+ ...(config.arrayColumn !== undefined ? { arrayColumn: config.arrayColumn } : {}),
80
+ arrayElementType: config.arrayElementType ?? 'uuid',
81
+ ...(config.blocksAllColumn !== undefined ? { blocksAllColumn: config.blocksAllColumn } : {}),
82
+ ...(config.tenantColumn !== undefined ? { tenantColumn: config.tenantColumn } : {}),
83
+ }
84
+ }
85
+
86
+ /**
87
+ * The claimability predicate for the claim query's candidate SELECT. Pure
88
+ * identifiers — all quoted, no values — so the result composes as a raw SQL
89
+ * fragment. The candidate row is aliased `candidate`, concurrent rows `r`.
90
+ */
91
+ export function exclusionClaimClause(tableQ: string, exclusion: ResolvedExclusion): string {
92
+ const arr = exclusion.arrayColumn !== undefined ? quoteIdentifier(exclusion.arrayColumn, 'exclusion column') : undefined
93
+ const blocks = exclusion.blocksAllColumn !== undefined ? quoteIdentifier(exclusion.blocksAllColumn, 'exclusion column') : undefined
94
+ const tenant = exclusion.tenantColumn !== undefined ? quoteIdentifier(exclusion.tenantColumn, 'exclusion column') : undefined
95
+
96
+ const tenantScope = tenant !== undefined ? `r.${tenant} = candidate.${tenant} AND ` : ''
97
+ const noConcurrent = (condition: string): string =>
98
+ `NOT EXISTS (SELECT 1 FROM ${tableQ} r WHERE ${tenantScope}r.status IN ('claimed', 'running') AND ${condition})`
99
+
100
+ if (arr !== undefined && blocks !== undefined) {
101
+ return '(' +
102
+ `(candidate.${blocks} = false AND candidate.${arr} IS NULL)` +
103
+ ` OR (candidate.${blocks} = true AND ${noConcurrent(`(r.${arr} IS NOT NULL OR r.${blocks} = true)`)})` +
104
+ ` OR (candidate.${blocks} = false AND candidate.${arr} IS NOT NULL` +
105
+ ` AND ${noConcurrent(`r.${blocks} = true`)}` +
106
+ ` AND ${noConcurrent(`r.${arr} IS NOT NULL AND r.${arr} && candidate.${arr}`)})` +
107
+ ')'
108
+ }
109
+
110
+ if (arr !== undefined) {
111
+ return `(candidate.${arr} IS NULL OR ${noConcurrent(`r.${arr} IS NOT NULL AND r.${arr} && candidate.${arr}`)})`
112
+ }
113
+
114
+ // blocks-all only: participation reduces to the flag itself, so a false
115
+ // candidate never conflicts and a true candidate waits for true jobs.
116
+ return `(candidate.${blocks!} = false OR ${noConcurrent(`r.${blocks!} = true`)})`
117
+ }
@@ -0,0 +1,219 @@
1
+ import type { Manifold } from '../../core/pipework.js'
2
+ import type { Handler } from '../../request/di/types.js'
3
+ import type { TenantConfig } from '../../auth/tenant/types.js'
4
+ import { runInContext } from '../../request/context/store.js'
5
+ import { createJobContext } from '../../request/context/create.js'
6
+ import { executeInTransaction } from '../../request/context/run-in-transaction.js'
7
+ import { resolveAndExecute, resolveHandlerDatabases, buildCheckpoint } from '../../request/di/resolve.js'
8
+ import { isTracingEnabled } from '../../trace/entry/tracing-enabled.js'
9
+ import { openTrace } from '../../trace/entry/open-trace.js'
10
+ import { parentTraceRef } from '../../trace/entry/parent-trace.js'
11
+ import type { ParentTraceRef } from '../../trace/entry/open-trace.js'
12
+ import { finalizeTrace } from '../../trace/entry/finalize-trace.js'
13
+ import { JobAbortedError } from './errors.js'
14
+ import { randomUUID } from 'node:crypto'
15
+ import { serializeForTrace } from '../../trace/capture/bounded-serializer.js'
16
+
17
+ /** Default timeout for setting up a tenant job's database transaction(s). */
18
+ const DEFAULT_JOB_TRANSACTION_TIMEOUT_MS = 5000
19
+
20
+ export interface ExecuteJobOptions {
21
+ instance: Manifold
22
+ jobId?: string
23
+ jobType?: string
24
+ /** 1-based attempt number, exposed as `flow.jobAttempt`. */
25
+ attempt?: number
26
+ /** The job's attempt limit, exposed as `flow.jobMaxAttempts`. */
27
+ maxAttempts?: number
28
+ auth?: unknown
29
+ tenant?: string | null
30
+ /**
31
+ * Tenant config carrying custom `sessionVars`. When provided alongside
32
+ * `tenant`, the custom session variables are propagated in addition to
33
+ * `pipework.tenant_id` — matching the HTTP surface's behaviour.
34
+ */
35
+ tenantConfig?: TenantConfig | null
36
+ input?: unknown
37
+ /** Timeout for multi-database transaction setup when running a tenant job. */
38
+ transactionTimeoutMs?: number
39
+ /**
40
+ * The trace this job continues. Omitted: the trace on the active Flow, if any.
41
+ * `null`: a root trace even inside a Flow. The worker surface passes the
42
+ * trace recorded when the job was enqueued.
43
+ */
44
+ parent?: ParentTraceRef | null
45
+ /** The ingress kind for the opened trace — `'cron'` for schedule-fired jobs, `'job'` otherwise. */
46
+ entryKind?: 'job' | 'cron'
47
+ /**
48
+ * Set when this attempt follows one that ended without failing on its own (a
49
+ * reap or a hand-back): the attempt's trace opens with a `pipework.job.restart`
50
+ * external step naming the reason and the worker that held the previous claim.
51
+ */
52
+ restart?: { readonly reason: 'reaped' | 'handed-back' | 'later'; readonly previousWorkerId: string | null }
53
+ /**
54
+ * Ends the job at the caller's deadline. On abort the job's in-flight query is
55
+ * cancelled server-side so its transaction rolls back and its connection
56
+ * returns to the pool, and `executeJob` rejects — with `signal.reason` when
57
+ * that is an `Error`, otherwise a `JobAbortedError` (`name: 'AbortError'`)
58
+ * naming the job. A handler that ignores the cancelled query keeps running;
59
+ * the rejection is still delivered on time.
60
+ */
61
+ signal?: AbortSignal
62
+ }
63
+
64
+ export async function executeJob<TDeps extends Record<string, unknown>, TReturn>(
65
+ handler: Handler<TDeps, TReturn>,
66
+ options: ExecuteJobOptions,
67
+ ): Promise<TReturn> {
68
+ const label = jobLabel(options)
69
+ if (options.signal?.aborted === true) throw abortReason(options.signal, label)
70
+
71
+ const jobCtxOptions: Parameters<typeof createJobContext>[0] = {
72
+ instance: options.instance,
73
+ }
74
+ if (options.jobId !== undefined) jobCtxOptions.jobId = options.jobId
75
+ if (options.jobType !== undefined) jobCtxOptions.jobType = options.jobType
76
+ if (options.attempt !== undefined) jobCtxOptions.attempt = options.attempt
77
+ if (options.maxAttempts !== undefined) jobCtxOptions.maxAttempts = options.maxAttempts
78
+ if (options.auth !== undefined) jobCtxOptions.auth = options.auth
79
+ if (options.tenant !== undefined) jobCtxOptions.tenant = options.tenant
80
+ if (options.tenantConfig !== undefined) jobCtxOptions.tenantConfig = options.tenantConfig
81
+ if (isTracingEnabled(options.instance)) {
82
+ jobCtxOptions.trace = openTrace({
83
+ instance: options.instance,
84
+ entryKind: options.entryKind ?? 'job',
85
+ parent: options.parent !== undefined ? options.parent : parentTraceRef(),
86
+ tenant: options.tenant ?? null,
87
+ auth: options.auth ?? null,
88
+ requestId: options.jobId ?? null,
89
+ sessionId: null,
90
+ })
91
+ }
92
+
93
+ if (options.restart !== undefined && jobCtxOptions.trace !== undefined && jobCtxOptions.trace !== null) {
94
+ const now = new Date()
95
+ jobCtxOptions.trace.buffer.stageExternal({
96
+ id: randomUUID(),
97
+ parentStepId: null,
98
+ flowStepRef: 'external:pipework.job.restart',
99
+ status: 'ok',
100
+ startedAt: now,
101
+ completedAt: now,
102
+ durationMicros: 0n,
103
+ capturedInputs: [serializeForTrace({ reason: options.restart.reason, previousWorkerId: options.restart.previousWorkerId })],
104
+ error: null,
105
+ })
106
+ }
107
+
108
+ // The handler's own signal: aborted, with the error `executeJob` rejects with,
109
+ // whenever the job stops being the handler's while it may still be running.
110
+ const own = new AbortController()
111
+ const ctx = createJobContext(jobCtxOptions)
112
+ const databases = resolveHandlerDatabases(handler, options.instance)
113
+ const timeoutMs = options.transactionTimeoutMs ?? DEFAULT_JOB_TRANSACTION_TIMEOUT_MS
114
+
115
+ // Manual transaction mode: the framework opens no outer transaction. The
116
+ // handler owns its commit boundaries through `checkpoint`, which opens a fresh
117
+ // tenant-scoped transaction per call (re-establishing the tenant session vars
118
+ // so database-side RLS sees the tenant) and commits it independently.
119
+ if (handler.meta.jobTransaction === 'manual') {
120
+ const checkpoint = buildCheckpoint(
121
+ handler,
122
+ ctx,
123
+ databases,
124
+ options.tenantConfig ?? null,
125
+ timeoutMs,
126
+ options.signal,
127
+ own.signal,
128
+ )
129
+ return finalizeTrace(
130
+ options.instance,
131
+ ctx.trace,
132
+ untilAborted(
133
+ runInContext(ctx, () => resolveAndExecute(handler, options.input, undefined, undefined, { checkpoint, signal: own.signal })),
134
+ options.signal,
135
+ label,
136
+ own,
137
+ ),
138
+ )
139
+ }
140
+
141
+ const run = (): Promise<TReturn> => resolveAndExecute(handler, options.input, undefined, undefined, { signal: own.signal })
142
+
143
+ // No tenant: app-level scoping does not apply, so there is nothing to
144
+ // propagate to Postgres — run the handler directly as before.
145
+ if (ctx.tenant === null || databases.length === 0) {
146
+ return finalizeTrace(options.instance, ctx.trace, untilAborted(runInContext(ctx, run), options.signal, label, own))
147
+ }
148
+
149
+ // Tenant job: wrap in a transaction and propagate session vars so
150
+ // database-side RLS sees the tenant — consistent with the HTTP surface.
151
+ return finalizeTrace(
152
+ options.instance,
153
+ ctx.trace,
154
+ untilAborted(
155
+ executeInTransaction(
156
+ ctx,
157
+ databases,
158
+ options.tenantConfig ?? null,
159
+ timeoutMs,
160
+ run,
161
+ options.signal,
162
+ ),
163
+ options.signal,
164
+ label,
165
+ own,
166
+ ),
167
+ )
168
+ }
169
+
170
+ /** `[type] id`, `[type]`, `id`, or `(anonymous)` — whatever the caller gave us to name the job by. */
171
+ function jobLabel(options: ExecuteJobOptions): string {
172
+ const parts: string[] = []
173
+ if (options.jobType !== undefined) parts.push(`"${options.jobType}"`)
174
+ if (options.jobId !== undefined) parts.push(`(${options.jobId})`)
175
+ return parts.length === 0 ? '(anonymous)' : parts.join(' ')
176
+ }
177
+
178
+ /**
179
+ * The error an abort rejects with: the caller's own `Error` reason when they set
180
+ * one (the worker passes its timeout error this way), otherwise a
181
+ * `JobAbortedError` naming the job. `abort()` with no reason leaves a generic
182
+ * DOMException that names nothing — that is the case worth replacing.
183
+ */
184
+ function abortReason(signal: AbortSignal, label: string): Error {
185
+ const reason: unknown = signal.reason
186
+ const isDefaultReason =
187
+ typeof DOMException === 'function' && reason instanceof DOMException && reason.name === 'AbortError'
188
+
189
+ return reason instanceof Error && !isDefaultReason
190
+ ? reason
191
+ : new JobAbortedError(label, reason)
192
+ }
193
+
194
+ /**
195
+ * Rejects when the signal aborts, even if the handler is still running — the
196
+ * caller's deadline is the caller's, not the handler's. The work promise's own
197
+ * rejection is swallowed once we have rejected, so a later unwind (the cancelled
198
+ * query surfacing) does not become an unhandled rejection. The handler's own
199
+ * signal aborts with that same rejection first, so it sees the abort while it runs on.
200
+ */
201
+ function untilAborted<T>(work: Promise<T>, signal: AbortSignal | undefined, label: string, own: AbortController): Promise<T> {
202
+ if (signal === undefined) return work
203
+
204
+ return new Promise<T>((resolve, reject) => {
205
+ const onAbort = (): void => {
206
+ work.catch(() => {})
207
+ const reason = abortReason(signal, label)
208
+ own.abort(reason)
209
+ reject(reason)
210
+ }
211
+ if (signal.aborted) {
212
+ onAbort()
213
+ return
214
+ }
215
+ signal.addEventListener('abort', onAbort, { once: true })
216
+ work.then(resolve, reject).finally(() => { signal.removeEventListener('abort', onAbort) })
217
+ })
218
+ }
219
+
@@ -0,0 +1,10 @@
1
+ export { executeJob } from './execute.js'
2
+ export type { ExecuteJobOptions } from './execute.js'
3
+ export { JobAbortedError, JobLaterError, JobPermanentError } from './errors.js'
4
+ export { createQueue } from './queue.js'
5
+ export type { Queue, QueueConfig, EnqueueOptions, EnqueueExclusion, ClaimedJob, JobClaim, JobClaimReason, ClaimedExclusion, DeadLetterInfo, ReapedJob, FailedAttempt, QueueTotals, QueueTypeTotals, JobResult, BackoffConfig } from './queue.js'
6
+ export type { ExclusionConfig } from './exclusion.js'
7
+ export type { WaitOptions, WaitResult, ListenClient, ListenHandle } from './listener.js'
8
+ export { parseCron, nextTick } from './cron.js'
9
+ export type { CronSchedule } from './cron.js'
10
+ export type { ScheduleSpec, ScheduleInfo, SchedulerOptions } from './scheduler.js'