@cosmicdrift/kumiko-framework 0.388.0 → 0.390.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 (711) hide show
  1. package/AGENTS.md +12 -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/golden-path.md +13 -1
  13. package/agents/examples/inbound-mail-triage.md +1 -0
  14. package/agents/examples/lane-routing.md +2 -1
  15. package/agents/examples/legal-pages.md +2 -2
  16. package/agents/examples/lifecycle-hooks.md +55 -2
  17. package/agents/examples/list-table-options.md +466 -0
  18. package/agents/examples/managed-config.md +4 -4
  19. package/agents/examples/managed-pages.md +1 -1
  20. package/agents/examples/pdf-audit-export.md +4 -2
  21. package/agents/examples/relations.md +19 -4
  22. package/agents/examples/search.md +4 -4
  23. package/agents/examples/secrets-demo.md +9 -6
  24. package/agents/examples/state-machine.md +5 -4
  25. package/agents/examples/tenant-isolation.md +73 -1
  26. package/agents/examples/tenant-settings.md +1 -1
  27. package/agents/examples/user-data-rights.md +3 -6
  28. package/agents/examples/workflow-engine.md +53 -47
  29. package/agents/examples.md +5 -4
  30. package/agents/features.md +1 -1
  31. package/agents/widgets.md +1 -0
  32. package/dist/api/api-constants.d.ts +1 -0
  33. package/dist/api/api-constants.js +2 -0
  34. package/dist/api/auth-middleware.js +1 -1
  35. package/dist/api/auth-routes-invite.js +2 -1
  36. package/dist/api/auth-routes-shared.d.ts +2 -0
  37. package/dist/api/auth-routes-shared.js +5 -0
  38. package/dist/api/client-error-route.js +2 -3
  39. package/dist/api/entity-read-access.d.ts +4 -1
  40. package/dist/api/entity-read-access.js +14 -0
  41. package/dist/api/export/export-cells-reference.d.ts +9 -0
  42. package/dist/api/export/export-cells-reference.js +21 -0
  43. package/dist/api/export/export-cells.d.ts +11 -0
  44. package/dist/api/export/export-cells.js +136 -0
  45. package/dist/api/export/export-ciphertext-guard.d.ts +2 -0
  46. package/dist/api/export/export-ciphertext-guard.js +27 -0
  47. package/dist/api/export/export-columns.d.ts +31 -0
  48. package/dist/api/export/export-columns.js +85 -0
  49. package/dist/api/export/export-errors.d.ts +4 -0
  50. package/dist/api/export/export-errors.js +14 -0
  51. package/dist/api/export/export-route.d.ts +4 -0
  52. package/dist/api/export/export-route.js +75 -0
  53. package/dist/api/export/export-rows.d.ts +13 -0
  54. package/dist/api/export/export-rows.js +62 -0
  55. package/dist/api/export/export-screen.d.ts +13 -0
  56. package/dist/api/export/export-screen.js +47 -0
  57. package/dist/api/export/export-xlsx-writer.d.ts +4 -0
  58. package/dist/api/export/export-xlsx-writer.js +21 -0
  59. package/dist/api/extra-route.d.ts +7 -1
  60. package/dist/api/index.d.ts +23 -27
  61. package/dist/api/index.js +13 -15
  62. package/dist/api/jwt.js +1 -1
  63. package/dist/api/observability-middleware.d.ts +1 -1
  64. package/dist/api/observability-middleware.js +2 -1
  65. package/dist/api/pii-leak-guard.d.ts +3 -0
  66. package/dist/api/pii-leak-guard.js +3 -2
  67. package/dist/api/request-context-internals.d.ts +31 -0
  68. package/dist/api/request-context-internals.js +11 -0
  69. package/dist/api/request-context-scopes.d.ts +14 -0
  70. package/dist/api/request-context-scopes.js +69 -0
  71. package/dist/api/request-context.d.ts +1 -40
  72. package/dist/api/request-context.js +22 -51
  73. package/dist/api/request-id-middleware.d.ts +1 -1
  74. package/dist/api/route-registrars.d.ts +2 -1
  75. package/dist/api/route-registrars.js +1 -1
  76. package/dist/api/routes.d.ts +16 -0
  77. package/dist/api/routes.js +9 -5
  78. package/dist/api/server-boot-checks.d.ts +1 -1
  79. package/dist/api/server-boot-checks.js +2 -2
  80. package/dist/api/server-event-dispatcher.d.ts +6 -1
  81. package/dist/api/server-event-dispatcher.js +3 -4
  82. package/dist/api/server-extra-routes.d.ts +1 -1
  83. package/dist/api/server-extra-routes.js +5 -1
  84. package/dist/api/server-middleware.js +3 -1
  85. package/dist/api/server-routes.d.ts +3 -2
  86. package/dist/api/server-routes.js +8 -2
  87. package/dist/api/server-wiring.js +8 -4
  88. package/dist/api/server.d.ts +2 -1
  89. package/dist/api/sse-route.d.ts +3 -1
  90. package/dist/api/sse-route.js +11 -1
  91. package/dist/api/tenant-scoped-secrets.d.ts +2 -0
  92. package/dist/api/tenant-scoped-secrets.js +13 -0
  93. package/dist/api/websocket-route.d.ts +1 -1
  94. package/dist/auth/index.d.ts +0 -1
  95. package/dist/auth/roles.d.ts +0 -5
  96. package/dist/compliance/duration-spec.d.ts +0 -1
  97. package/dist/compliance/duration-spec.js +0 -5
  98. package/dist/compliance/index.d.ts +4 -4
  99. package/dist/compliance/index.js +2 -2
  100. package/dist/compliance/profiles.d.ts +0 -15
  101. package/dist/compliance/profiles.js +0 -23
  102. package/dist/config/index.d.ts +11 -9
  103. package/dist/config/index.js +13 -1
  104. package/dist/config/internals.d.ts +9 -0
  105. package/dist/config/internals.js +1 -0
  106. package/dist/consumer-cli-internals.d.ts +4 -0
  107. package/dist/consumer-cli-internals.js +1 -0
  108. package/dist/consumer-cli.d.ts +1 -4
  109. package/dist/consumer-cli.js +5 -1
  110. package/dist/crypto/event-pii.js +1 -1
  111. package/dist/crypto/index.d.ts +8 -9
  112. package/dist/crypto/index.js +7 -8
  113. package/dist/crypto/pg-kms-adapter.d.ts +1 -0
  114. package/dist/crypto/pg-kms-adapter.js +17 -18
  115. package/dist/db/aggregate-sql.d.ts +2 -0
  116. package/dist/db/aggregate-sql.js +10 -0
  117. package/dist/db/apply-entity-event.d.ts +1 -1
  118. package/dist/db/apply-entity-event.js +15 -47
  119. package/dist/db/blind-index-cleanup.js +91 -77
  120. package/dist/db/closed-connection.js +12 -19
  121. package/dist/db/collect-table-metas.js +1 -1
  122. package/dist/db/compound-types.d.ts +1 -1
  123. package/dist/db/compound-types.js +0 -7
  124. package/dist/db/config-seed.d.ts +2 -1
  125. package/dist/db/config-seed.js +6 -1
  126. package/dist/db/connection.d.ts +7 -6
  127. package/dist/db/connection.js +43 -24
  128. package/dist/db/cross-tenant-reads.d.ts +1 -1
  129. package/dist/db/cross-tenant-reads.js +1 -1
  130. package/dist/db/dialect.d.ts +0 -5
  131. package/dist/db/dialect.js +0 -3
  132. package/dist/db/driver-row-coercion.js +4 -4
  133. package/dist/db/driver-value-preparation.js +6 -4
  134. package/dist/db/eagerload.d.ts +2 -1
  135. package/dist/db/entity-field-encryption.d.ts +1 -1
  136. package/dist/db/entity-table-meta.d.ts +1 -1
  137. package/dist/db/event-store-executor-context.d.ts +3 -1
  138. package/dist/db/event-store-executor-context.js +4 -3
  139. package/dist/db/event-store-executor-read-aggregate-currencies.d.ts +17 -0
  140. package/dist/db/event-store-executor-read-aggregate-currencies.js +40 -0
  141. package/dist/db/event-store-executor-read-aggregate.js +36 -5
  142. package/dist/db/event-store-executor-read-filter.d.ts +1 -1
  143. package/dist/db/event-store-executor-read-filter.js +6 -3
  144. package/dist/db/event-store-executor-read-rows.d.ts +2 -1
  145. package/dist/db/event-store-executor-read-search.d.ts +2 -1
  146. package/dist/db/event-store-executor-read-sort.d.ts +2 -1
  147. package/dist/db/event-store-executor-read.js +2 -2
  148. package/dist/db/event-store-executor-write-atomic.d.ts +4 -0
  149. package/dist/db/event-store-executor-write-atomic.js +42 -0
  150. package/dist/db/event-store-executor-write-steps.d.ts +3 -5
  151. package/dist/db/event-store-executor-write-steps.js +0 -5
  152. package/dist/db/event-store-executor-write.js +22 -19
  153. package/dist/db/event-store-executor.d.ts +1 -1
  154. package/dist/db/event-store-executor.js +2 -1
  155. package/dist/db/executor-managed-tables.d.ts +7 -1
  156. package/dist/db/executor-managed-tables.js +12 -3
  157. package/dist/db/index.d.ts +29 -28
  158. package/dist/db/index.js +22 -20
  159. package/dist/db/known-table-names.d.ts +6 -0
  160. package/dist/db/known-table-names.js +21 -0
  161. package/dist/db/list-aggregate-labels.d.ts +1 -1
  162. package/dist/db/located-timestamp.d.ts +1 -1
  163. package/dist/db/located-timestamp.js +0 -5
  164. package/dist/db/migrate-generator.d.ts +17 -1
  165. package/dist/db/migrate-generator.js +50 -20
  166. package/dist/db/migrate-primary-key.d.ts +12 -0
  167. package/dist/db/migrate-primary-key.js +45 -0
  168. package/dist/db/migrate-rls-diff.d.ts +20 -0
  169. package/dist/db/migrate-rls-diff.js +61 -0
  170. package/dist/db/migrate-runner.js +7 -3
  171. package/dist/db/money.d.ts +1 -1
  172. package/dist/db/money.js +1 -1
  173. package/dist/db/parent-ref-clause.d.ts +2 -1
  174. package/dist/db/pg-error.d.ts +2 -0
  175. package/dist/db/pg-error.js +37 -21
  176. package/dist/db/queries/backfill-pii.js +3 -6
  177. package/dist/db/queries/database-now.js +2 -1
  178. package/dist/db/queries/ddl.d.ts +3 -0
  179. package/dist/db/queries/ddl.js +34 -1
  180. package/dist/db/queries/event-store.js +4 -2
  181. package/dist/db/queries/event-tenants.d.ts +2 -0
  182. package/dist/db/queries/event-tenants.js +17 -0
  183. package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
  184. package/dist/db/queries/rebuild-rls-guard.js +29 -0
  185. package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
  186. package/dist/db/queries/rls-boot-catalog.js +39 -0
  187. package/dist/db/queries/rls-catalog.d.ts +6 -0
  188. package/dist/db/queries/rls-catalog.js +82 -0
  189. package/dist/db/queries/rls-scope.d.ts +3 -0
  190. package/dist/db/queries/rls-scope.js +17 -0
  191. package/dist/db/queries/rls-shape.d.ts +10 -0
  192. package/dist/db/queries/rls-shape.js +42 -0
  193. package/dist/db/queries/session-advisory-lock.d.ts +2 -0
  194. package/dist/db/queries/session-advisory-lock.js +23 -0
  195. package/dist/db/queries/shadow-swap.d.ts +1 -2
  196. package/dist/db/queries/shadow-swap.js +11 -28
  197. package/dist/db/queries/test-stack.d.ts +4 -1
  198. package/dist/db/queries/test-stack.js +83 -2
  199. package/dist/db/query.d.ts +14 -0
  200. package/dist/db/query.js +77 -48
  201. package/dist/db/reference-data.d.ts +1 -1
  202. package/dist/db/reference-data.js +20 -3
  203. package/dist/db/render-ddl.d.ts +6 -2
  204. package/dist/db/render-ddl.js +7 -7
  205. package/dist/db/render-rls-ddl.d.ts +35 -0
  206. package/dist/db/render-rls-ddl.js +127 -0
  207. package/dist/db/replay-migration-sql.d.ts +3 -1
  208. package/dist/db/replay-migration-sql.js +22 -5
  209. package/dist/db/replay-rls.d.ts +25 -0
  210. package/dist/db/replay-rls.js +156 -0
  211. package/dist/db/row-level-security-boot-check.d.ts +5 -0
  212. package/dist/db/row-level-security-boot-check.js +85 -0
  213. package/dist/db/row-level-security-connection.d.ts +3 -0
  214. package/dist/db/row-level-security-connection.js +213 -0
  215. package/dist/db/row-level-security-scope.d.ts +33 -0
  216. package/dist/db/row-level-security-scope.js +127 -0
  217. package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
  218. package/dist/db/scope-tenant-db-to-tenant.js +14 -0
  219. package/dist/db/sql-identifier.d.ts +1 -0
  220. package/dist/db/sql-identifier.js +3 -0
  221. package/dist/db/statement-timeout.js +2 -1
  222. package/dist/db/table-builder.d.ts +2 -1
  223. package/dist/db/table-builder.js +1 -1
  224. package/dist/db/table-info.js +1 -1
  225. package/dist/db/table-push.d.ts +11 -2
  226. package/dist/db/table-push.js +15 -2
  227. package/dist/db/tenant-db-runner.d.ts +3 -1
  228. package/dist/db/tenant-db-runner.js +4 -3
  229. package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
  230. package/dist/db/tenant-db-scoped-rebind.js +33 -0
  231. package/dist/db/tenant-db-statement-runner.d.ts +13 -0
  232. package/dist/db/tenant-db-statement-runner.js +48 -0
  233. package/dist/db/tenant-db-upsert.d.ts +5 -0
  234. package/dist/db/tenant-db-upsert.js +91 -0
  235. package/dist/db/tenant-db.d.ts +17 -12
  236. package/dist/db/tenant-db.js +60 -121
  237. package/dist/db/tenant-id-filter.d.ts +3 -0
  238. package/dist/db/tenant-id-filter.js +30 -0
  239. package/dist/db/transaction-serialization.d.ts +6 -0
  240. package/dist/db/transaction-serialization.js +60 -0
  241. package/dist/derivatives/delete-stored-file.js +1 -1
  242. package/dist/derivatives/index.d.ts +2 -5
  243. package/dist/derivatives/index.js +2 -3
  244. package/dist/engine/access.d.ts +2 -1
  245. package/dist/engine/access.js +1 -1
  246. package/dist/engine/boot-validator/bundled-lists-table.d.ts +2 -0
  247. package/dist/engine/boot-validator/bundled-lists-table.js +36 -0
  248. package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
  249. package/dist/engine/boot-validator/entity-handler.js +1 -1
  250. package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +3 -0
  251. package/dist/engine/boot-validator/entity-list-aggregate-options.js +23 -0
  252. package/dist/engine/boot-validator/list-bulk-actions.d.ts +3 -0
  253. package/dist/engine/boot-validator/list-bulk-actions.js +49 -0
  254. package/dist/engine/boot-validator/list-column-layout.d.ts +8 -0
  255. package/dist/engine/boot-validator/list-column-layout.js +41 -0
  256. package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +24 -0
  257. package/dist/engine/boot-validator/list-table-aggregate-options.js +145 -0
  258. package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +11 -0
  259. package/dist/engine/boot-validator/list-table-aggregate-query.js +31 -0
  260. package/dist/engine/boot-validator/list-table-export-options.d.ts +1 -0
  261. package/dist/engine/boot-validator/list-table-export-options.js +27 -0
  262. package/dist/engine/boot-validator/list-table-options.d.ts +3 -0
  263. package/dist/engine/boot-validator/list-table-options.js +77 -0
  264. package/dist/engine/boot-validator/list-table-reject-unknown-keys.d.ts +1 -0
  265. package/dist/engine/boot-validator/list-table-reject-unknown-keys.js +7 -0
  266. package/dist/engine/boot-validator/nav.d.ts +3 -1
  267. package/dist/engine/boot-validator/nav.js +1 -1
  268. package/dist/engine/boot-validator/ownership.d.ts +2 -1
  269. package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
  270. package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
  271. package/dist/engine/boot-validator/projection-list-screens.js +3 -13
  272. package/dist/engine/boot-validator/query-refs.d.ts +2 -1
  273. package/dist/engine/boot-validator/related-list-table-rules.d.ts +4 -0
  274. package/dist/engine/boot-validator/related-list-table-rules.js +42 -0
  275. package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
  276. package/dist/engine/boot-validator/screens-kind-entity-list.js +7 -0
  277. package/dist/engine/boot-validator/screens-kind-projection-list.js +4 -0
  278. package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
  279. package/dist/engine/boot-validator/screens-lists.js +12 -2
  280. package/dist/engine/boot-validator/screens.d.ts +2 -1
  281. package/dist/engine/boot-validator/workspaces.d.ts +3 -1
  282. package/dist/engine/bridge-stub.d.ts +5 -2
  283. package/dist/engine/bridge-stub.js +39 -24
  284. package/dist/engine/build-app-schema.d.ts +2 -1
  285. package/dist/engine/build-app-schema.js +9 -1
  286. package/dist/engine/build-config-feature-schema.js +6 -1
  287. package/dist/engine/config-helpers.d.ts +2 -2
  288. package/dist/engine/config-helpers.js +0 -9
  289. package/dist/engine/constants.d.ts +0 -10
  290. package/dist/engine/constants.js +0 -8
  291. package/dist/engine/create-app.js +1 -1
  292. package/dist/engine/define-feature.d.ts +2 -1
  293. package/dist/engine/define-feature.js +5 -2
  294. package/dist/engine/define-handler.d.ts +1 -1
  295. package/dist/engine/define-step.d.ts +0 -1
  296. package/dist/engine/define-step.js +0 -3
  297. package/dist/engine/embedded-derived.d.ts +1 -1
  298. package/dist/engine/entity-handlers.d.ts +2 -1
  299. package/dist/engine/entity-handlers.js +7 -7
  300. package/dist/engine/entity-list-runtime-options.js +3 -1
  301. package/dist/engine/entity-list-searchability.d.ts +2 -1
  302. package/dist/engine/event-def.d.ts +2 -1
  303. package/dist/engine/event-helpers.d.ts +3 -1
  304. package/dist/engine/event-helpers.js +3 -3
  305. package/dist/engine/extension-names.d.ts +2 -8
  306. package/dist/engine/extension-names.js +2 -2
  307. package/dist/engine/extension-selector-plugins.d.ts +1 -1
  308. package/dist/engine/extensions/storage-provider.d.ts +1 -2
  309. package/dist/engine/extensions/user-data.d.ts +0 -8
  310. package/dist/engine/factories.d.ts +2 -1
  311. package/dist/engine/feature-builder-state.d.ts +9 -1
  312. package/dist/engine/feature-builder-state.js +1 -0
  313. package/dist/engine/feature-changelog.d.ts +1 -1
  314. package/dist/engine/feature-config-events-jobs.d.ts +4 -1
  315. package/dist/engine/feature-entity-handlers.d.ts +5 -1
  316. package/dist/engine/feature-manifest.d.ts +1 -0
  317. package/dist/engine/feature-manifest.js +2 -1
  318. package/dist/engine/feature-ui-extensions.d.ts +7 -1
  319. package/dist/engine/feature-ui-extensions.js +6 -4
  320. package/dist/engine/field-access.d.ts +3 -1
  321. package/dist/engine/field-access.js +12 -0
  322. package/dist/engine/handler-field-references.d.ts +0 -4
  323. package/dist/engine/index.d.ts +58 -55
  324. package/dist/engine/index.js +23 -28
  325. package/dist/engine/instruction-fields.d.ts +1 -1
  326. package/dist/engine/personal-data-fields.d.ts +1 -1
  327. package/dist/engine/qualified-name.d.ts +0 -1
  328. package/dist/engine/read-claim.d.ts +2 -1
  329. package/dist/engine/registry-facade.js +0 -3
  330. package/dist/engine/registry-ingest.d.ts +2 -1
  331. package/dist/engine/registry-ingest.js +1 -2
  332. package/dist/engine/registry-state.d.ts +12 -2
  333. package/dist/engine/registry-state.js +2 -3
  334. package/dist/engine/registry-validate.d.ts +3 -1
  335. package/dist/engine/registry-validate.js +7 -7
  336. package/dist/engine/run-in.d.ts +1 -1
  337. package/dist/engine/run-in.js +0 -1
  338. package/dist/engine/schema-builder.d.ts +1 -1
  339. package/dist/engine/schema-builder.js +1 -1
  340. package/dist/engine/screen-filter-ops.d.ts +2 -1
  341. package/dist/engine/screen-filter-ops.js +2 -5
  342. package/dist/engine/soft-delete-cleanup.d.ts +1 -1
  343. package/dist/engine/soft-delete-cleanup.js +4 -4
  344. package/dist/engine/state-machine.js +2 -1
  345. package/dist/engine/steps/_read-source.js +1 -1
  346. package/dist/engine/steps/aggregate-append-event.js +2 -2
  347. package/dist/engine/steps/call-feature.js +2 -2
  348. package/dist/engine/steps/mail-send.js +1 -1
  349. package/dist/engine/steps/retry.js +1 -1
  350. package/dist/engine/steps/wait-for-event.js +1 -1
  351. package/dist/engine/steps/wait.js +1 -1
  352. package/dist/engine/steps/webhook-send.js +1 -1
  353. package/dist/engine/strip-disabled-features-from-app-schema.js +7 -3
  354. package/dist/engine/template-variables.d.ts +2 -1
  355. package/dist/engine/transfer-adjacency.d.ts +1 -1
  356. package/dist/engine/types/feature.d.ts +1 -0
  357. package/dist/engine/types/index.d.ts +8 -30
  358. package/dist/engine/types/index.js +2 -10
  359. package/dist/engine/types/screen.d.ts +1 -1
  360. package/dist/engine/types/screen.js +1 -1
  361. package/dist/engine/validation.d.ts +2 -1
  362. package/dist/entrypoint/index.d.ts +9 -35
  363. package/dist/entrypoint/index.js +10 -1
  364. package/dist/entrypoint/internals.d.ts +40 -0
  365. package/dist/entrypoint/internals.js +1 -0
  366. package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
  367. package/dist/entrypoint/row-level-security-mode-check.js +19 -0
  368. package/dist/env/dry-run-internals.d.ts +10 -0
  369. package/dist/env/dry-run-internals.js +1 -0
  370. package/dist/env/dry-run.d.ts +1 -10
  371. package/dist/env/dry-run.js +2 -1
  372. package/dist/env/index.d.ts +1 -85
  373. package/dist/env/index.js +6 -50
  374. package/dist/env/internals.d.ts +87 -0
  375. package/dist/env/internals.js +53 -0
  376. package/dist/errors/classes.js +2 -2
  377. package/dist/errors/index.d.ts +5 -14
  378. package/dist/errors/index.js +4 -9
  379. package/dist/errors/member-resolution.js +1 -1
  380. package/dist/errors/reasons.d.ts +0 -1
  381. package/dist/errors/reasons.js +7 -7
  382. package/dist/errors/serialize.d.ts +0 -18
  383. package/dist/errors/serialize.js +0 -27
  384. package/dist/es-ops/index.d.ts +4 -4
  385. package/dist/es-ops/index.js +2 -2
  386. package/dist/es-ops/operations-schema.d.ts +1 -1
  387. package/dist/es-ops/types.d.ts +4 -5
  388. package/dist/event-store/admin-api-internals.d.ts +14 -0
  389. package/dist/event-store/admin-api-internals.js +1 -0
  390. package/dist/event-store/admin-api.d.ts +1 -14
  391. package/dist/event-store/admin-api.js +11 -6
  392. package/dist/event-store/archive.js +4 -2
  393. package/dist/event-store/errors.js +2 -2
  394. package/dist/event-store/event-store.d.ts +1 -0
  395. package/dist/event-store/event-store.js +42 -32
  396. package/dist/event-store/events-schema.js +4 -1
  397. package/dist/event-store/index.d.ts +11 -13
  398. package/dist/event-store/index.js +7 -9
  399. package/dist/event-store/provenance-append.js +1 -1
  400. package/dist/event-store/rebuild-dead-letter.js +4 -2
  401. package/dist/event-store/snapshot.js +4 -3
  402. package/dist/event-store/stream-scope.d.ts +2 -0
  403. package/dist/event-store/stream-scope.js +6 -0
  404. package/dist/event-store/upcaster-dead-letter.js +4 -2
  405. package/dist/event-store/upcaster.d.ts +2 -1
  406. package/dist/files/action-form-upload.d.ts +2 -1
  407. package/dist/files/action-form-upload.js +1 -1
  408. package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
  409. package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
  410. package/dist/files/bind-pending-file-refs.d.ts +2 -1
  411. package/dist/files/bind-pending-file-refs.js +2 -1
  412. package/dist/files/bind-referenced-files.write.js +1 -1
  413. package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
  414. package/dist/files/create-file-ref-from-bytes.js +6 -3
  415. package/dist/files/create-file-ref.d.ts +6 -2
  416. package/dist/files/create-file-ref.js +13 -4
  417. package/dist/files/dispose-removed-file-refs.d.ts +2 -1
  418. package/dist/files/dispose-removed-file-refs.js +1 -1
  419. package/dist/files/feature.js +2 -2
  420. package/dist/files/file-handle.js +1 -1
  421. package/dist/files/file-routes.d.ts +3 -1
  422. package/dist/files/file-routes.js +41 -4
  423. package/dist/files/index.d.ts +11 -13
  424. package/dist/files/index.js +5 -7
  425. package/dist/files/load-save-file-refs.d.ts +2 -1
  426. package/dist/files/load-save-file-refs.js +1 -1
  427. package/dist/files/provider-resolver.d.ts +6 -4
  428. package/dist/files/provider-resolver.js +5 -5
  429. package/dist/files/record-write-check.d.ts +6 -0
  430. package/dist/files/record-write-check.js +13 -0
  431. package/dist/files/storage-tracking.js +4 -2
  432. package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
  433. package/dist/files/sweep-orphaned-uploads.js +1 -1
  434. package/dist/files/upload-ledger.d.ts +2 -2
  435. package/dist/files/upload-ledger.js +4 -4
  436. package/dist/i18n/index.d.ts +2 -8
  437. package/dist/i18n/index.js +1 -1
  438. package/dist/i18n/internals.d.ts +7 -0
  439. package/dist/i18n/internals.js +1 -0
  440. package/dist/i18n/required-surface-keys.d.ts +4 -1
  441. package/dist/i18n/required-surface-keys.js +7 -2
  442. package/dist/internal/row-level-security.d.ts +3 -0
  443. package/dist/internal/row-level-security.js +3 -0
  444. package/dist/internal/stack-support.d.ts +1 -1
  445. package/dist/internal/stack-support.js +1 -1
  446. package/dist/internal/testing.d.ts +1 -0
  447. package/dist/internal/testing.js +10 -6
  448. package/dist/jobs/index.d.ts +1 -1
  449. package/dist/jobs/job-append-event.d.ts +12 -0
  450. package/dist/jobs/job-append-event.js +30 -0
  451. package/dist/jobs/job-runner-context.d.ts +2 -2
  452. package/dist/jobs/job-runner-context.js +46 -16
  453. package/dist/jobs/job-runner-execution.d.ts +1 -1
  454. package/dist/jobs/job-runner-execution.js +6 -4
  455. package/dist/jobs/job-runner-gates.d.ts +1 -1
  456. package/dist/jobs/job-runner-gates.js +0 -1
  457. package/dist/jobs/job-runner-helpers.d.ts +11 -4
  458. package/dist/jobs/job-runner-helpers.js +10 -1
  459. package/dist/jobs/job-runner-scope.d.ts +5 -2
  460. package/dist/jobs/job-runner-scope.js +6 -6
  461. package/dist/jobs/job-runner-types.d.ts +2 -1
  462. package/dist/jobs/job-runner.js +22 -6
  463. package/dist/jobs/max-per-tenant.d.ts +1 -1
  464. package/dist/logging/index.d.ts +1 -2
  465. package/dist/logging/index.js +1 -1
  466. package/dist/logging/pino-logger.js +1 -1
  467. package/dist/logging/utils.d.ts +1 -0
  468. package/dist/logging/utils.js +6 -0
  469. package/dist/migrations/index.d.ts +3 -3
  470. package/dist/migrations/index.js +3 -3
  471. package/dist/migrations/pending-rebuilds.d.ts +1 -1
  472. package/dist/migrations/pending-rebuilds.js +1 -1
  473. package/dist/migrations/pii-event-backfill.js +4 -1
  474. package/dist/observability/escape-hatch-report.d.ts +2 -1
  475. package/dist/observability/escape-hatch-report.js +9 -2
  476. package/dist/observability/index.d.ts +7 -15
  477. package/dist/observability/index.js +4 -12
  478. package/dist/observability/metric-validator.js +1 -1
  479. package/dist/observability/metrics-handle.d.ts +0 -1
  480. package/dist/observability/metrics-handle.js +2 -15
  481. package/dist/observability/recording-tracer.d.ts +1 -2
  482. package/dist/observability/recording-tracer.js +0 -6
  483. package/dist/observability/sensitive-filter.d.ts +0 -2
  484. package/dist/observability/sensitive-filter.js +0 -29
  485. package/dist/pipeline/active-membership.d.ts +2 -1
  486. package/dist/pipeline/active-membership.js +6 -2
  487. package/dist/pipeline/after-rollback-sink.d.ts +6 -0
  488. package/dist/pipeline/after-rollback-sink.js +32 -0
  489. package/dist/pipeline/append-event-core.d.ts +2 -1
  490. package/dist/pipeline/append-event-core.js +2 -2
  491. package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
  492. package/dist/pipeline/attach-outside-transaction.js +13 -0
  493. package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
  494. package/dist/pipeline/cascade-handler.d.ts +2 -1
  495. package/dist/pipeline/cascade-handler.js +3 -2
  496. package/dist/pipeline/config-accessor-factory.d.ts +1 -1
  497. package/dist/pipeline/config-accessor-factory.js +1 -1
  498. package/dist/pipeline/context-services.d.ts +56 -0
  499. package/dist/pipeline/context-services.js +73 -0
  500. package/dist/pipeline/dispatch-batch.d.ts +2 -1
  501. package/dist/pipeline/dispatch-batch.js +39 -19
  502. package/dist/pipeline/dispatch-query.js +5 -4
  503. package/dist/pipeline/dispatch-scope.d.ts +6 -0
  504. package/dist/pipeline/dispatch-scope.js +27 -0
  505. package/dist/pipeline/dispatch-shared.d.ts +13 -9
  506. package/dist/pipeline/dispatch-shared.js +75 -194
  507. package/dist/pipeline/dispatch-stream.js +8 -4
  508. package/dist/pipeline/dispatch-write.d.ts +2 -1
  509. package/dist/pipeline/dispatch-write.js +10 -8
  510. package/dist/pipeline/dispatcher-utils.d.ts +3 -1
  511. package/dist/pipeline/dispatcher-utils.js +8 -2
  512. package/dist/pipeline/dispatcher.d.ts +3 -2
  513. package/dist/pipeline/dispatcher.js +4 -3
  514. package/dist/pipeline/event-consumer-state.d.ts +0 -1
  515. package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
  516. package/dist/pipeline/event-dispatcher-delivery.js +7 -3
  517. package/dist/pipeline/event-dispatcher.d.ts +3 -2
  518. package/dist/pipeline/event-dispatcher.js +13 -12
  519. package/dist/pipeline/event-retention.js +59 -56
  520. package/dist/pipeline/handler-access-error.js +2 -1
  521. package/dist/pipeline/handler-context-auth.d.ts +5 -6
  522. package/dist/pipeline/handler-context-auth.js +7 -4
  523. package/dist/pipeline/handler-context-config.d.ts +2 -5
  524. package/dist/pipeline/handler-context-config.js +2 -2
  525. package/dist/pipeline/handler-context-db.d.ts +32 -7
  526. package/dist/pipeline/handler-context-db.js +26 -17
  527. package/dist/pipeline/handler-context-dispatch.d.ts +14 -6
  528. package/dist/pipeline/handler-context-dispatch.js +18 -5
  529. package/dist/pipeline/handler-context-events.d.ts +22 -38
  530. package/dist/pipeline/handler-context-events.js +42 -35
  531. package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
  532. package/dist/pipeline/handler-context-member-resolution.js +110 -0
  533. package/dist/pipeline/handler-context-notify.d.ts +3 -2
  534. package/dist/pipeline/handler-context-notify.js +1 -1
  535. package/dist/pipeline/handler-context-observability.d.ts +2 -4
  536. package/dist/pipeline/handler-context-observability.js +7 -5
  537. package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
  538. package/dist/pipeline/handler-context-phase-denials.js +98 -0
  539. package/dist/pipeline/handler-context-scope.d.ts +7 -10
  540. package/dist/pipeline/handler-context-scope.js +18 -20
  541. package/dist/pipeline/index.d.ts +9 -21
  542. package/dist/pipeline/index.js +5 -7
  543. package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
  544. package/dist/pipeline/irreversible-operation-gate.js +2 -2
  545. package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
  546. package/dist/pipeline/lifecycle-pipeline.js +9 -15
  547. package/dist/pipeline/member-read-only-transaction.js +11 -3
  548. package/dist/pipeline/member-reader.d.ts +1 -1
  549. package/dist/pipeline/member-reader.js +2 -2
  550. package/dist/pipeline/msp-rebuild.js +5 -3
  551. package/dist/pipeline/multi-stream-apply-context.js +3 -2
  552. package/dist/pipeline/notify-scope.d.ts +2 -1
  553. package/dist/pipeline/pre-handler-gates.d.ts +2 -1
  554. package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
  555. package/dist/pipeline/pre-transaction-reservations.js +9 -7
  556. package/dist/pipeline/projection-rebuild.js +12 -5
  557. package/dist/pipeline/projection-state.d.ts +0 -6
  558. package/dist/pipeline/projection-state.js +0 -5
  559. package/dist/pipeline/projections-runner.d.ts +2 -1
  560. package/dist/pipeline/projections-runner.js +10 -6
  561. package/dist/pipeline/system-hooks.d.ts +6 -2
  562. package/dist/pipeline/system-hooks.js +61 -10
  563. package/dist/pipeline/system-identity-switch.d.ts +4 -2
  564. package/dist/pipeline/system-identity-switch.js +51 -36
  565. package/dist/pipeline/typed-append-event.d.ts +2 -0
  566. package/dist/pipeline/typed-append-event.js +4 -0
  567. package/dist/pipeline/write-origin.js +2 -2
  568. package/dist/pipeline/write-result-masking.d.ts +1 -1
  569. package/dist/pipeline/write-result-masking.js +13 -10
  570. package/dist/random/index.d.ts +1 -2
  571. package/dist/random/index.js +1 -2
  572. package/dist/rate-limit/bucket.d.ts +2 -1
  573. package/dist/rate-limit/middleware.js +2 -1
  574. package/dist/redis/index.d.ts +3 -4
  575. package/dist/redis/index.js +2 -2
  576. package/dist/schema-cli/apply-command.js +5 -2
  577. package/dist/schema-cli/baseline-command.js +7 -2
  578. package/dist/schema-cli/generate-command.js +7 -9
  579. package/dist/schema-cli/shared.d.ts +4 -0
  580. package/dist/schema-cli/shared.js +21 -2
  581. package/dist/schema-cli/status-command.js +8 -2
  582. package/dist/schema-cli/validate-command.js +52 -4
  583. package/dist/schema-cli.d.ts +0 -1
  584. package/dist/search/configure-tenant-index.d.ts +1 -3
  585. package/dist/search/configure-tenant-index.js +0 -4
  586. package/dist/search/index.d.ts +1 -4
  587. package/dist/search/index.js +0 -2
  588. package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
  589. package/dist/search/meilisearch-adapter-internals.js +9 -0
  590. package/dist/search/meilisearch-adapter.d.ts +1 -8
  591. package/dist/search/meilisearch-adapter.js +6 -7
  592. package/dist/search/meilisearch-peer.d.ts +2 -0
  593. package/dist/search/meilisearch-peer.js +5 -0
  594. package/dist/search/reindex-entity.js +107 -91
  595. package/dist/secrets/index.d.ts +3 -4
  596. package/dist/secrets/index.js +2 -3
  597. package/dist/seeding/index.d.ts +2 -2
  598. package/dist/seeding/index.js +1 -2
  599. package/dist/time/index.d.ts +2 -2
  600. package/dist/time/index.js +1 -1
  601. package/dist/time/tz-context.d.ts +0 -5
  602. package/dist/time/tz-context.js +0 -9
  603. package/dist/ui-types/index.d.ts +8 -11
  604. package/dist/ui-types/index.js +3 -3
  605. package/dist/upgrade-changelog.d.ts +3 -0
  606. package/dist/upgrade-changelog.js +18 -0
  607. package/dist/upgrade-cli-internals.d.ts +8 -0
  608. package/dist/upgrade-cli-internals.js +63 -0
  609. package/dist/upgrade-cli.d.ts +1 -18
  610. package/dist/upgrade-cli.js +29 -137
  611. package/dist/upgrade-marker-parse.d.ts +32 -0
  612. package/dist/upgrade-marker-parse.js +73 -0
  613. package/dist/utils/import-optional-peer.d.ts +6 -0
  614. package/dist/utils/import-optional-peer.js +19 -0
  615. package/dist/utils/index.d.ts +1 -4
  616. package/dist/utils/index.js +1 -4
  617. package/package.json +27 -20
  618. package/src/changes.json +451 -0
  619. package/dist/crypto/request-kms-cache.d.ts +0 -8
  620. package/dist/crypto/request-kms-cache.js +0 -21
  621. package/dist/engine/codemod/index.d.ts +0 -2
  622. package/dist/engine/codemod/index.js +0 -1
  623. package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
  624. package/dist/engine/codemod/pipeline-codemod.js +0 -536
  625. package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
  626. package/dist/engine/feature-ast/entity-field-types.js +0 -35
  627. package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
  628. package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
  629. package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
  630. package/dist/engine/feature-ast/extractors/events.js +0 -275
  631. package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
  632. package/dist/engine/feature-ast/extractors/handlers.js +0 -358
  633. package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
  634. package/dist/engine/feature-ast/extractors/hooks.js +0 -248
  635. package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
  636. package/dist/engine/feature-ast/extractors/index.js +0 -13
  637. package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
  638. package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
  639. package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
  640. package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
  641. package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
  642. package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
  643. package/dist/engine/feature-ast/extractors/round1.d.ts +0 -10
  644. package/dist/engine/feature-ast/extractors/round1.js +0 -81
  645. package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
  646. package/dist/engine/feature-ast/extractors/round2.js +0 -191
  647. package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
  648. package/dist/engine/feature-ast/extractors/round3.js +0 -292
  649. package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
  650. package/dist/engine/feature-ast/extractors/round5.js +0 -68
  651. package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
  652. package/dist/engine/feature-ast/extractors/round6.js +0 -17
  653. package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
  654. package/dist/engine/feature-ast/extractors/shared.js +0 -343
  655. package/dist/engine/feature-ast/index.d.ts +0 -16
  656. package/dist/engine/feature-ast/index.js +0 -10
  657. package/dist/engine/feature-ast/parse.d.ts +0 -31
  658. package/dist/engine/feature-ast/parse.js +0 -483
  659. package/dist/engine/feature-ast/patch.d.ts +0 -210
  660. package/dist/engine/feature-ast/patch.js +0 -610
  661. package/dist/engine/feature-ast/patcher.d.ts +0 -217
  662. package/dist/engine/feature-ast/patcher.js +0 -281
  663. package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1476
  664. package/dist/engine/feature-ast/pattern-change-schema.js +0 -1226
  665. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
  666. package/dist/engine/feature-ast/pattern-id-matchers.js +0 -210
  667. package/dist/engine/feature-ast/patterns.d.ts +0 -318
  668. package/dist/engine/feature-ast/patterns.js +0 -106
  669. package/dist/engine/feature-ast/render.d.ts +0 -47
  670. package/dist/engine/feature-ast/render.js +0 -662
  671. package/dist/engine/feature-ast/source-location.d.ts +0 -17
  672. package/dist/engine/feature-ast/source-location.js +0 -27
  673. package/dist/engine/pattern-library/index.d.ts +0 -2
  674. package/dist/engine/pattern-library/index.js +0 -3
  675. package/dist/engine/pattern-library/library.d.ts +0 -14
  676. package/dist/engine/pattern-library/library.js +0 -93
  677. package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
  678. package/dist/engine/pattern-library/mixed-schemas.js +0 -559
  679. package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
  680. package/dist/engine/pattern-library/opaque-schemas.js +0 -115
  681. package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
  682. package/dist/engine/pattern-library/shared-fields.js +0 -88
  683. package/dist/engine/pattern-library/static-schemas.d.ts +0 -20
  684. package/dist/engine/pattern-library/static-schemas.js +0 -478
  685. package/dist/engine/pattern-library/types.d.ts +0 -158
  686. package/dist/engine/pattern-library/types.js +0 -36
  687. package/dist/engine/provider-plugin-context.d.ts +0 -3
  688. package/dist/engine/provider-plugin-context.js +0 -28
  689. package/dist/engine/resolve-config-or-param.d.ts +0 -18
  690. package/dist/engine/resolve-config-or-param.js +0 -76
  691. package/src/scripts/codemod/README.md +0 -187
  692. package/src/scripts/codemod/codemod-support.ts +0 -334
  693. package/src/scripts/codemod/collect-source-files.ts +0 -48
  694. package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
  695. package/src/scripts/codemod/db-factory.ts +0 -810
  696. package/src/scripts/codemod/feature-factory.ts +0 -429
  697. package/src/scripts/codemod/feature-layout.ts +0 -424
  698. package/src/scripts/codemod/import-extensions.ts +0 -118
  699. package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
  700. package/src/scripts/codemod/migrate-db-raw.ts +0 -401
  701. package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
  702. package/src/scripts/codemod/object-form.ts +0 -746
  703. package/src/scripts/codemod/package-merge.ts +0 -299
  704. package/src/scripts/codemod/pii-personal-migration.ts +0 -816
  705. package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
  706. package/src/scripts/codemod/s3-imports.ts +0 -236
  707. package/src/scripts/codemod/tenant-db-options.ts +0 -454
  708. package/src/scripts/codemod/testing-injection.ts +0 -215
  709. package/src/scripts/codemod/testing-move-targets.ts +0 -161
  710. package/src/scripts/codemod/testing-move.ts +0 -542
  711. package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
