@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/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