@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.
- package/CHANGELOG.md +43 -0
- package/dist/application-BndtMTFY.mjs +3 -0
- package/dist/{application-Bb9NNp5m.mjs → application-DwmoI6ZQ.mjs} +231 -153
- package/dist/application-DwmoI6ZQ.mjs.map +1 -0
- package/dist/cli/commands/deploy/apply-phases.d.mts +1 -0
- package/dist/cli/commands/executor/trigger.d.mts +1 -1
- package/dist/cli/index.mjs +102 -13
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +2 -2
- package/dist/cli/lib.mjs +2 -2
- package/dist/cli/shared/client.d.mts +1 -1
- package/dist/completion/zsh-worker.zsh +28 -3
- package/dist/{repl-editor-BmQOyZJd.mjs → repl-editor-BCozyiNq.mjs} +3 -2
- package/dist/{repl-editor-BmQOyZJd.mjs.map → repl-editor-BCozyiNq.mjs.map} +1 -1
- package/dist/{runtime-B8O6JFS2.mjs → runtime-Zkg3SUwi.mjs} +1974 -1217
- package/dist/runtime-Zkg3SUwi.mjs.map +1 -0
- package/dist/{service-DiEtAsvc.mjs → service-BCRJ-3NV.mjs} +18 -1
- package/dist/{service-DiEtAsvc.mjs.map → service-BCRJ-3NV.mjs.map} +1 -1
- package/dist/service-CPMlIg3X.mjs +3 -0
- package/dist/tailor-proto/src/tailor/v1/aigateway_pb.d.mts +2 -2
- package/dist/tailor-proto/src/tailor/v1/aigateway_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/application_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/auth_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/auth_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/events_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/events_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/executor_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/function_registry_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/http_adapter_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/idp_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/idp_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/metadata_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/metadata_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/meter_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/pipeline_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/pipeline_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/secret_manager_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/secret_manager_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +2 -2
- package/dist/tailor-proto/src/tailor/v1/stateflow_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/stateflow_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/staticwebsite_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/staticwebsite_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/tailordb_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/tailordb_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/telemetryrouter_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +1 -1
- package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +2 -2
- package/dist/tailor-proto/src/tailor/v1/workspace_resource_pb.d.mts +1 -1
- package/dist/vitest/index.mjs +2 -1
- package/dist/vitest/index.mjs.map +1 -1
- package/docs/cli/application.md +21 -11
- package/docs/cli/setup.md +25 -0
- package/docs/cli-reference.md +1 -0
- package/docs/services/tailordb.md +23 -0
- package/package.json +8 -8
- package/dist/application-BXdCl6bp.mjs +0 -3
- package/dist/application-Bb9NNp5m.mjs.map +0 -1
- package/dist/runtime-B8O6JFS2.mjs.map +0 -1
- 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-
|
|
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
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
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 = "
|
|
2720
|
+
const NORMALIZER_IDENTIFIER = "__tailor_normalizeTriggerOptions";
|
|
2702
2721
|
/**
|
|
2703
2722
|
* Build the source text of the injected normalizer helper.
|
|
2704
2723
|
*
|
|
2705
|
-
*
|
|
2706
|
-
* `{ namespace, machineUserName }
|
|
2707
|
-
* The auth namespace is baked in at
|
|
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} = (
|
|
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
|
-
|
|
2869
|
-
|
|
2870
|
-
const
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
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
|
|
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"
|
|
2934
|
+
for (const call of triggerCalls) if (call.kind === "workflow") {
|
|
2953
2935
|
const workflowName = localWorkflowNameMap.get(call.identifierName);
|
|
2954
2936
|
if (workflowName) {
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
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
|
|
2961
|
-
const transformedCall = `tailor.workflow.triggerWorkflow("${workflowName}", ${call.argsText || "undefined"}
|
|
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
|
|
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 &&
|
|
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[
|
|
3557
|
-
name:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(`${
|
|
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
|
|
4376
|
-
|
|
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)
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
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 {
|
|
6458
|
-
//# sourceMappingURL=application-
|
|
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
|