@tailor-platform/sdk 1.73.2 → 1.74.0

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.
Files changed (67) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/application-BndtMTFY.mjs +3 -0
  3. package/dist/{application-Bb9NNp5m.mjs → application-DwmoI6ZQ.mjs} +231 -153
  4. package/dist/application-DwmoI6ZQ.mjs.map +1 -0
  5. package/dist/cli/commands/deploy/apply-phases.d.mts +1 -0
  6. package/dist/cli/commands/executor/trigger.d.mts +1 -1
  7. package/dist/cli/index.mjs +102 -13
  8. package/dist/cli/index.mjs.map +1 -1
  9. package/dist/cli/lib.d.mts +2 -2
  10. package/dist/cli/lib.mjs +2 -2
  11. package/dist/cli/shared/client.d.mts +1 -1
  12. package/dist/completion/zsh-worker.zsh +28 -3
  13. package/dist/{repl-editor-BmQOyZJd.mjs → repl-editor-BCozyiNq.mjs} +3 -2
  14. package/dist/{repl-editor-BmQOyZJd.mjs.map → repl-editor-BCozyiNq.mjs.map} +1 -1
  15. package/dist/{runtime-B8O6JFS2.mjs → runtime-Zkg3SUwi.mjs} +1974 -1217
  16. package/dist/runtime-Zkg3SUwi.mjs.map +1 -0
  17. package/dist/{service-DiEtAsvc.mjs → service-BCRJ-3NV.mjs} +18 -1
  18. package/dist/{service-DiEtAsvc.mjs.map → service-BCRJ-3NV.mjs.map} +1 -1
  19. package/dist/service-CPMlIg3X.mjs +3 -0
  20. package/dist/tailor-proto/src/tailor/v1/aigateway_pb.d.mts +2 -2
  21. package/dist/tailor-proto/src/tailor/v1/aigateway_resource_pb.d.mts +1 -1
  22. package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +1 -1
  23. package/dist/tailor-proto/src/tailor/v1/application_resource_pb.d.mts +1 -1
  24. package/dist/tailor-proto/src/tailor/v1/auth_pb.d.mts +1 -1
  25. package/dist/tailor-proto/src/tailor/v1/auth_resource_pb.d.mts +1 -1
  26. package/dist/tailor-proto/src/tailor/v1/events_pb.d.mts +1 -1
  27. package/dist/tailor-proto/src/tailor/v1/events_resource_pb.d.mts +1 -1
  28. package/dist/tailor-proto/src/tailor/v1/executor_pb.d.mts +1 -1
  29. package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +1 -1
  30. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +1 -1
  31. package/dist/tailor-proto/src/tailor/v1/function_registry_pb.d.mts +1 -1
  32. package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +1 -1
  33. package/dist/tailor-proto/src/tailor/v1/http_adapter_resource_pb.d.mts +1 -1
  34. package/dist/tailor-proto/src/tailor/v1/idp_pb.d.mts +1 -1
  35. package/dist/tailor-proto/src/tailor/v1/idp_resource_pb.d.mts +1 -1
  36. package/dist/tailor-proto/src/tailor/v1/metadata_pb.d.mts +1 -1
  37. package/dist/tailor-proto/src/tailor/v1/metadata_resource_pb.d.mts +1 -1
  38. package/dist/tailor-proto/src/tailor/v1/meter_pb.d.mts +1 -1
  39. package/dist/tailor-proto/src/tailor/v1/pipeline_pb.d.mts +1 -1
  40. package/dist/tailor-proto/src/tailor/v1/pipeline_resource_pb.d.mts +1 -1
  41. package/dist/tailor-proto/src/tailor/v1/resource_pb.d.mts +1 -1
  42. package/dist/tailor-proto/src/tailor/v1/secret_manager_pb.d.mts +1 -1
  43. package/dist/tailor-proto/src/tailor/v1/secret_manager_resource_pb.d.mts +1 -1
  44. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +2 -2
  45. package/dist/tailor-proto/src/tailor/v1/stateflow_pb.d.mts +1 -1
  46. package/dist/tailor-proto/src/tailor/v1/stateflow_resource_pb.d.mts +1 -1
  47. package/dist/tailor-proto/src/tailor/v1/staticwebsite_pb.d.mts +1 -1
  48. package/dist/tailor-proto/src/tailor/v1/staticwebsite_resource_pb.d.mts +1 -1
  49. package/dist/tailor-proto/src/tailor/v1/tailordb_pb.d.mts +1 -1
  50. package/dist/tailor-proto/src/tailor/v1/tailordb_resource_pb.d.mts +1 -1
  51. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_pb.d.mts +1 -1
  52. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +1 -1
  53. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +1 -1
  54. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +1 -1
  55. package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +2 -2
  56. package/dist/tailor-proto/src/tailor/v1/workspace_resource_pb.d.mts +1 -1
  57. package/dist/vitest/index.mjs +2 -1
  58. package/dist/vitest/index.mjs.map +1 -1
  59. package/docs/cli/application.md +21 -11
  60. package/docs/cli/setup.md +25 -0
  61. package/docs/cli-reference.md +1 -0
  62. package/docs/services/tailordb.md +23 -0
  63. package/package.json +8 -8
  64. package/dist/application-BXdCl6bp.mjs +0 -3
  65. package/dist/application-Bb9NNp5m.mjs.map +0 -1
  66. package/dist/runtime-B8O6JFS2.mjs.map +0 -1
  67. package/dist/service-BXmdFwSH.mjs +0 -3
@@ -1,7 +1,7 @@
1
1
  import { n as isSdkBranded } from "./brand-Eo4pLXPJ.mjs";
2
2
  import { t as assertDefined } from "./assert-DBxo8jPo.mjs";
3
3
  import { a as parseBoolean, n as logger, r as styles } from "./logger-BEiZZ3qT.mjs";
4
- import { a as TailorFieldSchema, i as AuthInvokerSchema, n as ExecutorSchema, o as loadFilesWithIgnores, r as AuthConfigSchema, s as functionSchema, t as createExecutorService } from "./service-DiEtAsvc.mjs";
4
+ import { a as TailorFieldSchema, i as AuthInvokerSchema, n as ExecutorSchema, o as loadFilesWithIgnores, r as AuthConfigSchema, s as functionSchema, t as createExecutorService } from "./service-BCRJ-3NV.mjs";
5
5
  import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "./enum-constants-j9QBF0cB.mjs";
6
6
  import { t as multiline } from "./multiline-sfHpTZZK.mjs";
7
7
  import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "./file-utils-DcyIPFQh.mjs";
