pipework 0.252.0 → 0.253.0

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 (695) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/infra/support/handle.d.ts +8 -1
  3. package/dist/infra/support/handle.d.ts.map +1 -1
  4. package/dist/infra/support/handle.js +9 -2
  5. package/dist/infra/support/handle.js.map +1 -1
  6. package/dist/infra/support/namespace.d.ts.map +1 -1
  7. package/package.json +4 -3
  8. package/src/async/jobs/abortable-delay.ts +18 -0
  9. package/src/async/jobs/claims.ts +52 -0
  10. package/src/async/jobs/cron.ts +179 -0
  11. package/src/async/jobs/errors.ts +56 -0
  12. package/src/async/jobs/exclusion.ts +117 -0
  13. package/src/async/jobs/execute.ts +219 -0
  14. package/src/async/jobs/index.ts +10 -0
  15. package/src/async/jobs/listener.ts +135 -0
  16. package/src/async/jobs/namespace.ts +20 -0
  17. package/src/async/jobs/queue-door.ts +44 -0
  18. package/src/async/jobs/queue.ts +1012 -0
  19. package/src/async/jobs/run-script.ts +67 -0
  20. package/src/async/jobs/scheduler.ts +218 -0
  21. package/src/async/jobs/schedules-table.ts +37 -0
  22. package/src/async/jobs/serialize-error.ts +48 -0
  23. package/src/async/jobs/table.ts +191 -0
  24. package/src/async/pipeline/define.ts +53 -0
  25. package/src/async/pipeline/errors.ts +35 -0
  26. package/src/async/pipeline/execute.ts +53 -0
  27. package/src/async/pipeline/index.ts +13 -0
  28. package/src/async/pipeline/namespace.ts +12 -0
  29. package/src/async/pipeline/resume.ts +67 -0
  30. package/src/async/pipeline/run-steps.ts +98 -0
  31. package/src/async/pipeline/types.ts +57 -0
  32. package/src/async/state-machine/define.ts +64 -0
  33. package/src/async/state-machine/errors.ts +29 -0
  34. package/src/async/state-machine/index.ts +3 -0
  35. package/src/async/state-machine/namespace.ts +12 -0
  36. package/src/async/state-machine/transition.ts +90 -0
  37. package/src/async/state-machine/types.ts +37 -0
  38. package/src/async/steps/errors.ts +31 -0
  39. package/src/async/steps/graph.ts +1214 -0
  40. package/src/async/steps/hash.ts +40 -0
  41. package/src/async/steps/index.ts +7 -0
  42. package/src/async/steps/namespace.ts +7 -0
  43. package/src/async/steps/table.ts +97 -0
  44. package/src/async/steps/types.ts +318 -0
  45. package/src/audit/chain/index.ts +9 -0
  46. package/src/audit/chain/install.ts +113 -0
  47. package/src/audit/chain/retire.ts +52 -0
  48. package/src/audit/chain/verify.ts +257 -0
  49. package/src/audit/query/cursor.ts +37 -0
  50. package/src/audit/query/index.ts +9 -0
  51. package/src/audit/query/query.ts +223 -0
  52. package/src/audit/schema/audit-record-fields.ts +68 -0
  53. package/src/audit/schema/audit-record.ts +23 -0
  54. package/src/auth/auth/audit.ts +31 -0
  55. package/src/auth/auth/chain.ts +84 -0
  56. package/src/auth/auth/cookie.ts +136 -0
  57. package/src/auth/auth/email-links.ts +311 -0
  58. package/src/auth/auth/guard.ts +128 -0
  59. package/src/auth/auth/index.ts +18 -0
  60. package/src/auth/auth/multi-org.ts +337 -0
  61. package/src/auth/auth/namespace.ts +34 -0
  62. package/src/auth/auth/parse-expiry.ts +13 -0
  63. package/src/auth/auth/passwords.ts +110 -0
  64. package/src/auth/auth/schema.ts +110 -0
  65. package/src/auth/auth/sessions.ts +565 -0
  66. package/src/auth/auth/sign-in.ts +156 -0
  67. package/src/auth/auth/signing-keys.ts +69 -0
  68. package/src/auth/auth/types.ts +26 -0
  69. package/src/auth/auth/uuid.ts +10 -0
  70. package/src/auth/rbac/cache.ts +55 -0
  71. package/src/auth/rbac/check.ts +30 -0
  72. package/src/auth/rbac/create.ts +35 -0
  73. package/src/auth/rbac/index.ts +5 -0
  74. package/src/auth/rbac/middleware.ts +20 -0
  75. package/src/auth/rbac/namespace.ts +15 -0
  76. package/src/auth/rbac/resolve.ts +31 -0
  77. package/src/auth/rbac/schema.sql +31 -0
  78. package/src/auth/rbac/seed.ts +67 -0
  79. package/src/auth/rbac/tables.ts +32 -0
  80. package/src/auth/rbac/types.ts +65 -0
  81. package/src/auth/tenant/extract.ts +33 -0
  82. package/src/auth/tenant/in-tenant.ts +49 -0
  83. package/src/auth/tenant/index.ts +7 -0
  84. package/src/auth/tenant/namespace.ts +23 -0
  85. package/src/auth/tenant/propagate.ts +20 -0
  86. package/src/auth/tenant/rls.ts +120 -0
  87. package/src/auth/tenant/scope.ts +33 -0
  88. package/src/auth/tenant/scoped-db.ts +581 -0
  89. package/src/auth/tenant/types.ts +14 -0
  90. package/src/auth/tenant/validate.ts +27 -0
  91. package/src/cli/commands/add.ts +158 -0
  92. package/src/cli/commands/alerts.ts +98 -0
  93. package/src/cli/commands/check.ts +1418 -0
  94. package/src/cli/commands/codemod.ts +78 -0
  95. package/src/cli/commands/db.ts +356 -0
  96. package/src/cli/commands/dev.ts +101 -0
  97. package/src/cli/commands/generate.ts +75 -0
  98. package/src/cli/commands/init.ts +36 -0
  99. package/src/cli/commands/install.ts +28 -0
  100. package/src/cli/commands/lint.ts +62 -0
  101. package/src/cli/commands/migrate.ts +132 -0
  102. package/src/cli/commands/openapi.ts +63 -0
  103. package/src/cli/commands/remove.ts +72 -0
  104. package/src/cli/commands/run.ts +50 -0
  105. package/src/cli/commands/scope.ts +54 -0
  106. package/src/cli/commands/serve.ts +68 -0
  107. package/src/cli/commands/shard.ts +31 -0
  108. package/src/cli/commands/shared/config-pipework-version.ts +28 -0
  109. package/src/cli/commands/shared/find-config.ts +22 -0
  110. package/src/cli/commands/shared/load-config.ts +35 -0
  111. package/src/cli/commands/shared/pnpm-install.ts +95 -0
  112. package/src/cli/commands/shared/report-removed.ts +8 -0
  113. package/src/cli/commands/sync.ts +32 -0
  114. package/src/cli/commands/test.ts +307 -0
  115. package/src/cli/commands/upgrade.ts +48 -0
  116. package/src/cli/dev-bootstrap.ts +24 -0
  117. package/src/cli/errors.ts +10 -0
  118. package/src/cli/index.ts +303 -0
  119. package/src/cli/output.ts +17 -0
  120. package/src/cli/port.ts +15 -0
  121. package/src/cli/surface-kinds.ts +20 -0
  122. package/src/client/index.ts +4 -0
  123. package/src/client/poll.ts +130 -0
  124. package/src/client/report-fault.ts +119 -0
  125. package/src/core/config/app-pool.ts +19 -0
  126. package/src/core/config/aws-env.ts +29 -0
  127. package/src/core/config/base-dir.ts +24 -0
  128. package/src/core/config/discover.ts +64 -0
  129. package/src/core/config/env-resolve.ts +87 -0
  130. package/src/core/config/env-types.ts +116 -0
  131. package/src/core/config/env.ts +55 -0
  132. package/src/core/config/errors.ts +9 -0
  133. package/src/core/config/import-config.ts +40 -0
  134. package/src/core/config/index.ts +8 -0
  135. package/src/core/config/load.ts +417 -0
  136. package/src/core/config/namespace.ts +14 -0
  137. package/src/core/config/resolve.ts +195 -0
  138. package/src/core/config/schema.ts +488 -0
  139. package/src/core/config/statement-observer.ts +48 -0
  140. package/src/core/config/ts-inline-hooks.ts +75 -0
  141. package/src/core/config/ts-register.ts +4 -0
  142. package/src/core/config/ts-resolve-hooks.ts +101 -0
  143. package/src/core/errors/base.ts +49 -0
  144. package/src/core/errors/http.ts +146 -0
  145. package/src/core/errors/index.ts +2 -0
  146. package/src/core/errors/namespace.ts +31 -0
  147. package/src/core/lifecycle/drain.ts +33 -0
  148. package/src/core/lifecycle/health.ts +72 -0
  149. package/src/core/lifecycle/index.ts +4 -0
  150. package/src/core/lifecycle/namespace.ts +7 -0
  151. package/src/core/lifecycle/startup.ts +102 -0
  152. package/src/core/lifecycle/types.ts +36 -0
  153. package/src/core/logging/context.ts +60 -0
  154. package/src/core/logging/error-chain.ts +68 -0
  155. package/src/core/logging/index.ts +5 -0
  156. package/src/core/logging/logger.ts +65 -0
  157. package/src/core/logging/namespace.ts +16 -0
  158. package/src/core/logging/proxy.ts +22 -0
  159. package/src/core/logging/redact-match.ts +24 -0
  160. package/src/core/logging/types.ts +47 -0
  161. package/src/core/pipework.ts +566 -0
  162. package/src/core/runtime/broker.ts +69 -0
  163. package/src/core/surface/http.ts +133 -0
  164. package/src/core/surface/index.ts +11 -0
  165. package/src/core/surface/job-timeout.ts +40 -0
  166. package/src/core/surface/namespace.ts +13 -0
  167. package/src/core/surface/script.ts +33 -0
  168. package/src/core/surface/start.ts +142 -0
  169. package/src/core/surface/types.ts +225 -0
  170. package/src/core/surface/validate.ts +88 -0
  171. package/src/core/surface/worker.ts +528 -0
  172. package/src/core/validation/connectivity.ts +49 -0
  173. package/src/core/validation/domain.ts +99 -0
  174. package/src/core/validation/index.ts +5 -0
  175. package/src/core/validation/queue-tables.ts +312 -0
  176. package/src/core/validation/rls-role.ts +138 -0
  177. package/src/core/validation/startup.ts +51 -0
  178. package/src/core/validation/surfaces.ts +65 -0
  179. package/src/core/validation/types.ts +25 -0
  180. package/src/data/db/advisory-lock.ts +55 -0
  181. package/src/data/db/aggregates.ts +172 -0
  182. package/src/data/db/array-elements.ts +111 -0
  183. package/src/data/db/bulk-set.ts +53 -0
  184. package/src/data/db/col/index.ts +14 -0
  185. package/src/data/db/composed.ts +53 -0
  186. package/src/data/db/db.ts +276 -0
  187. package/src/data/db/excluded.ts +16 -0
  188. package/src/data/db/expressions.ts +473 -0
  189. package/src/data/db/filter.ts +90 -0
  190. package/src/data/db/function-source.ts +114 -0
  191. package/src/data/db/identifiers.ts +16 -0
  192. package/src/data/db/idx/index.ts +9 -0
  193. package/src/data/db/in-list.ts +49 -0
  194. package/src/data/db/index.ts +9 -0
  195. package/src/data/db/insert-split.ts +137 -0
  196. package/src/data/db/instrumentation.ts +82 -0
  197. package/src/data/db/maintenance.ts +28 -0
  198. package/src/data/db/namespace.ts +107 -0
  199. package/src/data/db/owner-labels.ts +9 -0
  200. package/src/data/db/pool.ts +187 -0
  201. package/src/data/db/query-label.ts +13 -0
  202. package/src/data/db/query-watch.ts +116 -0
  203. package/src/data/db/raw-client-warning.ts +37 -0
  204. package/src/data/db/readonly.ts +23 -0
  205. package/src/data/db/reservation.ts +151 -0
  206. package/src/data/db/schema-features.ts +14 -0
  207. package/src/data/db/serializable.ts +83 -0
  208. package/src/data/db/sql.ts +1 -0
  209. package/src/data/db/timeouts.ts +76 -0
  210. package/src/data/db/types.ts +18 -0
  211. package/src/data/db/unbound.ts +33 -0
  212. package/src/data/db/values.ts +29 -0
  213. package/src/data/domain/brand.ts +15 -0
  214. package/src/data/domain/build-factory.ts +193 -0
  215. package/src/data/domain/build-schema.ts +161 -0
  216. package/src/data/domain/build-table.ts +355 -0
  217. package/src/data/domain/define.ts +239 -0
  218. package/src/data/domain/external-registry.ts +34 -0
  219. package/src/data/domain/external.ts +77 -0
  220. package/src/data/domain/field.ts +279 -0
  221. package/src/data/domain/index.ts +13 -0
  222. package/src/data/domain/naming.ts +6 -0
  223. package/src/data/domain/projections.ts +57 -0
  224. package/src/data/domain/trace-safe-projection.ts +31 -0
  225. package/src/data/domain/traits.ts +108 -0
  226. package/src/data/domain/types.ts +289 -0
  227. package/src/data/jsonb/composed.ts +18 -0
  228. package/src/data/jsonb/index.ts +1 -0
  229. package/src/data/jsonb/namespace.ts +30 -0
  230. package/src/data/jsonb/query.ts +86 -0
  231. package/src/data/migrate/append-only-generate.ts +47 -0
  232. package/src/data/migrate/applied.ts +47 -0
  233. package/src/data/migrate/apply.ts +309 -0
  234. package/src/data/migrate/check.ts +119 -0
  235. package/src/data/migrate/diff.ts +357 -0
  236. package/src/data/migrate/door-generate.ts +130 -0
  237. package/src/data/migrate/framework-rls.ts +58 -0
  238. package/src/data/migrate/generate.ts +201 -0
  239. package/src/data/migrate/history.ts +215 -0
  240. package/src/data/migrate/index.ts +9 -0
  241. package/src/data/migrate/internal-definitions.ts +175 -0
  242. package/src/data/migrate/post-process.ts +73 -0
  243. package/src/data/migrate/pragma.ts +73 -0
  244. package/src/data/migrate/provision-framework.ts +147 -0
  245. package/src/data/migrate/rls-generate.ts +61 -0
  246. package/src/data/migrate/run.ts +124 -0
  247. package/src/data/migrate/safety.ts +167 -0
  248. package/src/data/migrate/snapshot.ts +368 -0
  249. package/src/data/migrate/sql-emit.ts +392 -0
  250. package/src/data/migrate/statements.ts +312 -0
  251. package/src/data/query/alias.ts +126 -0
  252. package/src/data/query/batch.ts +8 -0
  253. package/src/data/query/cache/core/cache.ts +78 -0
  254. package/src/data/query/cache/core/index.ts +1 -0
  255. package/src/data/query/cache/core/types.ts +29 -0
  256. package/src/data/query/cache/readme.md +230 -0
  257. package/src/data/query/casing.ts +76 -0
  258. package/src/data/query/collation.ts +11 -0
  259. package/src/data/query/column-builder.ts +370 -0
  260. package/src/data/query/column.ts +150 -0
  261. package/src/data/query/entity.ts +42 -0
  262. package/src/data/query/errors.ts +33 -0
  263. package/src/data/query/index.ts +14 -0
  264. package/src/data/query/logger.ts +47 -0
  265. package/src/data/query/operations.ts +45 -0
  266. package/src/data/query/pg-core/alias.ts +12 -0
  267. package/src/data/query/pg-core/checks.ts +32 -0
  268. package/src/data/query/pg-core/columns/all.ts +71 -0
  269. package/src/data/query/pg-core/columns/bigint.ts +110 -0
  270. package/src/data/query/pg-core/columns/bigserial.ts +128 -0
  271. package/src/data/query/pg-core/columns/boolean.ts +43 -0
  272. package/src/data/query/pg-core/columns/char.ts +85 -0
  273. package/src/data/query/pg-core/columns/cidr.ts +43 -0
  274. package/src/data/query/pg-core/columns/common.ts +366 -0
  275. package/src/data/query/pg-core/columns/custom.ts +232 -0
  276. package/src/data/query/pg-core/columns/date.common.ts +15 -0
  277. package/src/data/query/pg-core/columns/date.ts +112 -0
  278. package/src/data/query/pg-core/columns/double-precision.ts +55 -0
  279. package/src/data/query/pg-core/columns/enum.ts +201 -0
  280. package/src/data/query/pg-core/columns/index.ts +35 -0
  281. package/src/data/query/pg-core/columns/inet.ts +43 -0
  282. package/src/data/query/pg-core/columns/int.common.ts +57 -0
  283. package/src/data/query/pg-core/columns/integer.ts +53 -0
  284. package/src/data/query/pg-core/columns/interval.ts +83 -0
  285. package/src/data/query/pg-core/columns/json.ts +58 -0
  286. package/src/data/query/pg-core/columns/jsonb.ts +56 -0
  287. package/src/data/query/pg-core/columns/line.ts +117 -0
  288. package/src/data/query/pg-core/columns/macaddr.ts +43 -0
  289. package/src/data/query/pg-core/columns/macaddr8.ts +43 -0
  290. package/src/data/query/pg-core/columns/numeric.ts +227 -0
  291. package/src/data/query/pg-core/columns/point.ts +127 -0
  292. package/src/data/query/pg-core/columns/postgis_extension/geometry.ts +119 -0
  293. package/src/data/query/pg-core/columns/postgis_extension/utils.ts +47 -0
  294. package/src/data/query/pg-core/columns/real.ts +58 -0
  295. package/src/data/query/pg-core/columns/serial.ts +55 -0
  296. package/src/data/query/pg-core/columns/smallint.ts +53 -0
  297. package/src/data/query/pg-core/columns/smallserial.ts +60 -0
  298. package/src/data/query/pg-core/columns/text.ts +67 -0
  299. package/src/data/query/pg-core/columns/time.ts +72 -0
  300. package/src/data/query/pg-core/columns/timestamp.ts +163 -0
  301. package/src/data/query/pg-core/columns/uuid.ts +51 -0
  302. package/src/data/query/pg-core/columns/varchar.ts +89 -0
  303. package/src/data/query/pg-core/columns/vector_extension/bit.ts +68 -0
  304. package/src/data/query/pg-core/columns/vector_extension/halfvec.ts +80 -0
  305. package/src/data/query/pg-core/columns/vector_extension/sparsevec.ts +67 -0
  306. package/src/data/query/pg-core/columns/vector_extension/vector.ts +80 -0
  307. package/src/data/query/pg-core/db.ts +674 -0
  308. package/src/data/query/pg-core/dialect.ts +1404 -0
  309. package/src/data/query/pg-core/expressions.ts +25 -0
  310. package/src/data/query/pg-core/foreign-keys.ts +130 -0
  311. package/src/data/query/pg-core/index.ts +21 -0
  312. package/src/data/query/pg-core/indexes.ts +276 -0
  313. package/src/data/query/pg-core/policies.ts +56 -0
  314. package/src/data/query/pg-core/primary-keys.ts +62 -0
  315. package/src/data/query/pg-core/query-builders/count.ts +86 -0
  316. package/src/data/query/pg-core/query-builders/delete.ts +293 -0
  317. package/src/data/query/pg-core/query-builders/index.ts +7 -0
  318. package/src/data/query/pg-core/query-builders/insert.ts +452 -0
  319. package/src/data/query/pg-core/query-builders/query-builder.ts +123 -0
  320. package/src/data/query/pg-core/query-builders/query.ts +157 -0
  321. package/src/data/query/pg-core/query-builders/raw.ts +49 -0
  322. package/src/data/query/pg-core/query-builders/refresh-materialized-view.ts +108 -0
  323. package/src/data/query/pg-core/query-builders/select.ts +1346 -0
  324. package/src/data/query/pg-core/query-builders/select.types.ts +437 -0
  325. package/src/data/query/pg-core/query-builders/update.ts +626 -0
  326. package/src/data/query/pg-core/roles.ts +41 -0
  327. package/src/data/query/pg-core/schema.ts +72 -0
  328. package/src/data/query/pg-core/sequence.ts +41 -0
  329. package/src/data/query/pg-core/session.ts +292 -0
  330. package/src/data/query/pg-core/subquery.ts +46 -0
  331. package/src/data/query/pg-core/table.ts +252 -0
  332. package/src/data/query/pg-core/unique-constraint.ts +73 -0
  333. package/src/data/query/pg-core/utils/array.ts +95 -0
  334. package/src/data/query/pg-core/utils/index.ts +1 -0
  335. package/src/data/query/pg-core/utils.ts +104 -0
  336. package/src/data/query/pg-core/view-base.ts +14 -0
  337. package/src/data/query/pg-core/view-common.ts +1 -0
  338. package/src/data/query/pg-core/view.ts +435 -0
  339. package/src/data/query/pg-core/with-builder.ts +41 -0
  340. package/src/data/query/postgres-js/README.md +46 -0
  341. package/src/data/query/postgres-js/array-parser.ts +45 -0
  342. package/src/data/query/postgres-js/driver-error-boundary.ts +149 -0
  343. package/src/data/query/postgres-js/driver.ts +163 -0
  344. package/src/data/query/postgres-js/index.ts +2 -0
  345. package/src/data/query/postgres-js/session.ts +234 -0
  346. package/src/data/query/primary-key.ts +11 -0
  347. package/src/data/query/query-builders/query-builder.ts +19 -0
  348. package/src/data/query/query-builders/select.types.ts +175 -0
  349. package/src/data/query/query-promise.ts +35 -0
  350. package/src/data/query/relations.ts +725 -0
  351. package/src/data/query/runnable-query.ts +12 -0
  352. package/src/data/query/selection-proxy.ts +121 -0
  353. package/src/data/query/session.ts +8 -0
  354. package/src/data/query/sql/expressions/conditions.ts +741 -0
  355. package/src/data/query/sql/expressions/index.ts +2 -0
  356. package/src/data/query/sql/expressions/select.ts +45 -0
  357. package/src/data/query/sql/functions/aggregate.ts +129 -0
  358. package/src/data/query/sql/functions/index.ts +2 -0
  359. package/src/data/query/sql/functions/vector.ts +178 -0
  360. package/src/data/query/sql/index.ts +3 -0
  361. package/src/data/query/sql/sql.ts +794 -0
  362. package/src/data/query/subquery.ts +53 -0
  363. package/src/data/query/table.ts +208 -0
  364. package/src/data/query/table.utils.ts +2 -0
  365. package/src/data/query/tracing-utils.ts +3 -0
  366. package/src/data/query/tracing.ts +11 -0
  367. package/src/data/query/utils.ts +357 -0
  368. package/src/data/query/version.ts +4 -0
  369. package/src/data/query/view-common.ts +1 -0
  370. package/src/data/schema/branded.ts +13 -0
  371. package/src/data/schema/generated/coerce.ts +5 -0
  372. package/src/data/schema/generated/combinator.ts +6 -0
  373. package/src/data/schema/generated/encoding.ts +5 -0
  374. package/src/data/schema/generated/error.ts +6 -0
  375. package/src/data/schema/generated/format.ts +5 -0
  376. package/src/data/schema/generated/type-constructor.ts +10 -0
  377. package/src/data/schema/generated/type.ts +6 -0
  378. package/src/data/schema/index.ts +6 -0
  379. package/src/data/schema/json-schema.ts +33 -0
  380. package/src/data/schema/namespace.ts +55 -0
  381. package/src/data/schema/parse.ts +39 -0
  382. package/src/data/schema/types.ts +39 -0
  383. package/src/data/temporal/append-only.ts +134 -0
  384. package/src/data/temporal/close.ts +27 -0
  385. package/src/data/temporal/columns.ts +10 -0
  386. package/src/data/temporal/definition-queries.ts +70 -0
  387. package/src/data/temporal/errors.ts +10 -0
  388. package/src/data/temporal/get-current.ts +22 -0
  389. package/src/data/temporal/index.ts +9 -0
  390. package/src/data/temporal/namespace.ts +36 -0
  391. package/src/data/temporal/query.ts +25 -0
  392. package/src/data/temporal/resolve.ts +17 -0
  393. package/src/data/temporal/revise.ts +67 -0
  394. package/src/data/temporal/types.ts +22 -0
  395. package/src/data/valve/artifact.ts +33 -0
  396. package/src/data/valve/contract-diff.ts +21 -0
  397. package/src/data/valve/cross.ts +57 -0
  398. package/src/data/valve/crossing-ledger.ts +50 -0
  399. package/src/data/valve/decision.ts +44 -0
  400. package/src/data/valve/durable-crossing.ts +52 -0
  401. package/src/data/valve/execute-crossing.ts +77 -0
  402. package/src/data/valve/faucet.ts +56 -0
  403. package/src/data/valve/gate.ts +114 -0
  404. package/src/data/valve/graph.ts +77 -0
  405. package/src/data/valve/index.ts +53 -0
  406. package/src/data/valve/namespace.ts +57 -0
  407. package/src/data/valve/registry.ts +50 -0
  408. package/src/data/valve/schema/valve-crossing-fields.ts +23 -0
  409. package/src/data/valve/schema/valve-crossing.ts +9 -0
  410. package/src/data/valve/supply.ts +154 -0
  411. package/src/data/valve/types.ts +143 -0
  412. package/src/data/vector/columns.ts +27 -0
  413. package/src/data/vector/index.ts +4 -0
  414. package/src/data/vector/namespace.ts +33 -0
  415. package/src/data/vector/query.ts +85 -0
  416. package/src/data/vector/validate.ts +16 -0
  417. package/src/data/write/audit/actor.ts +15 -0
  418. package/src/data/write/audit/audit-columns.ts +18 -0
  419. package/src/data/write/audit/audit-select.ts +111 -0
  420. package/src/data/write/audit/bound-transaction.ts +14 -0
  421. package/src/data/write/audit/cte-compile.ts +32 -0
  422. package/src/data/write/audit/decode-returning.ts +47 -0
  423. package/src/data/write/audit/final-select.ts +43 -0
  424. package/src/data/write/audit/infra-audit.ts +36 -0
  425. package/src/data/write/audit/primary-key.ts +65 -0
  426. package/src/data/write/audit/projection.ts +41 -0
  427. package/src/data/write/audit/read-touches.ts +86 -0
  428. package/src/data/write/audit/touch-match.ts +78 -0
  429. package/src/data/write/audit/verb-delete.ts +62 -0
  430. package/src/data/write/audit/verb-insert.ts +36 -0
  431. package/src/data/write/audit/verb-select.ts +47 -0
  432. package/src/data/write/audit/verb-update.ts +60 -0
  433. package/src/data/write/audit/verb-upsert.ts +104 -0
  434. package/src/data/write/conflict.ts +43 -0
  435. package/src/data/write/delete.ts +38 -0
  436. package/src/data/write/execute.ts +243 -0
  437. package/src/data/write/index.ts +11 -0
  438. package/src/data/write/insert.ts +63 -0
  439. package/src/data/write/state.ts +43 -0
  440. package/src/data/write/update.ts +54 -0
  441. package/src/data/write/upsert.ts +58 -0
  442. package/src/data/write/values.ts +19 -0
  443. package/src/index.ts +230 -0
  444. package/src/infra/access-links/code.ts +70 -0
  445. package/src/infra/access-links/handle.ts +892 -0
  446. package/src/infra/access-links/index.ts +9 -0
  447. package/src/infra/access-links/namespace.ts +30 -0
  448. package/src/infra/access-links/person-check.ts +177 -0
  449. package/src/infra/access-links/schema.ts +71 -0
  450. package/src/infra/alerts/async-sources.ts +231 -0
  451. package/src/infra/alerts/audit.ts +36 -0
  452. package/src/infra/alerts/beat.ts +123 -0
  453. package/src/infra/alerts/client-faults.ts +111 -0
  454. package/src/infra/alerts/faults.ts +156 -0
  455. package/src/infra/alerts/handle.ts +778 -0
  456. package/src/infra/alerts/http.ts +192 -0
  457. package/src/infra/alerts/index.ts +12 -0
  458. package/src/infra/alerts/infra-sources.ts +180 -0
  459. package/src/infra/alerts/namespace.ts +81 -0
  460. package/src/infra/alerts/redact.ts +21 -0
  461. package/src/infra/alerts/request-faults.ts +41 -0
  462. package/src/infra/alerts/schema.ts +124 -0
  463. package/src/infra/alerts/sinks.ts +125 -0
  464. package/src/infra/alerts/source-options.ts +26 -0
  465. package/src/infra/alerts/sources.ts +503 -0
  466. package/src/infra/alerts/subsystem-sources.ts +137 -0
  467. package/src/infra/audit/emit.ts +87 -0
  468. package/src/infra/audit/index.ts +2 -0
  469. package/src/infra/audit/namespace.ts +22 -0
  470. package/src/infra/audit/schema.sql +35 -0
  471. package/src/infra/audit/types.ts +18 -0
  472. package/src/infra/aws/credentials.ts +147 -0
  473. package/src/infra/aws/sigv4.ts +140 -0
  474. package/src/infra/cache/create.ts +58 -0
  475. package/src/infra/cache/entry.ts +81 -0
  476. package/src/infra/cache/index.ts +4 -0
  477. package/src/infra/cache/namespace.ts +10 -0
  478. package/src/infra/cache/tenant.ts +93 -0
  479. package/src/infra/cache/types.ts +24 -0
  480. package/src/infra/crawl/audit.ts +35 -0
  481. package/src/infra/crawl/errors.ts +25 -0
  482. package/src/infra/crawl/handle.ts +693 -0
  483. package/src/infra/crawl/index.ts +9 -0
  484. package/src/infra/crawl/links.ts +160 -0
  485. package/src/infra/crawl/namespace.ts +36 -0
  486. package/src/infra/crawl/robots.ts +100 -0
  487. package/src/infra/crawl/schema.ts +89 -0
  488. package/src/infra/credit-line/handle.ts +883 -0
  489. package/src/infra/credit-line/index.ts +6 -0
  490. package/src/infra/credit-line/namespace.ts +7 -0
  491. package/src/infra/credit-line/schema.ts +96 -0
  492. package/src/infra/credits/handle.ts +706 -0
  493. package/src/infra/credits/index.ts +5 -0
  494. package/src/infra/credits/namespace.ts +7 -0
  495. package/src/infra/credits/schema.ts +83 -0
  496. package/src/infra/email/audit.ts +36 -0
  497. package/src/infra/email/inbound.ts +622 -0
  498. package/src/infra/email/index.ts +11 -0
  499. package/src/infra/email/mail.ts +517 -0
  500. package/src/infra/email/mime.ts +447 -0
  501. package/src/infra/email/namespace.ts +22 -0
  502. package/src/infra/email/providers.ts +111 -0
  503. package/src/infra/email/schema.ts +96 -0
  504. package/src/infra/email/sns.ts +200 -0
  505. package/src/infra/email/unsubscribe.ts +44 -0
  506. package/src/infra/fetch/address.ts +88 -0
  507. package/src/infra/fetch/connect-retry.ts +87 -0
  508. package/src/infra/fetch/handle.ts +329 -0
  509. package/src/infra/fetch/index.ts +7 -0
  510. package/src/infra/fetch/namespace.ts +70 -0
  511. package/src/infra/idempotency/index.ts +3 -0
  512. package/src/infra/idempotency/middleware.ts +87 -0
  513. package/src/infra/idempotency/store.ts +92 -0
  514. package/src/infra/idempotency/types.ts +30 -0
  515. package/src/infra/join-requests/handle.ts +312 -0
  516. package/src/infra/join-requests/index.ts +2 -0
  517. package/src/infra/join-requests/namespace.ts +7 -0
  518. package/src/infra/join-requests/schema.ts +33 -0
  519. package/src/infra/outbox/core.ts +165 -0
  520. package/src/infra/quota/errors.ts +32 -0
  521. package/src/infra/quota/handle.ts +215 -0
  522. package/src/infra/quota/index.ts +5 -0
  523. package/src/infra/quota/namespace.ts +7 -0
  524. package/src/infra/quota/schema.ts +15 -0
  525. package/src/infra/storage/backend.ts +34 -0
  526. package/src/infra/storage/handle.ts +513 -0
  527. package/src/infra/storage/index.ts +9 -0
  528. package/src/infra/storage/local.ts +104 -0
  529. package/src/infra/storage/namespace.ts +13 -0
  530. package/src/infra/storage/s3.ts +257 -0
  531. package/src/infra/storage/schema.ts +24 -0
  532. package/src/infra/support/handle.ts +869 -0
  533. package/src/infra/support/http.ts +229 -0
  534. package/src/infra/support/index.ts +7 -0
  535. package/src/infra/support/namespace.ts +12 -0
  536. package/src/infra/support/schema.ts +96 -0
  537. package/src/infra/webhook/inbound.ts +45 -0
  538. package/src/infra/webhook/index.ts +5 -0
  539. package/src/infra/webhook/namespace.ts +24 -0
  540. package/src/infra/webhook/outbound.ts +315 -0
  541. package/src/infra/webhook/sign.ts +32 -0
  542. package/src/infra/webhook/verify.ts +82 -0
  543. package/src/invariants/assert.ts +26 -0
  544. package/src/invariants/index.ts +1 -0
  545. package/src/lint/config.ts +56 -0
  546. package/src/lint/doctrine.ts +163 -0
  547. package/src/lint/include.ts +97 -0
  548. package/src/lint/index.ts +3 -0
  549. package/src/lint/preset.ts +10 -0
  550. package/src/lint/resolver.ts +218 -0
  551. package/src/lint/rules/no-reexports.ts +46 -0
  552. package/src/request/behavior/audited.ts +85 -0
  553. package/src/request/behavior/cached.ts +62 -0
  554. package/src/request/behavior/compose.ts +28 -0
  555. package/src/request/behavior/index.ts +5 -0
  556. package/src/request/behavior/namespace.ts +16 -0
  557. package/src/request/behavior/types.ts +26 -0
  558. package/src/request/behavior/versioned.ts +54 -0
  559. package/src/request/context/create.ts +103 -0
  560. package/src/request/context/guard.ts +49 -0
  561. package/src/request/context/index.ts +4 -0
  562. package/src/request/context/run-in-transaction.ts +200 -0
  563. package/src/request/context/store.ts +28 -0
  564. package/src/request/context/types.ts +50 -0
  565. package/src/request/di/builder.ts +535 -0
  566. package/src/request/di/index.ts +8 -0
  567. package/src/request/di/resolve.ts +271 -0
  568. package/src/request/di/types.ts +262 -0
  569. package/src/request/fitting/namespace.ts +7 -0
  570. package/src/request/fixture/batch.ts +71 -0
  571. package/src/request/fixture/builder.ts +26 -0
  572. package/src/request/fixture/errors.ts +10 -0
  573. package/src/request/fixture/index.ts +8 -0
  574. package/src/request/fixture/namespace.ts +23 -0
  575. package/src/request/fixture/paginate.ts +44 -0
  576. package/src/request/fixture/to-handlers.ts +260 -0
  577. package/src/request/fixture/types.ts +79 -0
  578. package/src/request/flow/act-as.ts +78 -0
  579. package/src/request/flow/namespace.ts +17 -0
  580. package/src/request/http/error-step.ts +42 -0
  581. package/src/request/http/file.ts +141 -0
  582. package/src/request/http/index.ts +4 -0
  583. package/src/request/http/middleware.ts +141 -0
  584. package/src/request/http/namespace.ts +5 -0
  585. package/src/request/http/rate-limit-classes.ts +170 -0
  586. package/src/request/http/response.ts +82 -0
  587. package/src/request/http/server.ts +916 -0
  588. package/src/request/http/sniff.ts +261 -0
  589. package/src/request/http/types.ts +250 -0
  590. package/src/request/http/upload.ts +284 -0
  591. package/src/request/internal/text.ts +6 -0
  592. package/src/request/openapi/generate.ts +205 -0
  593. package/src/request/openapi/index.ts +2 -0
  594. package/src/request/openapi/namespace.ts +7 -0
  595. package/src/test/auth.ts +13 -0
  596. package/src/test/auto-setup.ts +45 -0
  597. package/src/test/context.ts +91 -0
  598. package/src/test/crawl-fixture.ts +157 -0
  599. package/src/test/discover-fork.ts +17 -0
  600. package/src/test/fingerprint.ts +135 -0
  601. package/src/test/globals.d.ts +7 -0
  602. package/src/test/index.ts +19 -0
  603. package/src/test/namespace.ts +87 -0
  604. package/src/test/plugin.ts +189 -0
  605. package/src/test/progress.ts +185 -0
  606. package/src/test/reap-after-run.ts +28 -0
  607. package/src/test/reap.ts +286 -0
  608. package/src/test/reset.ts +253 -0
  609. package/src/test/savepoints.ts +172 -0
  610. package/src/test/setup.ts +1422 -0
  611. package/src/test/system-channel.ts +50 -0
  612. package/src/test/vitest-plugin.ts +142 -0
  613. package/src/test/vitest-workspace.ts +507 -0
  614. package/src/test/vitest.ts +333 -0
  615. package/src/test/watch.ts +105 -0
  616. package/src/trace/capture/bounded-serializer.ts +146 -0
  617. package/src/trace/cardinality/analyze.ts +173 -0
  618. package/src/trace/cardinality/branch-context.ts +214 -0
  619. package/src/trace/cardinality/check.ts +33 -0
  620. package/src/trace/cardinality/classify-edge.ts +64 -0
  621. package/src/trace/cardinality/structural-max.ts +107 -0
  622. package/src/trace/check/coverage-check.ts +188 -0
  623. package/src/trace/check/flow-check.ts +103 -0
  624. package/src/trace/check/flow-step-site.ts +234 -0
  625. package/src/trace/check/io-pattern.ts +116 -0
  626. package/src/trace/codemod/add-cardinality.ts +152 -0
  627. package/src/trace/codemod/run.ts +80 -0
  628. package/src/trace/entry/child-trace.ts +21 -0
  629. package/src/trace/entry/close-trace.ts +87 -0
  630. package/src/trace/entry/finalize-trace.ts +28 -0
  631. package/src/trace/entry/open-trace.ts +138 -0
  632. package/src/trace/entry/parent-trace.ts +20 -0
  633. package/src/trace/entry/parse-traceparent.ts +39 -0
  634. package/src/trace/entry/process-start.ts +38 -0
  635. package/src/trace/entry/trace-context.ts +26 -0
  636. package/src/trace/entry/tracing-enabled.ts +10 -0
  637. package/src/trace/external/record.ts +195 -0
  638. package/src/trace/external/report.ts +66 -0
  639. package/src/trace/namespace.ts +19 -0
  640. package/src/trace/partition/day.ts +47 -0
  641. package/src/trace/partition/index.ts +14 -0
  642. package/src/trace/partition/partition-name.ts +23 -0
  643. package/src/trace/partition/plan.ts +82 -0
  644. package/src/trace/partition/schedule.ts +26 -0
  645. package/src/trace/partition/startup-hook.ts +39 -0
  646. package/src/trace/partition/sync.ts +154 -0
  647. package/src/trace/partition/tables.ts +53 -0
  648. package/src/trace/read/tree.ts +83 -0
  649. package/src/trace/retain/copy-on-error.ts +76 -0
  650. package/src/trace/runtime/expire-stale-traces.ts +54 -0
  651. package/src/trace/runtime/flow-step.ts +147 -0
  652. package/src/trace/runtime/flush-steps.ts +31 -0
  653. package/src/trace/runtime/pending-writes.ts +54 -0
  654. package/src/trace/runtime/step-buffer.ts +298 -0
  655. package/src/trace/runtime/step-error.ts +21 -0
  656. package/src/trace/runtime/step-meta.ts +55 -0
  657. package/src/trace/runtime/thenable.ts +12 -0
  658. package/src/trace/runtime/truncate-trace.ts +62 -0
  659. package/src/trace/schema/trace-fields.ts +52 -0
  660. package/src/trace/schema/trace-retained.ts +22 -0
  661. package/src/trace/schema/trace-step-fields.ts +44 -0
  662. package/src/trace/schema/trace-step-retained.ts +25 -0
  663. package/src/trace/schema/trace-step.ts +18 -0
  664. package/src/trace/schema/trace.ts +12 -0
  665. package/src/trace/transformer/apply.ts +79 -0
  666. package/src/trace/transformer/build-meta-literal.ts +30 -0
  667. package/src/trace/transformer/find-flow-step-sites.ts +85 -0
  668. package/src/trace/transformer/inject-flow-step-import.ts +39 -0
  669. package/src/trace/transformer/transform-error.ts +14 -0
  670. package/src/trace/transformer/transform-flow-steps.ts +123 -0
  671. package/src/trace/transformer/wrap-function-declaration.ts +62 -0
  672. package/src/trace/transformer/wrap-variable-declaration.ts +67 -0
  673. package/src/workspace/affected.ts +110 -0
  674. package/src/workspace/changed-files.ts +163 -0
  675. package/src/workspace/check-deps.ts +213 -0
  676. package/src/workspace/checksum.ts +20 -0
  677. package/src/workspace/dependency-graph.ts +67 -0
  678. package/src/workspace/detect-pipework-copies.ts +93 -0
  679. package/src/workspace/discover.ts +206 -0
  680. package/src/workspace/generate.ts +401 -0
  681. package/src/workspace/index.ts +7 -0
  682. package/src/workspace/module-imports-pipework.ts +39 -0
  683. package/src/workspace/module-package-name.ts +12 -0
  684. package/src/workspace/scrub-git-env.ts +23 -0
  685. package/src/workspace/source-paths.ts +36 -0
  686. package/src/workspace/sync.ts +182 -0
  687. package/dist/REFERENCE.md +0 -1477
  688. package/dist/infra/access-links/rate-limit.d.ts +0 -10
  689. package/dist/infra/access-links/rate-limit.d.ts.map +0 -1
  690. package/dist/infra/access-links/rate-limit.js +0 -28
  691. package/dist/infra/access-links/rate-limit.js.map +0 -1
  692. package/dist/infra/email/sigv4.d.ts +0 -24
  693. package/dist/infra/email/sigv4.d.ts.map +0 -1
  694. package/dist/infra/email/sigv4.js +0 -55
  695. package/dist/infra/email/sigv4.js.map +0 -1
