@cosmicdrift/kumiko-framework 0.387.0 → 0.388.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 (240) hide show
  1. package/AGENTS.md +6 -1
  2. package/agents/examples/anonymous-access.md +1 -1
  3. package/agents/examples/apex-landing.md +204 -0
  4. package/agents/examples/api-worker-split.md +64 -0
  5. package/agents/examples/app-config.md +14 -0
  6. package/agents/examples/auth-mfa.md +115 -0
  7. package/agents/examples/env-composition.md +28 -1
  8. package/agents/examples/legal-pages.md +1 -1
  9. package/agents/examples/prod-boot-options.md +16 -0
  10. package/agents/examples/rate-limiting.md +48 -0
  11. package/agents/examples/record-detail-layout.md +692 -0
  12. package/agents/examples/seed-migration.md +212 -0
  13. package/agents/examples/wizard-form.md +941 -0
  14. package/agents/examples/writeform-section.md +548 -0
  15. package/agents/features.md +19 -2
  16. package/agents/widgets.md +1 -0
  17. package/dist/api/client-error-route.js +8 -2
  18. package/dist/api/index.d.ts +3 -1
  19. package/dist/api/index.js +3 -1
  20. package/dist/api/request-context.d.ts +1 -1
  21. package/dist/api/request-context.js +1 -1
  22. package/dist/api/server-boot-checks.d.ts +10 -0
  23. package/dist/api/server-boot-checks.js +157 -0
  24. package/dist/api/server-event-dispatcher.d.ts +26 -0
  25. package/dist/api/server-event-dispatcher.js +208 -0
  26. package/dist/api/server-extra-routes.d.ts +11 -0
  27. package/dist/api/server-extra-routes.js +203 -0
  28. package/dist/api/server-middleware.d.ts +20 -0
  29. package/dist/api/server-middleware.js +211 -0
  30. package/dist/api/server-routes.d.ts +19 -0
  31. package/dist/api/server-routes.js +293 -0
  32. package/dist/api/server-websocket-routes.d.ts +4 -0
  33. package/dist/api/server-websocket-routes.js +108 -0
  34. package/dist/api/server-wiring.d.ts +32 -0
  35. package/dist/api/server-wiring.js +236 -0
  36. package/dist/api/server.d.ts +10 -15
  37. package/dist/api/server.js +48 -1251
  38. package/dist/api/session-cookies.js +4 -4
  39. package/dist/api/sse-route.js +16 -12
  40. package/dist/crypto/owner-transition-rekey.d.ts +5 -1
  41. package/dist/crypto/owner-transition-rekey.js +1 -1
  42. package/dist/crypto/pii-field-encryption.d.ts +5 -1
  43. package/dist/crypto/pii-field-encryption.js +3 -1
  44. package/dist/db/aggregate-sql.d.ts +21 -0
  45. package/dist/db/aggregate-sql.js +155 -0
  46. package/dist/db/closed-connection.d.ts +9 -0
  47. package/dist/db/closed-connection.js +95 -0
  48. package/dist/db/dialect.js +1 -1
  49. package/dist/db/distinct-on.d.ts +1 -1
  50. package/dist/db/driver-row-coercion.d.ts +2 -0
  51. package/dist/db/driver-row-coercion.js +186 -0
  52. package/dist/db/driver-value-preparation.d.ts +16 -0
  53. package/dist/db/driver-value-preparation.js +99 -0
  54. package/dist/db/entity-field-encryption.d.ts +1 -0
  55. package/dist/db/entity-field-encryption.js +1 -1
  56. package/dist/db/entity-table-meta.js +103 -110
  57. package/dist/db/event-store-executor-context.d.ts +2 -1
  58. package/dist/db/event-store-executor-read-aggregate.d.ts +8 -0
  59. package/dist/db/event-store-executor-read-aggregate.js +112 -0
  60. package/dist/db/event-store-executor-read-filter.d.ts +31 -0
  61. package/dist/db/event-store-executor-read-filter.js +203 -0
  62. package/dist/db/event-store-executor-read-paging.d.ts +14 -0
  63. package/dist/db/event-store-executor-read-paging.js +99 -0
  64. package/dist/db/event-store-executor-read-rows.d.ts +6 -0
  65. package/dist/db/event-store-executor-read-rows.js +32 -0
  66. package/dist/db/event-store-executor-read-search.d.ts +28 -0
  67. package/dist/db/event-store-executor-read-search.js +221 -0
  68. package/dist/db/event-store-executor-read-sort.d.ts +41 -0
  69. package/dist/db/event-store-executor-read-sort.js +130 -0
  70. package/dist/db/event-store-executor-read-where.d.ts +24 -0
  71. package/dist/db/event-store-executor-read-where.js +81 -0
  72. package/dist/db/event-store-executor-read.d.ts +2 -9
  73. package/dist/db/event-store-executor-read.js +48 -701
  74. package/dist/db/event-store-executor-write-steps.d.ts +20 -0
  75. package/dist/db/event-store-executor-write-steps.js +100 -0
  76. package/dist/db/event-store-executor-write.js +395 -499
  77. package/dist/db/index.d.ts +6 -2
  78. package/dist/db/index.js +5 -1
  79. package/dist/db/list-aggregate-labels.d.ts +14 -0
  80. package/dist/db/list-aggregate-labels.js +26 -0
  81. package/dist/db/migrate-generator.js +71 -86
  82. package/dist/db/migrate-runner.js +4 -1
  83. package/dist/db/query.d.ts +2 -15
  84. package/dist/db/query.js +8 -761
  85. package/dist/db/reference-data.js +6 -1
  86. package/dist/db/table-builder.js +113 -166
  87. package/dist/db/table-info.d.ts +10 -0
  88. package/dist/db/table-info.js +45 -0
  89. package/dist/db/temporal-value-guards.d.ts +6 -0
  90. package/dist/db/temporal-value-guards.js +15 -0
  91. package/dist/db/tenant-db-runner.d.ts +1 -0
  92. package/dist/db/tenant-db-runner.js +3 -0
  93. package/dist/db/tenant-db.js +39 -9
  94. package/dist/db/where-clause.d.ts +6 -0
  95. package/dist/db/where-clause.js +236 -0
  96. package/dist/derivatives/delete-stored-file.js +2 -1
  97. package/dist/engine/boot-validator/boot-check.js +1 -1
  98. package/dist/engine/boot-validator/detail-screens.js +2 -2
  99. package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
  100. package/dist/engine/boot-validator/entity-handler.js +17 -0
  101. package/dist/engine/boot-validator/form-derivations.js +35 -1
  102. package/dist/engine/boot-validator/i18n-keys.js +5 -3
  103. package/dist/engine/boot-validator/index.js +2 -0
  104. package/dist/engine/boot-validator/pii-retention.js +233 -155
  105. package/dist/engine/boot-validator/screens-actions.d.ts +1 -0
  106. package/dist/engine/boot-validator/screens-actions.js +8 -1
  107. package/dist/engine/boot-validator/screens-dashboard.js +2 -5
  108. package/dist/engine/boot-validator/screens-forms.js +2 -6
  109. package/dist/engine/boot-validator/screens-kind-config-edit.d.ts +3 -0
  110. package/dist/engine/boot-validator/screens-kind-config-edit.js +88 -0
  111. package/dist/engine/boot-validator/screens-kind-entity-edit.d.ts +3 -0
  112. package/dist/engine/boot-validator/screens-kind-entity-edit.js +55 -0
  113. package/dist/engine/boot-validator/screens-kind-entity-list.d.ts +3 -0
  114. package/dist/engine/boot-validator/screens-kind-entity-list.js +228 -0
  115. package/dist/engine/boot-validator/screens-kind-projection-detail.d.ts +3 -0
  116. package/dist/engine/boot-validator/screens-kind-projection-detail.js +235 -0
  117. package/dist/engine/boot-validator/screens-kind-projection-list.d.ts +3 -0
  118. package/dist/engine/boot-validator/screens-kind-projection-list.js +52 -0
  119. package/dist/engine/boot-validator/screens-kind-secret-mint.d.ts +3 -0
  120. package/dist/engine/boot-validator/screens-kind-secret-mint.js +28 -0
  121. package/dist/engine/boot-validator/screens-kind-shared.d.ts +37 -0
  122. package/dist/engine/boot-validator/screens-kind-shared.js +142 -0
  123. package/dist/engine/boot-validator/screens-lists.d.ts +2 -1
  124. package/dist/engine/boot-validator/screens-lists.js +12 -9
  125. package/dist/engine/boot-validator/screens.d.ts +0 -2
  126. package/dist/engine/boot-validator/screens.js +99 -860
  127. package/dist/engine/build-app-schema.js +56 -96
  128. package/dist/engine/define-feature.js +9 -2
  129. package/dist/engine/define-handler.js +1 -0
  130. package/dist/engine/entity-handlers.d.ts +13 -0
  131. package/dist/engine/entity-handlers.js +10 -21
  132. package/dist/engine/entity-list-runtime-options.d.ts +8 -0
  133. package/dist/engine/entity-list-runtime-options.js +18 -0
  134. package/dist/engine/feature-ast/extractors/handlers.js +1 -0
  135. package/dist/engine/feature-ast/extractors/round2.js +25 -6
  136. package/dist/engine/feature-ast/patch.js +4 -182
  137. package/dist/engine/feature-ast/pattern-change-schema.d.ts +3 -0
  138. package/dist/engine/feature-ast/pattern-change-schema.js +1 -0
  139. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +7 -0
  140. package/dist/engine/feature-ast/pattern-id-matchers.js +210 -0
  141. package/dist/engine/feature-ast/patterns.d.ts +9 -0
  142. package/dist/engine/feature-ast/patterns.js +43 -51
  143. package/dist/engine/feature-ast/render.js +48 -87
  144. package/dist/engine/feature-entity-handlers.js +3 -0
  145. package/dist/engine/form-derivations.js +18 -7
  146. package/dist/engine/handler-field-references.js +1 -1
  147. package/dist/engine/project-app-schema-for-roles.d.ts +2 -0
  148. package/dist/engine/project-app-schema-for-roles.js +6 -4
  149. package/dist/engine/registry-ingest.js +1 -1
  150. package/dist/engine/schema-builder.js +228 -212
  151. package/dist/engine/screen-helpers.js +1 -1
  152. package/dist/engine/screen-kind.d.ts +7 -0
  153. package/dist/engine/screen-kind.js +1 -0
  154. package/dist/engine/strip-disabled-features-from-app-schema.js +51 -14
  155. package/dist/engine/validate-projection-allowlist.js +2 -1
  156. package/dist/entrypoint/index.d.ts +4 -1
  157. package/dist/entrypoint/index.js +7 -1
  158. package/dist/errors/docs-url.d.ts +1 -1
  159. package/dist/errors/docs-url.js +22 -2
  160. package/dist/es-ops/context.js +1 -1
  161. package/dist/event-store/admin-api.js +1 -1
  162. package/dist/event-store/event-store.js +10 -4
  163. package/dist/files/bind-pending-file-refs.js +3 -3
  164. package/dist/files/create-file-ref-from-bytes.js +4 -1
  165. package/dist/files/file-handle.js +2 -3
  166. package/dist/files/file-routes.js +11 -8
  167. package/dist/files/resolve-content-type.js +43 -0
  168. package/dist/files/upload-ledger.js +7 -0
  169. package/dist/i18n/required-surface-keys.js +182 -206
  170. package/dist/internal/stack-support.d.ts +2 -1
  171. package/dist/internal/stack-support.js +1 -1
  172. package/dist/jobs/job-runner-context.d.ts +32 -0
  173. package/dist/jobs/job-runner-context.js +305 -0
  174. package/dist/jobs/job-runner-execution.d.ts +7 -0
  175. package/dist/jobs/job-runner-execution.js +160 -0
  176. package/dist/jobs/job-runner-gates.d.ts +19 -0
  177. package/dist/jobs/job-runner-gates.js +198 -0
  178. package/dist/jobs/job-runner-helpers.d.ts +17 -3
  179. package/dist/jobs/job-runner-helpers.js +61 -2
  180. package/dist/jobs/job-runner-scope.d.ts +44 -0
  181. package/dist/jobs/job-runner-scope.js +102 -0
  182. package/dist/jobs/job-runner-types.d.ts +12 -0
  183. package/dist/jobs/job-runner.d.ts +0 -1
  184. package/dist/jobs/job-runner.js +47 -657
  185. package/dist/observability/escape-hatch-report.d.ts +3 -0
  186. package/dist/observability/escape-hatch-report.js +12 -1
  187. package/dist/pipeline/cascade-handler.js +165 -138
  188. package/dist/pipeline/dispatch-query.js +10 -3
  189. package/dist/pipeline/dispatch-shared.d.ts +13 -3
  190. package/dist/pipeline/dispatch-shared.js +58 -710
  191. package/dist/pipeline/dispatch-write.js +296 -189
  192. package/dist/pipeline/event-dispatcher-admin.js +2 -1
  193. package/dist/pipeline/event-dispatcher-delivery.js +3 -5
  194. package/dist/pipeline/handler-context-auth.d.ts +9 -0
  195. package/dist/pipeline/handler-context-auth.js +54 -0
  196. package/dist/pipeline/handler-context-config.d.ts +14 -0
  197. package/dist/pipeline/handler-context-config.js +113 -0
  198. package/dist/pipeline/handler-context-db.d.ts +24 -0
  199. package/dist/pipeline/handler-context-db.js +149 -0
  200. package/dist/pipeline/handler-context-dispatch.d.ts +21 -0
  201. package/dist/pipeline/handler-context-dispatch.js +89 -0
  202. package/dist/pipeline/handler-context-events.d.ts +43 -0
  203. package/dist/pipeline/handler-context-events.js +237 -0
  204. package/dist/pipeline/handler-context-notify.d.ts +12 -0
  205. package/dist/pipeline/handler-context-notify.js +55 -0
  206. package/dist/pipeline/handler-context-observability.d.ts +7 -0
  207. package/dist/pipeline/handler-context-observability.js +21 -0
  208. package/dist/pipeline/handler-context-scope.d.ts +48 -0
  209. package/dist/pipeline/handler-context-scope.js +88 -0
  210. package/dist/pipeline/notify-scope.js +12 -1
  211. package/dist/pipeline/pre-handler-gates.js +20 -4
  212. package/dist/pipeline/pre-transaction-reservations.d.ts +1 -0
  213. package/dist/pipeline/pre-transaction-reservations.js +9 -3
  214. package/dist/pipeline/projection-rebuild.js +2 -1
  215. package/dist/schema-cli/apply-command.d.ts +2 -0
  216. package/dist/schema-cli/apply-command.js +97 -0
  217. package/dist/schema-cli/baseline-command.d.ts +2 -0
  218. package/dist/schema-cli/baseline-command.js +33 -0
  219. package/dist/schema-cli/generate-command.d.ts +2 -0
  220. package/dist/schema-cli/generate-command.js +90 -0
  221. package/dist/schema-cli/shared.d.ts +39 -0
  222. package/dist/schema-cli/shared.js +95 -0
  223. package/dist/schema-cli/status-command.d.ts +2 -0
  224. package/dist/schema-cli/status-command.js +73 -0
  225. package/dist/schema-cli/validate-boot-input.d.ts +5 -0
  226. package/dist/schema-cli/validate-boot-input.js +130 -0
  227. package/dist/schema-cli/validate-command.d.ts +2 -0
  228. package/dist/schema-cli/validate-command.js +130 -0
  229. package/dist/schema-cli.d.ts +2 -18
  230. package/dist/schema-cli.js +47 -604
  231. package/dist/search/meilisearch-adapter.js +2 -1
  232. package/dist/upgrade-cli.js +149 -121
  233. package/package.json +4 -4
  234. package/src/changes.json +310 -0
  235. package/src/scripts/codemod/feature-layout.ts +10 -2
  236. package/src/scripts/codemod/object-form.ts +41 -4
  237. package/src/scripts/codemod/package-merge.ts +58 -8
  238. package/src/scripts/codemod/pii-personal-migration.ts +175 -145
  239. package/src/scripts/codemod/testing-injection.ts +122 -42
  240. package/src/scripts/codemod/testing-move.ts +29 -7
