@fuzdev/fuz_app 0.44.0 → 0.46.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 +65 -39
- package/dist/actions/action_event.d.ts +10 -1
- package/dist/actions/action_event.d.ts.map +1 -1
- package/dist/actions/action_event.js +7 -0
- package/dist/actions/action_event_helpers.d.ts.map +1 -1
- package/dist/actions/action_event_helpers.js +14 -4
- package/dist/actions/broadcast_api.d.ts +1 -1
- package/dist/actions/broadcast_api.d.ts.map +1 -1
- package/dist/actions/frontend_rpc_client.d.ts +95 -23
- package/dist/actions/frontend_rpc_client.d.ts.map +1 -1
- package/dist/actions/frontend_rpc_client.js +48 -23
- package/dist/actions/rpc_client.d.ts +56 -86
- package/dist/actions/rpc_client.d.ts.map +1 -1
- package/dist/actions/rpc_client.js +51 -106
- package/dist/testing/ws_round_trip.d.ts +1 -1
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/ui/CLAUDE.md +10 -11
- package/dist/ui/admin_accounts_state.svelte.d.ts +20 -41
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_invites_state.svelte.d.ts +9 -18
- package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_rpc_adapters.d.ts +41 -29
- package/dist/ui/admin_rpc_adapters.d.ts.map +1 -1
- package/dist/ui/admin_rpc_adapters.js +28 -31
- package/dist/ui/admin_sessions_state.svelte.d.ts +3 -2
- package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/app_settings_state.svelte.d.ts +5 -10
- package/dist/ui/app_settings_state.svelte.d.ts.map +1 -1
- package/dist/ui/audit_log_state.svelte.d.ts +6 -18
- package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -5,14 +5,15 @@
|
|
|
5
5
|
* - **Tier 1** (simple, for tx): transport send/receive, Result return. No `environment`.
|
|
6
6
|
* - **Tier 2** (full, for zzz): ActionEvent lifecycle with `environment`.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Pass the consumer's generated `ActionsApi` interface as `<TApi>` to flow
|
|
9
|
+
* full type safety through without an explicit cast at the call site.
|
|
9
10
|
*
|
|
10
11
|
* @module
|
|
11
12
|
*/
|
|
12
13
|
import type { Result } from '@fuzdev/fuz_util/result.js';
|
|
13
14
|
import type { ActionEventEnvironment } from './action_event_types.js';
|
|
15
|
+
import { type ActionEvent } from './action_event.js';
|
|
14
16
|
import type { ActionPeer, ActionPeerSendOptions } from './action_peer.js';
|
|
15
|
-
import type { ActionEventDataUnion } from './action_event_data.js';
|
|
16
17
|
import type { TransportName } from './transports.js';
|
|
17
18
|
import type { JsonrpcErrorObject } from '../http/jsonrpc.js';
|
|
18
19
|
/**
|
|
@@ -24,21 +25,21 @@ import type { JsonrpcErrorObject } from '../http/jsonrpc.js';
|
|
|
24
25
|
* RPC surface lives on HTTP.
|
|
25
26
|
*/
|
|
26
27
|
export type TransportForMethod = (method: string) => TransportName | undefined;
|
|
27
|
-
/** Duck-typed action history — consumers pass their concrete Actions cell. */
|
|
28
|
-
export interface RpcClientActionHistory {
|
|
29
|
-
add_from_json: (json: {
|
|
30
|
-
method: string;
|
|
31
|
-
action_event_data: ActionEventDataUnion;
|
|
32
|
-
}) => {
|
|
33
|
-
listen_to_action_event: (event: any) => void;
|
|
34
|
-
} | undefined;
|
|
35
|
-
}
|
|
36
28
|
/** Options for `create_rpc_client`. */
|
|
37
|
-
export interface CreateRpcClientOptions {
|
|
29
|
+
export interface CreateRpcClientOptions<TApi extends object = object> {
|
|
38
30
|
peer: ActionPeer;
|
|
39
31
|
environment: ActionEventEnvironment;
|
|
40
|
-
/**
|
|
41
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Optional callback fired once per dispatched action with the live
|
|
34
|
+
* `ActionEvent`. Consumers wire reactive state here — e.g. zzz's `Actions`
|
|
35
|
+
* cell calls `add_from_json` + `listen_to_action_event` inside the
|
|
36
|
+
* callback so its history stays decoupled from the rpc_client surface.
|
|
37
|
+
*
|
|
38
|
+
* `event.spec.method` and `event.data.method` narrow to
|
|
39
|
+
* `keyof TApi & string` — drop the `as ActionMethod` cast at the call
|
|
40
|
+
* site when `TApi` is a generated `ActionsApi` interface.
|
|
41
|
+
*/
|
|
42
|
+
on_action_event?: (event: ActionEvent<keyof TApi & string>) => void;
|
|
42
43
|
/**
|
|
43
44
|
* Optional per-method transport selector. When provided, the client calls
|
|
44
45
|
* `peer.send(msg, {transport_name})` with the returned transport for each
|
|
@@ -55,10 +56,22 @@ export interface CreateRpcClientOptions {
|
|
|
55
56
|
* - `remote_notification` → send notification, return Result
|
|
56
57
|
* - `local_call` → execute locally (sync or async), return Result or throw
|
|
57
58
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
59
|
+
* Generic `TApi` is the consumer's typed Proxy interface (typically a
|
|
60
|
+
* codegen-derived `ActionsApi`). Required — no default, so forgetting it
|
|
61
|
+
* is a type error rather than a silent slide into `any`. The `as unknown
|
|
62
|
+
* as TApi` coercion lives inside this function so call sites get a typed
|
|
63
|
+
* return without a cast at the seam. `TApi` is a type-layer promise about
|
|
64
|
+
* what the Proxy responds to; the runtime walks `specs` (kept in sync by
|
|
65
|
+
* the consumer, codegen recommended).
|
|
66
|
+
*
|
|
67
|
+
* ```ts
|
|
68
|
+
* const api_result = create_rpc_client<MyActionsApi>({peer, environment});
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @param options - client options (peer, environment, optional callbacks)
|
|
72
|
+
* @returns a Proxy typed as `TApi` that responds to any method name found in the environment's specs
|
|
60
73
|
*/
|
|
61
|
-
export declare const create_rpc_client: (options: CreateRpcClientOptions
|
|
74
|
+
export declare const create_rpc_client: <TApi extends object>(options: CreateRpcClientOptions<TApi>) => TApi;
|
|
62
75
|
/**
|
|
63
76
|
* Per-call options accepted by every typed Proxy method. Same shape as
|
|
64
77
|
* `ActionPeerSendOptions` — the client threads these through unchanged
|
|
@@ -67,54 +80,6 @@ export declare const create_rpc_client: (options: CreateRpcClientOptions) => Rec
|
|
|
67
80
|
*/
|
|
68
81
|
export interface RpcClientCallOptions extends ActionPeerSendOptions {
|
|
69
82
|
}
|
|
70
|
-
/**
|
|
71
|
-
* `method, input -> unwrapped output` signature for adapter wiring.
|
|
72
|
-
*
|
|
73
|
-
* The typed `create_rpc_client` Proxy returns `Result<T, JsonrpcErrorObject>`
|
|
74
|
-
* on every call. UI adapters (e.g. `admin_rpc_adapters.ts`) want a
|
|
75
|
-
* throw-on-error shape so form components can match on `error.data.reason`
|
|
76
|
-
* via catch blocks. `create_throwing_rpc_call` bridges the two.
|
|
77
|
-
*/
|
|
78
|
-
export type ThrowingRpcCall = <TOutput = unknown>(method: string, input?: unknown) => Promise<TOutput>;
|
|
79
|
-
/**
|
|
80
|
-
* Wrap a typed RPC client so every call returns its unwrapped value or throws.
|
|
81
|
-
*
|
|
82
|
-
* On `{ok: false}`, throws an `Error` whose `message` comes from the
|
|
83
|
-
* JSON-RPC error object, plus `{code, data}` as own properties — so
|
|
84
|
-
* catch blocks reading `err.message` / `err.code` / `err.data?.reason`
|
|
85
|
-
* all work. On unknown method, throws a clear "rpc method not found"
|
|
86
|
-
* error instead of the cryptic `undefined is not a function` that
|
|
87
|
-
* would otherwise surface.
|
|
88
|
-
*
|
|
89
|
-
* Invariant upheld by `create_rpc_client`: every `{ok: false}` return
|
|
90
|
-
* carries a well-formed `JsonrpcErrorObject` with `code` + `message`.
|
|
91
|
-
* Callers must still use optional chaining on `err.data` because the
|
|
92
|
-
* JSON-RPC `data` field is spec-level optional — a handler that throws
|
|
93
|
-
* `jsonrpc_errors.forbidden()` without a `data` argument produces
|
|
94
|
-
* `err.data === undefined`.
|
|
95
|
-
*
|
|
96
|
-
* Only `{code, data}` cross onto the thrown Error — `message` flows
|
|
97
|
-
* through the `Error` constructor argument, and `name` / `stack` are
|
|
98
|
-
* left as the Error's own so attacker-shaped `result.error` payloads
|
|
99
|
-
* cannot overwrite them.
|
|
100
|
-
*
|
|
101
|
-
* The mapped-type generic constraint accepts both shapes without a cast:
|
|
102
|
-
* a codegen-derived typed `ActionsApi` (named-method interface, e.g.
|
|
103
|
-
* `{account_verify: (input) => Promise<Result<...>>, ...}`) and a loose
|
|
104
|
-
* `Record<string, (input?: any) => Promise<any> | void>`. Using `keyof TApi`
|
|
105
|
-
* in the constraint avoids the index-signature requirement that would
|
|
106
|
-
* otherwise force consumers to `as unknown as Record<string, …>` their
|
|
107
|
-
* generated client. The `| void` arm tolerates `remote_notification`
|
|
108
|
-
* methods, whose `ActionsApi` signature is `(input) => void` even though
|
|
109
|
-
* `create_remote_notification_method` returns a Promise at runtime — the
|
|
110
|
-
* throwing wrapper is intended for `request_response` calls but must
|
|
111
|
-
* accept mixed `ActionsApi` shapes without forcing a cast at the seam.
|
|
112
|
-
*
|
|
113
|
-
* @param api - typed RPC client from `create_rpc_client` (or any object
|
|
114
|
-
* whose values are all `(input?) => Promise<...> | void` functions —
|
|
115
|
-
* notably the consumer's generated `ActionsApi` interface)
|
|
116
|
-
*/
|
|
117
|
-
export declare const create_throwing_rpc_call: <TApi extends Record<keyof TApi, (input?: any) => Promise<any> | void>>(api: TApi) => ThrowingRpcCall;
|
|
118
83
|
/**
|
|
119
84
|
* Maps a typed `ActionsApi` to a throwing variant.
|
|
120
85
|
*
|
|
@@ -124,15 +89,23 @@ export declare const create_throwing_rpc_call: <TApi extends Record<keyof TApi,
|
|
|
124
89
|
* as `=> void`, sync `local_call` methods) pass through unchanged — there
|
|
125
90
|
* is nothing to unwrap.
|
|
126
91
|
*
|
|
127
|
-
* Input + options parameters are preserved verbatim
|
|
128
|
-
*
|
|
92
|
+
* Input + options parameters are preserved verbatim via `...args: infer TArgs`
|
|
93
|
+
* so the conditional matches both required-input (`input: T`) and
|
|
94
|
+
* optional-input (`input?: T` / nullary) signatures uniformly. Required-input
|
|
95
|
+
* shapes (e.g. `admin_session_revoke_all(input: AdminSessionRevokeAllInput)`)
|
|
96
|
+
* are not assignable to a `(input?: TInput) => …` pattern under
|
|
97
|
+
* `--strictFunctionTypes`, so an earlier `(input?, options?) =>` form
|
|
98
|
+
* silently fell through to `TApi[K]` and left those methods Result-shaped —
|
|
99
|
+
* `create_admin_rpc_adapters(api)` would then reject the typed throwing
|
|
100
|
+
* Proxy because half its surface still returned `Result<...>`. The rest-args
|
|
101
|
+
* form preserves both required and optional parameters and resolves the gap.
|
|
129
102
|
*/
|
|
130
103
|
export type ThrowingApi<TApi> = {
|
|
131
|
-
[K in keyof TApi]: TApi[K] extends (
|
|
104
|
+
[K in keyof TApi]: TApi[K] extends (...args: infer TArgs) => Promise<Result<{
|
|
132
105
|
value: infer TValue;
|
|
133
106
|
}, {
|
|
134
107
|
error: JsonrpcErrorObject;
|
|
135
|
-
}>> ? (
|
|
108
|
+
}>> ? (...args: TArgs) => Promise<TValue> : TApi[K];
|
|
136
109
|
};
|
|
137
110
|
/**
|
|
138
111
|
* Wrap a typed RPC client so every call resolves to its unwrapped value or
|
|
@@ -151,30 +124,27 @@ export type ThrowingApi<TApi> = {
|
|
|
151
124
|
*
|
|
152
125
|
* Only `{code, data}` cross onto the thrown Error — `name` / `stack` are
|
|
153
126
|
* left as the Error's own properties so attacker-shaped `result.error`
|
|
154
|
-
* payloads cannot overwrite them.
|
|
155
|
-
* `create_throwing_rpc_call`.
|
|
156
|
-
*
|
|
157
|
-
* Composable with `create_throwing_rpc_call` — same typed underlying
|
|
158
|
-
* client feeds both: the Proxy form for direct call sites, the loose
|
|
159
|
-
* method-keyed form for adapter wiring (`ui/admin_rpc_adapters.ts`).
|
|
127
|
+
* payloads cannot overwrite them.
|
|
160
128
|
*
|
|
161
|
-
* Recommended consumer convention:
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
129
|
+
* Recommended consumer convention: `create_frontend_rpc_client` ships
|
|
130
|
+
* both shapes by default — `api` (throwing) for hot-path call sites and
|
|
131
|
+
* `api_result` (Result) for sites that inspect `error.data.reason`
|
|
132
|
+
* without try/catch. Result is the protocol primitive; this wrapper is
|
|
133
|
+
* the ergonomic layer over it. Picking is per call site — both Proxies
|
|
134
|
+
* share the same underlying transport.
|
|
165
135
|
*
|
|
166
136
|
* Catch blocks read `err.data?.reason` — optional chaining required
|
|
167
137
|
* because JSON-RPC `data` is spec-level optional.
|
|
168
138
|
*
|
|
169
139
|
* On unknown string-keyed methods, the get trap returns a function that
|
|
170
|
-
* throws `"rpc method not found: <prop>"` on invocation —
|
|
171
|
-
* `
|
|
172
|
-
*
|
|
173
|
-
* undefined so the Proxy isn't accidentally treated as a thenable
|
|
140
|
+
* throws `"rpc method not found: <prop>"` on invocation — clearer than
|
|
141
|
+
* the JS default `"api.foo is not a function"`. Symbol props and `then`
|
|
142
|
+
* stay undefined so the Proxy isn't accidentally treated as a thenable
|
|
174
143
|
* (`await api` would otherwise probe `then` and trip the thrower).
|
|
175
144
|
*
|
|
176
|
-
* @param
|
|
177
|
-
*
|
|
145
|
+
* @param api_result - typed Result-returning RPC client from
|
|
146
|
+
* `create_rpc_client<ActionsApi>(...)`. The "_result" suffix names
|
|
147
|
+
* what the underlying calls return (`Result<{value}, {error}>`).
|
|
178
148
|
*/
|
|
179
|
-
export declare const create_throwing_api: <TApi extends object>(
|
|
149
|
+
export declare const create_throwing_api: <TApi extends object>(api_result: TApi) => ThrowingApi<TApi>;
|
|
180
150
|
//# sourceMappingURL=rpc_client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc_client.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/rpc_client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rpc_client.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/rpc_client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,4BAA4B,CAAC;AAQvD,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAsB,KAAK,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAMxE,OAAO,KAAK,EAAC,UAAU,EAAE,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AACxE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;AAM/E,uCAAuC;AACvC,MAAM,WAAW,sBAAsB,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACnE,IAAI,EAAE,UAAU,CAAC;IACjB,WAAW,EAAE,sBAAsB,CAAC;IACpC;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC;IACpE;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,kBAAkB,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,iBAAiB,GAAI,IAAI,SAAS,MAAM,EACpD,SAAS,sBAAsB,CAAC,IAAI,CAAC,KACnC,IA4BF,CAAC;AA6DF;;;;;GAKG;AACH,MAAM,WAAW,oBAAqB,SAAQ,qBAAqB;CAAG;AAoHtE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,WAAW,CAAC,IAAI,IAAI;KAC9B,CAAC,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAClC,GAAG,IAAI,EAAE,MAAM,KAAK,KAChB,OAAO,CAAC,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,MAAM,CAAA;KAAC,EAAE;QAAC,KAAK,EAAE,kBAAkB,CAAA;KAAC,CAAC,CAAC,GACrE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,MAAM,CAAC,GACnC,IAAI,CAAC,CAAC,CAAC;CACV,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,mBAAmB,GAAI,IAAI,SAAS,MAAM,EAAE,YAAY,IAAI,KAAG,WAAW,CAAC,IAAI,CA8B3F,CAAC"}
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* - **Tier 1** (simple, for tx): transport send/receive, Result return. No `environment`.
|
|
6
6
|
* - **Tier 2** (full, for zzz): ActionEvent lifecycle with `environment`.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Pass the consumer's generated `ActionsApi` interface as `<TApi>` to flow
|
|
9
|
+
* full type safety through without an explicit cast at the call site.
|
|
9
10
|
*
|
|
10
11
|
* @module
|
|
11
12
|
*/
|
|
@@ -20,18 +21,35 @@ import { jsonrpc_error_messages } from '../http/jsonrpc_errors.js';
|
|
|
20
21
|
* - `remote_notification` → send notification, return Result
|
|
21
22
|
* - `local_call` → execute locally (sync or async), return Result or throw
|
|
22
23
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
24
|
+
* Generic `TApi` is the consumer's typed Proxy interface (typically a
|
|
25
|
+
* codegen-derived `ActionsApi`). Required — no default, so forgetting it
|
|
26
|
+
* is a type error rather than a silent slide into `any`. The `as unknown
|
|
27
|
+
* as TApi` coercion lives inside this function so call sites get a typed
|
|
28
|
+
* return without a cast at the seam. `TApi` is a type-layer promise about
|
|
29
|
+
* what the Proxy responds to; the runtime walks `specs` (kept in sync by
|
|
30
|
+
* the consumer, codegen recommended).
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* const api_result = create_rpc_client<MyActionsApi>({peer, environment});
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @param options - client options (peer, environment, optional callbacks)
|
|
37
|
+
* @returns a Proxy typed as `TApi` that responds to any method name found in the environment's specs
|
|
25
38
|
*/
|
|
26
39
|
export const create_rpc_client = (options) => {
|
|
27
|
-
const { peer, environment,
|
|
40
|
+
const { peer, environment, on_action_event, transport_for_method } = options;
|
|
41
|
+
// Internal factories construct broadly-typed `ActionEvent` instances; the
|
|
42
|
+
// public callback narrows `event.spec.method` to `keyof TApi & string`.
|
|
43
|
+
// Cast once here — function parameters are contravariant, so the narrow
|
|
44
|
+
// callback isn't directly assignable to the broad slot the helpers take.
|
|
45
|
+
const broad_on_action_event = on_action_event;
|
|
28
46
|
return new Proxy({}, {
|
|
29
47
|
get(_target, method) {
|
|
30
48
|
const spec = environment.lookup_action_spec(method);
|
|
31
49
|
if (!spec) {
|
|
32
50
|
return undefined;
|
|
33
51
|
}
|
|
34
|
-
return create_action_method(peer, environment, spec,
|
|
52
|
+
return create_action_method(peer, environment, spec, broad_on_action_event, transport_for_method);
|
|
35
53
|
},
|
|
36
54
|
has(_target, method) {
|
|
37
55
|
return environment.lookup_action_spec(method) !== undefined;
|
|
@@ -41,30 +59,26 @@ export const create_rpc_client = (options) => {
|
|
|
41
59
|
/**
|
|
42
60
|
* Creates a method that executes an action through its complete lifecycle.
|
|
43
61
|
*/
|
|
44
|
-
const create_action_method = (peer, environment, spec,
|
|
62
|
+
const create_action_method = (peer, environment, spec, on_action_event, transport_for_method) => {
|
|
45
63
|
switch (spec.kind) {
|
|
46
64
|
case 'local_call':
|
|
47
65
|
return spec.async
|
|
48
|
-
? create_async_local_call_method(environment, spec,
|
|
49
|
-
: create_sync_local_call_method(environment, spec,
|
|
66
|
+
? create_async_local_call_method(environment, spec, on_action_event)
|
|
67
|
+
: create_sync_local_call_method(environment, spec, on_action_event);
|
|
50
68
|
case 'request_response':
|
|
51
|
-
return create_request_response_method(peer, environment, spec,
|
|
69
|
+
return create_request_response_method(peer, environment, spec, on_action_event, transport_for_method);
|
|
52
70
|
case 'remote_notification':
|
|
53
|
-
return create_remote_notification_method(peer, environment, spec,
|
|
71
|
+
return create_remote_notification_method(peer, environment, spec, on_action_event, transport_for_method);
|
|
54
72
|
}
|
|
55
73
|
};
|
|
56
74
|
/**
|
|
57
75
|
* Creates a synchronous local call method.
|
|
58
76
|
* Returns value directly - can throw on error (sync methods cannot return Result).
|
|
59
77
|
*/
|
|
60
|
-
const create_sync_local_call_method = (environment, spec,
|
|
78
|
+
const create_sync_local_call_method = (environment, spec, on_action_event) => {
|
|
61
79
|
return (input) => {
|
|
62
80
|
const event = create_action_event(environment, spec, input);
|
|
63
|
-
|
|
64
|
-
method: spec.method,
|
|
65
|
-
action_event_data: event.toJSON(),
|
|
66
|
-
});
|
|
67
|
-
action?.listen_to_action_event(event);
|
|
81
|
+
on_action_event?.(event);
|
|
68
82
|
event.parse().handle_sync();
|
|
69
83
|
const result = extract_action_result(event);
|
|
70
84
|
if (result.ok) {
|
|
@@ -84,7 +98,7 @@ const create_sync_local_call_method = (environment, spec, actions) => {
|
|
|
84
98
|
* `signal` can only short-circuit before the synchronous handler runs (no
|
|
85
99
|
* cooperative interrupt mid-handler).
|
|
86
100
|
*/
|
|
87
|
-
const create_async_local_call_method = (environment, spec,
|
|
101
|
+
const create_async_local_call_method = (environment, spec, on_action_event) => {
|
|
88
102
|
return async (input, options) => {
|
|
89
103
|
if (options?.signal?.aborted) {
|
|
90
104
|
return {
|
|
@@ -93,11 +107,7 @@ const create_async_local_call_method = (environment, spec, actions) => {
|
|
|
93
107
|
};
|
|
94
108
|
}
|
|
95
109
|
const event = create_action_event(environment, spec, input);
|
|
96
|
-
|
|
97
|
-
method: spec.method,
|
|
98
|
-
action_event_data: event.toJSON(),
|
|
99
|
-
});
|
|
100
|
-
action?.listen_to_action_event(event);
|
|
110
|
+
on_action_event?.(event);
|
|
101
111
|
await event.parse().handle_async();
|
|
102
112
|
return extract_action_result(event);
|
|
103
113
|
};
|
|
@@ -105,14 +115,10 @@ const create_async_local_call_method = (environment, spec, actions) => {
|
|
|
105
115
|
/**
|
|
106
116
|
* Creates a request/response method that communicates over the network.
|
|
107
117
|
*/
|
|
108
|
-
const create_request_response_method = (peer, environment, spec,
|
|
118
|
+
const create_request_response_method = (peer, environment, spec, on_action_event, transport_for_method) => {
|
|
109
119
|
return async (input, options) => {
|
|
110
120
|
const event = create_action_event(environment, spec, input);
|
|
111
|
-
|
|
112
|
-
method: spec.method,
|
|
113
|
-
action_event_data: event.toJSON(),
|
|
114
|
-
});
|
|
115
|
-
action?.listen_to_action_event(event);
|
|
121
|
+
on_action_event?.(event);
|
|
116
122
|
await event.parse().handle_async();
|
|
117
123
|
// Check if we're in send_error phase before type narrowing
|
|
118
124
|
if (event.data.kind === 'request_response' && event.data.phase === 'send_error') {
|
|
@@ -141,14 +147,10 @@ const create_request_response_method = (peer, environment, spec, actions, transp
|
|
|
141
147
|
* Creates a remote notification method (fire and forget).
|
|
142
148
|
* Returns Result<{value: void}> for consistency.
|
|
143
149
|
*/
|
|
144
|
-
const create_remote_notification_method = (peer, environment, spec,
|
|
150
|
+
const create_remote_notification_method = (peer, environment, spec, on_action_event, transport_for_method) => {
|
|
145
151
|
return async (input, options) => {
|
|
146
152
|
const event = create_action_event(environment, spec, input);
|
|
147
|
-
|
|
148
|
-
method: spec.method,
|
|
149
|
-
action_event_data: event.toJSON(),
|
|
150
|
-
});
|
|
151
|
-
action?.listen_to_action_event(event);
|
|
153
|
+
on_action_event?.(event);
|
|
152
154
|
await event.parse().handle_async();
|
|
153
155
|
if (!is_notification_send(event.data))
|
|
154
156
|
throw Error(); // TODO @many maybe make this an assertion helper?
|
|
@@ -168,60 +170,6 @@ const create_remote_notification_method = (peer, environment, spec, actions, tra
|
|
|
168
170
|
return extract_action_result(event);
|
|
169
171
|
};
|
|
170
172
|
};
|
|
171
|
-
/**
|
|
172
|
-
* Wrap a typed RPC client so every call returns its unwrapped value or throws.
|
|
173
|
-
*
|
|
174
|
-
* On `{ok: false}`, throws an `Error` whose `message` comes from the
|
|
175
|
-
* JSON-RPC error object, plus `{code, data}` as own properties — so
|
|
176
|
-
* catch blocks reading `err.message` / `err.code` / `err.data?.reason`
|
|
177
|
-
* all work. On unknown method, throws a clear "rpc method not found"
|
|
178
|
-
* error instead of the cryptic `undefined is not a function` that
|
|
179
|
-
* would otherwise surface.
|
|
180
|
-
*
|
|
181
|
-
* Invariant upheld by `create_rpc_client`: every `{ok: false}` return
|
|
182
|
-
* carries a well-formed `JsonrpcErrorObject` with `code` + `message`.
|
|
183
|
-
* Callers must still use optional chaining on `err.data` because the
|
|
184
|
-
* JSON-RPC `data` field is spec-level optional — a handler that throws
|
|
185
|
-
* `jsonrpc_errors.forbidden()` without a `data` argument produces
|
|
186
|
-
* `err.data === undefined`.
|
|
187
|
-
*
|
|
188
|
-
* Only `{code, data}` cross onto the thrown Error — `message` flows
|
|
189
|
-
* through the `Error` constructor argument, and `name` / `stack` are
|
|
190
|
-
* left as the Error's own so attacker-shaped `result.error` payloads
|
|
191
|
-
* cannot overwrite them.
|
|
192
|
-
*
|
|
193
|
-
* The mapped-type generic constraint accepts both shapes without a cast:
|
|
194
|
-
* a codegen-derived typed `ActionsApi` (named-method interface, e.g.
|
|
195
|
-
* `{account_verify: (input) => Promise<Result<...>>, ...}`) and a loose
|
|
196
|
-
* `Record<string, (input?: any) => Promise<any> | void>`. Using `keyof TApi`
|
|
197
|
-
* in the constraint avoids the index-signature requirement that would
|
|
198
|
-
* otherwise force consumers to `as unknown as Record<string, …>` their
|
|
199
|
-
* generated client. The `| void` arm tolerates `remote_notification`
|
|
200
|
-
* methods, whose `ActionsApi` signature is `(input) => void` even though
|
|
201
|
-
* `create_remote_notification_method` returns a Promise at runtime — the
|
|
202
|
-
* throwing wrapper is intended for `request_response` calls but must
|
|
203
|
-
* accept mixed `ActionsApi` shapes without forcing a cast at the seam.
|
|
204
|
-
*
|
|
205
|
-
* @param api - typed RPC client from `create_rpc_client` (or any object
|
|
206
|
-
* whose values are all `(input?) => Promise<...> | void` functions —
|
|
207
|
-
* notably the consumer's generated `ActionsApi` interface)
|
|
208
|
-
*/
|
|
209
|
-
export const create_throwing_rpc_call = (api) => {
|
|
210
|
-
const rec = api;
|
|
211
|
-
return async (method, input) => {
|
|
212
|
-
const fn = rec[method];
|
|
213
|
-
if (!fn)
|
|
214
|
-
throw new Error(`rpc method not found: ${method}`);
|
|
215
|
-
const result = await fn(input);
|
|
216
|
-
if (!result.ok) {
|
|
217
|
-
throw Object.assign(new Error(result.error?.message ?? 'rpc error'), {
|
|
218
|
-
code: result.error?.code,
|
|
219
|
-
data: result.error?.data,
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
return result.value;
|
|
223
|
-
};
|
|
224
|
-
};
|
|
225
173
|
/**
|
|
226
174
|
* Wrap a typed RPC client so every call resolves to its unwrapped value or
|
|
227
175
|
* throws an `Error` carrying the JSON-RPC `{code, message, data?}` shape.
|
|
@@ -239,33 +187,30 @@ export const create_throwing_rpc_call = (api) => {
|
|
|
239
187
|
*
|
|
240
188
|
* Only `{code, data}` cross onto the thrown Error — `name` / `stack` are
|
|
241
189
|
* left as the Error's own properties so attacker-shaped `result.error`
|
|
242
|
-
* payloads cannot overwrite them.
|
|
243
|
-
* `create_throwing_rpc_call`.
|
|
244
|
-
*
|
|
245
|
-
* Composable with `create_throwing_rpc_call` — same typed underlying
|
|
246
|
-
* client feeds both: the Proxy form for direct call sites, the loose
|
|
247
|
-
* method-keyed form for adapter wiring (`ui/admin_rpc_adapters.ts`).
|
|
190
|
+
* payloads cannot overwrite them.
|
|
248
191
|
*
|
|
249
|
-
* Recommended consumer convention:
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
192
|
+
* Recommended consumer convention: `create_frontend_rpc_client` ships
|
|
193
|
+
* both shapes by default — `api` (throwing) for hot-path call sites and
|
|
194
|
+
* `api_result` (Result) for sites that inspect `error.data.reason`
|
|
195
|
+
* without try/catch. Result is the protocol primitive; this wrapper is
|
|
196
|
+
* the ergonomic layer over it. Picking is per call site — both Proxies
|
|
197
|
+
* share the same underlying transport.
|
|
253
198
|
*
|
|
254
199
|
* Catch blocks read `err.data?.reason` — optional chaining required
|
|
255
200
|
* because JSON-RPC `data` is spec-level optional.
|
|
256
201
|
*
|
|
257
202
|
* On unknown string-keyed methods, the get trap returns a function that
|
|
258
|
-
* throws `"rpc method not found: <prop>"` on invocation —
|
|
259
|
-
* `
|
|
260
|
-
*
|
|
261
|
-
* undefined so the Proxy isn't accidentally treated as a thenable
|
|
203
|
+
* throws `"rpc method not found: <prop>"` on invocation — clearer than
|
|
204
|
+
* the JS default `"api.foo is not a function"`. Symbol props and `then`
|
|
205
|
+
* stay undefined so the Proxy isn't accidentally treated as a thenable
|
|
262
206
|
* (`await api` would otherwise probe `then` and trip the thrower).
|
|
263
207
|
*
|
|
264
|
-
* @param
|
|
265
|
-
*
|
|
208
|
+
* @param api_result - typed Result-returning RPC client from
|
|
209
|
+
* `create_rpc_client<ActionsApi>(...)`. The "_result" suffix names
|
|
210
|
+
* what the underlying calls return (`Result<{value}, {error}>`).
|
|
266
211
|
*/
|
|
267
|
-
export const create_throwing_api = (
|
|
268
|
-
return new Proxy(
|
|
212
|
+
export const create_throwing_api = (api_result) => {
|
|
213
|
+
return new Proxy(api_result, {
|
|
269
214
|
get(target, prop) {
|
|
270
215
|
const fn = target[prop];
|
|
271
216
|
if (typeof fn === 'function') {
|
|
@@ -267,7 +267,7 @@ export declare const keeper_identity: () => WsConnectIdentity;
|
|
|
267
267
|
* await client.wait_for(is_notification('tx_run_created'));
|
|
268
268
|
* ```
|
|
269
269
|
*/
|
|
270
|
-
export declare const build_broadcast_api: <TApi>(options: {
|
|
270
|
+
export declare const build_broadcast_api: <TApi extends object>(options: {
|
|
271
271
|
harness: WsTestHarness;
|
|
272
272
|
specs: ReadonlyArray<ActionSpecUnion>;
|
|
273
273
|
}) => TApi;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/ws_round_trip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAO,MAAM,MAAM,CAAC;AACxC,OAAO,EACN,SAAS,EAET,KAAK,gBAAgB,EAErB,KAAK,QAAQ,EACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAC/C,OAAO,EAAc,KAAK,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,4BAA4B,CAAC;AAEvD,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,kCAAkC,CAAC;AAE7E,OAAO,EAEN,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAC,yBAAyB,EAAC,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAsB,KAAK,cAAc,EAAC,MAAM,4BAA4B,CAAC;AAEpF,OAAO,EAA6C,KAAK,cAAc,EAAC,MAAM,oBAAoB,CAAC;AACnG,OAAO,EAAC,eAAe,EAAC,MAAM,oBAAoB,CAAC;AAanD;;;GAGG;AACH,MAAM,WAAW,MAAM;IACtB,EAAE,EAAE,SAAS,CAAC;IACd,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACrB,MAAM,EAAE,KAAK,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;CAChD;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAAO,MAajC,CAAC;AAEF,8CAA8C;AAC9C,MAAM,WAAW,sBAAsB;IACtC,eAAe,EAAE,cAAc,CAAC;IAChC,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;OAGG;IACH,eAAe,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GAAI,MAAM,sBAAsB,KAAG,OAWvE,CAAC;AAEF,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC3B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,iBAAiB,EAAE,MAAM,CAAC,CAAC,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACtE;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,QAAO,WAatC,CAAC;AAEF;;;;GAIG;AACH,qBAAa,wBAAyB,YAAW,sBAAsB;;IACtE,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAa;gBAEjC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC;IAGjD,qBAAqB,IAAI,SAAS;IAGlC,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;CAG/D;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC/B,YAAY,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAC9C,OAAO,YAAY,EACnB,IAAI,SAAS,KACX,OAAO,CAAC,IAAI,CAId,CAAC;AAMF,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IACjC,wEAAwE;IACxE,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,yFAAyF;IACzF,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kFAAkF;IAClF,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACtB;AAED,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC5B,uEAAuE;IACvE,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C;;;;;;;;OAQG;IACH,OAAO,EAAE,CAAC,CAAC,GAAG,OAAO,EACpB,EAAE,EAAE,MAAM,GAAG,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EACf,UAAU,CAAC,EAAE,MAAM,KACf,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB;;;;OAIG;IACH,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC1C;;;;;;;;OAQG;IACH,QAAQ,EAAE;QACT,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,GAAG,IAAI,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAE5E,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;KACrF,CAAC;CACF;AAkBD,MAAM,WAAW,wBAAwB,CAAC,CAAC,GAAG,OAAO;IACpD,OAAO,EAAE,OAAO,eAAe,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,CAAC;CACV;AAED,MAAM,WAAW,2BAA2B,CAAC,CAAC,GAAG,OAAO;IACvD,OAAO,EAAE,OAAO,eAAe,CAAC;IAChC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,EAAE,CAAC,CAAC;CACV;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC,GAAG,OAAO;IACrD,OAAO,EAAE,OAAO,eAAe,CAAC;IAChC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,KAAK,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,CAAC,CAAA;KAAC,CAAC;CACjD;AAED,6EAA6E;AAC7E,eAAO,MAAM,eAAe,GAC1B,QAAQ,MAAM,MACd,KAAK,OAAO,KAAG,OACsC,CAAC;AAExD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,GAC/B,CAAC,EAAE,QAAQ,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,MAChD,KAAK,OAAO,KAAG,GAAG,IAAI,wBAAwB,CAAC,CAAC,CAGE,CAAC;AAErD,gGAAgG;AAChG,eAAO,MAAM,eAAe,GAC1B,IAAI,MAAM,GAAG,MAAM,MACnB,KAAK,OAAO,KAAG,OAC8D,CAAC;AAEhF,4CAA4C;AAC5C,MAAM,WAAW,0BAA0B,CAAC,IAAI,SAAS,kBAAkB;IAC1E;;;;;OAKG;IACH,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACrC,cAAc,CAAC,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC,CAAC;IACjE,kEAAkE;IAClE,SAAS,CAAC,EAAE,yBAAyB,CAAC;IACtC;;;;OAIG;IACH,SAAS,CAAC,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,CAAC;IACvD,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,cAAc,CAAC,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC,CAAC;IACjE,yDAAyD;IACzD,eAAe,CAAC,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC,iBAAiB,CAAC,CAAC;CACnE;AAED,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,yBAAyB,CAAC;IACrC;;;;;;OAMG;IACH,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,iBAAiB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CACjE;AA8DD;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,GAAI,IAAI,SAAS,kBAAkB,EACrE,SAAS,0BAA0B,CAAC,IAAI,CAAC,KACvC,aA6KF,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,eAAe,QAAO,iBAGjC,CAAC;AAYH;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,GAAI,IAAI,EAAE,SAAS;
|
|
1
|
+
{"version":3,"file":"ws_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/ws_round_trip.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/CLAUDE.md
CHANGED
|
@@ -267,17 +267,16 @@ destructive actions.
|
|
|
267
267
|
(`get`, `update`). Fields: `settings`, `updating`. Single mutation
|
|
268
268
|
`update_open_signup(boolean)`.
|
|
269
269
|
- `admin_rpc_adapters.ts` (plain `.ts`, no reactive state) — bundled
|
|
270
|
-
wiring for the four admin RPC contexts. `create_admin_rpc_adapters(
|
|
271
|
-
takes
|
|
272
|
-
|
|
273
|
-
audit_log, app_settings}` adapter
|
|
274
|
-
calls `set` on all
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
`admin_rpc_adapters.test.ts` fixtures.
|
|
270
|
+
wiring for the four admin RPC contexts. `create_admin_rpc_adapters(api)`
|
|
271
|
+
takes the typed throwing Proxy from `create_frontend_rpc_client` (or
|
|
272
|
+
any object satisfying the `AdminRpcApi` interface) and returns
|
|
273
|
+
`{admin_accounts, admin_invites, audit_log, app_settings}` adapter
|
|
274
|
+
objects. `provide_admin_rpc_contexts(adapters)` calls `set` on all
|
|
275
|
+
four contexts in one shot. One line at the admin shell layout:
|
|
276
|
+
`provide_admin_rpc_contexts(create_admin_rpc_adapters(api))`.
|
|
277
|
+
Method-name mapping is in the module TSDoc (`grant_permit` →
|
|
278
|
+
`permit_offer_create`, `retract_offer` → `permit_offer_retract`, etc.)
|
|
279
|
+
and the `admin_rpc_adapters.test.ts` fixtures.
|
|
281
280
|
|
|
282
281
|
## RPC adapter contexts
|
|
283
282
|
|
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
import { SvelteSet } from 'svelte/reactivity';
|
|
7
|
+
import type { Uuid } from '@fuzdev/fuz_util/id.js';
|
|
7
8
|
import { Loadable } from './loadable.svelte.js';
|
|
8
9
|
import type { AdminAccountEntryJson } from '../auth/account_schema.js';
|
|
9
|
-
import type {
|
|
10
|
+
import type { RoleName } from '../auth/role_schema.js';
|
|
10
11
|
import type { PermitOfferJson } from '../auth/permit_offer_schema.js';
|
|
12
|
+
import type { AdminAccountListOutput, AdminSessionListOutput, AdminSessionRevokeAllInput, AdminSessionRevokeAllOutput, AdminTokenRevokeAllInput, AdminTokenRevokeAllOutput } from '../auth/admin_action_specs.js';
|
|
13
|
+
import type { PermitOfferCreateInput, PermitOfferCreateOutput, PermitOfferOkOutput, PermitRevokeInput, PermitRevokeOutput } from '../auth/permit_offer_action_specs.js';
|
|
11
14
|
/**
|
|
12
15
|
* Narrow RPC surface consumed by `AdminAccountsState`. Consumers adapt their
|
|
13
16
|
* typed RPC client (e.g. a `create_rpc_client` Proxy) to this shape — the
|
|
@@ -21,44 +24,20 @@ import type { PermitOfferJson } from '../auth/permit_offer_schema.js';
|
|
|
21
24
|
* `admin_session_revoke_all` and `admin_token_revoke_all`. Without the
|
|
22
25
|
* adapter the state class cannot fetch, grant, revoke, retract, or
|
|
23
26
|
* revoke-all sessions/tokens.
|
|
27
|
+
*
|
|
28
|
+
* Method signatures track the underlying action specs — `Uuid`-branded ids
|
|
29
|
+
* propagate from the wire through the state class to the components. The
|
|
30
|
+
* adapter built by `create_admin_rpc_adapters` therefore needs zero casts
|
|
31
|
+
* to bridge to the typed throwing Proxy.
|
|
24
32
|
*/
|
|
25
33
|
export interface AdminAccountsRpc {
|
|
26
|
-
list_accounts: () => Promise<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
grant_permit: (params: {
|
|
34
|
-
to_account_id: string;
|
|
35
|
-
role: string;
|
|
36
|
-
}) => Promise<{
|
|
37
|
-
offer: PermitOfferJson;
|
|
38
|
-
}>;
|
|
39
|
-
revoke_permit: (params: {
|
|
40
|
-
actor_id: string;
|
|
41
|
-
permit_id: string;
|
|
42
|
-
reason?: string | null;
|
|
43
|
-
}) => Promise<{
|
|
44
|
-
ok: true;
|
|
45
|
-
revoked: true;
|
|
46
|
-
}>;
|
|
47
|
-
retract_offer: (offer_id: string) => Promise<{
|
|
48
|
-
ok: true;
|
|
49
|
-
}>;
|
|
50
|
-
session_revoke_all: (params: {
|
|
51
|
-
account_id: string;
|
|
52
|
-
}) => Promise<{
|
|
53
|
-
ok: true;
|
|
54
|
-
count: number;
|
|
55
|
-
}>;
|
|
56
|
-
token_revoke_all: (params: {
|
|
57
|
-
account_id: string;
|
|
58
|
-
}) => Promise<{
|
|
59
|
-
ok: true;
|
|
60
|
-
count: number;
|
|
61
|
-
}>;
|
|
34
|
+
list_accounts: () => Promise<AdminAccountListOutput>;
|
|
35
|
+
list_sessions: () => Promise<AdminSessionListOutput>;
|
|
36
|
+
grant_permit: (params: PermitOfferCreateInput) => Promise<PermitOfferCreateOutput>;
|
|
37
|
+
revoke_permit: (params: PermitRevokeInput) => Promise<PermitRevokeOutput>;
|
|
38
|
+
retract_offer: (offer_id: Uuid) => Promise<PermitOfferOkOutput>;
|
|
39
|
+
session_revoke_all: (params: AdminSessionRevokeAllInput) => Promise<AdminSessionRevokeAllOutput>;
|
|
40
|
+
token_revoke_all: (params: AdminTokenRevokeAllInput) => Promise<AdminTokenRevokeAllOutput>;
|
|
62
41
|
}
|
|
63
42
|
/**
|
|
64
43
|
* Svelte context carrying the reactive `AdminAccountsRpc` accessor. The
|
|
@@ -86,7 +65,7 @@ export interface AdminAccountsStateOptions {
|
|
|
86
65
|
export declare class AdminAccountsState extends Loadable {
|
|
87
66
|
#private;
|
|
88
67
|
accounts: Array<AdminAccountEntryJson>;
|
|
89
|
-
grantable_roles: Array<
|
|
68
|
+
grantable_roles: Array<RoleName>;
|
|
90
69
|
readonly granting_keys: SvelteSet<string>;
|
|
91
70
|
readonly revoking_ids: SvelteSet<string>;
|
|
92
71
|
readonly retracting_ids: SvelteSet<string>;
|
|
@@ -111,7 +90,7 @@ export declare class AdminAccountsState extends Loadable {
|
|
|
111
90
|
* No-op when the rpc adapter is absent; `error` is set to a descriptive
|
|
112
91
|
* message so the UI surfaces the misconfiguration.
|
|
113
92
|
*/
|
|
114
|
-
grant_permit(account_id:
|
|
93
|
+
grant_permit(account_id: Uuid, role: RoleName): Promise<PermitOfferJson | undefined>;
|
|
115
94
|
/**
|
|
116
95
|
* Revoke an active permit via the `permit_revoke` RPC.
|
|
117
96
|
*
|
|
@@ -121,7 +100,7 @@ export declare class AdminAccountsState extends Loadable {
|
|
|
121
100
|
* The optional `reason` is stamped on `permit.revoked_reason` and
|
|
122
101
|
* surfaced on the revokee's WS notification.
|
|
123
102
|
*/
|
|
124
|
-
revoke_permit(actor_id:
|
|
103
|
+
revoke_permit(actor_id: Uuid, permit_id: Uuid, reason?: string | null): Promise<void>;
|
|
125
104
|
/**
|
|
126
105
|
* Retract a pending offer the admin issued via the `permit_offer_retract`
|
|
127
106
|
* RPC. The action handles auth, audit, and the
|
|
@@ -130,6 +109,6 @@ export declare class AdminAccountsState extends Loadable {
|
|
|
130
109
|
* After success, refetches the listing so `pending_offers` drops the
|
|
131
110
|
* row and the "+ {role}" button un-hides.
|
|
132
111
|
*/
|
|
133
|
-
retract_offer(offer_id:
|
|
112
|
+
retract_offer(offer_id: Uuid): Promise<void>;
|
|
134
113
|
}
|
|
135
114
|
//# sourceMappingURL=admin_accounts_state.svelte.d.ts.map
|