@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.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { t as toWorkflowType } from "./utils-B_iPTfDi.js";
2
+ import { builtinModules } from "module";
2
3
  import { readFileSync } from "fs";
3
4
  import { writeFile } from "fs/promises";
4
5
  import path, { basename, join } from "path";
@@ -276,6 +277,95 @@ function rebaseModulePath(modulePath, sourceFilePath, outputFilePath) {
276
277
  const resolvedPath = path.resolve(path.dirname(sourceFilePath), modulePath);
277
278
  return normalizeImportPath(path.relative(path.dirname(outputFilePath), resolvedPath), path.extname(resolvedPath));
278
279
  }
280
+ function parseWorkflowChain$1(node) {
281
+ const methods = [];
282
+ let current = node;
283
+ while (t.isCallExpression(current) && t.isMemberExpression(current.callee) && !current.callee.computed) {
284
+ if (!t.isIdentifier(current.callee.property)) return null;
285
+ methods.unshift({
286
+ name: current.callee.property.name,
287
+ args: current.arguments
288
+ });
289
+ current = current.callee.object;
290
+ }
291
+ if (!t.isCallExpression(current) || !t.isIdentifier(current.callee, { name: "createWorkflow" })) return null;
292
+ return {
293
+ createWorkflowCall: current,
294
+ methods
295
+ };
296
+ }
297
+ function getStaticWorkflowId(call, filePath) {
298
+ const [config] = call.arguments;
299
+ if (!t.isObjectExpression(config)) throw new Error(`Unable to determine workflow config in ${filePath}`);
300
+ for (const property of config.properties) {
301
+ if (!t.isObjectProperty(property) || getObjectPropertyName(property) !== "id") continue;
302
+ if (t.isStringLiteral(property.value)) return property.value.value;
303
+ if (t.isTemplateLiteral(property.value) && property.value.expressions.length === 0) return property.value.quasis[0]?.value.cooked ?? "";
304
+ }
305
+ throw new Error(`Workflow id must be a static string in ${filePath}`);
306
+ }
307
+ function toExportName(id) {
308
+ return id.replace(/[^a-zA-Z0-9]+(.)/g, (_match, char) => char.toUpperCase()).replace(/^[^a-zA-Z_$]+/, "").replace(/^(.)/, (char) => char.toLowerCase());
309
+ }
310
+ function collectStaticFunctionBindings(program) {
311
+ const bindings = /* @__PURE__ */ new Set();
312
+ for (const statement of program.body) {
313
+ const declaration = t.isExportNamedDeclaration(statement) ? statement.declaration : statement;
314
+ if (t.isFunctionDeclaration(declaration) && declaration.id) {
315
+ bindings.add(declaration.id.name);
316
+ continue;
317
+ }
318
+ if (!t.isVariableDeclaration(declaration) || declaration.kind !== "const") continue;
319
+ for (const declarator of declaration.declarations) if (t.isIdentifier(declarator.id) && (t.isArrowFunctionExpression(declarator.init) || t.isFunctionExpression(declarator.init))) bindings.add(declarator.id.name);
320
+ }
321
+ return bindings;
322
+ }
323
+ function collectTopLevelBindingNames(program) {
324
+ const bindings = /* @__PURE__ */ new Set();
325
+ for (const statement of program.body) for (const name of Object.keys(t.getBindingIdentifiers(statement))) bindings.add(name);
326
+ return bindings;
327
+ }
328
+ function createMappingActivityStatements(workflowExpression, filePath, staticFunctionBindings, usedExportNames, requestContextClassName, addBinding) {
329
+ const chain = parseWorkflowChain$1(workflowExpression);
330
+ if (!chain) return [];
331
+ const workflowId = getStaticWorkflowId(chain.createWorkflowCall, filePath);
332
+ const statements = [];
333
+ let mappingOrdinal = 0;
334
+ for (const method of chain.methods) {
335
+ if (method.name !== "map") continue;
336
+ const [callback] = method.args;
337
+ if (t.isObjectExpression(callback)) throw new Error(`.map() in workflow ${workflowId} (${filePath}) does not yet support declarative object mappings`);
338
+ if (!t.isArrowFunctionExpression(callback) && !t.isFunctionExpression(callback) && !(t.isIdentifier(callback) && staticFunctionBindings.has(callback.name))) throw new Error(`.map() in workflow ${workflowId} (${filePath}) requires an inline function or a statically declared function identifier`);
339
+ const mappingId = `mapping_${workflowId}_${mappingOrdinal++}`;
340
+ const baseExportName = toExportName(mappingId);
341
+ let exportName = baseExportName;
342
+ let exportSuffix = 1;
343
+ while (usedExportNames.has(exportName)) exportName = `${baseExportName}${exportSuffix++}`;
344
+ usedExportNames.add(exportName);
345
+ const contextNames = [
346
+ "requestContext",
347
+ "runId",
348
+ "resourceId",
349
+ "workflowId"
350
+ ];
351
+ const params = t.objectPattern([
352
+ t.objectProperty(t.identifier("inputData"), t.identifier("inputData"), false, true),
353
+ t.objectProperty(t.identifier("initData"), t.identifier("initData"), false, true),
354
+ ...contextNames.map((name) => t.objectProperty(t.identifier(name), t.identifier(name), false, true))
355
+ ]);
356
+ const callbackContext = t.objectExpression([
357
+ t.objectProperty(t.identifier("inputData"), t.identifier("inputData"), false, true),
358
+ t.objectProperty(t.identifier("getInitData"), t.arrowFunctionExpression([], t.identifier("initData"))),
359
+ t.objectProperty(t.identifier("requestContext"), t.newExpression(t.identifier(requestContextClassName), [t.identifier("requestContext")])),
360
+ ...contextNames.filter((name) => name !== "requestContext").map((name) => t.objectProperty(t.identifier(name), t.identifier(name), false, true))
361
+ ]);
362
+ const callbackExpression = t.cloneNode(callback, true);
363
+ const body = t.callExpression(callbackExpression, [callbackContext]);
364
+ statements.push(t.exportNamedDeclaration(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(exportName), t.arrowFunctionExpression([params], body, true))])));
365
+ addBinding(exportName, mappingId);
366
+ }
367
+ return statements;
368
+ }
279
369
  function collectWorkflowBindingNames(ast) {
280
370
  const workflowNames = /* @__PURE__ */ new Set();
281
371
  for (const statement of ast.program.body) {
@@ -307,27 +397,38 @@ function hasLocalMastraBinding(ast) {
307
397
  return declaration.declarations.some((declarator) => t.isIdentifier(declarator.id, { name: "mastra" }));
308
398
  });
309
399
  }
