@nice-code/action 0.5.1 → 0.5.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 +4 -1
- package/build/devtools/server/index.js +246 -0
- package/build/index.js +2548 -206
- package/package.json +4 -4
|
@@ -2399,7 +2399,10 @@ import { useEffect, useRef, useState as useState2 } from "react";
|
|
|
2399
2399
|
|
|
2400
2400
|
// src/devtools/browser/devtools_storage.ts
|
|
2401
2401
|
import { createTypedWebLocalStorage } from "@nice-code/util";
|
|
2402
|
-
var devtools_storage = createTypedWebLocalStorage(
|
|
2402
|
+
var devtools_storage = createTypedWebLocalStorage({
|
|
2403
|
+
localStorage: window.localStorage,
|
|
2404
|
+
keyPrefix: "nice-action-devtools::"
|
|
2405
|
+
});
|
|
2403
2406
|
devtools_storage.updateJsonWithDef("runtimeToProjectFilePath", {}, (prev) => prev);
|
|
2404
2407
|
|
|
2405
2408
|
// ../../node_modules/.bun/source-map-js@1.2.1/node_modules/source-map-js/source-map.js
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// src/devtools/server/NiceActionServerDevtools.ts
|
|
2
|
+
class ActionServerDevtools {
|
|
3
|
+
_options;
|
|
4
|
+
_inFlight = new Map;
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
const defaultEnabled = typeof process !== "undefined" ? true : true;
|
|
7
|
+
this._options = {
|
|
8
|
+
logger: options.logger ?? defaultConsoleLogger,
|
|
9
|
+
format: options.format ?? "pretty",
|
|
10
|
+
logPayloads: options.logPayloads ?? true,
|
|
11
|
+
enabled: options.enabled ?? defaultEnabled
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
attachToDomain(domain) {
|
|
15
|
+
if (!this._options.enabled) {
|
|
16
|
+
return () => {};
|
|
17
|
+
}
|
|
18
|
+
return domain.addActionListener((update) => {
|
|
19
|
+
const { runningAction, type, time } = update;
|
|
20
|
+
const actionPath = [...runningAction.allDomains, runningAction.id].join(".");
|
|
21
|
+
if (type === "started" /* started */) {
|
|
22
|
+
this._inFlight.set(runningAction.cuid, { startTime: time });
|
|
23
|
+
this._log("started", actionPath, runningAction.cuid, {
|
|
24
|
+
...this._options.logPayloads ? { input: runningAction.state?.request?.input } : {}
|
|
25
|
+
});
|
|
26
|
+
} else if (type === "progress" /* progress */) {
|
|
27
|
+
this._log("progress", actionPath, runningAction.cuid, { progress: update.progress });
|
|
28
|
+
} else if (type === "finished" /* finished */) {
|
|
29
|
+
const timing = this._inFlight.get(runningAction.cuid);
|
|
30
|
+
const duration = timing != null ? time - timing.startTime : undefined;
|
|
31
|
+
this._inFlight.delete(runningAction.cuid);
|
|
32
|
+
const finishType = update.finishType;
|
|
33
|
+
if (finishType === "success" /* success */) {
|
|
34
|
+
const result = update.response?.result;
|
|
35
|
+
if (result != null && !result.ok) {
|
|
36
|
+
this._log("action-error", actionPath, runningAction.cuid, {
|
|
37
|
+
...duration != null ? { duration: `${duration}ms` } : {},
|
|
38
|
+
error: serializeError(result.error)
|
|
39
|
+
});
|
|
40
|
+
} else {
|
|
41
|
+
this._log("success", actionPath, runningAction.cuid, {
|
|
42
|
+
...duration != null ? { duration: `${duration}ms` } : {},
|
|
43
|
+
...this._options.logPayloads ? { output: result?.output } : {}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
} else if (finishType === "failed" /* failed */) {
|
|
47
|
+
this._log("failed", actionPath, runningAction.cuid, {
|
|
48
|
+
...duration != null ? { duration: `${duration}ms` } : {},
|
|
49
|
+
error: serializeError(update.error)
|
|
50
|
+
});
|
|
51
|
+
} else {
|
|
52
|
+
this._log("aborted", actionPath, runningAction.cuid, {
|
|
53
|
+
...duration != null ? { duration: `${duration}ms` } : {},
|
|
54
|
+
...update.reason != null ? { reason: String(update.reason) } : {}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
_log(event, actionPath, cuid, data) {
|
|
61
|
+
const { logger, format } = this._options;
|
|
62
|
+
if (format === "json") {
|
|
63
|
+
logger(JSON.stringify({ time: new Date().toISOString(), event, action: actionPath, cuid, ...data }));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const prefix = PRETTY_PREFIX[event] ?? `[${event}]`;
|
|
67
|
+
const suffix = Object.keys(data).length > 0 ? ` ${formatPrettyData(data)}` : "";
|
|
68
|
+
logger(`${prefix} ${actionPath} cuid=${cuid}${suffix}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
var PRETTY_PREFIX = {
|
|
72
|
+
started: "[nice-action] ►",
|
|
73
|
+
progress: "[nice-action] ",
|
|
74
|
+
success: "[nice-action] ✓",
|
|
75
|
+
failed: "[nice-action] ✗",
|
|
76
|
+
aborted: "[nice-action] ○"
|
|
77
|
+
};
|
|
78
|
+
function formatPrettyData(data) {
|
|
79
|
+
return Object.entries(data).map(([k, v]) => `${k}=${safeStringify(v)}`).join(" ");
|
|
80
|
+
}
|
|
81
|
+
function safeStringify(value) {
|
|
82
|
+
if (value === undefined)
|
|
83
|
+
return "undefined";
|
|
84
|
+
if (value === null)
|
|
85
|
+
return "null";
|
|
86
|
+
if (typeof value === "string")
|
|
87
|
+
return `"${value}"`;
|
|
88
|
+
try {
|
|
89
|
+
return JSON.stringify(value);
|
|
90
|
+
} catch {
|
|
91
|
+
return String(value);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function serializeError(err) {
|
|
95
|
+
if (err == null)
|
|
96
|
+
return err;
|
|
97
|
+
if (err instanceof Error)
|
|
98
|
+
return { message: err.message, name: err.name, stack: err.stack };
|
|
99
|
+
if (typeof err === "object") {
|
|
100
|
+
try {
|
|
101
|
+
return JSON.parse(JSON.stringify(err));
|
|
102
|
+
} catch {
|
|
103
|
+
return String(err);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return err;
|
|
107
|
+
}
|
|
108
|
+
function defaultConsoleLogger(message) {
|
|
109
|
+
console.log(message);
|
|
110
|
+
}
|
|
111
|
+
// src/devtools/core/ActionDevtoolsCore.ts
|
|
112
|
+
function serializeErrorForDisplay(error) {
|
|
113
|
+
if (error != null && typeof error === "object" && error.name === "NiceError" && typeof error.toJsonObject === "function") {
|
|
114
|
+
return error.toJsonObject();
|
|
115
|
+
}
|
|
116
|
+
return error;
|
|
117
|
+
}
|
|
118
|
+
function extractRouting(context) {
|
|
119
|
+
return (context?.routing ?? []).map((item) => {
|
|
120
|
+
const handler = item.handler;
|
|
121
|
+
const isExternal = handler?.type === "external";
|
|
122
|
+
return {
|
|
123
|
+
runtime: {
|
|
124
|
+
envId: item.runtime?.envId ?? "unknown",
|
|
125
|
+
perId: item.runtime?.perId,
|
|
126
|
+
insId: item.runtime?.insId
|
|
127
|
+
},
|
|
128
|
+
handlerType: isExternal ? "external" : "local",
|
|
129
|
+
handlerClient: isExternal && handler.client != null ? {
|
|
130
|
+
envId: handler.client.envId ?? "unknown",
|
|
131
|
+
perId: handler.client.perId,
|
|
132
|
+
insId: handler.client.insId
|
|
133
|
+
} : undefined,
|
|
134
|
+
transport: isExternal ? handler.transType : undefined,
|
|
135
|
+
transportSummary: isExternal ? handler.transInfo?.summary : undefined,
|
|
136
|
+
transportUrl: isExternal ? handler.transInfo?.url : undefined,
|
|
137
|
+
time: item.time
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function extractMeta(context) {
|
|
142
|
+
return {
|
|
143
|
+
timeCreated: context?.timeCreated ?? Date.now(),
|
|
144
|
+
originClient: {
|
|
145
|
+
envId: context?.originClient?.envId ?? "unknown",
|
|
146
|
+
perId: context?.originClient?.perId,
|
|
147
|
+
insId: context?.originClient?.insId
|
|
148
|
+
},
|
|
149
|
+
routing: extractRouting(context)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
class ActionDevtoolsCore {
|
|
154
|
+
_entries = [];
|
|
155
|
+
_listeners = new Set;
|
|
156
|
+
constructor(_options = {}) {}
|
|
157
|
+
attachToDomain(domain) {
|
|
158
|
+
return domain.addActionListener((update) => {
|
|
159
|
+
const { runningAction, type, time } = update;
|
|
160
|
+
if (type === "started" /* started */) {
|
|
161
|
+
const entry = {
|
|
162
|
+
cuid: runningAction.cuid,
|
|
163
|
+
actionId: runningAction.id,
|
|
164
|
+
domain: runningAction.domain,
|
|
165
|
+
allDomains: [...runningAction.allDomains],
|
|
166
|
+
status: "running",
|
|
167
|
+
startTime: time,
|
|
168
|
+
input: runningAction.state?.request?.input,
|
|
169
|
+
inputHash: runningAction.state?.request?.inputHash,
|
|
170
|
+
progressUpdates: [],
|
|
171
|
+
meta: extractMeta(runningAction.context),
|
|
172
|
+
parentCuid: runningAction.parentCuid,
|
|
173
|
+
callSite: runningAction.callSite
|
|
174
|
+
};
|
|
175
|
+
this._entries = [entry, ...this._entries];
|
|
176
|
+
this._notify();
|
|
177
|
+
} else if (type === "progress" /* progress */) {
|
|
178
|
+
this._updateEntry(runningAction.cuid, (e) => ({
|
|
179
|
+
...e,
|
|
180
|
+
progressUpdates: [...e.progressUpdates, update.progress]
|
|
181
|
+
}));
|
|
182
|
+
} else if (type === "finished" /* finished */) {
|
|
183
|
+
this._updateEntry(runningAction.cuid, (e) => {
|
|
184
|
+
const finishedRoutingContext = update.response?.context ?? runningAction.context;
|
|
185
|
+
const base = {
|
|
186
|
+
...e,
|
|
187
|
+
endTime: time,
|
|
188
|
+
meta: { ...e.meta, routing: extractRouting(finishedRoutingContext) }
|
|
189
|
+
};
|
|
190
|
+
const finishType = update.finishType;
|
|
191
|
+
if (finishType === "success" /* success */) {
|
|
192
|
+
const result = update.response?.result;
|
|
193
|
+
const outputHash = update.response?.outputHash;
|
|
194
|
+
if (result != null && !result.ok) {
|
|
195
|
+
const rawError = result.error;
|
|
196
|
+
const errorStack2 = rawError instanceof Error ? rawError.stack : undefined;
|
|
197
|
+
return {
|
|
198
|
+
...base,
|
|
199
|
+
status: "action-error",
|
|
200
|
+
outputHash,
|
|
201
|
+
error: serializeErrorForDisplay(rawError),
|
|
202
|
+
errorStack: errorStack2
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return { ...base, status: "success", output: result?.output, outputHash };
|
|
206
|
+
}
|
|
207
|
+
if (finishType === "failed" /* failed */) {
|
|
208
|
+
const rawError = update.error;
|
|
209
|
+
const errorStack2 = rawError instanceof Error ? rawError.stack : undefined;
|
|
210
|
+
return { ...base, status: "failed", error: serializeErrorForDisplay(rawError), errorStack: errorStack2 };
|
|
211
|
+
}
|
|
212
|
+
const abortReason = update.reason;
|
|
213
|
+
const errorStack = abortReason instanceof Error ? abortReason.stack : undefined;
|
|
214
|
+
return { ...base, status: "aborted", abortReason: serializeErrorForDisplay(abortReason), errorStack };
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
getEntries() {
|
|
220
|
+
return this._entries;
|
|
221
|
+
}
|
|
222
|
+
subscribe(listener) {
|
|
223
|
+
this._listeners.add(listener);
|
|
224
|
+
listener(this._entries);
|
|
225
|
+
return () => {
|
|
226
|
+
this._listeners.delete(listener);
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
clear() {
|
|
230
|
+
this._entries = [];
|
|
231
|
+
this._notify();
|
|
232
|
+
}
|
|
233
|
+
_updateEntry(cuid, updater) {
|
|
234
|
+
this._entries = this._entries.map((e) => e.cuid === cuid ? updater(e) : e);
|
|
235
|
+
this._notify();
|
|
236
|
+
}
|
|
237
|
+
_notify() {
|
|
238
|
+
const snapshot = this._entries;
|
|
239
|
+
for (const listener of this._listeners)
|
|
240
|
+
listener(snapshot);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
export {
|
|
244
|
+
ActionServerDevtools,
|
|
245
|
+
ActionDevtoolsCore
|
|
246
|
+
};
|