@fuzdev/fuz_app 0.52.0 → 0.54.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 +29 -9
- package/dist/actions/action_codegen.d.ts +10 -35
- package/dist/actions/action_codegen.d.ts.map +1 -1
- package/dist/actions/action_codegen.js +13 -42
- package/dist/actions/action_peer.d.ts.map +1 -1
- package/dist/actions/action_peer.js +0 -9
- package/dist/actions/action_registry.d.ts +0 -4
- package/dist/actions/action_registry.d.ts.map +1 -1
- package/dist/actions/action_registry.js +4 -10
- package/dist/actions/action_rpc.d.ts +16 -0
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +41 -20
- package/dist/actions/action_spec.d.ts +54 -5
- package/dist/actions/action_spec.d.ts.map +1 -1
- package/dist/actions/action_spec.js +21 -5
- package/dist/actions/frontend_rpc_client.d.ts +1 -9
- package/dist/actions/frontend_rpc_client.d.ts.map +1 -1
- package/dist/actions/frontend_rpc_client.js +1 -9
- package/dist/actions/register_action_ws.d.ts +16 -0
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +41 -1
- package/dist/actions/request_tracker.svelte.d.ts +10 -15
- package/dist/actions/request_tracker.svelte.d.ts.map +1 -1
- package/dist/actions/request_tracker.svelte.js +10 -15
- package/dist/actions/rpc_client.d.ts +0 -1
- package/dist/actions/rpc_client.d.ts.map +1 -1
- package/dist/actions/rpc_client.js +3 -17
- package/dist/actions/socket.svelte.d.ts +0 -1
- package/dist/actions/socket.svelte.d.ts.map +1 -1
- package/dist/actions/socket.svelte.js +0 -1
- package/dist/actions/transports.d.ts +4 -3
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports.js +4 -13
- package/dist/actions/transports_ws_auth_guard.d.ts +0 -2
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_auth_guard.js +0 -2
- package/dist/actions/transports_ws_backend.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.js +0 -9
- package/dist/auth/CLAUDE.md +43 -19
- package/dist/auth/account_queries.d.ts +0 -3
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +0 -3
- package/dist/auth/admin_action_specs.d.ts +5 -0
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +5 -0
- package/dist/auth/api_token_queries.d.ts +0 -1
- package/dist/auth/api_token_queries.d.ts.map +1 -1
- package/dist/auth/api_token_queries.js +0 -1
- package/dist/auth/audit_log_queries.d.ts +0 -1
- package/dist/auth/audit_log_queries.d.ts.map +1 -1
- package/dist/auth/audit_log_queries.js +0 -1
- package/dist/auth/audit_log_routes.d.ts +2 -2
- package/dist/auth/audit_log_routes.js +2 -2
- package/dist/auth/invite_queries.d.ts +0 -1
- package/dist/auth/invite_queries.d.ts.map +1 -1
- package/dist/auth/invite_queries.js +0 -1
- package/dist/auth/permit_offer_action_specs.d.ts +1 -0
- package/dist/auth/permit_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/permit_offer_action_specs.js +1 -0
- package/dist/auth/permit_offer_actions.d.ts.map +1 -1
- package/dist/auth/permit_offer_actions.js +9 -6
- package/dist/auth/permit_offer_queries.d.ts +0 -1
- package/dist/auth/permit_offer_queries.d.ts.map +1 -1
- package/dist/auth/permit_offer_queries.js +0 -1
- package/dist/auth/permit_queries.d.ts +0 -1
- package/dist/auth/permit_queries.d.ts.map +1 -1
- package/dist/auth/permit_queries.js +0 -1
- package/dist/auth/request_context.d.ts +47 -2
- package/dist/auth/request_context.d.ts.map +1 -1
- package/dist/auth/request_context.js +57 -2
- package/dist/auth/self_service_role_actions.d.ts.map +1 -1
- package/dist/auth/self_service_role_actions.js +14 -11
- package/dist/auth/session_lifecycle.d.ts +0 -1
- package/dist/auth/session_lifecycle.d.ts.map +1 -1
- package/dist/auth/session_lifecycle.js +0 -1
- package/dist/auth/session_middleware.d.ts +0 -4
- package/dist/auth/session_middleware.d.ts.map +1 -1
- package/dist/auth/session_middleware.js +0 -4
- package/dist/cli/config.d.ts +0 -3
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +0 -3
- package/dist/cli/daemon.d.ts +1 -1
- package/dist/cli/daemon.js +1 -1
- package/dist/db/create_db.d.ts +0 -1
- package/dist/db/create_db.d.ts.map +1 -1
- package/dist/db/create_db.js +0 -1
- package/dist/db/db.d.ts +0 -4
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +0 -4
- package/dist/db/db_pg.d.ts +2 -2
- package/dist/db/db_pg.js +2 -2
- package/dist/db/db_pglite.d.ts +1 -2
- package/dist/db/db_pglite.d.ts.map +1 -1
- package/dist/db/db_pglite.js +1 -2
- package/dist/db/migrate.d.ts +0 -1
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +0 -1
- package/dist/dev/setup.d.ts +0 -3
- package/dist/dev/setup.d.ts.map +1 -1
- package/dist/dev/setup.js +0 -3
- package/dist/env/load.d.ts +0 -2
- package/dist/env/load.d.ts.map +1 -1
- package/dist/env/load.js +0 -2
- package/dist/hono_context.d.ts +2 -5
- package/dist/hono_context.d.ts.map +1 -1
- package/dist/hono_context.js +2 -5
- package/dist/http/common_routes.d.ts +0 -8
- package/dist/http/common_routes.d.ts.map +1 -1
- package/dist/http/common_routes.js +0 -8
- package/dist/http/db_routes.d.ts +0 -3
- package/dist/http/db_routes.d.ts.map +1 -1
- package/dist/http/db_routes.js +0 -3
- package/dist/http/error_schemas.d.ts +12 -11
- package/dist/http/error_schemas.d.ts.map +1 -1
- package/dist/http/error_schemas.js +11 -7
- package/dist/http/jsonrpc_errors.d.ts +0 -6
- package/dist/http/jsonrpc_errors.d.ts.map +1 -1
- package/dist/http/jsonrpc_errors.js +0 -6
- package/dist/http/origin.d.ts +6 -13
- package/dist/http/origin.d.ts.map +1 -1
- package/dist/http/origin.js +7 -14
- package/dist/http/proxy.d.ts +1 -7
- package/dist/http/proxy.d.ts.map +1 -1
- package/dist/http/proxy.js +1 -7
- package/dist/http/route_spec.d.ts +13 -35
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/route_spec.js +10 -22
- package/dist/http/schema_helpers.d.ts +0 -4
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +0 -4
- package/dist/http/surface.d.ts +2 -12
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +1 -12
- package/dist/rate_limiter.d.ts +16 -0
- package/dist/rate_limiter.d.ts.map +1 -1
- package/dist/rate_limiter.js +26 -0
- package/dist/realtime/sse.d.ts +0 -1
- package/dist/realtime/sse.d.ts.map +1 -1
- package/dist/realtime/sse.js +0 -1
- package/dist/realtime/subscriber_registry.d.ts +0 -3
- package/dist/realtime/subscriber_registry.d.ts.map +1 -1
- package/dist/realtime/subscriber_registry.js +0 -3
- package/dist/runtime/fs.d.ts +1 -4
- package/dist/runtime/fs.d.ts.map +1 -1
- package/dist/runtime/fs.js +1 -4
- package/dist/runtime/mock.d.ts +0 -3
- package/dist/runtime/mock.d.ts.map +1 -1
- package/dist/runtime/mock.js +0 -3
- package/dist/server/app_server.d.ts +27 -5
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +19 -7
- package/dist/server/startup.d.ts +0 -2
- package/dist/server/startup.d.ts.map +1 -1
- package/dist/server/startup.js +0 -2
- package/dist/server/static.d.ts +0 -1
- package/dist/server/static.d.ts.map +1 -1
- package/dist/server/static.js +0 -1
- package/dist/server/validate_nginx.d.ts +0 -3
- package/dist/server/validate_nginx.d.ts.map +1 -1
- package/dist/server/validate_nginx.js +0 -3
- package/dist/testing/CLAUDE.md +1 -1
- package/dist/testing/admin_integration.d.ts +0 -1
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +3 -6
- package/dist/testing/adversarial_404.d.ts +0 -2
- package/dist/testing/adversarial_404.d.ts.map +1 -1
- package/dist/testing/adversarial_404.js +0 -2
- package/dist/testing/adversarial_headers.d.ts +0 -1
- package/dist/testing/adversarial_headers.d.ts.map +1 -1
- package/dist/testing/adversarial_headers.js +0 -1
- package/dist/testing/adversarial_input.d.ts +0 -2
- package/dist/testing/adversarial_input.d.ts.map +1 -1
- package/dist/testing/adversarial_input.js +0 -2
- package/dist/testing/app_server.d.ts +22 -0
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +2 -4
- package/dist/testing/assertions.d.ts +0 -4
- package/dist/testing/assertions.d.ts.map +1 -1
- package/dist/testing/assertions.js +0 -4
- package/dist/testing/attack_surface.d.ts +0 -4
- package/dist/testing/attack_surface.d.ts.map +1 -1
- package/dist/testing/attack_surface.js +0 -4
- package/dist/testing/audit_completeness.d.ts +0 -1
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +0 -1
- package/dist/testing/auth_apps.d.ts +2 -10
- package/dist/testing/auth_apps.d.ts.map +1 -1
- package/dist/testing/auth_apps.js +2 -10
- package/dist/testing/data_exposure.d.ts +0 -11
- package/dist/testing/data_exposure.d.ts.map +1 -1
- package/dist/testing/data_exposure.js +0 -11
- package/dist/testing/db.d.ts +0 -6
- package/dist/testing/db.d.ts.map +1 -1
- package/dist/testing/db.js +0 -6
- package/dist/testing/error_coverage.d.ts +0 -14
- package/dist/testing/error_coverage.d.ts.map +1 -1
- package/dist/testing/error_coverage.js +0 -14
- package/dist/testing/integration.d.ts +0 -1
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +0 -1
- package/dist/testing/integration_helpers.d.ts +1 -36
- package/dist/testing/integration_helpers.d.ts.map +1 -1
- package/dist/testing/integration_helpers.js +1 -43
- package/dist/testing/middleware.d.ts +0 -10
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +0 -10
- package/dist/testing/mock_fs.d.ts +0 -2
- package/dist/testing/mock_fs.d.ts.map +1 -1
- package/dist/testing/mock_fs.js +0 -2
- package/dist/testing/rate_limiting.d.ts +0 -1
- package/dist/testing/rate_limiting.d.ts.map +1 -1
- package/dist/testing/rate_limiting.js +0 -1
- package/dist/testing/round_trip.d.ts +0 -2
- package/dist/testing/round_trip.d.ts.map +1 -1
- package/dist/testing/round_trip.js +0 -2
- package/dist/testing/rpc_attack_surface.d.ts +0 -2
- package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
- package/dist/testing/rpc_attack_surface.js +0 -2
- package/dist/testing/rpc_helpers.d.ts +0 -6
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_helpers.js +0 -6
- package/dist/testing/rpc_round_trip.d.ts +0 -2
- package/dist/testing/rpc_round_trip.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.js +0 -2
- package/dist/testing/schema_generators.d.ts +0 -3
- package/dist/testing/schema_generators.d.ts.map +1 -1
- package/dist/testing/schema_generators.js +29 -3
- package/dist/testing/sse_round_trip.d.ts +0 -1
- package/dist/testing/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/sse_round_trip.js +0 -1
- package/dist/testing/standard.d.ts +0 -2
- package/dist/testing/standard.d.ts.map +1 -1
- package/dist/testing/standard.js +0 -2
- package/dist/testing/stubs.d.ts +3 -5
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +5 -5
- package/dist/testing/surface_invariants.d.ts +0 -3
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +0 -3
- package/dist/ui/CLAUDE.md +1 -1
- package/dist/ui/audit_log_state.svelte.js +1 -1
- package/dist/ui/position_helpers.d.ts +0 -3
- package/dist/ui/position_helpers.d.ts.map +1 -1
- package/dist/ui/position_helpers.js +0 -3
- package/dist/ui/sidebar_state.svelte.d.ts +1 -2
- package/dist/ui/sidebar_state.svelte.d.ts.map +1 -1
- package/dist/ui/sidebar_state.svelte.js +1 -2
- package/dist/ui/ui_fetch.d.ts +1 -7
- package/dist/ui/ui_fetch.d.ts.map +1 -1
- package/dist/ui/ui_fetch.js +1 -7
- package/dist/ui/ui_format.d.ts +2 -14
- package/dist/ui/ui_format.d.ts.map +1 -1
- package/dist/ui/ui_format.js +2 -14
- package/package.json +2 -2
package/dist/actions/CLAUDE.md
CHANGED
|
@@ -19,10 +19,10 @@ IMPORTANT: Every exported Zod schema is paired with a same-named `z.infer`
|
|
|
19
19
|
type export. When adding new schemas, keep the pair invariant — it is the
|
|
20
20
|
convention callers rely on for type imports.
|
|
21
21
|
|
|
22
|
-
NOTE:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
NOTE: `ActionRegistry` keeps a few pre-built getters (auth filters,
|
|
23
|
+
initiator-direction filters) that codegen doesn't consume today — kept
|
|
24
|
+
low-cost for future filtering. Bridge, RPC endpoint, and per-derivation
|
|
25
|
+
codegen helpers are post-SAES-RPC-closeout stable.
|
|
26
26
|
|
|
27
27
|
## Action specs (`action_spec.ts`)
|
|
28
28
|
|
|
@@ -60,6 +60,23 @@ the same `as const` string constants the handler throws (e.g.
|
|
|
60
60
|
sites can import either side. Standard transport errors (validation,
|
|
61
61
|
auth, rate-limit) stay implicit.
|
|
62
62
|
|
|
63
|
+
Optional `rate_limit?: 'ip' | 'account' | 'both'` opts the action into
|
|
64
|
+
the dispatcher's per-action rate-limit hook. Same hook fires on the HTTP
|
|
65
|
+
RPC dispatcher (`create_rpc_endpoint`) and the WebSocket dispatcher
|
|
66
|
+
(`register_action_ws`) — one budget per action, not per transport.
|
|
67
|
+
`'ip'` keys on the resolved client IP; `'account'` keys on
|
|
68
|
+
`request_context.actor.id` (post-auth) and is rejected at registration
|
|
69
|
+
when paired with `auth: 'public'` (no actor to key on); `'both'` runs
|
|
70
|
+
both checks. **Throttle-requests semantics** — every invocation records,
|
|
71
|
+
regardless of outcome (different from REST login's throttle-failures
|
|
72
|
+
that resets on success). The motivating threat is admin mutation oracles
|
|
73
|
+
(`invite_create` account-existence probe) where the _successful_
|
|
74
|
+
invocation is the threat. Limiters are configured at server-assembly
|
|
75
|
+
time via `AppServerOptions.action_ip_rate_limiter` /
|
|
76
|
+
`action_account_rate_limiter` and threaded into both dispatchers
|
|
77
|
+
automatically; consumers wiring `register_action_ws` directly forward
|
|
78
|
+
the same limiters from `AppServerContext`.
|
|
79
|
+
|
|
63
80
|
Canonical spec shape: module-scope declaration with `satisfies` +
|
|
64
81
|
`{method}_action_spec` naming, preserving the literal `method` type and
|
|
65
82
|
dropping per-spec `*_METHOD` constants (readers dereference `.method` at
|
|
@@ -93,8 +110,11 @@ The remaining asymmetry today is runtime: there is no
|
|
|
93
110
|
`create_backend_rpc_client` and `create_broadcast_api` returns
|
|
94
111
|
`Promise<void>` (fire-and-forget broadcast) rather than the
|
|
95
112
|
`Promise<Result<{value}, {error}>>` shape `FrontendActionsApi` methods
|
|
96
|
-
return. Closing those gaps is
|
|
97
|
-
|
|
113
|
+
return. Closing those gaps is on the deferred follow-up set in the
|
|
114
|
+
[SAES RPC closeout](https://github.com/ryanatkn/grimoire/blob/main/quests/HISTORY.md#saes-rpc-direction-2026-04)
|
|
115
|
+
(grimoire `lore/fuz_app/TODO.md` § Future Directions tracks the symmetric
|
|
116
|
+
backend signature, backend RPC client, and local-call symmetry items) —
|
|
117
|
+
wait for a second backend runtime case.
|
|
98
118
|
|
|
99
119
|
`ActionRegistry(specs)` is a query/filter wrapper over `ActionSpecUnion[]`.
|
|
100
120
|
Codegen-used getter groups:
|
|
@@ -118,8 +138,8 @@ Codegen-used getter groups:
|
|
|
118
138
|
`request_response` join): `backend_initiated_specs`,
|
|
119
139
|
`backend_initiated_methods`.
|
|
120
140
|
|
|
121
|
-
Other getters (auth, initiator-direction) are pre-built
|
|
122
|
-
|
|
141
|
+
Other getters (auth filters, initiator-direction filters) are pre-built
|
|
142
|
+
API surface unused by codegen today.
|
|
123
143
|
|
|
124
144
|
`action_codegen.ts` provides gen helpers (used by consumer `*.gen.ts` files,
|
|
125
145
|
not the runtime):
|
|
@@ -189,7 +209,7 @@ and `FrontendActionHandlers`.
|
|
|
189
209
|
- `generate_action_event_datas(specs, imports, {same_file?, collections_path?, include_protocol_actions?})` — `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.
|
|
190
210
|
- `generate_frontend_actions_api(specs, imports, {interface_name?, method_filter?, collections_path?, sync_returns_value?, include_protocol_actions?})` — emits the typed `FrontendActionsApi` interface (configurable via `interface_name`, default `'FrontendActionsApi'`). One method signature per spec via `generate_actions_api_method_signature`. Protocol actions filtered by default; `method_filter: (spec) => boolean` runs after the protocol-action filter. Renamed from `generate_actions_api` in API review III to make the side-of-the-wire intent visible at every consumer site.
|
|
191
211
|
- `generate_frontend_action_handlers(specs, imports, {collections_path?, include_protocol_actions?})` — `FrontendActionHandlers` interface (Tier 2 only — wraps `generate_phase_handlers` with `action_event_type: 'TypedActionEvent'`). Pair with `generate_typed_action_event_alias`.
|
|
192
|
-
- `generate_backend_actions_api(specs, imports, {interface_name?, spec_array_name?, specs_module?, collections_path?, qualify_spec?, include_protocol_actions?})` — `BackendActionsApi` interface AND `broadcast_action_specs: ReadonlyArray<ActionSpecUnion>` array (both names configurable). Filter: `kind === 'remote_notification' && initiator !== 'frontend'`, with `streams`-target methods (request-scoped progress notifications invoked via `ctx.notify`) excluded — the discriminator is `ActionSpec.streams`, not a manual list. Adds `ActionInputs` (from `collections_path`) + `ActionSpecUnion`, plus `* as specs` from `specs_module` unless `qualify_spec` is set. Method shape today is `(input) => Promise<void>` (matches `create_broadcast_api`'s fire-and-forget runtime); generalizing to per-kind shapes via `generate_actions_api_method_signature` is deferred until a second backend runtime constructor lands (
|
|
212
|
+
- `generate_backend_actions_api(specs, imports, {interface_name?, spec_array_name?, specs_module?, collections_path?, qualify_spec?, include_protocol_actions?})` — `BackendActionsApi` interface AND `broadcast_action_specs: ReadonlyArray<ActionSpecUnion>` array (both names configurable). Filter: `kind === 'remote_notification' && initiator !== 'frontend'`, with `streams`-target methods (request-scoped progress notifications invoked via `ctx.notify`) excluded — the discriminator is `ActionSpec.streams`, not a manual list. Adds `ActionInputs` (from `collections_path`) + `ActionSpecUnion`, plus `* as specs` from `specs_module` unless `qualify_spec` is set. Method shape today is `(input) => Promise<void>` (matches `create_broadcast_api`'s fire-and-forget runtime); generalizing to per-kind shapes via `generate_actions_api_method_signature` is deferred until a second backend runtime constructor lands (tracked in grimoire `lore/fuz_app/TODO.md` § Future Directions, _Symmetric backend signature shape_).
|
|
193
213
|
- `generate_backend_action_handlers_map(imports, options?)` — emits the `BackendActionHandlers` mapped type (`{[K in BackendRequestResponseMethod]: (input: ActionInputs[K], ctx: BackendHandlerContext) => ActionOutputs[K] | Promise<ActionOutputs[K]>}`). Replaces the hand-maintained `Exclude<>` + parallel mapped-type pattern (zzz had this at `zzz/src/lib/server/zzz_action_handlers.ts:42-66`). Configurable type name, method enum name, and context type name; configurable `collections_path` / `metatypes_path` for the type imports.
|
|
194
214
|
|
|
195
215
|
### Wrapper + multi-source helper
|
|
@@ -22,9 +22,6 @@ export type ProtocolActionMethod = (typeof PROTOCOL_ACTION_METHODS)[number];
|
|
|
22
22
|
* });
|
|
23
23
|
*/
|
|
24
24
|
export declare const is_protocol_action_method: (method: string) => method is ProtocolActionMethod;
|
|
25
|
-
/**
|
|
26
|
-
* Represents an import item with its kind (type, value, or namespace).
|
|
27
|
-
*/
|
|
28
25
|
interface ImportItem {
|
|
29
26
|
name: string;
|
|
30
27
|
kind: 'type' | 'value' | 'namespace';
|
|
@@ -56,47 +53,31 @@ export declare class ImportBuilder {
|
|
|
56
53
|
#private;
|
|
57
54
|
imports: Map<string, Map<string, ImportItem>>;
|
|
58
55
|
/**
|
|
59
|
-
* Add a value import
|
|
60
|
-
*
|
|
61
|
-
* @param what - what to import (value)
|
|
56
|
+
* Add a value import. Accepts `* as ns` strings as namespace imports.
|
|
57
|
+
*
|
|
62
58
|
* @returns `this` for chaining
|
|
63
59
|
* @mutates this - inserts into the internal `imports` map
|
|
64
60
|
*/
|
|
65
61
|
add(from: string, what: string): this;
|
|
66
62
|
/**
|
|
67
|
-
* Add a type import
|
|
68
|
-
*
|
|
69
|
-
* @param what - what to import (type)
|
|
63
|
+
* Add a type-only import.
|
|
64
|
+
*
|
|
70
65
|
* @returns `this` for chaining
|
|
71
66
|
* @mutates this - inserts into the internal `imports` map (downgrade to
|
|
72
67
|
* type is suppressed if already registered as a value)
|
|
73
68
|
*/
|
|
74
69
|
add_type(from: string, what: string): this;
|
|
75
|
-
/**
|
|
76
|
-
* Add multiple value imports from the same module.
|
|
77
|
-
*/
|
|
78
70
|
add_many(from: string, ...items: Array<string>): this;
|
|
79
|
-
/**
|
|
80
|
-
* Add multiple type imports from the same module.
|
|
81
|
-
*/
|
|
82
71
|
add_types(from: string, ...items: Array<string>): this;
|
|
83
72
|
/**
|
|
84
|
-
* Generate the import statements.
|
|
85
|
-
*
|
|
73
|
+
* Generate the import statements. When every import from a module is a
|
|
74
|
+
* type, emits `import type {…}` so the whole statement disappears at
|
|
75
|
+
* compile time.
|
|
86
76
|
*/
|
|
87
77
|
build(): string;
|
|
88
|
-
/**
|
|
89
|
-
* Check if the builder has any imports.
|
|
90
|
-
*/
|
|
91
78
|
has_imports(): boolean;
|
|
92
|
-
/**
|
|
93
|
-
* Get the number of import statements that will be generated.
|
|
94
|
-
*/
|
|
95
79
|
get import_count(): number;
|
|
96
|
-
/**
|
|
97
|
-
* Preview what imports will be generated (useful for debugging).
|
|
98
|
-
* @returns array of import statement strings
|
|
99
|
-
*/
|
|
80
|
+
/** Build the same statement list as `build` without joining — for inspection in tests. */
|
|
100
81
|
preview(): Array<string>;
|
|
101
82
|
/**
|
|
102
83
|
* Clear all imports.
|
|
@@ -106,9 +87,7 @@ export declare class ImportBuilder {
|
|
|
106
87
|
*/
|
|
107
88
|
clear(): this;
|
|
108
89
|
}
|
|
109
|
-
/**
|
|
110
|
-
* Determines which phases an executor can handle based on the action spec.
|
|
111
|
-
*/
|
|
90
|
+
/** Phases an executor can handle for the given spec — kind + initiator → set of phases. */
|
|
112
91
|
export declare const get_executor_phases: (spec: ActionSpecUnion, executor: "frontend" | "backend") => Array<ActionEventPhase>;
|
|
113
92
|
/** Default `collections_path` — every consumer's gen producers point at the sibling `action_collections.js`. */
|
|
114
93
|
export declare const DEFAULT_COLLECTIONS_PATH = "./action_collections.js";
|
|
@@ -144,9 +123,7 @@ export declare const generate_phase_handlers: (spec: ActionSpecUnion, executor:
|
|
|
144
123
|
action_event_type?: string;
|
|
145
124
|
collections_path?: string;
|
|
146
125
|
}) => string;
|
|
147
|
-
/**
|
|
148
|
-
* Creates a file banner comment.
|
|
149
|
-
*/
|
|
126
|
+
/** "DO NOT EDIT" banner naming the gen producer. */
|
|
150
127
|
export declare const create_banner: (origin_path: string) => string;
|
|
151
128
|
export declare const to_action_spec_identifier: (method: string) => string;
|
|
152
129
|
export declare const to_action_spec_input_identifier: (method: string) => string;
|
|
@@ -177,8 +154,6 @@ export declare const to_action_spec_output_identifier: (method: string) => strin
|
|
|
177
154
|
* follows so wrappers no longer pre-register imports a per-spec emit might
|
|
178
155
|
* not actually use.
|
|
179
156
|
*
|
|
180
|
-
* @param spec - the action spec to emit
|
|
181
|
-
* @param imports - import builder to register references on
|
|
182
157
|
* @param options.sync_returns_value - When true (default), sync `local_call`
|
|
183
158
|
* methods return the output value directly; when false they're wrapped in
|
|
184
159
|
* `Result<{value, error}>` like async methods. Set to `false` if your
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action_codegen.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_codegen.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,eAAe,EAAE,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAGxE;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,kCAAmC,CAAC;AAExE,8FAA8F;AAC9F,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAI5E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,GAAI,QAAQ,MAAM,KAAG,MAAM,IAAI,oBACrC,CAAC;AAEjC
|
|
1
|
+
{"version":3,"file":"action_codegen.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_codegen.ts"],"names":[],"mappings":"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"}
|
|
@@ -49,9 +49,8 @@ export const is_protocol_action_method = (method) => PROTOCOL_METHOD_SET.has(met
|
|
|
49
49
|
export class ImportBuilder {
|
|
50
50
|
imports = new Map();
|
|
51
51
|
/**
|
|
52
|
-
* Add a value import
|
|
53
|
-
*
|
|
54
|
-
* @param what - what to import (value)
|
|
52
|
+
* Add a value import. Accepts `* as ns` strings as namespace imports.
|
|
53
|
+
*
|
|
55
54
|
* @returns `this` for chaining
|
|
56
55
|
* @mutates this - inserts into the internal `imports` map
|
|
57
56
|
*/
|
|
@@ -63,9 +62,8 @@ export class ImportBuilder {
|
|
|
63
62
|
return this.#add_import(from, what, 'value');
|
|
64
63
|
}
|
|
65
64
|
/**
|
|
66
|
-
* Add a type import
|
|
67
|
-
*
|
|
68
|
-
* @param what - what to import (type)
|
|
65
|
+
* Add a type-only import.
|
|
66
|
+
*
|
|
69
67
|
* @returns `this` for chaining
|
|
70
68
|
* @mutates this - inserts into the internal `imports` map (downgrade to
|
|
71
69
|
* type is suppressed if already registered as a value)
|
|
@@ -73,27 +71,18 @@ export class ImportBuilder {
|
|
|
73
71
|
add_type(from, what) {
|
|
74
72
|
return this.#add_import(from, what, 'type');
|
|
75
73
|
}
|
|
76
|
-
/**
|
|
77
|
-
* Add multiple value imports from the same module.
|
|
78
|
-
*/
|
|
79
74
|
add_many(from, ...items) {
|
|
80
75
|
for (const item of items) {
|
|
81
76
|
this.add(from, item);
|
|
82
77
|
}
|
|
83
78
|
return this;
|
|
84
79
|
}
|
|
85
|
-
/**
|
|
86
|
-
* Add multiple type imports from the same module.
|
|
87
|
-
*/
|
|
88
80
|
add_types(from, ...items) {
|
|
89
81
|
for (const item of items) {
|
|
90
82
|
this.add_type(from, item);
|
|
91
83
|
}
|
|
92
84
|
return this;
|
|
93
85
|
}
|
|
94
|
-
/**
|
|
95
|
-
* Internal method to add an import with its kind.
|
|
96
|
-
*/
|
|
97
86
|
#add_import(from, name, kind) {
|
|
98
87
|
// Skip empty imports
|
|
99
88
|
if (!name || (kind !== 'namespace' && name === '')) {
|
|
@@ -112,28 +101,20 @@ export class ImportBuilder {
|
|
|
112
101
|
return this;
|
|
113
102
|
}
|
|
114
103
|
/**
|
|
115
|
-
* Generate the import statements.
|
|
116
|
-
*
|
|
104
|
+
* Generate the import statements. When every import from a module is a
|
|
105
|
+
* type, emits `import type {…}` so the whole statement disappears at
|
|
106
|
+
* compile time.
|
|
117
107
|
*/
|
|
118
108
|
build() {
|
|
119
109
|
return this.#generate_import_statements().join('\n');
|
|
120
110
|
}
|
|
121
|
-
/**
|
|
122
|
-
* Check if the builder has any imports.
|
|
123
|
-
*/
|
|
124
111
|
has_imports() {
|
|
125
112
|
return this.imports.size > 0;
|
|
126
113
|
}
|
|
127
|
-
/**
|
|
128
|
-
* Get the number of import statements that will be generated.
|
|
129
|
-
*/
|
|
130
114
|
get import_count() {
|
|
131
115
|
return this.imports.size;
|
|
132
116
|
}
|
|
133
|
-
/**
|
|
134
|
-
* Preview what imports will be generated (useful for debugging).
|
|
135
|
-
* @returns array of import statement strings
|
|
136
|
-
*/
|
|
117
|
+
/** Build the same statement list as `build` without joining — for inspection in tests. */
|
|
137
118
|
preview() {
|
|
138
119
|
return this.#generate_import_statements();
|
|
139
120
|
}
|
|
@@ -147,10 +128,6 @@ export class ImportBuilder {
|
|
|
147
128
|
this.imports.clear();
|
|
148
129
|
return this;
|
|
149
130
|
}
|
|
150
|
-
/**
|
|
151
|
-
* Internal helper to generate import statements from the current state.
|
|
152
|
-
* Shared by both build() and preview() methods.
|
|
153
|
-
*/
|
|
154
131
|
#generate_import_statements() {
|
|
155
132
|
const statements = [];
|
|
156
133
|
for (const [from, module_imports] of this.imports) {
|
|
@@ -193,9 +170,7 @@ export class ImportBuilder {
|
|
|
193
170
|
return statements;
|
|
194
171
|
}
|
|
195
172
|
}
|
|
196
|
-
/**
|
|
197
|
-
* Determines which phases an executor can handle based on the action spec.
|
|
198
|
-
*/
|
|
173
|
+
/** Phases an executor can handle for the given spec — kind + initiator → set of phases. */
|
|
199
174
|
export const get_executor_phases = (spec, executor) => {
|
|
200
175
|
const { kind, initiator } = spec;
|
|
201
176
|
const phases = [];
|
|
@@ -222,9 +197,9 @@ export const get_executor_phases = (spec, executor) => {
|
|
|
222
197
|
}
|
|
223
198
|
if (can_receive) {
|
|
224
199
|
phases.push('receive_request', 'send_response');
|
|
225
|
-
// TODO
|
|
226
|
-
// (already
|
|
227
|
-
//
|
|
200
|
+
// TODO consolidate — `send_error` is added redundantly when
|
|
201
|
+
// initiator:'both' (already pushed above); the trailing Set dedup
|
|
202
|
+
// handles it.
|
|
228
203
|
phases.push('send_error');
|
|
229
204
|
}
|
|
230
205
|
break;
|
|
@@ -323,9 +298,7 @@ export const generate_phase_handlers = (spec, executor, imports, options) => {
|
|
|
323
298
|
.join(';\n\t\t');
|
|
324
299
|
return `${method}?: {\n\t\t${phase_handlers};\n\t}`;
|
|
325
300
|
};
|
|
326
|
-
/**
|
|
327
|
-
* Creates a file banner comment.
|
|
328
|
-
*/
|
|
301
|
+
/** "DO NOT EDIT" banner naming the gen producer. */
|
|
329
302
|
export const create_banner = (origin_path) => `generated by ${origin_path} - DO NOT EDIT OR RISK LOST DATA`;
|
|
330
303
|
// TODO rethink these, see also zzz `codegen.ts`
|
|
331
304
|
export const to_action_spec_identifier = (method) => `${method}_action_spec`;
|
|
@@ -357,8 +330,6 @@ export const to_action_spec_output_identifier = (method) => `${to_action_spec_id
|
|
|
357
330
|
* follows so wrappers no longer pre-register imports a per-spec emit might
|
|
358
331
|
* not actually use.
|
|
359
332
|
*
|
|
360
|
-
* @param spec - the action spec to emit
|
|
361
|
-
* @param imports - import builder to register references on
|
|
362
333
|
* @param options.sync_returns_value - When true (default), sync `local_call`
|
|
363
334
|
* methods return the output value directly; when false they're wrapped in
|
|
364
335
|
* `Result<{value, error}>` like async methods. Set to `false` if your
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action_peer.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_peer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEN,gCAAgC,EAChC,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,EAAC,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAC,MAAM,iBAAiB,CAAC;AAC1F,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AAOpE;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAsB,SAAQ,oBAAoB;IAClE,cAAc,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IACjC,WAAW,EAAE,sBAAsB,CAAC;IAGpC,UAAU,CAAC,EAAE,UAAU,CAAC;IAKxB,oBAAoB,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;CAC7D;AAED,qBAAa,UAAU;;IACtB,QAAQ,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC7C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAMhC,oBAAoB,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;gBAEhD,OAAO,EAAE,iBAAiB;IAMtC;;;;;;;;OAQG;IAEG,IAAI,CACT,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,sBAAsB,CAAC;IAC5B,IAAI,CACT,OAAO,EAAE,mBAAmB,EAC5B,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IA8CvC;;;;;;;OAOG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,gCAAgC,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"action_peer.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_peer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEN,gCAAgC,EAChC,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,EAAC,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAC,MAAM,iBAAiB,CAAC;AAC1F,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AAOpE;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAsB,SAAQ,oBAAoB;IAClE,cAAc,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IACjC,WAAW,EAAE,sBAAsB,CAAC;IAGpC,UAAU,CAAC,EAAE,UAAU,CAAC;IAKxB,oBAAoB,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;CAC7D;AAED,qBAAa,UAAU;;IACtB,QAAQ,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC7C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAMhC,oBAAoB,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;gBAEhD,OAAO,EAAE,iBAAiB;IAMtC;;;;;;;;OAQG;IAEG,IAAI,CACT,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,sBAAsB,CAAC;IAC5B,IAAI,CACT,OAAO,EAAE,mBAAmB,EAC5B,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IA8CvC;;;;;;;OAOG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,gCAAgC,GAAG,IAAI,CAAC;CAgIjF"}
|
|
@@ -67,9 +67,6 @@ export class ActionPeer {
|
|
|
67
67
|
return create_jsonrpc_error_response_from_thrown(to_jsonrpc_message_id(message), error);
|
|
68
68
|
} // TODO finally?
|
|
69
69
|
}
|
|
70
|
-
/**
|
|
71
|
-
* Processes a single JSON-RPC message, returning a response message if any.
|
|
72
|
-
*/
|
|
73
70
|
async #receive_message(message) {
|
|
74
71
|
if (is_jsonrpc_request(message)) {
|
|
75
72
|
return this.#receive_request(message);
|
|
@@ -82,9 +79,6 @@ export class ActionPeer {
|
|
|
82
79
|
return create_jsonrpc_error_response(to_jsonrpc_message_id(message), jsonrpc_error_messages.invalid_request());
|
|
83
80
|
}
|
|
84
81
|
}
|
|
85
|
-
/**
|
|
86
|
-
* Processes a JSON-RPC request. Returns the response message.
|
|
87
|
-
*/
|
|
88
82
|
async #receive_request(request) {
|
|
89
83
|
const spec = this.environment.lookup_action_spec(request.method);
|
|
90
84
|
if (!spec) {
|
|
@@ -130,9 +124,6 @@ export class ActionPeer {
|
|
|
130
124
|
return create_jsonrpc_error_response_from_thrown(request.id, error);
|
|
131
125
|
}
|
|
132
126
|
}
|
|
133
|
-
/**
|
|
134
|
-
* Processes a JSON-RPC notification. Returns nothing, no response exists.
|
|
135
|
-
*/
|
|
136
127
|
async #receive_notification(notification) {
|
|
137
128
|
const spec = this.environment.lookup_action_spec(notification.method);
|
|
138
129
|
if (!spec) {
|
|
@@ -27,10 +27,6 @@
|
|
|
27
27
|
* @module
|
|
28
28
|
*/
|
|
29
29
|
import type { ActionSpecUnion, RequestResponseActionSpec, RemoteNotificationActionSpec, LocalCallActionSpec } from './action_spec.js';
|
|
30
|
-
/**
|
|
31
|
-
* Utility class to manage and query action specifications.
|
|
32
|
-
* Provides helper methods to get actions by various criteria.
|
|
33
|
-
*/
|
|
34
30
|
export declare class ActionRegistry {
|
|
35
31
|
#private;
|
|
36
32
|
readonly specs: Array<ActionSpecUnion>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action_registry.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EACX,eAAe,EACf,yBAAyB,EACzB,4BAA4B,EAC5B,mBAAmB,EACnB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"action_registry.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EACX,eAAe,EACf,yBAAyB,EACzB,4BAA4B,EAC5B,mBAAmB,EACnB,MAAM,kBAAkB,CAAC;AAO1B,qBAAa,cAAc;;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;gBAE3B,KAAK,EAAE,KAAK,CAAC,eAAe,CAAC;IAKzC,IAAI,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAEjD;IAED,IAAI,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,CAE3B;IAID,IAAI,sBAAsB,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAE7D;IAED,IAAI,yBAAyB,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAEnE;IAED,IAAI,gBAAgB,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAEjD;IAED,IAAI,wBAAwB,IAAI,KAAK,CAAC,MAAM,CAAC,CAE5C;IAED,IAAI,2BAA2B,IAAI,KAAK,CAAC,MAAM,CAAC,CAE/C;IAED,IAAI,kBAAkB,IAAI,KAAK,CAAC,MAAM,CAAC,CAEtC;IAOD,IAAI,0BAA0B,IAAI,KAAK,CAAC,eAAe,CAAC,CAEvD;IAED,IAAI,yBAAyB,IAAI,KAAK,CAAC,eAAe,CAAC,CAEtD;IAED,IAAI,4BAA4B,IAAI,KAAK,CAAC,MAAM,CAAC,CAEhD;IAED,IAAI,2BAA2B,IAAI,KAAK,CAAC,MAAM,CAAC,CAE/C;IAOD,IAAI,sBAAsB,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAE7D;IAED,IAAI,qBAAqB,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAE5D;IAED,IAAI,wBAAwB,IAAI,KAAK,CAAC,MAAM,CAAC,CAE5C;IAED,IAAI,uBAAuB,IAAI,KAAK,CAAC,MAAM,CAAC,CAE3C;IASD,IAAI,eAAe,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAKzD;IAED,IAAI,iBAAiB,IAAI,KAAK,CAAC,MAAM,CAAC,CAErC;IAED,IAAI,uBAAuB,IAAI,KAAK,CAAC,eAAe,CAAC,CAKpD;IAED,IAAI,yBAAyB,IAAI,KAAK,CAAC,MAAM,CAAC,CAE7C;IAID,IAAI,yBAAyB,IAAI,KAAK,CAAC,eAAe,CAAC,CAEtD;IAED,IAAI,yBAAyB,IAAI,KAAK,CAAC,eAAe,CAAC,CAEtD;IAED,IAAI,2BAA2B,IAAI,KAAK,CAAC,MAAM,CAAC,CAE/C;IAED,IAAI,2BAA2B,IAAI,KAAK,CAAC,MAAM,CAAC,CAE/C;IAID,IAAI,YAAY,IAAI,KAAK,CAAC,eAAe,CAAC,CAEzC;IAED,IAAI,mBAAmB,IAAI,KAAK,CAAC,eAAe,CAAC,CAEhD;IAED,IAAI,cAAc,IAAI,KAAK,CAAC,MAAM,CAAC,CAElC;IAED,IAAI,qBAAqB,IAAI,KAAK,CAAC,MAAM,CAAC,CAEzC;CAaD"}
|
|
@@ -26,16 +26,10 @@
|
|
|
26
26
|
*
|
|
27
27
|
* @module
|
|
28
28
|
*/
|
|
29
|
-
//
|
|
30
|
-
// `
|
|
31
|
-
//
|
|
32
|
-
//
|
|
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.
|
|
35
|
-
/**
|
|
36
|
-
* Utility class to manage and query action specifications.
|
|
37
|
-
* Provides helper methods to get actions by various criteria.
|
|
38
|
-
*/
|
|
29
|
+
// The auth (`public_*`, `authenticated_*`) and initiator-direction
|
|
30
|
+
// (`backend_to_frontend_*`, `frontend_to_backend_*`) getters are pre-built
|
|
31
|
+
// API surface unused by codegen today; kept low-cost for future filtering
|
|
32
|
+
// without a registry change.
|
|
39
33
|
export class ActionRegistry {
|
|
40
34
|
specs;
|
|
41
35
|
constructor(specs) {
|
|
@@ -18,6 +18,7 @@ import { type RouteSpec } from '../http/route_spec.js';
|
|
|
18
18
|
import { type RequestContext } from '../auth/request_context.js';
|
|
19
19
|
import type { Db } from '../db/db.js';
|
|
20
20
|
import { type JsonrpcRequestId } from '../http/jsonrpc.js';
|
|
21
|
+
import type { RateLimiter } from '../rate_limiter.js';
|
|
21
22
|
/**
|
|
22
23
|
* Per-request context provided to RPC action handlers.
|
|
23
24
|
*
|
|
@@ -108,6 +109,21 @@ export interface CreateRpcEndpointOptions {
|
|
|
108
109
|
actions: Array<RpcAction>;
|
|
109
110
|
/** Logger instance for handler context. */
|
|
110
111
|
log: Logger;
|
|
112
|
+
/**
|
|
113
|
+
* Per-IP rate limiter consulted for actions whose spec declares
|
|
114
|
+
* `rate_limit: 'ip'` or `'both'`. `null` disables the IP check.
|
|
115
|
+
* Per-action gate via `action.spec.rate_limit`. Same limiter is
|
|
116
|
+
* shared with the WebSocket action dispatcher — one budget per
|
|
117
|
+
* action, not per transport.
|
|
118
|
+
*/
|
|
119
|
+
action_ip_rate_limiter?: RateLimiter | null;
|
|
120
|
+
/**
|
|
121
|
+
* Per-actor rate limiter consulted for actions whose spec declares
|
|
122
|
+
* `rate_limit: 'account'` or `'both'`. Keyed on
|
|
123
|
+
* `request_context.actor.id`. `null` disables the account check.
|
|
124
|
+
* Same limiter is shared with the WebSocket action dispatcher.
|
|
125
|
+
*/
|
|
126
|
+
action_account_rate_limiter?: RateLimiter | null;
|
|
111
127
|
}
|
|
112
128
|
/**
|
|
113
129
|
* Single JSON-RPC 2.0 endpoint — the canonical RPC transport binding.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action_rpc.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_rpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAgC,KAAK,cAAc,EAAC,MAAM,4BAA4B,CAAC;AAE9F,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAEpC,OAAO,EAGN,KAAK,gBAAgB,EAGrB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"action_rpc.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_rpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAgC,KAAK,cAAc,EAAC,MAAM,4BAA4B,CAAC;AAE9F,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAEpC,OAAO,EAGN,KAAK,gBAAgB,EAGrB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC7B,+DAA+D;IAC/D,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,iDAAiD;IACjD,UAAU,EAAE,gBAAgB,CAAC;IAC7B,8DAA8D;IAC9D,EAAE,EAAE,EAAE,CAAC;IACP,oFAAoF;IACpF,aAAa,EAAE,EAAE,CAAC;IAClB,2EAA2E;IAC3E,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC;;;;;;;OAOG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;OAQG;IACH,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD;;;;OAIG;IACH,MAAM,EAAE,WAAW,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,CAAC,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,CACxD,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,aAAa,KACd,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,yBAAyB,CAAC;IAChC,OAAO,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,SAAS,yBAAyB,EACjE,MAAM,KAAK,EACX,SAAS,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KACvE,SAGD,CAAC;AAEH,yCAAyC;AACzC,MAAM,WAAW,wBAAwB;IACxC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC1B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5C;;;;;OAKG;IACH,2BAA2B,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CACjD;AAkDD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,wBAAwB,KAAG,KAAK,CAAC,SAAS,CAkTtF,CAAC"}
|
|
@@ -43,13 +43,6 @@ export const rpc_action = (spec, handler) => ({
|
|
|
43
43
|
spec,
|
|
44
44
|
handler: handler,
|
|
45
45
|
});
|
|
46
|
-
/**
|
|
47
|
-
* Format a JSON-RPC error response.
|
|
48
|
-
*
|
|
49
|
-
* @param id - the request id (null if unknown)
|
|
50
|
-
* @param error - the error object
|
|
51
|
-
* @returns a JSON-RPC error response object
|
|
52
|
-
*/
|
|
53
46
|
const jsonrpc_error_response = (id, error) => ({
|
|
54
47
|
jsonrpc: JSONRPC_VERSION,
|
|
55
48
|
id,
|
|
@@ -58,10 +51,7 @@ const jsonrpc_error_response = (id, error) => ({
|
|
|
58
51
|
/**
|
|
59
52
|
* Check auth for an action spec against the request context.
|
|
60
53
|
*
|
|
61
|
-
* @
|
|
62
|
-
* @param request_context - the resolved identity (null if unauthenticated)
|
|
63
|
-
* @param credential_type - how the request was authenticated (session, api_token, daemon_token)
|
|
64
|
-
* @returns an error json if auth fails, or null if authorized
|
|
54
|
+
* @returns a JSON-RPC error object if auth fails, or `null` if authorized
|
|
65
55
|
*/
|
|
66
56
|
const check_action_auth = (auth, request_context, credential_type) => {
|
|
67
57
|
if (auth === 'public')
|
|
@@ -124,7 +114,7 @@ const check_action_auth = (auth, request_context, credential_type) => {
|
|
|
124
114
|
* `z.void()` for parameterless methods).
|
|
125
115
|
*/
|
|
126
116
|
export const create_rpc_endpoint = (options) => {
|
|
127
|
-
const { path: endpoint_path, actions, log } = options;
|
|
117
|
+
const { path: endpoint_path, actions, log, action_ip_rate_limiter = null, action_account_rate_limiter = null, } = options;
|
|
128
118
|
// build action lookup map
|
|
129
119
|
const action_map = new Map();
|
|
130
120
|
for (const action of actions) {
|
|
@@ -134,18 +124,18 @@ export const create_rpc_endpoint = (options) => {
|
|
|
134
124
|
if (is_null_schema(action.spec.input)) {
|
|
135
125
|
throw new Error(`RPC action "${action.spec.method}" uses z.null() for input — JSON-RPC 2.0 §4.2 forbids "params": null on the wire (must be omitted or be a Structured value). Use z.void() for parameterless methods.`);
|
|
136
126
|
}
|
|
127
|
+
// Reject account-keyed rate limiting on public actions — there's no
|
|
128
|
+
// actor post-auth, so the account bucket has no key to consume.
|
|
129
|
+
if ((action.spec.rate_limit === 'account' || action.spec.rate_limit === 'both') &&
|
|
130
|
+
action.spec.auth === 'public') {
|
|
131
|
+
throw new Error(`RPC action "${action.spec.method}" declares rate_limit: '${action.spec.rate_limit}' but auth: 'public' — no actor available for account-keyed limiting. Use 'ip' or change auth.`);
|
|
132
|
+
}
|
|
137
133
|
action_map.set(action.spec.method, action);
|
|
138
134
|
}
|
|
139
135
|
/**
|
|
140
136
|
* Core dispatcher — shared by GET and POST handlers.
|
|
141
137
|
*
|
|
142
|
-
* @param
|
|
143
|
-
* @param route - route context with db and pending_effects
|
|
144
|
-
* @param method_name - the JSON-RPC method name
|
|
145
|
-
* @param raw_params - the raw params (parsed from body or query string)
|
|
146
|
-
* @param id - the request id
|
|
147
|
-
* @param restrict_to_reads - true for GET requests (reject side_effects actions)
|
|
148
|
-
* @returns a Response
|
|
138
|
+
* @param restrict_to_reads - `true` for GET (rejects `side_effects: true` actions)
|
|
149
139
|
*/
|
|
150
140
|
const dispatch = async (c, route, method_name, raw_params, id, restrict_to_reads) => {
|
|
151
141
|
// step 2: lookup method
|
|
@@ -169,6 +159,38 @@ export const create_rpc_endpoint = (options) => {
|
|
|
169
159
|
const error = jsonrpc_error_response(id, auth_error);
|
|
170
160
|
return c.json(error, jsonrpc_error_code_to_http_status(auth_error.code));
|
|
171
161
|
}
|
|
162
|
+
// step 3.5: rate limit — throttle-requests semantics (record on every
|
|
163
|
+
// invocation, no success-reset). Suits admin mutation oracles where
|
|
164
|
+
// the *successful* call is the threat. Different from REST login's
|
|
165
|
+
// throttle-failures pattern that resets on success. Silent partial
|
|
166
|
+
// enforcement: a key is checked iff its bucket's limiter is wired —
|
|
167
|
+
// `rate_limit: 'both'` with only one limiter set runs only that side.
|
|
168
|
+
const rate_limit = action.spec.rate_limit;
|
|
169
|
+
const client_ip = get_client_ip(c);
|
|
170
|
+
if (rate_limit) {
|
|
171
|
+
const ip_check = action_ip_rate_limiter && (rate_limit === 'ip' || rate_limit === 'both');
|
|
172
|
+
const account_check = action_account_rate_limiter &&
|
|
173
|
+
request_context &&
|
|
174
|
+
(rate_limit === 'account' || rate_limit === 'both');
|
|
175
|
+
const reject = (retry_after) => {
|
|
176
|
+
const error = jsonrpc_error_response(id, jsonrpc_error_messages.rate_limited('rate limited', { retry_after }));
|
|
177
|
+
return c.json(error, jsonrpc_error_code_to_http_status(JSONRPC_ERROR_CODES.rate_limited));
|
|
178
|
+
};
|
|
179
|
+
if (ip_check) {
|
|
180
|
+
const result = action_ip_rate_limiter.check(client_ip);
|
|
181
|
+
if (!result.allowed)
|
|
182
|
+
return reject(result.retry_after);
|
|
183
|
+
}
|
|
184
|
+
if (account_check) {
|
|
185
|
+
const result = action_account_rate_limiter.check(request_context.actor.id);
|
|
186
|
+
if (!result.allowed)
|
|
187
|
+
return reject(result.retry_after);
|
|
188
|
+
}
|
|
189
|
+
if (ip_check)
|
|
190
|
+
action_ip_rate_limiter.record(client_ip);
|
|
191
|
+
if (account_check)
|
|
192
|
+
action_account_rate_limiter.record(request_context.actor.id);
|
|
193
|
+
}
|
|
172
194
|
// step 4: validate params
|
|
173
195
|
// Missing `params` on the envelope maps to `undefined` for `z.void()`
|
|
174
196
|
// input schemas and `{}` for object inputs (matches HTTP's "empty
|
|
@@ -195,7 +217,6 @@ export const create_rpc_endpoint = (options) => {
|
|
|
195
217
|
}
|
|
196
218
|
};
|
|
197
219
|
const signal = c.req.raw.signal;
|
|
198
|
-
const client_ip = get_client_ip(c);
|
|
199
220
|
const execute = async (db) => {
|
|
200
221
|
const action_context = {
|
|
201
222
|
auth: request_context,
|