@nice-code/action 0.6.1 → 0.6.3
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/build/devtools/browser/index.js +361 -176
- package/build/index.js +66 -35
- package/build/types/ActionRuntime/Handler/ExternalClient/ActionExternalClientHandler.d.ts +1 -0
- package/build/types/ActionRuntime/Handler/ExternalClient/Transport/ConnectionTransportManager.d.ts +7 -0
- package/build/types/devtools/browser/components/OriginChip.d.ts +15 -0
- package/build/types/devtools/browser/components/utils.d.ts +11 -0
- package/build/types/devtools/core/devtools_colors.d.ts +1 -0
- package/package.json +4 -4
package/build/index.js
CHANGED
|
@@ -965,6 +965,7 @@ class ActionRuntime {
|
|
|
965
965
|
}
|
|
966
966
|
async handleActionPayload(action, options) {
|
|
967
967
|
if (action.type === "request" /* request */) {
|
|
968
|
+
const observers = action.context._domain._collectActionObservers();
|
|
968
969
|
let handlerForAction;
|
|
969
970
|
try {
|
|
970
971
|
handlerForAction = this.getHandlerForActionOrThrow(action, options);
|
|
@@ -973,6 +974,7 @@ class ActionRuntime {
|
|
|
973
974
|
context: action.context,
|
|
974
975
|
request: action
|
|
975
976
|
});
|
|
977
|
+
runningAction2.addUpdateListeners(observers);
|
|
976
978
|
runningAction2._completeWithResult(action.errorResult(castNiceError(err2)));
|
|
977
979
|
return runningAction2;
|
|
978
980
|
}
|
|
@@ -980,6 +982,7 @@ class ActionRuntime {
|
|
|
980
982
|
...options,
|
|
981
983
|
targetLocalRuntime: this
|
|
982
984
|
});
|
|
985
|
+
runningAction.addUpdateListeners(observers);
|
|
983
986
|
this._trySetupReturnDispatch(runningAction);
|
|
984
987
|
return runningAction;
|
|
985
988
|
}
|
|
@@ -1293,6 +1296,9 @@ class ActionDomainBase {
|
|
|
1293
1296
|
this._listeners = this._listeners.filter((l) => l !== listener);
|
|
1294
1297
|
};
|
|
1295
1298
|
}
|
|
1299
|
+
_getActionObservers() {
|
|
1300
|
+
return this._listeners;
|
|
1301
|
+
}
|
|
1296
1302
|
}
|
|
1297
1303
|
|
|
1298
1304
|
// src/ActionDefinition/Domain/ActionDomain.ts
|
|
@@ -1309,6 +1315,9 @@ class ActionDomain extends ActionDomainBase {
|
|
|
1309
1315
|
get rootDomain() {
|
|
1310
1316
|
return this._rootDomain;
|
|
1311
1317
|
}
|
|
1318
|
+
_collectActionObservers() {
|
|
1319
|
+
return [...this._rootDomain._getActionObservers(), ...this._getActionObservers()];
|
|
1320
|
+
}
|
|
1312
1321
|
_registerRuntime(runtime2) {
|
|
1313
1322
|
this._rootDomain._registerRuntime(runtime2);
|
|
1314
1323
|
}
|
|
@@ -1794,20 +1803,24 @@ class ConnectionTransportManager {
|
|
|
1794
1803
|
addTransport(transport) {
|
|
1795
1804
|
this._transports.push(transport);
|
|
1796
1805
|
}
|
|
1806
|
+
getPreferredTransport() {
|
|
1807
|
+
return this._transports[0];
|
|
1808
|
+
}
|
|
1797
1809
|
async getReadyTransport(routeActionParams) {
|
|
1798
|
-
const initializingWaiters = [];
|
|
1799
|
-
const unavailableTransports = [];
|
|
1800
1810
|
const action = routeActionParams.action;
|
|
1811
|
+
const candidates = [];
|
|
1812
|
+
const unavailableTransports = [];
|
|
1801
1813
|
for (const transport of this._transports) {
|
|
1802
1814
|
const cacheKey = transport.getCacheKey(routeActionParams);
|
|
1803
1815
|
if (cacheKey != null) {
|
|
1804
1816
|
const cached = this._cache.get(cacheKey);
|
|
1805
1817
|
if (cached != null) {
|
|
1806
1818
|
if (cached instanceof Promise) {
|
|
1807
|
-
|
|
1819
|
+
candidates.push(cached);
|
|
1808
1820
|
continue;
|
|
1809
1821
|
}
|
|
1810
|
-
|
|
1822
|
+
candidates.push(Promise.resolve({ ...cached, transport }));
|
|
1823
|
+
break;
|
|
1811
1824
|
}
|
|
1812
1825
|
}
|
|
1813
1826
|
const statusInfo = transport.getTransport(routeActionParams);
|
|
@@ -1817,7 +1830,8 @@ class ConnectionTransportManager {
|
|
|
1817
1830
|
this._cache.set(cacheKey, { methods: readyData, transport });
|
|
1818
1831
|
readyData.addOnDisconnectListener?.(() => this._cache.delete(cacheKey));
|
|
1819
1832
|
}
|
|
1820
|
-
|
|
1833
|
+
candidates.push(Promise.resolve({ methods: readyData, transport }));
|
|
1834
|
+
break;
|
|
1821
1835
|
}
|
|
1822
1836
|
if (statusInfo.status === "unsupported" /* unsupported */) {
|
|
1823
1837
|
unavailableTransports.push(transport);
|
|
@@ -1847,10 +1861,10 @@ class ConnectionTransportManager {
|
|
|
1847
1861
|
if (cacheKey != null) {
|
|
1848
1862
|
this._cache.set(cacheKey, promise);
|
|
1849
1863
|
}
|
|
1850
|
-
|
|
1864
|
+
candidates.push(promise);
|
|
1851
1865
|
}
|
|
1852
1866
|
}
|
|
1853
|
-
if (
|
|
1867
|
+
if (candidates.length === 0) {
|
|
1854
1868
|
if (unavailableTransports.length > 0) {
|
|
1855
1869
|
throw err_nice_transport.fromId("unsupported" /* unsupported */, {
|
|
1856
1870
|
transportTypes: unavailableTransports.map((t) => t.type)
|
|
@@ -1860,13 +1874,17 @@ class ConnectionTransportManager {
|
|
|
1860
1874
|
actionId: action.id
|
|
1861
1875
|
});
|
|
1862
1876
|
}
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1877
|
+
let lastError;
|
|
1878
|
+
for (const candidate of candidates) {
|
|
1879
|
+
try {
|
|
1880
|
+
return await candidate;
|
|
1881
|
+
} catch (e) {
|
|
1882
|
+
lastError = e;
|
|
1883
|
+
}
|
|
1869
1884
|
}
|
|
1885
|
+
throw err_nice_transport.fromId("initialization_failed" /* initialization_failed */, {
|
|
1886
|
+
actionId: action.id
|
|
1887
|
+
}).withOriginError(lastError);
|
|
1870
1888
|
}
|
|
1871
1889
|
}
|
|
1872
1890
|
|
|
@@ -1926,20 +1944,19 @@ class ActionExternalClientHandler extends ActionHandler {
|
|
|
1926
1944
|
const incomingTimeout = config?.timeout ?? this._defaultTimeout;
|
|
1927
1945
|
const parentCuid = peekHandlerCuid();
|
|
1928
1946
|
const callSite = action._callSite ?? new Error().stack;
|
|
1929
|
-
const
|
|
1947
|
+
const routeParams = {
|
|
1930
1948
|
action,
|
|
1931
1949
|
localClient,
|
|
1932
1950
|
externalClient: this.externalClient
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1951
|
+
};
|
|
1952
|
+
const preferredTransport = this.transportManager.getPreferredTransport();
|
|
1953
|
+
const routeItem = preferredTransport != null ? {
|
|
1935
1954
|
runtime: localClient,
|
|
1936
|
-
handler: this.toHandlerRouteItem(
|
|
1937
|
-
action,
|
|
1938
|
-
localClient,
|
|
1939
|
-
externalClient: this.externalClient
|
|
1940
|
-
}),
|
|
1955
|
+
handler: this.toHandlerRouteItem(preferredTransport, routeParams),
|
|
1941
1956
|
time: Date.now()
|
|
1942
|
-
}
|
|
1957
|
+
} : undefined;
|
|
1958
|
+
if (routeItem != null)
|
|
1959
|
+
action.context.addRouteItem(routeItem);
|
|
1943
1960
|
const runningAction = new RunningAction({
|
|
1944
1961
|
context: action.context,
|
|
1945
1962
|
request: action,
|
|
@@ -1947,23 +1964,37 @@ class ActionExternalClientHandler extends ActionHandler {
|
|
|
1947
1964
|
callSite
|
|
1948
1965
|
});
|
|
1949
1966
|
localRuntime.registerRunningAction(runningAction);
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
timeout: incomingTimeout
|
|
1956
|
-
};
|
|
1957
|
-
if (action.type === "request" /* request */ && methods.updateRunConfig != null) {
|
|
1958
|
-
const runConfig = methods.updateRunConfig(routeActionParams);
|
|
1959
|
-
routeActionParams.timeout = runConfig?.timeout ?? incomingTimeout;
|
|
1960
|
-
}
|
|
1967
|
+
this._dispatchWhenTransportReady(runningAction, routeParams, routeItem, incomingTimeout);
|
|
1968
|
+
return runningAction;
|
|
1969
|
+
}
|
|
1970
|
+
async _dispatchWhenTransportReady(runningAction, routeParams, routeItem, incomingTimeout) {
|
|
1971
|
+
const action = routeParams.action;
|
|
1961
1972
|
try {
|
|
1962
|
-
methods.
|
|
1973
|
+
const { methods, transport } = await this.transportManager.getReadyTransport(routeParams);
|
|
1974
|
+
const handlerRouteItem = this.toHandlerRouteItem(transport, routeParams);
|
|
1975
|
+
if (routeItem != null) {
|
|
1976
|
+
routeItem.handler = handlerRouteItem;
|
|
1977
|
+
routeItem.time = Date.now();
|
|
1978
|
+
} else {
|
|
1979
|
+
action.context.addRouteItem({
|
|
1980
|
+
runtime: routeParams.localClient,
|
|
1981
|
+
handler: handlerRouteItem,
|
|
1982
|
+
time: Date.now()
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
const sendInput = {
|
|
1986
|
+
...routeParams,
|
|
1987
|
+
runningAction,
|
|
1988
|
+
timeout: incomingTimeout
|
|
1989
|
+
};
|
|
1990
|
+
if (action.type === "request" /* request */ && methods.updateRunConfig != null) {
|
|
1991
|
+
const runConfig = methods.updateRunConfig(sendInput);
|
|
1992
|
+
sendInput.timeout = runConfig?.timeout ?? incomingTimeout;
|
|
1993
|
+
}
|
|
1994
|
+
methods.sendActionData(sendInput);
|
|
1963
1995
|
} catch (err3) {
|
|
1964
1996
|
runningAction._abort(err3);
|
|
1965
1997
|
}
|
|
1966
|
-
return runningAction;
|
|
1967
1998
|
}
|
|
1968
1999
|
async sendReturnPayload(payload, config) {
|
|
1969
2000
|
const localClient = config.targetLocalRuntime.coordinate;
|
|
@@ -27,6 +27,7 @@ export declare class ActionExternalClientHandler extends ActionHandler<EActionHa
|
|
|
27
27
|
forActionIds<ACT_DOM extends IActionDomain, IDS extends ReadonlyArray<keyof ACT_DOM["actionSchema"] & string>>(domain: ActionDomain<ACT_DOM>, ids: IDS): this;
|
|
28
28
|
_setIncomingActionDataListener(listener: (json: TActionPayload_Any_JsonObject<any, any>) => void): void;
|
|
29
29
|
handleActionRequest<DOM extends IActionDomain, ID extends keyof DOM["actionSchema"] & string>(action: ActionPayload_Request<DOM, ID>, config?: IHandleActionOptions): Promise<RunningAction<DOM, ID>>;
|
|
30
|
+
private _dispatchWhenTransportReady;
|
|
30
31
|
/**
|
|
31
32
|
* Dispatch a result or progress payload directly back to the external client via the best
|
|
32
33
|
* available bidirectional transport (WebSocket / Custom). Used for return-path routing when the
|
package/build/types/ActionRuntime/Handler/ExternalClient/Transport/ConnectionTransportManager.d.ts
CHANGED
|
@@ -5,5 +5,12 @@ export declare class ConnectionTransportManager {
|
|
|
5
5
|
private _transports;
|
|
6
6
|
constructor(_cache: TTransportCache);
|
|
7
7
|
addTransport(transport: TransportConnection): void;
|
|
8
|
+
/**
|
|
9
|
+
* The highest-priority transport (first declared). Used to label an action's route *before* the
|
|
10
|
+
* transport has finished connecting — so a still-connecting action shows its (expected) destination
|
|
11
|
+
* instead of an "unknown" hop. {@link getReadyTransport} still decides the real winner, and the
|
|
12
|
+
* caller corrects the hop if a lower-priority transport ends up serving the action.
|
|
13
|
+
*/
|
|
14
|
+
getPreferredTransport(): TransportConnection | undefined;
|
|
8
15
|
getReadyTransport(routeActionParams: ITransportRouteActionParams): Promise<IActionTransportReady>;
|
|
9
16
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ESize } from "../ui_util/size";
|
|
2
|
+
/**
|
|
3
|
+
* Marks an action that was received from another runtime (a backend push, or an action relayed from
|
|
4
|
+
* another client) rather than dispatched locally. The chip shows the origin's `envId`; the tooltip
|
|
5
|
+
* carries the full coordinate. Render it only when {@link getInboundOrigin} returns a value.
|
|
6
|
+
*/
|
|
7
|
+
export declare function OriginChip({ origin, size, subtle, }: {
|
|
8
|
+
origin: {
|
|
9
|
+
envId: string;
|
|
10
|
+
perId?: string;
|
|
11
|
+
insId?: string;
|
|
12
|
+
};
|
|
13
|
+
size?: ESize;
|
|
14
|
+
subtle?: boolean;
|
|
15
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -5,6 +5,17 @@ export declare const STATUS_COLOR: Record<TDevtoolsActionStatus, string>;
|
|
|
5
5
|
export declare const STATUS_THING: Record<TDevtoolsActionStatus, ESemanticThing>;
|
|
6
6
|
export declare const STATUS_SYMBOL: Record<TDevtoolsActionStatus, string>;
|
|
7
7
|
export declare const STATUS_ICON: Record<TDevtoolsActionStatus, LucideIcon>;
|
|
8
|
+
/**
|
|
9
|
+
* The runtime an action *originated* on, when that differs from the runtime that handled it — i.e. an
|
|
10
|
+
* inbound action received over a transport (a backend push, or an action relayed from another client),
|
|
11
|
+
* rather than one dispatched locally. Returns `null` for locally-originated actions (where the origin
|
|
12
|
+
* matches the handling runtime) and for actions with no known origin.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getInboundOrigin(entry: IDevtoolsActionEntry): {
|
|
15
|
+
envId: string;
|
|
16
|
+
perId?: string;
|
|
17
|
+
insId?: string;
|
|
18
|
+
} | null;
|
|
8
19
|
export declare function safeStringify(value: unknown, indent?: number): string;
|
|
9
20
|
export declare function formatRelativeAge(ms: number): string;
|
|
10
21
|
export declare function formatDuration(entry: IDevtoolsActionEntry): string | null;
|
|
@@ -54,6 +54,7 @@ export declare enum ESemanticThing {
|
|
|
54
54
|
domain = "domain",
|
|
55
55
|
handler_local = "handler_local",
|
|
56
56
|
handler_external = "handler_external",
|
|
57
|
+
origin = "origin",// runtime an action was received from (inbound / pushed actions)
|
|
57
58
|
age = "age",// non-latest relative-age chip
|
|
58
59
|
io_input = "io_input",
|
|
59
60
|
io_output = "io_output",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nice-code/action",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"build-types": "tsc --project tsconfig.build.json"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@nice-code/common-errors": "0.6.
|
|
48
|
-
"@nice-code/error": "0.6.
|
|
49
|
-
"@nice-code/util": "0.6.
|
|
47
|
+
"@nice-code/common-errors": "0.6.3",
|
|
48
|
+
"@nice-code/error": "0.6.3",
|
|
49
|
+
"@nice-code/util": "0.6.3",
|
|
50
50
|
"@standard-schema/spec": "^1.1.0",
|
|
51
51
|
"@tanstack/react-virtual": "^3.13.26",
|
|
52
52
|
"http-status-codes": "^2.3.0",
|