@requence/service 1.0.0-alpha.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/CHANGELOG.md +16 -0
- package/README.md +191 -0
- package/build/chunk-2exhyr7n.js +234 -0
- package/build/chunk-2exhyr7n.js.map +14 -0
- package/build/cli.js +46 -0
- package/build/cli.js.map +10 -0
- package/build/index.js +1111 -0
- package/build/index.js.map +22 -0
- package/build/types/helpers/src/clone.d.ts +3 -0
- package/build/types/helpers/src/clone.d.ts.map +1 -0
- package/build/types/helpers/src/createObjectProxy.d.ts +2 -0
- package/build/types/helpers/src/createObjectProxy.d.ts.map +1 -0
- package/build/types/helpers/src/index.d.ts +7 -0
- package/build/types/helpers/src/index.d.ts.map +1 -0
- package/build/types/helpers/src/obfuscate.d.ts +4 -0
- package/build/types/helpers/src/obfuscate.d.ts.map +1 -0
- package/build/types/helpers/src/service.d.ts +156 -0
- package/build/types/helpers/src/service.d.ts.map +1 -0
- package/build/types/helpers/src/task.d.ts +49 -0
- package/build/types/helpers/src/task.d.ts.map +1 -0
- package/build/types/helpers/src/utils.d.ts +7 -0
- package/build/types/helpers/src/utils.d.ts.map +1 -0
- package/build/types/service/src/connections/createAmqpConnection.d.ts +42 -0
- package/build/types/service/src/connections/createAmqpConnection.d.ts.map +1 -0
- package/build/types/service/src/helpers.d.ts +121 -0
- package/build/types/service/src/helpers.d.ts.map +1 -0
- package/build/types/service/src/index.d.ts +12 -0
- package/build/types/service/src/index.d.ts.map +1 -0
- package/package.json +31 -0
package/build/index.js
ADDED
|
@@ -0,0 +1,1111 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clone,
|
|
3
|
+
createObjectProxy,
|
|
4
|
+
deobfuscate,
|
|
5
|
+
obfuscate
|
|
6
|
+
} from "./chunk-2exhyr7n.js";
|
|
7
|
+
|
|
8
|
+
// src/index.ts
|
|
9
|
+
import {readFileSync} from "node:fs";
|
|
10
|
+
import {z as z8} from "zod";
|
|
11
|
+
|
|
12
|
+
// ../helpers/src/context/context.ts
|
|
13
|
+
import {z} from "zod";
|
|
14
|
+
function isRecord(data) {
|
|
15
|
+
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
16
|
+
}
|
|
17
|
+
function getInternalContext(contextHelper) {
|
|
18
|
+
return contextHelper[internalKey];
|
|
19
|
+
}
|
|
20
|
+
function createContextHelper(context, nodes) {
|
|
21
|
+
const results = new Map(nodes.map((node) => [
|
|
22
|
+
node.id,
|
|
23
|
+
{
|
|
24
|
+
node,
|
|
25
|
+
executionDate: node.id in context.dates ? new Date(context.dates[node.id]) : null,
|
|
26
|
+
data: context.data[node.id] ?? null,
|
|
27
|
+
error: context.errors[node.id] ?? null
|
|
28
|
+
}
|
|
29
|
+
]));
|
|
30
|
+
const lookUpMap = new Map;
|
|
31
|
+
for (const node of nodes) {
|
|
32
|
+
const alias = typeof node.meta?.mapAlias === "string" ? node.meta.mapAlias : ("alias" in node) && node.alias;
|
|
33
|
+
if (alias) {
|
|
34
|
+
if (lookUpMap.has(alias)) {
|
|
35
|
+
lookUpMap.get(alias).push(node.id);
|
|
36
|
+
} else {
|
|
37
|
+
lookUpMap.set(alias, [node.id]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const name = typeof node.meta?.mapName === "string" ? node.meta.mapName : node.type === "service" && node.name;
|
|
41
|
+
if (name) {
|
|
42
|
+
if (lookUpMap.has(name)) {
|
|
43
|
+
lookUpMap.get(name).push(node.id);
|
|
44
|
+
} else {
|
|
45
|
+
lookUpMap.set(name, [node.id]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
[internalKey]: {
|
|
51
|
+
results
|
|
52
|
+
},
|
|
53
|
+
getInput() {
|
|
54
|
+
return context.input;
|
|
55
|
+
},
|
|
56
|
+
getTenantName() {
|
|
57
|
+
return context.tenant.name;
|
|
58
|
+
},
|
|
59
|
+
getMeta() {
|
|
60
|
+
return context.meta;
|
|
61
|
+
},
|
|
62
|
+
getData(alias) {
|
|
63
|
+
if (alias) {
|
|
64
|
+
const nodeIds = lookUpMap.get(alias);
|
|
65
|
+
if (!nodeIds) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const combinedData = nodeIds.map((nodeId) => results.get(nodeId)?.data).filter(Boolean);
|
|
69
|
+
if (combinedData.length === 0) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
if (combinedData.length === 1) {
|
|
73
|
+
return combinedData[0];
|
|
74
|
+
}
|
|
75
|
+
if (combinedData.every(isRecord)) {
|
|
76
|
+
return combinedData.reduce((acc, data) => ({ ...acc, ...data }), {});
|
|
77
|
+
}
|
|
78
|
+
return combinedData;
|
|
79
|
+
}
|
|
80
|
+
return Array.from(results.values()).filter((result) => result.executionDate && isRecord(result.data)).toSorted((a, b) => a.executionDate.getTime() - b.executionDate.getTime()).reduce((acc, result) => ({
|
|
81
|
+
...acc,
|
|
82
|
+
...result.data
|
|
83
|
+
}), isRecord(context.input) ? { ...context.input } : {});
|
|
84
|
+
},
|
|
85
|
+
getError(alias) {
|
|
86
|
+
const nodeIds = lookUpMap.get(alias);
|
|
87
|
+
if (!nodeIds) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return nodeIds.map((nodeId) => results.get(nodeId)?.error).filter((str) => typeof str === "string").join("\n");
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
var contextSchema = z.object({
|
|
95
|
+
input: z.any(),
|
|
96
|
+
meta: z.any(),
|
|
97
|
+
tenant: z.object({ name: z.string() }),
|
|
98
|
+
data: z.record(z.string(), z.any()),
|
|
99
|
+
errors: z.record(z.string(), z.string()),
|
|
100
|
+
dates: z.record(z.string(), z.string().datetime())
|
|
101
|
+
});
|
|
102
|
+
var internalKey = Symbol.for("internal");
|
|
103
|
+
// ../helpers/src/protocol/command.ts
|
|
104
|
+
import {z as z5} from "zod";
|
|
105
|
+
|
|
106
|
+
// ../helpers/src/protocol/nodes.ts
|
|
107
|
+
import {ZodError, z as z4} from "zod";
|
|
108
|
+
|
|
109
|
+
// ../helpers/src/protocol/getNodeOutputs.ts
|
|
110
|
+
function getNodeOutputs(node, outputName) {
|
|
111
|
+
const outputs = !outputName ? node.output : outputName === "__default__" ? node.output.filter((o) => o.default) : node.output.filter((o) => ("name" in o) && o.name === outputName);
|
|
112
|
+
const outputTargets = new Set;
|
|
113
|
+
for (const output of outputs) {
|
|
114
|
+
if (output.exit) {
|
|
115
|
+
outputTargets.add("__exit__");
|
|
116
|
+
} else {
|
|
117
|
+
outputTargets.add(output.target);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return Array.from(outputTargets);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ../helpers/src/protocol/createNodeMaps.ts
|
|
124
|
+
function createNodeMaps(nodes) {
|
|
125
|
+
const nodesByIdMap = new Map;
|
|
126
|
+
const nodesByNameOrAlias = new Map;
|
|
127
|
+
const inputsNodeMap = new Map([
|
|
128
|
+
["__exit__", []]
|
|
129
|
+
]);
|
|
130
|
+
for (const node of nodes) {
|
|
131
|
+
nodesByIdMap.set(node.id, node);
|
|
132
|
+
if ("alias" in node && node.alias) {
|
|
133
|
+
nodesByNameOrAlias.set(node.alias, node);
|
|
134
|
+
}
|
|
135
|
+
if ("name" in node && node.name) {
|
|
136
|
+
nodesByNameOrAlias.set(node.name, node);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
for (const node of nodes) {
|
|
140
|
+
for (const outputNodeId of getNodeOutputs(node)) {
|
|
141
|
+
if (!inputsNodeMap.has(outputNodeId)) {
|
|
142
|
+
inputsNodeMap.set(outputNodeId, []);
|
|
143
|
+
}
|
|
144
|
+
inputsNodeMap.get(outputNodeId).push(node);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
getInputs(node) {
|
|
149
|
+
if (typeof node === "string") {
|
|
150
|
+
return inputsNodeMap.get(node) ?? [];
|
|
151
|
+
}
|
|
152
|
+
if (node.type === "catch" || node.type === "entry") {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
return inputsNodeMap.get(node.id) ?? [];
|
|
156
|
+
},
|
|
157
|
+
getNode(nodeId) {
|
|
158
|
+
return nodesByIdMap.get(nodeId);
|
|
159
|
+
},
|
|
160
|
+
lookupNode(nameOrAlias) {
|
|
161
|
+
return nodesByNameOrAlias.get(nameOrAlias);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ../helpers/src/protocol/getPossiblePaths.ts
|
|
167
|
+
function getPossiblePaths({
|
|
168
|
+
getInputs,
|
|
169
|
+
getNode,
|
|
170
|
+
onMissingInputs
|
|
171
|
+
}) {
|
|
172
|
+
const sets = new Set;
|
|
173
|
+
const followPath = (nodeId, set2) => {
|
|
174
|
+
if (nodeId === "__entry__") {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const node = nodeId !== "__exit__" ? getNode(nodeId) : null;
|
|
178
|
+
const isOrNode = node?.type === "or";
|
|
179
|
+
const inputNodes = getInputs(nodeId);
|
|
180
|
+
if (node && node.type !== "catch" && inputNodes.length === 0) {
|
|
181
|
+
onMissingInputs?.(node, Array.from(set2).toReversed());
|
|
182
|
+
}
|
|
183
|
+
for (const inputNode of inputNodes) {
|
|
184
|
+
let usedSet = set2;
|
|
185
|
+
if (isOrNode) {
|
|
186
|
+
usedSet = new Set(set2);
|
|
187
|
+
sets.add(usedSet);
|
|
188
|
+
}
|
|
189
|
+
const inputNodeId = inputNode.id;
|
|
190
|
+
if (inputNode.type !== "or") {
|
|
191
|
+
if (usedSet.has(inputNodeId)) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
usedSet.add(inputNodeId);
|
|
195
|
+
}
|
|
196
|
+
followPath(inputNodeId, usedSet);
|
|
197
|
+
}
|
|
198
|
+
if (isOrNode) {
|
|
199
|
+
sets.delete(set2);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
const set = new Set(["__exit__"]);
|
|
203
|
+
sets.add(set);
|
|
204
|
+
followPath("__exit__", set);
|
|
205
|
+
return Array.from(sets, (set2) => Array.from(set2).toReversed());
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ../helpers/src/protocol/identifyNode.ts
|
|
209
|
+
function identifyNode(nodeId, getNode) {
|
|
210
|
+
if (nodeId === "__entry__") {
|
|
211
|
+
return "ENTRY";
|
|
212
|
+
}
|
|
213
|
+
if (nodeId === "__exit__") {
|
|
214
|
+
return "EXIT";
|
|
215
|
+
}
|
|
216
|
+
if (typeof nodeId === "symbol") {
|
|
217
|
+
return String(nodeId);
|
|
218
|
+
}
|
|
219
|
+
const node = getNode(nodeId);
|
|
220
|
+
if (!node) {
|
|
221
|
+
return `Unknown[${nodeId}]`;
|
|
222
|
+
}
|
|
223
|
+
switch (node.type) {
|
|
224
|
+
case "service": {
|
|
225
|
+
return `Service[${node.alias || node.name}]`;
|
|
226
|
+
}
|
|
227
|
+
case "catch": {
|
|
228
|
+
return `Catch[${identifyNode(node.subject, getNode)}]`;
|
|
229
|
+
}
|
|
230
|
+
case "logic": {
|
|
231
|
+
return `Logic[${node.alias || node.id}]`;
|
|
232
|
+
}
|
|
233
|
+
case "entry": {
|
|
234
|
+
return "ENTRY";
|
|
235
|
+
}
|
|
236
|
+
case "or": {
|
|
237
|
+
return `OR[${node.alias || node.id}]`;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ../helpers/src/protocol/node.ts
|
|
243
|
+
import {z as z3} from "zod";
|
|
244
|
+
|
|
245
|
+
// ../helpers/src/protocol/jsonSchema.ts
|
|
246
|
+
import {z as z2} from "zod";
|
|
247
|
+
var jsonSchema7Schema = z2.lazy(() => z2.object({
|
|
248
|
+
$id: z2.string().optional(),
|
|
249
|
+
$schema: z2.string().optional(),
|
|
250
|
+
$ref: z2.string().optional(),
|
|
251
|
+
title: z2.string().optional(),
|
|
252
|
+
description: z2.string().optional(),
|
|
253
|
+
type: z2.union([
|
|
254
|
+
z2.literal("string"),
|
|
255
|
+
z2.literal("number"),
|
|
256
|
+
z2.literal("integer"),
|
|
257
|
+
z2.literal("boolean"),
|
|
258
|
+
z2.literal("object"),
|
|
259
|
+
z2.literal("array"),
|
|
260
|
+
z2.literal("null")
|
|
261
|
+
]).optional(),
|
|
262
|
+
enum: z2.array(z2.union([z2.string(), z2.number(), z2.boolean(), z2.null()])).optional(),
|
|
263
|
+
const: z2.union([z2.string(), z2.number(), z2.boolean(), z2.null()]).optional(),
|
|
264
|
+
multipleOf: z2.number().positive().optional(),
|
|
265
|
+
maximum: z2.number().optional(),
|
|
266
|
+
exclusiveMaximum: z2.number().optional(),
|
|
267
|
+
minimum: z2.number().optional(),
|
|
268
|
+
exclusiveMinimum: z2.number().optional(),
|
|
269
|
+
maxLength: z2.number().int().nonnegative().optional(),
|
|
270
|
+
minLength: z2.number().int().nonnegative().optional(),
|
|
271
|
+
pattern: z2.string().optional(),
|
|
272
|
+
additionalItems: z2.boolean().optional(),
|
|
273
|
+
items: z2.union([z2.lazy(() => jsonSchema7Schema), z2.array(jsonSchema7Schema)]).optional(),
|
|
274
|
+
maxItems: z2.number().int().nonnegative().optional(),
|
|
275
|
+
minItems: z2.number().int().nonnegative().optional(),
|
|
276
|
+
uniqueItems: z2.boolean().optional(),
|
|
277
|
+
contains: z2.lazy(() => jsonSchema7Schema).optional(),
|
|
278
|
+
maxProperties: z2.number().int().nonnegative().optional(),
|
|
279
|
+
minProperties: z2.number().int().nonnegative().optional(),
|
|
280
|
+
required: z2.array(z2.string()).optional(),
|
|
281
|
+
properties: z2.record(jsonSchema7Schema).optional(),
|
|
282
|
+
patternProperties: z2.record(jsonSchema7Schema).optional(),
|
|
283
|
+
additionalProperties: z2.union([z2.boolean(), z2.lazy(() => jsonSchema7Schema)]).optional(),
|
|
284
|
+
dependencies: z2.record(z2.union([z2.array(z2.string()), jsonSchema7Schema])).optional(),
|
|
285
|
+
propertyNames: z2.lazy(() => jsonSchema7Schema).optional(),
|
|
286
|
+
if: z2.lazy(() => jsonSchema7Schema).optional(),
|
|
287
|
+
then: z2.lazy(() => jsonSchema7Schema).optional(),
|
|
288
|
+
else: z2.lazy(() => jsonSchema7Schema).optional(),
|
|
289
|
+
allOf: z2.array(jsonSchema7Schema).optional(),
|
|
290
|
+
anyOf: z2.array(jsonSchema7Schema).optional(),
|
|
291
|
+
oneOf: z2.array(jsonSchema7Schema).optional(),
|
|
292
|
+
not: z2.lazy(() => jsonSchema7Schema).optional(),
|
|
293
|
+
definitions: z2.record(jsonSchema7Schema).optional(),
|
|
294
|
+
format: z2.string().optional(),
|
|
295
|
+
contentMediaType: z2.string().optional(),
|
|
296
|
+
contentEncoding: z2.string().optional()
|
|
297
|
+
}));
|
|
298
|
+
var jsonSchema7ObjectSchema = z2.object({
|
|
299
|
+
type: z2.literal("object"),
|
|
300
|
+
properties: z2.record(jsonSchema7Schema),
|
|
301
|
+
required: z2.array(z2.string()).optional(),
|
|
302
|
+
description: z2.string().optional(),
|
|
303
|
+
maxProperties: z2.number().int().nonnegative().optional(),
|
|
304
|
+
minProperties: z2.number().int().nonnegative().optional(),
|
|
305
|
+
additionalProperties: z2.boolean().optional()
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// ../helpers/src/protocol/node.ts
|
|
309
|
+
function validateOutputs(outputs, ctx) {
|
|
310
|
+
const exitOutputs = new Set(outputs.filter((output) => output.exit).map((output) => output.default ? "__default__" : output.name));
|
|
311
|
+
outputs.filter((output) => !output.exit).forEach((output) => {
|
|
312
|
+
const name = output.default ? "__default__" : output.name;
|
|
313
|
+
if (exitOutputs.has(name)) {
|
|
314
|
+
ctx.addIssue({
|
|
315
|
+
code: "custom",
|
|
316
|
+
message: output.default ? `default exit output cannot be mixed with target output "${output.target}"` : `named exit output "${name}" cannot be mixed with target output "${output.target}"`
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
const targets = new Map;
|
|
321
|
+
outputs.forEach((output) => {
|
|
322
|
+
const name = output.default ? "__default__" : output.name;
|
|
323
|
+
const target = output.exit ? "__exit__" : output.target;
|
|
324
|
+
if (!targets.has(name)) {
|
|
325
|
+
targets.set(name, new Set);
|
|
326
|
+
}
|
|
327
|
+
const knownTargets = targets.get(name);
|
|
328
|
+
if (knownTargets.has(target)) {
|
|
329
|
+
ctx.addIssue({
|
|
330
|
+
code: "custom",
|
|
331
|
+
message: [
|
|
332
|
+
output.default ? "duplicate default output" : `duplicate named output "${name}"`,
|
|
333
|
+
output.exit ? "for exit" : `for target "${target}"`
|
|
334
|
+
].join(" ")
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
knownTargets.add(target);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
var outputDefinitionSchema = z3.object({
|
|
341
|
+
schema: jsonSchema7Schema.nullable().optional()
|
|
342
|
+
}).and(z3.union([
|
|
343
|
+
z3.object({
|
|
344
|
+
default: z3.literal(false).default(false),
|
|
345
|
+
name: z3.string().min(1)
|
|
346
|
+
}),
|
|
347
|
+
z3.object({
|
|
348
|
+
default: z3.literal(true).default(true)
|
|
349
|
+
})
|
|
350
|
+
])).and(z3.union([
|
|
351
|
+
z3.object({
|
|
352
|
+
exit: z3.literal(false).default(false),
|
|
353
|
+
target: z3.string().min(1)
|
|
354
|
+
}),
|
|
355
|
+
z3.object({ exit: z3.literal(true) })
|
|
356
|
+
]));
|
|
357
|
+
var defaultOutputSchema = z3.union([
|
|
358
|
+
z3.string().min(1),
|
|
359
|
+
z3.object({ default: z3.literal(true).default(true), exit: z3.literal(true) }),
|
|
360
|
+
z3.object({
|
|
361
|
+
default: z3.literal(true).default(true),
|
|
362
|
+
exit: z3.literal(false).default(false),
|
|
363
|
+
target: z3.string().min(1)
|
|
364
|
+
})
|
|
365
|
+
]).transform((output) => {
|
|
366
|
+
if (typeof output === "string") {
|
|
367
|
+
return {
|
|
368
|
+
default: true,
|
|
369
|
+
exit: false,
|
|
370
|
+
target: output
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
return output;
|
|
374
|
+
});
|
|
375
|
+
var outputSchema = z3.union([z3.string().min(1), outputDefinitionSchema]).transform((output) => {
|
|
376
|
+
if (typeof output === "string") {
|
|
377
|
+
return {
|
|
378
|
+
default: true,
|
|
379
|
+
exit: false,
|
|
380
|
+
target: output
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
return output;
|
|
384
|
+
});
|
|
385
|
+
var defaultOutputsSchema = z3.array(defaultOutputSchema).default([]).superRefine(validateOutputs);
|
|
386
|
+
var outputsSchema = z3.array(outputSchema).default([]).superRefine(validateOutputs);
|
|
387
|
+
var idSchema = z3.string().uuid().default(() => crypto.randomUUID());
|
|
388
|
+
var metaSchema = z3.record(z3.any()).optional();
|
|
389
|
+
var entryNodeSchema = z3.object({
|
|
390
|
+
type: z3.literal("entry"),
|
|
391
|
+
id: z3.literal("__entry__").default("__entry__"),
|
|
392
|
+
output: defaultOutputsSchema,
|
|
393
|
+
inputSchema: jsonSchema7Schema.nullable().optional(),
|
|
394
|
+
metaSchema: jsonSchema7Schema.nullable().optional(),
|
|
395
|
+
meta: metaSchema
|
|
396
|
+
});
|
|
397
|
+
var serviceNodeSchema = z3.object({
|
|
398
|
+
type: z3.literal("service"),
|
|
399
|
+
output: outputsSchema,
|
|
400
|
+
inputSchema: jsonSchema7ObjectSchema.nullable().optional(),
|
|
401
|
+
id: idSchema,
|
|
402
|
+
name: z3.string(),
|
|
403
|
+
version: z3.string().default("*"),
|
|
404
|
+
configuration: z3.any().optional(),
|
|
405
|
+
alias: z3.string().optional(),
|
|
406
|
+
ttl: z3.number().int().min(1).optional(),
|
|
407
|
+
retry: z3.number().int().min(1).optional(),
|
|
408
|
+
retryDelay: z3.number().int().min(100).optional(),
|
|
409
|
+
meta: metaSchema
|
|
410
|
+
});
|
|
411
|
+
var catchNodeSchema = z3.object({
|
|
412
|
+
type: z3.literal("catch"),
|
|
413
|
+
output: outputsSchema,
|
|
414
|
+
id: idSchema,
|
|
415
|
+
subject: z3.string(),
|
|
416
|
+
meta: metaSchema
|
|
417
|
+
});
|
|
418
|
+
var logicNodeSchema = z3.object({
|
|
419
|
+
type: z3.literal("logic"),
|
|
420
|
+
alias: z3.string().optional(),
|
|
421
|
+
inputSchema: jsonSchema7ObjectSchema.nullable().optional(),
|
|
422
|
+
output: outputsSchema,
|
|
423
|
+
id: idSchema,
|
|
424
|
+
script: z3.string(),
|
|
425
|
+
concurrency: z3.boolean().default(true),
|
|
426
|
+
language: z3.enum(["javascript", "python", "typescript"]).default("javascript"),
|
|
427
|
+
maxExecutionTime: z3.number().int().min(0).default(200),
|
|
428
|
+
meta: metaSchema
|
|
429
|
+
});
|
|
430
|
+
var orNodeSchema = z3.object({
|
|
431
|
+
id: idSchema,
|
|
432
|
+
type: z3.literal("or"),
|
|
433
|
+
alias: z3.string().optional(),
|
|
434
|
+
output: outputsSchema,
|
|
435
|
+
meta: metaSchema
|
|
436
|
+
});
|
|
437
|
+
var nodeSchema = z3.discriminatedUnion("type", [
|
|
438
|
+
entryNodeSchema,
|
|
439
|
+
serviceNodeSchema,
|
|
440
|
+
catchNodeSchema,
|
|
441
|
+
logicNodeSchema,
|
|
442
|
+
orNodeSchema
|
|
443
|
+
]);
|
|
444
|
+
|
|
445
|
+
// ../helpers/src/protocol/nodes.ts
|
|
446
|
+
class NodesError extends ZodError {
|
|
447
|
+
constructor(message, params, path = []) {
|
|
448
|
+
super([
|
|
449
|
+
{
|
|
450
|
+
code: z4.ZodIssueCode.custom,
|
|
451
|
+
message,
|
|
452
|
+
path,
|
|
453
|
+
params
|
|
454
|
+
}
|
|
455
|
+
]);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
var nodesSchema = z4.array(nodeSchema).transform((nodes) => {
|
|
459
|
+
const aliases = new Map;
|
|
460
|
+
const names = new Map;
|
|
461
|
+
let entryNode = null;
|
|
462
|
+
let firstNodeId = null;
|
|
463
|
+
for (const node2 of nodes) {
|
|
464
|
+
if (node2.type === "entry") {
|
|
465
|
+
entryNode = node2;
|
|
466
|
+
}
|
|
467
|
+
if ((node2.type === "service" || node2.type === "logic") && !firstNodeId) {
|
|
468
|
+
firstNodeId = node2.id;
|
|
469
|
+
}
|
|
470
|
+
if ("alias" in node2 && node2.alias) {
|
|
471
|
+
if (!aliases.has(node2.alias)) {
|
|
472
|
+
aliases.set(node2.alias, []);
|
|
473
|
+
}
|
|
474
|
+
aliases.get(node2.alias).push(node2.id);
|
|
475
|
+
}
|
|
476
|
+
if ("name" in node2 && node2.name) {
|
|
477
|
+
if (!names.has(node2.name)) {
|
|
478
|
+
names.set(node2.name, []);
|
|
479
|
+
}
|
|
480
|
+
names.get(node2.name).push(node2.id);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (!entryNode && firstNodeId) {
|
|
484
|
+
nodes.unshift({
|
|
485
|
+
type: "entry",
|
|
486
|
+
id: "__entry__",
|
|
487
|
+
output: [{ default: true, exit: false, target: firstNodeId }]
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
const resolveOutput = (identifier) => {
|
|
491
|
+
if (aliases.get(identifier)?.length === 1) {
|
|
492
|
+
return aliases.get(identifier)[0];
|
|
493
|
+
}
|
|
494
|
+
if (names.get(identifier)?.length === 1) {
|
|
495
|
+
return names.get(identifier)[0];
|
|
496
|
+
}
|
|
497
|
+
return identifier;
|
|
498
|
+
};
|
|
499
|
+
return nodes.map((node2) => {
|
|
500
|
+
node2.output = node2.output.map((output) => ("target" in output) ? {
|
|
501
|
+
...output,
|
|
502
|
+
target: resolveOutput(output.target)
|
|
503
|
+
} : output);
|
|
504
|
+
if ("subject" in node2) {
|
|
505
|
+
node2.subject = resolveOutput(node2.subject);
|
|
506
|
+
}
|
|
507
|
+
return node2;
|
|
508
|
+
});
|
|
509
|
+
}).transform((nodes) => {
|
|
510
|
+
const { getInputs, getNode } = createNodeMaps(nodes);
|
|
511
|
+
const nodeAliases = new Set;
|
|
512
|
+
const nodeIds = new Set;
|
|
513
|
+
const catchSubjects = new Map;
|
|
514
|
+
const identify = (nodeId) => identifyNode(nodeId, getNode);
|
|
515
|
+
for (const node2 of nodes) {
|
|
516
|
+
if (nodeIds.has(node2.id)) {
|
|
517
|
+
throw new NodesError("id is not unique", {
|
|
518
|
+
id: node2.id
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
nodeIds.add(node2.id);
|
|
522
|
+
if ("alias" in node2 && node2.alias) {
|
|
523
|
+
if (nodeAliases.has(node2.alias)) {
|
|
524
|
+
throw new NodesError("alias is not unique", {
|
|
525
|
+
alias: node2.alias
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
nodeAliases.add(node2.alias);
|
|
529
|
+
}
|
|
530
|
+
if (node2.type === "catch") {
|
|
531
|
+
if (catchSubjects.has(node2.subject)) {
|
|
532
|
+
throw new NodesError("only one catch node per service allowed", {
|
|
533
|
+
id: node2.subject
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
catchSubjects.set(node2.subject, node2);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
if (!getNode("__entry__")) {
|
|
540
|
+
throw new NodesError("missing entry node");
|
|
541
|
+
}
|
|
542
|
+
if (getInputs("__exit__").length === 0) {
|
|
543
|
+
throw new NodesError("no path leads to exit");
|
|
544
|
+
}
|
|
545
|
+
for (const catchNode of nodes.filter((node2) => node2.type === "catch")) {
|
|
546
|
+
if (!getNode(catchNode.subject)) {
|
|
547
|
+
throw new NodesError("catch node has invalid subject", {
|
|
548
|
+
id: catchNode.subject
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
for (const node2 of nodes) {
|
|
553
|
+
if (node2.type === "or") {
|
|
554
|
+
const inputs = getInputs(node2);
|
|
555
|
+
if (!inputs || inputs.length < 2) {
|
|
556
|
+
throw new NodesError("or nodes need at least 2 inputs");
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
for (const targetNodeId of getNodeOutputs(node2)) {
|
|
560
|
+
if (targetNodeId !== "__exit__" && !getNode(targetNodeId)) {
|
|
561
|
+
throw new NodesError("missing node", {
|
|
562
|
+
id: targetNodeId
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
const possiblePaths = getPossiblePaths({
|
|
568
|
+
getInputs,
|
|
569
|
+
getNode,
|
|
570
|
+
onMissingInputs: (_node, path) => {
|
|
571
|
+
throw new NodesError("no path from entry to node", {
|
|
572
|
+
path: path.map(identify)
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
if (possiblePaths.every((possiblePath) => !possiblePath.includes("__entry__"))) {
|
|
577
|
+
throw new NodesError("no path from entry to exit");
|
|
578
|
+
}
|
|
579
|
+
for (const possiblePath of possiblePaths) {
|
|
580
|
+
for (const pathSegment of possiblePath) {
|
|
581
|
+
const node2 = pathSegment === "__exit__" ? null : getNode(pathSegment);
|
|
582
|
+
if (node2?.type === "catch" && possiblePath.includes(node2.subject)) {
|
|
583
|
+
throw new NodesError("Unresolvable, inputs needs both catch and subject", {
|
|
584
|
+
path: possiblePath.map(identify)
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return nodes;
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// ../helpers/src/protocol/command.ts
|
|
593
|
+
var abortSchema = z5.object({
|
|
594
|
+
type: z5.literal("ABORT"),
|
|
595
|
+
reason: z5.string().optional()
|
|
596
|
+
});
|
|
597
|
+
var nodeOptionsSchema = z5.object({
|
|
598
|
+
maxExecutions: z5.number().int().min(0).optional().default(10)
|
|
599
|
+
});
|
|
600
|
+
var createNodesSchema = z5.object({
|
|
601
|
+
type: z5.literal("CREATE_NODES"),
|
|
602
|
+
nodes: nodesSchema,
|
|
603
|
+
input: z5.any(),
|
|
604
|
+
meta: z5.any(),
|
|
605
|
+
options: nodeOptionsSchema
|
|
606
|
+
});
|
|
607
|
+
var commandSchema = z5.union([abortSchema, createNodesSchema]);
|
|
608
|
+
// ../helpers/src/protocol/update.ts
|
|
609
|
+
import {z as z6} from "zod";
|
|
610
|
+
var baseUpdateSchema = z6.object({
|
|
611
|
+
timestamp: z6.number().int().transform((int) => new Date(int))
|
|
612
|
+
});
|
|
613
|
+
var baseNodeUpdateSchema = baseUpdateSchema.extend({
|
|
614
|
+
nodeId: z6.string().uuid()
|
|
615
|
+
});
|
|
616
|
+
var nodeStartUpdateSchema = baseNodeUpdateSchema.extend({
|
|
617
|
+
type: z6.literal("NODE_START"),
|
|
618
|
+
context: contextSchema
|
|
619
|
+
});
|
|
620
|
+
var nodeErrorUpdateSchema = baseNodeUpdateSchema.extend({
|
|
621
|
+
type: z6.literal("NODE_ERROR"),
|
|
622
|
+
error: z6.string(),
|
|
623
|
+
context: contextSchema
|
|
624
|
+
});
|
|
625
|
+
var nodeUpdateSchema = baseNodeUpdateSchema.extend({
|
|
626
|
+
type: z6.literal("NODE_UPDATE"),
|
|
627
|
+
output: z6.string(),
|
|
628
|
+
data: z6.unknown(),
|
|
629
|
+
context: contextSchema
|
|
630
|
+
});
|
|
631
|
+
var nodeFinishedUpdateSchema = baseNodeUpdateSchema.extend({
|
|
632
|
+
type: z6.literal("NODE_FINISHED"),
|
|
633
|
+
context: contextSchema
|
|
634
|
+
});
|
|
635
|
+
var nodeDebugUpdateSchema = baseNodeUpdateSchema.extend({
|
|
636
|
+
type: z6.literal("NODE_DEBUG"),
|
|
637
|
+
severity: z6.enum(["log", "info", "warn", "error"]),
|
|
638
|
+
data: z6.unknown(),
|
|
639
|
+
context: contextSchema
|
|
640
|
+
});
|
|
641
|
+
var nodeDeferUpdateSchema = baseNodeUpdateSchema.extend({
|
|
642
|
+
type: z6.literal("NODE_DEFER"),
|
|
643
|
+
data: z6.unknown(),
|
|
644
|
+
context: contextSchema
|
|
645
|
+
});
|
|
646
|
+
var taskStartUpdateSchema = baseUpdateSchema.extend({
|
|
647
|
+
type: z6.literal("TASK_START"),
|
|
648
|
+
nodes: nodesSchema,
|
|
649
|
+
context: contextSchema
|
|
650
|
+
});
|
|
651
|
+
var taskErrorUpdateSchema = baseUpdateSchema.extend({
|
|
652
|
+
type: z6.literal("TASK_ERROR"),
|
|
653
|
+
reason: z6.string().optional(),
|
|
654
|
+
context: contextSchema
|
|
655
|
+
});
|
|
656
|
+
var taskFinishedUpdateSchema = baseUpdateSchema.extend({
|
|
657
|
+
type: z6.literal("TASK_FINISHED"),
|
|
658
|
+
context: contextSchema
|
|
659
|
+
});
|
|
660
|
+
var updateSchema = z6.discriminatedUnion("type", [
|
|
661
|
+
nodeStartUpdateSchema,
|
|
662
|
+
nodeErrorUpdateSchema,
|
|
663
|
+
nodeUpdateSchema,
|
|
664
|
+
nodeFinishedUpdateSchema,
|
|
665
|
+
nodeDebugUpdateSchema,
|
|
666
|
+
nodeDeferUpdateSchema,
|
|
667
|
+
taskStartUpdateSchema,
|
|
668
|
+
taskErrorUpdateSchema,
|
|
669
|
+
taskFinishedUpdateSchema
|
|
670
|
+
]);
|
|
671
|
+
// src/connections/createAmqpConnection.ts
|
|
672
|
+
import {connect} from "amqp-connection-manager";
|
|
673
|
+
import semver from "semver";
|
|
674
|
+
import {z as z7} from "zod";
|
|
675
|
+
|
|
676
|
+
// src/helpers.ts
|
|
677
|
+
function isOutputValue(value) {
|
|
678
|
+
return value !== null && typeof value === "object" && OUTPUT_VALUE in value;
|
|
679
|
+
}
|
|
680
|
+
function unwrapResult(result) {
|
|
681
|
+
if (isOutputValue(result)) {
|
|
682
|
+
return { value: result.value, outputName: result[OUTPUT_VALUE] };
|
|
683
|
+
}
|
|
684
|
+
return { value: result, outputName: null };
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
class RetryError extends Error {
|
|
688
|
+
delay;
|
|
689
|
+
constructor(delay) {
|
|
690
|
+
super();
|
|
691
|
+
this.delay = delay;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
class AbortError extends Error {
|
|
696
|
+
}
|
|
697
|
+
var OUTPUT_VALUE = Symbol("output_value");
|
|
698
|
+
function createExtendedContextHelper(options) {
|
|
699
|
+
const contextHelper = createContextHelper(options.context, options.nodes);
|
|
700
|
+
const internalContext = getInternalContext(contextHelper);
|
|
701
|
+
return Object.assign(contextHelper, {
|
|
702
|
+
taskId: options.taskId,
|
|
703
|
+
toOutput(name, value) {
|
|
704
|
+
return {
|
|
705
|
+
[OUTPUT_VALUE]: name,
|
|
706
|
+
value
|
|
707
|
+
};
|
|
708
|
+
},
|
|
709
|
+
defer: options.onDefer,
|
|
710
|
+
getConfiguration() {
|
|
711
|
+
const result = internalContext.results.get(options.serviceId);
|
|
712
|
+
if (result?.node.type === "service") {
|
|
713
|
+
return result.node.configuration ?? null;
|
|
714
|
+
}
|
|
715
|
+
return null;
|
|
716
|
+
},
|
|
717
|
+
getNode() {
|
|
718
|
+
return internalContext.results.get(options.serviceId).node;
|
|
719
|
+
},
|
|
720
|
+
state: createObjectProxy(options.state, options.onStateChange),
|
|
721
|
+
debug: {
|
|
722
|
+
log(...data) {
|
|
723
|
+
options.onLog("log", data);
|
|
724
|
+
},
|
|
725
|
+
info(...data) {
|
|
726
|
+
options.onLog("info", data);
|
|
727
|
+
},
|
|
728
|
+
warn(...data) {
|
|
729
|
+
options.onLog("warn", data);
|
|
730
|
+
},
|
|
731
|
+
error(...data) {
|
|
732
|
+
options.onLog("error", data);
|
|
733
|
+
}
|
|
734
|
+
},
|
|
735
|
+
retry(delay) {
|
|
736
|
+
throw new RetryError(delay);
|
|
737
|
+
},
|
|
738
|
+
abort(reason) {
|
|
739
|
+
throw new AbortError(reason);
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// src/connections/createAmqpConnection.ts
|
|
745
|
+
function isMessageHandlerGenerator(handler) {
|
|
746
|
+
return handler.constructor.name === "GeneratorFunction" || handler.constructor.name === "AsyncGeneratorFunction";
|
|
747
|
+
}
|
|
748
|
+
var messageKeySchema = z7.string().transform((str) => deobfuscate(str)).pipe(z7.array(z7.string().uuid()).length(3)).transform((arr) => ({
|
|
749
|
+
taskId: arr[0],
|
|
750
|
+
serviceId: arr[1],
|
|
751
|
+
messageId: arr[2]
|
|
752
|
+
}));
|
|
753
|
+
var headerSchema = z7.object({
|
|
754
|
+
properties: z7.object({
|
|
755
|
+
correlationId: z7.string().uuid(),
|
|
756
|
+
headers: z7.object({
|
|
757
|
+
version: z7.string(),
|
|
758
|
+
taskId: z7.string().uuid(),
|
|
759
|
+
serviceId: z7.string().uuid()
|
|
760
|
+
})
|
|
761
|
+
})
|
|
762
|
+
}).transform((msg) => ({
|
|
763
|
+
version: msg.properties.headers.version,
|
|
764
|
+
messageId: msg.properties.correlationId,
|
|
765
|
+
taskId: msg.properties.headers.taskId,
|
|
766
|
+
serviceId: msg.properties.headers.serviceId
|
|
767
|
+
}));
|
|
768
|
+
var payloadSchema = z7.object({ content: z7.instanceof(Buffer) }).transform((msg) => JSON.parse(msg.content.toString())).pipe(z7.object({
|
|
769
|
+
context: contextSchema,
|
|
770
|
+
meta: z7.object({
|
|
771
|
+
nodes: nodesSchema,
|
|
772
|
+
state: z7.record(z7.any())
|
|
773
|
+
})
|
|
774
|
+
}));
|
|
775
|
+
var activeMessages = new Set;
|
|
776
|
+
function createConnection({
|
|
777
|
+
url,
|
|
778
|
+
version,
|
|
779
|
+
prefetch = 1,
|
|
780
|
+
silent = false,
|
|
781
|
+
connectionTimeout
|
|
782
|
+
}, messageHandler) {
|
|
783
|
+
const queue = url.username;
|
|
784
|
+
const exchange = url.username;
|
|
785
|
+
const connection = connect(url.toString());
|
|
786
|
+
const connectedPromise = new Promise((resolve, reject) => {
|
|
787
|
+
const unsubscribe = () => {
|
|
788
|
+
clearTimeout(timeout);
|
|
789
|
+
connection.removeListener("connect", handleConnect);
|
|
790
|
+
connection.removeListener("connectFailed", handleConnectFailed);
|
|
791
|
+
};
|
|
792
|
+
const timeout = setTimeout(() => {
|
|
793
|
+
handleConnectFailed({ err: "Connection timeout" });
|
|
794
|
+
}, connectionTimeout);
|
|
795
|
+
const handleConnect = () => {
|
|
796
|
+
unsubscribe();
|
|
797
|
+
resolve();
|
|
798
|
+
};
|
|
799
|
+
const handleConnectFailed = ({ err }) => {
|
|
800
|
+
unsubscribe();
|
|
801
|
+
reject(new Error(err));
|
|
802
|
+
};
|
|
803
|
+
connection.addListener("connect", handleConnect);
|
|
804
|
+
connection.addListener("connectFailed", handleConnectFailed);
|
|
805
|
+
});
|
|
806
|
+
const channel = connection.createChannel({
|
|
807
|
+
async setup(channel2) {
|
|
808
|
+
await channel2.checkExchange(exchange);
|
|
809
|
+
await channel2.checkExchange(`${exchange}-retry`);
|
|
810
|
+
await channel2.checkQueue(queue);
|
|
811
|
+
await channel2.prefetch(prefetch);
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
const publish = ({
|
|
815
|
+
data,
|
|
816
|
+
outputName,
|
|
817
|
+
messageId,
|
|
818
|
+
...headers
|
|
819
|
+
}) => {
|
|
820
|
+
channel.publish(exchange, "", Buffer.from(JSON.stringify(data ?? null)), {
|
|
821
|
+
correlationId: messageId,
|
|
822
|
+
contentType: "application/json",
|
|
823
|
+
headers: {
|
|
824
|
+
outputName: outputName ?? null,
|
|
825
|
+
...headers
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
};
|
|
829
|
+
channel.consume(queue, async (message) => {
|
|
830
|
+
if (message.properties.headers?.abort || message.properties.headers?.exception) {
|
|
831
|
+
channel.nack(message, false, false);
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
let removeActiveMessage = () => {
|
|
835
|
+
};
|
|
836
|
+
try {
|
|
837
|
+
let deferred = false;
|
|
838
|
+
let deferredReason = null;
|
|
839
|
+
const {
|
|
840
|
+
messageId,
|
|
841
|
+
serviceId,
|
|
842
|
+
taskId,
|
|
843
|
+
version: expectedVersion
|
|
844
|
+
} = headerSchema.parse(message);
|
|
845
|
+
activeMessages.add(messageId);
|
|
846
|
+
removeActiveMessage = () => activeMessages.delete(messageId);
|
|
847
|
+
if (!semver.satisfies(version, expectedVersion)) {
|
|
848
|
+
let expirationDate = message.properties.headers?.["original-expiration-date"] ?? null;
|
|
849
|
+
if (!expirationDate && message.properties.expiration) {
|
|
850
|
+
expirationDate = String(Date.now() + parseInt(message.properties.expiration));
|
|
851
|
+
}
|
|
852
|
+
if (expirationDate && Date.now() > parseInt(expirationDate)) {
|
|
853
|
+
channel.nack(message, false, false);
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
const properties = {
|
|
857
|
+
...message.properties,
|
|
858
|
+
headers: {
|
|
859
|
+
...message.properties.headers,
|
|
860
|
+
"version-mismatch": version,
|
|
861
|
+
"original-expiration-date": expirationDate
|
|
862
|
+
},
|
|
863
|
+
expiration: 0
|
|
864
|
+
};
|
|
865
|
+
channel.publish(`${exchange}-retry`, "retry", message.content, properties);
|
|
866
|
+
channel.ack(message);
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
const payload = payloadSchema.parse(message);
|
|
870
|
+
let acked = false;
|
|
871
|
+
const ack = () => {
|
|
872
|
+
if (!acked) {
|
|
873
|
+
acked = true;
|
|
874
|
+
channel.ack(message);
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
let immediateUpdateState;
|
|
878
|
+
const extendedContext = createExtendedContextHelper({
|
|
879
|
+
serviceId,
|
|
880
|
+
context: payload.context,
|
|
881
|
+
nodes: payload.meta.nodes,
|
|
882
|
+
taskId,
|
|
883
|
+
state: payload.meta.state,
|
|
884
|
+
onStateChange(newState) {
|
|
885
|
+
clearImmediate(immediateUpdateState);
|
|
886
|
+
immediateUpdateState = setImmediate(() => {
|
|
887
|
+
publish({
|
|
888
|
+
messageId,
|
|
889
|
+
taskId,
|
|
890
|
+
serviceId,
|
|
891
|
+
data: clone(newState),
|
|
892
|
+
state: true
|
|
893
|
+
});
|
|
894
|
+
});
|
|
895
|
+
},
|
|
896
|
+
onLog(debugMethod, data) {
|
|
897
|
+
publish({
|
|
898
|
+
messageId,
|
|
899
|
+
taskId,
|
|
900
|
+
serviceId,
|
|
901
|
+
data,
|
|
902
|
+
debugMethod,
|
|
903
|
+
debug: true
|
|
904
|
+
});
|
|
905
|
+
},
|
|
906
|
+
onDefer(reason) {
|
|
907
|
+
deferred = true;
|
|
908
|
+
deferredReason = reason || null;
|
|
909
|
+
ack();
|
|
910
|
+
return obfuscate(taskId, serviceId, messageId);
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
if (isMessageHandlerGenerator(messageHandler)) {
|
|
914
|
+
const generator = messageHandler(extendedContext);
|
|
915
|
+
while (true) {
|
|
916
|
+
const { value: result, done } = await generator.next();
|
|
917
|
+
ack();
|
|
918
|
+
if (deferred) {
|
|
919
|
+
deferred = false;
|
|
920
|
+
console.warn("returning a value in a deferred message resets the deferred status");
|
|
921
|
+
}
|
|
922
|
+
const { value, outputName } = unwrapResult(result);
|
|
923
|
+
publish({
|
|
924
|
+
messageId,
|
|
925
|
+
taskId,
|
|
926
|
+
serviceId,
|
|
927
|
+
data: value,
|
|
928
|
+
outputName
|
|
929
|
+
});
|
|
930
|
+
if (done) {
|
|
931
|
+
break;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
} else {
|
|
935
|
+
const result = await messageHandler(extendedContext);
|
|
936
|
+
ack();
|
|
937
|
+
const { value, outputName } = unwrapResult(result);
|
|
938
|
+
if (deferred && value) {
|
|
939
|
+
console.warn("returning a value in a deferred message resets the deferred status");
|
|
940
|
+
deferred = false;
|
|
941
|
+
}
|
|
942
|
+
if (!deferred || value) {
|
|
943
|
+
publish({
|
|
944
|
+
messageId,
|
|
945
|
+
taskId,
|
|
946
|
+
serviceId,
|
|
947
|
+
data: value,
|
|
948
|
+
outputName
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
publish({
|
|
953
|
+
messageId,
|
|
954
|
+
taskId,
|
|
955
|
+
serviceId,
|
|
956
|
+
data: deferredReason,
|
|
957
|
+
deferred,
|
|
958
|
+
done: !deferred
|
|
959
|
+
});
|
|
960
|
+
} catch (error) {
|
|
961
|
+
if (error instanceof RetryError) {
|
|
962
|
+
const properties = {
|
|
963
|
+
...message.properties,
|
|
964
|
+
expiration: error.delay || 1000
|
|
965
|
+
};
|
|
966
|
+
channel.publish(`${exchange}-retry`, "retry", message.content, properties);
|
|
967
|
+
channel.ack(message);
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
if (error instanceof AbortError && error.message.length > 0) {
|
|
971
|
+
channel.publish(`${exchange}-retry`, "requeue", error.message, {
|
|
972
|
+
...message.properties,
|
|
973
|
+
expiration: 0,
|
|
974
|
+
priority: 0,
|
|
975
|
+
contentType: "text/plain",
|
|
976
|
+
headers: {
|
|
977
|
+
...message.properties.headers,
|
|
978
|
+
abort: true
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
channel.ack(message);
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
if (error instanceof Error) {
|
|
985
|
+
if (!silent) {
|
|
986
|
+
console.error(`Encountered an error inside service handler:`);
|
|
987
|
+
console.error(error);
|
|
988
|
+
}
|
|
989
|
+
channel.publish(`${exchange}-retry`, "requeue", message.content, {
|
|
990
|
+
...message.properties,
|
|
991
|
+
expiration: 0,
|
|
992
|
+
priority: 0,
|
|
993
|
+
headers: {
|
|
994
|
+
...message.properties.headers,
|
|
995
|
+
exception: true,
|
|
996
|
+
"error-message": error.message || "error in service handler"
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
channel.ack(message);
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
channel.nack(message, false, false);
|
|
1003
|
+
} finally {
|
|
1004
|
+
removeActiveMessage();
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1007
|
+
const api = {
|
|
1008
|
+
close: () => channel.close(),
|
|
1009
|
+
open: () => connectedPromise.then(() => api),
|
|
1010
|
+
sendToOutput(messageKey, outputName, data) {
|
|
1011
|
+
const { taskId, serviceId, messageId } = messageKeySchema.parse(messageKey);
|
|
1012
|
+
if (activeMessages.has(messageId)) {
|
|
1013
|
+
throw new Error("Cannot send deferred message while callback handler is still running");
|
|
1014
|
+
}
|
|
1015
|
+
publish({
|
|
1016
|
+
messageId,
|
|
1017
|
+
taskId,
|
|
1018
|
+
serviceId,
|
|
1019
|
+
data,
|
|
1020
|
+
outputName
|
|
1021
|
+
});
|
|
1022
|
+
},
|
|
1023
|
+
send(messageKey, data) {
|
|
1024
|
+
const { taskId, serviceId, messageId } = messageKeySchema.parse(messageKey);
|
|
1025
|
+
if (activeMessages.has(messageId)) {
|
|
1026
|
+
throw new Error("Cannot send deferred message while callback handler is still running");
|
|
1027
|
+
}
|
|
1028
|
+
publish({
|
|
1029
|
+
messageId,
|
|
1030
|
+
taskId,
|
|
1031
|
+
serviceId,
|
|
1032
|
+
data
|
|
1033
|
+
});
|
|
1034
|
+
},
|
|
1035
|
+
end(messageKey) {
|
|
1036
|
+
const { taskId, serviceId, messageId } = messageKeySchema.parse(messageKey);
|
|
1037
|
+
if (activeMessages.has(messageId)) {
|
|
1038
|
+
throw new Error("Cannot send deferred message while callback handler is still running");
|
|
1039
|
+
}
|
|
1040
|
+
publish({
|
|
1041
|
+
messageId,
|
|
1042
|
+
taskId,
|
|
1043
|
+
serviceId,
|
|
1044
|
+
done: true
|
|
1045
|
+
});
|
|
1046
|
+
},
|
|
1047
|
+
abort(messageKey, error) {
|
|
1048
|
+
const { taskId, serviceId, messageId } = messageKeySchema.parse(messageKey);
|
|
1049
|
+
if (activeMessages.has(messageId)) {
|
|
1050
|
+
throw new Error("Cannot send deferred message while callback handler is still running");
|
|
1051
|
+
}
|
|
1052
|
+
channel.publish(`${exchange}-retry`, "requeue", error instanceof Error ? error.message : error, {
|
|
1053
|
+
correlationId: messageId,
|
|
1054
|
+
expiration: 0,
|
|
1055
|
+
priority: 0,
|
|
1056
|
+
contentType: "text/plain",
|
|
1057
|
+
headers: {
|
|
1058
|
+
taskId,
|
|
1059
|
+
serviceId,
|
|
1060
|
+
abort: true
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
};
|
|
1065
|
+
return api;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// src/index.ts
|
|
1069
|
+
var versionSchema = z8.string().regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/, "not a valid version");
|
|
1070
|
+
var connectionOptionsSchema = z8.object({
|
|
1071
|
+
url: z8.union([
|
|
1072
|
+
z8.string().regex(/^amqps?:\/\/(.+):(.+)@(.+)$/).transform((str) => new URL(str)),
|
|
1073
|
+
z8.instanceof(URL).refine((url) => url.protocol.match(/^amqps?:/), "Wrong protocol")
|
|
1074
|
+
]),
|
|
1075
|
+
version: versionSchema,
|
|
1076
|
+
silent: z8.boolean().optional(),
|
|
1077
|
+
prefetch: z8.number().int().optional(),
|
|
1078
|
+
connectionTimeout: z8.number().positive().default(3000)
|
|
1079
|
+
});
|
|
1080
|
+
function createService(optionsOrVersion, optionalMessageHandler) {
|
|
1081
|
+
let options;
|
|
1082
|
+
let messageHandler;
|
|
1083
|
+
if (typeof optionsOrVersion === "string") {
|
|
1084
|
+
options = {
|
|
1085
|
+
version: optionsOrVersion
|
|
1086
|
+
};
|
|
1087
|
+
messageHandler = optionalMessageHandler;
|
|
1088
|
+
} else {
|
|
1089
|
+
options = optionsOrVersion;
|
|
1090
|
+
messageHandler = optionalMessageHandler;
|
|
1091
|
+
}
|
|
1092
|
+
const key = options.serviceKey ?? process.env.REQUENCE_SERVICE_KEY ?? JSON.parse(readFileSync("package.json", "utf-8")).requence?.serviceKey;
|
|
1093
|
+
if (!key) {
|
|
1094
|
+
throw Error("No service key found");
|
|
1095
|
+
}
|
|
1096
|
+
const parts = deobfuscate(key);
|
|
1097
|
+
if (parts.length < 2 || parts[0] !== "service") {
|
|
1098
|
+
throw new Error("Invalid service key");
|
|
1099
|
+
}
|
|
1100
|
+
const connectionOptions = {
|
|
1101
|
+
...options,
|
|
1102
|
+
url: parts[1]
|
|
1103
|
+
};
|
|
1104
|
+
return createConnection(connectionOptionsSchema.parse(connectionOptions), messageHandler);
|
|
1105
|
+
}
|
|
1106
|
+
export {
|
|
1107
|
+
createService as default
|
|
1108
|
+
};
|
|
1109
|
+
|
|
1110
|
+
//# debugId=C7AD515DE676451264756E2164756E21
|
|
1111
|
+
//# sourceMappingURL=index.js.map
|