@@ -1540,8 +1540,8 @@ function createDepCollectorPlugin() {
1540
1540
 
1541
1541
  //#endregion
1542
1542
  //#region src/cli/cache/bundle-cache.ts
1543
- function buildCacheKey(kind, name) {
1544
- return `${kind}:${name}`;
1543
+ function buildCacheKey(kind, name, namespace) {
1544
+ return namespace ? `${kind}:${namespace}:${name}` : `${kind}:${name}`;
1545
1545
  }
1546
1546
  function combineHash(fileHash, contextHash) {
1547
1547
  if (!contextHash) return fileHash;
@@ -1568,10 +1568,11 @@ function computeBundlerContextHash(params) {
1568
1568
  * @returns The bundled code string
1569
1569
  */
1570
1570
  async function withCache(params) {
1571
- const { cache, kind, name, sourceFile, contextHash, build } = params;
1571
+ const { cache, kind, namespace, name, sourceFile, contextHash, build } = params;
1572
1572
  if (!cache) return await build([]);
1573
1573
  const content = cache.tryRestore({
1574
1574
  kind,
1575
+ namespace,
1575
1576
  name,
1576
1577
  contextHash
1577
1578
  });
@@ -1583,6 +1584,7 @@ async function withCache(params) {
1583
1584
  const code = await build([plugin]);
1584
1585
  cache.save({
1585
1586
  kind,
1587
+ namespace,
1586
1588
  name,
1587
1589
  sourceFile,
1588
1590
  content: code,
@@ -1598,7 +1600,7 @@ async function withCache(params) {
1598
1600
  */
1599
1601
  function createBundleCache(store) {
1600
1602
  function tryRestore(params) {
1601
- const cacheKey = buildCacheKey(params.kind, params.name);
1603
+ const cacheKey = buildCacheKey(params.kind, params.name, params.namespace);
1602
1604
  const entry = store.getEntry(cacheKey);
1603
1605
  if (!entry) return;
1604
1606
  let currentHash;
@@ -1611,8 +1613,8 @@ function createBundleCache(store) {
1611
1613
  return store.restoreBundleContent(cacheKey);
1612
1614
  }
1613
1615
  function save(params) {
1614
- const { kind, name, sourceFile, content, dependencyPaths, contextHash } = params;
1615
- const cacheKey = buildCacheKey(kind, name);
1616
+ const { kind, namespace, name, sourceFile, content, dependencyPaths, contextHash } = params;
1617
+ const cacheKey = buildCacheKey(kind, name, namespace);
1616
1618
  const allDeps = dependencyPaths.includes(sourceFile) ? dependencyPaths : [sourceFile, ...dependencyPaths];
1617
1619
  const inputHash = combineHash(hashFiles(allDeps), contextHash);
1618
1620
  const contentHash = hashContent(content);
@@ -2324,6 +2326,32 @@ function getImportSource(node) {
2324
2326
  }
2325
2327
  return null;
2326
2328
  }
2329
+ function argumentSourceText(arg, sourceText) {
2330
+ if (arg && typeof arg === "object" && "start" in arg && "end" in arg) return sourceText.slice(arg.start, arg.end);
2331
+ }
2332
+ /**
2333
+ * Get metadata for a static `identifier.trigger(...)` call.
2334
+ * @param node - AST node to inspect
2335
+ * @param sourceText - Source code text
2336
+ * @returns Trigger call metadata, or null when the node is not a trigger call
2337
+ */
2338
+ function getTriggerCallInfo(node, sourceText) {
2339
+ if (!node || typeof node !== "object" || node.type !== "CallExpression") return null;
2340
+ const callExpr = node;
2341
+ const callee = callExpr.callee;
2342
+ if (callee.type !== "MemberExpression") return null;
2343
+ const memberExpr = callee;
2344
+ if (memberExpr.computed || memberExpr.object.type !== "Identifier" || memberExpr.property.name !== "trigger") return null;
2345
+ return {
2346
+ identifierName: memberExpr.object.name,
2347
+ callRange: {
2348
+ start: callExpr.start,
2349
+ end: callExpr.end
2350
+ },
2351
+ argsText: argumentSourceText(callExpr.arguments[0], sourceText) ?? "",
2352
+ optionsText: argumentSourceText(callExpr.arguments[1], sourceText)
2353
+ };
2354
+ }
2327
2355
  /**
2328
2356
  * Unwrap AwaitExpression to get the inner expression
2329
2357
  * @param node - AST expression node
@@ -2370,12 +2398,20 @@ function findProperty(properties, name) {
2370
2398
  /**
2371
2399
  * Apply string replacements to source code
2372
2400
  * Replacements are applied from end to start to maintain positions
2401
+ * Ranges must not overlap; applying an overlapping range on top of an
2402
+ * already-shifted string would splice at stale offsets and corrupt the output,
2403
+ * so overlap is rejected up front
2373
2404
  * @param source - Original source code
2374
2405
  * @param replacements - Replacements to apply
2375
2406
  * @returns Transformed source code
2376
2407
  */
2377
2408
  function applyReplacements(source, replacements) {
2378
2409
  const sorted = replacements.toSorted((a, b) => b.start - a.start);
2410
+ for (let i = 0; i + 1 < sorted.length; i++) {
2411
+ const current = assertDefined(sorted[i], `replacement missing at index ${i}`);
2412
+ const previous = assertDefined(sorted[i + 1], `replacement missing at index ${i + 1}`);
2413
+ if (previous.end > current.start) throw new Error(`applyReplacements: overlapping replacement ranges [${previous.start}, ${previous.end}) and [${current.start}, ${current.end})`);
2414
+ }
2379
2415
  let result = source;
2380
2416
  for (const r of sorted) result = result.slice(0, r.start) + r.text + result.slice(r.end);
2381
2417
  return result;
@@ -2570,29 +2606,12 @@ function detectTriggerCalls(program, sourceText) {
2570
2606
  const calls = [];
2571
2607
  function walk(node) {
2572
2608
  if (!node || typeof node !== "object") return;
2573
- if (node.type === "CallExpression") {
2574
- const callExpr = node;
2575
- const callee = callExpr.callee;
2576
- if (callee.type === "MemberExpression") {
2577
- const memberExpr = callee;
2578
- if (!memberExpr.computed && memberExpr.object.type === "Identifier" && memberExpr.property.name === "trigger") {
2579
- const identifierName = memberExpr.object.name;
2580
- let argsText = "";
2581
- if (callExpr.arguments.length > 0) {
2582
- const firstArg = callExpr.arguments[0];
2583
- if (firstArg && "start" in firstArg && "end" in firstArg) argsText = sourceText.slice(firstArg.start, firstArg.end);
2584
- }
2585
- calls.push({
2586
- identifierName,
2587
- callRange: {
2588
- start: callExpr.start,
2589
- end: callExpr.end
2590
- },
2591
- argsText
2592
- });
2593
- }
2594
- }
2595
- }
2609
+ const triggerCall = getTriggerCallInfo(node, sourceText);
2610
+ if (triggerCall) calls.push({
2611
+ identifierName: triggerCall.identifierName,
2612
+ callRange: triggerCall.callRange,
2613
+ argsText: triggerCall.argsText
2614
+ });
2596
2615
  for (const key of Object.keys(node)) {
2597
2616
  const child = node[key];
2598
2617
  if (Array.isArray(child)) child.forEach((c) => walk(c));
@@ -2698,44 +2717,19 @@ function detectDefaultImports(program) {
2698
2717
  * Name of the injected runtime normalizer helper. Chosen to be unique enough
2699
2718
  * to avoid collisions with user code.
2700
2719
  */
2701
- const NORMALIZER_IDENTIFIER = "__tailor_normalizeAuthInvoker";
2720
+ const NORMALIZER_IDENTIFIER = "__tailor_normalizeTriggerOptions";
2702
2721
  /**
2703
2722
  * Build the source text of the injected normalizer helper.
2704
2723
  *
2705
- * Accepts either a plain string (machine user name) or the object form
2706
- * `{ namespace, machineUserName }`, and always returns the object form.
2707
- * The auth namespace is baked in at bundle time.
2724
+ * Expands a plain-string `authInvoker` (machine user name) in the trigger
2725
+ * options to the object form `{ namespace, machineUserName }`; any other
2726
+ * options value passes through unchanged. The auth namespace is baked in at
2727
+ * bundle time.
2708
2728
  * @param authNamespace - Auth service namespace to embed
2709
2729
  * @returns Source line defining the helper
2710
2730
  */
2711
2731
  function buildNormalizerHelperSource(authNamespace) {
2712
- return `const ${NORMALIZER_IDENTIFIER} = (v) => typeof v === "string" ? { namespace: ${JSON.stringify(authNamespace)}, machineUserName: v } : v;\n`;
2713
- }
2714
- /**
2715
- * Extract authInvoker info from a config object expression
2716
- * Returns the authInvoker value text and whether it's a shorthand property
2717
- * @param configArg - Config argument node
2718
- * @param sourceText - Source code text
2719
- * @returns Extracted authInvoker info, if any
2720
- */
2721
- function extractAuthInvokerInfo(configArg, sourceText) {
2722
- if (!configArg || typeof configArg !== "object") return void 0;
2723
- if (configArg.type !== "ObjectExpression") return void 0;
2724
- const objExpr = configArg;
2725
- for (const prop of objExpr.properties) {
2726
- if (prop.type !== "Property") continue;
2727
- const objProp = prop;
2728
- if ((objProp.key.type === "Identifier" ? objProp.key.name : objProp.key.type === "Literal" ? objProp.key.value : null) === "authInvoker") {
2729
- if (objProp.shorthand) return {
2730
- isShorthand: true,
2731
- valueText: "authInvoker"
2732
- };
2733
- return {
2734
- isShorthand: false,
2735
- valueText: sourceText.slice(objProp.value.start, objProp.value.end)
2736
- };
2737
- }
2738
- }
2732
+ return `const ${NORMALIZER_IDENTIFIER} = (o) => o && typeof o.authInvoker === "string" ? { ...o, authInvoker: { namespace: ${JSON.stringify(authNamespace)}, machineUserName: o.authInvoker } } : o;\n`;
2739
2733
  }
2740
2734
  /**
2741
2735
  * Check if an AST binding pattern (parameter, catch clause, etc.) contains an Identifier with the given name.
@@ -2865,48 +2859,23 @@ function detectExtendedTriggerCalls(program, sourceText, workflowNames, jobNames
2865
2859
  const calls = [];
2866
2860
  function walk(node) {
2867
2861
  if (!node || typeof node !== "object") return;
2868
- if (node.type === "CallExpression") {
2869
- const callExpr = node;
2870
- const callee = callExpr.callee;
2871
- if (callee.type === "MemberExpression") {
2872
- const memberExpr = callee;
2873
- const identifierName = !memberExpr.computed && memberExpr.object.type === "Identifier" ? memberExpr.object.name : null;
2874
- const propertyName = !memberExpr.computed ? memberExpr.property.name : null;
2875
- if (identifierName && propertyName === "trigger") {
2876
- const isWorkflow = workflowNames.has(identifierName);
2877
- const isJob = jobNames.has(identifierName);
2878
- if (isWorkflow || isJob) {
2879
- const argCount = callExpr.arguments.length;
2880
- let argsText = "";
2881
- if (argCount > 0) {
2882
- const firstArg = callExpr.arguments[0];
2883
- if (firstArg && "start" in firstArg && "end" in firstArg) argsText = sourceText.slice(firstArg.start, firstArg.end);
2884
- }
2885
- if (isWorkflow && argCount >= 2) {
2886
- const secondArg = callExpr.arguments[1];
2887
- const authInvoker = extractAuthInvokerInfo(secondArg, sourceText);
2888
- if (authInvoker) calls.push({
2889
- kind: "workflow",
2890
- identifierName,
2891
- callRange: {
2892
- start: callExpr.start,
2893
- end: callExpr.end
2894
- },
2895
- argsText,
2896
- authInvoker
2897
- });
2898
- } else if (isJob) calls.push({
2899
- kind: "job",
2900
- identifierName,
2901
- callRange: {
2902
- start: callExpr.start,
2903
- end: callExpr.end
2904
- },
2905
- argsText
2906
- });
2907
- }
2908
- }
2909
- }
2862
+ const triggerCall = getTriggerCallInfo(node, sourceText);
2863
+ if (triggerCall) {
2864
+ const isWorkflow = workflowNames.has(triggerCall.identifierName);
2865
+ const isJob = jobNames.has(triggerCall.identifierName);
2866
+ if (isWorkflow) calls.push({
2867
+ kind: "workflow",
2868
+ identifierName: triggerCall.identifierName,
2869
+ callRange: triggerCall.callRange,
2870
+ argsText: triggerCall.argsText,
2871
+ optionsText: triggerCall.optionsText
2872
+ });
2873
+ else if (isJob) calls.push({
2874
+ kind: "job",
2875
+ identifierName: triggerCall.identifierName,
2876
+ callRange: triggerCall.callRange,
2877
+ argsText: triggerCall.argsText
2878
+ });
2910
2879
  }
2911
2880
  for (const key of Object.keys(node)) {
2912
2881
  const child = node[key];
@@ -2945,20 +2914,32 @@ function transformFunctionTriggers(source, workflowNameMap, jobNameMap, workflow
2945
2914
  }
2946
2915
  }
2947
2916
  }
2948
- const triggerCalls = detectExtendedTriggerCalls(program, source, new Set(localWorkflowNameMap.keys()), new Set(jobNameMap.keys()));
2917
+ const allTriggerCalls = detectExtendedTriggerCalls(program, source, new Set(localWorkflowNameMap.keys()), new Set(jobNameMap.keys()));
2918
+ const nestedTriggerCalls = [];
2919
+ const triggerCalls = allTriggerCalls.filter((call) => {
2920
+ const parent = allTriggerCalls.find((other) => other !== call && other.callRange.start <= call.callRange.start && call.callRange.end <= other.callRange.end);
2921
+ if (parent) {
2922
+ nestedTriggerCalls.push({
2923
+ call,
2924
+ parent
2925
+ });
2926
+ return false;
2927
+ }
2928
+ return true;
2929
+ });
2930
+ for (const { call, parent } of nestedTriggerCalls) logger.warn(`Nested trigger call "${call.identifierName}.trigger(...)" inside "${parent.identifierName}.trigger(...)" cannot be converted. Move it to a separate statement and pass the result instead.`);
2949
2931
  const replacements = [];
2950
2932
  let needsNormalizerHelper = false;
2951
2933
  const transformedCallsPerIdentifier = /* @__PURE__ */ new Map();
2952
- for (const call of triggerCalls) if (call.kind === "workflow" && call.authInvoker) {
2934
+ for (const call of triggerCalls) if (call.kind === "workflow") {
2953
2935
  const workflowName = localWorkflowNameMap.get(call.identifierName);
2954
2936
  if (workflowName) {
2955
- const rawExpr = call.authInvoker.isShorthand ? "authInvoker" : call.authInvoker.valueText;
2956
- let authInvokerExpr;
2957
- if (authNamespace) {
2958
- authInvokerExpr = `${NORMALIZER_IDENTIFIER}(${rawExpr})`;
2937
+ let optionsPart = "";
2938
+ if (call.optionsText !== void 0) if (authNamespace) {
2939
+ optionsPart = `, ${NORMALIZER_IDENTIFIER}(${call.optionsText})`;
2959
2940
  needsNormalizerHelper = true;
2960
- } else authInvokerExpr = rawExpr;
2961
- const transformedCall = `tailor.workflow.triggerWorkflow("${workflowName}", ${call.argsText || "undefined"}, { authInvoker: ${authInvokerExpr} })`;
2941
+ } else optionsPart = `, ${call.optionsText}`;
2942
+ const transformedCall = `tailor.workflow.triggerWorkflow("${workflowName}", ${call.argsText || "undefined"}${optionsPart})`;
2962
2943
  replacements.push({
2963
2944
  start: call.callRange.start,
2964
2945
  end: call.callRange.end,
@@ -2966,7 +2947,7 @@ function transformFunctionTriggers(source, workflowNameMap, jobNameMap, workflow
2966
2947
  });
2967
2948
  transformedCallsPerIdentifier.set(call.identifierName, (transformedCallsPerIdentifier.get(call.identifierName) ?? 0) + 1);
2968
2949
  }
2969
- } else if (call.kind === "job") {
2950
+ } else {
2970
2951
  const jobName = jobNameMap.get(call.identifierName);
2971
2952
  if (jobName) {
2972
2953
  const transformedCall = `(async () => tailor.workflow.triggerJobFunction("${jobName}", ${call.argsText || "undefined"}))()`;
@@ -3161,6 +3142,28 @@ async function bundleAuthHooks(options) {
3161
3142
  return bundledCode;
3162
3143
  }
3163
3144
 
3145
+ //#endregion
3146
+ //#region src/utils/script-expr.ts
3147
+ const MAX_GENERATED_CODE_LENGTH = 2e3;
3148
+ function formatGeneratedCode(expr) {
3149
+ if (expr.length <= MAX_GENERATED_CODE_LENGTH) return `Generated code:\n${expr}`;
3150
+ return `Generated code (truncated to ${MAX_GENERATED_CODE_LENGTH} of ${expr.length} characters):\n${expr.slice(0, MAX_GENERATED_CODE_LENGTH)}\n...`;
3151
+ }
3152
+ /**
3153
+ * Assert that a generated script expression is syntactically valid JavaScript.
3154
+ * Invalid generated code would otherwise surface much later as a confusing
3155
+ * bundler or platform-side syntax error, far from the definition that caused it.
3156
+ * @param expr - Generated JavaScript expression
3157
+ * @param context - What generated the expression, used to label the error
3158
+ * @returns The expression unchanged when it parses successfully
3159
+ */
3160
+ function assertParsableExpression(expr, context) {
3161
+ const { errors } = parseSync("generated-expr.js", `(${expr}\n);`);
3162
+ if (errors.length === 0) return expr;
3163
+ const details = errors.map((error) => ` - ${error.message}`).join("\n");
3164
+ throw new Error(`Generated ${context} script is not valid JavaScript.\nParse errors:\n${details}\n` + formatGeneratedCode(expr));
3165
+ }
3166
+
3164
3167
  //#endregion
3165
3168
  //#region src/parser/service/tailordb/hooks-validate-precompiled-expr.ts
3166
3169
  const PRECOMPILED_EXPR_KEY = "__precompiledScriptExpr";
@@ -3214,30 +3217,38 @@ const stringifyFunction = (fn) => {
3214
3217
  if (firstObjectProperty(`({m: ${src}})`)) return src;
3215
3218
  const wrapped = `({${src}})`;
3216
3219
  const property = firstObjectProperty(wrapped);
3217
- if (property?.type === "Property" && property.method && !property.computed && property.value.type === "FunctionExpression") {
3220
+ if (property?.type === "Property" && property.method && property.computed) throw new Error("Computed-key method shorthand cannot be converted to a TailorDB script expression. Use an arrow function or function expression instead.");
3221
+ if (property?.type === "Property" && property.method && property.value.type === "FunctionExpression") {
3218
3222
  const { async, generator } = property.value;
3219
3223
  const body = wrapped.slice(property.value.start, property.value.end);
3220
3224
  return `${async ? "async " : ""}function${generator ? "*" : ""} ${body}`;
3221
3225
  }
3222
3226
  return src;
3223
3227
  };
3228
+ function formatScriptContext(kind, context) {
3229
+ if (!context) return kind === "validate" ? kind : "hooks";
3230
+ return `${kind} for ${context.typeName}.${context.fieldPath.join(".")}`;
3231
+ }
3224
3232
  /**
3225
3233
  * Convert a hook or validator function to a script expression.
3226
3234
  * @param fn - Hook or validator function
3235
+ * @param kind - Label naming the source of the expression in conversion errors
3236
+ * @param context - Optional field context for conversion errors
3227
3237
  * @returns JavaScript expression calling the function
3228
3238
  */
3229
- const convertToScriptExpr = (fn) => {
3239
+ const convertToScriptExpr = (fn, kind, context) => {
3230
3240
  const precompiledExpr = getPrecompiledScriptExpr(fn);
3231
3241
  if (precompiledExpr) return precompiledExpr;
3232
- return `(${stringifyFunction(fn)})({ value: _value, data: _data, user: ${tailorUserMap} })`;
3242
+ return assertParsableExpression(`(${stringifyFunction(fn)})({ value: _value, data: _data, user: ${tailorUserMap} })`, formatScriptContext(kind, context));
3233
3243
  };
3234
3244
  /**
3235
3245
  * Parse TailorDBField into OperatorFieldConfig.
3236
3246
  * This transforms user-defined functions into script expressions.
3237
3247
  * @param field - TailorDB field definition
3248
+ * @param context - Optional field context for conversion errors
3238
3249
  * @returns Parsed operator field configuration
3239
3250
  */
3240
- function parseFieldConfig(field) {
3251
+ function parseFieldConfig(field, context) {
3241
3252
  const metadata = field.metadata;
3242
3253
  const fieldType = field.type;
3243
3254
  const rawRelation = field.rawRelation;
@@ -3247,7 +3258,10 @@ function parseFieldConfig(field) {
3247
3258
  ...metadata,
3248
3259
  rawRelation,
3249
3260
  ...fieldType === "nested" && nestedFields && Object.keys(nestedFields).length > 0 ? { fields: Object.entries(nestedFields).reduce((acc, [key, nestedField]) => {
3250
- acc[key] = parseFieldConfig(nestedField);
3261
+ acc[key] = parseFieldConfig(nestedField, context && {
3262
+ ...context,
3263
+ fieldPath: [...context.fieldPath, key]
3264
+ });
3251
3265
  return acc;
3252
3266
  }, {}) } : {},
3253
3267
  validate: metadata.validate?.map((v) => {
@@ -3259,13 +3273,13 @@ function parseFieldConfig(field) {
3259
3273
  message: v[1]
3260
3274
  };
3261
3275
  return {
3262
- script: { expr: convertToScriptExpr(fn) },
3276
+ script: { expr: convertToScriptExpr(fn, "validate", context) },
3263
3277
  errorMessage: message
3264
3278
  };
3265
3279
  }),
3266
3280
  hooks: metadata.hooks ? {
3267
- create: metadata.hooks.create ? { expr: convertToScriptExpr(metadata.hooks.create) } : void 0,
3268
- update: metadata.hooks.update ? { expr: convertToScriptExpr(metadata.hooks.update) } : void 0
3281
+ create: metadata.hooks.create ? { expr: convertToScriptExpr(metadata.hooks.create, "hooks.create", context) } : void 0,
3282
+ update: metadata.hooks.update ? { expr: convertToScriptExpr(metadata.hooks.update, "hooks.update", context) } : void 0
3269
3283
  } : void 0,
3270
3284
  serial: metadata.serial ? {
3271
3285
  start: metadata.serial.start,
@@ -3508,7 +3522,7 @@ function applyRelationMetadataToFieldConfig(fieldConfig, metadata) {
3508
3522
  function parseTypes(rawTypes, namespace, typeSourceInfo) {
3509
3523
  const types = createRecord();
3510
3524
  const allTypeNames = new Set(Object.keys(rawTypes));
3511
- for (const [typeName, type] of Object.entries(rawTypes)) types[typeName] = parseTailorDBType(type, allTypeNames, rawTypes);
3525
+ for (const [typeName, type] of Object.entries(rawTypes)) types[typeName] = parseTailorDBType(type, allTypeNames, rawTypes, typeSourceInfo);
3512
3526
  buildBackwardRelationships(types, namespace, typeSourceInfo);
3513
3527
  validatePluralFormUniqueness(types, namespace, typeSourceInfo);
3514
3528
  return types;
@@ -3518,21 +3532,26 @@ function parseTypes(rawTypes, namespace, typeSourceInfo) {
3518
3532
  * @param type - TailorDB type to parse
3519
3533
  * @param allTypeNames - Set of all TailorDB type names
3520
3534
  * @param rawTypes - All raw TailorDB types keyed by name
3535
+ * @param typeSourceInfo - Optional type source information
3521
3536
  * @returns Parsed TailorDB type
3522
3537
  */
3523
- function parseTailorDBType(type, allTypeNames, rawTypes) {
3538
+ function parseTailorDBType(type, allTypeNames, rawTypes, typeSourceInfo) {
3524
3539
  const metadata = type.metadata;
3525
3540
  const pluralForm = metadata.settings?.pluralForm || inflection.pluralize(type.name);
3541
+ const typeLocation = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, type.name));
3526
3542
  const fields = createRecord();
3527
3543
  const forwardRelationships = createRecord();
3528
3544
  for (const [fieldName, fieldDef] of Object.entries(type.fields)) {
3529
- let fieldConfig = parseFieldConfig(fieldDef);
3530
- const rawRelation = fieldConfig.rawRelation;
3531
3545
  const context = {
3532
3546
  typeName: type.name,
3533
3547
  fieldName,
3534
3548
  allTypeNames
3535
3549
  };
3550
+ let fieldConfig = parseFieldConfig(fieldDef, {
3551
+ typeName: type.name,
3552
+ fieldPath: [fieldName]
3553
+ });
3554
+ const rawRelation = fieldConfig.rawRelation;
3536
3555
  if (rawRelation) {
3537
3556
  validateRelationConfig(rawRelation, context);
3538
3557
  if ([
@@ -3552,9 +3571,18 @@ function parseTailorDBType(type, allTypeNames, rawTypes) {
3552
3571
  const relationInfo = rawRelation ? buildRelationInfo(rawRelation, context) : void 0;
3553
3572
  if (relationInfo) {
3554
3573
  parsedField.relation = { ...relationInfo };
3574
+ const forwardName = relationInfo.forwardName;
3575
+ if (forwardName.length === 0) throw new Error(`Forward relation name for field "${fieldName}" on type "${type.name}"${typeLocation} cannot be empty. Use the "as" option in .relation({ toward: { as: ... } }) to specify a non-empty name.`);
3576
+ const existingForward = forwardRelationships[forwardName];
3577
+ if (existingForward) throw new Error(`Forward relation name "${forwardName}" on type "${type.name}"${typeLocation} is duplicated between fields "${existingForward.targetField}" and "${fieldName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a unique name.`);
3578
+ if (Object.hasOwn(type.fields, forwardName)) {
3579
+ const message = forwardName === fieldName ? `Forward relation name "${forwardName}" on type "${type.name}"${typeLocation} is the same as its own relation field "${fieldName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a different name.` : `Forward relation name "${forwardName}" from field "${fieldName}" on type "${type.name}"${typeLocation} conflicts with existing field "${forwardName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a different name.`;
3580
+ throw new Error(message);
3581
+ }
3582
+ if (Object.hasOwn(metadata.files, forwardName)) throw new Error(`Forward relation name "${forwardName}" from field "${fieldName}" on type "${type.name}"${typeLocation} conflicts with files field "${forwardName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a different name.`);
3555
3583
  const targetType = rawTypes[relationInfo.targetType];
3556
- forwardRelationships[relationInfo.forwardName] = {
3557
- name: relationInfo.forwardName,
3584
+ forwardRelationships[forwardName] = {
3585
+ name: forwardName,
3558
3586
  targetType: relationInfo.targetType,
3559
3587
  targetField: fieldName,
3560
3588
  sourceField: relationInfo.key,
@@ -3615,13 +3643,11 @@ function buildBackwardRelationships(types, namespace, typeSourceInfo) {
3615
3643
  for (const [targetTypeName, backwardNames] of Object.entries(backwardNameSources)) {
3616
3644
  const targetType = types[targetTypeName];
3617
3645
  if (targetType === void 0) throw new Error(`type not found: ${targetTypeName}`);
3618
- const targetTypeSourceInfo = getTypeSourceInfo(typeSourceInfo, targetTypeName);
3619
- const targetLocation = targetTypeSourceInfo ? isPluginGeneratedType(targetTypeSourceInfo) ? ` (plugin: ${targetTypeSourceInfo.pluginId})` : ` (${targetTypeSourceInfo.filePath})` : "";
3646
+ const targetLocation = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, targetTypeName));
3620
3647
  for (const [backwardName, sources] of Object.entries(backwardNames)) {
3621
3648
  if (sources.length > 1) {
3622
3649
  const sourceList = sources.map((s) => {
3623
- const sourceInfo = getTypeSourceInfo(typeSourceInfo, s.sourceType);
3624
- const location = sourceInfo ? isPluginGeneratedType(sourceInfo) ? ` (plugin: ${sourceInfo.pluginId})` : ` (${sourceInfo.filePath})` : "";
3650
+ const location = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, s.sourceType));
3625
3651
  return `${s.sourceType}.${s.fieldName}${location}`;
3626
3652
  }).join(", ");
3627
3653
  errors.push(`Backward relation name "${backwardName}" on type "${targetTypeName}" is duplicated from: ${sourceList}. Use the "backward" option in .relation() to specify unique names.`);
@@ -3629,17 +3655,21 @@ function buildBackwardRelationships(types, namespace, typeSourceInfo) {
3629
3655
  if (Object.hasOwn(targetType.fields, backwardName)) {
3630
3656
  const source = sources[0];
3631
3657
  if (source === void 0) throw new Error(`no source found for backward name: ${backwardName}`);
3632
- const sourceInfo = getTypeSourceInfo(typeSourceInfo, source.sourceType);
3633
- const sourceLocation = sourceInfo ? isPluginGeneratedType(sourceInfo) ? ` (plugin: ${sourceInfo.pluginId})` : ` (${sourceInfo.filePath})` : "";
3658
+ const sourceLocation = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, source.sourceType));
3634
3659
  errors.push(`Backward relation name "${backwardName}" from ${source.sourceType}.${source.fieldName}${sourceLocation} conflicts with existing field "${backwardName}" on type "${targetTypeName}"${targetLocation}. Use the "backward" option in .relation() to specify a different name.`);
3635
3660
  }
3636
3661
  if (targetType.files && Object.hasOwn(targetType.files, backwardName)) {
3637
3662
  const source = sources[0];
3638
3663
  if (source === void 0) throw new Error(`no source found for backward name: ${backwardName}`);
3639
- const sourceInfo = getTypeSourceInfo(typeSourceInfo, source.sourceType);
3640
- const sourceLocation = sourceInfo ? isPluginGeneratedType(sourceInfo) ? ` (plugin: ${sourceInfo.pluginId})` : ` (${sourceInfo.filePath})` : "";
3664
+ const sourceLocation = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, source.sourceType));
3641
3665
  errors.push(`Backward relation name "${backwardName}" from ${source.sourceType}.${source.fieldName}${sourceLocation} conflicts with files field "${backwardName}" on type "${targetTypeName}"${targetLocation}. Use the "backward" option in .relation() to specify a different name.`);
3642
3666
  }
3667
+ if (Object.hasOwn(targetType.forwardRelationships, backwardName)) {
3668
+ const source = sources[0];
3669
+ if (source === void 0) throw new Error(`no source found for backward name: ${backwardName}`);
3670
+ const sourceLocation = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, source.sourceType));
3671
+ errors.push(`Relation name "${backwardName}" on type "${targetTypeName}"${targetLocation} is used by both a forward relationship and a backward relationship from ${source.sourceType}.${source.fieldName}${sourceLocation}. Use the "as" option in .relation({ toward: { as: ... } }) or the "backward" option in .relation() to specify unique names.`);
3672
+ }
3643
3673
  }
3644
3674
  }
3645
3675
  if (errors.length > 0) throw new Error(`Backward relation name conflicts detected in TailorDB service "${namespace}".\n${errors.map((e) => ` - ${e}`).join("\n")}`);
@@ -3658,8 +3688,7 @@ function validatePluralFormUniqueness(types, namespace, typeSourceInfo) {
3658
3688
  for (const [, parsedType] of Object.entries(types)) {
3659
3689
  const singularQuery = inflection.camelize(parsedType.name, true);
3660
3690
  if (singularQuery === inflection.camelize(parsedType.pluralForm, true)) {
3661
- const sourceInfo = getTypeSourceInfo(typeSourceInfo, parsedType.name);
3662
- const location = sourceInfo ? isPluginGeneratedType(sourceInfo) ? ` (plugin: ${sourceInfo.pluginId})` : ` (${sourceInfo.filePath})` : "";
3691
+ const location = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, parsedType.name));
3663
3692
  errors.push(`Type "${parsedType.name}"${location} has identical singular and plural query names "${singularQuery}". Use db.type(["${parsedType.name}", "UniquePluralForm"], {...}) to set a unique pluralForm.`);
3664
3693
  }
3665
3694
  }
@@ -3685,8 +3714,7 @@ function validatePluralFormUniqueness(types, namespace, typeSourceInfo) {
3685
3714
  const duplicates = [...queryNameToSource].filter(([, sources]) => sources.length > 1);
3686
3715
  for (const [queryName, sources] of duplicates) {
3687
3716
  const sourceList = sources.map((s) => {
3688
- const sourceInfo = getTypeSourceInfo(typeSourceInfo, s.typeName);
3689
- const location = sourceInfo ? isPluginGeneratedType(sourceInfo) ? ` (plugin: ${sourceInfo.pluginId})` : ` (${sourceInfo.filePath})` : "";
3717
+ const location = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, s.typeName));
3690
3718
  return `"${s.typeName}"${location} (${s.kind})`;
3691
3719
  }).join(", ");
3692
3720
  errors.push(`GraphQL query field "${queryName}" conflicts between: ${sourceList}`);
@@ -3696,6 +3724,10 @@ function validatePluralFormUniqueness(types, namespace, typeSourceInfo) {
3696
3724
  function getTypeSourceInfo(typeSourceInfo, typeName) {
3697
3725
  return typeSourceInfo && Object.hasOwn(typeSourceInfo, typeName) ? typeSourceInfo[typeName] : void 0;
3698
3726
  }
3727
+ function formatTypeSourceLocation(sourceInfo) {
3728
+ if (!sourceInfo) return "";
3729
+ return isPluginGeneratedType(sourceInfo) ? ` (plugin: ${sourceInfo.pluginId})` : ` (${sourceInfo.filePath})`;
3730
+ }
3699
3731
  function createRecord() {
3700
3732
  return Object.create(null);
3701
3733
  }
@@ -4211,12 +4243,13 @@ function buildMinimalEntryFromResolved(imports, declarations, fnSource, sourceFi
4211
4243
  }
4212
4244
  async function bundleScriptTarget(args) {
4213
4245
  const { fn, kind, sourceFilePath, sourceBindings, tempDir, targetIndex, tsconfig } = args;
4246
+ const context = `${kind} in ${sourceFilePath}`;
4214
4247
  const fnSource = stringifyFunction(fn);
4215
- const inlineExpr = `(${fnSource})({ value: _value, data: _data, user: ${tailorUserMap} })`;
4248
+ const inlineExpr = assertParsableExpression(`(${fnSource})({ value: _value, data: _data, user: ${tailorUserMap} })`, context);
4216
4249
  const freeVars = findUndefinedReferences(`const __fn = ${fnSource};`);
4217
4250
  if (freeVars.size === 0) return inlineExpr;
4218
4251
  const { imports, declarations, unresolved } = resolveNeededBindings(freeVars, sourceBindings);
4219
- if (unresolved.length > 0) throw new Error(`${kind} in ${sourceFilePath} captures unresolvable variables (${unresolved.join(", ")}). Hooks and validators must not reference variables that cannot be resolved from the source file.
4252
+ if (unresolved.length > 0) throw new Error(`${context} captures unresolvable variables (${unresolved.join(", ")}). Hooks and validators must not reference variables that cannot be resolved from the source file.
4220
4253
  ${kind}: ${fnSource}`);
4221
4254
  const entryContent = buildMinimalEntryFromResolved(imports, declarations, fnSource, sourceFilePath);
4222
4255
  const entryPath = join(tempDir, `tailordb-script-${targetIndex}.entry.ts`);
@@ -4239,7 +4272,7 @@ async function bundleScriptTarget(args) {
4239
4272
  },
4240
4273
  logLevel: "silent"
4241
4274
  })).output[0].code;
4242
- return buildPrecompiledExpr(bundledCode);
4275
+ return assertParsableExpression(buildPrecompiledExpr(bundledCode), context);
4243
4276
  }
4244
4277
  /**
4245
4278
  * Precompile TailorDB hooks/validators into self-contained script expressions using rolldown.
@@ -4372,8 +4405,23 @@ function assertUniqueLocalTailorDBTypeNames(args) {
4372
4405
  */
4373
4406
  async function assertUniqueTailorDBTypeNamesWithExternal(args) {
4374
4407
  const localSources = collectLocalTailorDBTypeNameSources(args);
4375
- const externalSources = args.externalTailorDBNamespaces.length > 0 ? await fetchExternalTailorDBTypeNameSources(args) : [];
4376
- assertUniqueTailorDBTypeNames({ sources: [...localSources, ...externalSources] });
4408
+ const plannedExternalServices = args.plannedExternalTailorDBServices ?? [];
4409
+ const plannedExternalNamespaces = new Set(plannedExternalServices.map((service) => service.namespace));
4410
+ const plannedExternalSources = collectLocalTailorDBTypeNameSources({ tailorDBServices: plannedExternalServices }).map((source) => ({
4411
+ ...source,
4412
+ kind: "external"
4413
+ }));
4414
+ const remoteExternalNamespaces = args.externalTailorDBNamespaces.filter((namespace) => !plannedExternalNamespaces.has(namespace));
4415
+ const externalSources = remoteExternalNamespaces.length > 0 ? await fetchExternalTailorDBTypeNameSources({
4416
+ client: args.client,
4417
+ workspaceId: args.workspaceId,
4418
+ externalTailorDBNamespaces: remoteExternalNamespaces
4419
+ }) : [];
4420
+ assertUniqueTailorDBTypeNames({ sources: [
4421
+ ...localSources,
4422
+ ...plannedExternalSources,
4423
+ ...externalSources
4424
+ ] });
4377
4425
  }
4378
4426
  function formatTailorDBTypeNameSource(source) {
4379
4427
  const namespaceLabel = source.kind === "external" ? `external namespace "${source.namespace}"` : `namespace "${source.namespace}"`;
@@ -5226,12 +5274,12 @@ async function bundleResolvers(namespace, config, triggerContext, cache, inlineS
5226
5274
  } catch {
5227
5275
  tsconfig = void 0;
5228
5276
  }
5229
- const results = await withBundleConcurrency(resolvers, (resolver) => bundleSingleResolver(resolver, outputDir, tsconfig, triggerContext, cache, inlineSourcemap, bundleLogLevel));
5277
+ const results = await withBundleConcurrency(resolvers, (resolver) => bundleSingleResolver(namespace, resolver, outputDir, tsconfig, triggerContext, cache, inlineSourcemap, bundleLogLevel));
5230
5278
  for (const [name, code] of results) bundledCode.set(name, code);
5231
5279
  logger.log(`${styles.success("Bundled")} ${styles.info(`"${namespace}"`)}`);
5232
5280
  return bundledCode;
5233
5281
  }
5234
- async function bundleSingleResolver(resolver, outputDir, tsconfig, triggerContext, cache, inlineSourcemap, bundleLogLevel = "DEBUG") {
5282
+ async function bundleSingleResolver(namespace, resolver, outputDir, tsconfig, triggerContext, cache, inlineSourcemap, bundleLogLevel = "DEBUG") {
5235
5283
  const serializedTriggerContext = serializeTriggerContext(triggerContext);
5236
5284
  const contextHash = computeBundlerContextHash({
5237
5285
  sourceFile: resolver.sourceFile,
@@ -5243,6 +5291,7 @@ async function bundleSingleResolver(resolver, outputDir, tsconfig, triggerContex
5243
5291
  const code = await withCache({
5244
5292
  cache,
5245
5293
  kind: "resolver",
5294
+ namespace,
5246
5295
  name: resolver.name,
5247
5296
  sourceFile: resolver.sourceFile,
5248
5297
  contextHash,
@@ -5337,9 +5386,26 @@ function createResolverService(namespace, config) {
5337
5386
  const resolverFiles = loadFilesWithIgnores(config);
5338
5387
  logger.log(`Found ${styles.highlight(resolverFiles.length.toString())} resolver files for service ${styles.highlight(`"${namespace}"`)}`);
5339
5388
  await Promise.all(resolverFiles.map((resolverFile) => loadResolverForFile(resolverFile)));
5389
+ assertUniqueResolverNames(resolvers, namespace);
5340
5390
  }
5341
5391
  };
5342
5392
  }
5393
+ /**
5394
+ * Assert that every loaded resolver in a namespace has a unique name.
5395
+ * Resolvers are stored by source file, so two files declaring the same
5396
+ * `name` would otherwise silently share a single bundle cache entry.
5397
+ * @param resolvers - Loaded resolvers keyed by source file
5398
+ * @param namespace - The namespace the resolvers belong to
5399
+ */
5400
+ function assertUniqueResolverNames(resolvers, namespace) {
5401
+ const seenNames = /* @__PURE__ */ new Map();
5402
+ for (const [file, resolver] of Object.entries(resolvers)) {
5403
+ const relativePath = path.relative(process.cwd(), file);
5404
+ const existing = seenNames.get(resolver.name);
5405
+ if (existing) throw new Error(`Duplicate resolver name "${resolver.name}" found in namespace "${namespace}":\n - ${existing}\n - ${relativePath}\nEach resolver must have a unique name within a namespace.`);
5406
+ seenNames.set(resolver.name, relativePath);
5407
+ }
5408
+ }
5343
5409
 
5344
5410
  //#endregion
5345
5411
  //#region src/cli/services/workflow/source-transformer.ts
@@ -5444,11 +5510,17 @@ function transformWorkflowSource(source, targetJobName, targetJobExportName, oth
5444
5510
  end: endPos,
5445
5511
  text: ""
5446
5512
  });
5447
- } else if (!job.statementRange) replacements.push({
5448
- start: job.bodyValueRange.start,
5449
- end: job.bodyValueRange.end,
5450
- text: "() => {}"
5451
- });
5513
+ } else if (!job.statementRange) {
5514
+ removedRanges.push({
5515
+ start: job.bodyValueRange.start,
5516
+ end: job.bodyValueRange.end
5517
+ });
5518
+ replacements.push({
5519
+ start: job.bodyValueRange.start,
5520
+ end: job.bodyValueRange.end,
5521
+ text: "() => {}"
5522
+ });
5523
+ }
5452
5524
  }
5453
5525
  if (otherJobExportNames) for (const exportName of otherJobExportNames) {
5454
5526
  if (exportName === targetJobExportName) continue;
@@ -5900,6 +5972,12 @@ function resolveInlineSourcemap(configValue) {
5900
5972
  return true;
5901
5973
  }
5902
5974
 
5975
+ //#endregion
5976
+ //#region src/cli/shared/resolver-bundle-key.ts
5977
+ function resolverBundleKey(namespace, resolverName) {
5978
+ return `${namespace}:${resolverName}`;
5979
+ }
5980
+
5903
5981
  //#endregion
5904
5982
  //#region src/parser/service/aigateway/schema.ts
5905
5983
  const NAME_PATTERN = /^[a-z0-9][a-z0-9-]{1,28}[a-z0-9]$/;
@@ -6387,7 +6465,7 @@ async function loadApplication(params) {
6387
6465
  };
6388
6466
  for (const pipeline of resolverResult.resolverServices) {
6389
6467
  const resolverBundles = await bundleResolvers(pipeline.namespace, pipeline.config, triggerContext, bundleCache, inlineSourcemap, bundleLogLevel);
6390
- for (const [name, code] of resolverBundles) bundledScripts.resolvers.set(name, code);
6468
+ for (const [name, code] of resolverBundles) bundledScripts.resolvers.set(resolverBundleKey(pipeline.namespace, name), code);
6391
6469
  }
6392
6470
  if (executorService) bundledScripts.executors = await bundleExecutors({
6393
6471
  config: executorService.config,
@@ -6454,5 +6532,5 @@ async function loadApplication(params) {
6454
6532
  }
6455
6533
 
6456
6534
  //#endregion
6457
- export { initOperatorClient as $, loadAccessToken as A, saveUserTokens as B, hashContent as C, fetchLatestToken as D, deleteUserTokens as E, loadStoredUserTokens as F, fetchMachineUserToken as G, closeConnectionPool as H, loadWorkspaceId as I, fetchUserInfo as J, fetchPaged as K, platformConfigFromProfile as L, loadConsoleBaseUrl as M, loadMachineUserName as N, hasAnyUserTokenEntry as O, loadPlatformClientConfig as P, initOAuth2Client as Q, readPlatformConfig as R, getDistDir as S, loadConfig as T, defaultPlatformBaseUrl as U, writePlatformConfig as V, fetchAll as W, getOAuth2ClientId as X, getConsoleBaseUrl as Y, getPlatformBaseUrl as Z, createLogLevelTreeshakeOptions as _, WorkflowJobSchema as a, hasGenerationHooks as b, INVOKER_EXPR as c, assertUniqueLocalTailorDBTypeNames as d, isDefaultPlatform as et, assertUniqueTailorDBTypeNamesWithExternal as f, composeFunctionTreeshakeOptions as g, platformBundleDefinePlugin as h, resolveInlineSourcemap as i, loadConfigPath as j, hasUserTokenEntry as k, buildExecutorArgsExpr as l, stringifyFunction as m, generatePluginFilesIfNeeded as n, byName as nt, ResolverSchema as o, TailorDBTypeSchema as p, fetchPlatformMachineUserToken as q, loadApplication as r, HTTP_METHODS as s, defineApplication as t, resolveStaticWebsiteUrls as tt, buildResolverOperationHookExpr as u, resolveBundleLogLevel as v, hashFile as w, createBundleCache as x, getPluginGenerationDependencies as y, resolveUserTokenKey as z };
6458
- //# sourceMappingURL=application-Bb9NNp5m.mjs.map
6535
+ export { initOAuth2Client as $, hasUserTokenEntry as A, resolveUserTokenKey as B, getDistDir as C, deleteUserTokens as D, loadConfig as E, loadPlatformClientConfig as F, fetchAll as G, writePlatformConfig as H, loadStoredUserTokens as I, fetchPlatformMachineUserToken as J, fetchMachineUserToken as K, loadWorkspaceId as L, loadConfigPath as M, loadConsoleBaseUrl as N, fetchLatestToken as O, loadMachineUserName as P, getPlatformBaseUrl as Q, platformConfigFromProfile as R, createBundleCache as S, hashFile as T, closeConnectionPool as U, saveUserTokens as V, defaultPlatformBaseUrl as W, getConsoleBaseUrl as X, fetchUserInfo as Y, getOAuth2ClientId as Z, composeFunctionTreeshakeOptions as _, resolveInlineSourcemap as a, getPluginGenerationDependencies as b, HTTP_METHODS as c, buildResolverOperationHookExpr as d, initOperatorClient as et, assertUniqueLocalTailorDBTypeNames as f, platformBundleDefinePlugin as g, stringifyFunction as h, resolverBundleKey as i, loadAccessToken as j, hasAnyUserTokenEntry as k, INVOKER_EXPR as l, TailorDBTypeSchema as m, generatePluginFilesIfNeeded as n, resolveStaticWebsiteUrls as nt, WorkflowJobSchema as o, assertUniqueTailorDBTypeNamesWithExternal as p, fetchPaged as q, loadApplication as r, byName as rt, ResolverSchema as s, defineApplication as t, isDefaultPlatform as tt, buildExecutorArgsExpr as u, createLogLevelTreeshakeOptions as v, hashContent as w, hasGenerationHooks as x, resolveBundleLogLevel as y, readPlatformConfig as z };
6536
+ //# sourceMappingURL=application-DwmoI6ZQ.mjs.map