@@ -1,2 +1,3 @@
1
- import type { AccessRule, SessionUser } from "./types/index.ts";
1
+ import type { AccessRule } from "@cosmicdrift/kumiko-types/handlers";
2
+ import type { SessionUser } from "./types/index.ts";
2
3
  export declare function hasAccess(user: Pick<SessionUser, "roles">, access: AccessRule | undefined): boolean;
@@ -1,5 +1,5 @@
1
+ import { isOpenToAllGranted } from "@cosmicdrift/kumiko-types/handlers";
1
2
  import { ANONYMOUS_ROLE } from "./system-user.js";
2
- import { isOpenToAllGranted } from "./types/index.js";
3
3
  // Default-deny: a handler without an explicit AccessRule is unreachable. To
4
4
  // grant access a handler must either list allowed roles or opt into
5
5
  // openToAll. Leaving access undefined now returns false (previously true) —
@@ -0,0 +1,2 @@
1
+ export declare const BUNDLED_LISTS_OPTION_KEYS: readonly ["table", "pinFirstColumn"];
2
+ export declare function validateBundledListsOptions(options: unknown): void;
@@ -0,0 +1,36 @@
1
+ import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
2
+ import { LIST_TABLE_OPTION_KEYS } from "../types/screen.js";
3
+ import { validateListTableOptions } from "./list-table-options.js";
4
+ export const BUNDLED_LISTS_OPTION_KEYS = ["table", "pinFirstColumn"];
5
+ // grouping and totals name fields of one list, so they cannot be shared across lists
6
+ const SCREEN_ONLY_TABLE_KEYS = ["grouping", "totals"];
7
+ export function validateBundledListsOptions(options) {
8
+ if (!isPlainObject(options)) {
9
+ throw new Error("bundledLists must be an object like { table: { columnPicker: true } }.");
10
+ }
11
+ const unknownKeys = Object.keys(options).filter((key) => !BUNDLED_LISTS_OPTION_KEYS.some((allowed) => allowed === key));
12
+ if (unknownKeys.length > 0) {
13
+ throw new Error(`bundledLists has unknown key(s) ${unknownKeys.map((k) => `"${k}"`).join(", ")}. ` +
14
+ `Allowed keys: ${BUNDLED_LISTS_OPTION_KEYS.join(", ")}.`);
15
+ }
16
+ const table = options["table"];
17
+ if (!isPlainObject(table)) {
18
+ const allowed = LIST_TABLE_OPTION_KEYS.filter((key) => !SCREEN_ONLY_TABLE_KEYS.some((screenOnly) => screenOnly === key));
19
+ throw new Error(`bundledLists.table must be an object like { columnPicker: true }. ` +
20
+ `Allowed keys: ${allowed.join(", ")}.`);
21
+ }
22
+ for (const key of SCREEN_ONLY_TABLE_KEYS) {
23
+ if (table[key] !== undefined) {
24
+ throw new Error(`bundledLists.table.${key} is not allowed: ${key} depends on the fields of one list. ` +
25
+ `Set it in the table block of that screen.`);
26
+ }
27
+ }
28
+ validateListTableOptions("bundledLists", table, [], true);
29
+ const pinFirstColumn = options["pinFirstColumn"];
30
+ if (pinFirstColumn !== undefined && typeof pinFirstColumn !== "boolean") {
31
+ throw new Error("bundledLists.pinFirstColumn must be a boolean.");
32
+ }
33
+ if (pinFirstColumn === true && table["pinning"] !== true) {
34
+ throw new Error("bundledLists.pinFirstColumn needs bundledLists.table.pinning: true.");
35
+ }
36
+ }
@@ -1,4 +1,5 @@
1
- import type { FeatureDefinition, QueryHandlerDef } from "../types/index.ts";
1
+ import type { QueryHandlerDef } from "@cosmicdrift/kumiko-types/handlers";
2
+ import type { FeatureDefinition } from "../types/index.ts";
2
3
  export declare const FILE_FIELD_TYPES: Set<string>;
