@cosmicdrift/kumiko-framework 0.389.0 → 0.390.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (617) hide show
  1. package/AGENTS.md +9 -4
  2. package/README.md +1 -1
  3. package/agents/examples/apex-surface-auth.md +2 -3
  4. package/agents/examples/api-worker-split.md +9 -2
  5. package/agents/examples/auth-claims.md +1 -1
  6. package/agents/examples/cross-feature-events.md +12 -12
  7. package/agents/examples/crypto-shredding-hr.md +2 -2
  8. package/agents/examples/encrypted-tenant-config.md +1 -1
  9. package/agents/examples/error-contract.md +12 -7
  10. package/agents/examples/event-sourcing.md +29 -29
  11. package/agents/examples/files-post-processing.md +10 -8
  12. package/agents/examples/inbound-mail-triage.md +1 -0
  13. package/agents/examples/lane-routing.md +2 -1
  14. package/agents/examples/legal-pages.md +2 -2
  15. package/agents/examples/lifecycle-hooks.md +3 -3
  16. package/agents/examples/managed-config.md +4 -4
  17. package/agents/examples/managed-pages.md +1 -1
  18. package/agents/examples/relations.md +19 -4
  19. package/agents/examples/search.md +4 -4
  20. package/agents/examples/secrets-demo.md +9 -6
  21. package/agents/examples/state-machine.md +2 -2
  22. package/agents/examples/tenant-settings.md +1 -1
  23. package/agents/examples/user-data-rights.md +3 -6
  24. package/agents/examples/workflow-engine.md +53 -47
  25. package/agents/examples.md +4 -4
  26. package/agents/features.md +1 -1
  27. package/dist/api/auth-middleware.js +1 -1
  28. package/dist/api/auth-routes-invite.js +2 -1
  29. package/dist/api/entity-read-access.d.ts +3 -1
  30. package/dist/api/export/export-columns.d.ts +3 -1
  31. package/dist/api/export/export-route.js +3 -2
  32. package/dist/api/export/export-screen.d.ts +2 -1
  33. package/dist/api/extra-route.d.ts +3 -1
  34. package/dist/api/index.d.ts +23 -27
  35. package/dist/api/index.js +13 -15
  36. package/dist/api/jwt.js +1 -1
  37. package/dist/api/observability-middleware.d.ts +1 -1
  38. package/dist/api/observability-middleware.js +2 -1
  39. package/dist/api/request-context-internals.d.ts +31 -0
  40. package/dist/api/request-context-internals.js +11 -0
  41. package/dist/api/request-context-scopes.d.ts +14 -0
  42. package/dist/api/request-context-scopes.js +69 -0
  43. package/dist/api/request-context.d.ts +1 -40
  44. package/dist/api/request-context.js +22 -51
  45. package/dist/api/request-id-middleware.d.ts +1 -1
  46. package/dist/api/route-registrars.d.ts +2 -1
  47. package/dist/api/route-registrars.js +1 -1
  48. package/dist/api/routes.js +7 -3
  49. package/dist/api/server-boot-checks.d.ts +1 -1
  50. package/dist/api/server-boot-checks.js +2 -2
  51. package/dist/api/server-event-dispatcher.d.ts +6 -1
  52. package/dist/api/server-event-dispatcher.js +3 -4
  53. package/dist/api/server-extra-routes.d.ts +1 -1
  54. package/dist/api/server-extra-routes.js +2 -1
  55. package/dist/api/server-middleware.js +3 -1
  56. package/dist/api/server-routes.d.ts +2 -1
  57. package/dist/api/server-wiring.js +6 -4
  58. package/dist/api/server.d.ts +2 -1
  59. package/dist/api/sse-route.d.ts +2 -1
  60. package/dist/api/tenant-scoped-secrets.d.ts +2 -0
  61. package/dist/api/tenant-scoped-secrets.js +13 -0
  62. package/dist/api/websocket-route.d.ts +1 -1
  63. package/dist/auth/index.d.ts +0 -1
  64. package/dist/auth/roles.d.ts +0 -5
  65. package/dist/compliance/duration-spec.d.ts +0 -1
  66. package/dist/compliance/duration-spec.js +0 -5
  67. package/dist/compliance/index.d.ts +4 -4
  68. package/dist/compliance/index.js +2 -2
  69. package/dist/compliance/profiles.d.ts +0 -15
  70. package/dist/compliance/profiles.js +0 -23
  71. package/dist/config/index.d.ts +10 -10
  72. package/dist/config/index.js +13 -1
  73. package/dist/config/internals.d.ts +9 -0
  74. package/dist/config/internals.js +1 -0
  75. package/dist/consumer-cli-internals.d.ts +4 -0
  76. package/dist/consumer-cli-internals.js +1 -0
  77. package/dist/consumer-cli.d.ts +1 -4
  78. package/dist/consumer-cli.js +5 -1
  79. package/dist/crypto/event-pii.js +1 -1
  80. package/dist/crypto/index.d.ts +8 -9
  81. package/dist/crypto/index.js +7 -8
  82. package/dist/crypto/pg-kms-adapter.js +6 -1
  83. package/dist/db/apply-entity-event.d.ts +1 -1
  84. package/dist/db/apply-entity-event.js +15 -47
  85. package/dist/db/blind-index-cleanup.js +91 -77
  86. package/dist/db/collect-table-metas.js +1 -1
  87. package/dist/db/compound-types.d.ts +1 -1
  88. package/dist/db/compound-types.js +0 -7
  89. package/dist/db/config-seed.d.ts +2 -1
  90. package/dist/db/config-seed.js +6 -1
  91. package/dist/db/connection.d.ts +3 -1
  92. package/dist/db/connection.js +15 -5
  93. package/dist/db/cross-tenant-reads.d.ts +1 -1
  94. package/dist/db/cross-tenant-reads.js +1 -1
  95. package/dist/db/dialect.d.ts +0 -5
  96. package/dist/db/dialect.js +0 -3
  97. package/dist/db/driver-value-preparation.js +23 -2
  98. package/dist/db/eagerload.d.ts +2 -1
  99. package/dist/db/entity-field-encryption.d.ts +1 -1
  100. package/dist/db/entity-table-meta.d.ts +1 -1
  101. package/dist/db/event-store-executor-context.d.ts +3 -1
  102. package/dist/db/event-store-executor-context.js +4 -3
  103. package/dist/db/event-store-executor-read-filter.d.ts +1 -1
  104. package/dist/db/event-store-executor-read-rows.d.ts +2 -1
  105. package/dist/db/event-store-executor-read-search.d.ts +2 -1
  106. package/dist/db/event-store-executor-read-sort.d.ts +2 -1
  107. package/dist/db/event-store-executor-read.js +2 -2
  108. package/dist/db/event-store-executor-write-atomic.js +8 -7
  109. package/dist/db/event-store-executor-write-steps.d.ts +3 -2
  110. package/dist/db/event-store-executor-write.js +7 -4
  111. package/dist/db/event-store-executor.d.ts +1 -1
  112. package/dist/db/executor-managed-tables.d.ts +7 -1
  113. package/dist/db/executor-managed-tables.js +11 -2
  114. package/dist/db/index.d.ts +29 -28
  115. package/dist/db/index.js +22 -20
  116. package/dist/db/known-table-names.d.ts +6 -0
  117. package/dist/db/known-table-names.js +21 -0
  118. package/dist/db/list-aggregate-labels.d.ts +1 -1
  119. package/dist/db/located-timestamp.d.ts +1 -1
  120. package/dist/db/located-timestamp.js +0 -5
  121. package/dist/db/migrate-generator.d.ts +17 -1
  122. package/dist/db/migrate-generator.js +50 -20
  123. package/dist/db/migrate-primary-key.d.ts +12 -0
  124. package/dist/db/migrate-primary-key.js +45 -0
  125. package/dist/db/migrate-rls-diff.d.ts +20 -0
  126. package/dist/db/migrate-rls-diff.js +61 -0
  127. package/dist/db/migrate-runner.js +4 -0
  128. package/dist/db/money.d.ts +1 -1
  129. package/dist/db/money.js +1 -1
  130. package/dist/db/parent-ref-clause.d.ts +2 -1
  131. package/dist/db/pg-error.d.ts +2 -0
  132. package/dist/db/pg-error.js +11 -0
  133. package/dist/db/queries/ddl.d.ts +3 -0
  134. package/dist/db/queries/ddl.js +34 -1
  135. package/dist/db/queries/event-store.js +4 -2
  136. package/dist/db/queries/event-tenants.d.ts +2 -0
  137. package/dist/db/queries/event-tenants.js +17 -0
  138. package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
  139. package/dist/db/queries/rebuild-rls-guard.js +29 -0
  140. package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
  141. package/dist/db/queries/rls-boot-catalog.js +39 -0
  142. package/dist/db/queries/rls-catalog.d.ts +6 -0
  143. package/dist/db/queries/rls-catalog.js +82 -0
  144. package/dist/db/queries/rls-scope.d.ts +3 -0
  145. package/dist/db/queries/rls-scope.js +17 -0
  146. package/dist/db/queries/rls-shape.d.ts +10 -0
  147. package/dist/db/queries/rls-shape.js +42 -0
  148. package/dist/db/queries/session-advisory-lock.d.ts +2 -0
  149. package/dist/db/queries/session-advisory-lock.js +23 -0
  150. package/dist/db/queries/shadow-swap.d.ts +1 -2
  151. package/dist/db/queries/shadow-swap.js +9 -25
  152. package/dist/db/queries/test-stack.d.ts +4 -1
  153. package/dist/db/queries/test-stack.js +84 -2
  154. package/dist/db/query.js +11 -7
  155. package/dist/db/reference-data.d.ts +1 -1
  156. package/dist/db/reference-data.js +6 -1
  157. package/dist/db/render-ddl.d.ts +6 -2
  158. package/dist/db/render-ddl.js +7 -7
  159. package/dist/db/render-rls-ddl.d.ts +35 -0
  160. package/dist/db/render-rls-ddl.js +127 -0
  161. package/dist/db/replay-migration-sql.d.ts +3 -1
  162. package/dist/db/replay-migration-sql.js +22 -5
  163. package/dist/db/replay-rls.d.ts +25 -0
  164. package/dist/db/replay-rls.js +156 -0
  165. package/dist/db/row-level-security-boot-check.d.ts +6 -0
  166. package/dist/db/row-level-security-boot-check.js +86 -0
  167. package/dist/db/row-level-security-connection.d.ts +3 -0
  168. package/dist/db/row-level-security-connection.js +213 -0
  169. package/dist/db/row-level-security-scope.d.ts +33 -0
  170. package/dist/db/row-level-security-scope.js +127 -0
  171. package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
  172. package/dist/db/scope-tenant-db-to-tenant.js +14 -0
  173. package/dist/db/sql-identifier.d.ts +1 -0
  174. package/dist/db/sql-identifier.js +3 -0
  175. package/dist/db/table-builder.d.ts +2 -1
  176. package/dist/db/table-builder.js +1 -1
  177. package/dist/db/table-info.js +1 -1
  178. package/dist/db/table-push.d.ts +11 -2
  179. package/dist/db/table-push.js +15 -2
  180. package/dist/db/tenant-db-runner.d.ts +3 -1
  181. package/dist/db/tenant-db-runner.js +4 -3
  182. package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
  183. package/dist/db/tenant-db-scoped-rebind.js +33 -0
  184. package/dist/db/tenant-db-statement-runner.d.ts +13 -0
  185. package/dist/db/tenant-db-statement-runner.js +48 -0
  186. package/dist/db/tenant-db.d.ts +17 -12
  187. package/dist/db/tenant-db.js +49 -120
  188. package/dist/db/tenant-id-filter.d.ts +3 -0
  189. package/dist/db/tenant-id-filter.js +30 -0
  190. package/dist/db/transaction-serialization.d.ts +6 -0
  191. package/dist/db/transaction-serialization.js +60 -0
  192. package/dist/derivatives/delete-stored-file.js +1 -1
  193. package/dist/derivatives/index.d.ts +2 -5
  194. package/dist/derivatives/index.js +2 -3
  195. package/dist/engine/access.d.ts +2 -1
  196. package/dist/engine/access.js +1 -1
  197. package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
  198. package/dist/engine/boot-validator/entity-handler.js +1 -1
  199. package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +1 -1
  200. package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +1 -1
  201. package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +2 -1
  202. package/dist/engine/boot-validator/nav.d.ts +3 -1
  203. package/dist/engine/boot-validator/nav.js +1 -1
  204. package/dist/engine/boot-validator/ownership.d.ts +2 -1
  205. package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
  206. package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
  207. package/dist/engine/boot-validator/query-refs.d.ts +2 -1
  208. package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
  209. package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
  210. package/dist/engine/boot-validator/screens.d.ts +2 -1
  211. package/dist/engine/boot-validator/workspaces.d.ts +3 -1
  212. package/dist/engine/bridge-stub.d.ts +5 -2
  213. package/dist/engine/bridge-stub.js +39 -24
  214. package/dist/engine/config-helpers.d.ts +2 -2
  215. package/dist/engine/config-helpers.js +0 -9
  216. package/dist/engine/constants.d.ts +0 -10
  217. package/dist/engine/constants.js +0 -8
  218. package/dist/engine/create-app.js +1 -1
  219. package/dist/engine/define-feature.d.ts +2 -1
  220. package/dist/engine/define-feature.js +1 -2
  221. package/dist/engine/define-handler.d.ts +1 -1
  222. package/dist/engine/define-step.d.ts +0 -1
  223. package/dist/engine/define-step.js +0 -3
  224. package/dist/engine/embedded-derived.d.ts +1 -1
  225. package/dist/engine/entity-handlers.d.ts +2 -1
  226. package/dist/engine/entity-handlers.js +7 -7
  227. package/dist/engine/entity-list-runtime-options.js +3 -1
  228. package/dist/engine/entity-list-searchability.d.ts +2 -1
  229. package/dist/engine/event-def.d.ts +2 -1
  230. package/dist/engine/event-helpers.d.ts +3 -1
  231. package/dist/engine/event-helpers.js +3 -3
  232. package/dist/engine/extension-names.d.ts +2 -8
  233. package/dist/engine/extension-names.js +2 -2
  234. package/dist/engine/extension-selector-plugins.d.ts +1 -1
  235. package/dist/engine/extensions/storage-provider.d.ts +1 -2
  236. package/dist/engine/extensions/user-data.d.ts +0 -8
  237. package/dist/engine/factories.d.ts +2 -1
  238. package/dist/engine/feature-builder-state.d.ts +8 -1
  239. package/dist/engine/feature-changelog.d.ts +1 -1
  240. package/dist/engine/feature-config-events-jobs.d.ts +4 -1
  241. package/dist/engine/feature-entity-handlers.d.ts +5 -1
  242. package/dist/engine/feature-manifest.js +1 -1
  243. package/dist/engine/feature-ui-extensions.d.ts +7 -1
  244. package/dist/engine/feature-ui-extensions.js +6 -4
  245. package/dist/engine/field-access.d.ts +2 -1
  246. package/dist/engine/handler-field-references.d.ts +0 -4
  247. package/dist/engine/index.d.ts +57 -54
  248. package/dist/engine/index.js +22 -27
  249. package/dist/engine/instruction-fields.d.ts +1 -1
  250. package/dist/engine/personal-data-fields.d.ts +1 -1
  251. package/dist/engine/qualified-name.d.ts +0 -1
  252. package/dist/engine/read-claim.d.ts +2 -1
  253. package/dist/engine/registry-facade.js +0 -3
  254. package/dist/engine/registry-ingest.d.ts +2 -1
  255. package/dist/engine/registry-ingest.js +1 -2
  256. package/dist/engine/registry-state.d.ts +12 -2
  257. package/dist/engine/registry-state.js +2 -3
  258. package/dist/engine/registry-validate.d.ts +3 -1
  259. package/dist/engine/registry-validate.js +7 -7
  260. package/dist/engine/run-in.d.ts +1 -1
  261. package/dist/engine/run-in.js +0 -1
  262. package/dist/engine/schema-builder.d.ts +1 -1
  263. package/dist/engine/schema-builder.js +1 -1
  264. package/dist/engine/screen-filter-ops.d.ts +2 -1
  265. package/dist/engine/screen-filter-ops.js +0 -5
  266. package/dist/engine/soft-delete-cleanup.d.ts +1 -1
  267. package/dist/engine/soft-delete-cleanup.js +4 -4
  268. package/dist/engine/state-machine.js +2 -1
  269. package/dist/engine/steps/_read-source.js +1 -1
  270. package/dist/engine/steps/aggregate-append-event.js +2 -2
  271. package/dist/engine/steps/call-feature.js +2 -2
  272. package/dist/engine/steps/mail-send.js +1 -1
  273. package/dist/engine/steps/retry.js +1 -1
  274. package/dist/engine/steps/wait-for-event.js +1 -1
  275. package/dist/engine/steps/wait.js +1 -1
  276. package/dist/engine/steps/webhook-send.js +1 -1
  277. package/dist/engine/template-variables.d.ts +2 -1
  278. package/dist/engine/transfer-adjacency.d.ts +1 -1
  279. package/dist/engine/types/index.d.ts +8 -31
  280. package/dist/engine/types/index.js +2 -10
  281. package/dist/engine/validation.d.ts +2 -1
  282. package/dist/entrypoint/index.d.ts +7 -35
  283. package/dist/entrypoint/index.js +7 -1
  284. package/dist/entrypoint/internals.d.ts +40 -0
  285. package/dist/entrypoint/internals.js +1 -0
  286. package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
  287. package/dist/entrypoint/row-level-security-mode-check.js +19 -0
  288. package/dist/env/dry-run-internals.d.ts +10 -0
  289. package/dist/env/dry-run-internals.js +1 -0
  290. package/dist/env/dry-run.d.ts +1 -10
  291. package/dist/env/dry-run.js +2 -1
  292. package/dist/env/index.d.ts +1 -85
  293. package/dist/env/index.js +6 -50
  294. package/dist/env/internals.d.ts +87 -0
  295. package/dist/env/internals.js +53 -0
  296. package/dist/errors/classes.js +2 -2
  297. package/dist/errors/index.d.ts +5 -14
  298. package/dist/errors/index.js +4 -9
  299. package/dist/errors/member-resolution.js +1 -1
  300. package/dist/errors/reasons.d.ts +0 -1
  301. package/dist/errors/reasons.js +7 -7
  302. package/dist/errors/serialize.d.ts +0 -18
  303. package/dist/errors/serialize.js +0 -27
  304. package/dist/es-ops/index.d.ts +4 -4
  305. package/dist/es-ops/index.js +2 -2
  306. package/dist/es-ops/operations-schema.d.ts +1 -1
  307. package/dist/es-ops/types.d.ts +4 -5
  308. package/dist/event-store/admin-api-internals.d.ts +14 -0
  309. package/dist/event-store/admin-api-internals.js +1 -0
  310. package/dist/event-store/admin-api.d.ts +1 -14
  311. package/dist/event-store/admin-api.js +11 -6
  312. package/dist/event-store/archive.js +4 -2
  313. package/dist/event-store/errors.js +2 -2
  314. package/dist/event-store/event-store.js +41 -34
  315. package/dist/event-store/events-schema.js +4 -1
  316. package/dist/event-store/index.d.ts +11 -13
  317. package/dist/event-store/index.js +7 -9
  318. package/dist/event-store/rebuild-dead-letter.js +4 -2
  319. package/dist/event-store/snapshot.js +4 -3
  320. package/dist/event-store/stream-scope.d.ts +2 -0
  321. package/dist/event-store/stream-scope.js +6 -0
  322. package/dist/event-store/upcaster-dead-letter.js +4 -2
  323. package/dist/event-store/upcaster.d.ts +2 -1
  324. package/dist/files/action-form-upload.d.ts +2 -1
  325. package/dist/files/action-form-upload.js +1 -1
  326. package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
  327. package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
  328. package/dist/files/bind-pending-file-refs.d.ts +2 -1
  329. package/dist/files/bind-pending-file-refs.js +2 -1
  330. package/dist/files/bind-referenced-files.write.js +1 -1
  331. package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
  332. package/dist/files/create-file-ref-from-bytes.js +3 -3
  333. package/dist/files/create-file-ref.d.ts +3 -2
  334. package/dist/files/create-file-ref.js +2 -2
  335. package/dist/files/dispose-removed-file-refs.d.ts +2 -1
  336. package/dist/files/dispose-removed-file-refs.js +1 -1
  337. package/dist/files/feature.js +2 -2
  338. package/dist/files/file-handle.js +1 -1
  339. package/dist/files/file-routes.d.ts +1 -1
  340. package/dist/files/file-routes.js +12 -2
  341. package/dist/files/index.d.ts +11 -13
  342. package/dist/files/index.js +5 -7
  343. package/dist/files/load-save-file-refs.d.ts +2 -1
  344. package/dist/files/load-save-file-refs.js +1 -1
  345. package/dist/files/provider-resolver.d.ts +5 -4
  346. package/dist/files/provider-resolver.js +4 -4
  347. package/dist/files/storage-tracking.js +4 -2
  348. package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
  349. package/dist/files/sweep-orphaned-uploads.js +1 -1
  350. package/dist/i18n/index.d.ts +2 -8
  351. package/dist/i18n/index.js +1 -1
  352. package/dist/i18n/internals.d.ts +7 -0
  353. package/dist/i18n/internals.js +1 -0
  354. package/dist/i18n/required-surface-keys.d.ts +4 -1
  355. package/dist/internal/row-level-security.d.ts +3 -0
  356. package/dist/internal/row-level-security.js +3 -0
  357. package/dist/internal/stack-support.d.ts +1 -1
  358. package/dist/internal/stack-support.js +1 -1
  359. package/dist/internal/testing.d.ts +1 -0
  360. package/dist/internal/testing.js +9 -5
  361. package/dist/jobs/index.d.ts +1 -1
  362. package/dist/jobs/job-append-event.d.ts +12 -0
  363. package/dist/jobs/job-append-event.js +30 -0
  364. package/dist/jobs/job-runner-context.d.ts +2 -2
  365. package/dist/jobs/job-runner-context.js +46 -16
  366. package/dist/jobs/job-runner-execution.d.ts +1 -1
  367. package/dist/jobs/job-runner-execution.js +6 -4
  368. package/dist/jobs/job-runner-gates.d.ts +1 -1
  369. package/dist/jobs/job-runner-gates.js +0 -1
  370. package/dist/jobs/job-runner-helpers.d.ts +11 -4
  371. package/dist/jobs/job-runner-helpers.js +10 -1
  372. package/dist/jobs/job-runner-scope.d.ts +5 -2
  373. package/dist/jobs/job-runner-types.d.ts +2 -1
  374. package/dist/jobs/job-runner.js +19 -6
  375. package/dist/jobs/max-per-tenant.d.ts +1 -1
  376. package/dist/logging/index.d.ts +1 -2
  377. package/dist/logging/index.js +1 -1
  378. package/dist/logging/pino-logger.js +1 -1
  379. package/dist/logging/utils.d.ts +1 -0
  380. package/dist/logging/utils.js +6 -0
  381. package/dist/migrations/index.d.ts +3 -3
  382. package/dist/migrations/index.js +3 -3
  383. package/dist/migrations/pending-rebuilds.d.ts +1 -1
  384. package/dist/migrations/pending-rebuilds.js +1 -1
  385. package/dist/migrations/pii-event-backfill.js +4 -1
  386. package/dist/observability/escape-hatch-report.d.ts +2 -1
  387. package/dist/observability/index.d.ts +7 -15
  388. package/dist/observability/index.js +4 -12
  389. package/dist/observability/metric-validator.js +1 -1
  390. package/dist/observability/metrics-handle.d.ts +0 -1
  391. package/dist/observability/metrics-handle.js +2 -15
  392. package/dist/observability/recording-tracer.d.ts +1 -2
  393. package/dist/observability/recording-tracer.js +0 -6
  394. package/dist/observability/sensitive-filter.d.ts +0 -2
  395. package/dist/observability/sensitive-filter.js +0 -29
  396. package/dist/pipeline/active-membership.d.ts +2 -1
  397. package/dist/pipeline/active-membership.js +6 -2
  398. package/dist/pipeline/append-event-core.d.ts +2 -1
  399. package/dist/pipeline/append-event-core.js +2 -2
  400. package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
  401. package/dist/pipeline/attach-outside-transaction.js +13 -0
  402. package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
  403. package/dist/pipeline/cascade-handler.d.ts +2 -1
  404. package/dist/pipeline/cascade-handler.js +3 -2
  405. package/dist/pipeline/config-accessor-factory.d.ts +1 -1
  406. package/dist/pipeline/config-accessor-factory.js +1 -1
  407. package/dist/pipeline/context-services.d.ts +56 -0
  408. package/dist/pipeline/context-services.js +73 -0
  409. package/dist/pipeline/dispatch-batch.d.ts +2 -1
  410. package/dist/pipeline/dispatch-batch.js +31 -18
  411. package/dist/pipeline/dispatch-query.js +5 -4
  412. package/dist/pipeline/dispatch-scope.d.ts +6 -0
  413. package/dist/pipeline/dispatch-scope.js +27 -0
  414. package/dist/pipeline/dispatch-shared.d.ts +13 -9
  415. package/dist/pipeline/dispatch-shared.js +75 -198
  416. package/dist/pipeline/dispatch-stream.js +8 -4
  417. package/dist/pipeline/dispatch-write.d.ts +2 -1
  418. package/dist/pipeline/dispatch-write.js +10 -8
  419. package/dist/pipeline/dispatcher-utils.d.ts +3 -1
  420. package/dist/pipeline/dispatcher-utils.js +8 -2
  421. package/dist/pipeline/dispatcher.d.ts +3 -2
  422. package/dist/pipeline/dispatcher.js +4 -3
  423. package/dist/pipeline/event-consumer-state.d.ts +0 -1
  424. package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
  425. package/dist/pipeline/event-dispatcher-delivery.js +4 -2
  426. package/dist/pipeline/event-dispatcher.d.ts +2 -2
  427. package/dist/pipeline/event-dispatcher.js +7 -3
  428. package/dist/pipeline/event-retention.js +59 -56
  429. package/dist/pipeline/handler-access-error.js +2 -1
  430. package/dist/pipeline/handler-context-auth.d.ts +5 -6
  431. package/dist/pipeline/handler-context-auth.js +7 -4
  432. package/dist/pipeline/handler-context-config.d.ts +2 -5
  433. package/dist/pipeline/handler-context-config.js +2 -2
  434. package/dist/pipeline/handler-context-db.d.ts +32 -7
  435. package/dist/pipeline/handler-context-db.js +26 -17
  436. package/dist/pipeline/handler-context-dispatch.d.ts +13 -7
  437. package/dist/pipeline/handler-context-dispatch.js +9 -8
  438. package/dist/pipeline/handler-context-events.d.ts +22 -36
  439. package/dist/pipeline/handler-context-events.js +36 -31
  440. package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
  441. package/dist/pipeline/handler-context-member-resolution.js +110 -0
  442. package/dist/pipeline/handler-context-notify.d.ts +3 -2
  443. package/dist/pipeline/handler-context-notify.js +1 -1
  444. package/dist/pipeline/handler-context-observability.d.ts +2 -4
  445. package/dist/pipeline/handler-context-observability.js +7 -5
  446. package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
  447. package/dist/pipeline/handler-context-phase-denials.js +98 -0
  448. package/dist/pipeline/handler-context-scope.d.ts +7 -10
  449. package/dist/pipeline/handler-context-scope.js +18 -20
  450. package/dist/pipeline/index.d.ts +9 -21
  451. package/dist/pipeline/index.js +5 -7
  452. package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
  453. package/dist/pipeline/irreversible-operation-gate.js +2 -2
  454. package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
  455. package/dist/pipeline/lifecycle-pipeline.js +9 -15
  456. package/dist/pipeline/member-read-only-transaction.js +11 -3
  457. package/dist/pipeline/member-reader.d.ts +1 -1
  458. package/dist/pipeline/member-reader.js +2 -2
  459. package/dist/pipeline/msp-rebuild.js +5 -3
  460. package/dist/pipeline/multi-stream-apply-context.js +3 -2
  461. package/dist/pipeline/notify-scope.d.ts +2 -1
  462. package/dist/pipeline/pre-handler-gates.d.ts +2 -1
  463. package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
  464. package/dist/pipeline/pre-transaction-reservations.js +9 -7
  465. package/dist/pipeline/projection-rebuild.js +12 -5
  466. package/dist/pipeline/projection-state.d.ts +0 -6
  467. package/dist/pipeline/projection-state.js +0 -5
  468. package/dist/pipeline/projections-runner.d.ts +2 -1
  469. package/dist/pipeline/projections-runner.js +10 -6
  470. package/dist/pipeline/system-hooks.d.ts +3 -1
  471. package/dist/pipeline/system-hooks.js +6 -4
  472. package/dist/pipeline/system-identity-switch.d.ts +4 -2
  473. package/dist/pipeline/system-identity-switch.js +51 -36
  474. package/dist/pipeline/typed-append-event.d.ts +2 -0
  475. package/dist/pipeline/typed-append-event.js +4 -0
  476. package/dist/pipeline/write-origin.js +2 -2
  477. package/dist/pipeline/write-result-masking.d.ts +1 -1
  478. package/dist/random/index.d.ts +1 -2
  479. package/dist/random/index.js +1 -2
  480. package/dist/rate-limit/bucket.d.ts +2 -1
  481. package/dist/rate-limit/middleware.js +2 -1
  482. package/dist/redis/index.d.ts +3 -4
  483. package/dist/redis/index.js +2 -2
  484. package/dist/schema-cli/apply-command.js +5 -2
  485. package/dist/schema-cli/baseline-command.js +7 -2
  486. package/dist/schema-cli/generate-command.js +7 -9
  487. package/dist/schema-cli/shared.d.ts +12 -2
  488. package/dist/schema-cli/shared.js +24 -2
  489. package/dist/schema-cli/status-command.js +8 -2
  490. package/dist/schema-cli/validate-command.js +48 -4
  491. package/dist/schema-cli.d.ts +0 -1
  492. package/dist/search/configure-tenant-index.d.ts +1 -3
  493. package/dist/search/configure-tenant-index.js +0 -4
  494. package/dist/search/index.d.ts +1 -4
  495. package/dist/search/index.js +0 -2
  496. package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
  497. package/dist/search/meilisearch-adapter-internals.js +9 -0
  498. package/dist/search/meilisearch-adapter.d.ts +1 -8
  499. package/dist/search/meilisearch-adapter.js +6 -7
  500. package/dist/search/meilisearch-peer.d.ts +2 -0
  501. package/dist/search/meilisearch-peer.js +5 -0
  502. package/dist/search/reindex-entity.js +93 -87
  503. package/dist/secrets/index.d.ts +3 -4
  504. package/dist/secrets/index.js +2 -3
  505. package/dist/seeding/index.d.ts +2 -2
  506. package/dist/seeding/index.js +1 -2
  507. package/dist/time/index.d.ts +2 -2
  508. package/dist/time/index.js +1 -1
  509. package/dist/time/tz-context.d.ts +0 -5
  510. package/dist/time/tz-context.js +0 -9
  511. package/dist/ui-types/index.d.ts +8 -11
  512. package/dist/ui-types/index.js +3 -3
  513. package/dist/upgrade-changelog.d.ts +3 -2
  514. package/dist/upgrade-changelog.js +12 -8
  515. package/dist/upgrade-cli-internals.d.ts +8 -0
  516. package/dist/upgrade-cli-internals.js +63 -0
  517. package/dist/upgrade-cli.d.ts +2 -9
  518. package/dist/upgrade-cli.js +28 -70
  519. package/dist/utils/import-optional-peer.d.ts +6 -0
  520. package/dist/utils/import-optional-peer.js +19 -0
  521. package/dist/utils/index.d.ts +1 -4
  522. package/dist/utils/index.js +1 -4
  523. package/package.json +23 -19
  524. package/src/changes.json +236 -0
  525. package/dist/crypto/request-kms-cache.d.ts +0 -8
  526. package/dist/crypto/request-kms-cache.js +0 -21
  527. package/dist/engine/codemod/index.d.ts +0 -2
  528. package/dist/engine/codemod/index.js +0 -1
  529. package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
  530. package/dist/engine/codemod/pipeline-codemod.js +0 -536
  531. package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
  532. package/dist/engine/feature-ast/entity-field-types.js +0 -35
  533. package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
  534. package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
  535. package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
  536. package/dist/engine/feature-ast/extractors/events.js +0 -275
  537. package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
  538. package/dist/engine/feature-ast/extractors/handlers.js +0 -358
  539. package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
  540. package/dist/engine/feature-ast/extractors/hooks.js +0 -248
  541. package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
  542. package/dist/engine/feature-ast/extractors/index.js +0 -13
  543. package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
  544. package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
  545. package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
  546. package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
  547. package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
  548. package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
  549. package/dist/engine/feature-ast/extractors/round1.d.ts +0 -11
  550. package/dist/engine/feature-ast/extractors/round1.js +0 -87
  551. package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
  552. package/dist/engine/feature-ast/extractors/round2.js +0 -191
  553. package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
  554. package/dist/engine/feature-ast/extractors/round3.js +0 -292
  555. package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
  556. package/dist/engine/feature-ast/extractors/round5.js +0 -68
  557. package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
  558. package/dist/engine/feature-ast/extractors/round6.js +0 -17
  559. package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
  560. package/dist/engine/feature-ast/extractors/shared.js +0 -343
  561. package/dist/engine/feature-ast/index.d.ts +0 -16
  562. package/dist/engine/feature-ast/index.js +0 -10
  563. package/dist/engine/feature-ast/parse.d.ts +0 -31
  564. package/dist/engine/feature-ast/parse.js +0 -485
  565. package/dist/engine/feature-ast/patch.d.ts +0 -212
  566. package/dist/engine/feature-ast/patch.js +0 -611
  567. package/dist/engine/feature-ast/patcher.d.ts +0 -217
  568. package/dist/engine/feature-ast/patcher.js +0 -281
  569. package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1238
  570. package/dist/engine/feature-ast/pattern-change-schema.js +0 -1072
  571. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
  572. package/dist/engine/feature-ast/pattern-id-matchers.js +0 -211
  573. package/dist/engine/feature-ast/pattern-id-schema.d.ts +0 -251
  574. package/dist/engine/feature-ast/pattern-id-schema.js +0 -166
  575. package/dist/engine/feature-ast/patterns.d.ts +0 -322
  576. package/dist/engine/feature-ast/patterns.js +0 -107
  577. package/dist/engine/feature-ast/render.d.ts +0 -47
  578. package/dist/engine/feature-ast/render.js +0 -666
  579. package/dist/engine/feature-ast/source-location.d.ts +0 -17
  580. package/dist/engine/feature-ast/source-location.js +0 -27
  581. package/dist/engine/pattern-library/index.d.ts +0 -2
  582. package/dist/engine/pattern-library/index.js +0 -3
  583. package/dist/engine/pattern-library/library.d.ts +0 -14
  584. package/dist/engine/pattern-library/library.js +0 -94
  585. package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
  586. package/dist/engine/pattern-library/mixed-schemas.js +0 -559
  587. package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
  588. package/dist/engine/pattern-library/opaque-schemas.js +0 -115
  589. package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
  590. package/dist/engine/pattern-library/shared-fields.js +0 -88
  591. package/dist/engine/pattern-library/static-schemas.d.ts +0 -21
  592. package/dist/engine/pattern-library/static-schemas.js +0 -487
  593. package/dist/engine/pattern-library/types.d.ts +0 -158
  594. package/dist/engine/pattern-library/types.js +0 -36
  595. package/dist/engine/resolve-config-or-param.d.ts +0 -18
  596. package/dist/engine/resolve-config-or-param.js +0 -76
  597. package/src/scripts/codemod/README.md +0 -187
  598. package/src/scripts/codemod/codemod-support.ts +0 -334
  599. package/src/scripts/codemod/collect-source-files.ts +0 -48
  600. package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
  601. package/src/scripts/codemod/db-factory.ts +0 -810
  602. package/src/scripts/codemod/feature-factory.ts +0 -429
  603. package/src/scripts/codemod/feature-layout.ts +0 -424
  604. package/src/scripts/codemod/import-extensions.ts +0 -118
  605. package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
  606. package/src/scripts/codemod/migrate-db-raw.ts +0 -401
  607. package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
  608. package/src/scripts/codemod/object-form.ts +0 -746
  609. package/src/scripts/codemod/package-merge.ts +0 -299
  610. package/src/scripts/codemod/pii-personal-migration.ts +0 -816
  611. package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
  612. package/src/scripts/codemod/s3-imports.ts +0 -236
  613. package/src/scripts/codemod/tenant-db-options.ts +0 -454
  614. package/src/scripts/codemod/testing-injection.ts +0 -215
  615. package/src/scripts/codemod/testing-move-targets.ts +0 -161
  616. package/src/scripts/codemod/testing-move.ts +0 -542
  617. package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
