@fuzdev/fuz_app 0.47.0 → 0.49.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.
- package/dist/actions/CLAUDE.md +92 -47
- package/dist/actions/action_codegen.d.ts +199 -29
- package/dist/actions/action_codegen.d.ts.map +1 -1
- package/dist/actions/action_codegen.js +321 -70
- package/dist/actions/action_registry.d.ts +41 -9
- package/dist/actions/action_registry.d.ts.map +1 -1
- package/dist/actions/action_registry.js +109 -32
- package/package.json +1 -1
|
@@ -1,13 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `ActionRegistry` — query and filter utility over `ActionSpecUnion[]`.
|
|
3
3
|
*
|
|
4
|
+
* Vocabulary (set in API review III, see the `docs/` directory and the SAES quest):
|
|
5
|
+
* - `*_handled_*` — request_response specs the named side **receives**
|
|
6
|
+
* (so the named side owns the handler). Used by codegen to emit typed
|
|
7
|
+
* handler maps.
|
|
8
|
+
* - `*_relevant_to_*` — the loose "everything this side might encounter"
|
|
9
|
+
* set, used by the typed-Proxy method enums (`FrontendActionMethod`,
|
|
10
|
+
* `BackendActionMethod`).
|
|
11
|
+
* - `broadcast_*` — kind-narrow `remote_notification` set with the
|
|
12
|
+
* `streams`-target exclusion. Today this matches what the broadcast
|
|
13
|
+
* API exposes.
|
|
14
|
+
* - `backend_initiated_*` — forward-looking kind-agnostic version of the
|
|
15
|
+
* broadcast set. Same content today; will diverge when local_calls or
|
|
16
|
+
* backend `request_response` join the backend's typed surface.
|
|
17
|
+
*
|
|
18
|
+
* Cache discipline: `spec_by_method` (Map) and the internal streams-target
|
|
19
|
+
* set lazy-memoize because the Map is consulted per-RPC dispatch
|
|
20
|
+
* (`frontend_rpc_client.ts` wires it into `lookup_action_spec`) and the
|
|
21
|
+
* streams set is rebuilt by two public getters. Array-returning getters
|
|
22
|
+
* recompute on each call so callers can mutate the result freely
|
|
23
|
+
* (`.sort()`, `.push(injected)` on a copy, etc.) without affecting the
|
|
24
|
+
* registry — codegen is a build-time path where the extra `.filter` /
|
|
25
|
+
* `.map` work is negligible.
|
|
26
|
+
*
|
|
4
27
|
* @module
|
|
5
28
|
*/
|
|
6
|
-
// TODO @action-system-review Many getters below are stub API surface — only
|
|
7
|
-
// `
|
|
8
|
-
// `
|
|
9
|
-
//
|
|
10
|
-
//
|
|
29
|
+
// TODO @action-system-review Many getters below are stub API surface — only
|
|
30
|
+
// `spec_by_method`, `methods`, the kind-narrow `*_specs` (`request_response_specs`,
|
|
31
|
+
// `remote_notification_specs`, `local_call_specs`), the `*_handled_*` pair,
|
|
32
|
+
// the `*_relevant_to_*` pair, and `broadcast_*` / `backend_initiated_*` are
|
|
33
|
+
// used by codegen. The auth + initiator-direction getters are pre-built for
|
|
34
|
+
// future use. Revisit which getters to keep when the action system matures.
|
|
11
35
|
/**
|
|
12
36
|
* Utility class to manage and query action specifications.
|
|
13
37
|
* Provides helper methods to get actions by various criteria.
|
|
@@ -17,9 +41,14 @@ export class ActionRegistry {
|
|
|
17
41
|
constructor(specs) {
|
|
18
42
|
this.specs = specs;
|
|
19
43
|
}
|
|
44
|
+
#spec_by_method;
|
|
20
45
|
get spec_by_method() {
|
|
21
|
-
return new Map(this.specs.map((spec) => [spec.method, spec]));
|
|
46
|
+
return (this.#spec_by_method ??= new Map(this.specs.map((spec) => [spec.method, spec])));
|
|
47
|
+
}
|
|
48
|
+
get methods() {
|
|
49
|
+
return this.specs.map((spec) => spec.method);
|
|
22
50
|
}
|
|
51
|
+
// --- Kind-narrow getters ---
|
|
23
52
|
get request_response_specs() {
|
|
24
53
|
return this.specs.filter((spec) => spec.kind === 'request_response');
|
|
25
54
|
}
|
|
@@ -29,44 +58,73 @@ export class ActionRegistry {
|
|
|
29
58
|
get local_call_specs() {
|
|
30
59
|
return this.specs.filter((spec) => spec.kind === 'local_call');
|
|
31
60
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
get
|
|
61
|
+
get request_response_methods() {
|
|
62
|
+
return this.request_response_specs.map((spec) => spec.method);
|
|
63
|
+
}
|
|
64
|
+
get remote_notification_methods() {
|
|
65
|
+
return this.remote_notification_specs.map((spec) => spec.method);
|
|
66
|
+
}
|
|
67
|
+
get local_call_methods() {
|
|
68
|
+
return this.local_call_specs.map((spec) => spec.method);
|
|
69
|
+
}
|
|
70
|
+
// --- Loose "relevant to side" getters ---
|
|
71
|
+
// Backs the `FrontendActionMethod` / `BackendActionMethod` enums — the
|
|
72
|
+
// typed-Proxy method enums where every spec the side might encounter
|
|
73
|
+
// (call, receive, or execute) belongs in the union.
|
|
74
|
+
get specs_relevant_to_frontend() {
|
|
75
|
+
return this.specs.slice();
|
|
76
|
+
}
|
|
77
|
+
get specs_relevant_to_backend() {
|
|
36
78
|
return this.specs.filter((spec) => spec.kind !== 'local_call');
|
|
37
79
|
}
|
|
38
|
-
get
|
|
39
|
-
return this.
|
|
80
|
+
get methods_relevant_to_frontend() {
|
|
81
|
+
return this.specs_relevant_to_frontend.map((spec) => spec.method);
|
|
40
82
|
}
|
|
41
|
-
get
|
|
42
|
-
return this.
|
|
83
|
+
get methods_relevant_to_backend() {
|
|
84
|
+
return this.specs_relevant_to_backend.map((spec) => spec.method);
|
|
43
85
|
}
|
|
44
|
-
|
|
45
|
-
|
|
86
|
+
// --- Narrow handler-side getters (request_response only) ---
|
|
87
|
+
// "Handled" = this side **receives** (initiator excludes own side).
|
|
88
|
+
// Drives `FrontendRequestResponseMethod` / `BackendRequestResponseMethod`
|
|
89
|
+
// enums and the typed `BackendActionHandlers` mapped type.
|
|
90
|
+
get frontend_handled_specs() {
|
|
91
|
+
return this.request_response_specs.filter((spec) => spec.initiator !== 'frontend');
|
|
46
92
|
}
|
|
47
|
-
get
|
|
48
|
-
return this.
|
|
93
|
+
get backend_handled_specs() {
|
|
94
|
+
return this.request_response_specs.filter((spec) => spec.initiator !== 'backend');
|
|
49
95
|
}
|
|
50
|
-
get
|
|
51
|
-
return this.
|
|
96
|
+
get frontend_handled_methods() {
|
|
97
|
+
return this.frontend_handled_specs.map((spec) => spec.method);
|
|
52
98
|
}
|
|
53
|
-
get
|
|
54
|
-
return this.
|
|
99
|
+
get backend_handled_methods() {
|
|
100
|
+
return this.backend_handled_specs.map((spec) => spec.method);
|
|
55
101
|
}
|
|
56
|
-
|
|
57
|
-
|
|
102
|
+
// --- Broadcast / backend-initiated getters ---
|
|
103
|
+
// Excludes `streams` targets (request-scoped progress notifications
|
|
104
|
+
// invoked via `ctx.notify` inside the parent handler). Today
|
|
105
|
+
// `broadcast_*` and `backend_initiated_*` return the same set;
|
|
106
|
+
// `backend_initiated_*` is the forward-looking name that will widen
|
|
107
|
+
// when local_calls or backend-initiated `request_response` join.
|
|
108
|
+
get broadcast_specs() {
|
|
109
|
+
const streams_targets = this.#get_streams_target_methods();
|
|
110
|
+
return this.remote_notification_specs.filter((spec) => spec.initiator !== 'frontend' && !streams_targets.has(spec.method));
|
|
58
111
|
}
|
|
59
|
-
get
|
|
60
|
-
return this.
|
|
112
|
+
get broadcast_methods() {
|
|
113
|
+
return this.broadcast_specs.map((spec) => spec.method);
|
|
61
114
|
}
|
|
62
|
-
get
|
|
63
|
-
|
|
115
|
+
get backend_initiated_specs() {
|
|
116
|
+
const streams_targets = this.#get_streams_target_methods();
|
|
117
|
+
return this.specs.filter((spec) => spec.initiator !== 'frontend' && !streams_targets.has(spec.method));
|
|
64
118
|
}
|
|
65
|
-
get
|
|
66
|
-
return this.
|
|
119
|
+
get backend_initiated_methods() {
|
|
120
|
+
return this.backend_initiated_specs.map((spec) => spec.method);
|
|
67
121
|
}
|
|
68
|
-
|
|
69
|
-
|
|
122
|
+
// --- Initiator-direction (pre-built, unused by codegen today) ---
|
|
123
|
+
get backend_to_frontend_specs() {
|
|
124
|
+
return this.specs.filter((spec) => spec.initiator === 'backend' || spec.initiator === 'both');
|
|
125
|
+
}
|
|
126
|
+
get frontend_to_backend_specs() {
|
|
127
|
+
return this.specs.filter((spec) => spec.initiator === 'frontend' || spec.initiator === 'both');
|
|
70
128
|
}
|
|
71
129
|
get frontend_to_backend_methods() {
|
|
72
130
|
return this.frontend_to_backend_specs.map((spec) => spec.method);
|
|
@@ -74,10 +132,29 @@ export class ActionRegistry {
|
|
|
74
132
|
get backend_to_frontend_methods() {
|
|
75
133
|
return this.backend_to_frontend_specs.map((spec) => spec.method);
|
|
76
134
|
}
|
|
135
|
+
// --- Auth (pre-built, unused by codegen today) ---
|
|
136
|
+
get public_specs() {
|
|
137
|
+
return this.specs.filter((spec) => spec.auth === 'public');
|
|
138
|
+
}
|
|
139
|
+
get authenticated_specs() {
|
|
140
|
+
return this.specs.filter((spec) => spec.auth === 'authenticated');
|
|
141
|
+
}
|
|
77
142
|
get public_methods() {
|
|
78
143
|
return this.public_specs.map((spec) => spec.method);
|
|
79
144
|
}
|
|
80
145
|
get authenticated_methods() {
|
|
81
146
|
return this.authenticated_specs.map((spec) => spec.method);
|
|
82
147
|
}
|
|
148
|
+
// --- Internal ---
|
|
149
|
+
#streams_target_methods;
|
|
150
|
+
#get_streams_target_methods() {
|
|
151
|
+
if (this.#streams_target_methods)
|
|
152
|
+
return this.#streams_target_methods;
|
|
153
|
+
const targets = new Set();
|
|
154
|
+
for (const spec of this.specs) {
|
|
155
|
+
if (spec.streams)
|
|
156
|
+
targets.add(spec.streams);
|
|
157
|
+
}
|
|
158
|
+
return (this.#streams_target_methods = targets);
|
|
159
|
+
}
|
|
83
160
|
}
|