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,97 @@
1
+ import { existsSync, readdirSync } from 'node:fs'
2
+ import { join, relative, resolve, sep } from 'node:path'
3
+ import { discoverWorkspacePackages } from '../workspace/discover.js'
4
+
5
+ /**
6
+ * The file globs a module lints, relative to the module directory.
7
+ *
8
+ * `configured` — `lint.modules.<path>.include`, else `lint.include` — replaces the
9
+ * default outright: a module whose sources are not under `src` says so once. The
10
+ * default covers `src` plus the `src` of each workspace package under `dir`, so a
11
+ * nested workspace is not left matching nothing (#393).
12
+ */
13
+ export function lintIncludeGlobs(dir: string, configured?: readonly string[]): string[] {
14
+ if (configured !== undefined && configured.length > 0) return [...configured]
15
+
16
+ const globs = ['src/**/*.ts', 'src/**/*.tsx']
17
+ for (const pkg of discoverWorkspacePackages(dir)) {
18
+ globs.push(pkg + '/src/**/*.ts', pkg + '/src/**/*.tsx')
19
+ }
20
+ return globs
21
+ }
22
+
23
+ /**
24
+ * The longest directory prefix of `glob` that contains no wildcard.
25
+ *
26
+ * `app/src/**\/*.ts` → `app/src`; `**\/*.ts` → `''` (the module root). That is the
27
+ * directory eslint is pointed at and the directory walked to find files the run
28
+ * should have covered.
29
+ */
30
+ export function globRoot(glob: string): string {
31
+ const parts = glob.split('/')
32
+ const wildcard = parts.findIndex(p => p.includes('*') || p.includes('?'))
33
+ return (wildcard === -1 ? parts.slice(0, -1) : parts.slice(0, wildcard)).join('/')
34
+ }
35
+
36
+ /**
37
+ * Match a path (relative, `/`-separated) against one glob.
38
+ *
39
+ * `**` crosses directory separators, `*` and `?` do not. Enough for the `files`
40
+ * patterns eslint itself accepts; anything richer belongs in eslint's config, not here.
41
+ */
42
+ export function matchesGlob(path: string, glob: string): boolean {
43
+ return globToRegExp(glob).test(path)
44
+ }
45
+
46
+ function globToRegExp(glob: string): RegExp {
47
+ let out = '^'
48
+ for (let i = 0; i < glob.length; i++) {
49
+ const ch = glob[i]!
50
+ if (ch === '*') {
51
+ if (glob[i + 1] === '*') {
52
+ // `**/` may match zero segments, so the separator is part of the optional group.
53
+ i++
54
+ if (glob[i + 1] === '/') i++
55
+ out += '(?:[^/]*(?:/|$))*'
56
+ } else {
57
+ out += '[^/]*'
58
+ }
59
+ } else if (ch === '?') {
60
+ out += '[^/]'
61
+ } else {
62
+ out += ch.replace(/[.+^${}()|[\]\\]/g, '\\$&')
63
+ }
64
+ }
65
+ return new RegExp(out + '$')
66
+ }
67
+
68
+ /**
69
+ * Every file under `dir` that the module's globs say should be linted.
70
+ *
71
+ * Walked from each glob's static root so the cost tracks the configured scope, not the
72
+ * whole module. `node_modules` and `dist` are never descended — eslint ignores both.
73
+ */
74
+ export function filesMatchingGlobs(dir: string, globs: readonly string[]): string[] {
75
+ const found = new Set<string>()
76
+ for (const glob of globs) {
77
+ const root = globRoot(glob)
78
+ const rootDir = root === '' ? dir : join(dir, root)
79
+ if (!existsSync(rootDir)) continue
80
+ for (const file of walk(rootDir, dir)) {
81
+ if (matchesGlob(file, glob)) found.add(file)
82
+ }
83
+ }
84
+ return [...found].sort()
85
+ }
86
+
87
+ function walk(dir: string, base: string, out: string[] = []): string[] {
88
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
89
+ if (entry.isDirectory()) {
90
+ if (entry.name === 'node_modules' || entry.name === 'dist') continue
91
+ walk(join(dir, entry.name), base, out)
92
+ } else {
93
+ out.push(relative(resolve(base), resolve(dir, entry.name)).split(sep).join('/'))
94
+ }
95
+ }
96
+ return out
97
+ }
@@ -0,0 +1,3 @@
1
+ export { createLintConfig, rules } from './config.js'
2
+ export type { LintOptions } from './config.js'
3
+ export { resolveLintConfig } from './resolver.js'
@@ -0,0 +1,10 @@
1
+ import { resolveLintConfig } from './resolver.js'
2
+
3
+ // `pipework check` lints each module directory with `--config <this file>` (see
4
+ // lintDirectory in src/cli/commands/check.ts). Resolving here — rather than a
5
+ // static createLintConfig() — makes that per-module pass honour pipework.config.ts:
6
+ // `lint.extra` applies everywhere, and `lint.modules` applies to the module being
7
+ // linted (resolveLintConfig keys off the eslint process cwd, i.e. the module dir).
8
+ // With `--config`, eslint's base path IS the cwd, so cwd is also the right root for
9
+ // the file globs here — unlike the generated eslint.config.js, which passes its own dir.
10
+ export default await resolveLintConfig()
@@ -0,0 +1,218 @@
1
+ import { dirname, join, relative, sep } from 'node:path'
2
+ import type { Manifold } from '../core/pipework.js'
3
+ import type { LintModuleConfig } from '../core/config/schema.js'
4
+ import { findConfig, registerTsResolveHooks } from '../core/config/discover.js'
5
+ import { importConfig } from '../core/config/import-config.js'
6
+ import { loadEnvFiles } from '../core/config/env.js'
7
+ import { expandGlob } from '../workspace/discover.js'
8
+ import { lintIncludeGlobs } from './include.js'
9
+ import { createLintConfig, type LintOptions } from './config.js'
10
+
11
+ /**
12
+ * Build the full eslint flat-config array from pipework.config.ts.
13
+ *
14
+ * The generated `eslint.config.js` delegates here, passing its own directory as `cwd` —
15
+ * eslint resolves flat-config globs against that directory, not the process cwd.
16
+ * Everything that would normally live in `eslint.config.js` — extra plugins, rules, additional
17
+ * flat-config blocks — flows through `pipework.config.ts` so pipework remains the single source
18
+ * of truth and the generated file stays byte-stable for `pipework check`.
19
+ *
20
+ * Shape:
21
+ * - `lint.extra.plugins` → registered in pipework's main lint block; rules under
22
+ * `lint.extra.rules` (or `pipework`'s built-in rules) can reference them as `name/rule`.
23
+ * - `lint.extra.rules` → merged into pipework's main block (can override defaults).
24
+ * - `lint.extra.configs` → appended as additional flat-config entries after pipework's block.
25
+ * - `lint.include` (or a module's own `include`) → the block's `files`. Unset, the globs
26
+ * are derived from the workspace rooted at `base`: a glob for `src` plus one per
27
+ * workspace package under it, nested workspaces included. Without either, a package
28
+ * whose sources are not under `base/src` matches no block, eslint reports "no matching
29
+ * configuration", and `pipework check` still prints Lint ✓ (#392, #393).
30
+ * - `lint.modules` → per-module overrides, applied per file whatever the directory eslint
31
+ * runs from. When `cwd` resolves inside a declared module (the per-module `pipework check`
32
+ * pass, `pipework lint`), that module's `rules` and `configs` are layered on top of
33
+ * `lint.extra`. For a module below `cwd` (the generated root `eslint.config.js`), its
34
+ * `rules` and `configs` become config entries whose `files` and `ignores` are prefixed
35
+ * with the module's path, so plain `eslint <file>` agrees with `pipework check`.
36
+ */
37
+ export async function resolveLintConfig(cwd?: string): Promise<unknown[]> {
38
+ const start = cwd ?? process.cwd()
39
+ const configPath = findConfig(start)
40
+
41
+ if (configPath === null) {
42
+ return createLintConfig({ include: lintIncludeGlobs(start) })
43
+ }
44
+
45
+ const configDir = dirname(configPath)
46
+ loadEnvFiles(configDir)
47
+ registerTsResolveHooks()
48
+
49
+ let manifold: Manifold
50
+ try {
51
+ manifold = await importConfig(configPath)
52
+ } catch (err: unknown) {
53
+ const message = err instanceof Error ? err.message : String(err)
54
+ throw new Error(
55
+ `[pipework] Failed to load pipework.config.ts for eslint config resolution.\n\n` +
56
+ ` ${message}\n\n` +
57
+ ' The eslint config resolver imports your config to read `lint.extra`.\n' +
58
+ ' It does not connect to any database.\n',
59
+ )
60
+ }
61
+
62
+ const lint = manifold.config.raw.lint
63
+ if (lint === undefined) {
64
+ return createLintConfig({ include: lintIncludeGlobs(start) })
65
+ }
66
+
67
+ const extra = lint.extra
68
+ const moduleOverride = resolveModuleOverride(lint.modules, configDir, start)
69
+
70
+ const extraRules = { ...extra?.rules, ...moduleOverride.rules }
71
+ const extraConfigs = [...(extra?.configs ?? []), ...moduleOverride.configs]
72
+
73
+ const below = resolveBelowOverrides(lint, configDir, start)
74
+
75
+ const options: LintOptions = {
76
+ include: unique([...lintIncludeGlobs(start, moduleOverride.include ?? lint.include), ...below.include]),
77
+ ...(extra?.plugins !== undefined ? { extraPlugins: extra.plugins } : {}),
78
+ ...(Object.keys(extraRules).length > 0 ? { extraRules } : {}),
79
+ ...(extraConfigs.length > 0 || below.configs.length > 0 ? { extraConfigs: [...extraConfigs, ...below.configs] } : {}),
80
+ }
81
+
82
+ return createLintConfig(options)
83
+ }
84
+
85
+ function unique(globs: readonly string[]): string[] {
86
+ return [...new Set(globs)]
87
+ }
88
+
89
+ /**
90
+ * Every `lint.modules` entry as `{ path, config }`, glob keys expanded the same way as the
91
+ * top-level `modules` map. Glob keys come first so that when a glob expands to the same
92
+ * path as an explicit key, the explicit entry lands later; the callers' sort by path length
93
+ * is stable, so the explicit entry stays last and wins — an explicit module entry refines a
94
+ * glob match regardless of declaration order.
95
+ */
96
+ function moduleEntries(
97
+ modules: Record<string, LintModuleConfig> | undefined,
98
+ configDir: string,
99
+ ): Array<{ path: string; config: LintModuleConfig }> {
100
+ const entries: Array<{ path: string; config: LintModuleConfig }> = []
101
+ if (modules === undefined) return entries
102
+ for (const [key, config] of Object.entries(modules)) {
103
+ if (key.includes('*')) {
104
+ for (const path of expandGlob(key, configDir)) entries.push({ path, config })
105
+ }
106
+ }
107
+ for (const [key, config] of Object.entries(modules)) {
108
+ if (!key.includes('*')) entries.push({ path: key, config })
109
+ }
110
+ return entries
111
+ }
112
+
113
+ function prefixGlob(prefix: string, glob: string): string {
114
+ const negated = glob.startsWith('!')
115
+ const bare = (negated ? glob.slice(1) : glob).replace(/^\.\//, '')
116
+ return (negated ? '!' : '') + prefix + '/' + bare
117
+ }
118
+
119
+ // A flat-config `files` item is a glob or an array of globs that must all match.
120
+ function prefixFiles(prefix: string, files: unknown): unknown {
121
+ if (typeof files === 'string') return prefixGlob(prefix, files)
122
+ if (Array.isArray(files)) return files.map(f => prefixFiles(prefix, f))
123
+ return files
124
+ }
125
+
126
+ /**
127
+ * Re-root one module-relative flat-config entry at `prefix`. An entry with no `files`
128
+ * applied to the whole module, so it takes the module's include globs; an entry with only
129
+ * `ignores` is a global ignore and just has its patterns prefixed.
130
+ */
131
+ function prefixConfig(prefix: string, config: unknown, moduleFiles: readonly string[]): unknown {
132
+ if (typeof config !== 'object' || config === null || Array.isArray(config)) return config
133
+ const entry = { ...(config as Record<string, unknown>) }
134
+ const ignoresOnly = entry['files'] === undefined && entry['ignores'] !== undefined &&
135
+ Object.keys(entry).every(k => k === 'ignores' || k === 'name')
136
+ if (entry['files'] !== undefined) {
137
+ entry['files'] = prefixFiles(prefix, entry['files'])
138
+ } else if (!ignoresOnly) {
139
+ entry['files'] = moduleFiles.map(g => prefixGlob(prefix, g))
140
+ }
141
+ if (Array.isArray(entry['ignores'])) {
142
+ entry['ignores'] = entry['ignores'].map((g: unknown) => typeof g === 'string' ? prefixGlob(prefix, g) : g)
143
+ }
144
+ return entry
145
+ }
146
+
147
+ /**
148
+ * Overrides of modules strictly below `start`, as config entries scoped to each module's
149
+ * files, plus the module's include globs re-rooted at `start` so the main block reaches them.
150
+ */
151
+ function resolveBelowOverrides(
152
+ lint: { include?: readonly string[] | undefined; modules?: Record<string, LintModuleConfig> | undefined },
153
+ configDir: string,
154
+ start: string,
155
+ ): { configs: unknown[]; include: string[] } {
156
+ const configs: unknown[] = []
157
+ const include: string[] = []
158
+ const below = moduleEntries(lint.modules, configDir)
159
+ .map(e => ({ ...e, prefix: relative(start, join(configDir, e.path)).split(sep).join('/') }))
160
+ .filter(e => e.prefix !== '' && e.prefix !== '..' && !e.prefix.startsWith('../') && !e.prefix.startsWith('/'))
161
+ .sort((a, b) => a.prefix.length - b.prefix.length)
162
+
163
+ for (const { path, config, prefix } of below) {
164
+ const moduleFiles = lintIncludeGlobs(join(configDir, path), config.include ?? lint.include)
165
+ include.push(...moduleFiles.map(g => prefixGlob(prefix, g)))
166
+ if (config.rules !== undefined && Object.keys(config.rules).length > 0) {
167
+ configs.push({ files: moduleFiles.map(g => prefixGlob(prefix, g)), rules: config.rules })
168
+ }
169
+ for (const c of config.configs ?? []) configs.push(prefixConfig(prefix, c, moduleFiles))
170
+ }
171
+ return { configs, include }
172
+ }
173
+
174
+ /**
175
+ * Collect the `lint.modules` rules and configs that apply to `start`.
176
+ *
177
+ * `start` is the directory eslint runs in — a module directory for a per-module
178
+ * `pipework check` pass, or the repo root for the generated root `eslint.config.js`
179
+ * (where modules below it are handled by `resolveBelowOverrides`).
180
+ * An override applies when its module path (glob keys expanded the same way as the
181
+ * top-level `modules` map) contains `start`. Least-specific module first, so a deeper
182
+ * module's rules win, and a glob match is refined by an explicit module entry.
183
+ */
184
+ function resolveModuleOverride(
185
+ modules: Record<string, LintModuleConfig> | undefined,
186
+ configDir: string,
187
+ start: string,
188
+ ): { rules: Record<string, unknown>; configs: readonly unknown[]; include?: readonly string[] } {
189
+ if (modules === undefined) {
190
+ return { rules: {}, configs: [] }
191
+ }
192
+
193
+ // `findConfig` only walks upward, so `configDir` is always an ancestor of
194
+ // `start`; an empty `rel` means `start` *is* the repo root (the generated
195
+ // root eslint.config.js) — no module override applies there.
196
+ const rel = relative(configDir, start)
197
+ if (rel === '') {
198
+ return { rules: {}, configs: [] }
199
+ }
200
+
201
+ const entries = moduleEntries(modules, configDir)
202
+
203
+ const matching = entries
204
+ .filter(e => rel === e.path || rel.startsWith(e.path + '/'))
205
+ .sort((a, b) => a.path.length - b.path.length)
206
+
207
+ let rules: Record<string, unknown> = {}
208
+ let configs: readonly unknown[] = []
209
+ let include: readonly string[] | undefined
210
+ for (const { config } of matching) {
211
+ rules = { ...rules, ...config.rules }
212
+ configs = [...configs, ...(config.configs ?? [])]
213
+ // Replaced, not merged: `include` names the module's sources outright, so the
214
+ // deepest module that declares it wins rather than accumulating a union.
215
+ if (config.include !== undefined) include = config.include
216
+ }
217
+ return { rules, configs, ...(include !== undefined ? { include } : {}) }
218
+ }
@@ -0,0 +1,46 @@
1
+ import type { Rule } from 'eslint'
2
+
3
+ function isTypeOnly(node: Record<string, unknown>): boolean {
4
+ return (node as Record<string, unknown>)['exportKind'] === 'type'
5
+ }
6
+
7
+ export const noReexports: Rule.RuleModule = {
8
+ meta: {
9
+ type: 'problem',
10
+ docs: {
11
+ description: 'Disallow re-exporting from other modules. Each module should export its own declarations.',
12
+ },
13
+ messages: {
14
+ noReexport:
15
+ 'Do not re-export from "{{source}}". Import into the consuming module directly.\n' +
16
+ 'Re-exports create hidden coupling and make it harder to trace where a symbol is defined.',
17
+ noBarrelExport:
18
+ 'Do not use `export * from "{{source}}"`. Barrel files obscure the dependency graph.\n' +
19
+ 'Import from the source module directly.',
20
+ },
21
+ schema: [],
22
+ },
23
+
24
+ create(context) {
25
+ return {
26
+ ExportAllDeclaration(node) {
27
+ if (isTypeOnly(node as unknown as Record<string, unknown>)) return
28
+ context.report({
29
+ node,
30
+ messageId: 'noBarrelExport',
31
+ data: { source: String(node.source.value) },
32
+ })
33
+ },
34
+
35
+ ExportNamedDeclaration(node) {
36
+ if (node.source === null || node.source === undefined) return
37
+ if (isTypeOnly(node as unknown as Record<string, unknown>)) return
38
+ context.report({
39
+ node,
40
+ messageId: 'noReexport',
41
+ data: { source: String(node.source.value) },
42
+ })
43
+ },
44
+ }
45
+ },
46
+ }
@@ -0,0 +1,85 @@
1
+ import type { DB } from '../../data/db/index.js'
2
+ import type { ResourceOperations, ResourceId } from '../fixture/types.js'
3
+ import type { AuditedBehaviorConfig } from './types.js'
4
+ import type { Audit, AuditEmitOptions } from '../../infra/audit/types.js'
5
+ import { singularize } from '../internal/text.js'
6
+
7
+ export function applyAudited<TAuth>(
8
+ ops: ResourceOperations<TAuth>,
9
+ config: AuditedBehaviorConfig | Audit,
10
+ resourceName: string,
11
+ ): ResourceOperations<TAuth> {
12
+ const audit: Audit = 'emit' in config ? config : config.audit
13
+ const isConfig = !('emit' in config)
14
+ const entityType = isConfig && (config as AuditedBehaviorConfig).entityType !== undefined
15
+ ? (config as AuditedBehaviorConfig).entityType!
16
+ : singularize(resourceName)
17
+ const prefix = isConfig && (config as AuditedBehaviorConfig).actionPrefix !== undefined
18
+ ? (config as AuditedBehaviorConfig).actionPrefix!
19
+ : entityType
20
+
21
+ const result: Record<string, unknown> = { ...ops }
22
+
23
+ if (ops.create !== undefined) {
24
+ const original = ops.create
25
+ result['create'] = {
26
+ input: original.input,
27
+ handler: async (db: DB, auth: TAuth, tenant: string, input: unknown) => {
28
+ const created = await original.handler(db, auth, tenant, input)
29
+ const opts: AuditEmitOptions = {
30
+ actionType: `${prefix}.created`,
31
+ entityType,
32
+ entityId: extractEntityId(created),
33
+ after: created,
34
+ }
35
+ await audit.emit(opts)
36
+ return created
37
+ },
38
+ }
39
+ }
40
+
41
+ if (ops.update !== undefined) {
42
+ const original = ops.update
43
+ result['update'] = {
44
+ input: original.input,
45
+ handler: async (db: DB, auth: TAuth, tenant: string, id: ResourceId, input: unknown) => {
46
+ const before = ops.get !== undefined ? await ops.get(db, auth, tenant, id) : null
47
+ const updated = await original.handler(db, auth, tenant, id, input)
48
+ const opts: AuditEmitOptions = {
49
+ actionType: `${prefix}.updated`,
50
+ entityType,
51
+ entityId: id,
52
+ before: before ?? undefined,
53
+ after: updated,
54
+ }
55
+ await audit.emit(opts)
56
+ return updated
57
+ },
58
+ }
59
+ }
60
+
61
+ if (ops.delete !== undefined) {
62
+ const original = ops.delete
63
+ result['delete'] = async (db: DB, auth: TAuth, tenant: string, id: ResourceId) => {
64
+ const before = ops.get !== undefined ? await ops.get(db, auth, tenant, id) : null
65
+ await original(db, auth, tenant, id)
66
+ const opts: AuditEmitOptions = {
67
+ actionType: `${prefix}.deleted`,
68
+ entityType,
69
+ entityId: id,
70
+ before: before ?? undefined,
71
+ }
72
+ await audit.emit(opts)
73
+ }
74
+ }
75
+
76
+ return result as ResourceOperations<TAuth>
77
+ }
78
+
79
+ function extractEntityId(result: unknown): string {
80
+ if (result !== null && typeof result === 'object' && 'id' in result) {
81
+ return String((result as { id: unknown }).id)
82
+ }
83
+ return 'unknown'
84
+ }
85
+
@@ -0,0 +1,62 @@
1
+ import type { DB } from '../../data/db/index.js'
2
+ import type { ResourceOperations, ResourceId } from '../fixture/types.js'
3
+ import type { InvalidationBehaviorConfig } from './types.js'
4
+ import { createCache } from '../../infra/cache/create.js'
5
+ import type { Cache } from '../../infra/cache/types.js'
6
+
7
+ export function withInvalidation<TAuth>(
8
+ ops: ResourceOperations<TAuth>,
9
+ config: InvalidationBehaviorConfig,
10
+ resourceName: string,
11
+ ): ResourceOperations<TAuth> & { readonly cache: Cache<unknown[]> } {
12
+ const listCache = createCache<unknown[]>({
13
+ name: `resource:${resourceName}:list`,
14
+ database: config.database,
15
+ ttlMs: config.ttlMs,
16
+ load: () => Promise.resolve([]),
17
+ })
18
+
19
+ const result: Record<string, unknown> = { ...ops, cache: listCache }
20
+
21
+ if (ops.list !== undefined) {
22
+ const original = ops.list
23
+ result['list'] = async (db: DB, auth: TAuth, tenant: string) => {
24
+ const data = await original(db, auth, tenant)
25
+ return data
26
+ }
27
+ }
28
+
29
+ if (ops.create !== undefined) {
30
+ const original = ops.create
31
+ result['create'] = {
32
+ input: original.input,
33
+ handler: async (db: DB, auth: TAuth, tenant: string, input: unknown) => {
34
+ const created = await original.handler(db, auth, tenant, input)
35
+ listCache.invalidate()
36
+ return created
37
+ },
38
+ }
39
+ }
40
+
41
+ if (ops.update !== undefined) {
42
+ const original = ops.update
43
+ result['update'] = {
44
+ input: original.input,
45
+ handler: async (db: DB, auth: TAuth, tenant: string, id: ResourceId, input: unknown) => {
46
+ const updated = await original.handler(db, auth, tenant, id, input)
47
+ listCache.invalidate()
48
+ return updated
49
+ },
50
+ }
51
+ }
52
+
53
+ if (ops.delete !== undefined) {
54
+ const original = ops.delete
55
+ result['delete'] = async (db: DB, _auth: TAuth, _tenant: string, id: ResourceId) => {
56
+ await original(db, _auth, _tenant, id)
57
+ listCache.invalidate()
58
+ }
59
+ }
60
+
61
+ return result as unknown as ResourceOperations<TAuth> & { readonly cache: Cache<unknown[]> }
62
+ }
@@ -0,0 +1,28 @@
1
+ import type { ResourceOperations } from '../fixture/types.js'
2
+ import type { BehaviorConfig } from './types.js'
3
+ import { applyVersioned } from './versioned.js'
4
+ import { applyAudited } from './audited.js'
5
+ import { withInvalidation } from './cached.js'
6
+
7
+ export function withBehaviors<TAuth>(
8
+ ops: ResourceOperations<TAuth>,
9
+ config: BehaviorConfig,
10
+ resourceName?: string,
11
+ ): ResourceOperations<TAuth> {
12
+ const name = resourceName ?? 'resource'
13
+ let decorated = ops
14
+
15
+ if (config.versioned !== undefined) {
16
+ decorated = applyVersioned(decorated, config.versioned, name)
17
+ }
18
+
19
+ if (config.audited !== undefined) {
20
+ decorated = applyAudited(decorated, config.audited, name)
21
+ }
22
+
23
+ if (config.cached !== undefined) {
24
+ decorated = withInvalidation(decorated, config.cached, name)
25
+ }
26
+
27
+ return decorated
28
+ }
@@ -0,0 +1,5 @@
1
+ export { withBehaviors } from './compose.js'
2
+ export { applyVersioned } from './versioned.js'
3
+ export { applyAudited } from './audited.js'
4
+ export { withInvalidation } from './cached.js'
5
+ export type { BehaviorConfig, VersionedBehaviorConfig, AuditedBehaviorConfig, InvalidationBehaviorConfig } from './types.js'
@@ -0,0 +1,16 @@
1
+ import { withBehaviors } from './compose.js'
2
+ import { applyVersioned } from './versioned.js'
3
+ import { applyAudited } from './audited.js'
4
+ import { withInvalidation } from './cached.js'
5
+
6
+ /** Resource behavior decorators — compose versioning, audit trails, and cache invalidation onto CRUD operations. */
7
+ export const behavior = {
8
+ /** Applies multiple behaviors to a ResourceOperations set in order. */
9
+ compose: withBehaviors,
10
+ /** Adds optimistic concurrency control via a version column — rejects stale updates. */
11
+ versioned: applyVersioned,
12
+ /** Wraps operations to emit audit records on create/update/delete. */
13
+ audited: applyAudited,
14
+ /** Wraps operations to invalidate a cache on mutations. Returns ops with an attached .cache handle. */
15
+ invalidate: withInvalidation,
16
+ }
@@ -0,0 +1,26 @@
1
+ import type { Audit } from '../../infra/audit/types.js'
2
+ import type { SQL, DB } from '../../data/db/types.js'
3
+
4
+ export interface VersionedBehaviorConfig {
5
+ readonly table: string
6
+ readonly whereFromId?: (id: string) => SQL
7
+ readonly softDelete?: boolean
8
+ readonly beforeRevise?: (db: DB, auth: unknown, tenant: string, id: string, input: unknown) => Promise<void>
9
+ }
10
+
11
+ export interface AuditedBehaviorConfig {
12
+ readonly audit: Audit
13
+ readonly entityType?: string
14
+ readonly actionPrefix?: string
15
+ }
16
+
17
+ export interface InvalidationBehaviorConfig {
18
+ readonly ttlMs: number
19
+ readonly database: string
20
+ }
21
+
22
+ export interface BehaviorConfig {
23
+ readonly versioned?: VersionedBehaviorConfig
24
+ readonly audited?: AuditedBehaviorConfig | Audit
25
+ readonly cached?: InvalidationBehaviorConfig
26
+ }
@@ -0,0 +1,54 @@
1
+ import type { DB } from '../../data/db/index.js'
2
+ import type { ResourceOperations, ResourceId } from '../fixture/types.js'
3
+ import type { VersionedBehaviorConfig } from './types.js'
4
+ import type { ReviseOptions } from '../../data/temporal/types.js'
5
+ import { sql } from '../../data/db/sql.js'
6
+ import { revise } from '../../data/temporal/revise.js'
7
+
8
+ export function applyVersioned<TAuth>(
9
+ ops: ResourceOperations<TAuth>,
10
+ config: VersionedBehaviorConfig,
11
+ _resourceName: string,
12
+ ): ResourceOperations<TAuth> {
13
+ const softDelete = config.softDelete !== false
14
+
15
+ const buildWhere = config.whereFromId
16
+ ?? ((id: string) => sql`id = ${id}::uuid`)
17
+
18
+ const result: Record<string, unknown> = { ...ops }
19
+
20
+ if (ops.update !== undefined) {
21
+ const originalUpdate = ops.update
22
+ result['update'] = {
23
+ input: originalUpdate.input,
24
+ handler: async (db: DB, auth: TAuth, _tenant: string, id: ResourceId, input: unknown) => {
25
+ return (db as DB).transaction(async (tx) => {
26
+ await config.beforeRevise?.(db, auth, _tenant, id, input)
27
+ const userId = extractUserId(auth)
28
+ const opts: ReviseOptions = userId !== undefined
29
+ ? { tx, table: config.table, where: sql`${buildWhere(id)} AND effective_to IS NULL`, data: input as Record<string, unknown>, userId }
30
+ : { tx, table: config.table, where: sql`${buildWhere(id)} AND effective_to IS NULL`, data: input as Record<string, unknown> }
31
+ return revise(opts)
32
+ })
33
+ },
34
+ }
35
+ }
36
+
37
+ if (ops.delete !== undefined && softDelete) {
38
+ result['delete'] = async (db: DB, _auth: TAuth, _tenant: string, id: ResourceId) => {
39
+ await db.execute(
40
+ sql`UPDATE ${sql.identifier(config.table)} SET effective_to = now() WHERE ${buildWhere(id)} AND effective_to IS NULL`,
41
+ )
42
+ }
43
+ }
44
+
45
+ return result as ResourceOperations<TAuth>
46
+ }
47
+
48
+ function extractUserId(auth: unknown): string | undefined {
49
+ if (auth !== null && typeof auth === 'object' && 'userId' in auth) {
50
+ const userId = (auth as { userId: unknown }).userId
51
+ if (typeof userId === 'string') return userId
52
+ }
53
+ return undefined
54
+ }