3
4
  export declare const PII_DIRECT_NAME_HINTS: ReadonlySet<string>;
4
5
  export declare const PII_USER_OWNED_NAME_HINTS: ReadonlySet<string>;
@@ -209,7 +209,7 @@ export function validatePerCommandTransaction(featureName, handlerName, handler)
209
209
  const conflicting = perCommandConflict(handler);
210
210
  if (conflicting !== undefined) {
211
211
  throw new Error(`write handler "${featureName}:write:${handlerName}" declares transaction: "perCommand" together with ${conflicting} — ` +
212
- "a perCommand handler holds no transaction, so move the phase into the commands it issues via ctx.write.");
212
+ "a perCommand handler holds no transaction, so move the phase into the commands it issues via ctx.dispatch.write.");
213
213
  }
214
214
  }
215
215
  const IP_SCOPED_RATE_LIMIT_PER = ["ip", "ip+handler"];
@@ -0,0 +1,3 @@
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
+ import type { EntityListScreenDefinition } from "../types/screen.ts";
3
+ export declare function validateEntityListAggregateOptions(where: string, screen: EntityListScreenDefinition, entity: EntityDefinition): void;
@@ -0,0 +1,23 @@
1
+ import { isListFilterAllowed } from "../../db/entity-field-encryption.js";
2
+ import { isFieldFilterable } from "../screen-filter-ops.js";
3
+ import { entityAggregateFieldLookup, validateListTableAggregateFieldTypes, } from "./list-table-aggregate-options.js";
4
+ const RANGE_FACET_TYPES = ["number", "decimal", "money", "bigInt"];
5
+ function validateRangeFacets(where, facets, entity) {
6
+ for (const [field, config] of Object.entries(facets ?? {})) {
7
+ if (config === false || config.display !== "range")
8
+ continue;
9
+ const def = Object.hasOwn(entity.fields, field) ? entity.fields[field] : undefined;
10
+ if (def === undefined || !RANGE_FACET_TYPES.includes(def.type)) {
11
+ throw new Error(`${where} facets.${field}: display "range" needs a number, decimal, money or bigInt field.`);
12
+ }
13
+ if (!isFieldFilterable(def) || !isListFilterAllowed(entity, field, { op: "gte", value: 0 })) {
14
+ throw new Error(`${where} facets.${field}: display "range" needs filterable: true on a field that is not encrypted, personal or secret.`);
15
+ }
16
+ }
17
+ }
18
+ export function validateEntityListAggregateOptions(where, screen, entity) {
19
+ if (screen.table !== undefined) {
20
+ validateListTableAggregateFieldTypes(where, screen.table, entityAggregateFieldLookup(entity), true);
21
+ }
22
+ validateRangeFacets(where, screen.facets, entity);
23
+ }
@@ -0,0 +1,3 @@
1
+ import { type RowAction } from "../types/screen.ts";
2
+ /** `where` is the full message prefix, e.g. `[Feature x] Screen "y" (entityList)`. */
3
+ export declare function validateListBulkActions(where: string, bulkActions: unknown, rowActions: readonly RowAction[] | undefined): void;
@@ -0,0 +1,49 @@
1
+ import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
2
+ import { isKebabSegment } from "../qualified-name.js";
3
+ import { LIST_BULK_ACTION_KEYS } from "../types/screen.js";
4
+ function validateBulkActionTarget(where, bulkId, target, rowActions) {
5
+ if (typeof target !== "string" || target === "") {
6
+ throw new Error(`${where} bulk action "${bulkId}" needs rowAction: the id of a row action.`);
7
+ }
8
+ const rowAction = rowActions.find((action) => action.id === target);
9
+ if (rowAction === undefined) {
10
+ const known = rowActions.map((action) => action.id).join(", ") || "(none)";
11
+ throw new Error(`${where} bulk action "${bulkId}" points at rowAction "${target}", which is not declared ` +
12
+ `in rowActions. Declared row actions: ${known}.`);
13
+ }
14
+ if (rowAction.kind !== undefined && rowAction.kind !== "writeHandler") {
15
+ throw new Error(`${where} bulk action "${bulkId}" points at rowAction "${target}" of kind "${rowAction.kind}". ` +
16
+ `Bulk actions run one server write per row, so only writeHandler row actions are allowed.`);
17
+ }
18
+ }
19
+ /** `where` is the full message prefix, e.g. `[Feature x] Screen "y" (entityList)`. */
20
+ export function validateListBulkActions(where, bulkActions, rowActions) {
21
+ // skip: no bulk actions declared
22
+ if (bulkActions === undefined)
23
+ return;
24
+ if (!Array.isArray(bulkActions) || bulkActions.length === 0) {
25
+ throw new Error(`${where} bulkActions must be a non-empty array like [{ id: "archive", rowAction: "archive" }].`);
26
+ }
27
+ const seen = new Set();
28
+ for (const entry of bulkActions) {
29
+ if (!isPlainObject(entry)) {
30
+ throw new Error(`${where} bulkActions entries must be objects with id and rowAction.`);
31
+ }
32
+ const id = entry["id"];
33
+ if (typeof id !== "string" || !isKebabSegment(id)) {
34
+ throw new Error(`${where} bulk action id ${JSON.stringify(id)} must be a kebab-case string.`);
35
+ }
36
+ if (seen.has(id))
37
+ throw new Error(`${where} declares bulk action "${id}" twice.`);
38
+ seen.add(id);
39
+ const unknown = Object.keys(entry).filter((key) => !isOneOfBulkKeys(key));
40
+ if (unknown.length > 0) {
41
+ throw new Error(`${where} bulk action "${id}" has unknown key(s) ${unknown.map((k) => `"${k}"`).join(", ")}. ` +
42
+ `Allowed keys: ${LIST_BULK_ACTION_KEYS.join(", ")}.`);
43
+ }
44
+ validateBulkActionTarget(where, id, entry["rowAction"], rowActions ?? []);
45
+ }
46
+ }
47
+ function isOneOfBulkKeys(key) {
48
+ return LIST_BULK_ACTION_KEYS.some((allowed) => allowed === key);
49
+ }
@@ -0,0 +1,8 @@
1
+ import { type ListColumnSpec } from "../types/screen.ts";
2
+ type ColumnLayoutFlags = {
3
+ readonly pinning: boolean;
4
+ readonly resizing: boolean;
5
+ };
6
+ /** Checks `pinned`, `width` and `minWidth` of every column against the table's opt-in flags. */
7
+ export declare function validateColumnLayout(where: string, flags: ColumnLayoutFlags, columns: readonly ListColumnSpec[]): void;
8
+ export {};
@@ -0,0 +1,41 @@
1
+ import { isOneOf } from "@cosmicdrift/kumiko-types/type-guards";
2
+ import { normalizeListColumn } from "../screen-helpers.js";
3
+ import { LIST_COLUMN_PINS } from "../types/screen.js";
4
+ function isPositiveFiniteNumber(value) {
5
+ return typeof value === "number" && Number.isFinite(value) && value > 0;
6
+ }
7
+ function validatePixelWidth(where, field, key, value) {
8
+ if (!isPositiveFiniteNumber(value)) {
9
+ throw new Error(`${where} column "${field}" has ${key} ${JSON.stringify(value)} — ` +
10
+ `must be a finite number of pixels greater than 0.`);
11
+ }
12
+ }
13
+ /** Checks `pinned`, `width` and `minWidth` of every column against the table's opt-in flags. */
14
+ export function validateColumnLayout(where, flags, columns) {
15
+ for (const col of columns.map(normalizeListColumn)) {
16
+ if (col.pinned !== undefined) {
17
+ if (!isOneOf(LIST_COLUMN_PINS, col.pinned)) {
18
+ throw new Error(`${where} column "${col.field}" has pinned ${JSON.stringify(col.pinned)} — ` +
19
+ `must be one of ${LIST_COLUMN_PINS.map((pin) => `"${pin}"`).join(", ")}.`);
20
+ }
21
+ if (!flags.pinning) {
22
+ throw new Error(`${where} column "${col.field}" is pinned but table.pinning is not enabled, ` +
23
+ `so the pin would have no effect. Set table: { pinning: true } or remove "pinned".`);
24
+ }
25
+ }
26
+ for (const key of ["width", "minWidth"]) {
27
+ const value = col[key];
28
+ if (value === undefined)
29
+ continue;
30
+ validatePixelWidth(where, col.field, key, value);
31
+ if (!flags.resizing) {
32
+ throw new Error(`${where} column "${col.field}" sets ${key} but table.resizing is not enabled, ` +
33
+ `so it would have no effect. Set table: { resizing: true } or remove "${key}".`);
34
+ }
35
+ }
36
+ if (col.width !== undefined && col.minWidth !== undefined && col.minWidth > col.width) {
37
+ throw new Error(`${where} column "${col.field}" has minWidth ${col.minWidth} greater than width ${col.width}. ` +
38
+ `Lower minWidth or raise width.`);
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,24 @@
1
+ import type { EntityDefinition, FieldDefinition } from "@cosmicdrift/kumiko-types/fields";
2
+ import { type ListColumnSpec, type ListTableGrouping, type ListTableTotal } from "../types/screen.ts";
3
+ type FieldType = FieldDefinition["type"];
4
+ export type AggregateFieldInfo = {
5
+ readonly type: FieldType;
6
+ readonly multiple: boolean;
7
+ readonly secret: boolean;
8
+ };
9
+ export declare function groupingFieldsOf(grouping: {
10
+ readonly field?: unknown;
11
+ readonly fields?: unknown;
12
+ }): string[];
13
+ /** Structure and column membership; field types are checked where the entity is known. */
14
+ export declare function validateListTableAggregateShape(where: string, table: Readonly<Record<string, unknown>>, columns: readonly ListColumnSpec[]): void;
15
+ /**
16
+ * `lookup` answers undefined for a field it does not know. With `strict` (an entity
17
+ * stands behind the list) that is an error; otherwise the field is left to the server.
18
+ */
19
+ export declare function validateListTableAggregateFieldTypes(where: string, table: {
20
+ readonly grouping?: ListTableGrouping;
21
+ readonly totals?: readonly ListTableTotal[];
22
+ }, lookup: (field: string) => AggregateFieldInfo | undefined, strict: boolean): void;
23
+ export declare function entityAggregateFieldLookup(entity: EntityDefinition): (field: string) => AggregateFieldInfo | undefined;
24
+ export {};
@@ -0,0 +1,145 @@
1
+ import { LIST_AGGREGATE_MEASURE_KINDS } from "@cosmicdrift/kumiko-types/list-aggregate-types";
2
+ import { isOneOf, isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
3
+ import { isListAggregateGroupable, isListAggregateMeasureSupported, } from "../../db/aggregate-sql.js";
4
+ import { holdsCiphertextOrSecret } from "../../db/entity-field-encryption.js";
5
+ import { normalizeListColumn } from "../screen-helpers.js";
6
+ import { LIST_TABLE_GROUPING_KEYS, LIST_TABLE_TOTAL_KEYS, } from "../types/screen.js";
7
+ import { rejectUnknownKeys } from "./list-table-reject-unknown-keys.js";
8
+ function isStringArray(value) {
9
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
10
+ }
11
+ function isStringRecord(value) {
12
+ return isPlainObject(value) && Object.values(value).every((entry) => typeof entry === "string");
13
+ }
14
+ function isGroupKeyScalar(value) {
15
+ return value === null || ["string", "number", "boolean"].includes(typeof value);
16
+ }
17
+ function requireScreenColumn(where, path, field, columnFields) {
18
+ // skip: the field is a column, nothing to report
19
+ if (columnFields.has(field))
20
+ return;
21
+ throw new Error(`${where} ${path} "${field}" is not a column of this screen. ` +
22
+ `Columns: ${[...columnFields].join(", ")}.`);
23
+ }
24
+ const GROUPING_VALUE_CHECKS = [
25
+ { key: "field", isValid: (v) => typeof v === "string", expected: "must be a string" },
26
+ { key: "fields", isValid: isStringArray, expected: "must be an array of field names" },
27
+ { key: "userChoice", isValid: (v) => typeof v === "boolean", expected: "must be a boolean" },
28
+ { key: "label", isValid: (v) => typeof v === "string", expected: "must be an i18n key" },
29
+ { key: "labels", isValid: isStringRecord, expected: "must map group keys to i18n keys" },
30
+ {
31
+ key: "collapsedWhen",
32
+ isValid: isGroupKeyScalar,
33
+ expected: "must be a string, number, boolean or null",
34
+ },
35
+ ];
36
+ function validateGroupingValueTypes(where, grouping) {
37
+ for (const check of GROUPING_VALUE_CHECKS) {
38
+ const value = grouping[check.key];
39
+ if (value !== undefined && !check.isValid(value)) {
40
+ throw new Error(`${where} table.grouping.${check.key} ${check.expected}.`);
41
+ }
42
+ }
43
+ }
44
+ function validateGroupingFieldChoice(where, grouping) {
45
+ const { field, fields, userChoice } = grouping;
46
+ const offered = isStringArray(fields) ? fields : [];
47
+ if (field === undefined && (userChoice !== true || offered.length === 0)) {
48
+ throw new Error(`${where} table.grouping has no field. Set field, or userChoice: true with at least one entry in fields.`);
49
+ }
50
+ if (fields !== undefined && userChoice !== true) {
51
+ throw new Error(`${where} table.grouping.fields needs userChoice: true, or the user could never pick them.`);
52
+ }
53
+ }
54
+ function validateGroupingShape(where, grouping, columnFields) {
55
+ if (!isPlainObject(grouping)) {
56
+ throw new Error(`${where} table.grouping must be an object like { field: "status" }.`);
57
+ }
58
+ rejectUnknownKeys(where, "table.grouping", grouping, LIST_TABLE_GROUPING_KEYS);
59
+ validateGroupingValueTypes(where, grouping);
60
+ validateGroupingFieldChoice(where, grouping);
61
+ for (const name of groupingFieldsOf(grouping)) {
62
+ requireScreenColumn(where, "table.grouping field", name, columnFields);
63
+ }
64
+ }
65
+ function validateTotalsShape(where, totals, columnFields) {
66
+ if (!Array.isArray(totals) || totals.length === 0) {
67
+ throw new Error(`${where} table.totals must be a non-empty array like [{ field: "amount", kind: "sum" }].`);
68
+ }
69
+ for (const [i, entry] of totals.entries()) {
70
+ if (!isPlainObject(entry))
71
+ throw new Error(`${where} table.totals[${i}] must be an object.`);
72
+ rejectUnknownKeys(where, `table.totals[${i}]`, entry, LIST_TABLE_TOTAL_KEYS);
73
+ if (typeof entry["field"] !== "string") {
74
+ throw new Error(`${where} table.totals[${i}].field must be a field name.`);
75
+ }
76
+ if (!isOneOf(LIST_AGGREGATE_MEASURE_KINDS, entry["kind"])) {
77
+ throw new Error(`${where} table.totals[${i}].kind must be one of ${LIST_AGGREGATE_MEASURE_KINDS.join(", ")}.`);
78
+ }
79
+ requireScreenColumn(where, `table.totals[${i}].field`, entry["field"], columnFields);
80
+ }
81
+ }
82
+ export function groupingFieldsOf(grouping) {
83
+ const named = typeof grouping.field === "string" ? [grouping.field] : [];
84
+ const offered = isStringArray(grouping.fields) ? grouping.fields : [];
85
+ return [...new Set([...named, ...offered])];
86
+ }
87
+ /** Structure and column membership; field types are checked where the entity is known. */
88
+ export function validateListTableAggregateShape(where, table, columns) {
89
+ const columnFields = new Set(columns.map((col) => normalizeListColumn(col).field));
90
+ if (table["grouping"] !== undefined)
91
+ validateGroupingShape(where, table["grouping"], columnFields);
92
+ if (table["totals"] !== undefined)
93
+ validateTotalsShape(where, table["totals"], columnFields);
94
+ }
95
+ function rejectSecret(where, path, field, info) {
96
+ // skip: only secret fields are rejected here
97
+ if (!info.secret)
98
+ return;
99
+ throw new Error(`${where} ${path} "${field}" is encrypted, personal or secret and cannot be grouped or summed.`);
100
+ }
101
+ /**
102
+ * `lookup` answers undefined for a field it does not know. With `strict` (an entity
103
+ * stands behind the list) that is an error; otherwise the field is left to the server.
104
+ */
105
+ export function validateListTableAggregateFieldTypes(where, table, lookup, strict) {
106
+ const resolve = (path, field) => {
107
+ const info = lookup(field);
108
+ if (info === undefined && strict) {
109
+ throw new Error(`${where} ${path} "${field}" is not a field of the entity behind this list.`);
110
+ }
111
+ return info;
112
+ };
113
+ for (const field of groupingFieldsOf(table.grouping ?? {})) {
114
+ const info = resolve("table.grouping field", field);
115
+ if (info === undefined)
116
+ continue;
117
+ rejectSecret(where, "table.grouping field", field, info);
118
+ if (!isListAggregateGroupable(info.type, info.multiple)) {
119
+ throw new Error(`${where} table.grouping field "${field}" (${info.type}) cannot be grouped by.`);
120
+ }
121
+ }
122
+ for (const [i, total] of (table.totals ?? []).entries()) {
123
+ const path = `table.totals[${i}]`;
124
+ const info = resolve(`${path}.field`, total.field);
125
+ if (info === undefined)
126
+ continue;
127
+ rejectSecret(where, `${path}.field`, total.field, info);
128
+ if (!isListAggregateMeasureSupported(total.kind, info.type)) {
129
+ throw new Error(`${where} ${path}: "${total.kind}" is not supported on ${info.type} field "${total.field}". ` +
130
+ `sum and avg need number, decimal, money or bigInt; min and max also take date and timestamp.`);
131
+ }
132
+ }
133
+ }
134
+ export function entityAggregateFieldLookup(entity) {
135
+ return (field) => {
136
+ const def = Object.hasOwn(entity.fields, field) ? entity.fields[field] : undefined;
137
+ if (def === undefined)
138
+ return undefined;
139
+ return {
140
+ type: def.type,
141
+ multiple: def.type === "reference" && def.multiple === true,
142
+ secret: holdsCiphertextOrSecret(entity, field),
143
+ };
144
+ };
145
+ }
@@ -0,0 +1,11 @@
1
+ import type { QueryHandlerDef } from "@cosmicdrift/kumiko-types/handlers";
2
+ import type { FeatureDefinition } from "../types/index.ts";
3
+ import type { ListColumnSpec, ListTableOptions } from "../types/screen.ts";
4
+ export declare function validateListTableAggregateQuery(args: {
5
+ readonly prefix: string;
6
+ readonly query: string;
7
+ readonly table?: ListTableOptions | undefined;
8
+ readonly columns: readonly ListColumnSpec[];
9
+ readonly handler: QueryHandlerDef | undefined;
10
+ readonly featureMap: ReadonlyMap<string, FeatureDefinition>;
11
+ }): void;
@@ -0,0 +1,31 @@
1
+ import { resolveEntityBehindListQuery } from "../entity-list-searchability.js";
2
+ import { normalizeListColumn } from "../screen-helpers.js";
3
+ import { entityAggregateFieldLookup, validateListTableAggregateFieldTypes, } from "./list-table-aggregate-options.js";
4
+ import { findEntity } from "./parent-ref.js";
5
+ import { getZodObjectShape } from "./zod-shape.js";
6
+ function columnValueTypeLookup(columns) {
7
+ const valueTypes = new Map(columns
8
+ .map(normalizeListColumn)
9
+ .flatMap((col) => (col.valueType === undefined ? [] : [[col.field, col.valueType]])));
10
+ return (field) => {
11
+ const type = valueTypes.get(field);
12
+ return type === undefined ? undefined : { type, multiple: false, secret: false };
13
+ };
14
+ }
15
+ // Same pattern as searchable vs search: grouping and totals send `aggregate`,
16
+ // which a query without it in its Zod schema would reject on every load.
17
+ export function validateListTableAggregateQuery(args) {
18
+ const { prefix, query, table, handler } = args;
19
+ // skip: neither grouping nor totals declared, nothing travels via aggregate
20
+ if (table?.grouping === undefined && table?.totals === undefined)
21
+ return;
22
+ const shape = getZodObjectShape(handler?.schema);
23
+ if (shape === undefined || !("aggregate" in shape)) {
24
+ throw new Error(`${prefix}: table.grouping/table.totals need query "${query}" to accept "aggregate" — ` +
25
+ `reuse entityListSchema (or listAggregatePayloadSchema) in the handler's schema and answer it ` +
26
+ `with answerListAggregate, or remove grouping and totals.`);
27
+ }
28
+ const entity = resolveEntityBehindListQuery(query, handler, (name) => findEntity(args.featureMap, name));
29
+ const lookup = entity === undefined ? columnValueTypeLookup(args.columns) : entityAggregateFieldLookup(entity);
30
+ validateListTableAggregateFieldTypes(prefix, table, lookup, entity !== undefined);
31
+ }
@@ -0,0 +1 @@
1
+ export declare function validateExportOptions(where: string, value: unknown, allowed: boolean): void;
@@ -0,0 +1,27 @@
1
+ import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
2
+ import { LIST_TABLE_EXPORT_KEYS, MAX_EXPORT_MAX_ROWS } from "../types/screen.js";
3
+ import { rejectUnknownKeys } from "./list-table-reject-unknown-keys.js";
4
+ export function validateExportOptions(where, value, allowed) {
5
+ if (!allowed) {
6
+ throw new Error(`${where} table.export is only available on entityList and projectionList screens. Remove it here.`);
7
+ }
8
+ if (!isPlainObject(value)) {
9
+ throw new Error(`${where} table.export must be an object like { xlsx: true, maxRows: 5000 }.`);
10
+ }
11
+ rejectUnknownKeys(where, "table.export", value, LIST_TABLE_EXPORT_KEYS);
12
+ if (value["xlsx"] !== true) {
13
+ throw new Error(`${where} table.export.xlsx must be true (the only export format).`);
14
+ }
15
+ if (value["maxRows"] !== undefined)
16
+ validateMaxRows(where, value["maxRows"]);
17
+ }
18
+ function validateMaxRows(where, maxRows) {
19
+ if (typeof maxRows !== "number" || !Number.isInteger(maxRows) || maxRows < 1) {
20
+ throw new Error(`${where} table.export.maxRows is ${JSON.stringify(maxRows)} — must be an integer >= 1. ` +
21
+ `Set a positive row limit or remove maxRows to use the default.`);
22
+ }
23
+ if (maxRows > MAX_EXPORT_MAX_ROWS) {
24
+ throw new Error(`${where} table.export.maxRows is ${maxRows} — must be at most ${MAX_EXPORT_MAX_ROWS} ` +
25
+ `(the workbook is built in memory). Lower maxRows.`);
26
+ }
27
+ }
@@ -0,0 +1,3 @@
1
+ import { type ListColumnSpec } from "../types/screen.ts";
2
+ /** `where` is the full message prefix, e.g. `[Feature x] Screen "y" (entityList)`. */
3
+ export declare function validateListTableOptions(where: string, table: unknown, columns: readonly ListColumnSpec[], exportAllowed?: boolean): void;
@@ -0,0 +1,77 @@
1
+ import { isOneOf, isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
2
+ import { normalizeListColumn } from "../screen-helpers.js";
3
+ import { LIST_TABLE_DENSITIES, LIST_TABLE_DENSITY_KEYS, LIST_TABLE_OPTION_KEYS, } from "../types/screen.js";
4
+ import { validateColumnLayout } from "./list-column-layout.js";
5
+ import { validateListTableAggregateShape } from "./list-table-aggregate-options.js";
6
+ import { validateExportOptions } from "./list-table-export-options.js";
7
+ import { rejectUnknownKeys } from "./list-table-reject-unknown-keys.js";
8
+ const BOOLEAN_OPTION_KEYS = [
9
+ "rememberState",
10
+ "resetAll",
11
+ "columnPicker",
12
+ "pinning",
13
+ "resizing",
14
+ "keyboardNavigation",
15
+ ];
16
+ function validateDensity(where, density) {
17
+ if (!isPlainObject(density)) {
18
+ throw new Error(`${where} table.density must be an object like { default: "compact", userChoice: true }.`);
19
+ }
20
+ rejectUnknownKeys(where, "table.density", density, LIST_TABLE_DENSITY_KEYS);
21
+ if (Object.keys(density).length === 0) {
22
+ throw new Error(`${where} table.density is empty. Set default (${LIST_TABLE_DENSITIES.join(" | ")}) ` +
23
+ `and/or userChoice, or remove table.density.`);
24
+ }
25
+ if (density["default"] !== undefined && !isOneOf(LIST_TABLE_DENSITIES, density["default"])) {
26
+ throw new Error(`${where} table.density.default is ${JSON.stringify(density["default"])} — ` +
27
+ `must be one of ${LIST_TABLE_DENSITIES.map((d) => `"${d}"`).join(", ")}.`);
28
+ }
29
+ if (density["userChoice"] !== undefined && typeof density["userChoice"] !== "boolean") {
30
+ throw new Error(`${where} table.density.userChoice must be a boolean.`);
31
+ }
32
+ }
33
+ function validateHiddenColumns(where, columnPickerOn, columns) {
34
+ const normalized = columns.map(normalizeListColumn);
35
+ for (const col of normalized) {
36
+ if (col.hidden !== undefined && typeof col.hidden !== "boolean") {
37
+ throw new Error(`${where} column "${col.field}" has a non-boolean "hidden".`);
38
+ }
39
+ }
40
+ const hidden = normalized.filter((col) => col.hidden === true);
41
+ // skip: no hidden columns, nothing to validate
42
+ if (hidden.length === 0)
43
+ return;
44
+ if (!columnPickerOn) {
45
+ throw new Error(`${where} column "${hidden[0]?.field}" is hidden but table.columnPicker is not enabled, ` +
46
+ `so the user could never show it. Set table: { columnPicker: true } or remove "hidden".`);
47
+ }
48
+ if (hidden.length === normalized.length) {
49
+ throw new Error(`${where} hides every column. At least one column must start visible — remove "hidden" from one.`);
50
+ }
51
+ }
52
+ /** `where` is the full message prefix, e.g. `[Feature x] Screen "y" (entityList)`. */
53
+ export function validateListTableOptions(where, table, columns, exportAllowed = false) {
54
+ if (table === undefined) {
55
+ validateHiddenColumns(where, false, columns);
56
+ validateColumnLayout(where, { pinning: false, resizing: false }, columns);
57
+ // skip: no table block: nothing else to check
58
+ return;
59
+ }
60
+ if (!isPlainObject(table)) {
61
+ throw new Error(`${where} table must be an object like { rememberState: true }. ` +
62
+ `Allowed keys: ${LIST_TABLE_OPTION_KEYS.join(", ")}.`);
63
+ }
64
+ rejectUnknownKeys(where, "table", table, LIST_TABLE_OPTION_KEYS);
65
+ for (const key of BOOLEAN_OPTION_KEYS) {
66
+ if (table[key] !== undefined && typeof table[key] !== "boolean") {
67
+ throw new Error(`${where} table.${key} must be a boolean, got ${typeof table[key]}.`);
68
+ }
69
+ }
70
+ if (table["density"] !== undefined)
71
+ validateDensity(where, table["density"]);
72
+ if (table["export"] !== undefined)
73
+ validateExportOptions(where, table["export"], exportAllowed);
74
+ validateListTableAggregateShape(where, table, columns);
75
+ validateHiddenColumns(where, table["columnPicker"] === true, columns);
76
+ validateColumnLayout(where, { pinning: table["pinning"] === true, resizing: table["resizing"] === true }, columns);
77
+ }
@@ -0,0 +1 @@
1
+ export declare function rejectUnknownKeys(where: string, block: string, value: Record<string, unknown>, allowed: readonly string[]): void;
@@ -0,0 +1,7 @@
1
+ export function rejectUnknownKeys(where, block, value, allowed) {
2
+ const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
3
+ if (unknown.length > 0) {
4
+ throw new Error(`${where} ${block} has unknown key(s) ${unknown.map((k) => `"${k}"`).join(", ")}. ` +
5
+ `Allowed keys: ${allowed.join(", ")}.`);
6
+ }
7
+ }
@@ -1,4 +1,6 @@
1
- import type { FeatureDefinition, NavDefinition, WorkspaceDefinition } from "../types/index.ts";
1
+ import type { NavDefinition } from "@cosmicdrift/kumiko-types/nav";
2
+ import type { WorkspaceDefinition } from "@cosmicdrift/kumiko-types/workspace";
3
+ import type { FeatureDefinition } from "../types/index.ts";
2
4
  export declare function collectWriteHandlerQns(features: readonly FeatureDefinition[]): Set<string>;
3
5
  export declare function collectNavQns(features: readonly FeatureDefinition[]): Map<string, NavDefinition & {
4
6
  readonly featureName: string;
@@ -1,9 +1,9 @@
1
1
  // Nav validation + collectKnownRoles (role synthesis for ownership
2
2
  // validation in index.ts — thematically adjacent to ownership.ts, kept
3
3
  // here since this is a structural move, not a semantic reorg).
4
+ import { isOpenToAllGranted } from "@cosmicdrift/kumiko-types/handlers";
4
5
  import { createFallbackLogger } from "../../logging/utils.js";
5
6
  import { qualifyEntityName } from "../qualified-name.js";
6
- import { isOpenToAllGranted } from "../types/index.js";
7
7
  const log = createFallbackLogger("kumiko:boot");
8
8
  export function collectWriteHandlerQns(features) {
9
9
  const set = new Set();
@@ -1,5 +1,6 @@
1
+ import type { ClaimKeyDefinition } from "@cosmicdrift/kumiko-types/handlers";
1
2
  import { type OwnershipMap, type WhereRule } from "../ownership.ts";
2
- import type { ClaimKeyDefinition, FeatureDefinition } from "../types/index.ts";
3
+ import type { FeatureDefinition } from "../types/index.ts";
3
4
  export type WhereRuleProbe = {
4
5
  readonly table: unknown;
5
6
  readonly tableName: string;
@@ -1,3 +1,4 @@
1
- import type { EntityDefinition, FeatureDefinition } from "../types/index.ts";
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
+ import type { FeatureDefinition } from "../types/index.ts";
2
3
  export declare function findEntity(featureMap: ReadonlyMap<string, FeatureDefinition>, entityName: string): EntityDefinition | undefined;
3
4
  export declare function validateParentRefs(feature: FeatureDefinition, featureMap: ReadonlyMap<string, FeatureDefinition>): void;
@@ -1,4 +1,5 @@
1
- import { type FeatureDefinition, type QueryHandlerDef } from "../types/index.ts";
1
+ import type { QueryHandlerDef } from "@cosmicdrift/kumiko-types/handlers";
2
+ import type { FeatureDefinition } from "../types/index.ts";
2
3
  export declare function buildQueryHandlerMap(features: readonly FeatureDefinition[]): ReadonlyMap<string, QueryHandlerDef>;
3
4
  export declare function validateProjectionListScreens(features: readonly FeatureDefinition[]): void;
4
5
  export declare function validateRelatedListSectionQueries(features: readonly FeatureDefinition[]): void;