310
- function createTemporalActivitiesHelperStatements(mastraImportPath, hasMastraBinding) {
311
- return parse(mastraImportPath ? `
312
- function createStep(args) {
313
- return async (params) => {
314
- const { mastra } = await import(${JSON.stringify(mastraImportPath)});
315
- return args.execute({ ...params, mastra });
316
- };
317
- }
318
- ` : hasMastraBinding ? `
319
- function createStep(args) {
320
- return async (params) => {
321
- return args.execute({ ...params, mastra });
322
- };
323
- }
324
- ` : `
325
- function createStep(args) {
326
- return async (params) => {
327
- return args.execute(params);
328
- };
329
- }
330
- `, {
400
+ function createTemporalActivitiesHelperStatements(mastraImportPath, hasMastraBinding, requestContextClassName) {
401
+ return parse(`
402
+ function withRequestContext(params) {
403
+ const { requestContext, initData, ...rest } = params;
404
+ return {
405
+ ...rest,
406
+ requestContext: new ${requestContextClassName}(requestContext),
407
+ getInitData: () => initData,
408
+ };
409
+ }
410
+
411
+ ${mastraImportPath ? `
412
+ function createStep(args) {
413
+ return async (params) => {
414
+ const { mastra } = await import(${JSON.stringify(mastraImportPath)});
415
+ return args.execute({ ...withRequestContext(params), mastra });
416
+ };
417
+ }
418
+ ` : hasMastraBinding ? `
419
+ function createStep(args) {
420
+ return async (params) => {
421
+ return args.execute({ ...withRequestContext(params), mastra });
422
+ };
423
+ }
424
+ ` : `
425
+ function createStep(args) {
426
+ return async (params) => {
427
+ return args.execute(withRequestContext(params));
428
+ };
429
+ }
430
+ `}
431
+ `, {
331
432
  sourceType: "module",
332
433
  plugins: parserPlugins
333
434
  }).program.body;
@@ -335,15 +436,18 @@ function createTemporalActivitiesHelperStatements(mastraImportPath, hasMastraBin
335
436
  async function buildTemporalActivitiesModule(entryFile, outputDirectory, outputFileName) {
336
437
  const activityBindings = [];
337
438
  const seenActivityBindingNames = /* @__PURE__ */ new Set();
338
- const addActivityBinding = (exportName, call) => {
339
- const stepId = getCreateStepId(call);
340
- if (!stepId || seenActivityBindingNames.has(exportName)) return;
439
+ const addGeneratedActivityBinding = (exportName, stepId) => {
440
+ if (seenActivityBindingNames.has(exportName)) return;
341
441
  seenActivityBindingNames.add(exportName);
342
442
  activityBindings.push({
343
443
  exportName,
344
444
  stepId
345
445
  });
346
446
  };
447
+ const addActivityBinding = (exportName, call) => {
448
+ const stepId = getCreateStepId(call);
449
+ if (stepId) addGeneratedActivityBinding(exportName, stepId);
450
+ };
347
451
  const bundle = await rollup({
348
452
  input: entryFile,
349
453
  treeshake: "smallest",
@@ -356,17 +460,23 @@ async function buildTemporalActivitiesModule(entryFile, outputDirectory, outputF
356
460
  plugins: parserPlugins,
357
461
  sourceFilename: id
358
462
  });
359
- const statements = [];
463
+ const usedExportNames = collectTopLevelBindingNames(ast.program);
464
+ let requestContextClassName = "TemporalRequestContext";
465
+ let requestContextSuffix = 1;
466
+ while (usedExportNames.has(requestContextClassName)) requestContextClassName = `TemporalRequestContext${requestContextSuffix++}`;
467
+ usedExportNames.add(requestContextClassName);
468
+ const statements = [t.importDeclaration([t.importSpecifier(t.identifier(requestContextClassName), t.identifier("RequestContext"))], t.stringLiteral("@mastra/core/di"))];
360
469
  const seenNames = /* @__PURE__ */ new Set();
361
470
  const strippedNames = /* @__PURE__ */ new Set();
362
471
  const workflowBindingNames = collectWorkflowBindingNames(ast);
363
472
  const stepFactoryBindings = collectCreateStepFactoryBindings(ast.program);
473
+ const staticFunctionBindings = collectStaticFunctionBindings(ast.program);
364
474
  const sourceFilePath = id;
365
475
  const hasMastraBinding = hasLocalMastraBinding(ast);
366
476
  let helperInserted = false;
367
477
  const ensureHelperInserted = () => {
368
478
  if (helperInserted) return;
369
- statements.push(...createTemporalActivitiesHelperStatements(null, hasMastraBinding));
479
+ statements.push(...createTemporalActivitiesHelperStatements(null, hasMastraBinding, requestContextClassName));
370
480
  helperInserted = true;
371
481
  };
372
482
  for (const statement of ast.program.body) {
@@ -422,6 +532,7 @@ async function buildTemporalActivitiesModule(entryFile, outputDirectory, outputF
422
532
  if (hasCreateWorkflowCall(declaration.init)) {
423
533
  workflowBindingNames.add(declaration.id.name);
424
534
  strippedNames.add(declaration.id.name);
535
+ statements.push(...createMappingActivityStatements(declaration.init, sourceFilePath, staticFunctionBindings, usedExportNames, requestContextClassName, addGeneratedActivityBinding));
425
536
  collectInlineCreateSteps(declaration.init, seenNames, statements, addActivityBinding);
426
537
  continue;
427
538
  }
@@ -461,6 +572,7 @@ async function buildTemporalActivitiesModule(entryFile, outputDirectory, outputF
461
572
  if (hasCreateWorkflowCall(declaration.init)) {
462
573
  workflowBindingNames.add(declaration.id.name);
463
574
  strippedNames.add(declaration.id.name);
575
+ statements.push(...createMappingActivityStatements(declaration.init, sourceFilePath, staticFunctionBindings, usedExportNames, requestContextClassName, addGeneratedActivityBinding));
464
576
  collectInlineCreateSteps(declaration.init, seenNames, statements, addActivityBinding);
465
577
  continue;
466
578
  }
@@ -660,7 +772,7 @@ function getWorkflowStepName(node, stepBindings) {
660
772
  * Most step references collapse down to step ids so the generated workflow can call
661
773
  * activities by id instead of keeping the original `createStep` definitions around.
662
774
  */
663
- function rewriteChainMethod(method, filePath, workflowName, stepBindings, workflowBindings) {
775
+ function rewriteChainMethod(method, filePath, workflowName, workflowId, mappingOrdinal, stepBindings, workflowBindings) {
664
776
  const argNode = (index) => method.args[index];
665
777
  const rewritten = (args, name = method.name) => ({
666
778
  name,
@@ -695,9 +807,16 @@ function rewriteChainMethod(method, filePath, workflowName, stepBindings, workfl
695
807
  case "parallel": {
696
808
  const arg = argNode(0);
697
809
  if (!t.isArrayExpression(arg)) throw new Error(`.parallel() in ${workflowName} (${filePath}) requires an array literal argument`);
698
- const names = arg.elements.map((el) => getWorkflowStepName(el, stepBindings));
699
- if (names.some((n) => !n)) throw new Error(`Unable to determine step names inside .parallel() in ${workflowName} (${filePath})`);
700
- return rewritten([t.arrayExpression(names.map((n) => t.stringLiteral(n)))]);
810
+ const entries = arg.elements.map((element) => {
811
+ if (t.isIdentifier(element)) {
812
+ const workflowType = workflowBindings.get(element.name);
813
+ if (workflowType) return t.objectExpression([t.objectProperty(t.identifier("type"), t.stringLiteral("childWorkflow")), t.objectProperty(t.identifier("workflowType"), t.stringLiteral(workflowType))]);
814
+ }
815
+ const stepId = getWorkflowStepName(element, stepBindings);
816
+ if (!stepId) throw new Error(`Unable to determine step names inside .parallel() in ${workflowName} (${filePath})`);
817
+ return t.objectExpression([t.objectProperty(t.identifier("type"), t.stringLiteral("step")), t.objectProperty(t.identifier("step"), t.objectExpression([t.objectProperty(t.identifier("id"), t.stringLiteral(stepId))]))]);
818
+ });
819
+ return rewritten([t.arrayExpression(entries)]);
701
820
  }
702
821
  case "branch": {
703
822
  const arg = argNode(0);
@@ -726,6 +845,15 @@ function rewriteChainMethod(method, filePath, workflowName, stepBindings, workfl
726
845
  if (optsArg && t.isExpression(optsArg)) args.push(t.cloneNode(optsArg, true));
727
846
  return rewritten(args);
728
847
  }
848
+ case "map": {
849
+ const callback = argNode(0);
850
+ if (t.isObjectExpression(callback)) throw new Error(`.map() in ${workflowName} (${filePath}) does not yet support declarative object mappings; use a callback mapping`);
851
+ if (!t.isArrowFunctionExpression(callback) && !t.isFunctionExpression(callback) && !t.isIdentifier(callback)) throw new Error(`.map() in ${workflowName} (${filePath}) requires an inline function or a statically declared function identifier`);
852
+ const args = [t.stringLiteral(`mapping_${workflowId}_${mappingOrdinal}`)];
853
+ const optsArg = method.args[1];
854
+ if (optsArg && t.isExpression(optsArg)) args.push(t.cloneNode(optsArg, true));
855
+ return rewritten(args);
856
+ }
729
857
  case "commit": return rewritten([]);
730
858
  default: throw new Error(`Unsupported workflow chain method .${method.name}() in ${workflowName} (${filePath})`);
731
859
  }
@@ -740,12 +868,14 @@ function getExportedName(node) {
740
868
  * we emit a deterministic exported function whose name matches Temporal's runtime
741
869
  * lookup and whose body delegates into the injected helper runtime.
742
870
  */
743
- function createTemporalWorkflowStatements(exportName, workflowId, methods, filePath, includeCommit, stepBindings, workflowBindings, runtimeOptions) {
871
+ function createTemporalWorkflowStatements(exportName, workflowId, workflowIdValue, methods, filePath, includeCommit, stepBindings, workflowBindings, runtimeOptions) {
744
872
  const createWorkflowArgs = [t.cloneNode(workflowId, true)];
745
873
  if (runtimeOptions) createWorkflowArgs.push(t.cloneNode(runtimeOptions, true));
746
874
  let expression = t.callExpression(t.identifier("createWorkflow"), createWorkflowArgs);
875
+ let mappingOrdinal = 0;
747
876
  for (const method of methods) {
748
- const rewrittenMethod = rewriteChainMethod(method, filePath, exportName, stepBindings, workflowBindings);
877
+ const rewrittenMethod = rewriteChainMethod(method, filePath, exportName, workflowIdValue, mappingOrdinal, stepBindings, workflowBindings);
878
+ if (method.name === "map") mappingOrdinal += 1;
749
879
  expression = t.callExpression(t.memberExpression(expression, t.identifier(rewrittenMethod.name)), rewrittenMethod.args);
750
880
  }
751
881
  if (includeCommit && !methods.some((m) => m.name === "commit")) expression = t.callExpression(t.memberExpression(expression, t.identifier("commit")), []);
@@ -777,6 +907,10 @@ function getCommittedWorkflowName(statement) {
777
907
  if (!t.isCallExpression(expression) || !t.isMemberExpression(expression.callee) || expression.callee.computed || !isIdentifierNamed(expression.callee.property, "commit") || !t.isIdentifier(expression.callee.object)) return null;
778
908
  return expression.callee.object.name;
779
909
  }
910
+ const nodeBuiltinModules = new Set(builtinModules.flatMap((moduleName) => [moduleName, `node:${moduleName}`]));
911
+ function isNodeBuiltinModule(moduleId) {
912
+ return nodeBuiltinModules.has(moduleId);
913
+ }
780
914
  function createWorkflowTransformState(program, filePath) {
781
915
  return {
782
916
  statements: [...createTemporalWorkflowHelperStatements()],
@@ -866,12 +1000,12 @@ function rewriteWorkflowVariableDeclaration(statement, filePath, state) {
866
1000
  }
867
1001
  const [workflowConfig] = workflowChain.createWorkflowCall.arguments;
868
1002
  if (!workflowConfig || !t.isObjectExpression(workflowConfig)) throw new Error(`Unable to determine workflow config for ${declaration.id.name} in ${filePath}`);
869
- const { expression: workflowId } = getWorkflowIdMetadata(workflowConfig, declaration.id.name, filePath);
1003
+ const { expression: workflowId, workflowId: workflowIdValue } = getWorkflowIdMetadata(workflowConfig, declaration.id.name, filePath);
870
1004
  const workflowExport = getTemporalWorkflowExportFromDeclaration(declaration, filePath);
871
1005
  if (!workflowExport) throw new Error(`Unable to determine workflow export for ${declaration.id.name} in ${filePath}`);
872
1006
  const { exportName } = workflowExport;
873
1007
  state.workflowExports.push(workflowExport);
874
- state.statements.push(...createTemporalWorkflowStatements(exportName, workflowId, workflowChain.methods, filePath, state.committedWorkflowNames.has(declaration.id.name), state.stepBindings, state.workflowBindings, state.runtimeOptions));
1008
+ state.statements.push(...createTemporalWorkflowStatements(exportName, workflowId, workflowIdValue, workflowChain.methods, filePath, state.committedWorkflowNames.has(declaration.id.name), state.stepBindings, state.workflowBindings, state.runtimeOptions));
875
1009
  }
876
1010
  if (declarations.length > 0) {
877
1011
  const cloned = declarations.map((declaration) => t.cloneNode(declaration, true));
@@ -936,14 +1070,16 @@ async function buildTemporalWorkflowModule(entryFile, outputDirectory, outputFil
936
1070
  }]
937
1071
  });
938
1072
  try {
939
- const baseName = basename(outputFileName);
940
- const { output } = await bundle.write({
1073
+ const outputOptions = {
941
1074
  dir: outputDirectory,
942
1075
  entryFileNames: outputFileName,
943
- chunkFileNames: `${baseName}-[hash].mjs`,
1076
+ chunkFileNames: `${basename(outputFileName)}-[hash].mjs`,
944
1077
  format: "esm",
945
1078
  sourcemap: "inline"
946
- });
1079
+ };
1080
+ const forbiddenImport = (await bundle.generate(outputOptions)).output.filter((output) => output.type === "chunk").flatMap((chunk) => [...chunk.imports, ...chunk.dynamicImports]).find(isNodeBuiltinModule);
1081
+ 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.`);
1082
+ const { output } = await bundle.write(outputOptions);
947
1083
  return { outputPath: join(outputDirectory, output.find((chunk) => chunk.type === "chunk" && chunk.isEntry).fileName) };
948
1084
  } finally {
949
1085
  await bundle.close();