@upstash/workflow 0.2.3 → 0.2.4

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.
@@ -30,6 +30,23 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  mod
31
31
  ));
32
32
 
33
+ // src/constants.ts
34
+ var WORKFLOW_ID_HEADER = "Upstash-Workflow-RunId";
35
+ var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
36
+ var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
37
+ var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
38
+ var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
39
+ var WORKFLOW_PROTOCOL_VERSION = "1";
40
+ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
41
+ var DEFAULT_CONTENT_TYPE = "application/json";
42
+ var NO_CONCURRENCY = 1;
43
+ var DEFAULT_RETRIES = 3;
44
+ var VERSION = "v0.2.3";
45
+ var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
46
+ var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
47
+ var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
48
+ var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
49
+
33
50
  // src/error.ts
34
51
  import { QstashError } from "@upstash/qstash";
35
52
  var WorkflowError = class extends QstashError {
@@ -738,30 +755,23 @@ var Err = class {
738
755
  };
739
756
  var fromThrowable = Result.fromThrowable;
740
757
 
741
- // src/constants.ts
742
- var WORKFLOW_ID_HEADER = "Upstash-Workflow-RunId";
743
- var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
744
- var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
745
- var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
746
- var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
747
- var WORKFLOW_PROTOCOL_VERSION = "1";
748
- var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
749
- var DEFAULT_CONTENT_TYPE = "application/json";
750
- var NO_CONCURRENCY = 1;
751
- var DEFAULT_RETRIES = 3;
752
-
753
758
  // src/workflow-requests.ts
754
759
  import { QstashError as QstashError3 } from "@upstash/qstash";
755
- var triggerFirstInvocation = async (workflowContext, retries, useJSONContent, debug) => {
756
- const { headers } = getHeaders(
757
- "true",
758
- workflowContext.workflowRunId,
759
- workflowContext.url,
760
- workflowContext.headers,
761
- void 0,
762
- workflowContext.failureUrl,
763
- retries
764
- );
760
+ var triggerFirstInvocation = async ({
761
+ workflowContext,
762
+ useJSONContent,
763
+ telemetry,
764
+ debug
765
+ }) => {
766
+ const { headers } = getHeaders({
767
+ initHeaderValue: "true",
768
+ workflowRunId: workflowContext.workflowRunId,
769
+ workflowUrl: workflowContext.url,
770
+ userHeaders: workflowContext.headers,
771
+ failureUrl: workflowContext.failureUrl,
772
+ retries: workflowContext.retries,
773
+ telemetry
774
+ });
765
775
  if (useJSONContent) {
766
776
  headers["content-type"] = "application/json";
767
777
  }
@@ -867,7 +877,16 @@ var recreateUserHeaders = (headers) => {
867
877
  }
868
878
  return filteredHeaders;
869
879
  };
870
- var handleThirdPartyCallResult = async (request, requestPayload, client, workflowUrl, failureUrl, retries, debug) => {
880
+ var handleThirdPartyCallResult = async ({
881
+ request,
882
+ requestPayload,
883
+ client,
884
+ workflowUrl,
885
+ failureUrl,
886
+ retries,
887
+ telemetry,
888
+ debug
889
+ }) => {
871
890
  try {
872
891
  if (request.headers.get("Upstash-Workflow-Callback")) {
873
892
  let callbackPayload;
@@ -926,15 +945,15 @@ ${atob(callbackMessage.body ?? "")}`
926
945
  );
927
946
  }
928
947
  const userHeaders = recreateUserHeaders(request.headers);
929
- const { headers: requestHeaders } = getHeaders(
930
- "false",
948
+ const { headers: requestHeaders } = getHeaders({
949
+ initHeaderValue: "false",
931
950
  workflowRunId,
932
951
  workflowUrl,
933
952
  userHeaders,
934
- void 0,
935
953
  failureUrl,
936
- retries
937
- );
954
+ retries,
955
+ telemetry
956
+ });
938
957
  const callResponse = {
939
958
  status: callbackMessage.status,
940
959
  body: atob(callbackMessage.body ?? ""),
@@ -972,12 +991,31 @@ ${atob(callbackMessage.body ?? "")}`
972
991
  );
973
992
  }
974
993
  };
975
- var getHeaders = (initHeaderValue, workflowRunId, workflowUrl, userHeaders, step, failureUrl, retries, callRetries, callTimeout) => {
994
+ var getTelemetryHeaders = (telemetry) => {
995
+ return {
996
+ [TELEMETRY_HEADER_SDK]: telemetry.sdk,
997
+ [TELEMETRY_HEADER_FRAMEWORK]: telemetry.framework,
998
+ [TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
999
+ };
1000
+ };
1001
+ var getHeaders = ({
1002
+ initHeaderValue,
1003
+ workflowRunId,
1004
+ workflowUrl,
1005
+ userHeaders,
1006
+ failureUrl,
1007
+ retries,
1008
+ step,
1009
+ callRetries,
1010
+ callTimeout,
1011
+ telemetry
1012
+ }) => {
976
1013
  const baseHeaders = {
977
1014
  [WORKFLOW_INIT_HEADER]: initHeaderValue,
978
1015
  [WORKFLOW_ID_HEADER]: workflowRunId,
979
1016
  [WORKFLOW_URL_HEADER]: workflowUrl,
980
- [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody"
1017
+ [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1018
+ ...telemetry ? getTelemetryHeaders(telemetry) : {}
981
1019
  };
982
1020
  if (!step?.callUrl) {
983
1021
  baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
@@ -1051,6 +1089,13 @@ var getHeaders = (initHeaderValue, workflowRunId, workflowUrl, userHeaders, step
1051
1089
  ...Object.fromEntries(
1052
1090
  Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
1053
1091
  ),
1092
+ // to include telemetry headers:
1093
+ ...telemetry ? Object.fromEntries(
1094
+ Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1095
+ header,
1096
+ [value]
1097
+ ])
1098
+ ) : {},
1054
1099
  // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1055
1100
  "Upstash-Workflow-Runid": [workflowRunId],
1056
1101
  [WORKFLOW_INIT_HEADER]: ["false"],
@@ -1089,6 +1134,7 @@ If you want to disable QStash Verification, you should clear env variables QSTAS
1089
1134
  };
1090
1135
 
1091
1136
  // src/context/auto-executor.ts
1137
+ import { QstashError as QstashError4 } from "@upstash/qstash";
1092
1138
  var AutoExecutor = class _AutoExecutor {
1093
1139
  context;
1094
1140
  promises = /* @__PURE__ */ new WeakMap();
@@ -1097,13 +1143,15 @@ var AutoExecutor = class _AutoExecutor {
1097
1143
  nonPlanStepCount;
1098
1144
  steps;
1099
1145
  indexInCurrentList = 0;
1146
+ telemetry;
1100
1147
  stepCount = 0;
1101
1148
  planStepCount = 0;
1102
1149
  executingStep = false;
1103
- constructor(context, steps, debug) {
1150
+ constructor(context, steps, telemetry, debug) {
1104
1151
  this.context = context;
1105
- this.debug = debug;
1106
1152
  this.steps = steps;
1153
+ this.telemetry = telemetry;
1154
+ this.debug = debug;
1107
1155
  this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
1108
1156
  }
1109
1157
  /**
@@ -1246,7 +1294,7 @@ var AutoExecutor = class _AutoExecutor {
1246
1294
  );
1247
1295
  await this.submitStepsToQStash([resultStep], [parallelStep]);
1248
1296
  } catch (error) {
1249
- if (error instanceof WorkflowAbort) {
1297
+ if (error instanceof WorkflowAbort || error instanceof QstashError4 && error.status === 400) {
1250
1298
  throw error;
1251
1299
  }
1252
1300
  throw new WorkflowError(
@@ -1317,15 +1365,16 @@ var AutoExecutor = class _AutoExecutor {
1317
1365
  });
1318
1366
  if (steps[0].waitEventId && steps.length === 1) {
1319
1367
  const waitStep = steps[0];
1320
- const { headers, timeoutHeaders } = getHeaders(
1321
- "false",
1322
- this.context.workflowRunId,
1323
- this.context.url,
1324
- this.context.headers,
1325
- waitStep,
1326
- this.context.failureUrl,
1327
- this.context.retries
1328
- );
1368
+ const { headers, timeoutHeaders } = getHeaders({
1369
+ initHeaderValue: "false",
1370
+ workflowRunId: this.context.workflowRunId,
1371
+ workflowUrl: this.context.url,
1372
+ userHeaders: this.context.headers,
1373
+ step: waitStep,
1374
+ failureUrl: this.context.failureUrl,
1375
+ retries: this.context.retries,
1376
+ telemetry: this.telemetry
1377
+ });
1329
1378
  const waitBody = {
1330
1379
  url: this.context.url,
1331
1380
  timeout: waitStep.timeout,
@@ -1352,17 +1401,18 @@ var AutoExecutor = class _AutoExecutor {
1352
1401
  const result = await this.context.qstashClient.batchJSON(
1353
1402
  steps.map((singleStep, index) => {
1354
1403
  const lazyStep = lazySteps[index];
1355
- const { headers } = getHeaders(
1356
- "false",
1357
- this.context.workflowRunId,
1358
- this.context.url,
1359
- this.context.headers,
1360
- singleStep,
1361
- this.context.failureUrl,
1362
- this.context.retries,
1363
- lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
1364
- lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0
1365
- );
1404
+ const { headers } = getHeaders({
1405
+ initHeaderValue: "false",
1406
+ workflowRunId: this.context.workflowRunId,
1407
+ workflowUrl: this.context.url,
1408
+ userHeaders: this.context.headers,
1409
+ step: singleStep,
1410
+ failureUrl: this.context.failureUrl,
1411
+ retries: this.context.retries,
1412
+ callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
1413
+ callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
1414
+ telemetry: this.telemetry
1415
+ });
1366
1416
  const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
1367
1417
  singleStep.out = JSON.stringify(singleStep.out);
1368
1418
  return singleStep.callUrl ? (
@@ -1727,7 +1777,8 @@ var WorkflowContext = class {
1727
1777
  debug,
1728
1778
  initialPayload,
1729
1779
  env,
1730
- retries
1780
+ retries,
1781
+ telemetry
1731
1782
  }) {
1732
1783
  this.qstashClient = qstashClient;
1733
1784
  this.workflowRunId = workflowRunId;
@@ -1738,7 +1789,7 @@ var WorkflowContext = class {
1738
1789
  this.requestPayload = initialPayload;
1739
1790
  this.env = env ?? {};
1740
1791
  this.retries = retries ?? DEFAULT_RETRIES;
1741
- this.executor = new AutoExecutor(this, this.steps, debug);
1792
+ this.executor = new AutoExecutor(this, this.steps, telemetry, debug);
1742
1793
  }
1743
1794
  /**
1744
1795
  * Executes a workflow step
@@ -2251,7 +2302,7 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
2251
2302
  };
2252
2303
  }
2253
2304
  };
2254
- var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, debug) => {
2305
+ var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, debug) => {
2255
2306
  if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
2256
2307
  return ok("not-failure-callback");
2257
2308
  }
@@ -2276,7 +2327,11 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2276
2327
  steps: [],
2277
2328
  url,
2278
2329
  failureUrl: url,
2279
- debug
2330
+ debug,
2331
+ env,
2332
+ retries,
2333
+ telemetry: void 0
2334
+ // not going to make requests in authentication check
2280
2335
  });
2281
2336
  const authCheck = await DisabledWorkflowContext.tryAuthentication(
2282
2337
  routeFunction,
@@ -2351,6 +2406,7 @@ var processOptions = (options) => {
2351
2406
  env: environment,
2352
2407
  retries: DEFAULT_RETRIES,
2353
2408
  useJSONContent: false,
2409
+ disableTelemetry: false,
2354
2410
  ...options
2355
2411
  };
2356
2412
  };
@@ -2385,7 +2441,7 @@ var determineUrls = async (request, url, baseUrl, failureFunction, failureUrl, d
2385
2441
  var AUTH_FAIL_MESSAGE = `Failed to authenticate Workflow request. If this is unexpected, see the caveat https://upstash.com/docs/workflow/basics/caveats#avoid-non-deterministic-code-outside-context-run`;
2386
2442
 
2387
2443
  // src/serve/index.ts
2388
- var serveBase = (routeFunction, options) => {
2444
+ var serveBase = (routeFunction, telemetry, options) => {
2389
2445
  const {
2390
2446
  qstashClient,
2391
2447
  onStepFinish,
@@ -2398,8 +2454,10 @@ var serveBase = (routeFunction, options) => {
2398
2454
  baseUrl,
2399
2455
  env,
2400
2456
  retries,
2401
- useJSONContent
2457
+ useJSONContent,
2458
+ disableTelemetry
2402
2459
  } = processOptions(options);
2460
+ telemetry = disableTelemetry ? void 0 : telemetry;
2403
2461
  const debug = WorkflowLogger.getLogger(verbose);
2404
2462
  const handler = async (request) => {
2405
2463
  await debug?.log("INFO", "ENDPOINT_START");
@@ -2435,7 +2493,10 @@ var serveBase = (routeFunction, options) => {
2435
2493
  qstashClient,
2436
2494
  initialPayloadParser,
2437
2495
  routeFunction,
2438
- failureFunction
2496
+ failureFunction,
2497
+ env,
2498
+ retries,
2499
+ debug
2439
2500
  );
2440
2501
  if (failureCheck.isErr()) {
2441
2502
  throw failureCheck.error;
@@ -2453,7 +2514,8 @@ var serveBase = (routeFunction, options) => {
2453
2514
  failureUrl: workflowFailureUrl,
2454
2515
  debug,
2455
2516
  env,
2456
- retries
2517
+ retries,
2518
+ telemetry
2457
2519
  });
2458
2520
  const authCheck = await DisabledWorkflowContext.tryAuthentication(
2459
2521
  routeFunction,
@@ -2469,22 +2531,23 @@ var serveBase = (routeFunction, options) => {
2469
2531
  "auth-fail"
2470
2532
  );
2471
2533
  }
2472
- const callReturnCheck = await handleThirdPartyCallResult(
2534
+ const callReturnCheck = await handleThirdPartyCallResult({
2473
2535
  request,
2474
- rawInitialPayload,
2475
- qstashClient,
2536
+ requestPayload: rawInitialPayload,
2537
+ client: qstashClient,
2476
2538
  workflowUrl,
2477
- workflowFailureUrl,
2539
+ failureUrl: workflowFailureUrl,
2478
2540
  retries,
2541
+ telemetry,
2479
2542
  debug
2480
- );
2543
+ });
2481
2544
  if (callReturnCheck.isErr()) {
2482
2545
  await debug?.log("ERROR", "SUBMIT_THIRD_PARTY_RESULT", {
2483
2546
  error: callReturnCheck.error.message
2484
2547
  });
2485
2548
  throw callReturnCheck.error;
2486
2549
  } else if (callReturnCheck.value === "continue-workflow") {
2487
- const result = isFirstInvocation ? await triggerFirstInvocation(workflowContext, retries, useJSONContent, debug) : await triggerRouteFunction({
2550
+ const result = isFirstInvocation ? await triggerFirstInvocation({ workflowContext, useJSONContent, telemetry, debug }) : await triggerRouteFunction({
2488
2551
  onStep: async () => routeFunction(workflowContext),
2489
2552
  onCleanup: async () => {
2490
2553
  await triggerWorkflowDelete(workflowContext, debug);
@@ -2519,7 +2582,14 @@ var serveBase = (routeFunction, options) => {
2519
2582
  return { handler: safeHandler };
2520
2583
  };
2521
2584
  var serve = (routeFunction, options) => {
2522
- return serveBase(routeFunction, options);
2585
+ return serveBase(
2586
+ routeFunction,
2587
+ {
2588
+ sdk: SDK_TELEMETRY,
2589
+ framework: "unknown"
2590
+ },
2591
+ options
2592
+ );
2523
2593
  };
2524
2594
 
2525
2595
  export {
@@ -2528,9 +2598,9 @@ export {
2528
2598
  __toESM,
2529
2599
  makeNotifyRequest,
2530
2600
  makeGetWaitersRequest,
2601
+ SDK_TELEMETRY,
2531
2602
  WorkflowError,
2532
2603
  WorkflowAbort,
2533
- DEFAULT_RETRIES,
2534
2604
  StepTypes,
2535
2605
  triggerFirstInvocation,
2536
2606
  WorkflowContext,
package/cloudflare.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as RouteFunction, j as PublicServeOptions } from './types-R9q4MUwl.mjs';
1
+ import { R as RouteFunction, j as PublicServeOptions } from './types-Bt4-paRy.mjs';
2
2
  import '@upstash/qstash';
3
3
 
4
4
  type WorkflowBindings = {
package/cloudflare.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as RouteFunction, j as PublicServeOptions } from './types-R9q4MUwl.js';
1
+ import { R as RouteFunction, j as PublicServeOptions } from './types-Bt4-paRy.js';
2
2
  import '@upstash/qstash';
3
3
 
4
4
  type WorkflowBindings = {