@teleporthq/teleport-plugin-next-workflows 0.45.4 → 0.45.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teleporthq/teleport-plugin-next-workflows",
3
- "version": "0.45.4",
3
+ "version": "0.45.5",
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": "4fc86526c794a1304f0298809bf3530b4d380486"
72
+ "gitHead": "3af9d41f936652db5b37d0a40ebcc78bdfd685a5"
73
73
  }
@@ -14,7 +14,12 @@ import { isCostBearingNodeType } from './nodes/cost-bearing-node-types'
14
14
  import { nodeRegistry } from './nodes'
15
15
  import { NodeHandlerGenerator, ServerHandlerOptions, resolveHandlerEntryName } from './nodes/types'
16
16
  import { generalWait } from './nodes/general/general-wait'
17
- import { needsVisitorRequest, VISITOR_REQUEST_INJECTION } from './nodes/general/visitor-request'
17
+ import {
18
+ isOutboundMessageNodeType,
19
+ needsVisitorRequest,
20
+ VISITOR_REQUEST_INJECTION,
21
+ } from './nodes/general/visitor-request'
22
+ import { stepNameOf } from './nodes/email/message-trust'
18
23
  import {
19
24
  markVisitorBoundMessageNodes,
20
25
  markWebhookMessageNodes,
@@ -2180,6 +2185,33 @@ const generateErrorHandlerRunBlock = (
2180
2185
  }
2181
2186
  }`
2182
2187
 
2188
+ /**
2189
+ * The email and SMS steps a run of this automation can report as not having
2190
+ * sent. None when it could not tell: a custom node may send by itself, and a
2191
+ * parallel branch the run does not wait for has no result when the run ends.
2192
+ * Steps on the error branch do not count: a run that ends well never reaches them.
2193
+ */
2194
+ const reportableSendSteps = (
2195
+ workflow: UIDLWorkflow,
2196
+ errorHandlerNodes: Array<{ id: string }> | null
2197
+ ): Array<{ id: string; label: string }> => {
2198
+ const nodes = workflow.nodes || []
2199
+ const couldNotTell = nodes.some(
2200
+ (node) =>
2201
+ node.type === 'general-custom-node' ||
2202
+ (node.type === 'general-parallel' &&
2203
+ node.config?.waitForAll !== undefined &&
2204
+ node.config.waitForAll !== true)
2205
+ )
2206
+ if (couldNotTell) {
2207
+ return []
2208
+ }
2209
+ const errorBranch = new Set((errorHandlerNodes || []).map((node) => node.id))
2210
+ return nodes
2211
+ .filter((node) => isOutboundMessageNodeType(node.type) && !errorBranch.has(node.id))
2212
+ .map((node) => ({ id: node.id, label: stepNameOf(node) }))
2213
+ }
2214
+
2183
2215
  /**
2184
2216
  * An automation's handler module (`lib/automations/handlers/<file>.js`, see
2185
2217
  * automations/handler-module-generator.ts): the webhook route's node loop as
@@ -2199,6 +2231,8 @@ const generateErrorHandlerRunBlock = (
2199
2231
  * nothing and resolves `{ waiting: true, wouldWait }`; a Wait with no step
2200
2232
  * after it stores nothing and the run ends there). A run that fails rejects,
2201
2233
  * after the error-handler branch ran, so the dispatcher records the failure.
2234
+ * A run that ends with its email and SMS steps all unsent resolves with their
2235
+ * names under `sentNothing`, so the History can say so instead of Done.
2202
2236
  */
2203
2237
  export const generateHandlerFunction = (
2204
2238
  workflow: UIDLWorkflow,
@@ -2277,6 +2311,8 @@ const WORKFLOW_CONFIG = ${workflowConfig};
2277
2311
 
2278
2312
  var ERROR_HANDLER_NODES = ${errorHandlerNodesJson};
2279
2313
 
2314
+ var SEND_STEPS = ${JSON.stringify(reportableSendSteps(workflow, errorHandlerNodes))};
2315
+
2280
2316
  const nodeHandlers = {
2281
2317
  ${nodeHandlersEntries}
2282
2318
  };
@@ -2318,6 +2354,17 @@ ${executionLoop}
2318
2354
  return { waiting: false };
2319
2355
  }
2320
2356
 
2357
+ // The names of the send steps when the run has some and none of them sent: a
2358
+ // step a condition skipped has no result, one that failed and went on says so.
2359
+ function unsentSendSteps(context) {
2360
+ if (SEND_STEPS.length === 0) return null;
2361
+ var sent = SEND_STEPS.some(function(step) {
2362
+ var result = context[step.id];
2363
+ return !!result && !utils.isFatalNodeResult(result);
2364
+ });
2365
+ return sent ? null : SEND_STEPS.map(function(step) { return step.label; });
2366
+ }
2367
+
2321
2368
  async function run(event, context, resumeFrom) {
2322
2369
  context = context && typeof context === 'object' ? context : {};
2323
2370
  // Shared fire-and-forget queue — drained before the run settles.
@@ -2350,13 +2397,16 @@ async function run(event, context, resumeFrom) {
2350
2397
  sourceRef: WORKFLOW_ID,
2351
2398
  orderId: trigger.order && trigger.order.id ? String(trigger.order.id) : null,
2352
2399
  };
2400
+ var outcome;
2353
2401
  try {
2354
- return await runNodes(context, resumeFrom || null);
2402
+ outcome = await runNodes(context, resumeFrom || null);
2355
2403
  } catch (error) {
2356
2404
  ${generateErrorHandlerRunBlock('Automation error handler failed:')}
2357
2405
  await utils.settlePendingNodePromises(context);
2358
2406
  throw error;
2359
2407
  }
2408
+ var unsent = outcome.waiting ? null : unsentSendSteps(context);
2409
+ return unsent ? Object.assign({}, outcome, { sentNothing: unsent }) : outcome;
2360
2410
  }
2361
2411
 
2362
2412
  module.exports.run = run;
@@ -361,6 +361,14 @@ function runStatus(error, value) {
361
361
  return value && value.waiting === true ? 'waiting' : 'delivered';
362
362
  }
363
363
 
364
+ // What a run leaves in its delivery's error column: its error, or, for a run
365
+ // that finished, the send steps that did not send. Its status says nothing of
366
+ // them: such a run is delivered, and is neither retried nor counted as failed.
367
+ function runNote(error, value) {
368
+ if (error) return store.errorMessage(error);
369
+ return value && value.sentNothing ? JSON.stringify({ sentNothing: value.sentNothing }) : null;
370
+ }
371
+
364
372
  // Whether a guarded write found its row (the claim it names still held it).
365
373
  function wrote(result) {
366
374
  return !!result && result.rowCount > 0;
@@ -368,7 +376,7 @@ function wrote(result) {
368
376
 
369
377
  function lateDeliveryWriter(delivery, testRun, resumePoint) {
370
378
  return function (error, value) {
371
- var message = error ? store.errorMessage(error) : null;
379
+ var message = runNote(error, value);
372
380
  var status = testRun ? 'test' : runStatus(error, value);
373
381
  store.withClient(async function (client) {
374
382
  var finished = await client.query(FINISH_DELIVERY_SQL, [delivery.id, status, message, delivery.attempts]);
@@ -386,7 +394,7 @@ function lateWaitWriter(wait, resumedAt) {
386
394
  // Nothing is written once another dispatcher took the stale resume over:
387
395
  // that run records the outcome.
388
396
  store.withClient(function (client) {
389
- return finishResume(client, wait, runStatus(error, value), error ? store.errorMessage(error) : null, resumedAt);
397
+ return finishResume(client, wait, runStatus(error, value), runNote(error, value), resumedAt);
390
398
  }).catch(function (writeError) {
391
399
  console.error('[automations] could not record a late resume: ' + store.errorMessage(writeError));
392
400
  });
@@ -624,7 +632,7 @@ async function deliverEvent(client, row, context) {
624
632
  var error = ran.error ? store.errorMessage(ran.error) : null;
625
633
  if (error) console.error('[automations] ' + entry.name + ' failed for event ' + row.id + ': ' + error);
626
634
  // A run that stopped at a Wait is not finished: its delivery waits too.
627
- var finished = await client.query(FINISH_DELIVERY_SQL, [delivery.id, runStatus(ran.error, ran.value), error, delivery.attempts]);
635
+ var finished = await client.query(FINISH_DELIVERY_SQL, [delivery.id, runStatus(ran.error, ran.value), runNote(ran.error, ran.value), delivery.attempts]);
628
636
  if (resumePoint && !error && wrote(finished)) await client.query(SETTLE_FAILED_WAIT_SQL, [resumePoint.id]);
629
637
  if (error) outcome.failed += 1;
630
638
  else outcome.delivered += 1;
@@ -690,7 +698,7 @@ async function resumeWaits(client, context) {
690
698
  wait,
691
699
  eventRow,
692
700
  runStatus(ran.error, ran.value),
693
- ran.error ? store.errorMessage(ran.error) : null,
701
+ runNote(ran.error, ran.value),
694
702
  resumedAt
695
703
  );
696
704
  }
@@ -834,7 +842,7 @@ async function runTest(input, options) {
834
842
  }, timeoutMs, lateDeliveryWriter(delivery, true));
835
843
  if (ran.timedOut) return totals;
836
844
  var wouldWait = ran.value && ran.value.wouldWait ? ran.value.wouldWait : null;
837
- var note = ran.error ? store.errorMessage(ran.error) : wouldWait ? JSON.stringify({ wouldWait: wouldWait }) : null;
845
+ var note = wouldWait ? JSON.stringify({ wouldWait: wouldWait }) : runNote(ran.error, ran.value);
838
846
  await client.query(FINISH_DELIVERY_SQL, [delivery.id, 'test', note, delivery.attempts]);
839
847
  if (ran.error) totals.failed = 1;
840
848
  else totals.delivered = 1;
@@ -1008,6 +1008,9 @@ async function executeWorkflow(workflowConfig, triggerContext, nodeHandlers, opt
1008
1008
  if (triggerContext && triggerContext.__dynamicRouteParam) {
1009
1009
  context.__dynamicRouteParam = triggerContext.__dynamicRouteParam;
1010
1010
  }
1011
+ if (triggerContext && triggerContext.__tpa) {
1012
+ context.__tpa = triggerContext.__tpa;
1013
+ }
1011
1014
  if (triggerContext && triggerContext.triggerElement) {
1012
1015
  context.triggerElement = triggerContext.triggerElement;
1013
1016
  }
@@ -2151,6 +2154,7 @@ function buildContext(workflowConfig, triggerContext) {
2151
2154
  if (triggerContext.__stateValues) context.__stateValues = triggerContext.__stateValues;
2152
2155
  if (triggerContext.__routeParams) context.__routeParams = triggerContext.__routeParams;
2153
2156
  if (triggerContext.__dynamicRouteParam) context.__dynamicRouteParam = triggerContext.__dynamicRouteParam;
2157
+ if (triggerContext.__tpa) context.__tpa = triggerContext.__tpa;
2154
2158
  if (triggerContext.triggerElement) context.triggerElement = triggerContext.triggerElement;
2155
2159
  }
2156
2160
  // See executeWorkflow: the page's language travels with the run.