@powerhousedao/reactor-workflow 6.2.3-dev.11
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/LICENSE +661 -0
- package/README.md +130 -0
- package/dist/descriptor-DXbWuxhE.js +169 -0
- package/dist/descriptor-DXbWuxhE.js.map +1 -0
- package/dist/index.d.ts +19068 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3771 -0
- package/dist/index.js.map +1 -0
- package/dist/piece-registry-BWWihLyp.js +1419 -0
- package/dist/piece-registry-BWWihLyp.js.map +1 -0
- package/dist/piece-registry-CE0UFmDA.d.ts +600 -0
- package/dist/piece-registry-CE0UFmDA.d.ts.map +1 -0
- package/dist/redact-C7LWgAyD.js +797 -0
- package/dist/redact-C7LWgAyD.js.map +1 -0
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +4 -0
- package/dist/worker-entry.d.ts +1 -0
- package/dist/worker-entry.js +605 -0
- package/dist/worker-entry.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
import { A as REACTOR_MODEL, C as jsonSafe, D as REACTOR_EXECUTE, E as REACTOR_CREATE, F as UnsupportedContextMemberError, I as throwingStub, L as withTouchTracking, M as STORE_DELETE, N as STORE_GET, O as REACTOR_FIND, P as STORE_PUT, R as getActions, S as buildActionContext, T as OUTPUT_UPDATE, a as redactMessage, b as InMemoryConnectionsProvider, d as buildTriggerContext, h as StagedFilesService, i as redactError, j as REACTOR_MODELS, k as REACTOR_GET, l as installEgressGuard, m as DataUriFilesService, p as runTriggerHook, u as runWithEgressPolicy, v as assertWithinLimit, w as LOG_WRITE, x as InMemoryKeyValueStore, y as maxFileBytes, z as getTriggers } from "./redact-C7LWgAyD.js";
|
|
2
|
+
import { i as loadPieceFromDir, n as describeProperties, r as loadPiece, t as buildDescriptor } from "./descriptor-DXbWuxhE.js";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { format } from "node:util";
|
|
5
|
+
import { arrayZipperProcessor, formatPieceError, processors } from "@powerhousedao/pieces-framework/host";
|
|
6
|
+
//#region src/pieces/activepieces/worker/host-call.ts
|
|
7
|
+
const DEFAULT_HOST_CALL_TIMEOUT_MS = 1e4;
|
|
8
|
+
const pending = /* @__PURE__ */ new Map();
|
|
9
|
+
let nextId = 1;
|
|
10
|
+
let listening = false;
|
|
11
|
+
var HostCallError = class extends Error {
|
|
12
|
+
constructor(method, detail) {
|
|
13
|
+
super(`Host call "${method}" failed: ${detail}`);
|
|
14
|
+
this.name = "HostCallError";
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var HostCallTimeoutError = class extends Error {
|
|
18
|
+
constructor(method, timeoutMs) {
|
|
19
|
+
super(`Host call "${method}" got no answer within ${timeoutMs}ms`);
|
|
20
|
+
this.name = "HostCallTimeoutError";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function isHostCallResponse(value) {
|
|
24
|
+
return typeof value === "object" && value !== null && value.type === "host-result";
|
|
25
|
+
}
|
|
26
|
+
function ensureListening() {
|
|
27
|
+
if (listening) return;
|
|
28
|
+
listening = true;
|
|
29
|
+
process.on("message", (message) => {
|
|
30
|
+
if (!isHostCallResponse(message)) return;
|
|
31
|
+
const entry = pending.get(message.id);
|
|
32
|
+
if (!entry) return;
|
|
33
|
+
pending.delete(message.id);
|
|
34
|
+
clearTimeout(entry.timer);
|
|
35
|
+
if (message.error !== void 0) {
|
|
36
|
+
entry.reject(new HostCallError(entry.method, message.error));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
entry.resolve(message.value);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function callHost(method, payload, timeoutMs = DEFAULT_HOST_CALL_TIMEOUT_MS) {
|
|
43
|
+
if (!process.send) return Promise.reject(new HostCallError(method, "the worker has no channel to its host"));
|
|
44
|
+
ensureListening();
|
|
45
|
+
const id = nextId++;
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
const timer = setTimeout(() => {
|
|
48
|
+
pending.delete(id);
|
|
49
|
+
reject(new HostCallTimeoutError(method, timeoutMs));
|
|
50
|
+
}, timeoutMs);
|
|
51
|
+
pending.set(id, {
|
|
52
|
+
method,
|
|
53
|
+
resolve,
|
|
54
|
+
reject,
|
|
55
|
+
timer
|
|
56
|
+
});
|
|
57
|
+
process.send?.({
|
|
58
|
+
id,
|
|
59
|
+
type: "host-call",
|
|
60
|
+
method,
|
|
61
|
+
payload
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function notifyHost(method, payload) {
|
|
66
|
+
try {
|
|
67
|
+
process.send?.({
|
|
68
|
+
type: "host-notify",
|
|
69
|
+
method,
|
|
70
|
+
payload
|
|
71
|
+
});
|
|
72
|
+
} catch {}
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/pieces/activepieces/context/reactor.ts
|
|
76
|
+
var RemoteReactorService = class {
|
|
77
|
+
models() {
|
|
78
|
+
return callHost(REACTOR_MODELS, {});
|
|
79
|
+
}
|
|
80
|
+
model(documentType) {
|
|
81
|
+
return callHost(REACTOR_MODEL, { documentType });
|
|
82
|
+
}
|
|
83
|
+
get(input) {
|
|
84
|
+
return callHost(REACTOR_GET, input);
|
|
85
|
+
}
|
|
86
|
+
find(input) {
|
|
87
|
+
return callHost(REACTOR_FIND, input);
|
|
88
|
+
}
|
|
89
|
+
create(input) {
|
|
90
|
+
return callHost(REACTOR_CREATE, input);
|
|
91
|
+
}
|
|
92
|
+
execute(input) {
|
|
93
|
+
return callHost(REACTOR_EXECUTE, input);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/pieces/activepieces/context/check.ts
|
|
98
|
+
function buildCheckConnectionContext(options = {}) {
|
|
99
|
+
const touched = /* @__PURE__ */ new Set();
|
|
100
|
+
return {
|
|
101
|
+
context: withTouchTracking({
|
|
102
|
+
auth: options.auth,
|
|
103
|
+
server: options.server ? {
|
|
104
|
+
...options.server,
|
|
105
|
+
mintOidcToken: throwingStub("server.mintOidcToken")
|
|
106
|
+
} : throwingStub("server")
|
|
107
|
+
}, touched, options.onTouch),
|
|
108
|
+
touched
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/pieces/activepieces/context/normalize.ts
|
|
113
|
+
const FETCH_TIMEOUT_MS = 3e4;
|
|
114
|
+
const FILE_REF = /^(?:attachment|apfile):\/\//i;
|
|
115
|
+
var FileFetchError = class extends Error {
|
|
116
|
+
constructor(url, reason) {
|
|
117
|
+
super(`Could not fetch FILE prop "${url}": ${reason}`);
|
|
118
|
+
this.name = "FileFetchError";
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
function isRecord(value) {
|
|
122
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
123
|
+
}
|
|
124
|
+
const DATA_URI = /^data:([^;,]*)((?:;[^;,]*)*),([\s\S]*)$/;
|
|
125
|
+
function extensionOf(filename) {
|
|
126
|
+
const dot = filename.lastIndexOf(".");
|
|
127
|
+
return dot > 0 && dot < filename.length - 1 ? filename.slice(dot + 1) : void 0;
|
|
128
|
+
}
|
|
129
|
+
const MIME_EXTENSIONS = {
|
|
130
|
+
"image/png": "png",
|
|
131
|
+
"image/jpeg": "jpg",
|
|
132
|
+
"image/gif": "gif",
|
|
133
|
+
"image/webp": "webp",
|
|
134
|
+
"image/svg+xml": "svg",
|
|
135
|
+
"application/pdf": "pdf",
|
|
136
|
+
"application/json": "json",
|
|
137
|
+
"text/plain": "txt",
|
|
138
|
+
"text/csv": "csv"
|
|
139
|
+
};
|
|
140
|
+
function toFileValue(data, filename, contentType) {
|
|
141
|
+
const mime = contentType?.split(";")[0].trim().toLowerCase();
|
|
142
|
+
const mimeExtension = mime ? MIME_EXTENSIONS[mime] : void 0;
|
|
143
|
+
const name = filename && filename !== "" ? filename : `file${mimeExtension ? `.${mimeExtension}` : ""}`;
|
|
144
|
+
const extension = extensionOf(name) ?? mimeExtension;
|
|
145
|
+
return {
|
|
146
|
+
filename: name,
|
|
147
|
+
...extension ? { extension } : {},
|
|
148
|
+
base64: data.toString("base64"),
|
|
149
|
+
data
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function filenameFromDisposition(header) {
|
|
153
|
+
if (!header) return void 0;
|
|
154
|
+
const utf8 = /filename\*=(?:UTF-8'')?([^;]+)/i.exec(header);
|
|
155
|
+
if (utf8) try {
|
|
156
|
+
return decodeURIComponent(utf8[1].trim().replace(/^"|"$/g, ""));
|
|
157
|
+
} catch {}
|
|
158
|
+
const plain = /filename="?([^";]+)"?/i.exec(header);
|
|
159
|
+
return plain ? plain[1].trim() : void 0;
|
|
160
|
+
}
|
|
161
|
+
async function defaultFetchFile(url) {
|
|
162
|
+
let response;
|
|
163
|
+
try {
|
|
164
|
+
response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });
|
|
165
|
+
} catch (error) {
|
|
166
|
+
throw new FileFetchError(url, error instanceof Error ? error.message : String(error));
|
|
167
|
+
}
|
|
168
|
+
if (!response.ok) throw new FileFetchError(url, `HTTP ${response.status}`);
|
|
169
|
+
const limit = maxFileBytes();
|
|
170
|
+
const declared = Number(response.headers.get("content-length"));
|
|
171
|
+
if (Number.isFinite(declared) && declared > limit) throw new FileFetchError(url, `${declared} bytes exceeds ${limit}`);
|
|
172
|
+
const data = Buffer.from(await response.arrayBuffer());
|
|
173
|
+
if (data.byteLength > limit) throw new FileFetchError(url, `${data.byteLength} bytes exceeds ${limit}`);
|
|
174
|
+
let filename = filenameFromDisposition(response.headers.get("content-disposition"));
|
|
175
|
+
if (!filename) {
|
|
176
|
+
const segment = new URL(url).pathname.split("/").filter(Boolean).pop();
|
|
177
|
+
if (segment) filename = decodeURIComponent(segment);
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
data,
|
|
181
|
+
filename,
|
|
182
|
+
contentType: response.headers.get("content-type") ?? void 0
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function isFileShaped(value) {
|
|
186
|
+
return isRecord(value) && typeof value.filename === "string" && (typeof value.base64 === "string" || Buffer.isBuffer(value.data));
|
|
187
|
+
}
|
|
188
|
+
async function toApFile(value, options = {}) {
|
|
189
|
+
if (isFileShaped(value)) {
|
|
190
|
+
const data = Buffer.isBuffer(value.data) ? value.data : Buffer.from(value.base64, "base64");
|
|
191
|
+
assertWithinLimit(data.byteLength);
|
|
192
|
+
const extension = value.extension ?? extensionOf(value.filename);
|
|
193
|
+
return {
|
|
194
|
+
...value,
|
|
195
|
+
...extension ? { extension } : {},
|
|
196
|
+
base64: typeof value.base64 === "string" ? value.base64 : data.toString("base64"),
|
|
197
|
+
data
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
if (typeof value !== "string") return value;
|
|
201
|
+
const trimmed = value.trim();
|
|
202
|
+
if (trimmed === "") return void 0;
|
|
203
|
+
const dataUri = DATA_URI.exec(trimmed);
|
|
204
|
+
if (dataUri) {
|
|
205
|
+
const [, mime, params, payload] = dataUri;
|
|
206
|
+
const data = /;base64/i.test(params) ? Buffer.from(payload, "base64") : Buffer.from(decodeURIComponent(payload), "utf8");
|
|
207
|
+
assertWithinLimit(data.byteLength);
|
|
208
|
+
const nameParam = /;name=([^;]+)/i.exec(params)?.[1];
|
|
209
|
+
return toFileValue(data, nameParam ? decodeURIComponent(nameParam) : void 0, mime || void 0);
|
|
210
|
+
}
|
|
211
|
+
if (FILE_REF.test(trimmed)) {
|
|
212
|
+
if (!options.resolveRef) throw new FileFetchError(trimmed, "no attachment resolver is available in this context");
|
|
213
|
+
const resolved = await options.resolveRef(trimmed);
|
|
214
|
+
assertWithinLimit(resolved.data.byteLength);
|
|
215
|
+
return toFileValue(resolved.data, resolved.filename, resolved.contentType);
|
|
216
|
+
}
|
|
217
|
+
if (/^https?:\/\//i.test(trimmed)) {
|
|
218
|
+
const fetched = await (options.fetchFile ?? defaultFetchFile)(trimmed);
|
|
219
|
+
return toFileValue(fetched.data, fetched.filename, fetched.contentType);
|
|
220
|
+
}
|
|
221
|
+
return value;
|
|
222
|
+
}
|
|
223
|
+
async function normalizeArray(prop, value, options) {
|
|
224
|
+
const fields = prop.properties;
|
|
225
|
+
if (!fields) return value;
|
|
226
|
+
const zipped = arrayZipperProcessor(prop, value);
|
|
227
|
+
if (!Array.isArray(zipped)) return value;
|
|
228
|
+
return Promise.all(zipped.map((item) => isRecord(item) ? normalizePropsValue(fields, item, options) : item));
|
|
229
|
+
}
|
|
230
|
+
function plainFile(value) {
|
|
231
|
+
if (!isRecord(value) || typeof value.filename !== "string") return value;
|
|
232
|
+
const { data } = value;
|
|
233
|
+
if (!Buffer.isBuffer(data)) return value;
|
|
234
|
+
const extension = typeof value.extension === "string" ? value.extension : extensionOf(value.filename);
|
|
235
|
+
return {
|
|
236
|
+
filename: value.filename,
|
|
237
|
+
...extension ? { extension } : {},
|
|
238
|
+
base64: typeof value.base64 === "string" ? value.base64 : data.toString("base64"),
|
|
239
|
+
data
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
const table = processors;
|
|
243
|
+
async function normalizeValue(prop, value, options = {}) {
|
|
244
|
+
if (value === void 0 || value === null) return value;
|
|
245
|
+
if (prop.type === "ARRAY") return normalizeArray(prop, value, options);
|
|
246
|
+
if (prop.type === "FILE") {
|
|
247
|
+
const hydrated = await toApFile(value, options);
|
|
248
|
+
if (typeof hydrated !== "string") return hydrated;
|
|
249
|
+
return plainFile(await table.FILE?.(prop, hydrated));
|
|
250
|
+
}
|
|
251
|
+
const processor = prop.type ? table[prop.type] : void 0;
|
|
252
|
+
if (!processor) return value;
|
|
253
|
+
return plainFile(await processor(prop, value));
|
|
254
|
+
}
|
|
255
|
+
async function normalizePropsValue(props, values, options = {}) {
|
|
256
|
+
if (!props || !isRecord(values)) return values;
|
|
257
|
+
const out = { ...values };
|
|
258
|
+
for (const [name, prop] of Object.entries(props)) {
|
|
259
|
+
if (!(name in out) || !isRecord(prop)) continue;
|
|
260
|
+
const normalized = await normalizeValue(prop, out[name], options);
|
|
261
|
+
if (normalized === void 0) delete out[name];
|
|
262
|
+
else out[name] = normalized;
|
|
263
|
+
}
|
|
264
|
+
return out;
|
|
265
|
+
}
|
|
266
|
+
//#endregion
|
|
267
|
+
//#region src/pieces/activepieces/context/props.ts
|
|
268
|
+
function buildPropertyContext(options = {}) {
|
|
269
|
+
const touched = /* @__PURE__ */ new Set();
|
|
270
|
+
return {
|
|
271
|
+
context: withTouchTracking({
|
|
272
|
+
searchValue: options.searchValue,
|
|
273
|
+
reactor: options.reactor ?? throwingStub("reactor"),
|
|
274
|
+
server: options.server ?? throwingStub("server"),
|
|
275
|
+
project: {
|
|
276
|
+
id: options.projectId ?? "project",
|
|
277
|
+
externalId: () => Promise.resolve(options.projectId ?? "project")
|
|
278
|
+
},
|
|
279
|
+
flows: options.flows ?? { list: throwingStub("flows.list") },
|
|
280
|
+
connections: options.connections ?? { get: throwingStub("connections.get") }
|
|
281
|
+
}, touched, options.onTouch),
|
|
282
|
+
touched
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
var NotDynamicPropertyError = class extends Error {
|
|
286
|
+
constructor(actionName, propName) {
|
|
287
|
+
super(`Property "${actionName}.${propName}" has no dynamic resolver`);
|
|
288
|
+
this.name = "NotDynamicPropertyError";
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
function pickResolver(prop) {
|
|
292
|
+
if (typeof prop.options === "function") return prop.options;
|
|
293
|
+
if (typeof prop.props === "function") return prop.props;
|
|
294
|
+
}
|
|
295
|
+
function ownerProps(piece, actionName, kind = "action") {
|
|
296
|
+
const owner = kind === "trigger" ? getTriggers(piece)[actionName] : getActions(piece)[actionName];
|
|
297
|
+
if (!owner) throw new Error(`No ${kind} "${actionName}" on piece`);
|
|
298
|
+
return owner.props ?? {};
|
|
299
|
+
}
|
|
300
|
+
function findProperty(piece, actionName, propName, kind = "action") {
|
|
301
|
+
const prop = ownerProps(piece, actionName, kind)[propName];
|
|
302
|
+
if (!prop) throw new Error(`No prop "${propName}" on ${kind} "${actionName}"`);
|
|
303
|
+
return prop;
|
|
304
|
+
}
|
|
305
|
+
async function resolveDynamicProperty(params) {
|
|
306
|
+
const { piece, actionName, propName, kind = "action" } = params;
|
|
307
|
+
const resolver = pickResolver(findProperty(piece, actionName, propName, kind));
|
|
308
|
+
if (!resolver) throw new NotDynamicPropertyError(actionName, propName);
|
|
309
|
+
return await resolver(params.refresherValues ?? {}, params.context);
|
|
310
|
+
}
|
|
311
|
+
//#endregion
|
|
312
|
+
//#region src/pieces/activepieces/context/remote-store.ts
|
|
313
|
+
var RemoteKeyValueStore = class {
|
|
314
|
+
async put(key, value, scope) {
|
|
315
|
+
const stored = jsonSafe(value);
|
|
316
|
+
await callHost(STORE_PUT, {
|
|
317
|
+
key,
|
|
318
|
+
value: stored,
|
|
319
|
+
scope
|
|
320
|
+
});
|
|
321
|
+
return stored;
|
|
322
|
+
}
|
|
323
|
+
get(key, scope) {
|
|
324
|
+
return callHost(STORE_GET, {
|
|
325
|
+
key,
|
|
326
|
+
scope
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
async delete(key, scope) {
|
|
330
|
+
await callHost(STORE_DELETE, {
|
|
331
|
+
key,
|
|
332
|
+
scope
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/pieces/activepieces/context/remote-output.ts
|
|
338
|
+
var RemoteOutput = class {
|
|
339
|
+
open = true;
|
|
340
|
+
update(output) {
|
|
341
|
+
if (this.open) notifyHost(OUTPUT_UPDATE, jsonSafe(output));
|
|
342
|
+
return Promise.resolve();
|
|
343
|
+
}
|
|
344
|
+
close() {
|
|
345
|
+
this.open = false;
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
//#endregion
|
|
349
|
+
//#region src/pieces/activepieces/worker/logs.ts
|
|
350
|
+
const MAX_MESSAGE_LENGTH = 8192;
|
|
351
|
+
const MAX_ENTRIES_PER_REQUEST = 1e3;
|
|
352
|
+
const LEVELS = [
|
|
353
|
+
"log",
|
|
354
|
+
"info",
|
|
355
|
+
"warn",
|
|
356
|
+
"error",
|
|
357
|
+
"debug"
|
|
358
|
+
];
|
|
359
|
+
function captureConsole() {
|
|
360
|
+
const original = /* @__PURE__ */ new Map();
|
|
361
|
+
let sent = 0;
|
|
362
|
+
for (const level of LEVELS) {
|
|
363
|
+
const previous = console[level];
|
|
364
|
+
original.set(level, previous);
|
|
365
|
+
console[level] = (...args) => {
|
|
366
|
+
if (sent > MAX_ENTRIES_PER_REQUEST) return;
|
|
367
|
+
sent += 1;
|
|
368
|
+
notifyHost(LOG_WRITE, {
|
|
369
|
+
level,
|
|
370
|
+
message: sent > MAX_ENTRIES_PER_REQUEST ? `[log truncated after ${MAX_ENTRIES_PER_REQUEST} entries]` : format(...args).slice(0, MAX_MESSAGE_LENGTH),
|
|
371
|
+
at: Date.now()
|
|
372
|
+
});
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
return () => {
|
|
376
|
+
for (const [level, previous] of original) console[level] = previous;
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
//#endregion
|
|
380
|
+
//#region src/pieces/activepieces/worker/entry.ts
|
|
381
|
+
installEgressGuard();
|
|
382
|
+
const loadedPieces = /* @__PURE__ */ new Map();
|
|
383
|
+
const stores = /* @__PURE__ */ new Map();
|
|
384
|
+
function storeForScope(scope) {
|
|
385
|
+
let store = stores.get(scope);
|
|
386
|
+
if (!store) {
|
|
387
|
+
store = new InMemoryKeyValueStore();
|
|
388
|
+
stores.set(scope, store);
|
|
389
|
+
}
|
|
390
|
+
return store;
|
|
391
|
+
}
|
|
392
|
+
function pieceRefKey(ref) {
|
|
393
|
+
const key = ref.entryPath ?? ref.bundleDir;
|
|
394
|
+
if (!key) throw new Error("Request names no piece module (entryPath or bundleDir)");
|
|
395
|
+
return key;
|
|
396
|
+
}
|
|
397
|
+
function loadCached(ref) {
|
|
398
|
+
const key = pieceRefKey(ref);
|
|
399
|
+
let loading = loadedPieces.get(key);
|
|
400
|
+
if (!loading) {
|
|
401
|
+
loading = ref.entryPath ? loadPiece(key) : loadPieceFromDir(key);
|
|
402
|
+
loadedPieces.set(key, loading);
|
|
403
|
+
}
|
|
404
|
+
return loading;
|
|
405
|
+
}
|
|
406
|
+
function redactValuesOf(message) {
|
|
407
|
+
return message.request.redactValues ?? [];
|
|
408
|
+
}
|
|
409
|
+
function serializeError(error, values = []) {
|
|
410
|
+
const properties = {};
|
|
411
|
+
if (typeof error === "object" && error !== null) for (const key of Object.keys(error)) properties[key] = jsonSafe(error[key]);
|
|
412
|
+
const { __apErrorVersion, message, errorName, ...http } = formatPieceError(error);
|
|
413
|
+
return {
|
|
414
|
+
name: typeof error === "object" && error !== null && error.constructor.name || errorName || "Error",
|
|
415
|
+
message: redactMessage(message, { values }),
|
|
416
|
+
properties: redactError({
|
|
417
|
+
...properties,
|
|
418
|
+
...jsonSafe(http)
|
|
419
|
+
}, { values }),
|
|
420
|
+
unsupportedMember: error instanceof UnsupportedContextMemberError ? error.member : void 0
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function consumeTlsFlag() {
|
|
424
|
+
const poisoned = process.env.NODE_TLS_REJECT_UNAUTHORIZED === "0";
|
|
425
|
+
delete process.env.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
426
|
+
return poisoned;
|
|
427
|
+
}
|
|
428
|
+
async function handleResolveOptions(message) {
|
|
429
|
+
const { request } = message;
|
|
430
|
+
const { piece } = await loadCached(request);
|
|
431
|
+
const { context, touched } = buildPropertyContext({
|
|
432
|
+
searchValue: request.searchValue,
|
|
433
|
+
flows: { list: () => Promise.resolve({ data: [] }) },
|
|
434
|
+
...request.reactorAccess ? { reactor: new RemoteReactorService() } : {}
|
|
435
|
+
});
|
|
436
|
+
const refresherValues = {
|
|
437
|
+
...request.auth !== void 0 ? { auth: request.auth } : {},
|
|
438
|
+
...request.refresherValues
|
|
439
|
+
};
|
|
440
|
+
const prop = findProperty(piece, request.actionName, request.propName, request.kind);
|
|
441
|
+
const output = await resolveDynamicProperty({
|
|
442
|
+
piece,
|
|
443
|
+
actionName: request.actionName,
|
|
444
|
+
kind: request.kind,
|
|
445
|
+
propName: request.propName,
|
|
446
|
+
refresherValues,
|
|
447
|
+
context
|
|
448
|
+
});
|
|
449
|
+
const isDynamic = typeof prop.props === "function" && typeof prop.options !== "function";
|
|
450
|
+
return {
|
|
451
|
+
id: message.id,
|
|
452
|
+
type: "result",
|
|
453
|
+
output: isDynamic ? describeProperties(output) : jsonSafe(output),
|
|
454
|
+
touched: [...touched],
|
|
455
|
+
tlsPoisoned: consumeTlsFlag()
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function stagedInputResolver(inputs) {
|
|
459
|
+
if (!inputs || inputs.length === 0) return void 0;
|
|
460
|
+
const byRef = new Map(inputs.map((input) => [input.ref, input]));
|
|
461
|
+
return async (ref) => {
|
|
462
|
+
const staged = byRef.get(ref);
|
|
463
|
+
if (!staged) throw new Error(`No staged file for reference "${ref}"`);
|
|
464
|
+
return {
|
|
465
|
+
data: await readFile(staged.path),
|
|
466
|
+
filename: staged.fileName,
|
|
467
|
+
contentType: staged.contentType
|
|
468
|
+
};
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
async function handleRun(message) {
|
|
472
|
+
const { request } = message;
|
|
473
|
+
const { piece } = await loadCached(request);
|
|
474
|
+
const action = getActions(piece)[request.actionName];
|
|
475
|
+
if (!action) throw new Error(`No action "${request.actionName}" in ${pieceRefKey(request)}`);
|
|
476
|
+
const files = request.stagingDir ? new StagedFilesService(request.stagingDir) : new DataUriFilesService();
|
|
477
|
+
const durableStore = request.durableStore ? new RemoteKeyValueStore() : void 0;
|
|
478
|
+
const liveOutput = request.liveOutput ? new RemoteOutput() : void 0;
|
|
479
|
+
const reactor = request.reactorAccess ? new RemoteReactorService() : void 0;
|
|
480
|
+
const { context, touched } = buildActionContext({
|
|
481
|
+
propsValue: await normalizePropsValue(action.props, request.propsValue, { resolveRef: stagedInputResolver(request.stagedInputs) }),
|
|
482
|
+
auth: request.auth,
|
|
483
|
+
store: durableStore ?? (request.storeScope ? storeForScope(request.storeScope) : void 0),
|
|
484
|
+
files,
|
|
485
|
+
connections: request.connections ? new InMemoryConnectionsProvider(request.connections) : void 0,
|
|
486
|
+
output: liveOutput,
|
|
487
|
+
reactor,
|
|
488
|
+
executionType: request.executionType,
|
|
489
|
+
identity: request.identity
|
|
490
|
+
});
|
|
491
|
+
const restoreConsole = request.captureLogs ? captureConsole() : void 0;
|
|
492
|
+
let output;
|
|
493
|
+
try {
|
|
494
|
+
output = await action.run(context);
|
|
495
|
+
} finally {
|
|
496
|
+
restoreConsole?.();
|
|
497
|
+
liveOutput?.close();
|
|
498
|
+
}
|
|
499
|
+
return {
|
|
500
|
+
id: message.id,
|
|
501
|
+
type: "result",
|
|
502
|
+
output: jsonSafe(output),
|
|
503
|
+
...files instanceof StagedFilesService && files.staged().length > 0 ? { files: files.staged() } : {},
|
|
504
|
+
touched: [...touched],
|
|
505
|
+
tlsPoisoned: consumeTlsFlag()
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
async function handleTriggerHook(message) {
|
|
509
|
+
const { request } = message;
|
|
510
|
+
const { piece } = await loadCached(request);
|
|
511
|
+
const trigger = getTriggers(piece)[request.triggerName];
|
|
512
|
+
if (!trigger) throw new Error(`No trigger "${request.triggerName}" in bundle ${request.bundleDir}`);
|
|
513
|
+
const snapshot = request.durableStore ? void 0 : new InMemoryKeyValueStore(request.storeState);
|
|
514
|
+
const runsPiece = request.hook === "run" || request.hook === "test";
|
|
515
|
+
const handle = buildTriggerContext({
|
|
516
|
+
propsValue: await normalizePropsValue(trigger.props, request.propsValue),
|
|
517
|
+
auth: request.auth,
|
|
518
|
+
store: snapshot ?? new RemoteKeyValueStore(),
|
|
519
|
+
hostPartitionedStore: request.durableStore,
|
|
520
|
+
storePrefix: request.hook === "test" ? "test" : "",
|
|
521
|
+
identity: request.identity,
|
|
522
|
+
isRepublish: request.isRepublish,
|
|
523
|
+
payload: request.payload,
|
|
524
|
+
webhookUrl: request.webhookUrl,
|
|
525
|
+
server: request.server,
|
|
526
|
+
files: runsPiece ? new DataUriFilesService() : void 0
|
|
527
|
+
});
|
|
528
|
+
const output = await runTriggerHook(trigger, request.hook, handle);
|
|
529
|
+
return {
|
|
530
|
+
id: message.id,
|
|
531
|
+
type: "result",
|
|
532
|
+
output: jsonSafe(output),
|
|
533
|
+
touched: [...handle.touched],
|
|
534
|
+
tlsPoisoned: consumeTlsFlag(),
|
|
535
|
+
...snapshot ? { storeState: jsonSafe(snapshot.snapshot()) } : {},
|
|
536
|
+
schedules: handle.schedules,
|
|
537
|
+
listeners: handle.listeners
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
async function handleCheckConnection(message) {
|
|
541
|
+
const { request } = message;
|
|
542
|
+
const { piece } = await loadCached(request);
|
|
543
|
+
const app = piece;
|
|
544
|
+
if (typeof app.checkConnection !== "function") return {
|
|
545
|
+
id: message.id,
|
|
546
|
+
type: "result",
|
|
547
|
+
output: { declared: false },
|
|
548
|
+
touched: [],
|
|
549
|
+
tlsPoisoned: consumeTlsFlag()
|
|
550
|
+
};
|
|
551
|
+
const { context, touched } = buildCheckConnectionContext({ auth: request.auth });
|
|
552
|
+
const outcome = {
|
|
553
|
+
declared: true,
|
|
554
|
+
result: jsonSafe(await app.checkConnection(context))
|
|
555
|
+
};
|
|
556
|
+
return {
|
|
557
|
+
id: message.id,
|
|
558
|
+
type: "result",
|
|
559
|
+
output: outcome,
|
|
560
|
+
touched: [...touched],
|
|
561
|
+
tlsPoisoned: consumeTlsFlag()
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
async function handleDescribe(message) {
|
|
565
|
+
const { request } = message;
|
|
566
|
+
const { piece } = await loadCached(request);
|
|
567
|
+
const descriptor = buildDescriptor(piece, {
|
|
568
|
+
packageName: request.packageName,
|
|
569
|
+
version: request.version
|
|
570
|
+
});
|
|
571
|
+
return {
|
|
572
|
+
id: message.id,
|
|
573
|
+
type: "result",
|
|
574
|
+
output: jsonSafe(descriptor),
|
|
575
|
+
touched: [],
|
|
576
|
+
tlsPoisoned: consumeTlsFlag()
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
function isWorkerMessage(value) {
|
|
580
|
+
if (typeof value !== "object" || value === null) return false;
|
|
581
|
+
const type = value.type;
|
|
582
|
+
return type === "run" || type === "resolve-options" || type === "trigger-hook" || type === "check-connection" || type === "describe";
|
|
583
|
+
}
|
|
584
|
+
function dispatch(message) {
|
|
585
|
+
switch (message.type) {
|
|
586
|
+
case "run": return handleRun(message);
|
|
587
|
+
case "resolve-options": return handleResolveOptions(message);
|
|
588
|
+
case "trigger-hook": return handleTriggerHook(message);
|
|
589
|
+
case "check-connection": return handleCheckConnection(message);
|
|
590
|
+
case "describe": return handleDescribe(message);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
process.on("message", (message) => {
|
|
594
|
+
if (!isWorkerMessage(message)) return;
|
|
595
|
+
Promise.resolve().then(() => runWithEgressPolicy(message.request.egress, () => dispatch(message))).catch((error) => ({
|
|
596
|
+
id: message.id,
|
|
597
|
+
type: "error",
|
|
598
|
+
error: serializeError(error, redactValuesOf(message)),
|
|
599
|
+
tlsPoisoned: consumeTlsFlag()
|
|
600
|
+
})).then((response) => process.send?.(response)).catch(() => process.exit(1));
|
|
601
|
+
});
|
|
602
|
+
//#endregion
|
|
603
|
+
export {};
|
|
604
|
+
|
|
605
|
+
//# sourceMappingURL=worker-entry.js.map
|