@fuzdev/fuz_app 0.47.0 → 0.48.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.
@@ -107,20 +107,22 @@ should not appear in consumer-owned typed surfaces (`ActionMethod`,
107
107
  `include_composables: true` only if a consumer genuinely owns composables
108
108
  in their typed API.
109
109
 
110
- **Consumer tiers and the single-namespace assumption.** Single-source consumers
111
- (zzz, undying — every spec lives in one local `action_specs.ts`) drop straight
112
- into the helpers. Multi-source consumers (tx, visiones which stitch local
113
- specs together with `all_admin_action_specs` / `all_permit_offer_action_specs` /
114
- `all_account_action_specs` / `all_self_service_role_action_specs` from fuz_app)
115
- need a per-method namespace lookup, and the helpers that emit
116
- `specs.{method}_action_spec` (`generate_action_specs_record`,
117
- `generate_action_inputs_outputs`, `generate_backend_actions_api`) currently
118
- assume one `* as specs from specs_module` import covers everything. Multi-source
119
- consumers keep using the lower-level primitives directly
120
- (`to_action_spec_input_identifier`, `to_action_spec_output_identifier`,
121
- `ActionRegistry`) see tx's `action_collections.gen.ts` for the current
122
- pattern. A `qualify_spec?: (spec) => string` callback is the planned extension
123
- point; design it against the Step 3 (tx parity) consumer.
110
+ **Consumer tiers and namespace handling.** Single-source consumers (zzz,
111
+ undying — every spec lives in one local `action_specs.ts`) drop straight
112
+ into the helpers and accept the default `* as specs from specs_module`
113
+ namespace import. Multi-source consumers (tx, visiones — which stitch
114
+ local specs together with `all_admin_action_specs` /
115
+ `all_permit_offer_action_specs` / `all_account_action_specs` /
116
+ `all_self_service_role_action_specs` from fuz_app) pass
117
+ `qualify_spec?: (spec) => string` to the three multi-source helpers
118
+ (`generate_action_specs_record`, `generate_action_inputs_outputs`,
119
+ `generate_backend_actions_api`). When `qualify_spec` is set, the helper
120
+ emits the callback's return value (e.g.
121
+ `admin_specs.account_list_action_spec`) and skips the default `* as specs`
122
+ import the consumer manages its own multi-namespace imports. The helper
123
+ appends `.input` / `.output` to the qualified identifier in
124
+ `generate_action_inputs_outputs` automatically; the callback returns the
125
+ bare spec identifier.
124
126
 
125
127
  Tier 1 (HTTP-only, e.g. tx/visiones) emits a smaller surface — typically just
126
128
  `ActionMethod` + `ActionsApi` + `ActionInputs` / `ActionOutputs` interfaces —
@@ -131,12 +133,12 @@ zzz) emits the full set including `ActionEventDatas`, `TypedActionEvent`, and
131
133
 