@@ -0,0 +1,78 @@
1
+ // The `pipework codemod` command. Today it runs one codemod: filling missing
2
+ // `@downstream <kind>` cardinalities (Phase 4a). It uses the same module
3
+ // discovery as `pipework check`, so the codemod's scope matches the corpus
4
+ // the flow / cardinality checks would validate.
5
+
6
+ import { findSourceFiles } from '../../lint/doctrine.js'
7
+ import { runFlowCardinalityCodemod, type FileResult } from '../../trace/codemod/run.js'
8
+ import { info, success, warn } from '../output.js'
9
+ import { resolveModulePaths } from './check.js'
10
+
11
+ export interface CodemodOptions {
12
+ readonly cwd: string
13
+ readonly dryRun: boolean
14
+ }
15
+
16
+ export async function codemod(options: CodemodOptions): Promise<void> {
17
+ const { paths: modulePaths } = await resolveModulePaths(options.cwd, { kind: 'all' })
18
+ if (modulePaths.length === 0) {
19
+ success('No source modules — nothing to codemod')
20
+ return
21
+ }
22
+
23
+ const files = findSourceFiles(options.cwd, modulePaths)
24
+ if (files.length === 0) {
25
+ success('No TypeScript sources — nothing to codemod')
26
+ return
27
+ }
28
+
29
+ info(options.dryRun ? 'Cardinality codemod (dry run)' : 'Cardinality codemod')
30
+
31
+ const result = runFlowCardinalityCodemod({
32
+ cwd: options.cwd,
33
+ files,
34
+ dryRun: options.dryRun,
35
+ })
36
+
37
+ reportFills(result.files)
38
+ reportUnresolved(result.files)
39
+
40
+ const verb = options.dryRun ? 'would update' : 'updated'
41
+ if (result.totalFills > 0) {
42
+ success(
43
+ `Cardinality codemod (${verb} ${String(result.filesChanged)} `
44
+ + `file${result.filesChanged === 1 ? '' : 's'}, `
45
+ + `${String(result.totalFills)} edge${result.totalFills === 1 ? '' : 's'} filled)`,
46
+ )
47
+ } else {
48
+ success('Cardinality codemod (no fillable edges)')
49
+ }
50
+
51
+ if (result.totalUnresolved > 0) {
52
+ warn(
53
+ `Cardinality codemod: ${String(result.totalUnresolved)} edge`
54
+ + `${result.totalUnresolved === 1 ? '' : 's'} need human attention `
55
+ + `(see "unresolved" output above)`,
56
+ )
57
+ }
58
+ }
59
+
60
+ function reportFills(files: readonly FileResult[]): void {
61
+ for (const fr of files) {
62
+ if (fr.fills.length === 0) continue
63
+ info(` ${fr.file} (${String(fr.fills.length)} filled)`)
64
+ for (const fill of fr.fills) {
65
+ info(` ${String(fill.line)}: @downstream ${fill.target} ${fill.kind}`)
66
+ }
67
+ }
68
+ }
69
+
70
+ function reportUnresolved(files: readonly FileResult[]): void {
71
+ for (const fr of files) {
72
+ if (fr.unresolved.length === 0) continue
73
+ warn(` ${fr.file} (${String(fr.unresolved.length)} unresolved)`)
74
+ for (const u of fr.unresolved) {
75
+ warn(` ${String(u.line)}: @downstream ${u.target} — ${u.reason}`)
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,356 @@
1
+ import { randomBytes } from 'node:crypto'
2
+ import { resolve, join } from 'node:path'
3
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs'
4
+ import { bold, info, success, error as logError, warn } from '../output.js'
5
+ import { loadConfig } from './shared/load-config.js'
6
+ import type { Blueprint, DatabaseConfig } from '../../core/config/schema.js'
7
+
8
+ export interface DbOptions {
9
+ readonly cwd: string
10
+ readonly subcommand: string | undefined
11
+ readonly db?: string | undefined
12
+ readonly test?: boolean | undefined
13
+ readonly confirm?: boolean | undefined
14
+ readonly adminUrl?: string | undefined
15
+ }
16
+
17
+ export async function db(opts: DbOptions): Promise<void> {
18
+ switch (opts.subcommand) {
19
+ case 'setup':
20
+ await setup(opts)
21
+ break
22
+ case 'teardown':
23
+ await teardown(opts)
24
+ break
25
+ case 'reset':
26
+ await teardown(opts)
27
+ await setup(opts)
28
+ break
29
+ default: {
30
+ const sub = opts.subcommand ?? '(none)'
31
+ logError('Unknown db subcommand: ' + sub)
32
+ process.stderr.write('\n Usage: ' + bold('pipework db <setup|teardown|reset>') + '\n\n')
33
+ process.stderr.write(' setup Create databases, roles, extensions, run migrations\n')
34
+ process.stderr.write(' setup --test Create test database with isolated credentials\n')
35
+ process.stderr.write(' teardown Drop databases and roles\n')
36
+ process.stderr.write(' reset Teardown + setup\n\n')
37
+ process.exit(1)
38
+ }
39
+ }
40
+ }
41
+
42
+ async function setup(opts: DbOptions): Promise<void> {
43
+ {
44
+ const { config } = await loadConfig(resolve(opts.cwd))
45
+ const databases = filterDatabases(config, opts.db)
46
+
47
+ for (const [name, dbConfig] of databases) {
48
+ info('Setting up database: ' + name)
49
+
50
+ const adminUrl = resolveAdminUrl(opts, dbConfig)
51
+ if (adminUrl === null) {
52
+ const envName = dbConfig.adminUrl ?? 'ADMIN_DATABASE_URL'
53
+ logError('No admin URL for database "' + name + '". Set ' + envName + ' or pass --admin-url.')
54
+ process.exit(1)
55
+ }
56
+
57
+ const isTest = opts.test === true
58
+ const dbName = isTest ? name + '_test' : name
59
+ const ownerRole = name + '_owner'
60
+ const runtimeRole = name + '_app'
61
+ const ownerPassword = randomBytes(16).toString('hex')
62
+ const runtimePassword = randomBytes(16).toString('hex')
63
+ const ownerUrl = buildConnectionUrl(adminUrl, dbName, ownerRole, ownerPassword)
64
+ const runtimeUrl = buildConnectionUrl(adminUrl, dbName, runtimeRole, runtimePassword)
65
+ const ownerEnvVar = isTest ? dbConfig.testUrl : dbConfig.url
66
+ const runtimeEnvVar = isTest ? dbConfig.appTestUrl : dbConfig.appUrl
67
+ // Platform mode: the platform role is named in config (generated policies
68
+ // name it), created here like the runtime role, and written to systemUrl.
69
+ const platformRole = dbConfig.rls?.platformRole
70
+ const platformPassword = randomBytes(16).toString('hex')
71
+ const platformUrl = platformRole !== undefined ? buildConnectionUrl(adminUrl, dbName, platformRole, platformPassword) : undefined
72
+ const platformEnvVar = isTest ? dbConfig.systemTestUrl : dbConfig.systemUrl
73
+
74
+ let adminClient: AdminClient | null = null
75
+ try {
76
+ adminClient = await connectAdmin(adminUrl)
77
+
78
+ await ensureRole(adminClient, ownerRole, ownerPassword, { bypassRls: true })
79
+ await ensureRole(adminClient, runtimeRole, runtimePassword, { bypassRls: false })
80
+ if (platformRole !== undefined) await ensureRole(adminClient, platformRole, platformPassword, { bypassRls: false })
81
+ await ensureDatabase(adminClient, dbName, ownerRole)
82
+ await grantConnect(adminClient, dbName, runtimeRole)
83
+ if (platformRole !== undefined) await grantConnect(adminClient, dbName, platformRole)
84
+
85
+ // Extensions and the runtime grants run as the owner so the database
86
+ // objects (and the owner-scoped default privileges) belong to the owner.
87
+ const ownerClient = await connectAdmin(ownerUrl)
88
+ try {
89
+ if (dbConfig.extensions !== undefined) {
90
+ for (const ext of dbConfig.extensions) {
91
+ await ensureExtension(ownerClient, ext)
92
+ }
93
+ }
94
+ for (const stmt of buildRuntimeGrants('public', ownerRole, runtimeRole)) {
95
+ await ownerClient.query(stmt)
96
+ }
97
+ // The platform role gets the runtime role's privileges; which rows it
98
+ // sees is the policies' business (a door, or none).
99
+ if (platformRole !== undefined) {
100
+ for (const stmt of buildRuntimeGrants('public', ownerRole, platformRole)) {
101
+ await ownerClient.query(stmt)
102
+ }
103
+ }
104
+ } finally {
105
+ await ownerClient.close()
106
+ }
107
+ info('Granted runtime DML to role: ' + runtimeRole)
108
+ if (platformRole !== undefined) info('Granted runtime DML to platform role: ' + platformRole)
109
+
110
+ success('Database "' + dbName + '" ready (owner: ' + ownerRole + ', runtime: ' + runtimeRole + ')')
111
+
112
+ if (ownerEnvVar !== undefined) {
113
+ writeEnvVar(opts.cwd, ownerEnvVar, ownerUrl)
114
+ success('Wrote ' + ownerEnvVar + ' to .env')
115
+ }
116
+ if (runtimeEnvVar !== undefined) {
117
+ writeEnvVar(opts.cwd, runtimeEnvVar, runtimeUrl)
118
+ success('Wrote ' + runtimeEnvVar + ' to .env')
119
+ }
120
+ if (platformUrl !== undefined && platformEnvVar !== undefined) {
121
+ writeEnvVar(opts.cwd, platformEnvVar, platformUrl)
122
+ success('Wrote ' + platformEnvVar + ' to .env')
123
+ }
124
+ if (runtimeEnvVar === undefined) {
125
+ warn('No appUrl configured for "' + name + '" — runtime would fall back to the owner connection and RLS would be inert. Set appUrl/appTestUrl in the database config to enable role separation.')
126
+ }
127
+ } catch (err) {
128
+ logError('Failed to setup "' + name + '": ' + (err instanceof Error ? err.message : String(err)))
129
+ process.exit(1)
130
+ } finally {
131
+ if (adminClient !== null) {
132
+ await adminClient.close()
133
+ }
134
+ }
135
+ }
136
+
137
+ success('Database setup complete')
138
+ }
139
+ }
140
+
141
+ async function teardown(opts: DbOptions): Promise<void> {
142
+ {
143
+ const { config } = await loadConfig(resolve(opts.cwd))
144
+ const databases = filterDatabases(config, opts.db)
145
+
146
+ if (config.environment === 'production' && opts.confirm !== true) {
147
+ logError('Teardown in production requires --confirm flag.')
148
+ process.exit(1)
149
+ }
150
+
151
+ for (const [name, dbConfig] of databases) {
152
+ const adminUrl = resolveAdminUrl(opts, dbConfig)
153
+ if (adminUrl === null) {
154
+ warn('No admin URL for database "' + name + '" — skipping teardown')
155
+ continue
156
+ }
157
+
158
+ let adminClient: AdminClient | null = null
159
+ try {
160
+ adminClient = await connectAdmin(adminUrl)
161
+
162
+ const dbName = name
163
+ const testDbName = name + '_test'
164
+ const ownerRole = name + '_owner'
165
+ const runtimeRole = name + '_app'
166
+
167
+ // Databases first: dropping them removes the in-database grants and
168
+ // owner-scoped default privileges, so the roles drop cleanly afterwards.
169
+ await dropDatabaseIfExists(adminClient, testDbName)
170
+ await dropDatabaseIfExists(adminClient, dbName)
171
+ await dropRoleIfExists(adminClient, runtimeRole)
172
+ if (dbConfig.rls?.platformRole !== undefined) await dropRoleIfExists(adminClient, dbConfig.rls.platformRole)
173
+ await dropRoleIfExists(adminClient, ownerRole)
174
+
175
+ success('Torn down: ' + name)
176
+ } catch (err) {
177
+ logError('Failed to teardown "' + name + '": ' + (err instanceof Error ? err.message : String(err)))
178
+ } finally {
179
+ if (adminClient !== null) {
180
+ await adminClient.close()
181
+ }
182
+ }
183
+ }
184
+
185
+ success('Database teardown complete')
186
+ }
187
+ }
188
+
189
+ function filterDatabases(config: Blueprint, dbFilter?: string): Array<[string, DatabaseConfig]> {
190
+ const entries = Object.entries(config.databases)
191
+ if (dbFilter !== undefined) {
192
+ const filtered = entries.filter(([name]) => name === dbFilter)
193
+ if (filtered.length === 0) {
194
+ logError('Database "' + dbFilter + '" not found in config. Available: ' + entries.map(([n]) => n).join(', '))
195
+ process.exit(1)
196
+ }
197
+ return filtered
198
+ }
199
+ return entries
200
+ }
201
+
202
+ function resolveAdminUrl(opts: DbOptions, dbConfig: DatabaseConfig): string | null {
203
+ if (opts.adminUrl !== undefined) return opts.adminUrl
204
+ if (dbConfig.adminUrl !== undefined) {
205
+ const fromEnv = process.env[dbConfig.adminUrl]
206
+ if (fromEnv !== undefined && fromEnv !== '') return fromEnv
207
+ }
208
+ const fallback = process.env['ADMIN_DATABASE_URL']
209
+ if (fallback !== undefined && fallback !== '') return fallback
210
+ return null
211
+ }
212
+
213
+ function buildConnectionUrl(adminUrl: string, dbName: string, role: string, password: string): string {
214
+ try {
215
+ const url = new URL(adminUrl)
216
+ url.username = role
217
+ url.password = password
218
+ url.pathname = '/' + dbName
219
+ return url.toString()
220
+ } catch {
221
+ const match = adminUrl.match(/^postgresql:\/\/([^@]+@)?([^/]+)/)
222
+ if (match !== null) {
223
+ return 'postgresql://' + role + ':' + password + '@' + String(match[2]) + '/' + dbName
224
+ }
225
+ return 'postgresql://' + role + ':' + password + '@localhost:5432/' + dbName
226
+ }
227
+ }
228
+
229
+ interface AdminClient {
230
+ query(sql: string, params?: unknown[]): Promise<unknown[]>
231
+ close(): Promise<void>
232
+ }
233
+
234
+ async function connectAdmin(url: string): Promise<AdminClient> {
235
+ const { default: postgres } = await import('postgres')
236
+ const client = postgres(url, { max: 1, onnotice: () => {} })
237
+ return {
238
+ async query(sqlStr: string, params?: unknown[]) {
239
+ if (params !== undefined && params.length > 0) {
240
+ return client.unsafe(sqlStr, params as never[])
241
+ }
242
+ return client.unsafe(sqlStr)
243
+ },
244
+ async close() {
245
+ await client.end()
246
+ },
247
+ }
248
+ }
249
+
250
+ interface RoleAttributes {
251
+ /** Owner roles carry BYPASSRLS so migrations/bootstrap span tenants regardless of FORCE; runtime roles must not, or RLS is inert. */
252
+ readonly bypassRls: boolean
253
+ }
254
+
255
+ // Both roles are LOGIN, non-superuser, and cannot create databases or roles.
256
+ // The single discriminator is BYPASSRLS: the owner has it (DDL/bootstrap reads
257
+ // and writes across every tenant), the non-owner runtime role explicitly does
258
+ // not, so generated RLS policies actually bind to it.
259
+ function roleAttributeClause(attrs: RoleAttributes): string {
260
+ return 'NOSUPERUSER NOCREATEDB NOCREATEROLE ' + (attrs.bypassRls ? 'BYPASSRLS' : 'NOBYPASSRLS')
261
+ }
262
+
263
+ async function ensureRole(client: AdminClient, name: string, password: string, attrs: RoleAttributes): Promise<void> {
264
+ const clause = roleAttributeClause(attrs)
265
+ const rows = await client.query('SELECT 1 FROM pg_roles WHERE rolname = $1', [name]) as unknown[]
266
+ if (rows.length === 0) {
267
+ await client.query('CREATE ROLE ' + quoteIdent(name) + ' WITH LOGIN PASSWORD \'' + escapePassword(password) + '\' ' + clause)
268
+ info('Created role: ' + name)
269
+ } else {
270
+ await client.query('ALTER ROLE ' + quoteIdent(name) + ' WITH LOGIN PASSWORD \'' + escapePassword(password) + '\' ' + clause)
271
+ info('Updated role: ' + name)
272
+ }
273
+ }
274
+
275
+ async function grantConnect(client: AdminClient, dbName: string, role: string): Promise<void> {
276
+ await client.query('GRANT CONNECT ON DATABASE ' + quoteIdent(dbName) + ' TO ' + quoteIdent(role))
277
+ }
278
+
279
+ /**
280
+ * The DML grants for the non-owner runtime role, applied at provision time on a
281
+ * connection authenticated as the owner. The two ALTER DEFAULT PRIVILEGES lines
282
+ * are the drift guard: every future table the owner creates via migrations is
283
+ * granted to the runtime role automatically, so an RLS-enabled table can never
284
+ * be left ungranted — which would blank the rows the app is entitled to.
285
+ */
286
+ export function buildRuntimeGrants(schema: string, ownerRole: string, runtimeRole: string): string[] {
287
+ const s = quoteIdent(schema)
288
+ const owner = quoteIdent(ownerRole)
289
+ const runtime = quoteIdent(runtimeRole)
290
+ return [
291
+ 'GRANT USAGE ON SCHEMA ' + s + ' TO ' + runtime,
292
+ 'GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA ' + s + ' TO ' + runtime,
293
+ 'GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA ' + s + ' TO ' + runtime,
294
+ 'ALTER DEFAULT PRIVILEGES FOR ROLE ' + owner + ' IN SCHEMA ' + s + ' GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO ' + runtime,
295
+ 'ALTER DEFAULT PRIVILEGES FOR ROLE ' + owner + ' IN SCHEMA ' + s + ' GRANT USAGE, SELECT ON SEQUENCES TO ' + runtime,
296
+ ]
297
+ }
298
+
299
+
300
+ async function ensureDatabase(client: AdminClient, dbName: string, owner: string): Promise<void> {
301
+ const rows = await client.query('SELECT 1 FROM pg_database WHERE datname = $1', [dbName]) as unknown[]
302
+ if (rows.length === 0) {
303
+ await client.query('CREATE DATABASE ' + quoteIdent(dbName) + ' OWNER ' + quoteIdent(owner))
304
+ info('Created database: ' + dbName)
305
+ } else {
306
+ info('Database "' + dbName + '" already exists')
307
+ }
308
+ }
309
+
310
+ async function ensureExtension(client: AdminClient, ext: string): Promise<void> {
311
+ await client.query('CREATE EXTENSION IF NOT EXISTS ' + quoteIdent(ext))
312
+ info('Extension: ' + ext)
313
+ }
314
+
315
+ async function dropDatabaseIfExists(client: AdminClient, dbName: string): Promise<void> {
316
+ const rows = await client.query('SELECT 1 FROM pg_database WHERE datname = $1', [dbName]) as unknown[]
317
+ if (rows.length > 0) {
318
+ await client.query('DROP DATABASE ' + quoteIdent(dbName))
319
+ info('Dropped database: ' + dbName)
320
+ }
321
+ }
322
+
323
+ async function dropRoleIfExists(client: AdminClient, name: string): Promise<void> {
324
+ const rows = await client.query('SELECT 1 FROM pg_roles WHERE rolname = $1', [name]) as unknown[]
325
+ if (rows.length > 0) {
326
+ await client.query('DROP ROLE ' + quoteIdent(name))
327
+ info('Dropped role: ' + name)
328
+ }
329
+ }
330
+
331
+ function quoteIdent(name: string): string {
332
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
333
+ throw new Error('[pipework] Invalid identifier: "' + name + '"')
334
+ }
335
+ return '"' + name + '"'
336
+ }
337
+
338
+ function escapePassword(password: string): string {
339
+ return password.replace(/'/g, "''")
340
+ }
341
+
342
+ function writeEnvVar(cwd: string, key: string, value: string): void {
343
+ const envPath = join(cwd, '.env')
344
+ let content = ''
345
+ if (existsSync(envPath)) {
346
+ content = readFileSync(envPath, 'utf-8')
347
+ const pattern = new RegExp('^' + key + '=.*$', 'm')
348
+ if (pattern.test(content)) {
349
+ content = content.replace(pattern, key + '=' + value)
350
+ writeFileSync(envPath, content, 'utf-8')
351
+ return
352
+ }
353
+ }
354
+ const newLine = content.length > 0 && !content.endsWith('\n') ? '\n' : ''
355
+ writeFileSync(envPath, content + newLine + key + '=' + value + '\n', 'utf-8')
356
+ }
@@ -0,0 +1,101 @@
1
+ import { spawn } from 'node:child_process'
2
+ import { resolve, dirname } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { info, bold, cyan, yellow } from '../output.js'
5
+
6
+ export interface DevOptions {
7
+ port: string | undefined
8
+ cwd: string
9
+ entry: string | undefined
10
+ }
11
+
12
+ export function dev(options: DevOptions): void {
13
+ if (options.entry !== undefined) {
14
+ startLegacy(options)
15
+ return
16
+ }
17
+
18
+ startSurfaceAware(options)
19
+ }
20
+
21
+ // dev.js compiles to dist/cli/commands/dev.js. The TS loader and the dev
22
+ // bootstrap are sibling build outputs, NOT source files — once pipework is
23
+ // installed they live under node_modules. Both must be resolved as the
24
+ // compiled `.js`: the loader source is src/core/config/ts-register.ts →
25
+ // dist/core/config/ts-register.js (two levels up to dist, then core/config),
26
+ // and the bootstrap is src/cli/dev-bootstrap.ts → dist/cli/dev-bootstrap.js
27
+ // (one level up to dist/cli). Referencing the bootstrap as `.ts` only works in
28
+ // pipework's own repo (source not under node_modules) and is doubly broken
29
+ // once installed: the `.ts` isn't shipped, and Node refuses to strip types for
30
+ // any file under node_modules.
31
+ export function resolveRegisterPath(cliDir: string): string {
32
+ return resolve(cliDir, '..', '..', 'core', 'config', 'ts-register.js')
33
+ }
34
+
35
+ export function resolveBootstrapPath(cliDir: string): string {
36
+ return resolve(cliDir, '..', 'dev-bootstrap.js')
37
+ }
38
+
39
+
40
+ function startSurfaceAware(options: DevOptions): void {
41
+ {
42
+ const cliDir = dirname(fileURLToPath(import.meta.url))
43
+ const bootstrapPath = resolveBootstrapPath(cliDir)
44
+ const registerPath = resolveRegisterPath(cliDir)
45
+
46
+ const env: Record<string, string | undefined> = { ...process.env, 'PIPEWORK_CWD': options.cwd }
47
+ if (options.port !== undefined) {
48
+ env['PORT'] = options.port
49
+ }
50
+
51
+ printBanner()
52
+
53
+ const args = ['--watch', '--import', registerPath, bootstrapPath]
54
+
55
+ const child = spawn('node', args, {
56
+ cwd: options.cwd,
57
+ stdio: 'inherit',
58
+ env,
59
+ })
60
+
61
+ child.on('exit', (code, signal) => {
62
+ if (signal === 'SIGTERM' || signal === 'SIGINT') {
63
+ process.exit(0)
64
+ }
65
+ process.exit(code ?? 0)
66
+ })
67
+
68
+ process.on('SIGTERM', () => child.kill('SIGTERM'))
69
+ process.on('SIGINT', () => child.kill('SIGINT'))
70
+ }
71
+ }
72
+
73
+ function startLegacy(options: DevOptions): void {
74
+ {
75
+ const cliDir = dirname(fileURLToPath(import.meta.url))
76
+ const registerPath = resolveRegisterPath(cliDir)
77
+ const entry = options.entry ?? 'src/server.ts'
78
+ const args = ['--watch', '--import', registerPath, entry]
79
+
80
+ if (options.port !== undefined) {
81
+ process.env['PORT'] = options.port
82
+ }
83
+
84
+ info(`Starting dev server: node ${args.join(' ')}`)
85
+
86
+ const child = spawn('node', args, {
87
+ cwd: options.cwd,
88
+ stdio: 'inherit',
89
+ env: process.env,
90
+ })
91
+
92
+ child.on('exit', (code) => {
93
+ process.exit(code ?? 0)
94
+ })
95
+ }
96
+ }
97
+
98
+ function printBanner(): void {
99
+ process.stderr.write(`\n ${bold(cyan('pipework dev'))}\n`)
100
+ process.stderr.write(` ${yellow('watching for changes...')}\n\n`)
101
+ }
@@ -0,0 +1,75 @@
1
+ import type { ResolvedConfig, ResolvedDoor } from '../../core/config/load.js'
2
+ import { queueFrameworkDoors } from '../../async/jobs/queue-door.js'
3
+ import { info, success, warn, error as logError } from '../output.js'
4
+
5
+ export interface GenerateCommandOptions {
6
+ db: string | undefined
7
+ name: string | undefined
8
+ cwd: string
9
+ }
10
+
11
+ /** Evaluated after the schema files load: queue tables register when a worker surface or graph is constructed. */
12
+ function doorsOf(config: ResolvedConfig, database: string): () => ResolvedDoor[] {
13
+ return () => [...Object.values(config.doors), ...Object.values(config.frameworkDoors), ...Object.values(queueFrameworkDoors(config))]
14
+ .filter(door => door.database === database)
15
+ }
16
+
17
+ export async function generate(options: GenerateCommandOptions): Promise<void> {
18
+ const { discoverInstance, findConfig } = await import('../../core/config/discover.js')
19
+ const { generateForDatabase } = await import('../../data/migrate/generate.js')
20
+ const { loadInternalDefinitions } = await import('../../data/migrate/internal-definitions.js')
21
+
22
+ if (findConfig(options.cwd) === null) {
23
+ logError(
24
+ 'No pipework.config.ts found.\n\n' +
25
+ ' Run `pipework init` to create one.\n'
26
+ )
27
+ process.exit(1)
28
+ }
29
+
30
+ // A config that exists but fails to load (missing env var, refused
31
+ // url/testUrl identity, …) must surface its real error, not be misreported
32
+ // as a missing config.
33
+ const instance = await discoverInstance(options.cwd)
34
+
35
+ const defaultDbName = instance.config.defaultDatabaseName()
36
+
37
+ try {
38
+ if (options.db !== undefined) {
39
+ const dbConfig = instance.config.database(options.db)
40
+ info(`Generating migration for database: ${options.db}`)
41
+ // Passed as a thunk so queue registrations made by glob-imported schema
42
+ // modules (inside generateForDatabase) are visible when it runs.
43
+ const internal = () => loadInternalDefinitions(instance.config.raw, {
44
+ isDefaultDatabase: options.db === defaultDbName,
45
+ })
46
+ const result = await generateForDatabase(dbConfig, options.name, internal, doorsOf(instance.config, dbConfig.name))
47
+ if (result.migrationFile === null) {
48
+ warn(`${options.db}: no schema changes detected`)
49
+ } else {
50
+ success(`${options.db}: generated ${result.migrationFile}`)
51
+ }
52
+ } else {
53
+ info('Generating migrations for all databases...')
54
+ let generated = 0
55
+ for (const [, dbConfig] of instance.config.databases()) {
56
+ if (dbConfig.schema === undefined) continue
57
+ const internal = () => loadInternalDefinitions(instance.config.raw, {
58
+ isDefaultDatabase: dbConfig.name === defaultDbName,
59
+ })
60
+ const result = await generateForDatabase(dbConfig, options.name, internal, doorsOf(instance.config, dbConfig.name))
61
+ if (result.migrationFile === null) {
62
+ warn(`${dbConfig.name}: no schema changes detected`)
63
+ } else {
64
+ success(`${dbConfig.name}: generated ${result.migrationFile}`)
65
+ generated++
66
+ }
67
+ }
68
+ if (generated === 0) {
69
+ warn('No schema changes detected in any database.')
70
+ }
71
+ }
72
+ } finally {
73
+ await instance.pool.closeAll()
74
+ }
75
+ }
@@ -0,0 +1,36 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
2
+ import { join } from 'node:path'
3
+ import { success, warn } from '../output.js'
4
+
5
+ const CONFIG_TEMPLATE = `import { createManifold } from 'pipework'
6
+
7
+ export default createManifold({
8
+ databases: {
9
+ app: {
10
+ url: 'DATABASE_URL',
11
+ testUrl: 'DATABASE_URL_TEST',
12
+ schema: './src/db/schema.ts',
13
+ migrations: './migrations/app',
14
+ },
15
+ },
16
+ })
17
+ `
18
+
19
+ export function init(cwd: string): void {
20
+ const configPath = join(cwd, 'pipework.config.ts')
21
+ const migrationsPath = join(cwd, 'migrations', 'app')
22
+
23
+ if (existsSync(configPath)) {
24
+ warn('pipework.config.ts already exists — skipping')
25
+ } else {
26
+ writeFileSync(configPath, CONFIG_TEMPLATE, 'utf-8')
27
+ success('Created pipework.config.ts')
28
+ }
29
+
30
+ if (!existsSync(migrationsPath)) {
31
+ mkdirSync(migrationsPath, { recursive: true })
32
+ success(`Created ${migrationsPath}`)
33
+ } else {
34
+ warn(`${migrationsPath} already exists — skipping`)
35
+ }
36
+ }
@@ -0,0 +1,28 @@
1
+ import { resolve } from 'node:path'
2
+ import { sync as syncWorkspace } from '../../workspace/sync.js'
3
+ import { loadConfig } from './shared/load-config.js'
4
+ import { reportRemoved } from './shared/report-removed.js'
5
+ import { runPnpmInstall } from './shared/pnpm-install.js'
6
+ import { info, success, error } from '../output.js'
7
+
8
+ export async function install(cwd: string, pipeworkVersion?: string): Promise<void> {
9
+ const resolved = resolve(cwd)
10
+ const { config, appName } = await loadConfig(resolved)
11
+
12
+ info('Syncing workspace...')
13
+ const syncInput = { config, cwd: resolved, appName }
14
+ const result = syncWorkspace(
15
+ pipeworkVersion !== undefined ? { ...syncInput, pipeworkVersion } : syncInput,
16
+ )
17
+
18
+ success(`Generated ${String(result.files.length)} file(s).`)
19
+ reportRemoved(result)
20
+
21
+ info('Running pnpm install...')
22
+ const outcome = runPnpmInstall({ cwd: resolved, requiredPipeworkVersion: result.pipeworkVersion })
23
+ if (!outcome.ok) {
24
+ error(outcome.message)
25
+ process.exit(1)
26
+ }
27
+ success(`Install complete — pipework@${outcome.installedPipeworkVersion} in node_modules.`)
28
+ }