@nice-code/action 0.6.2 → 0.7.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/build/devtools/browser/index.js +141 -23
- package/build/index.js +141 -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/ActionRuntime/Handler/ExternalClient/Transport/WebSocket/secureWsChannel.d.ts +63 -0
- package/build/types/ActionRuntime/Handler/Server/ActionServerHandler.d.ts +7 -1
- package/build/types/ActionRuntime/Handler/Server/createSecureActionServer.d.ts +71 -0
- package/build/types/index.d.ts +2 -0
- package/package.json +4 -4
|
@@ -5516,6 +5516,7 @@ var PREFS_KEY = "__nice-action-devtools-prefs";
|
|
|
5516
5516
|
var DOCKED_HEIGHT_DEFAULT = 320;
|
|
5517
5517
|
var DOCKED_WIDTH_DEFAULT = 420;
|
|
5518
5518
|
var DETAIL_RATIO_DEFAULT = 0.5;
|
|
5519
|
+
var SANS_FONT2 = "ui-sans-serif, system-ui, sans-serif";
|
|
5519
5520
|
var DOCK_POSITIONS = ["dock-bottom", "dock-top", "dock-left", "dock-right"];
|
|
5520
5521
|
function isDockPosition(value) {
|
|
5521
5522
|
return typeof value === "string" && DOCK_POSITIONS.includes(value);
|
|
@@ -5526,7 +5527,9 @@ function readPrefs(defaultPosition, initialOpen) {
|
|
|
5526
5527
|
isOpen: initialOpen,
|
|
5527
5528
|
dockedHeight: DOCKED_HEIGHT_DEFAULT,
|
|
5528
5529
|
dockedWidth: DOCKED_WIDTH_DEFAULT,
|
|
5529
|
-
detailRatio: DETAIL_RATIO_DEFAULT
|
|
5530
|
+
detailRatio: DETAIL_RATIO_DEFAULT,
|
|
5531
|
+
stayOnLatest: true,
|
|
5532
|
+
followLatestOnSelect: true
|
|
5530
5533
|
};
|
|
5531
5534
|
try {
|
|
5532
5535
|
if (typeof localStorage === "undefined")
|
|
@@ -5555,15 +5558,23 @@ function getHandlerKey(entry) {
|
|
|
5555
5558
|
return "local";
|
|
5556
5559
|
return `ext:${hop.transport ?? "ext"}`;
|
|
5557
5560
|
}
|
|
5561
|
+
function entriesShareActionInput(a, b) {
|
|
5562
|
+
if (a.actionId !== b.actionId || a.domain !== b.domain)
|
|
5563
|
+
return false;
|
|
5564
|
+
return a.inputHash != null && b.inputHash != null ? a.inputHash === b.inputHash : safeStringify(a.input, 0) === safeStringify(b.input, 0);
|
|
5565
|
+
}
|
|
5558
5566
|
function canGroupWith(a, b) {
|
|
5559
|
-
if (a
|
|
5567
|
+
if (!entriesShareActionInput(a, b))
|
|
5560
5568
|
return false;
|
|
5561
5569
|
const handlerA = getHandlerKey(a);
|
|
5562
5570
|
const handlerB = getHandlerKey(b);
|
|
5563
5571
|
const handlerConflict = handlerA !== "none" && handlerB !== "none" && handlerA !== handlerB;
|
|
5564
|
-
|
|
5572
|
+
if (handlerConflict)
|
|
5573
|
+
return false;
|
|
5574
|
+
if (a.status === "running" || b.status === "running")
|
|
5575
|
+
return true;
|
|
5565
5576
|
const outputMatch = a.outputHash != null && b.outputHash != null ? a.outputHash === b.outputHash : true;
|
|
5566
|
-
return a.
|
|
5577
|
+
return a.status === b.status && outputMatch;
|
|
5567
5578
|
}
|
|
5568
5579
|
function groupEntries(entries) {
|
|
5569
5580
|
const groups = [];
|
|
@@ -5596,7 +5607,7 @@ function NiceActionDevtools_Panel({
|
|
|
5596
5607
|
useEffect4(() => core.subscribe(setEntries), [core]);
|
|
5597
5608
|
const groups = useMemo3(() => {
|
|
5598
5609
|
const byCuid = new Map(entries.map((e) => [e.cuid, e]));
|
|
5599
|
-
const roots = entries.filter((e) => e.
|
|
5610
|
+
const roots = entries.filter((e) => e.parentCuid == null || !byCuid.has(e.parentCuid));
|
|
5600
5611
|
return groupEntries(roots);
|
|
5601
5612
|
}, [entries]);
|
|
5602
5613
|
const childEntriesMap = useMemo3(() => {
|
|
@@ -5612,16 +5623,6 @@ function NiceActionDevtools_Panel({
|
|
|
5612
5623
|
}
|
|
5613
5624
|
return map;
|
|
5614
5625
|
}, [entries]);
|
|
5615
|
-
const handleGroupRowClick = (group) => {
|
|
5616
|
-
const repCuid = group.representative.cuid;
|
|
5617
|
-
const allInGroup = [group.representative, ...group.rest];
|
|
5618
|
-
const selectedInGroup = allInGroup.find((e) => e.cuid === selectedCuid) ?? null;
|
|
5619
|
-
if (selectedInGroup != null && selectedCuid !== repCuid) {
|
|
5620
|
-
setSelectedCuid(repCuid);
|
|
5621
|
-
} else {
|
|
5622
|
-
setSelectedCuid(selectedCuid === repCuid ? null : repCuid);
|
|
5623
|
-
}
|
|
5624
|
-
};
|
|
5625
5626
|
const setPrefs = (update) => {
|
|
5626
5627
|
setPrefsRaw((prev) => ({ ...prev, ...update }));
|
|
5627
5628
|
};
|
|
@@ -5629,10 +5630,34 @@ function NiceActionDevtools_Panel({
|
|
|
5629
5630
|
const timer = setTimeout(() => writePrefs(prefs), 250);
|
|
5630
5631
|
return () => clearTimeout(timer);
|
|
5631
5632
|
}, [prefs]);
|
|
5632
|
-
const { position, isOpen, dockedHeight, dockedWidth, detailRatio } = prefs;
|
|
5633
|
+
const { position, isOpen, dockedHeight, dockedWidth, detailRatio, stayOnLatest, followLatestOnSelect } = prefs;
|
|
5633
5634
|
const dockSide = getDockSide(position);
|
|
5634
5635
|
const isHorizDock = dockSide === "top" || dockSide === "bottom";
|
|
5635
5636
|
const dockedSize = isHorizDock ? dockedHeight : dockedWidth;
|
|
5637
|
+
const latestCuid = groups.length > 0 ? groups[0].representative.cuid : null;
|
|
5638
|
+
useEffect4(() => {
|
|
5639
|
+
if (stayOnLatest && latestCuid != null)
|
|
5640
|
+
setSelectedCuid(latestCuid);
|
|
5641
|
+
}, [stayOnLatest, latestCuid]);
|
|
5642
|
+
const applySelection = (next) => {
|
|
5643
|
+
if (next != null && next === latestCuid && followLatestOnSelect) {
|
|
5644
|
+
if (!stayOnLatest)
|
|
5645
|
+
setPrefs({ stayOnLatest: true });
|
|
5646
|
+
} else if (stayOnLatest) {
|
|
5647
|
+
setPrefs({ stayOnLatest: false });
|
|
5648
|
+
}
|
|
5649
|
+
setSelectedCuid(next);
|
|
5650
|
+
};
|
|
5651
|
+
const handleGroupRowClick = (group) => {
|
|
5652
|
+
const repCuid = group.representative.cuid;
|
|
5653
|
+
const allInGroup = [group.representative, ...group.rest];
|
|
5654
|
+
const selectedInGroup = allInGroup.find((e) => e.cuid === selectedCuid) ?? null;
|
|
5655
|
+
if (selectedInGroup != null && selectedCuid !== repCuid) {
|
|
5656
|
+
applySelection(repCuid);
|
|
5657
|
+
} else {
|
|
5658
|
+
applySelection(selectedCuid === repCuid ? null : repCuid);
|
|
5659
|
+
}
|
|
5660
|
+
};
|
|
5636
5661
|
const selectedEntry = selectedCuid != null ? entries.find((e) => e.cuid === selectedCuid) : null;
|
|
5637
5662
|
const runningCount = entries.filter((e) => e.status === "running").length;
|
|
5638
5663
|
const dock = useMemo3(() => getDevtoolsDockCoordinator(), []);
|
|
@@ -5716,7 +5741,7 @@ function NiceActionDevtools_Panel({
|
|
|
5716
5741
|
selectedCuid,
|
|
5717
5742
|
onGroupClick: handleGroupRowClick,
|
|
5718
5743
|
onSubClick: (cuid, isSelected) => {
|
|
5719
|
-
|
|
5744
|
+
applySelection(isSelected ? null : cuid);
|
|
5720
5745
|
},
|
|
5721
5746
|
childEntriesMap
|
|
5722
5747
|
};
|
|
@@ -5748,18 +5773,35 @@ function NiceActionDevtools_Panel({
|
|
|
5748
5773
|
minHeight: 0
|
|
5749
5774
|
},
|
|
5750
5775
|
children: [
|
|
5751
|
-
/* @__PURE__ */
|
|
5776
|
+
/* @__PURE__ */ jsxs20("div", {
|
|
5752
5777
|
style: {
|
|
5753
5778
|
flexGrow: selectedEntry != null ? 1 - detailRatio : 1,
|
|
5754
5779
|
flexShrink: 1,
|
|
5755
5780
|
flexBasis: 0,
|
|
5756
5781
|
minWidth: 0,
|
|
5757
|
-
minHeight: 0
|
|
5782
|
+
minHeight: 0,
|
|
5783
|
+
display: "flex",
|
|
5784
|
+
flexDirection: "column",
|
|
5785
|
+
overflow: "hidden"
|
|
5758
5786
|
},
|
|
5759
|
-
children:
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5787
|
+
children: [
|
|
5788
|
+
/* @__PURE__ */ jsx23(FollowToggles, {
|
|
5789
|
+
stayOnLatest,
|
|
5790
|
+
onStayOnLatestChange: (next) => setPrefs({ stayOnLatest: next }),
|
|
5791
|
+
followLatestOnSelect,
|
|
5792
|
+
onFollowLatestOnSelectChange: (next) => {
|
|
5793
|
+
if (next && latestCuid != null && selectedCuid === latestCuid && !stayOnLatest) {
|
|
5794
|
+
setPrefs({ followLatestOnSelect: next, stayOnLatest: true });
|
|
5795
|
+
} else {
|
|
5796
|
+
setPrefs({ followLatestOnSelect: next });
|
|
5797
|
+
}
|
|
5798
|
+
}
|
|
5799
|
+
}),
|
|
5800
|
+
/* @__PURE__ */ jsx23(ActionList, {
|
|
5801
|
+
...virtualListProps,
|
|
5802
|
+
style: { width: "100%", flex: 1, minHeight: 0, overflowY: "auto" }
|
|
5803
|
+
})
|
|
5804
|
+
]
|
|
5763
5805
|
}),
|
|
5764
5806
|
selectedEntry != null && /* @__PURE__ */ jsxs20(Fragment11, {
|
|
5765
5807
|
children: [
|
|
@@ -5799,6 +5841,82 @@ function NiceActionDevtools_Panel({
|
|
|
5799
5841
|
]
|
|
5800
5842
|
});
|
|
5801
5843
|
}
|
|
5844
|
+
function FollowToggles({
|
|
5845
|
+
stayOnLatest,
|
|
5846
|
+
onStayOnLatestChange,
|
|
5847
|
+
followLatestOnSelect,
|
|
5848
|
+
onFollowLatestOnSelectChange
|
|
5849
|
+
}) {
|
|
5850
|
+
return /* @__PURE__ */ jsxs20("div", {
|
|
5851
|
+
style: {
|
|
5852
|
+
display: "flex",
|
|
5853
|
+
flexDirection: "column",
|
|
5854
|
+
flexShrink: 0,
|
|
5855
|
+
paddingBottom: "3px",
|
|
5856
|
+
background: DEVTOOL_SECTION_BACKGROUND,
|
|
5857
|
+
borderBottom: `1px solid ${DEVTOOL_LIST_BASE_BACKGROUND}`
|
|
5858
|
+
},
|
|
5859
|
+
children: [
|
|
5860
|
+
/* @__PURE__ */ jsx23(ToggleLabel, {
|
|
5861
|
+
title: "Auto-select the most recent action so the detail pane keeps showing the latest as new actions land",
|
|
5862
|
+
checked: stayOnLatest,
|
|
5863
|
+
onChange: onStayOnLatestChange,
|
|
5864
|
+
children: "Follow latest"
|
|
5865
|
+
}),
|
|
5866
|
+
/* @__PURE__ */ jsxs20("div", {
|
|
5867
|
+
style: { display: "flex", alignItems: "center", paddingLeft: "12px", marginTop: "-4px" },
|
|
5868
|
+
children: [
|
|
5869
|
+
/* @__PURE__ */ jsx23("span", {
|
|
5870
|
+
"aria-hidden": true,
|
|
5871
|
+
style: {
|
|
5872
|
+
color: DEVTOOL_COLOR_TEXT_MUTED,
|
|
5873
|
+
fontFamily: SANS_FONT2,
|
|
5874
|
+
fontSize: "10px",
|
|
5875
|
+
lineHeight: 1
|
|
5876
|
+
},
|
|
5877
|
+
children: "└"
|
|
5878
|
+
}),
|
|
5879
|
+
/* @__PURE__ */ jsx23(ToggleLabel, {
|
|
5880
|
+
title: "When you click the latest action, turn 'Follow latest' back on so the view resumes tracking new actions. Turn this off to pin exactly to the action you click instead.",
|
|
5881
|
+
checked: followLatestOnSelect,
|
|
5882
|
+
onChange: onFollowLatestOnSelectChange,
|
|
5883
|
+
children: "clicking latest re-follows"
|
|
5884
|
+
})
|
|
5885
|
+
]
|
|
5886
|
+
})
|
|
5887
|
+
]
|
|
5888
|
+
});
|
|
5889
|
+
}
|
|
5890
|
+
function ToggleLabel({
|
|
5891
|
+
checked,
|
|
5892
|
+
onChange,
|
|
5893
|
+
title,
|
|
5894
|
+
children
|
|
5895
|
+
}) {
|
|
5896
|
+
return /* @__PURE__ */ jsxs20("label", {
|
|
5897
|
+
title,
|
|
5898
|
+
style: {
|
|
5899
|
+
display: "flex",
|
|
5900
|
+
alignItems: "center",
|
|
5901
|
+
gap: "6px",
|
|
5902
|
+
padding: "5px 10px",
|
|
5903
|
+
cursor: "pointer",
|
|
5904
|
+
userSelect: "none",
|
|
5905
|
+
color: checked ? DEVTOOL_COLOR_TEXT_SECONDARY : DEVTOOL_COLOR_TEXT_MUTED,
|
|
5906
|
+
fontSize: "10px",
|
|
5907
|
+
fontFamily: SANS_FONT2
|
|
5908
|
+
},
|
|
5909
|
+
children: [
|
|
5910
|
+
/* @__PURE__ */ jsx23("input", {
|
|
5911
|
+
type: "checkbox",
|
|
5912
|
+
checked,
|
|
5913
|
+
onChange: (e) => onChange(e.target.checked),
|
|
5914
|
+
style: { accentColor: DEVTOOL_COLOR_SEMANTIC_SYSTEM, cursor: "pointer", margin: 0 }
|
|
5915
|
+
}),
|
|
5916
|
+
children
|
|
5917
|
+
]
|
|
5918
|
+
});
|
|
5919
|
+
}
|
|
5802
5920
|
export {
|
|
5803
5921
|
NiceActionDevtools,
|
|
5804
5922
|
ActionDevtoolsCore
|
package/build/index.js
CHANGED
|
@@ -1803,20 +1803,24 @@ class ConnectionTransportManager {
|
|
|
1803
1803
|
addTransport(transport) {
|
|
1804
1804
|
this._transports.push(transport);
|
|
1805
1805
|
}
|
|
1806
|
+
getPreferredTransport() {
|
|
1807
|
+
return this._transports[0];
|
|
1808
|
+
}
|
|
1806
1809
|
async getReadyTransport(routeActionParams) {
|
|
1807
|
-
const initializingWaiters = [];
|
|
1808
|
-
const unavailableTransports = [];
|
|
1809
1810
|
const action = routeActionParams.action;
|
|
1811
|
+
const candidates = [];
|
|
1812
|
+
const unavailableTransports = [];
|
|
1810
1813
|
for (const transport of this._transports) {
|
|
1811
1814
|
const cacheKey = transport.getCacheKey(routeActionParams);
|
|
1812
1815
|
if (cacheKey != null) {
|
|
1813
1816
|
const cached = this._cache.get(cacheKey);
|
|
1814
1817
|
if (cached != null) {
|
|
1815
1818
|
if (cached instanceof Promise) {
|
|
1816
|
-
|
|
1819
|
+
candidates.push(cached);
|
|
1817
1820
|
continue;
|
|
1818
1821
|
}
|
|
1819
|
-
|
|
1822
|
+
candidates.push(Promise.resolve({ ...cached, transport }));
|
|
1823
|
+
break;
|
|
1820
1824
|
}
|
|
1821
1825
|
}
|
|
1822
1826
|
const statusInfo = transport.getTransport(routeActionParams);
|
|
@@ -1826,7 +1830,8 @@ class ConnectionTransportManager {
|
|
|
1826
1830
|
this._cache.set(cacheKey, { methods: readyData, transport });
|
|
1827
1831
|
readyData.addOnDisconnectListener?.(() => this._cache.delete(cacheKey));
|
|
1828
1832
|
}
|
|
1829
|
-
|
|
1833
|
+
candidates.push(Promise.resolve({ methods: readyData, transport }));
|
|
1834
|
+
break;
|
|
1830
1835
|
}
|
|
1831
1836
|
if (statusInfo.status === "unsupported" /* unsupported */) {
|
|
1832
1837
|
unavailableTransports.push(transport);
|
|
@@ -1856,10 +1861,10 @@ class ConnectionTransportManager {
|
|
|
1856
1861
|
if (cacheKey != null) {
|
|
1857
1862
|
this._cache.set(cacheKey, promise);
|
|
1858
1863
|
}
|
|
1859
|
-
|
|
1864
|
+
candidates.push(promise);
|
|
1860
1865
|
}
|
|
1861
1866
|
}
|
|
1862
|
-
if (
|
|
1867
|
+
if (candidates.length === 0) {
|
|
1863
1868
|
if (unavailableTransports.length > 0) {
|
|
1864
1869
|
throw err_nice_transport.fromId("unsupported" /* unsupported */, {
|
|
1865
1870
|
transportTypes: unavailableTransports.map((t) => t.type)
|
|
@@ -1869,13 +1874,17 @@ class ConnectionTransportManager {
|
|
|
1869
1874
|
actionId: action.id
|
|
1870
1875
|
});
|
|
1871
1876
|
}
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1877
|
+
let lastError;
|
|
1878
|
+
for (const candidate of candidates) {
|
|
1879
|
+
try {
|
|
1880
|
+
return await candidate;
|
|
1881
|
+
} catch (e) {
|
|
1882
|
+
lastError = e;
|
|
1883
|
+
}
|
|
1878
1884
|
}
|
|
1885
|
+
throw err_nice_transport.fromId("initialization_failed" /* initialization_failed */, {
|
|
1886
|
+
actionId: action.id
|
|
1887
|
+
}).withOriginError(lastError);
|
|
1879
1888
|
}
|
|
1880
1889
|
}
|
|
1881
1890
|
|
|
@@ -1935,20 +1944,19 @@ class ActionExternalClientHandler extends ActionHandler {
|
|
|
1935
1944
|
const incomingTimeout = config?.timeout ?? this._defaultTimeout;
|
|
1936
1945
|
const parentCuid = peekHandlerCuid();
|
|
1937
1946
|
const callSite = action._callSite ?? new Error().stack;
|
|
1938
|
-
const
|
|
1947
|
+
const routeParams = {
|
|
1939
1948
|
action,
|
|
1940
1949
|
localClient,
|
|
1941
1950
|
externalClient: this.externalClient
|
|
1942
|
-
}
|
|
1943
|
-
|
|
1951
|
+
};
|
|
1952
|
+
const preferredTransport = this.transportManager.getPreferredTransport();
|
|
1953
|
+
const routeItem = preferredTransport != null ? {
|
|
1944
1954
|
runtime: localClient,
|
|
1945
|
-
handler: this.toHandlerRouteItem(
|
|
1946
|
-
action,
|
|
1947
|
-
localClient,
|
|
1948
|
-
externalClient: this.externalClient
|
|
1949
|
-
}),
|
|
1955
|
+
handler: this.toHandlerRouteItem(preferredTransport, routeParams),
|
|
1950
1956
|
time: Date.now()
|
|
1951
|
-
}
|
|
1957
|
+
} : undefined;
|
|
1958
|
+
if (routeItem != null)
|
|
1959
|
+
action.context.addRouteItem(routeItem);
|
|
1952
1960
|
const runningAction = new RunningAction({
|
|
1953
1961
|
context: action.context,
|
|
1954
1962
|
request: action,
|
|
@@ -1956,23 +1964,37 @@ class ActionExternalClientHandler extends ActionHandler {
|
|
|
1956
1964
|
callSite
|
|
1957
1965
|
});
|
|
1958
1966
|
localRuntime.registerRunningAction(runningAction);
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
timeout: incomingTimeout
|
|
1965
|
-
};
|
|
1966
|
-
if (action.type === "request" /* request */ && methods.updateRunConfig != null) {
|
|
1967
|
-
const runConfig = methods.updateRunConfig(routeActionParams);
|
|
1968
|
-
routeActionParams.timeout = runConfig?.timeout ?? incomingTimeout;
|
|
1969
|
-
}
|
|
1967
|
+
this._dispatchWhenTransportReady(runningAction, routeParams, routeItem, incomingTimeout);
|
|
1968
|
+
return runningAction;
|
|
1969
|
+
}
|
|
1970
|
+
async _dispatchWhenTransportReady(runningAction, routeParams, routeItem, incomingTimeout) {
|
|
1971
|
+
const action = routeParams.action;
|
|
1970
1972
|
try {
|
|
1971
|
-
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);
|
|
1972
1995
|
} catch (err3) {
|
|
1973
1996
|
runningAction._abort(err3);
|
|
1974
1997
|
}
|
|
1975
|
-
return runningAction;
|
|
1976
1998
|
}
|
|
1977
1999
|
async sendReturnPayload(payload, config) {
|
|
1978
2000
|
const localClient = config.targetLocalRuntime.coordinate;
|
|
@@ -2934,6 +2956,9 @@ function createBinaryWsSessionFactory(domains, options) {
|
|
|
2934
2956
|
};
|
|
2935
2957
|
};
|
|
2936
2958
|
}
|
|
2959
|
+
// src/ActionRuntime/Handler/ExternalClient/Transport/WebSocket/secureWsChannel.ts
|
|
2960
|
+
import { ClientCryptoKeyLink } from "@nice-code/util";
|
|
2961
|
+
|
|
2937
2962
|
// src/utils/decodeActionFrame.ts
|
|
2938
2963
|
function decodeActionFrame(frame, decoder) {
|
|
2939
2964
|
const decoded = decoder?.incoming?.(frame) ?? (typeof frame === "string" ? parseJsonActionFrame(frame) : undefined);
|
|
@@ -3291,6 +3316,44 @@ class WebSocketTransport extends Transport {
|
|
|
3291
3316
|
};
|
|
3292
3317
|
}
|
|
3293
3318
|
}
|
|
3319
|
+
|
|
3320
|
+
// src/ActionRuntime/Handler/ExternalClient/Transport/WebSocket/secureWsChannel.ts
|
|
3321
|
+
function deriveDictionaryVersion(domains) {
|
|
3322
|
+
const { intToRoute } = buildActionRouteDictionary(domains);
|
|
3323
|
+
const signature = intToRoute.map((route) => `${route.domain}:${route.id}`).join(",");
|
|
3324
|
+
let hash = 2166136261;
|
|
3325
|
+
for (let i = 0;i < signature.length; i++) {
|
|
3326
|
+
hash ^= signature.charCodeAt(i);
|
|
3327
|
+
hash = Math.imul(hash, 16777619);
|
|
3328
|
+
}
|
|
3329
|
+
return `auto:${(hash >>> 0).toString(16).padStart(8, "0")}`;
|
|
3330
|
+
}
|
|
3331
|
+
function defineSecureWsChannel(options) {
|
|
3332
|
+
return {
|
|
3333
|
+
dictionaryVersion: options.dictionaryVersion ?? deriveDictionaryVersion(options.domains),
|
|
3334
|
+
createCodec: createBinaryWsSessionFactory(options.domains, options.sessionOptions)
|
|
3335
|
+
};
|
|
3336
|
+
}
|
|
3337
|
+
function createSecureWebSocketTransport(options) {
|
|
3338
|
+
const link = new ClientCryptoKeyLink({ storageAdapter: options.storageAdapter });
|
|
3339
|
+
return WebSocketTransport.create({
|
|
3340
|
+
createWebSocket: options.createWebSocket ?? (() => {
|
|
3341
|
+
const ws = new WebSocket(options.url);
|
|
3342
|
+
ws.binaryType = "arraybuffer";
|
|
3343
|
+
return ws;
|
|
3344
|
+
}),
|
|
3345
|
+
getTransportCacheKey: options.getTransportCacheKey ?? (() => [options.url]),
|
|
3346
|
+
createFormatMessage: options.channel.createCodec,
|
|
3347
|
+
updateRunConfig: options.updateRunConfig,
|
|
3348
|
+
getRouteInfo: options.getRouteInfo,
|
|
3349
|
+
security: {
|
|
3350
|
+
securityLevel: options.securityLevel,
|
|
3351
|
+
link,
|
|
3352
|
+
localCoordinate: options.runtime.coordinate.toJsonObject(),
|
|
3353
|
+
dictionaryVersion: options.channel.dictionaryVersion
|
|
3354
|
+
}
|
|
3355
|
+
});
|
|
3356
|
+
}
|
|
3294
3357
|
// src/ActionRuntime/Handler/Server/ActionServerHandler.ts
|
|
3295
3358
|
class ActionServerHandler extends ActionExternalClientHandler {
|
|
3296
3359
|
_formatMessage;
|
|
@@ -3343,6 +3406,9 @@ class ActionServerHandler extends ActionExternalClientHandler {
|
|
|
3343
3406
|
_setIncomingActionDataListener(listener) {
|
|
3344
3407
|
this._incomingListeners.push(listener);
|
|
3345
3408
|
}
|
|
3409
|
+
setOnConnectionBound(onConnectionBound) {
|
|
3410
|
+
this._onConnectionBound = onConnectionBound;
|
|
3411
|
+
}
|
|
3346
3412
|
receive(connection, frame) {
|
|
3347
3413
|
if (this._security == null || !this._handshakeMode) {
|
|
3348
3414
|
this._receivePlain(connection, frame);
|
|
@@ -3605,6 +3671,42 @@ class ActionServerHandler extends ActionExternalClientHandler {
|
|
|
3605
3671
|
var createServerHandler = (options) => {
|
|
3606
3672
|
return new ActionServerHandler(options);
|
|
3607
3673
|
};
|
|
3674
|
+
// src/ActionRuntime/Handler/Server/createSecureActionServer.ts
|
|
3675
|
+
import { ClientCryptoKeyLink as ClientCryptoKeyLink2 } from "@nice-code/util";
|
|
3676
|
+
var DEFAULT_SERVER_SECURITY_LEVELS = [
|
|
3677
|
+
"none" /* none */,
|
|
3678
|
+
"authenticated" /* authenticated */,
|
|
3679
|
+
"encrypted" /* encrypted */
|
|
3680
|
+
];
|
|
3681
|
+
function createSecureActionServerHandler(options) {
|
|
3682
|
+
const link = new ClientCryptoKeyLink2({ storageAdapter: options.storageAdapter });
|
|
3683
|
+
return new ActionServerHandler({
|
|
3684
|
+
clientEnv: options.clientEnv,
|
|
3685
|
+
createFormatMessage: options.channel.createCodec,
|
|
3686
|
+
send: options.send,
|
|
3687
|
+
defaultTimeout: options.defaultTimeout,
|
|
3688
|
+
security: {
|
|
3689
|
+
securityLevel: options.securityLevel ?? DEFAULT_SERVER_SECURITY_LEVELS,
|
|
3690
|
+
link,
|
|
3691
|
+
localCoordinate: options.runtime.coordinate.toJsonObject(),
|
|
3692
|
+
dictionaryVersion: options.channel.dictionaryVersion,
|
|
3693
|
+
verifyKeyResolver: options.verifyKeyResolver ?? createStorageTofuVerifyKeyResolver(options.storageAdapter)
|
|
3694
|
+
}
|
|
3695
|
+
});
|
|
3696
|
+
}
|
|
3697
|
+
function createHibernatableWsServerAdapter(options) {
|
|
3698
|
+
const { handler, getWebSockets, getAttachment, setAttachment } = options;
|
|
3699
|
+
handler.setOnConnectionBound(setAttachment);
|
|
3700
|
+
for (const connection of getWebSockets()) {
|
|
3701
|
+
const binding = getAttachment(connection);
|
|
3702
|
+
if (binding != null)
|
|
3703
|
+
handler.rehydrateConnection(connection, binding);
|
|
3704
|
+
}
|
|
3705
|
+
return {
|
|
3706
|
+
receive: (connection, frame) => handler.receive(connection, frame),
|
|
3707
|
+
drop: (connection) => handler.dropConnection(connection)
|
|
3708
|
+
};
|
|
3709
|
+
}
|
|
3608
3710
|
export {
|
|
3609
3711
|
runtimeLinkId,
|
|
3610
3712
|
isActionPayload_Result_JsonObject,
|
|
@@ -3615,13 +3717,17 @@ export {
|
|
|
3615
3717
|
err_nice_external_client,
|
|
3616
3718
|
err_nice_action,
|
|
3617
3719
|
encodeHandshakeMessage,
|
|
3720
|
+
defineSecureWsChannel,
|
|
3618
3721
|
decodeHandshakeMessage,
|
|
3619
3722
|
decodeActionFrame,
|
|
3620
3723
|
createStorageTofuVerifyKeyResolver,
|
|
3621
3724
|
createServerHandshake,
|
|
3622
3725
|
createServerHandler,
|
|
3726
|
+
createSecureWebSocketTransport,
|
|
3727
|
+
createSecureActionServerHandler,
|
|
3623
3728
|
createLocalHandler,
|
|
3624
3729
|
createInMemoryTofuVerifyKeyResolver,
|
|
3730
|
+
createHibernatableWsServerAdapter,
|
|
3625
3731
|
createExternalClientHandler,
|
|
3626
3732
|
createClientHandshake,
|
|
3627
3733
|
createBinaryWsSessionFactory,
|
|
@@ -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
|
}
|
package/build/types/ActionRuntime/Handler/ExternalClient/Transport/WebSocket/secureWsChannel.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type StorageAdapter } from "@nice-code/util";
|
|
2
|
+
import type { ActionDomain } from "../../../../../ActionDefinition/Domain/ActionDomain";
|
|
3
|
+
import type { ActionRuntime } from "../../../../ActionRuntime";
|
|
4
|
+
import type { ITransportRouteActionParams, ITransportRouteInfo, TUpdateActionRunConfig } from "../Transport.types";
|
|
5
|
+
import { ESecurityLevel } from "./actionWsHandshake";
|
|
6
|
+
import { type IBinaryWsSessionOptions } from "./createBinaryWsSessionFactory";
|
|
7
|
+
import type { IActionTransportReadyData_Ws } from "./TransportWebSocket.types";
|
|
8
|
+
import { WebSocketTransport } from "./WebSocketTransport";
|
|
9
|
+
/** The per-connection binary session codec — built once per socket from the channel's domains. */
|
|
10
|
+
type TChannelCodec = NonNullable<IActionTransportReadyData_Ws["formatMessage"]>;
|
|
11
|
+
/**
|
|
12
|
+
* The shared identity of a secure WebSocket channel: the wire dictionary version both ends check
|
|
13
|
+
* during the handshake, plus the per-connection codec factory both ends build from the *same* domain
|
|
14
|
+
* list. Define it once (typically in code shared by client and server) and hand it to
|
|
15
|
+
* {@link createSecureWebSocketTransport} on the client and `createSecureActionServerHandler` on the
|
|
16
|
+
* server, so the codec and version can never drift apart.
|
|
17
|
+
*/
|
|
18
|
+
export interface ISecureWsChannel {
|
|
19
|
+
/** Wire dictionary version — derived from the domains by default; the handshake rejects a mismatch. */
|
|
20
|
+
dictionaryVersion: string;
|
|
21
|
+
/** Per-connection session codec factory (call once per live connection). */
|
|
22
|
+
createCodec: () => TChannelCodec;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Bundle a secure channel's shared identity from its transported domains. Both ends MUST call this
|
|
26
|
+
* with the same domains in the same order (the binary wire dictionary is positional). The
|
|
27
|
+
* `dictionaryVersion` is derived from those domains unless you pin an explicit one.
|
|
28
|
+
*/
|
|
29
|
+
export declare function defineSecureWsChannel(options: {
|
|
30
|
+
/** Domains transported over this channel, in a stable order. Add new ones to the *end*. */
|
|
31
|
+
domains: ActionDomain<any>[];
|
|
32
|
+
/** Pin a human-readable version instead of the derived hash (must match on both ends). */
|
|
33
|
+
dictionaryVersion?: string;
|
|
34
|
+
/** Tuning for the per-connection binary session (e.g. correlation TTL). */
|
|
35
|
+
sessionOptions?: IBinaryWsSessionOptions;
|
|
36
|
+
}): ISecureWsChannel;
|
|
37
|
+
export interface ISecureWebSocketTransportOptions {
|
|
38
|
+
/** The shared channel identity (codec + dictionary version). */
|
|
39
|
+
channel: ISecureWsChannel;
|
|
40
|
+
/** This client's runtime — its coordinate is the authenticated identity sent in the handshake. */
|
|
41
|
+
runtime: ActionRuntime;
|
|
42
|
+
/** Backing store for this client's crypto identity (a stable verify key across reloads). */
|
|
43
|
+
storageAdapter: StorageAdapter;
|
|
44
|
+
/** The level this client requests; the server must allow it. */
|
|
45
|
+
securityLevel: ESecurityLevel;
|
|
46
|
+
/** Endpoint URL — drives both the socket and the per-endpoint cache key. */
|
|
47
|
+
url: string;
|
|
48
|
+
/** Override socket creation (defaults to a `new WebSocket(url)` with `binaryType = "arraybuffer"`). */
|
|
49
|
+
createWebSocket?: (input: ITransportRouteActionParams) => WebSocket;
|
|
50
|
+
/** Override the reuse key (defaults to `[url]`, so one socket is shared per endpoint). */
|
|
51
|
+
getTransportCacheKey?: (input: ITransportRouteActionParams) => string[];
|
|
52
|
+
updateRunConfig?: TUpdateActionRunConfig;
|
|
53
|
+
getRouteInfo?: (input: ITransportRouteActionParams) => ITransportRouteInfo;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build a {@link WebSocketTransport} for the secure binary channel with the boilerplate folded in: it
|
|
57
|
+
* creates the {@link ClientCryptoKeyLink} from `storageAdapter`, opens an `arraybuffer` socket to
|
|
58
|
+
* `url`, caches it per endpoint, installs the channel's per-connection codec, and assembles the
|
|
59
|
+
* `security` block from the runtime coordinate + channel version. Pass `createWebSocket` /
|
|
60
|
+
* `getTransportCacheKey` to take over those bits when you need to.
|
|
61
|
+
*/
|
|
62
|
+
export declare function createSecureWebSocketTransport(options: ISecureWebSocketTransportOptions): WebSocketTransport;
|
|
63
|
+
export {};
|
|
@@ -117,7 +117,7 @@ export declare class ActionServerHandler<TConn = unknown> extends ActionExternal
|
|
|
117
117
|
private readonly _createFormatMessage?;
|
|
118
118
|
private readonly _send;
|
|
119
119
|
private readonly _serverTimeout;
|
|
120
|
-
private
|
|
120
|
+
private _onConnectionBound?;
|
|
121
121
|
/** Incoming-data listeners installed by the runtime (`resolveIncomingActionPayload`). */
|
|
122
122
|
private readonly _incomingListeners;
|
|
123
123
|
private readonly _security?;
|
|
@@ -142,6 +142,12 @@ export declare class ActionServerHandler<TConn = unknown> extends ActionExternal
|
|
|
142
142
|
*/
|
|
143
143
|
private _codecFor;
|
|
144
144
|
_setIncomingActionDataListener(listener: (json: TActionPayload_Any_JsonObject<any>) => void): void;
|
|
145
|
+
/**
|
|
146
|
+
* Register (or replace) the connection-bound persistence callback after construction. Used by
|
|
147
|
+
* lifecycle helpers like {@link createHibernatableWsServerAdapter} so persistence and replay are
|
|
148
|
+
* owned by one place instead of being split across the constructor options.
|
|
149
|
+
*/
|
|
150
|
+
setOnConnectionBound(onConnectionBound: (connection: TConn, binding: IActionServerConnectionBinding) => void): void;
|
|
145
151
|
/**
|
|
146
152
|
* Feed one inbound frame from a connection into the runtime. Decodes text or binary, binds the
|
|
147
153
|
* connection to the requesting client's identity, then routes it (requests execute locally;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type StorageAdapter } from "@nice-code/util";
|
|
2
|
+
import type { ActionRuntime } from "../../ActionRuntime";
|
|
3
|
+
import type { RuntimeCoordinate } from "../../RuntimeCoordinate";
|
|
4
|
+
import { ESecurityLevel, type IClientVerifyKeyResolver } from "../ExternalClient/Transport/WebSocket/actionWsHandshake";
|
|
5
|
+
import type { ISecureWsChannel } from "../ExternalClient/Transport/WebSocket/secureWsChannel";
|
|
6
|
+
import { ActionServerHandler, type IActionServerConnectionBinding } from "./ActionServerHandler";
|
|
7
|
+
export interface ISecureActionServerHandlerOptions<TConn> {
|
|
8
|
+
/** The shared channel identity (codec + dictionary version) — same one the clients use. */
|
|
9
|
+
channel: ISecureWsChannel;
|
|
10
|
+
/**
|
|
11
|
+
* Coordinate of the *connecting clients* (typically env-only, e.g. `RuntimeCoordinate.env("web_app")`),
|
|
12
|
+
* used to route results/pushes back over this handler.
|
|
13
|
+
*/
|
|
14
|
+
clientEnv: RuntimeCoordinate;
|
|
15
|
+
/** This server's runtime — its coordinate is the server identity presented in the handshake. */
|
|
16
|
+
runtime: ActionRuntime;
|
|
17
|
+
/**
|
|
18
|
+
* One backing store for the server's crypto identity *and* its trust-on-first-use verify-key pins.
|
|
19
|
+
* Their keys don't collide, so a single adapter is enough; back it with persistent storage (e.g. a
|
|
20
|
+
* Durable Object's storage) so identity and pins survive eviction.
|
|
21
|
+
*/
|
|
22
|
+
storageAdapter: StorageAdapter;
|
|
23
|
+
/** Write an encoded frame to a specific live connection (e.g. `(ws, frame) => ws.send(frame)`). */
|
|
24
|
+
send: (connection: TConn, frame: string | Uint8Array | ArrayBuffer) => void;
|
|
25
|
+
/** Accepted level(s); defaults to negotiating any of none/authenticated/encrypted. */
|
|
26
|
+
securityLevel?: ESecurityLevel | readonly ESecurityLevel[];
|
|
27
|
+
/** Trust decision for a client's verify key; defaults to storage-backed TOFU over `storageAdapter`. */
|
|
28
|
+
verifyKeyResolver?: IClientVerifyKeyResolver;
|
|
29
|
+
/** Timeout (ms) applied to server-initiated actions awaiting a client response. */
|
|
30
|
+
defaultTimeout?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build an {@link ActionServerHandler} for the secure binary channel with the boilerplate folded in:
|
|
34
|
+
* it creates the {@link ClientCryptoKeyLink} and the storage-backed TOFU resolver from a single
|
|
35
|
+
* `storageAdapter`, installs the channel's per-connection codec, and assembles the `security` block
|
|
36
|
+
* from the runtime coordinate + channel version (accepting all three levels by default).
|
|
37
|
+
*
|
|
38
|
+
* For a hibernatable transport (e.g. a Durable Object), pair it with
|
|
39
|
+
* {@link createHibernatableWsServerAdapter} to wire persistence + replay.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createSecureActionServerHandler<TConn = unknown>(options: ISecureActionServerHandlerOptions<TConn>): ActionServerHandler<TConn>;
|
|
42
|
+
export interface IHibernatableWsServerAdapterOptions<TConn> {
|
|
43
|
+
/** The handler to drive (from {@link createSecureActionServerHandler} or `createServerHandler`). */
|
|
44
|
+
handler: ActionServerHandler<TConn>;
|
|
45
|
+
/** All currently-live connections — replayed on construction to rebuild bindings after a wake. */
|
|
46
|
+
getWebSockets: () => TConn[];
|
|
47
|
+
/** Read a connection's persisted binding (e.g. `(ws) => ws.deserializeAttachment()`). */
|
|
48
|
+
getAttachment: (connection: TConn) => IActionServerConnectionBinding | undefined;
|
|
49
|
+
/** Persist a connection's binding when it is bound (e.g. `(ws, b) => ws.serializeAttachment(b)`). */
|
|
50
|
+
setAttachment: (connection: TConn, binding: IActionServerConnectionBinding) => void;
|
|
51
|
+
}
|
|
52
|
+
export interface IHibernatableWsServerAdapter<TConn> {
|
|
53
|
+
/** Feed one inbound frame from a connection into the handler. */
|
|
54
|
+
receive: (connection: TConn, frame: string | ArrayBuffer | Uint8Array) => void;
|
|
55
|
+
/** Forget a connection (call on socket close/error). */
|
|
56
|
+
drop: (connection: TConn) => void;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Wire the hibernation lifecycle for a server handler on a transport whose sockets outlive process
|
|
60
|
+
* eviction (e.g. a Durable Object's hibernatable WebSockets). It owns persistence end to end:
|
|
61
|
+
* registers `setAttachment` as the handler's connection-bound callback and immediately replays every
|
|
62
|
+
* live connection's stored binding via `getAttachment`, so results/pushes still route after a wake.
|
|
63
|
+
*
|
|
64
|
+
* Construct it once when the handler is built, then forward socket events:
|
|
65
|
+
* ```ts
|
|
66
|
+
* const wsServer = createHibernatableWsServerAdapter({ handler, getWebSockets, getAttachment, setAttachment });
|
|
67
|
+
* // webSocketMessage(ws, msg) => wsServer.receive(ws, msg);
|
|
68
|
+
* // webSocketClose/Error(ws) => wsServer.drop(ws);
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare function createHibernatableWsServerAdapter<TConn>(options: IHibernatableWsServerAdapterOptions<TConn>): IHibernatableWsServerAdapter<TConn>;
|
package/build/types/index.d.ts
CHANGED
|
@@ -26,10 +26,12 @@ export { createActionFrameCrypto, type IActionFrameCrypto, type IActionFrameCryp
|
|
|
26
26
|
export { createClientHandshake, createInMemoryTofuVerifyKeyResolver, createServerHandshake, createStorageTofuVerifyKeyResolver, decodeHandshakeMessage, EHandshakeMessageType, ESecurityLevel, encodeHandshakeMessage, type IClientHandshakeConfig, type IClientVerifyKeyResolveInput, type IClientVerifyKeyResolver, type IHandshakeEncryptionKeyMaterial, type IHandshakeResult, type IServerHandshakeConfig, runtimeLinkId, type THandshakeMessage, } from "./ActionRuntime/Handler/ExternalClient/Transport/WebSocket/actionWsHandshake";
|
|
27
27
|
export { createBinaryWsAdapter } from "./ActionRuntime/Handler/ExternalClient/Transport/WebSocket/createBinaryWsAdapter";
|
|
28
28
|
export { createBinaryWsSessionFactory, type IBinaryWsSessionOptions, } from "./ActionRuntime/Handler/ExternalClient/Transport/WebSocket/createBinaryWsSessionFactory";
|
|
29
|
+
export { createSecureWebSocketTransport, defineSecureWsChannel, type ISecureWebSocketTransportOptions, type ISecureWsChannel, } from "./ActionRuntime/Handler/ExternalClient/Transport/WebSocket/secureWsChannel";
|
|
29
30
|
export type { IActionTransportDef_Ws, IActionTransportInitialized_Ws, IActionTransportReadyData_Ws, } from "./ActionRuntime/Handler/ExternalClient/Transport/WebSocket/TransportWebSocket.types";
|
|
30
31
|
export { type IWebSocketTransportAdvancedOptions, type IWebSocketTransportSocketOptions, type TWebSocketTransportOptions, WebSocketTransport, } from "./ActionRuntime/Handler/ExternalClient/Transport/WebSocket/WebSocketTransport";
|
|
31
32
|
export { ActionLocalHandler, createLocalHandler, } from "./ActionRuntime/Handler/Local/ActionLocalHandler";
|
|
32
33
|
export { ActionServerHandler, createServerHandler, type IActionServerConnectionBinding, type IActionServerHandlerOptions, type TActionChannelFormatMessage, type TActionConnectionEncoding, } from "./ActionRuntime/Handler/Server/ActionServerHandler";
|
|
34
|
+
export { createHibernatableWsServerAdapter, createSecureActionServerHandler, type IHibernatableWsServerAdapter, type IHibernatableWsServerAdapterOptions, type ISecureActionServerHandlerOptions, } from "./ActionRuntime/Handler/Server/createSecureActionServer";
|
|
33
35
|
export * from "./ActionRuntime/RuntimeCoordinate";
|
|
34
36
|
export { EErrId_NiceAction, err_nice_action } from "./errors/err_nice_action";
|
|
35
37
|
export { decodeActionFrame, type IActionFrameDecoder } from "./utils/decodeActionFrame";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nice-code/action",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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.
|
|
48
|
-
"@nice-code/error": "0.
|
|
49
|
-
"@nice-code/util": "0.
|
|
47
|
+
"@nice-code/common-errors": "0.7.0",
|
|
48
|
+
"@nice-code/error": "0.7.0",
|
|
49
|
+
"@nice-code/util": "0.7.0",
|
|
50
50
|
"@standard-schema/spec": "^1.1.0",
|
|
51
51
|
"@tanstack/react-virtual": "^3.13.26",
|
|
52
52
|
"http-status-codes": "^2.3.0",
|