132
134
  - `generate_action_method_enums(specs, imports, {emit?})` — up to six `z.enum` + `z.infer` pairs (`ActionMethod`, `RequestResponseActionMethod`, `RemoteNotificationActionMethod`, `LocalCallActionMethod`, `FrontendActionMethod`, `BackendActionMethod`). `emit: ReadonlySet<ActionMethodEnumKind>` restricts to a subset (Tier 1 HTTP-only consumers don't need all six). Skips kinds whose method list is empty (`z.enum([])` is invalid) and skips the `zod` import when no blocks are emitted. Adds `import {z} from 'zod'` only when at least one block is produced.
133
135
  - `generate_typed_action_event_alias(imports, {collections_path?, metatypes_path?})` — fixed-shape `TypedActionEvent<TMethod, TPhase, TStep>` alias narrowing `ActionEvent.data` against `ActionEventDatas`. Adds the three fuz_app type imports + `ActionEventDatas` (from `collections_path`) + `ActionMethod` (from `metatypes_path`).
134
- - `generate_action_specs_record(specs, imports, {specs_module?})` — `ActionSpecs` runtime const + interface + `action_specs: Array<ActionSpecUnion>` value. Adds `* as specs` from `specs_module`.
135
- - `generate_action_inputs_outputs(specs, imports, {specs_module?})` — `ActionInputs` and `ActionOutputs` runtime consts + interfaces. Adds `* as specs` from `specs_module`.
136
- - `generate_action_event_datas(specs, imports, {collections_path?})` — `ActionEventDatas` interface; per-spec variant by kind (`ActionEventRequestResponseData` / `ActionEventRemoteNotificationData` / `ActionEventLocalCallData`). When `collections_path` is set, adds `ActionInputs` / `ActionOutputs` type imports from that path; default (unset) assumes same-file scope, the zzz pattern where this helper feeds the same `action_collections.ts` output as `generate_action_inputs_outputs`.
136
+ - `generate_action_specs_record(specs, imports, {specs_module?, qualify_spec?})` — `ActionSpecs` runtime const + interface + `action_specs: Array<ActionSpecUnion>` value. Adds `* as specs` from `specs_module` unless `qualify_spec` is set (then `specs_module` is ignored and the consumer owns namespace imports).
137
+ - `generate_action_inputs_outputs(specs, imports, {specs_module?, qualify_spec?})` — `ActionInputs` and `ActionOutputs` runtime consts + interfaces. Same `qualify_spec` semantics as `generate_action_specs_record`; the helper appends `.input` / `.output` to the qualified identifier.
138
+ - `generate_action_event_datas(specs, imports, {same_file?, collections_path?})` — `ActionEventDatas` interface; per-spec variant by kind (`ActionEventRequestResponseData` / `ActionEventRemoteNotificationData` / `ActionEventLocalCallData`). `same_file` (default `true`) is the file-layout switch: when `true`, assumes `ActionInputs` / `ActionOutputs` are in the same module and adds no import (the zzz pattern); when `false`, adds the type imports from `collections_path` (default `'./action_collections.js'`). `collections_path` alone is a no-op — the surprising omit-vs-default behavior of earlier versions has been replaced.
137
139
  - `generate_actions_api(specs, imports, {method_filter?, collections_path?, sync_returns_value?})` — `ActionsApi` interface. Composables filtered by default; `method_filter: (spec) => boolean` runs after the composable filter for tx-style additional subsets.
138
140
  - `generate_frontend_action_handlers(specs, imports, {collections_path?})` — `FrontendActionHandlers` interface (Tier 2 only — wraps `generate_phase_handlers` with `action_event_type: 'TypedActionEvent'`). Pair with `generate_typed_action_event_alias`.
139
- - `generate_backend_actions_api(specs, imports, {specs_module?, collections_path?})` — `BackendActionsApi` interface AND `broadcast_action_specs: ReadonlyArray<ActionSpecUnion>` array. Filter: `kind === 'remote_notification' && initiator !== 'frontend'`. Adds the `* as specs` namespace import + `ActionInputs` (from `collections_path`) + `ActionSpecUnion`.
141
+ - `generate_backend_actions_api(specs, imports, {specs_module?, collections_path?, qualify_spec?})` — `BackendActionsApi` interface AND `broadcast_action_specs: ReadonlyArray<ActionSpecUnion>` array. Filter: `kind === 'remote_notification' && initiator !== 'frontend'`. Adds `ActionInputs` (from `collections_path`) + `ActionSpecUnion`, plus `* as specs` from `specs_module` unless `qualify_spec` is set.
140
142
 
141
143
  ## HTTP bridge (`action_bridge.ts`)
142
144
 
@@ -209,14 +209,16 @@ export declare const generate_typed_action_event_alias: (imports: ImportBuilder,
209
209
  * Array<ActionSpecUnion>` value bundling every spec. Adds the `* as specs`
210
210
  * namespace import + the `ActionSpecUnion` type import.
211
211
  *
212
- * **Single-namespace.** Every spec is referenced as `specs.{method}_action_spec`.
213
- * Multi-source consumers (tx, visiones) need a per-method namespace lookup
214
- * and currently use lower-level primitives instead see the `--- High-level
215
- * codegen helpers ---` banner above for the rationale and the planned
216
- * `qualify_spec?` extension point.
212
+ * @param options.qualify_spec - per-spec qualified identifier callback for
213
+ * multi-source consumers (e.g. ``(s) => `admin_specs.${s.method}_action_spec` ``).
214
+ * When set, the helper emits the callback's return value instead of
215
+ * ``specs.${method}_action_spec`` and skips the default `* as specs`
216
+ * import the consumer manages its own namespace imports. `specs_module`
217
+ * is ignored when `qualify_spec` is set. Single-source consumers omit it.
217
218
  */
218
219
  export declare const generate_action_specs_record: (specs: ReadonlyArray<ActionSpecUnion>, imports: ImportBuilder, options?: {
219
220
  specs_module?: string;
221
+ qualify_spec?: (spec: ActionSpecUnion) => string;
220
222
  include_composables?: boolean;
221
223
  }) => string;
222
224
  /**
@@ -226,11 +228,15 @@ export declare const generate_action_specs_record: (specs: ReadonlyArray<ActionS
226
228
  *
227
229
  * Adds `import {z} from 'zod';` and the `* as specs` namespace import.
228
230
  *
229
- * **Single-namespace.** Same caveat as `generate_action_specs_record`
230
- * multi-source consumers use the lower-level primitives.
231
+ * @param options.qualify_spec - per-spec qualified identifier callback for
232
+ * multi-source consumers. The helper appends `.input` / `.output` to the
233
+ * callback's return value. When set, the helper skips the default
234
+ * `* as specs` import — the consumer manages its own namespace imports —
235
+ * and `specs_module` is ignored. Single-source consumers omit it.
231
236
  */
232
237
  export declare const generate_action_inputs_outputs: (specs: ReadonlyArray<ActionSpecUnion>, imports: ImportBuilder, options?: {
233
238
  specs_module?: string;
239
+ qualify_spec?: (spec: ActionSpecUnion) => string;
234
240
  include_composables?: boolean;
235
241
  }) => string;
236
242
  /**
@@ -242,14 +248,19 @@ export declare const generate_action_inputs_outputs: (specs: ReadonlyArray<Actio
242
248
  *
243
249
  * Adds the per-kind data type imports (only the kinds that appear in `specs`).
244
250
  *
245
- * @param options.collections_path - when set, adds `ActionInputs` /
246
- * `ActionOutputs` type imports from this path. Leave unset (default) when
247
- * the producer emits `ActionEventDatas` in the same file as
248
- * `ActionInputs` / `ActionOutputs` same-file scope means no imports
249
- * needed (the zzz pattern, where `generate_action_inputs_outputs` and
250
- * this helper feed the same `action_collections.ts` output).
251
+ * @param options.same_file - when `true` (default), assumes `ActionInputs` /
252
+ * `ActionOutputs` are in the same module as the emitted `ActionEventDatas`
253
+ * and adds no import (the zzz pattern, where `generate_action_inputs_outputs`
254
+ * and this helper feed the same `action_collections.ts` output). When
255
+ * `false`, adds `ActionInputs` / `ActionOutputs` type imports from
256
+ * `collections_path`.
257
+ * @param options.collections_path - import path used when `same_file: false`.
258
+ * Defaults to `'./action_collections.js'`. Ignored when `same_file: true`
259
+ * — `same_file` is the file-layout switch; `collections_path` is just the
260
+ * path the import resolves to.
251
261
  */
252
262
  export declare const generate_action_event_datas: (specs: ReadonlyArray<ActionSpecUnion>, imports: ImportBuilder, options?: {
263
+ same_file?: boolean;
253
264
  collections_path?: string;
254
265
  include_composables?: boolean;
255
266
  }) => string;
@@ -290,12 +301,17 @@ export declare const generate_frontend_action_handlers: (specs: ReadonlyArray<Ac
290
301
  * `ActionInputs` type import (from `collections_path`), and the
291
302
  * `ActionSpecUnion` type import.
292
303
  *
293
- * **Single-namespace.** Same caveat as `generate_action_specs_record`
294
- * multi-source consumers use the lower-level primitives.
304
+ * @param options.qualify_spec - per-spec qualified identifier callback for
305
+ * multi-source consumers. When set, the helper emits the callback's return
306
+ * value instead of ``specs.${method}_action_spec`` in the broadcast array
307
+ * and skips the default `* as specs` import — the consumer manages its own
308
+ * namespace imports. `specs_module` is ignored when `qualify_spec` is set.
309
+ * Single-source consumers omit it.
295
310
  */
296
311
  export declare const generate_backend_actions_api: (specs: ReadonlyArray<ActionSpecUnion>, imports: ImportBuilder, options?: {
297
312
  specs_module?: string;
298
313
  collections_path?: string;
314
+ qualify_spec?: (spec: ActionSpecUnion) => string;
299
315
  include_composables?: boolean;
300
316
  }) => string;
301
317
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"action_codegen.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_codegen.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"action_codegen.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_codegen.ts"],"names":[],"mappings":"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"}
@@ -372,6 +372,22 @@ export const ACTION_METHOD_ENUM_KINDS_ALL = new Set([
372
372
  * surfaces (`ActionMethod`, `ActionsApi`, `ActionInputs`, etc.) by default.
373
373
  */
374
374
  const filter_composables = (specs, include_composables) => include_composables ? specs : specs.filter((s) => !is_composable_action_method(s.method));
375
+ /**
376
+ * Resolve the per-spec identifier qualifier used by the multi-source helpers
377
+ * (`generate_action_specs_record`, `generate_action_inputs_outputs`,
378
+ * `generate_backend_actions_api`). When `qualify_spec` is set, returns the
379
+ * caller's callback verbatim — the consumer is managing its own namespace
380
+ * imports. Otherwise, registers the default `* as specs from specs_module`
381
+ * import (defaulting to `'./action_specs.js'`) and returns the matching
382
+ * `specs.${method}_action_spec` qualifier.
383
+ */
384
+ const resolve_spec_qualifier = (imports, options) => {
385
+ if (options?.qualify_spec)
386
+ return options.qualify_spec;
387
+ const specs_module = options?.specs_module ?? DEFAULT_SPECS_MODULE;
388
+ imports.add(specs_module, '* as specs');
389
+ return (s) => `specs.${s.method}_action_spec`;
390
+ };
375
391
  /**
376
392
  * Emit one or more `z.enum([...])` declarations for action method names —
377
393
  * `ActionMethod`, `RequestResponseActionMethod`, `RemoteNotificationActionMethod`,
@@ -449,11 +465,12 @@ type TypedActionEvent<
449
465
  * Array<ActionSpecUnion>` value bundling every spec. Adds the `* as specs`
450
466
  * namespace import + the `ActionSpecUnion` type import.
451
467
  *
452
- * **Single-namespace.** Every spec is referenced as `specs.{method}_action_spec`.
453
- * Multi-source consumers (tx, visiones) need a per-method namespace lookup
454
- * and currently use lower-level primitives instead see the `--- High-level
455
- * codegen helpers ---` banner above for the rationale and the planned
456
- * `qualify_spec?` extension point.
468
+ * @param options.qualify_spec - per-spec qualified identifier callback for
469
+ * multi-source consumers (e.g. ``(s) => `admin_specs.${s.method}_action_spec` ``).
470
+ * When set, the helper emits the callback's return value instead of
471
+ * ``specs.${method}_action_spec`` and skips the default `* as specs`
472
+ * import the consumer manages its own namespace imports. `specs_module`
473
+ * is ignored when `qualify_spec` is set. Single-source consumers omit it.
457
474
  */
458
475
  export const generate_action_specs_record = (specs, imports, options) => {
459
476
  const filtered = filter_composables(specs, options?.include_composables);
@@ -470,14 +487,9 @@ export interface ActionSpecs {}
470
487
 
471
488
  export const action_specs: Array<ActionSpecUnion> = Object.values(ActionSpecs);`;
472
489
  }
473
- const specs_module = options?.specs_module ?? DEFAULT_SPECS_MODULE;
474
- imports.add(specs_module, '* as specs');
475
- const value_lines = filtered
476
- .map((s) => `\t${s.method}: specs.${s.method}_action_spec,`)
477
- .join('\n');
478
- const type_lines = filtered
479
- .map((s) => `\t${s.method}: typeof specs.${s.method}_action_spec;`)
480
- .join('\n');
490
+ const qualify = resolve_spec_qualifier(imports, options);
491
+ const value_lines = filtered.map((s) => `\t${s.method}: ${qualify(s)},`).join('\n');
492
+ const type_lines = filtered.map((s) => `\t${s.method}: typeof ${qualify(s)};`).join('\n');
481
493
  return `/**
482
494
  * Action specifications indexed by method name.
483
495
  * These represent the complete action spec definitions.
@@ -498,8 +510,11 @@ export const action_specs: Array<ActionSpecUnion> = Object.values(ActionSpecs);`
498
510
  *
499
511
  * Adds `import {z} from 'zod';` and the `* as specs` namespace import.
500
512
  *
501
- * **Single-namespace.** Same caveat as `generate_action_specs_record`
502
- * multi-source consumers use the lower-level primitives.
513
+ * @param options.qualify_spec - per-spec qualified identifier callback for
514
+ * multi-source consumers. The helper appends `.input` / `.output` to the
515
+ * callback's return value. When set, the helper skips the default
516
+ * `* as specs` import — the consumer manages its own namespace imports —
517
+ * and `specs_module` is ignored. Single-source consumers omit it.
503
518
  */
504
519
  export const generate_action_inputs_outputs = (specs, imports, options) => {
505
520
  const filtered = filter_composables(specs, options?.include_composables);
@@ -523,19 +538,14 @@ export const ActionOutputs = {} as const;
523
538
  export interface ActionOutputs {}`;
524
539
  }
525
540
  imports.add('zod', 'z');
526
- const specs_module = options?.specs_module ?? DEFAULT_SPECS_MODULE;
527
- imports.add(specs_module, '* as specs');
528
- const inputs_value = filtered
529
- .map((s) => `\t${s.method}: specs.${s.method}_action_spec.input,`)
530
- .join('\n');
541
+ const qualify = resolve_spec_qualifier(imports, options);
542
+ const inputs_value = filtered.map((s) => `\t${s.method}: ${qualify(s)}.input,`).join('\n');
531
543
  const inputs_type = filtered
532
- .map((s) => `\t${s.method}: z.infer<typeof specs.${s.method}_action_spec.input>;`)
533
- .join('\n');
534
- const outputs_value = filtered
535
- .map((s) => `\t${s.method}: specs.${s.method}_action_spec.output,`)
544
+ .map((s) => `\t${s.method}: z.infer<typeof ${qualify(s)}.input>;`)
536
545
  .join('\n');
546
+ const outputs_value = filtered.map((s) => `\t${s.method}: ${qualify(s)}.output,`).join('\n');
537
547
  const outputs_type = filtered
538
- .map((s) => `\t${s.method}: z.infer<typeof specs.${s.method}_action_spec.output>;`)
548
+ .map((s) => `\t${s.method}: z.infer<typeof ${qualify(s)}.output>;`)
539
549
  .join('\n');
540
550
  return `/**
541
551
  * Action parameter schemas indexed by method name.
@@ -570,12 +580,16 @@ ${outputs_type}
570
580
  *
571
581
  * Adds the per-kind data type imports (only the kinds that appear in `specs`).
572
582
  *
573
- * @param options.collections_path - when set, adds `ActionInputs` /
574
- * `ActionOutputs` type imports from this path. Leave unset (default) when
575
- * the producer emits `ActionEventDatas` in the same file as
576
- * `ActionInputs` / `ActionOutputs` same-file scope means no imports
577
- * needed (the zzz pattern, where `generate_action_inputs_outputs` and
578
- * this helper feed the same `action_collections.ts` output).
583
+ * @param options.same_file - when `true` (default), assumes `ActionInputs` /
584
+ * `ActionOutputs` are in the same module as the emitted `ActionEventDatas`
585
+ * and adds no import (the zzz pattern, where `generate_action_inputs_outputs`
586
+ * and this helper feed the same `action_collections.ts` output). When
587
+ * `false`, adds `ActionInputs` / `ActionOutputs` type imports from
588
+ * `collections_path`.
589
+ * @param options.collections_path - import path used when `same_file: false`.
590
+ * Defaults to `'./action_collections.js'`. Ignored when `same_file: true`
591
+ * — `same_file` is the file-layout switch; `collections_path` is just the
592
+ * path the import resolves to.
579
593
  */
580
594
  export const generate_action_event_datas = (specs, imports, options) => {
581
595
  const filtered = filter_composables(specs, options?.include_composables);
@@ -589,8 +603,10 @@ export const generate_action_event_datas = (specs, imports, options) => {
589
603
  */
590
604
  export interface ActionEventDatas {}`;
591
605
  }
592
- if (options?.collections_path) {
593
- imports.add_types(options.collections_path, 'ActionInputs', 'ActionOutputs');
606
+ const same_file = options?.same_file ?? true;
607
+ if (!same_file) {
608
+ const collections_path = options?.collections_path ?? DEFAULT_COLLECTIONS_PATH;
609
+ imports.add_types(collections_path, 'ActionInputs', 'ActionOutputs');
594
610
  }
595
611
  const lines = filtered.map((spec) => {
596
612
  const data_type = spec.kind === 'request_response'
@@ -702,8 +718,12 @@ ${lines};
702
718
  * `ActionInputs` type import (from `collections_path`), and the
703
719
  * `ActionSpecUnion` type import.
704
720
  *
705
- * **Single-namespace.** Same caveat as `generate_action_specs_record`
706
- * multi-source consumers use the lower-level primitives.
721
+ * @param options.qualify_spec - per-spec qualified identifier callback for
722
+ * multi-source consumers. When set, the helper emits the callback's return
723
+ * value instead of ``specs.${method}_action_spec`` in the broadcast array
724
+ * and skips the default `* as specs` import — the consumer manages its own
725
+ * namespace imports. `specs_module` is ignored when `qualify_spec` is set.
726
+ * Single-source consumers omit it.
707
727
  */
708
728
  export const generate_backend_actions_api = (specs, imports, options) => {
709
729
  const composable_filtered = filter_composables(specs, options?.include_composables);
@@ -722,16 +742,15 @@ export interface BackendActionsApi {}
722
742
 
723
743
  export const broadcast_action_specs: ReadonlyArray<ActionSpecUnion> = [];`;
724
744
  }
725
- const specs_module = options?.specs_module ?? DEFAULT_SPECS_MODULE;
726
745
  const collections_path = options?.collections_path ?? DEFAULT_COLLECTIONS_PATH;
727
- imports.add(specs_module, '* as specs');
728
746
  imports.add_type(collections_path, 'ActionInputs');
747
+ const qualify = resolve_spec_qualifier(imports, options);
729
748
  const interface_body = '\n' +
730
749
  broadcast
731
750
  .map((s) => `\t${s.method}: (input: ActionInputs['${s.method}']) => Promise<void>;`)
732
751
  .join('\n') +
733
752
  '\n';
734
- const array_body = '\n' + broadcast.map((s) => `\tspecs.${s.method}_action_spec,`).join('\n') + '\n';
753
+ const array_body = '\n' + broadcast.map((s) => `\t${qualify(s)},`).join('\n') + '\n';
735
754
  return `${interface_doc}
736
755
  export interface BackendActionsApi {${interface_body}}
737
756
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzdev/fuz_app",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "fullstack app library",
5
5
  "glyph": "🗝",
6
6
  "logo": "logo.svg",