@@ -221,222 +221,198 @@ function pushExpandableRowKeys(out, section) {
221
221
  pushRowActionKeys(out, section.emptyState.action);
222
222
  }
223
223
  }
224
- export function requiredKeysFromScreen(featureName, screen, options = {}) {
225
- const { treatDotFormAsKey = false } = options;
226
- const out = new Set();
227
- pushKey(out, screenTitleKey(screen.id));
228
- switch (screen.type) {
229
- case "entityList": {
230
- const list = screen;
231
- for (const col of list.columns) {
232
- const normalized = normalizeListColumn(col);
233
- if (normalized.label !== undefined) {
234
- pushKey(out, normalized.label);
235
- }
236
- else {
237
- out.add(fieldLabelKey(featureName, list.entity, normalized.field));
238
- }
239
- }
240
- pushKey(out, list.createLabel);
241
- pushKey(out, list.searchPlaceholder);
242
- pushKey(out, list.description);
243
- pushListEmptyStateKeys(out, list.emptyState);
244
- for (const action of list.rowActions ?? [])
245
- pushRowActionKeys(out, action);
246
- for (const action of list.toolbarActions ?? [])
247
- pushToolbarActionKeys(out, action);
248
- if (list.expandableRow !== undefined)
249
- pushExpandableRowKeys(out, list.expandableRow);
250
- break;
224
+ function pushFieldLabelOrOverrideKey(ctx, labelEntity, fieldName, fieldLabels, treatAsKey = false) {
225
+ const override = fieldLabels?.[fieldName];
226
+ if (override !== undefined)
227
+ pushKey(ctx.out, override, treatAsKey);
228
+ else
229
+ ctx.out.add(fieldLabelKey(ctx.featureName, labelEntity, fieldName));
230
+ }
231
+ function pushListChromeKeys(out, list) {
232
+ pushKey(out, list.createLabel);
233
+ pushKey(out, list.searchPlaceholder);
234
+ pushKey(out, list.description);
235
+ pushListEmptyStateKeys(out, list.emptyState);
236
+ for (const action of list.rowActions ?? [])
237
+ pushRowActionKeys(out, action);
238
+ for (const action of list.toolbarActions ?? [])
239
+ pushToolbarActionKeys(out, action);
240
+ }
241
+ function collectEntityListKeys(ctx, list) {
242
+ for (const col of list.columns) {
243
+ const normalized = normalizeListColumn(col);
244
+ if (normalized.label !== undefined) {
245
+ pushKey(ctx.out, normalized.label);
251
246
  }
252
- case "projectionList": {
253
- const list = screen;
254
- // No entity means there are no field-label fallbacks; only explicit column labels are
255
- // collected.
256
- for (const col of list.columns) {
257
- const normalized = normalizeListColumn(col);
258
- if (normalized.label !== undefined)
259
- pushKey(out, normalized.label);
260
- }
261
- pushKey(out, list.createLabel);
262
- pushKey(out, list.searchPlaceholder);
263
- pushKey(out, list.description);
264
- pushListEmptyStateKeys(out, list.emptyState);
265
- for (const action of list.rowActions ?? [])
266
- pushRowActionKeys(out, action);
267
- for (const action of list.toolbarActions ?? [])
268
- pushToolbarActionKeys(out, action);
269
- break;
247
+ else {
248
+ ctx.out.add(fieldLabelKey(ctx.featureName, list.entity, normalized.field));
270
249
  }
271
- case "dashboard": {
272
- pushDashboardScreenKeys(out, screen);
273
- break;
250
+ }
251
+ pushListChromeKeys(ctx.out, list);
252
+ if (list.expandableRow !== undefined)
253
+ pushExpandableRowKeys(ctx.out, list.expandableRow);
254
+ }
255
+ function collectProjectionListKeys(ctx, list) {
256
+ // No entity means there are no field-label fallbacks; only explicit column labels are
257
+ // collected.
258
+ for (const col of list.columns) {
259
+ const normalized = normalizeListColumn(col);
260
+ if (normalized.label !== undefined)
261
+ pushKey(ctx.out, normalized.label);
262
+ }
263
+ pushListChromeKeys(ctx.out, list);
264
+ }
265
+ function pushEditLayoutSectionKeys(ctx, sections, labelEntity, fieldLabels) {
266
+ for (const section of sections) {
267
+ if (isExtensionEditSection(section)) {
268
+ pushKey(ctx.out, section.title);
269
+ continue;
274
270
  }
275
- case "entityEdit": {
276
- const edit = screen;
277
- pushKey(out, edit.submitLabel);
278
- pushKey(out, edit.titleTemplate);
279
- for (const section of edit.layout.sections) {
280
- if (isExtensionEditSection(section)) {
281
- pushKey(out, section.title);
282
- continue;
283
- }
284
- if (section.kind === "relatedList")
285
- continue; // rejected at boot, unreachable here
286
- pushSectionTitles(out, section);
287
- for (const f of sectionFieldSpecs(section)) {
288
- pushEditFieldTextKeys(out, f);
289
- const fieldName = editFieldName(f);
290
- const override = edit.fieldLabels?.[fieldName];
291
- if (override !== undefined)
292
- pushKey(out, override);
293
- else
294
- out.add(fieldLabelKey(featureName, edit.entity, fieldName));
295
- }
296
- }
297
- break;
271
+ if (section.kind === "relatedList")
272
+ continue; // rejected at boot, unreachable here
273
+ pushSectionTitles(ctx.out, section);
274
+ for (const f of sectionFieldSpecs(section)) {
275
+ pushEditFieldTextKeys(ctx.out, f);
276
+ pushFieldLabelOrOverrideKey(ctx, labelEntity, editFieldName(f), fieldLabels);
298
277
  }
299
- case "actionForm": {
300
- const form = screen;
301
- pushKey(out, form.submitLabel);
302
- pushKey(out, form.summary?.title);
303
- pushKey(out, form.summary?.subtitle);
304
- for (const action of form.footerActions ?? [])
305
- pushKey(out, action.label);
306
- for (const link of form.successLinks ?? [])
307
- pushKey(out, link.label);
308
- for (const fact of form.successFacts ?? [])
309
- pushKey(out, fact.label);
310
- for (const fieldName of Object.keys(form.fields)) {
311
- const override = form.fieldLabels?.[fieldName];
312
- if (override !== undefined)
313
- pushKey(out, override);
314
- else
315
- out.add(fieldLabelKey(featureName, ACTION_FORM_ENTITY, fieldName));
316
- }
317
- for (const section of form.layout.sections) {
318
- if (isExtensionEditSection(section)) {
319
- pushKey(out, section.title);
320
- continue;
321
- }
322
- if (section.kind === "relatedList")
323
- continue; // rejected at boot, unreachable here
324
- pushSectionTitles(out, section);
325
- for (const f of sectionFieldSpecs(section)) {
326
- pushEditFieldTextKeys(out, f);
327
- const fieldName = editFieldName(f);
328
- const override = form.fieldLabels?.[fieldName];
329
- if (override !== undefined)
330
- pushKey(out, override);
331
- else
332
- out.add(fieldLabelKey(featureName, ACTION_FORM_ENTITY, fieldName));
333
- }
334
- }
335
- break;
278
+ }
279
+ }
280
+ function collectEntityEditKeys(ctx, edit) {
281
+ pushKey(ctx.out, edit.submitLabel);
282
+ pushKey(ctx.out, edit.titleTemplate);
283
+ pushEditLayoutSectionKeys(ctx, edit.layout.sections, edit.entity, edit.fieldLabels);
284
+ }
285
+ function collectActionFormKeys(ctx, form) {
286
+ pushKey(ctx.out, form.submitLabel);
287
+ pushKey(ctx.out, form.summary?.title);
288
+ pushKey(ctx.out, form.summary?.subtitle);
289
+ for (const action of form.footerActions ?? [])
290
+ pushKey(ctx.out, action.label);
291
+ for (const link of form.successLinks ?? [])
292
+ pushKey(ctx.out, link.label);
293
+ for (const fact of form.successFacts ?? [])
294
+ pushKey(ctx.out, fact.label);
295
+ for (const fieldName of Object.keys(form.fields)) {
296
+ pushFieldLabelOrOverrideKey(ctx, ACTION_FORM_ENTITY, fieldName, form.fieldLabels);
297
+ }
298
+ pushEditLayoutSectionKeys(ctx, form.layout.sections, ACTION_FORM_ENTITY, form.fieldLabels);
299
+ }
300
+ function collectSecretMintKeys(ctx, mint) {
301
+ const { out, featureName } = ctx;
302
+ pushKey(out, mint.submitLabel);
303
+ pushActionFormShapedKeys(out, featureName, mint);
304
+ pushKey(out, mint.reveal.title);
305
+ pushKey(out, mint.reveal.warning);
306
+ pushKey(out, mint.reveal.confirmLabel);
307
+ pushKey(out, mint.reveal.acknowledge);
308
+ for (const revealField of mint.reveal.fields) {
309
+ pushKey(out, revealField.label);
310
+ }
311
+ if (mint.confirm !== undefined) {
312
+ pushKey(out, mint.confirm.submitLabel);
313
+ pushKey(out, mint.confirm.doneMessage);
314
+ pushActionFormShapedKeys(out, featureName, mint.confirm);
315
+ }
316
+ }
317
+ function pushConfigEditSectionKeys(ctx, config) {
318
+ const { out, treatDotFormAsKey } = ctx;
319
+ for (const section of config.layout.sections) {
320
+ if (isExtensionEditSection(section)) {
321
+ pushKey(out, section.title);
322
+ continue;
336
323
  }
337
- case "secretMint": {
338
- const mint = screen;
339
- pushKey(out, mint.submitLabel);
340
- pushActionFormShapedKeys(out, featureName, mint);
341
- pushKey(out, mint.reveal.title);
342
- pushKey(out, mint.reveal.warning);
343
- pushKey(out, mint.reveal.confirmLabel);
344
- pushKey(out, mint.reveal.acknowledge);
345
- for (const revealField of mint.reveal.fields) {
346
- pushKey(out, revealField.label);
347
- }
348
- if (mint.confirm !== undefined) {
349
- pushKey(out, mint.confirm.submitLabel);
350
- pushKey(out, mint.confirm.doneMessage);
351
- pushActionFormShapedKeys(out, featureName, mint.confirm);
352
- }
353
- break;
324
+ if (section.kind === "relatedList")
325
+ continue; // rejected at boot, unreachable here
326
+ pushSectionTitles(out, section, treatDotFormAsKey);
327
+ pushKey(out, section.description, treatDotFormAsKey);
328
+ for (const f of sectionFieldSpecs(section)) {
329
+ pushEditFieldTextKeys(out, f, treatDotFormAsKey);
330
+ pushFieldLabelOrOverrideKey(ctx, CONFIG_EDIT_ENTITY, editFieldName(f), config.fieldLabels, treatDotFormAsKey);
354
331
  }
355
- case "configEdit": {
356
- const config = screen;
357
- pushKey(out, config.submitLabel);
358
- pushKey(out, config.description, treatDotFormAsKey);
359
- for (const key of Object.values(config.fieldDescriptions ?? {})) {
360
- pushKey(out, key, treatDotFormAsKey);
361
- }
362
- for (const fieldName of Object.keys(config.fields)) {
363
- const override = config.fieldLabels?.[fieldName];
364
- if (override !== undefined)
365
- pushKey(out, override, treatDotFormAsKey);
366
- else
367
- out.add(fieldLabelKey(featureName, CONFIG_EDIT_ENTITY, fieldName));
368
- }
369
- for (const section of config.layout.sections) {
370
- if (isExtensionEditSection(section)) {
371
- pushKey(out, section.title);
372
- continue;
373
- }
374
- if (section.kind === "relatedList")
375
- continue; // rejected at boot, unreachable here
376
- pushSectionTitles(out, section, treatDotFormAsKey);
377
- pushKey(out, section.description, treatDotFormAsKey);
378
- for (const f of sectionFieldSpecs(section)) {
379
- pushEditFieldTextKeys(out, f, treatDotFormAsKey);
380
- const fieldName = editFieldName(f);
381
- const override = config.fieldLabels?.[fieldName];
382
- if (override !== undefined)
383
- pushKey(out, override, treatDotFormAsKey);
384
- else
385
- out.add(fieldLabelKey(featureName, CONFIG_EDIT_ENTITY, fieldName));
386
- }
387
- }
388
- break;
332
+ }
333
+ }
334
+ function collectConfigEditKeys(ctx, config) {
335
+ const { out, treatDotFormAsKey } = ctx;
336
+ pushKey(out, config.submitLabel);
337
+ pushKey(out, config.description, treatDotFormAsKey);
338
+ for (const key of Object.values(config.fieldDescriptions ?? {})) {
339
+ pushKey(out, key, treatDotFormAsKey);
340
+ }
341
+ for (const fieldName of Object.keys(config.fields)) {
342
+ pushFieldLabelOrOverrideKey(ctx, CONFIG_EDIT_ENTITY, fieldName, config.fieldLabels, treatDotFormAsKey);
343
+ }
344
+ pushConfigEditSectionKeys(ctx, config);
345
+ }
346
+ function collectSecretsEditKeys(ctx, secretsEdit) {
347
+ const { out, treatDotFormAsKey } = ctx;
348
+ for (const key of Object.values(secretsEdit.fieldLabels))
349
+ pushKey(out, key, treatDotFormAsKey);
350
+ for (const key of Object.values(secretsEdit.fieldHints ?? {})) {
351
+ pushKey(out, key, treatDotFormAsKey);
352
+ }
353
+ for (const section of secretsEdit.sections)
354
+ pushKey(out, section.title, treatDotFormAsKey);
355
+ }
356
+ function pushWriteFormSectionKeys(ctx, section) {
357
+ pushKey(ctx.out, section.title);
358
+ pushKey(ctx.out, section.description);
359
+ pushKey(ctx.out, section.submitLabel);
360
+ for (const f of section.fields) {
361
+ pushEditFieldTextKeys(ctx.out, f);
362
+ ctx.out.add(fieldLabelKey(ctx.featureName, WRITE_FORM_SECTION_ENTITY, editFieldName(f)));
363
+ }
364
+ }
365
+ function collectProjectionDetailKeys(ctx, detail) {
366
+ for (const metric of detail.metrics ?? [])
367
+ pushKey(ctx.out, metric.label);
368
+ for (const section of detail.layout.sections) {
369
+ if (isExtensionEditSection(section)) {
370
+ pushKey(ctx.out, section.title);
371
+ continue;
389
372
  }
390
- case "secretsEdit": {
391
- const secretsEdit = screen;
392
- for (const key of Object.values(secretsEdit.fieldLabels))
393
- pushKey(out, key, treatDotFormAsKey);
394
- for (const key of Object.values(secretsEdit.fieldHints ?? {})) {
395
- pushKey(out, key, treatDotFormAsKey);
396
- }
397
- for (const section of secretsEdit.sections)
398
- pushKey(out, section.title, treatDotFormAsKey);
399
- break;
373
+ if (section.kind === "relatedList") {
374
+ pushRelatedListSectionKeys(ctx.out, section);
375
+ continue;
400
376
  }
401
- case "projectionDetail": {
402
- const detail = screen;
403
- for (const section of detail.layout.sections) {
404
- if (isExtensionEditSection(section)) {
405
- pushKey(out, section.title);
406
- continue;
407
- }
408
- if (section.kind === "relatedList") {
409
- pushRelatedListSectionKeys(out, section);
410
- continue;
411
- }
412
- if (isWriteFormEditSection(section)) {
413
- pushKey(out, section.title);
414
- pushKey(out, section.description);
415
- pushKey(out, section.submitLabel);
416
- for (const f of section.fields) {
417
- pushEditFieldTextKeys(out, f);
418
- const fieldName = editFieldName(f);
419
- out.add(fieldLabelKey(featureName, WRITE_FORM_SECTION_ENTITY, fieldName));
420
- }
421
- continue;
422
- }
423
- pushSectionTitles(out, section);
424
- for (const f of sectionFieldSpecs(section)) {
425
- pushEditFieldTextKeys(out, f);
426
- const fieldName = editFieldName(f);
427
- const override = detail.fieldLabels?.[fieldName];
428
- if (override !== undefined)
429
- pushKey(out, override);
430
- else
431
- out.add(fieldLabelKey(featureName, PROJECTION_DETAIL_ENTITY, fieldName));
432
- }
433
- }
434
- break;
377
+ if (isWriteFormEditSection(section)) {
378
+ pushWriteFormSectionKeys(ctx, section);
379
+ continue;
380
+ }
381
+ pushSectionTitles(ctx.out, section);
382
+ for (const f of sectionFieldSpecs(section)) {
383
+ pushEditFieldTextKeys(ctx.out, f);
384
+ pushFieldLabelOrOverrideKey(ctx, PROJECTION_DETAIL_ENTITY, editFieldName(f), detail.fieldLabels);
435
385
  }
436
- case "custom":
437
- break;
438
386
  }
439
- return [...out];
387
+ }
388
+ const SCREEN_KEY_COLLECTORS = {
389
+ entityList: collectEntityListKeys,
390
+ projectionList: collectProjectionListKeys,
391
+ entityEdit: collectEntityEditKeys,
392
+ actionForm: collectActionFormKeys,
393
+ secretMint: collectSecretMintKeys,
394
+ configEdit: collectConfigEditKeys,
395
+ secretsEdit: collectSecretsEditKeys,
396
+ projectionDetail: collectProjectionDetailKeys,
397
+ dashboard: (ctx, screen) => pushDashboardScreenKeys(ctx.out, screen),
398
+ // Custom screens translate their own texts.
399
+ custom: () => { },
400
+ };
401
+ function collectScreenKeysOfKind(ctx, kind, screen) {
402
+ SCREEN_KEY_COLLECTORS[kind](ctx, screen);
403
+ }
404
+ export function requiredKeysFromScreen(featureName, screen, options = {}) {
405
+ const ctx = {
406
+ out: new Set(),
407
+ featureName,
408
+ treatDotFormAsKey: options.treatDotFormAsKey ?? false,
409
+ };
410
+ pushKey(ctx.out, screenTitleKey(screen.id));
411
+ // An unknown type is only reachable by casting past ScreenDefinition and yields the title key alone.
412
+ if (Object.hasOwn(SCREEN_KEY_COLLECTORS, screen.type)) {
413
+ collectScreenKeysOfKind(ctx, screen.type, screen);
414
+ }
415
+ return [...ctx.out];
440
416
  }
441
417
  export function requiredKeysFromNav(nav, options = {}) {
442
418
  const out = new Set();
@@ -1,6 +1,7 @@
1
+ export { isClosedConnectionError } from "../db/closed-connection.ts";
1
2
  export { createDbConnection } from "../db/connection.ts";
2
3
  export { acquireSessionAdvisoryLock, createDatabase, databaseExists, dropDatabaseIfExists, listDatabaseNamesWithPrefix, renameDatabase, truncateTablesRestartIdentity, } from "../db/queries/test-stack.ts";
3
- export { type AnyDb, isClosedConnectionError } from "../db/query.ts";
4
+ export type { AnyDb } from "../db/query.ts";
4
5
  export { columnNamesOf } from "../db/schema-inspection.ts";
5
6
  export { schemaTableName } from "../db/table-introspection.ts";
6
7
  export { addMissingColumns, addMissingIndexes, tableToMeta, unsafeCreateEntityTable, unsafeEnsureEntityTable, unsafePushTables, } from "../db/table-push.ts";
@@ -1,7 +1,7 @@
1
1
  // @runtime dev
2
+ export { isClosedConnectionError } from "../db/closed-connection.js";
2
3
  export { createDbConnection } from "../db/connection.js";
3
4
  export { acquireSessionAdvisoryLock, createDatabase, databaseExists, dropDatabaseIfExists, listDatabaseNamesWithPrefix, renameDatabase, truncateTablesRestartIdentity, } from "../db/queries/test-stack.js";
4
- export { isClosedConnectionError } from "../db/query.js";
5
5
  export { columnNamesOf } from "../db/schema-inspection.js";
6
6
  export { schemaTableName } from "../db/table-introspection.js";
7
7
  export { addMissingColumns, addMissingIndexes, tableToMeta, unsafeCreateEntityTable, unsafeEnsureEntityTable, unsafePushTables, } from "../db/table-push.js";
@@ -0,0 +1,32 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
2
+ import type { ConfigAccessor } from "@cosmicdrift/kumiko-types/config";
3
+ import type { WriteOrigin } from "@cosmicdrift/kumiko-types/event-store-types";
4
+ import type { DbRow } from "../db/connection.ts";
5
+ import type { JobContext, JobDefinition } from "../engine/types/index.ts";
6
+ import type { JobRunnerScope } from "./job-runner-scope.ts";
7
+ import type { JobInvocation, JobLogEntry, JobMeta } from "./job-runner-types.ts";
8
+ export type TenantVisibleSubjects = {
9
+ readonly failureSubject: string | null;
10
+ readonly runSubject: string | null;
11
+ readonly configError: Error | undefined;
12
+ };
13
+ export type JobRun = {
14
+ readonly jobName: string;
15
+ readonly jobDef: JobDefinition;
16
+ readonly jobId: string;
17
+ readonly startTime: number;
18
+ readonly logs: JobLogEntry[];
19
+ readonly rawData: DbRow;
20
+ readonly attempt: number;
21
+ readonly finalAttempt: boolean;
22
+ readonly meta: JobMeta;
23
+ readonly payload: Record<string, unknown>;
24
+ readonly tenantId: string;
25
+ readonly triggeredById: string | null;
26
+ readonly subjects: TenantVisibleSubjects;
27
+ readonly writeOrigin: WriteOrigin | undefined;
28
+ readonly writeOriginInvalid: boolean;
29
+ readonly config: ConfigAccessor | undefined;
30
+ readonly jobContext: Omit<JobContext, "tz">;
31
+ };
32
+ export declare function prepareJobRun(scope: JobRunnerScope, jobDef: JobDefinition, bullJob: JobInvocation, token: string | undefined): JobRun;