@@ -1,746 +0,0 @@
1
- #!/usr/bin/env bun
2
- // object-form — rewrites the positional registrar calls r.writeHandler / r.queryHandler /
3
- // r.entity / r.requires / r.hook to their object form and registerEntityCrud(r, …) to
4
- // r.crud(…). The positional overloads are gone; the object form is the only API.
5
- //
6
- // Usage:
7
- // bun scripts/codemod/object-form.ts <targetDir...> [--check | --dry-run | --write] [--no-format]
8
- // Without a mode flag it writes (kumiko-upgrade --apply calls it that way). --check exits 1
9
- // while any rewritable or manual site is left; --dry-run only reports.
10
-
11
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
12
- import { dirname, join, relative, resolve } from "node:path";
13
- import {
14
- type CallExpression,
15
- type ImportSpecifier,
16
- Node,
17
- type ParameterDeclaration,
18
- Project,
19
- type SourceFile,
20
- SyntaxKind,
21
- } from "ts-morph";
22
- import { collectSourceFiles } from "./collect-source-files.ts";
23
-
24
- export const REGISTRAR_METHODS = [
25
- "writeHandler",
26
- "queryHandler",
27
- "entity",
28
- "requires",
29
- "hook",
30
- ] as const;
31
- export type RegistrarMethod = (typeof REGISTRAR_METHODS)[number];
32
- export type ObjectFormMethod = RegistrarMethod | "registerEntityCrud";
33
-
34
- const CRUD_FUNCTION_NAME = "registerEntityCrud";
35
- const REGISTRAR_TYPE_MARKER = "FeatureRegistrar";
36
- const REGISTRAR_RECEIVER_NAMES: ReadonlySet<string> = new Set(["r", "registrar"]);
37
- const FEATURE_FACTORY_NAME = "defineFeature";
38
- const CHEAP_PREFILTER = /\b(writeHandler|queryHandler|entity|requires|hook|registerEntityCrud)\b/;
39
-
40
- export interface ObjectFormRewrite {
41
- readonly file: string;
42
- readonly line: number;
43
- readonly method: ObjectFormMethod;
44
- }
45
-
46
- export interface ObjectFormManualSite extends ObjectFormRewrite {
47
- readonly why: string;
48
- }
49
-
50
- export interface ObjectFormResult {
51
- readonly output: string;
52
- readonly rewrites: ObjectFormRewrite[];
53
- readonly manual: ObjectFormManualSite[];
54
- }
55
-
56
- export type ReceiverResolution = "registrar" | "other" | "unresolved";
57
-
58
- function isRegistrarMethod(name: string): name is RegistrarMethod {
59
- return REGISTRAR_METHODS.some((method) => method === name);
60
- }
61
-
62
- function isFeatureFactoryCallee(callee: Node): boolean {
63
- if (Node.isIdentifier(callee)) return callee.getText() === FEATURE_FACTORY_NAME;
64
- if (Node.isPropertyAccessExpression(callee)) return callee.getName() === FEATURE_FACTORY_NAME;
65
- return false;
66
- }
67
-
68
- function isFeatureCallbackParameter(param: ParameterDeclaration): boolean {
69
- const fn = param.getParent();
70
- if (!Node.isArrowFunction(fn) && !Node.isFunctionExpression(fn)) return false;
71
- if (fn.getParameters()[0] !== param) return false;
72
- const call = fn.getParentIfKind(SyntaxKind.CallExpression);
73
- return (
74
- call !== undefined &&
75
- call.getArguments()[1] === fn &&
76
- isFeatureFactoryCallee(call.getExpression())
77
- );
78
- }
79
-
80
- function resolveParameter(param: ParameterDeclaration): ReceiverResolution {
81
- if (isFeatureCallbackParameter(param)) return "registrar";
82
- const typeNode = param.getTypeNode();
83
- if (typeNode === undefined) return "unresolved";
84
- return typeNode.getText().includes(REGISTRAR_TYPE_MARKER) ? "registrar" : "other";
85
- }
86
-
87
- function declaredVariableIn(scope: Node, name: string): ReceiverResolution | undefined {
88
- if (!Node.isBlock(scope) && !Node.isSourceFile(scope) && !Node.isModuleBlock(scope)) {
89
- return undefined;
90
- }
91
- for (const statement of scope.getStatements()) {
92
- if (!Node.isVariableStatement(statement)) continue;
93
- for (const declaration of statement.getDeclarations()) {
94
- if (declaration.getNameNode().getText() !== name) continue;
95
- const typeText = declaration.getTypeNode()?.getText();
96
- if (typeText === undefined) return "unresolved";
97
- return typeText.includes(REGISTRAR_TYPE_MARKER) ? "registrar" : "other";
98
- }
99
- }
100
- return undefined;
101
- }
102
-
103
- // Scope walk instead of a type checker: the nearest binding of the receiver's name decides.
104
- export function resolveReceiver(receiver: Node): ReceiverResolution {
105
- if (!Node.isIdentifier(receiver)) return "other";
106
- const name = receiver.getText();
107
- for (
108
- let scope: Node | undefined = receiver.getParent();
109
- scope !== undefined;
110
- scope = scope.getParent()
111
- ) {
112
- if (Node.isParametered(scope)) {
113
- const param = scope.getParameters().find((p) => p.getNameNode().getText() === name);
114
- if (param !== undefined) return resolveParameter(param);
115
- }
116
- const variable = declaredVariableIn(scope, name);
117
- if (variable !== undefined) return variable;
118
- }
119
- return "unresolved";
120
- }
121
-
122
- export function isFeatureRegistrarReceiver(receiver: Node): boolean {
123
- return resolveReceiver(receiver) === "registrar";
124
- }
125
-
126
- function isUnresolvedRegistrarLookalike(receiver: Node): boolean {
127
- return (
128
- Node.isIdentifier(receiver) &&
129
- REGISTRAR_RECEIVER_NAMES.has(receiver.getText()) &&
130
- resolveReceiver(receiver) === "unresolved"
131
- );
132
- }
133
-
134
- function isAssumedRegistrar(receiver: Node, assumeRegistrarNames: ReadonlySet<string>): boolean {
135
- return (
136
- Node.isIdentifier(receiver) &&
137
- assumeRegistrarNames.has(receiver.getText()) &&
138
- resolveReceiver(receiver) === "unresolved"
139
- );
140
- }
141
-
142
- function isFeatureNameLiteral(arg: Node): boolean {
143
- return (
144
- Node.isStringLiteral(arg) ||
145
- Node.isNoSubstitutionTemplateLiteral(arg) ||
146
- Node.isTemplateExpression(arg) ||
147
- Node.isSpreadElement(arg)
148
- );
149
- }
150
-
151
- // An identifier or call argument could be a features object (already the object form) or a name,
152
- // so it is neither rewritten nor skipped silently.
153
- function isAmbiguousRequires(method: RegistrarMethod, args: readonly Node[]): boolean {
154
- return (
155
- method === "requires" &&
156
- !args.some(isFeatureNameLiteral) &&
157
- args.some((arg) => !Node.isObjectLiteralExpression(arg))
158
- );
159
- }
160
-
161
- export function isPositionalShape(method: RegistrarMethod, args: readonly Node[]): boolean {
162
- if (method === "requires") return args.some(isFeatureNameLiteral);
163
- // The object form takes exactly one argument, so a spread can only be a positional call.
164
- if (args.some((arg) => Node.isSpreadElement(arg))) return true;
165
- return args.length >= (method === "hook" ? 3 : 2);
166
- }
167
-
168
- interface Edit {
169
- readonly start: number;
170
- readonly end: number;
171
- readonly render: () => string;
172
- }
173
-
174
- type Plan = { readonly edit: Edit } | { readonly why: string };
175
-
176
- let sharedProject: Project | undefined;
177
-
178
- function parserProject(): Project {
179
- sharedProject ??= new Project({
180
- useInMemoryFileSystem: true,
181
- skipFileDependencyResolution: true,
182
- });
183
- return sharedProject;
184
- }
185
-
186
- function lastLineHasLineComment(piece: string): boolean {
187
- return piece.slice(piece.lastIndexOf("\n") + 1).includes("//");
188
- }
189
-
190
- function terminated(piece: string): string {
191
- if (lastLineHasLineComment(piece)) return `${piece}\n,`;
192
- return piece.endsWith(",") ? piece : `${piece},`;
193
- }
194
-
195
- function composeObjectCall(pieces: readonly string[]): string {
196
- const parts = pieces.filter((piece) => piece.length > 0);
197
- const last = parts.at(-1) ?? "";
198
- const body = [...parts.slice(0, -1).map(terminated), last].join(" ");
199
- return `({ ${body}${lastLineHasLineComment(last) ? "\n" : " "}})`;
200
- }
201
-
202
- class SourceRewriter {
203
- private readonly edits: Edit[] = [];
204
- readonly rewrites: ObjectFormRewrite[] = [];
205
- readonly manual: ObjectFormManualSite[] = [];
206
-
207
- constructor(
208
- private readonly text: string,
209
- private readonly fileName: string,
210
- ) {}
211
-
212
- addEdit(edit: Edit): void {
213
- this.edits.push(edit);
214
- }
215
-
216
- site(call: Node, method: ObjectFormMethod): ObjectFormRewrite {
217
- return { file: this.fileName, line: call.getStartLineNumber(), method };
218
- }
219
-
220
- recordPlan(call: Node, method: ObjectFormMethod, plan: Plan): void {
221
- if ("why" in plan) {
222
- this.manual.push({ ...this.site(call, method), why: plan.why });
223
- } else {
224
- this.edits.push(plan.edit);
225
- this.rewrites.push(this.site(call, method));
226
- }
227
- }
228
-
229
- recordManual(call: Node, method: ObjectFormMethod, why: string): void {
230
- this.manual.push({ ...this.site(call, method), why });
231
- }
232
-
233
- // Source between two offsets with every contained edit applied, so a rewritten call nested in
234
- // an argument of another rewritten call is rendered once, inside the outer replacement.
235
- textOf = (start: number, end: number): string => {
236
- const ordered = [...this.edits].sort((a, b) => a.start - b.start || b.end - a.end);
237
- let out = "";
238
- let cursor = start;
239
- for (const edit of ordered) {
240
- if (edit.start < cursor || edit.end > end) continue;
241
- out += this.text.slice(cursor, edit.start) + edit.render();
242
- cursor = edit.end;
243
- }
244
- return out + this.text.slice(cursor, end);
245
- };
246
-
247
- commaEndAfter(position: number): number {
248
- let i = position;
249
- while (i < this.text.length) {
250
- const ch = this.text[i];
251
- if (ch === ",") return i + 1;
252
- if (this.text.startsWith("/*", i)) {
253
- const close = this.text.indexOf("*/", i + 2);
254
- i = close === -1 ? this.text.length : close + 2;
255
- } else if (this.text.startsWith("//", i)) {
256
- const newline = this.text.indexOf("\n", i);
257
- i = newline === -1 ? this.text.length : newline + 1;
258
- } else {
259
- i += 1;
260
- }
261
- }
262
- return position;
263
- }
264
-
265
- // Leading comments stay attached: the slice starts right after the previous comma / the paren.
266
- argSource(call: CallExpression, index: number): string {
267
- const args = call.getArguments();
268
- const arg = args[index];
269
- if (arg === undefined) return "";
270
- const previous = args[index - 1];
271
- const start =
272
- previous !== undefined
273
- ? this.commaEndAfter(previous.getEnd())
274
- : (call.getFirstChildByKind(SyntaxKind.OpenParenToken)?.getEnd() ?? arg.getStart());
275
- return this.textOf(start, arg.getEnd()).trimStart();
276
- }
277
-
278
- fieldFrom(call: CallExpression, index: number, field: string): string {
279
- const source = this.argSource(call, index);
280
- return source === field ? field : `${field}: ${source}`;
281
- }
282
-
283
- // Property list of an object literal, comments inside it included, outer braces and trailing comma cut.
284
- innerOf(literal: Node): string {
285
- const inner = this.textOf(literal.getStart() + 1, literal.getEnd() - 1).trim();
286
- return inner.endsWith(",") ? inner.slice(0, -1).trimEnd() : inner;
287
- }
288
-
289
- spreadOrInline(call: CallExpression, index: number): string {
290
- const arg = call.getArguments()[index];
291
- if (arg !== undefined && Node.isObjectLiteralExpression(arg)) return this.innerOf(arg);
292
- return `...${this.argSource(call, index)}`;
293
- }
294
-
295
- // Replaces everything after the callee (type arguments and the argument list).
296
- objectCallEdit(call: CallExpression, pieces: () => readonly string[]): Edit {
297
- return {
298
- start: call.getExpression().getEnd(),
299
- end: call.getEnd(),
300
- render: () => composeObjectCall(pieces()),
301
- };
302
- }
303
- }
304
-
305
- function hasSpreadArgument(args: readonly Node[]): boolean {
306
- return args.some((arg) => Node.isSpreadElement(arg));
307
- }
308
-
309
- function planHandler(
310
- rewriter: SourceRewriter,
311
- call: CallExpression,
312
- fieldNames: readonly [string, string, string],
313
- ): Plan {
314
- const args = call.getArguments();
315
- if (hasSpreadArgument(args)) return { why: "spread argument — rewrite by hand" };
316
- if (Node.isObjectLiteralExpression(args[0])) {
317
- return { why: "first argument is an object literal — not the positional form" };
318
- }
319
- if (args.length < 3) return { why: "fewer than 3 arguments (name, schema, handler)" };
320
- if (args.length > 4) return { why: "more than 4 arguments" };
321
- const options = args[3];
322
- return {
323
- edit: rewriter.objectCallEdit(call, () => [
324
- ...fieldNames.map((field, index) => rewriter.fieldFrom(call, index, field)),
325
- options === undefined ? "" : rewriter.spreadOrInline(call, 3),
326
- ]),
327
- };
328
- }
329
-
330
- type BackingTableField = (() => string) | { readonly why: string };
331
-
332
- function backingTableOf(rewriter: SourceRewriter, call: CallExpression): BackingTableField {
333
- const options = call.getArguments()[2];
334
- if (options === undefined) return () => "";
335
- if (!Node.isObjectLiteralExpression(options)) {
336
- return { why: "entity options argument is not an object literal" };
337
- }
338
- const only = options.getProperties()[0];
339
- const invalid = { why: "entity options must contain exactly `table`" };
340
- if (options.getProperties().length !== 1 || only === undefined) return invalid;
341
- if (Node.isShorthandPropertyAssignment(only) && only.getName() === "table") {
342
- return () => "backingTable: table";
343
- }
344
- if (Node.isPropertyAssignment(only) && only.getName() === "table") {
345
- const initializer = only.getInitializer();
346
- if (initializer === undefined) return { why: "entity `table` option has no value" };
347
- return () => `backingTable: ${rewriter.textOf(initializer.getStart(), initializer.getEnd())}`;
348
- }
349
- return invalid;
350
- }
351
-
352
- function planEntity(rewriter: SourceRewriter, call: CallExpression): Plan {
353
- const args = call.getArguments();
354
- if (hasSpreadArgument(args)) return { why: "spread argument — rewrite by hand" };
355
- if (Node.isObjectLiteralExpression(args[0])) {
356
- return { why: "first argument is an object literal — not the positional form" };
357
- }
358
- if (args.length > 3) return { why: "more than 3 arguments" };
359
- const backingTable = backingTableOf(rewriter, call);
360
- if ("why" in backingTable) return backingTable;
361
- return {
362
- edit: rewriter.objectCallEdit(call, () => [
363
- rewriter.fieldFrom(call, 0, "name"),
364
- rewriter.spreadOrInline(call, 1),
365
- backingTable(),
366
- ]),
367
- };
368
- }
369
-
370
- function planRequires(rewriter: SourceRewriter, call: CallExpression): Plan {
371
- const args = call.getArguments();
372
- if (args.some((arg) => Node.isObjectLiteralExpression(arg))) {
373
- return { why: "mixes object literals with feature names" };
374
- }
375
- return {
376
- edit: rewriter.objectCallEdit(call, () => [
377
- `features: [${args.map((_, index) => rewriter.argSource(call, index)).join(", ")}]`,
378
- ]),
379
- };
380
- }
381
-
382
- function planHook(rewriter: SourceRewriter, call: CallExpression): Plan {
383
- const args = call.getArguments();
384
- if (hasSpreadArgument(args)) return { why: "spread argument — rewrite by hand" };
385
- if (args.length > 4) return { why: "more than 4 arguments" };
386
- return {
387
- edit: rewriter.objectCallEdit(call, () => [
388
- rewriter.fieldFrom(call, 0, "type"),
389
- rewriter.fieldFrom(call, 1, "target"),
390
- rewriter.fieldFrom(call, 2, "handler"),
391
- args[3] === undefined ? "" : rewriter.spreadOrInline(call, 3),
392
- ]),
393
- };
394
- }
395
-
396
- function planRegistrarCall(
397
- rewriter: SourceRewriter,
398
- call: CallExpression,
399
- method: RegistrarMethod,
400
- ): Plan {
401
- switch (method) {
402
- case "writeHandler":
403
- case "queryHandler":
404
- return planHandler(rewriter, call, ["name", "schema", "handler"]);
405
- case "entity":
406
- return planEntity(rewriter, call);
407
- case "requires":
408
- return planRequires(rewriter, call);
409
- case "hook":
410
- return planHook(rewriter, call);
411
- }
412
- }
413
-
414
- function crudImportsByLocalName(sourceFile: Node): Map<string, ImportSpecifier> {
415
- const byLocalName = new Map<string, ImportSpecifier>();
416
- for (const specifier of sourceFile.getDescendantsOfKind(SyntaxKind.ImportSpecifier)) {
417
- if (specifier.getName() !== CRUD_FUNCTION_NAME) continue;
418
- byLocalName.set(specifier.getAliasNode()?.getText() ?? specifier.getName(), specifier);
419
- }
420
- return byLocalName;
421
- }
422
-
423
- function planCrud(
424
- rewriter: SourceRewriter,
425
- call: CallExpression,
426
- text: string,
427
- assumeRegistrarNames: ReadonlySet<string>,
428
- ): Plan {
429
- const args = call.getArguments();
430
- if (hasSpreadArgument(args)) return { why: "spread argument — rewrite by hand" };
431
- if (args.length < 3) return { why: "fewer than 3 arguments (registrar, name, entity)" };
432
- const receiver = args[0];
433
- const second = args[1];
434
- if (receiver === undefined || second === undefined) return { why: "missing arguments" };
435
- if (!Node.isIdentifier(receiver)) {
436
- return {
437
- why: "first argument is not a plain identifier — rewrite to <registrar>.crud(…) by hand",
438
- };
439
- }
440
- const resolution = resolveReceiver(receiver);
441
- const looksLikeRegistrar =
442
- resolution === "registrar" ||
443
- (resolution === "unresolved" &&
444
- (REGISTRAR_RECEIVER_NAMES.has(receiver.getText()) ||
445
- assumeRegistrarNames.has(receiver.getText())));
446
- if (!looksLikeRegistrar) {
447
- return {
448
- why: `first argument \`${receiver.getText()}\` is not a recognized FeatureRegistrar — rewrite to <registrar>.crud(…) by hand`,
449
- };
450
- }
451
- const start = call.getStart();
452
- const commaEnd = rewriter.commaEndAfter(receiver.getEnd());
453
- const gap = text.slice(commaEnd, second.getStart());
454
- const end = gap.trim() === "" ? second.getStart() : commaEnd;
455
- return { edit: { start, end, render: () => `${receiver.getText()}.crud(` } };
456
- }
457
-
458
- function removeImportSpecifierEdit(specifier: ImportSpecifier): Edit {
459
- const declaration = specifier.getImportDeclaration();
460
- const named = declaration.getNamedImports();
461
- if (
462
- named.length === 1 &&
463
- declaration.getDefaultImport() === undefined &&
464
- declaration.getNamespaceImport() === undefined
465
- ) {
466
- const sourceText = declaration.getSourceFile().getFullText();
467
- const start = declaration.getStart();
468
- let end = declaration.getEnd();
469
- if (sourceText[end] === "\n") end += 1;
470
- return { start, end, render: () => "" };
471
- }
472
- const index = named.indexOf(specifier);
473
- const next = named[index + 1];
474
- const previous = named[index - 1];
475
- if (next !== undefined) {
476
- return { start: specifier.getStart(), end: next.getStart(), render: () => "" };
477
- }
478
- return {
479
- start: previous?.getEnd() ?? specifier.getStart(),
480
- end: specifier.getEnd(),
481
- render: () => "",
482
- };
483
- }
484
-
485
- function isOwnedByImport(node: Node): boolean {
486
- return node.getFirstAncestorByKind(SyntaxKind.ImportDeclaration) !== undefined;
487
- }
488
-
489
- function visitRegistrarCall(
490
- rewriter: SourceRewriter,
491
- call: CallExpression,
492
- assumeRegistrarNames: ReadonlySet<string>,
493
- ): void {
494
- const callee = call.getExpression();
495
- const method = Node.isPropertyAccessExpression(callee) ? callee.getName() : undefined;
496
- if (
497
- !Node.isPropertyAccessExpression(callee) ||
498
- method === undefined ||
499
- !isRegistrarMethod(method)
500
- ) {
501
- // skip: not a registrar method call, nothing to rewrite
502
- return;
503
- }
504
- const args = call.getArguments();
505
- const receiver = callee.getExpression();
506
- if (isAmbiguousRequires(method, args)) {
507
- if (
508
- isFeatureRegistrarReceiver(receiver) ||
509
- isAssumedRegistrar(receiver, assumeRegistrarNames)
510
- ) {
511
- rewriter.recordManual(
512
- call,
513
- method,
514
- "argument is not a string literal, so it may already be the object form — check by hand",
515
- );
516
- }
517
- // skip: an ambiguous argument is never rewritten; registrar receivers were reported above
518
- return;
519
- }
520
- if (!isPositionalShape(method, args)) {
521
- // skip: not a positional registrar call, nothing to rewrite
522
- return;
523
- }
524
- if (isFeatureRegistrarReceiver(receiver) || isAssumedRegistrar(receiver, assumeRegistrarNames)) {
525
- rewriter.recordPlan(call, method, planRegistrarCall(rewriter, call, method));
526
- } else if (isUnresolvedRegistrarLookalike(receiver)) {
527
- rewriter.recordManual(
528
- call,
529
- method,
530
- `receiver \`${receiver.getText()}\` is not a resolvable FeatureRegistrar (no defineFeature callback parameter or FeatureRegistrar-typed binding) — rewrite by hand`,
531
- );
532
- }
533
- }
534
-
535
- function reportCrudImportLeftovers(
536
- sourceFile: SourceFile,
537
- rewriter: SourceRewriter,
538
- crudImports: ReadonlyMap<string, ImportSpecifier>,
539
- rewrittenCrudCallees: ReadonlySet<Node>,
540
- ): void {
541
- for (const [localName, specifier] of crudImports) {
542
- const remainingUses = sourceFile
543
- .getDescendantsOfKind(SyntaxKind.Identifier)
544
- .filter(
545
- (id) => id.getText() === localName && !isOwnedByImport(id) && !rewrittenCrudCallees.has(id),
546
- );
547
- if (remainingUses.length === 0) rewriter.addEdit(removeImportSpecifierEdit(specifier));
548
- for (const use of remainingUses) {
549
- if (use.getParentIfKind(SyntaxKind.CallExpression)?.getExpression() === use) continue;
550
- rewriter.recordManual(
551
- use,
552
- CRUD_FUNCTION_NAME,
553
- "referenced other than as a direct call — migrate by hand",
554
- );
555
- }
556
- }
557
- }
558
-
559
- export interface ObjectFormSourceOptions {
560
- /** Receivers with these names count as registrars when their binding cannot be resolved — for doc snippets that show `r.…` without a surrounding defineFeature. */
561
- readonly assumeRegistrarNames?: ReadonlySet<string>;
562
- }
563
-
564
- export function transformObjectFormSource(
565
- text: string,
566
- fileName = "snippet.ts",
567
- options: ObjectFormSourceOptions = {},
568
- ): ObjectFormResult {
569
- const assumeRegistrarNames = options.assumeRegistrarNames ?? new Set<string>();
570
- if (!CHEAP_PREFILTER.test(text)) return { output: text, rewrites: [], manual: [] };
571
-
572
- const project = parserProject();
573
- const sourceFile = project.createSourceFile(fileName, text, { overwrite: true });
574
- const rewriter = new SourceRewriter(text, fileName);
575
- const crudImports = crudImportsByLocalName(sourceFile);
576
- const rewrittenCrudCallees = new Set<Node>();
577
-
578
- for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
579
- const callee = call.getExpression();
580
- if (Node.isIdentifier(callee) && crudImports.has(callee.getText())) {
581
- const plan = planCrud(rewriter, call, text, assumeRegistrarNames);
582
- rewriter.recordPlan(call, CRUD_FUNCTION_NAME, plan);
583
- if (!("why" in plan)) rewrittenCrudCallees.add(callee);
584
- } else {
585
- visitRegistrarCall(rewriter, call, assumeRegistrarNames);
586
- }
587
- }
588
-
589
- reportCrudImportLeftovers(sourceFile, rewriter, crudImports, rewrittenCrudCallees);
590
-
591
- const output = rewriter.textOf(0, text.length);
592
- project.removeSourceFile(sourceFile);
593
- return { output, rewrites: rewriter.rewrites, manual: rewriter.manual };
594
- }
595
-
596
- class CliError extends Error {}
597
-
598
- type Mode = "write" | "dry-run" | "check";
599
-
600
- interface CliOptions {
601
- readonly mode: Mode;
602
- readonly format: boolean;
603
- readonly paths: string[];
604
- }
605
-
606
- function parseArgs(argv: readonly string[]): CliOptions {
607
- let mode: Mode | undefined;
608
- let format = true;
609
- const paths: string[] = [];
610
- const setMode = (next: Mode): void => {
611
- if (mode !== undefined && mode !== next)
612
- throw new CliError("--check, --dry-run and --write are mutually exclusive");
613
- mode = next;
614
- };
615
- for (const arg of argv) {
616
- if (arg === "--check") setMode("check");
617
- else if (arg === "--dry-run") setMode("dry-run");
618
- else if (arg === "--write") setMode("write");
619
- else if (arg === "--no-format") format = false;
620
- else if (arg.startsWith("--")) throw new CliError(`unknown flag: ${arg}`);
621
- else paths.push(arg);
622
- }
623
- if (paths.length === 0) throw new CliError("at least one target directory is required");
624
- return { mode: mode ?? "write", format, paths };
625
- }
626
-
627
- function isMigratableFile(name: string): boolean {
628
- return /\.(ts|tsx)$/.test(name) && !name.endsWith(".d.ts");
629
- }
630
-
631
- function isFixturePath(file: string): boolean {
632
- return file.includes("/__tests__/fixtures/");
633
- }
634
-
635
- function findBiomeBinary(startDir: string): string | undefined {
636
- let dir = resolve(startDir);
637
- for (;;) {
638
- const candidate = join(dir, "node_modules", ".bin", "biome");
639
- if (existsSync(candidate)) return candidate;
640
- const parent = dirname(dir);
641
- if (parent === dir) return undefined;
642
- dir = parent;
643
- }
644
- }
645
-
646
- const FORMAT_BATCH_SIZE = 50;
647
-
648
- async function formatWithBiome(files: readonly string[], cwd: string): Promise<void> {
649
- const biome = findBiomeBinary(cwd);
650
- if (biome === undefined) {
651
- console.log(
652
- "[object-form] biome not found in node_modules/.bin — format the changed files yourself",
653
- );
654
- // skip: formatting is a convenience, the rewrite itself is already on disk
655
- return;
656
- }
657
- for (let i = 0; i < files.length; i += FORMAT_BATCH_SIZE) {
658
- const batch = files.slice(i, i + FORMAT_BATCH_SIZE);
659
- const proc = Bun.spawn({
660
- cmd: [biome, "format", "--write", "--no-errors-on-unmatched", ...batch],
661
- cwd,
662
- stdout: "pipe",
663
- stderr: "pipe",
664
- });
665
- const [stderr, exitCode] = await Promise.all([new Response(proc.stderr).text(), proc.exited]);
666
- if (exitCode !== 0) {
667
- console.log(
668
- `[object-form] biome format exited ${exitCode}; run it on the changed files yourself\n${stderr.trim()}`,
669
- );
670
- }
671
- }
672
- }
673
-
674
- function displayPath(file: string): string {
675
- const fromCwd = relative(process.cwd(), file);
676
- return fromCwd.startsWith("..") ? file : fromCwd;
677
- }
678
-
679
- function countByMethod(rewrites: readonly ObjectFormRewrite[]): string {
680
- const methods: readonly ObjectFormMethod[] = [...REGISTRAR_METHODS, CRUD_FUNCTION_NAME];
681
- return methods
682
- .map((method) => `${method} ${rewrites.filter((r) => r.method === method).length}`)
683
- .join(", ");
684
- }
685
-
686
- function parseArgsOrExit(argv: readonly string[]): CliOptions {
687
- try {
688
- return parseArgs(argv);
689
- } catch (err) {
690
- if (err instanceof CliError) {
691
- console.error(`[object-form] ${err.message}`);
692
- process.exit(2);
693
- }
694
- throw err;
695
- }
696
- }
697
-
698
- interface RunSummary {
699
- readonly rewrites: ObjectFormRewrite[];
700
- readonly manual: ObjectFormManualSite[];
701
- readonly changedFiles: string[];
702
- }
703
-
704
- function transformFiles(files: readonly string[], mode: Mode): RunSummary {
705
- const summary: RunSummary = { rewrites: [], manual: [], changedFiles: [] };
706
- for (const file of files) {
707
- const before = readFileSync(file, "utf8");
708
- const result = transformObjectFormSource(before, file);
709
- const shown = displayPath(file);
710
- for (const site of result.rewrites)
711
- console.log(`${shown}:${site.line} ${site.method} rewritten`);
712
- for (const site of result.manual) {
713
- console.log(`${shown}:${site.line} ${site.method} manual: ${site.why}`);
714
- }
715
- summary.rewrites.push(...result.rewrites);
716
- summary.manual.push(...result.manual);
717
- if (mode === "write" && result.output !== before) {
718
- writeFileSync(file, result.output);
719
- summary.changedFiles.push(file);
720
- }
721
- }
722
- return summary;
723
- }
724
-
725
- async function main(): Promise<void> {
726
- const options = parseArgsOrExit(process.argv.slice(2));
727
- const files = collectSourceFiles(options.paths, { isMigratableFile }).filter(
728
- (file) => !isFixturePath(file),
729
- );
730
- const { rewrites, manual, changedFiles } = transformFiles(files, options.mode);
731
-
732
- console.log(
733
- `\n[object-form] ${options.mode === "write" ? "rewritten" : "rewritable"}: ${rewrites.length} (${countByMethod(rewrites)}); manual: ${manual.length}`,
734
- );
735
-
736
- if (options.mode === "write" && options.format && changedFiles.length > 0) {
737
- await formatWithBiome(changedFiles, resolve(options.paths[0] ?? "."));
738
- }
739
-
740
- const hasOpenSites = rewrites.length + manual.length > 0;
741
- process.exit(options.mode === "check" && hasOpenSites ? 1 : 0);
742
- }
743
-
744
- if (import.meta.main) {
745
- await main();
746
- }