@teleporthq/teleport-plugin-next-workflows 0.45.14 → 0.45.15
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/__tests__/server-loop-types.test.ts +371 -0
- package/dist/cjs/api-route-generator.d.ts.map +1 -1
- package/dist/cjs/api-route-generator.js +14 -11
- package/dist/cjs/api-route-generator.js.map +1 -1
- package/dist/cjs/executor-generator.d.ts.map +1 -1
- package/dist/cjs/executor-generator.js +62 -27
- package/dist/cjs/executor-generator.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/api-route-generator.d.ts.map +1 -1
- package/dist/esm/api-route-generator.js +14 -11
- package/dist/esm/api-route-generator.js.map +1 -1
- package/dist/esm/executor-generator.d.ts.map +1 -1
- package/dist/esm/executor-generator.js +62 -27
- package/dist/esm/executor-generator.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/api-route-generator.ts +14 -11
- package/src/executor-generator.ts +62 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teleporthq/teleport-plugin-next-workflows",
|
|
3
|
-
"version": "0.45.
|
|
3
|
+
"version": "0.45.15",
|
|
4
4
|
"description": "A plugin for workflow code generation in Next.js projects.",
|
|
5
5
|
"author": "teleportHQ",
|
|
6
6
|
"license": "MIT",
|
|
@@ -69,5 +69,5 @@
|
|
|
69
69
|
"@teleporthq/teleport-shared": "^0.45.0",
|
|
70
70
|
"@teleporthq/teleport-types": "^0.45.0"
|
|
71
71
|
},
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "c93e2bd998c78f667928f7a87b6bb5175de8fea1"
|
|
73
73
|
}
|
|
@@ -479,8 +479,8 @@ module.exports = async function handler(req, res) {
|
|
|
479
479
|
continue;
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
-
// Loop nodes must be handled specially:
|
|
483
|
-
//
|
|
482
|
+
// Loop nodes must be handled specially: run the loop body nodes once per
|
|
483
|
+
// pass of the loop type (see createLoopSteps), then continue after the loop.
|
|
484
484
|
if (node.type === 'general-loop') {
|
|
485
485
|
const loopEdges = SEGMENT_CONFIG.edges.filter(function(e) { return e.source === node.id; });
|
|
486
486
|
const loopBodyEdge = loopEdges.find(function(e) { return e.sourceHandle === 'loop'; });
|
|
@@ -531,8 +531,9 @@ module.exports = async function handler(req, res) {
|
|
|
531
531
|
if (!context.__loopNodeIds) context.__loopNodeIds = {};
|
|
532
532
|
context.__loopNodeIds[node.id] = true;
|
|
533
533
|
|
|
534
|
-
|
|
535
|
-
|
|
534
|
+
var loopSteps = utils.createLoopSteps(node, resolved, context, collection);
|
|
535
|
+
for (var loopPass = loopSteps.next(context); loopPass; loopPass = loopSteps.next(context)) {
|
|
536
|
+
context[loopPass.key] = loopPass.value;
|
|
536
537
|
for (var bi = 0; bi < bodyNodes.length; bi++) {
|
|
537
538
|
var bNode = bodyNodes[bi];
|
|
538
539
|
var bResolved = resolveNodeConfig(bNode, context);
|
|
@@ -561,7 +562,7 @@ module.exports = async function handler(req, res) {
|
|
|
561
562
|
|
|
562
563
|
context.__loopScopeStack.pop();
|
|
563
564
|
|
|
564
|
-
context[node.id] = { completed: true, iterations:
|
|
565
|
+
context[node.id] = { completed: true, iterations: loopSteps.iterations(), results: loopResults };
|
|
565
566
|
// Store body node IDs so the outer loop can skip them
|
|
566
567
|
if (!context.__loopBodyNodeIds) context.__loopBodyNodeIds = {};
|
|
567
568
|
Object.assign(context.__loopBodyNodeIds, bodyNodeIds);
|
|
@@ -916,8 +917,9 @@ module.exports = async function handler(req, res) {
|
|
|
916
917
|
context.__loopScopeStack.push({ loopNodeId: node.id, bodyNodeIds: ssBodyNodeIds });
|
|
917
918
|
if (!context.__loopNodeIds) context.__loopNodeIds = {};
|
|
918
919
|
context.__loopNodeIds[node.id] = true;
|
|
919
|
-
|
|
920
|
-
|
|
920
|
+
var ssLoopSteps = utils.createLoopSteps(node, resolved, context, ssLoopCollection);
|
|
921
|
+
for (var ssLoopPass = ssLoopSteps.next(context); ssLoopPass; ssLoopPass = ssLoopSteps.next(context)) {
|
|
922
|
+
context[ssLoopPass.key] = ssLoopPass.value;
|
|
921
923
|
for (var ssbi = 0; ssbi < ssBodyNodes.length; ssbi++) {
|
|
922
924
|
var ssbNode = ssBodyNodes[ssbi];
|
|
923
925
|
var ssbRes = resolveNodeConfig(ssbNode, context);
|
|
@@ -941,7 +943,7 @@ module.exports = async function handler(req, res) {
|
|
|
941
943
|
}
|
|
942
944
|
}
|
|
943
945
|
context.__loopScopeStack.pop();
|
|
944
|
-
context[node.id] = { completed: true, iterations:
|
|
946
|
+
context[node.id] = { completed: true, iterations: ssLoopSteps.iterations(), results: ssLoopResults };
|
|
945
947
|
Object.keys(ssBodyNodeIds).forEach(function(k) { executed[k] = true; });
|
|
946
948
|
executed[node.id] = true;
|
|
947
949
|
if (streamStarted) {
|
|
@@ -1750,8 +1752,9 @@ ${resumeBlock}
|
|
|
1750
1752
|
if (!context.__loopNodeIds) context.__loopNodeIds = {};
|
|
1751
1753
|
context.__loopNodeIds[node.id] = true;
|
|
1752
1754
|
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
+
var loopSteps = utils.createLoopSteps(node, resolved, context, collection);
|
|
1756
|
+
for (var loopPass = loopSteps.next(context); loopPass; loopPass = loopSteps.next(context)) {
|
|
1757
|
+
context[loopPass.key] = loopPass.value;
|
|
1755
1758
|
for (var bi = 0; bi < bodyNodes.length; bi++) {
|
|
1756
1759
|
var bNode = bodyNodes[bi];
|
|
1757
1760
|
var bResolved = resolveNodeConfig(bNode, context);
|
|
@@ -1780,7 +1783,7 @@ ${resumeBlock}
|
|
|
1780
1783
|
|
|
1781
1784
|
context.__loopScopeStack.pop();
|
|
1782
1785
|
|
|
1783
|
-
context[node.id] = { completed: true, iterations:
|
|
1786
|
+
context[node.id] = { completed: true, iterations: loopSteps.iterations(), results: loopResults };
|
|
1784
1787
|
if (!context.__loopBodyNodeIds) context.__loopBodyNodeIds = {};
|
|
1785
1788
|
Object.assign(context.__loopBodyNodeIds, bodyNodeIds);
|
|
1786
1789
|
continue;
|
|
@@ -161,6 +161,60 @@ function loopIterationContext(collection, index) {
|
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
// How every loop type steps, for the client executor and for each server
|
|
165
|
+
// route alike. next(context) hands back what one pass publishes before its
|
|
166
|
+
// body runs ({ key, value }, stored as context[key]), or null once the loop is
|
|
167
|
+
// over. A collection is walked under the loop's own id; a counted or a
|
|
168
|
+
// conditional loop publishes its counter under "<loopId>_iter". A while / until
|
|
169
|
+
// condition is tested before every pass, against the context of that pass.
|
|
170
|
+
var DEFAULT_LOOP_MAX_ITERATIONS = 1000;
|
|
171
|
+
|
|
172
|
+
function createLoopSteps(loopNode, config, context, collection) {
|
|
173
|
+
var loopType = config.loopType || 'forEach';
|
|
174
|
+
var iterKey = loopNode.id + '_iter';
|
|
175
|
+
var passes = 0;
|
|
176
|
+
var next;
|
|
177
|
+
if (loopType === 'forEach' || loopType === 'map') {
|
|
178
|
+
next = function() {
|
|
179
|
+
return passes < collection.length
|
|
180
|
+
? { key: loopNode.id, value: loopIterationContext(collection, passes) }
|
|
181
|
+
: null;
|
|
182
|
+
};
|
|
183
|
+
} else if (loopType === 'for') {
|
|
184
|
+
var cursor = Number(resolveValue(config.startIndex, context)) || 0;
|
|
185
|
+
var end = Number(resolveValue(config.endIndex, context)) || 0;
|
|
186
|
+
var step = Number(resolveValue(config.step, context)) || 1;
|
|
187
|
+
next = function() {
|
|
188
|
+
if (!(step > 0 ? cursor < end : cursor > end)) return null;
|
|
189
|
+
var index = cursor;
|
|
190
|
+
cursor += step;
|
|
191
|
+
return { key: iterKey, value: { index: index } };
|
|
192
|
+
};
|
|
193
|
+
} else {
|
|
194
|
+
var maxIterations = Number(resolveValue(config.maxIterations, context)) || DEFAULT_LOOP_MAX_ITERATIONS;
|
|
195
|
+
var authoredCondition = loopNode.config && loopNode.config.condition;
|
|
196
|
+
next = function(passContext) {
|
|
197
|
+
if (passes >= maxIterations) return null;
|
|
198
|
+
var scaffold = { iteration: passes };
|
|
199
|
+
var testContext = Object.assign({}, passContext);
|
|
200
|
+
testContext[iterKey] = scaffold;
|
|
201
|
+
var condition = resolveValue(config.condition, testContext);
|
|
202
|
+
// Only the authored condition is compiled (see runExpression).
|
|
203
|
+
var holds = runExpression(authoredCondition, condition, ['context'], [testContext], testContext);
|
|
204
|
+
if (loopType === 'until' ? holds : !holds) return null;
|
|
205
|
+
return { key: iterKey, value: scaffold };
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
next: function(passContext) {
|
|
210
|
+
var pass = next(passContext || context);
|
|
211
|
+
if (pass) passes++;
|
|
212
|
+
return pass;
|
|
213
|
+
},
|
|
214
|
+
iterations: function() { return passes; }
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
164
218
|
function resolveCtxRef(ref, context) {
|
|
165
219
|
var elem = context.triggerElement;
|
|
166
220
|
if (!elem || typeof elem.getAttribute !== 'function') return undefined;
|
|
@@ -1496,35 +1550,15 @@ async function executeLoop(loopNode, config, allNodes, edges, context, nodeHandl
|
|
|
1496
1550
|
context[loopNode.id] = loopType === 'map'
|
|
1497
1551
|
? { results: results, iterations: collection.length }
|
|
1498
1552
|
: { completed: true, iterations: collection.length };
|
|
1499
|
-
} else if (loopType === 'for') {
|
|
1500
|
-
const start = resolveValue(config.startIndex, context) || 0;
|
|
1501
|
-
const end = resolveValue(config.endIndex, context) || 0;
|
|
1502
|
-
const step = resolveValue(config.step, context) || 1;
|
|
1503
|
-
let count = 0;
|
|
1504
|
-
for (let fi = start; step > 0 ? fi < end : fi > end; fi += step) {
|
|
1505
|
-
const forCtx = Object.assign({}, context);
|
|
1506
|
-
forCtx[loopNode.id + '_iter'] = { index: fi };
|
|
1507
|
-
await executeNodes(bodyNodes, edges, forCtx, nodeHandlers, workflowConfig, callServerSegment, executionId);
|
|
1508
|
-
Object.assign(context, forCtx);
|
|
1509
|
-
count++;
|
|
1510
|
-
}
|
|
1511
|
-
context[loopNode.id] = { completed: true, iterations: count };
|
|
1512
1553
|
} else {
|
|
1513
|
-
const
|
|
1514
|
-
let
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
// Only the authored condition is compiled (see runExpression).
|
|
1520
|
-
const condResult = runExpression(loopNode.config && loopNode.config.condition, condStr, ['context'], [whileCtx], whileCtx);
|
|
1521
|
-
if (loopType === 'while' && !condResult) break;
|
|
1522
|
-
if (loopType === 'until' && condResult) break;
|
|
1523
|
-
await executeNodes(bodyNodes, edges, whileCtx, nodeHandlers, workflowConfig, callServerSegment, executionId);
|
|
1524
|
-
Object.assign(context, whileCtx);
|
|
1525
|
-
iter++;
|
|
1554
|
+
const steps = createLoopSteps(loopNode, config, context);
|
|
1555
|
+
for (let pass = steps.next(context); pass; pass = steps.next(context)) {
|
|
1556
|
+
const passCtx = Object.assign({}, context);
|
|
1557
|
+
passCtx[pass.key] = pass.value;
|
|
1558
|
+
await executeNodes(bodyNodes, edges, passCtx, nodeHandlers, workflowConfig, callServerSegment, executionId);
|
|
1559
|
+
Object.assign(context, passCtx);
|
|
1526
1560
|
}
|
|
1527
|
-
context[loopNode.id] = { completed: true, iterations:
|
|
1561
|
+
context[loopNode.id] = { completed: true, iterations: steps.iterations() };
|
|
1528
1562
|
}
|
|
1529
1563
|
} finally {
|
|
1530
1564
|
context.__loopScopeStack.pop();
|
|
@@ -1820,6 +1854,7 @@ module.exports = {
|
|
|
1820
1854
|
resolveRichTextContext,
|
|
1821
1855
|
unwrapWorkflowCollection,
|
|
1822
1856
|
loopIterationContext,
|
|
1857
|
+
createLoopSteps,
|
|
1823
1858
|
snapshotIncomingContext,
|
|
1824
1859
|
segmentReply,
|
|
1825
1860
|
withoutCredentialColumns,
|