@mastra/temporal 0.4.6-alpha.0 → 0.4.6-alpha.11

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/dist/worker.cjs CHANGED
@@ -32,6 +32,7 @@ let _babel_parser = require("@babel/parser");
32
32
  let _babel_types = require("@babel/types");
33
33
  _babel_types = __toESM(_babel_types, 1);
34
34
  let rollup = require("rollup");
35
+ let module$1 = require("module");
35
36
  //#region src/transforms/shared.ts
36
37
  const parserPlugins = [
37
38
  "typescript",
@@ -301,6 +302,95 @@ function rebaseModulePath(modulePath, sourceFilePath, outputFilePath) {
301
302
  const resolvedPath = path.default.resolve(path.default.dirname(sourceFilePath), modulePath);
302
303
  return normalizeImportPath(path.default.relative(path.default.dirname(outputFilePath), resolvedPath), path.default.extname(resolvedPath));
303
304
  }
305
+ function parseWorkflowChain$1(node) {
306
+ const methods = [];
307
+ let current = node;
308
+ while (_babel_types.isCallExpression(current) && _babel_types.isMemberExpression(current.callee) && !current.callee.computed) {
309
+ if (!_babel_types.isIdentifier(current.callee.property)) return null;
310
+ methods.unshift({
311
+ name: current.callee.property.name,
312
+ args: current.arguments
313
+ });
314
+ current = current.callee.object;
315
+ }
316
+ if (!_babel_types.isCallExpression(current) || !_babel_types.isIdentifier(current.callee, { name: "createWorkflow" })) return null;
317
+ return {
318
+ createWorkflowCall: current,
319
+ methods
320
+ };
321
+ }
322
+ function getStaticWorkflowId(call, filePath) {
323
+ const [config] = call.arguments;
324
+ if (!_babel_types.isObjectExpression(config)) throw new Error(`Unable to determine workflow config in ${filePath}`);
325
+ for (const property of config.properties) {
326
+ if (!_babel_types.isObjectProperty(property) || getObjectPropertyName(property) !== "id") continue;
327
+ if (_babel_types.isStringLiteral(property.value)) return property.value.value;
328
+ if (_babel_types.isTemplateLiteral(property.value) && property.value.expressions.length === 0) return property.value.quasis[0]?.value.cooked ?? "";
329
+ }
330
+ throw new Error(`Workflow id must be a static string in ${filePath}`);
331
+ }
332
+ function toExportName(id) {
333
+ return id.replace(/[^a-zA-Z0-9]+(.)/g, (_match, char) => char.toUpperCase()).replace(/^[^a-zA-Z_$]+/, "").replace(/^(.)/, (char) => char.toLowerCase());
334
+ }
335
+ function collectStaticFunctionBindings(program) {
336
+ const bindings = /* @__PURE__ */ new Set();
337
+ for (const statement of program.body) {
338
+ const declaration = _babel_types.isExportNamedDeclaration(statement) ? statement.declaration : statement;
339
+ if (_babel_types.isFunctionDeclaration(declaration) && declaration.id) {
340
+ bindings.add(declaration.id.name);
341
+ continue;
342
+ }
343
+ if (!_babel_types.isVariableDeclaration(declaration) || declaration.kind !== "const") continue;
344
+ for (const declarator of declaration.declarations) if (_babel_types.isIdentifier(declarator.id) && (_babel_types.isArrowFunctionExpression(declarator.init) || _babel_types.isFunctionExpression(declarator.init))) bindings.add(declarator.id.name);
345
+ }
346
+ return bindings;
347
+ }
348
+ function collectTopLevelBindingNames(program) {
349
+ const bindings = /* @__PURE__ */ new Set();
350
+ for (const statement of program.body) for (const name of Object.keys(_babel_types.getBindingIdentifiers(statement))) bindings.add(name);
351
+ return bindings;
352
+ }
353
+ function createMappingActivityStatements(workflowExpression, filePath, staticFunctionBindings, usedExportNames, requestContextClassName, addBinding) {
354
+ const chain = parseWorkflowChain$1(workflowExpression);
355
+ if (!chain) return [];
356
+ const workflowId = getStaticWorkflowId(chain.createWorkflowCall, filePath);
357
+ const statements = [];
358
+ let mappingOrdinal = 0;
359
+ for (const method of chain.methods) {
360
+ if (method.name !== "map") continue;
361
+ const [callback] = method.args;
362
+ if (_babel_types.isObjectExpression(callback)) throw new Error(`.map() in workflow ${workflowId} (${filePath}) does not yet support declarative object mappings`);
363
+ if (!_babel_types.isArrowFunctionExpression(callback) && !_babel_types.isFunctionExpression(callback) && !(_babel_types.isIdentifier(callback) && staticFunctionBindings.has(callback.name))) throw new Error(`.map() in workflow ${workflowId} (${filePath}) requires an inline function or a statically declared function identifier`);
364
+ const mappingId = `mapping_${workflowId}_${mappingOrdinal++}`;
365
+ const baseExportName = toExportName(mappingId);
366
+ let exportName = baseExportName;
367
+ let exportSuffix = 1;
368
+ while (usedExportNames.has(exportName)) exportName = `${baseExportName}${exportSuffix++}`;
369
+ usedExportNames.add(exportName);
370
+ const contextNames = [
371
+ "requestContext",
372
+ "runId",
373
+ "resourceId",
374
+ "workflowId"
375
+ ];
376
+ const params = _babel_types.objectPattern([
377
+ _babel_types.objectProperty(_babel_types.identifier("inputData"), _babel_types.identifier("inputData"), false, true),
378
+ _babel_types.objectProperty(_babel_types.identifier("initData"), _babel_types.identifier("initData"), false, true),
379
+ ...contextNames.map((name) => _babel_types.objectProperty(_babel_types.identifier(name), _babel_types.identifier(name), false, true))
380
+ ]);
381
+ const callbackContext = _babel_types.objectExpression([
382
+ _babel_types.objectProperty(_babel_types.identifier("inputData"), _babel_types.identifier("inputData"), false, true),
383
+ _babel_types.objectProperty(_babel_types.identifier("getInitData"), _babel_types.arrowFunctionExpression([], _babel_types.identifier("initData"))),
384
+ _babel_types.objectProperty(_babel_types.identifier("requestContext"), _babel_types.newExpression(_babel_types.identifier(requestContextClassName), [_babel_types.identifier("requestContext")])),
385
+ ...contextNames.filter((name) => name !== "requestContext").map((name) => _babel_types.objectProperty(_babel_types.identifier(name), _babel_types.identifier(name), false, true))
386
+ ]);
387
+ const callbackExpression = _babel_types.cloneNode(callback, true);
388
+ const body = _babel_types.callExpression(callbackExpression, [callbackContext]);
389
+ statements.push(_babel_types.exportNamedDeclaration(_babel_types.variableDeclaration("const", [_babel_types.variableDeclarator(_babel_types.identifier(exportName), _babel_types.arrowFunctionExpression([params], body, true))])));
390
+ addBinding(exportName, mappingId);
391
+ }
392
+ return statements;
393
+ }
304
394
  function collectWorkflowBindingNames(ast) {
305
395
  const workflowNames = /* @__PURE__ */ new Set();
306
396
  for (const statement of ast.program.body) {
@@ -332,27 +422,38 @@ function hasLocalMastraBinding(ast) {
332
422
  return declaration.declarations.some((declarator) => _babel_types.isIdentifier(declarator.id, { name: "mastra" }));
333
423
  });
334
424
  }
335
- function createTemporalActivitiesHelperStatements(mastraImportPath, hasMastraBinding) {
336
- return (0, _babel_parser.parse)(mastraImportPath ? `
337
- function createStep(args) {
338
- return async (params) => {
339
- const { mastra } = await import(${JSON.stringify(mastraImportPath)});
340
- return args.execute({ ...params, mastra });
341
- };
342
- }
343
- ` : hasMastraBinding ? `
344
- function createStep(args) {
345
- return async (params) => {
346
- return args.execute({ ...params, mastra });
347
- };
348
- }
349
- ` : `
350
- function createStep(args) {
351
- return async (params) => {
352
- return args.execute(params);
353
- };
354
- }
355
- `, {
425
+ function createTemporalActivitiesHelperStatements(mastraImportPath, hasMastraBinding, requestContextClassName) {
426
+ return (0, _babel_parser.parse)(`
427
+ function withRequestContext(params) {
428
+ const { requestContext, initData, ...rest } = params;
429
+ return {
430
+ ...rest,
431
+ requestContext: new ${requestContextClassName}(requestContext),
432
+ getInitData: () => initData,
433
+ };
434
+ }
435
+
436
+ ${mastraImportPath ? `
437
+ function createStep(args) {
438
+ return async (params) => {
439
+ const { mastra } = await import(${JSON.stringify(mastraImportPath)});
440
+ return args.execute({ ...withRequestContext(params), mastra });
441
+ };
442
+ }
443
+ ` : hasMastraBinding ? `
444
+ function createStep(args) {
445
+ return async (params) => {
446
+ return args.execute({ ...withRequestContext(params), mastra });
447
+ };
448
+ }
449
+ ` : `
450
+ function createStep(args) {
451
+ return async (params) => {
452
+ return args.execute(withRequestContext(params));
453
+ };
454
+ }
455
+ `}
456
+ `, {
356
457
  sourceType: "module",
357
458
  plugins: parserPlugins
358
459
  }).program.body;
@@ -360,15 +461,18 @@ function createTemporalActivitiesHelperStatements(mastraImportPath, hasMastraBin
360
461
  async function buildTemporalActivitiesModule(entryFile, outputDirectory, outputFileName) {
361
462
  const activityBindings = [];
362
463
  const seenActivityBindingNames = /* @__PURE__ */ new Set();
363
- const addActivityBinding = (exportName, call) => {
364
- const stepId = getCreateStepId(call);
365
- if (!stepId || seenActivityBindingNames.has(exportName)) return;
464
+ const addGeneratedActivityBinding = (exportName, stepId) => {
465
+ if (seenActivityBindingNames.has(exportName)) return;
366
466
  seenActivityBindingNames.add(exportName);
367
467
  activityBindings.push({
368
468
  exportName,
369
469
  stepId
370
470
  });
371
471
  };
472
+ const addActivityBinding = (exportName, call) => {
473
+ const stepId = getCreateStepId(call);
474
+ if (stepId) addGeneratedActivityBinding(exportName, stepId);
475
+ };
372
476
  const bundle = await (0, rollup.rollup)({
373
477
  input: entryFile,
374
478
  treeshake: "smallest",
@@ -381,17 +485,23 @@ async function buildTemporalActivitiesModule(entryFile, outputDirectory, outputF
381
485
  plugins: parserPlugins,
382
486
  sourceFilename: id
383
487
  });
384
- const statements = [];
488
+ const usedExportNames = collectTopLevelBindingNames(ast.program);
489
+ let requestContextClassName = "TemporalRequestContext";
490
+ let requestContextSuffix = 1;
491
+ while (usedExportNames.has(requestContextClassName)) requestContextClassName = `TemporalRequestContext${requestContextSuffix++}`;
492
+ usedExportNames.add(requestContextClassName);
493
+ const statements = [_babel_types.importDeclaration([_babel_types.importSpecifier(_babel_types.identifier(requestContextClassName), _babel_types.identifier("RequestContext"))], _babel_types.stringLiteral("@mastra/core/di"))];
385
494
  const seenNames = /* @__PURE__ */ new Set();
386
495
  const strippedNames = /* @__PURE__ */ new Set();
387
496
  const workflowBindingNames = collectWorkflowBindingNames(ast);
388
497
  const stepFactoryBindings = collectCreateStepFactoryBindings(ast.program);
498
+ const staticFunctionBindings = collectStaticFunctionBindings(ast.program);
389
499
  const sourceFilePath = id;
390
500
  const hasMastraBinding = hasLocalMastraBinding(ast);
391
501
  let helperInserted = false;
392
502
  const ensureHelperInserted = () => {
393
503
  if (helperInserted) return;
394
- statements.push(...createTemporalActivitiesHelperStatements(null, hasMastraBinding));
504
+ statements.push(...createTemporalActivitiesHelperStatements(null, hasMastraBinding, requestContextClassName));
395
505
  helperInserted = true;
396
506
  };
397
507
  for (const statement of ast.program.body) {
@@ -447,6 +557,7 @@ async function buildTemporalActivitiesModule(entryFile, outputDirectory, outputF
447
557
  if (hasCreateWorkflowCall(declaration.init)) {
448
558
  workflowBindingNames.add(declaration.id.name);
449
559
  strippedNames.add(declaration.id.name);
560
+ statements.push(...createMappingActivityStatements(declaration.init, sourceFilePath, staticFunctionBindings, usedExportNames, requestContextClassName, addGeneratedActivityBinding));
450
561
  collectInlineCreateSteps(declaration.init, seenNames, statements, addActivityBinding);
451
562
  continue;
452
563
  }
@@ -486,6 +597,7 @@ async function buildTemporalActivitiesModule(entryFile, outputDirectory, outputF
486
597
  if (hasCreateWorkflowCall(declaration.init)) {
487
598
  workflowBindingNames.add(declaration.id.name);
488
599
  strippedNames.add(declaration.id.name);
600
+ statements.push(...createMappingActivityStatements(declaration.init, sourceFilePath, staticFunctionBindings, usedExportNames, requestContextClassName, addGeneratedActivityBinding));
489
601
  collectInlineCreateSteps(declaration.init, seenNames, statements, addActivityBinding);
490
602
  continue;
491
603
  }
@@ -685,7 +797,7 @@ function getWorkflowStepName(node, stepBindings) {
685
797
  * Most step references collapse down to step ids so the generated workflow can call
686
798
  * activities by id instead of keeping the original `createStep` definitions around.
687
799
  */
688
- function rewriteChainMethod(method, filePath, workflowName, stepBindings, workflowBindings) {
800
+ function rewriteChainMethod(method, filePath, workflowName, workflowId, mappingOrdinal, stepBindings, workflowBindings) {
689
801
  const argNode = (index) => method.args[index];
690
802
  const rewritten = (args, name = method.name) => ({
691
803
  name,
@@ -720,9 +832,16 @@ function rewriteChainMethod(method, filePath, workflowName, stepBindings, workfl
720
832
  case "parallel": {
721
833
  const arg = argNode(0);
722
834
  if (!_babel_types.isArrayExpression(arg)) throw new Error(`.parallel() in ${workflowName} (${filePath}) requires an array literal argument`);
723
- const names = arg.elements.map((el) => getWorkflowStepName(el, stepBindings));
724
- if (names.some((n) => !n)) throw new Error(`Unable to determine step names inside .parallel() in ${workflowName} (${filePath})`);
725
- return rewritten([_babel_types.arrayExpression(names.map((n) => _babel_types.stringLiteral(n)))]);
835
+ const entries = arg.elements.map((element) => {
836
+ if (_babel_types.isIdentifier(element)) {
837
+ const workflowType = workflowBindings.get(element.name);
838
+ if (workflowType) return _babel_types.objectExpression([_babel_types.objectProperty(_babel_types.identifier("type"), _babel_types.stringLiteral("childWorkflow")), _babel_types.objectProperty(_babel_types.identifier("workflowType"), _babel_types.stringLiteral(workflowType))]);
839
+ }
840
+ const stepId = getWorkflowStepName(element, stepBindings);
841
+ if (!stepId) throw new Error(`Unable to determine step names inside .parallel() in ${workflowName} (${filePath})`);
842
+ return _babel_types.objectExpression([_babel_types.objectProperty(_babel_types.identifier("type"), _babel_types.stringLiteral("step")), _babel_types.objectProperty(_babel_types.identifier("step"), _babel_types.objectExpression([_babel_types.objectProperty(_babel_types.identifier("id"), _babel_types.stringLiteral(stepId))]))]);
843
+ });
844
+ return rewritten([_babel_types.arrayExpression(entries)]);
726
845
  }
727
846
  case "branch": {
728
847
  const arg = argNode(0);
@@ -751,6 +870,15 @@ function rewriteChainMethod(method, filePath, workflowName, stepBindings, workfl
751
870
  if (optsArg && _babel_types.isExpression(optsArg)) args.push(_babel_types.cloneNode(optsArg, true));
752
871
  return rewritten(args);
753
872
  }
873
+ case "map": {
874
+ const callback = argNode(0);
875
+ if (_babel_types.isObjectExpression(callback)) throw new Error(`.map() in ${workflowName} (${filePath}) does not yet support declarative object mappings; use a callback mapping`);
876
+ if (!_babel_types.isArrowFunctionExpression(callback) && !_babel_types.isFunctionExpression(callback) && !_babel_types.isIdentifier(callback)) throw new Error(`.map() in ${workflowName} (${filePath}) requires an inline function or a statically declared function identifier`);
877
+ const args = [_babel_types.stringLiteral(`mapping_${workflowId}_${mappingOrdinal}`)];
878
+ const optsArg = method.args[1];
879
+ if (optsArg && _babel_types.isExpression(optsArg)) args.push(_babel_types.cloneNode(optsArg, true));
880
+ return rewritten(args);
881
+ }
754
882
  case "commit": return rewritten([]);
755
883
  default: throw new Error(`Unsupported workflow chain method .${method.name}() in ${workflowName} (${filePath})`);
756
884
  }
@@ -765,12 +893,14 @@ function getExportedName(node) {
765
893
  * we emit a deterministic exported function whose name matches Temporal's runtime
766
894
  * lookup and whose body delegates into the injected helper runtime.
767
895
  */
768
- function createTemporalWorkflowStatements(exportName, workflowId, methods, filePath, includeCommit, stepBindings, workflowBindings, runtimeOptions) {
896
+ function createTemporalWorkflowStatements(exportName, workflowId, workflowIdValue, methods, filePath, includeCommit, stepBindings, workflowBindings, runtimeOptions) {
769
897
  const createWorkflowArgs = [_babel_types.cloneNode(workflowId, true)];
770
898
  if (runtimeOptions) createWorkflowArgs.push(_babel_types.cloneNode(runtimeOptions, true));
771
899
  let expression = _babel_types.callExpression(_babel_types.identifier("createWorkflow"), createWorkflowArgs);
900
+ let mappingOrdinal = 0;
772
901
  for (const method of methods) {
773
- const rewrittenMethod = rewriteChainMethod(method, filePath, exportName, stepBindings, workflowBindings);
902
+ const rewrittenMethod = rewriteChainMethod(method, filePath, exportName, workflowIdValue, mappingOrdinal, stepBindings, workflowBindings);
903
+ if (method.name === "map") mappingOrdinal += 1;
774
904
  expression = _babel_types.callExpression(_babel_types.memberExpression(expression, _babel_types.identifier(rewrittenMethod.name)), rewrittenMethod.args);
775
905
  }
776
906
  if (includeCommit && !methods.some((m) => m.name === "commit")) expression = _babel_types.callExpression(_babel_types.memberExpression(expression, _babel_types.identifier("commit")), []);
@@ -802,6 +932,10 @@ function getCommittedWorkflowName(statement) {
802
932
  if (!_babel_types.isCallExpression(expression) || !_babel_types.isMemberExpression(expression.callee) || expression.callee.computed || !isIdentifierNamed(expression.callee.property, "commit") || !_babel_types.isIdentifier(expression.callee.object)) return null;
803
933
  return expression.callee.object.name;
804
934
  }
935
+ const nodeBuiltinModules = new Set(module$1.builtinModules.flatMap((moduleName) => [moduleName, `node:${moduleName}`]));
936
+ function isNodeBuiltinModule(moduleId) {
937
+ return nodeBuiltinModules.has(moduleId);
938
+ }
805
939
  function createWorkflowTransformState(program, filePath) {
806
940
  return {
807
941
  statements: [...createTemporalWorkflowHelperStatements()],
@@ -891,12 +1025,12 @@ function rewriteWorkflowVariableDeclaration(statement, filePath, state) {
891
1025
  }
892
1026
  const [workflowConfig] = workflowChain.createWorkflowCall.arguments;
893
1027
  if (!workflowConfig || !_babel_types.isObjectExpression(workflowConfig)) throw new Error(`Unable to determine workflow config for ${declaration.id.name} in ${filePath}`);
894
- const { expression: workflowId } = getWorkflowIdMetadata(workflowConfig, declaration.id.name, filePath);
1028
+ const { expression: workflowId, workflowId: workflowIdValue } = getWorkflowIdMetadata(workflowConfig, declaration.id.name, filePath);
895
1029
  const workflowExport = getTemporalWorkflowExportFromDeclaration(declaration, filePath);
896
1030
  if (!workflowExport) throw new Error(`Unable to determine workflow export for ${declaration.id.name} in ${filePath}`);
897
1031
  const { exportName } = workflowExport;
898
1032
  state.workflowExports.push(workflowExport);
899
- state.statements.push(...createTemporalWorkflowStatements(exportName, workflowId, workflowChain.methods, filePath, state.committedWorkflowNames.has(declaration.id.name), state.stepBindings, state.workflowBindings, state.runtimeOptions));
1033
+ state.statements.push(...createTemporalWorkflowStatements(exportName, workflowId, workflowIdValue, workflowChain.methods, filePath, state.committedWorkflowNames.has(declaration.id.name), state.stepBindings, state.workflowBindings, state.runtimeOptions));
900
1034
  }
901
1035
  if (declarations.length > 0) {
902
1036
  const cloned = declarations.map((declaration) => _babel_types.cloneNode(declaration, true));
@@ -961,14 +1095,16 @@ async function buildTemporalWorkflowModule(entryFile, outputDirectory, outputFil
961
1095
  }]
962
1096
  });
963
1097
  try {
964
- const baseName = (0, path.basename)(outputFileName);
965
- const { output } = await bundle.write({
1098
+ const outputOptions = {
966
1099
  dir: outputDirectory,
967
1100
  entryFileNames: outputFileName,
968
- chunkFileNames: `${baseName}-[hash].mjs`,
1101
+ chunkFileNames: `${(0, path.basename)(outputFileName)}-[hash].mjs`,
969
1102
  format: "esm",
970
1103
  sourcemap: "inline"
971
- });
1104
+ };
1105
+ const forbiddenImport = (await bundle.generate(outputOptions)).output.filter((output) => output.type === "chunk").flatMap((chunk) => [...chunk.imports, ...chunk.dynamicImports]).find(isNodeBuiltinModule);
1106
+ if (forbiddenImport) throw new Error(`Temporal workflow bundle cannot depend on Node.js builtin '${forbiddenImport}'. Move the dependency into an activity or remove it from workflow initialization.`);
1107
+ const { output } = await bundle.write(outputOptions);
972
1108
  return { outputPath: (0, path.join)(outputDirectory, output.find((chunk) => chunk.type === "chunk" && chunk.isEntry).fileName) };
973
1109
  } finally {
974
1110
  await bundle.close();