@tailor-platform/sdk 0.13.0 → 0.14.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.
@@ -1,4 +1,4 @@
1
- import { WORKFLOW_JOB_BRAND, getDistDir, tailorUserMap } from "./job-vYIg6hFf.mjs";
1
+ import { WORKFLOW_JOB_BRAND, getDistDir, tailorUserMap } from "./job-inTmXxpa.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { defineCommand } from "citty";
4
4
  import * as path from "node:path";
@@ -115,16 +115,180 @@ function loadFilesWithIgnores(config) {
115
115
  return files;
116
116
  }
117
117
 
118
+ //#endregion
119
+ //#region src/parser/service/auth/schema.ts
120
+ const AuthInvokerSchema = z.object({
121
+ namespace: z.string(),
122
+ machineUserName: z.string()
123
+ });
124
+ const secretValueSchema = z.object({
125
+ vaultName: z.string(),
126
+ secretKey: z.string()
127
+ });
128
+ const samlBaseSchema = z.object({
129
+ name: z.string(),
130
+ kind: z.literal("SAML"),
131
+ spCertBase64: secretValueSchema.optional(),
132
+ spKeyBase64: secretValueSchema.optional()
133
+ });
134
+ const OIDCSchema = z.object({
135
+ name: z.string(),
136
+ kind: z.literal("OIDC"),
137
+ clientID: z.string(),
138
+ clientSecret: secretValueSchema,
139
+ providerURL: z.string(),
140
+ issuerURL: z.string().optional(),
141
+ usernameClaim: z.string().optional()
142
+ });
143
+ const SAMLSchema = samlBaseSchema.extend({
144
+ metadataURL: z.string().optional(),
145
+ rawMetadata: z.string().optional()
146
+ }).refine((value) => {
147
+ const hasMetadata = value.metadataURL !== void 0;
148
+ const hasRaw = value.rawMetadata !== void 0;
149
+ return hasMetadata !== hasRaw;
150
+ }, "Provide either metadataURL or rawMetadata");
151
+ const IDTokenSchema = z.object({
152
+ name: z.string(),
153
+ kind: z.literal("IDToken"),
154
+ providerURL: z.string(),
155
+ issuerURL: z.string().optional(),
156
+ clientID: z.string(),
157
+ usernameClaim: z.string().optional()
158
+ });
159
+ const BuiltinIdPSchema = z.object({
160
+ name: z.string(),
161
+ kind: z.literal("BuiltInIdP"),
162
+ namespace: z.string(),
163
+ clientName: z.string()
164
+ });
165
+ const IdProviderSchema = z.discriminatedUnion("kind", [
166
+ OIDCSchema,
167
+ SAMLSchema,
168
+ IDTokenSchema,
169
+ BuiltinIdPSchema
170
+ ]);
171
+ const OAuth2ClientGrantTypeSchema = z.union([z.literal("authorization_code"), z.literal("refresh_token")]);
172
+ const OAuth2ClientSchema = z.object({
173
+ description: z.string().optional(),
174
+ grantTypes: z.array(OAuth2ClientGrantTypeSchema).default(["authorization_code", "refresh_token"]),
175
+ redirectURIs: z.array(z.union([
176
+ z.templateLiteral(["https://", z.string()]),
177
+ z.templateLiteral(["http://", z.string()]),
178
+ z.templateLiteral([z.string(), ":url"]),
179
+ z.templateLiteral([
180
+ z.string(),
181
+ ":url/",
182
+ z.string()
183
+ ])
184
+ ])),
185
+ clientType: z.union([
186
+ z.literal("confidential"),
187
+ z.literal("public"),
188
+ z.literal("browser")
189
+ ]).optional()
190
+ });
191
+ const SCIMAuthorizationSchema = z.object({
192
+ type: z.union([z.literal("oauth2"), z.literal("bearer")]),
193
+ bearerSecret: secretValueSchema.optional()
194
+ });
195
+ const SCIMAttributeTypeSchema = z.union([
196
+ z.literal("string"),
197
+ z.literal("number"),
198
+ z.literal("boolean"),
199
+ z.literal("datetime"),
200
+ z.literal("complex")
201
+ ]);
202
+ const SCIMAttributeSchema = z.object({
203
+ type: SCIMAttributeTypeSchema,
204
+ name: z.string(),
205
+ description: z.string().optional(),
206
+ mutability: z.union([
207
+ z.literal("readOnly"),
208
+ z.literal("readWrite"),
209
+ z.literal("writeOnly")
210
+ ]).optional(),
211
+ required: z.boolean().optional(),
212
+ multiValued: z.boolean().optional(),
213
+ uniqueness: z.union([
214
+ z.literal("none"),
215
+ z.literal("server"),
216
+ z.literal("global")
217
+ ]).optional(),
218
+ canonicalValues: z.array(z.string()).nullable().optional(),
219
+ get subAttributes() {
220
+ return z.array(SCIMAttributeSchema).nullable().optional();
221
+ }
222
+ });
223
+ const SCIMSchemaSchema = z.object({
224
+ name: z.string(),
225
+ attributes: z.array(SCIMAttributeSchema)
226
+ });
227
+ const SCIMAttributeMappingSchema = z.object({
228
+ tailorDBField: z.string(),
229
+ scimPath: z.string()
230
+ });
231
+ const SCIMResourceSchema = z.object({
232
+ name: z.string(),
233
+ tailorDBNamespace: z.string(),
234
+ tailorDBType: z.string(),
235
+ coreSchema: SCIMSchemaSchema,
236
+ attributeMapping: z.array(SCIMAttributeMappingSchema)
237
+ });
238
+ const SCIMSchema = z.object({
239
+ machineUserName: z.string(),
240
+ authorization: SCIMAuthorizationSchema,
241
+ resources: z.array(SCIMResourceSchema)
242
+ });
243
+ const TenantProviderSchema = z.object({
244
+ namespace: z.string(),
245
+ type: z.string(),
246
+ signatureField: z.string()
247
+ });
248
+ const UserProfileSchema = z.object({
249
+ type: z.object({
250
+ name: z.string(),
251
+ fields: z.any(),
252
+ metadata: z.any(),
253
+ hooks: z.any(),
254
+ validate: z.any(),
255
+ features: z.any(),
256
+ indexes: z.any(),
257
+ files: z.any(),
258
+ permission: z.any(),
259
+ gqlPermission: z.any(),
260
+ _output: z.any()
261
+ }),
262
+ usernameField: z.string(),
263
+ attributes: z.record(z.string(), z.literal(true)).optional(),
264
+ attributeList: z.array(z.string()).optional()
265
+ });
266
+ const ValueOperandSchema = z.union([
267
+ z.string(),
268
+ z.boolean(),
269
+ z.array(z.string()),
270
+ z.array(z.boolean())
271
+ ]);
272
+ const MachineUserSchema = z.object({
273
+ attributes: z.record(z.string(), ValueOperandSchema).optional(),
274
+ attributeList: z.array(z.uuid()).optional()
275
+ });
276
+ const AuthConfigSchema = z.object({
277
+ name: z.string(),
278
+ userProfile: UserProfileSchema.optional(),
279
+ machineUsers: z.record(z.string(), MachineUserSchema).optional(),
280
+ oauth2Clients: z.record(z.string(), OAuth2ClientSchema).optional(),
281
+ idProvider: IdProviderSchema.optional(),
282
+ scim: SCIMSchema.optional(),
283
+ tenantProvider: TenantProviderSchema.optional()
284
+ }).brand("AuthConfig");
285
+
118
286
  //#endregion
119
287
  //#region src/parser/service/common.ts
120
288
  const functionSchema = z.custom((val) => typeof val === "function");
121
289
 
122
290
  //#endregion
123
291
  //#region src/parser/service/executor/schema.ts
124
- const InvokerSchema = z.object({
125
- authName: z.string(),
126
- machineUser: z.string()
127
- });
128
292
  const RecordTriggerSchema = z.object({
129
293
  kind: z.enum([
130
294
  "recordCreated",
@@ -154,14 +318,14 @@ const TriggerSchema = z.discriminatedUnion("kind", [
154
318
  const FunctionOperationSchema = z.object({
155
319
  kind: z.enum(["function", "jobFunction"]),
156
320
  body: functionSchema,
157
- invoker: InvokerSchema.optional()
321
+ authInvoker: AuthInvokerSchema.optional()
158
322
  });
159
323
  const GqlOperationSchema = z.object({
160
324
  kind: z.literal("graphql"),
161
325
  appName: z.string().optional(),
162
326
  query: z.string(),
163
327
  variables: functionSchema.optional(),
164
- invoker: InvokerSchema.optional()
328
+ authInvoker: AuthInvokerSchema.optional()
165
329
  });
166
330
  const WebhookOperationSchema = z.object({
167
331
  kind: z.literal("webhook"),
@@ -691,191 +855,7 @@ function isWorkflowJob(value) {
691
855
  }
692
856
 
693
857
  //#endregion
694
- //#region src/cli/bundler/executor/loader.ts
695
- async function loadExecutor(executorFilePath) {
696
- const executor = (await import(`${pathToFileURL(executorFilePath).href}?t=${Date.now()}`)).default;
697
- const parseResult = ExecutorSchema.safeParse(executor);
698
- if (!parseResult.success) return null;
699
- return parseResult.data;
700
- }
701
-
702
- //#endregion
703
- //#region src/cli/bundler/executor/executor-bundler.ts
704
- /**
705
- * Bundle executors from the specified configuration
706
- *
707
- * This function:
708
- * 1. Creates entry file that extracts operation.body
709
- * 2. Bundles in a single step with tree-shaking
710
- */
711
- async function bundleExecutors(config) {
712
- const files = loadFilesWithIgnores(config);
713
- if (files.length === 0) throw new Error(`No files found matching pattern: ${config.files?.join(", ")}`);
714
- console.log("");
715
- console.log("Bundling", styleText("cyanBright", files.length.toString()), "files for", styleText("cyan", "\"executor\""));
716
- const executors = [];
717
- for (const file of files) {
718
- const executor = await loadExecutor(file);
719
- if (!executor) {
720
- console.log(styleText("dim", ` Skipping: ${file} (could not be loaded)`));
721
- continue;
722
- }
723
- if (!["function", "jobFunction"].includes(executor.operation.kind)) {
724
- console.log(styleText("dim", ` Skipping: ${executor.name} (not a function executor)`));
725
- continue;
726
- }
727
- executors.push({
728
- name: executor.name,
729
- sourceFile: file
730
- });
731
- }
732
- if (executors.length === 0) {
733
- console.log(styleText("dim", " No function executors to bundle"));
734
- return;
735
- }
736
- const outputDir = path.resolve(getDistDir(), "executors");
737
- fs.mkdirSync(outputDir, { recursive: true });
738
- let tsconfig;
739
- try {
740
- tsconfig = await resolveTSConfig();
741
- } catch {
742
- tsconfig = void 0;
743
- }
744
- await Promise.all(executors.map((executor) => bundleSingleExecutor(executor, outputDir, tsconfig)));
745
- console.log(styleText("green", "Bundled"), styleText("cyan", "\"executor\""));
746
- }
747
- async function bundleSingleExecutor(executor, outputDir, tsconfig) {
748
- const entryPath = path.join(outputDir, `${executor.name}.entry.js`);
749
- const absoluteSourcePath = path.resolve(executor.sourceFile).replace(/\\/g, "/");
750
- const entryContent = ml`
751
- import _internalExecutor from "${absoluteSourcePath}";
752
-
753
- const __executor_function = _internalExecutor.operation.body;
754
-
755
- globalThis.main = __executor_function;
756
- `;
757
- fs.writeFileSync(entryPath, entryContent);
758
- const outputPath = path.join(outputDir, `${executor.name}.js`);
759
- await rolldown.build(rolldown.defineConfig({
760
- input: entryPath,
761
- output: {
762
- file: outputPath,
763
- format: "esm",
764
- sourcemap: true,
765
- minify: true,
766
- inlineDynamicImports: true
767
- },
768
- tsconfig,
769
- treeshake: {
770
- moduleSideEffects: false,
771
- annotations: true,
772
- unknownGlobalSideEffects: false
773
- },
774
- logLevel: "silent"
775
- }));
776
- }
777
-
778
- //#endregion
779
- //#region src/cli/bundler/resolver/loader.ts
780
- async function loadResolver(resolverFilePath) {
781
- const resolver = (await import(`${pathToFileURL(resolverFilePath).href}?t=${Date.now()}`)).default;
782
- const parseResult = ResolverSchema.safeParse(resolver);
783
- if (!parseResult.success) return null;
784
- return parseResult.data;
785
- }
786
-
787
- //#endregion
788
- //#region src/cli/bundler/resolver/resolver-bundler.ts
789
- /**
790
- * Bundle resolvers for the specified namespace
791
- *
792
- * This function:
793
- * 1. Uses a transform plugin to add validation wrapper during bundling
794
- * 2. Creates entry file
795
- * 3. Bundles in a single step with tree-shaking
796
- */
797
- async function bundleResolvers(namespace, config) {
798
- const files = loadFilesWithIgnores(config);
799
- if (files.length === 0) throw new Error(`No files found matching pattern: ${config.files?.join(", ")}`);
800
- console.log("");
801
- console.log("Bundling", styleText("cyanBright", files.length.toString()), "files for", styleText("cyan", `"${namespace}"`));
802
- const resolvers = [];
803
- for (const file of files) {
804
- const resolver = await loadResolver(file);
805
- if (!resolver) {
806
- console.log(styleText("dim", ` Skipping: ${file} (could not be loaded)`));
807
- continue;
808
- }
809
- resolvers.push({
810
- name: resolver.name,
811
- sourceFile: file
812
- });
813
- }
814
- const outputDir = path.resolve(getDistDir(), "resolvers");
815
- fs.mkdirSync(outputDir, { recursive: true });
816
- let tsconfig;
817
- try {
818
- tsconfig = await resolveTSConfig();
819
- } catch {
820
- tsconfig = void 0;
821
- }
822
- await Promise.all(resolvers.map((resolver) => bundleSingleResolver(resolver, outputDir, tsconfig)));
823
- console.log(styleText("green", "Bundled"), styleText("cyan", `"${namespace}"`));
824
- }
825
- async function bundleSingleResolver(resolver, outputDir, tsconfig) {
826
- const entryPath = path.join(outputDir, `${resolver.name}.entry.js`);
827
- const absoluteSourcePath = path.resolve(resolver.sourceFile).replace(/\\/g, "/");
828
- const entryContent = ml`
829
- import _internalResolver from "${absoluteSourcePath}";
830
- import { t } from "@tailor-platform/sdk";
831
-
832
- const $tailor_resolver_body = async (context) => {
833
- if (_internalResolver.input) {
834
- const result = t.object(_internalResolver.input).parse({
835
- value: context.input,
836
- data: context.input,
837
- user: context.user,
838
- });
839
-
840
- if (result.issues) {
841
- const errorMessages = result.issues
842
- .map(issue => {
843
- const path = issue.path ? issue.path.join('.') : '';
844
- return path ? \` \${path}: \${issue.message}\` : issue.message;
845
- })
846
- .join('\\n');
847
- throw new Error(\`Failed to input validation:\\n\${errorMessages}\`);
848
- }
849
- }
850
-
851
- return _internalResolver.body(context);
852
- };
853
-
854
- globalThis.main = $tailor_resolver_body;
855
- `;
856
- fs.writeFileSync(entryPath, entryContent);
857
- const outputPath = path.join(outputDir, `${resolver.name}.js`);
858
- await rolldown.build(rolldown.defineConfig({
859
- input: entryPath,
860
- output: {
861
- file: outputPath,
862
- format: "esm",
863
- sourcemap: true,
864
- minify: true,
865
- inlineDynamicImports: true
866
- },
867
- tsconfig,
868
- treeshake: {
869
- moduleSideEffects: false,
870
- annotations: true,
871
- unknownGlobalSideEffects: false
872
- },
873
- logLevel: "silent"
874
- }));
875
- }
876
-
877
- //#endregion
878
- //#region src/cli/bundler/workflow/ast-transformer.ts
858
+ //#region src/cli/bundler/workflow/ast-utils.ts
879
859
  /**
880
860
  * Check if a module source is from \@tailor-platform/sdk (including subpaths)
881
861
  */
@@ -908,81 +888,7 @@ function unwrapAwait(node) {
908
888
  return node;
909
889
  }
910
890
  /**
911
- * Collect all import bindings for createWorkflowJob from \@tailor-platform/sdk
912
- * Returns a Set of local names that refer to createWorkflowJob
913
- */
914
- function collectCreateWorkflowJobBindings(program) {
915
- const bindings = /* @__PURE__ */ new Set();
916
- function walk(node) {
917
- if (!node || typeof node !== "object") return;
918
- const nodeType = node.type;
919
- if (nodeType === "ImportDeclaration") {
920
- const importDecl = node;
921
- const source = importDecl.source?.value;
922
- if (typeof source === "string" && isTailorSdkSource(source)) {
923
- for (const specifier of importDecl.specifiers || []) if (specifier.type === "ImportSpecifier") {
924
- const importSpec = specifier;
925
- const imported = importSpec.imported.type === "Identifier" ? importSpec.imported.name : importSpec.imported.value;
926
- if (imported === "createWorkflowJob") bindings.add(importSpec.local?.name || imported);
927
- } else if (specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
928
- const spec = specifier;
929
- bindings.add(`__namespace__:${spec.local?.name}`);
930
- }
931
- }
932
- }
933
- if (nodeType === "VariableDeclaration") {
934
- const varDecl = node;
935
- for (const decl of varDecl.declarations || []) {
936
- const init = unwrapAwait(decl.init);
937
- const source = getImportSource(init);
938
- if (source && isTailorSdkSource(source)) {
939
- const id = decl.id;
940
- if (id?.type === "Identifier") bindings.add(`__namespace__:${id.name}`);
941
- else if (id?.type === "ObjectPattern") {
942
- const objPattern = id;
943
- for (const prop of objPattern.properties || []) if (prop.type === "Property") {
944
- const bindingProp = prop;
945
- const keyName = bindingProp.key.type === "Identifier" ? bindingProp.key.name : bindingProp.key.value;
946
- if (keyName === "createWorkflowJob") {
947
- const localName = bindingProp.value.type === "Identifier" ? bindingProp.value.name : keyName;
948
- bindings.add(localName ?? "");
949
- }
950
- }
951
- }
952
- }
953
- }
954
- }
955
- for (const key of Object.keys(node)) {
956
- const child = node[key];
957
- if (Array.isArray(child)) child.forEach((c) => walk(c));
958
- else if (child && typeof child === "object") walk(child);
959
- }
960
- }
961
- walk(program);
962
- return bindings;
963
- }
964
- /**
965
- * Check if a CallExpression is a createWorkflowJob call
966
- */
967
- function isCreateWorkflowJobCall(node, bindings) {
968
- if (node.type !== "CallExpression") return false;
969
- const callee = node.callee;
970
- if (callee.type === "Identifier") {
971
- const identifier = callee;
972
- return bindings.has(identifier.name);
973
- }
974
- if (callee.type === "MemberExpression") {
975
- const memberExpr = callee;
976
- if (!memberExpr.computed) {
977
- const object = memberExpr.object;
978
- const property = memberExpr.property;
979
- if (object.type === "Identifier" && bindings.has(`__namespace__:${object.name}`) && property.name === "createWorkflowJob") return true;
980
- }
981
- }
982
- return false;
983
- }
984
- /**
985
- * Check if a node is a string literal
891
+ * Check if a node is a string literal
986
892
  */
987
893
  function isStringLiteral(node) {
988
894
  return node?.type === "Literal" && typeof node.value === "string";
@@ -1009,14 +915,124 @@ function findProperty(properties, name) {
1009
915
  return null;
1010
916
  }
1011
917
  /**
918
+ * Apply string replacements to source code
919
+ * Replacements are applied from end to start to maintain positions
920
+ */
921
+ function applyReplacements(source, replacements) {
922
+ const sorted = [...replacements].sort((a, b) => b.start - a.start);
923
+ let result = source;
924
+ for (const r of sorted) result = result.slice(0, r.start) + r.text + result.slice(r.end);
925
+ return result;
926
+ }
927
+ /**
928
+ * Find the end of a statement including any trailing newline
929
+ */
930
+ function findStatementEnd(source, position) {
931
+ let i = position;
932
+ while (i < source.length && (source[i] === ";" || source[i] === " " || source[i] === " ")) i++;
933
+ if (i < source.length && source[i] === "\n") i++;
934
+ return i;
935
+ }
936
+ /**
937
+ * Resolve a relative path from a base directory
938
+ * Simple implementation that handles ./ and ../ prefixes
939
+ */
940
+ function resolvePath(baseDir, relativePath) {
941
+ const parts = relativePath.replace(/\\/g, "/").split("/");
942
+ const baseParts = baseDir.replace(/\\/g, "/").split("/");
943
+ for (const part of parts) if (part === ".") {} else if (part === "..") baseParts.pop();
944
+ else baseParts.push(part);
945
+ return baseParts.join("/");
946
+ }
947
+
948
+ //#endregion
949
+ //#region src/cli/bundler/workflow/sdk-binding-collector.ts
950
+ /**
951
+ * Collect all import bindings for a specific function from \@tailor-platform/sdk
952
+ * Returns a Set of local names that refer to the function
953
+ */
954
+ function collectSdkBindings(program, functionName) {
955
+ const bindings = /* @__PURE__ */ new Set();
956
+ function walk(node) {
957
+ if (!node || typeof node !== "object") return;
958
+ const nodeType = node.type;
959
+ if (nodeType === "ImportDeclaration") {
960
+ const importDecl = node;
961
+ const source = importDecl.source?.value;
962
+ if (typeof source === "string" && isTailorSdkSource(source)) {
963
+ for (const specifier of importDecl.specifiers || []) if (specifier.type === "ImportSpecifier") {
964
+ const importSpec = specifier;
965
+ const imported = importSpec.imported.type === "Identifier" ? importSpec.imported.name : importSpec.imported.value;
966
+ if (imported === functionName) bindings.add(importSpec.local?.name || imported);
967
+ } else if (specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
968
+ const spec = specifier;
969
+ bindings.add(`__namespace__:${spec.local?.name}`);
970
+ }
971
+ }
972
+ }
973
+ if (nodeType === "VariableDeclaration") {
974
+ const varDecl = node;
975
+ for (const decl of varDecl.declarations || []) {
976
+ const init = unwrapAwait(decl.init);
977
+ const source = getImportSource(init);
978
+ if (source && isTailorSdkSource(source)) {
979
+ const id = decl.id;
980
+ if (id?.type === "Identifier") bindings.add(`__namespace__:${id.name}`);
981
+ else if (id?.type === "ObjectPattern") {
982
+ const objPattern = id;
983
+ for (const prop of objPattern.properties || []) if (prop.type === "Property") {
984
+ const bindingProp = prop;
985
+ const keyName = bindingProp.key.type === "Identifier" ? bindingProp.key.name : bindingProp.key.value;
986
+ if (keyName === functionName) {
987
+ const localName = bindingProp.value.type === "Identifier" ? bindingProp.value.name : keyName;
988
+ bindings.add(localName ?? "");
989
+ }
990
+ }
991
+ }
992
+ }
993
+ }
994
+ }
995
+ for (const key of Object.keys(node)) {
996
+ const child = node[key];
997
+ if (Array.isArray(child)) child.forEach((c) => walk(c));
998
+ else if (child && typeof child === "object") walk(child);
999
+ }
1000
+ }
1001
+ walk(program);
1002
+ return bindings;
1003
+ }
1004
+ /**
1005
+ * Check if a CallExpression is a call to a specific SDK function
1006
+ */
1007
+ function isSdkFunctionCall(node, bindings, functionName) {
1008
+ if (node.type !== "CallExpression") return false;
1009
+ const callee = node.callee;
1010
+ if (callee.type === "Identifier") {
1011
+ const identifier = callee;
1012
+ return bindings.has(identifier.name);
1013
+ }
1014
+ if (callee.type === "MemberExpression") {
1015
+ const memberExpr = callee;
1016
+ if (!memberExpr.computed) {
1017
+ const object = memberExpr.object;
1018
+ const property = memberExpr.property;
1019
+ if (object.type === "Identifier" && bindings.has(`__namespace__:${object.name}`) && property.name === functionName) return true;
1020
+ }
1021
+ }
1022
+ return false;
1023
+ }
1024
+
1025
+ //#endregion
1026
+ //#region src/cli/bundler/workflow/job-detector.ts
1027
+ /**
1012
1028
  * Find all workflow jobs by detecting createWorkflowJob calls from \@tailor-platform/sdk
1013
1029
  */
1014
1030
  function findAllJobs(program, _sourceText) {
1015
1031
  const jobs = [];
1016
- const bindings = collectCreateWorkflowJobBindings(program);
1032
+ const bindings = collectSdkBindings(program, "createWorkflowJob");
1017
1033
  function walk(node, parents = []) {
1018
1034
  if (!node || typeof node !== "object") return;
1019
- if (isCreateWorkflowJobCall(node, bindings)) {
1035
+ if (isSdkFunctionCall(node, bindings, "createWorkflowJob")) {
1020
1036
  const args = node.arguments;
1021
1037
  if (args?.length >= 1 && args[0]?.type === "ObjectExpression") {
1022
1038
  const configObj = args[0];
@@ -1063,23 +1079,12 @@ function findAllJobs(program, _sourceText) {
1063
1079
  return jobs;
1064
1080
  }
1065
1081
  /**
1066
- * Apply string replacements to source code
1067
- * Replacements are applied from end to start to maintain positions
1068
- */
1069
- function applyReplacements(source, replacements) {
1070
- const sorted = [...replacements].sort((a, b) => b.start - a.start);
1071
- let result = source;
1072
- for (const r of sorted) result = result.slice(0, r.start) + r.text + result.slice(r.end);
1073
- return result;
1074
- }
1075
- /**
1076
- * Find the end of a statement including any trailing newline
1082
+ * Build a map from export name to job name from detected jobs
1077
1083
  */
1078
- function findStatementEnd(source, position) {
1079
- let i = position;
1080
- while (i < source.length && (source[i] === ";" || source[i] === " " || source[i] === " ")) i++;
1081
- if (i < source.length && source[i] === "\n") i++;
1082
- return i;
1084
+ function buildJobNameMap(jobs) {
1085
+ const map = /* @__PURE__ */ new Map();
1086
+ for (const job of jobs) if (job.exportName) map.set(job.exportName, job.name);
1087
+ return map;
1083
1088
  }
1084
1089
  /**
1085
1090
  * Detect all .trigger() calls in the source code
@@ -1122,15 +1127,488 @@ function detectTriggerCalls(program, sourceText) {
1122
1127
  walk(program);
1123
1128
  return calls;
1124
1129
  }
1130
+
1131
+ //#endregion
1132
+ //#region src/cli/bundler/workflow/workflow-detector.ts
1125
1133
  /**
1126
- * Build a map from export name to job name from detected jobs
1134
+ * Find all workflows by detecting createWorkflow calls from \@tailor-platform/sdk
1127
1135
  */
1128
- function buildJobNameMap(jobs) {
1136
+ function findAllWorkflows(program, _sourceText) {
1137
+ const workflows = [];
1138
+ const bindings = collectSdkBindings(program, "createWorkflow");
1139
+ function walk(node, parents = []) {
1140
+ if (!node || typeof node !== "object") return;
1141
+ if (isSdkFunctionCall(node, bindings, "createWorkflow")) {
1142
+ const args = node.arguments;
1143
+ if (args?.length >= 1 && args[0]?.type === "ObjectExpression") {
1144
+ const configObj = args[0];
1145
+ const nameProp = findProperty(configObj.properties, "name");
1146
+ if (nameProp && isStringLiteral(nameProp.value)) {
1147
+ let exportName;
1148
+ let isDefaultExport = false;
1149
+ for (let i = parents.length - 1; i >= 0; i--) {
1150
+ const parent = parents[i];
1151
+ if (parent.type === "VariableDeclarator") {
1152
+ const declarator = parent;
1153
+ if (declarator.id?.type === "Identifier") {
1154
+ exportName = declarator.id.name;
1155
+ break;
1156
+ }
1157
+ }
1158
+ if (parent.type === "ExportDefaultDeclaration") isDefaultExport = true;
1159
+ }
1160
+ workflows.push({
1161
+ name: nameProp.value.value,
1162
+ exportName,
1163
+ isDefaultExport
1164
+ });
1165
+ }
1166
+ }
1167
+ }
1168
+ const newParents = [...parents, node];
1169
+ for (const key of Object.keys(node)) {
1170
+ const child = node[key];
1171
+ if (Array.isArray(child)) child.forEach((c) => walk(c, newParents));
1172
+ else if (child && typeof child === "object") walk(child, newParents);
1173
+ }
1174
+ }
1175
+ walk(program);
1176
+ return workflows;
1177
+ }
1178
+ /**
1179
+ * Build a map from export name to workflow name from detected workflows
1180
+ */
1181
+ function buildWorkflowNameMap(workflows) {
1129
1182
  const map = /* @__PURE__ */ new Map();
1130
- for (const job of jobs) if (job.exportName) map.set(job.exportName, job.name);
1183
+ for (const workflow of workflows) if (workflow.exportName) map.set(workflow.exportName, workflow.name);
1131
1184
  return map;
1132
1185
  }
1133
1186
  /**
1187
+ * Detect default imports in a source file and return a map from local name to import source
1188
+ */
1189
+ function detectDefaultImports(program) {
1190
+ const imports = /* @__PURE__ */ new Map();
1191
+ function walk(node) {
1192
+ if (!node || typeof node !== "object") return;
1193
+ if (node.type === "ImportDeclaration") {
1194
+ const importDecl = node;
1195
+ const source = importDecl.source?.value;
1196
+ if (typeof source === "string") {
1197
+ for (const specifier of importDecl.specifiers || []) if (specifier.type === "ImportDefaultSpecifier") {
1198
+ const spec = specifier;
1199
+ if (spec.local?.name) imports.set(spec.local.name, source);
1200
+ }
1201
+ }
1202
+ }
1203
+ for (const key of Object.keys(node)) {
1204
+ const child = node[key];
1205
+ if (Array.isArray(child)) child.forEach((c) => walk(c));
1206
+ else if (child && typeof child === "object") walk(child);
1207
+ }
1208
+ }
1209
+ walk(program);
1210
+ return imports;
1211
+ }
1212
+
1213
+ //#endregion
1214
+ //#region src/cli/bundler/workflow/trigger-transformer.ts
1215
+ /**
1216
+ * Extract authInvoker info from a config object expression
1217
+ * Returns the authInvoker value text and whether it's a shorthand property
1218
+ */
1219
+ function extractAuthInvokerInfo(configArg, sourceText) {
1220
+ if (!configArg || typeof configArg !== "object") return void 0;
1221
+ if (configArg.type !== "ObjectExpression") return void 0;
1222
+ const objExpr = configArg;
1223
+ for (const prop of objExpr.properties) {
1224
+ if (prop.type !== "Property") continue;
1225
+ const objProp = prop;
1226
+ if ((objProp.key.type === "Identifier" ? objProp.key.name : objProp.key.type === "Literal" ? objProp.key.value : null) === "authInvoker") {
1227
+ if (objProp.shorthand) return {
1228
+ isShorthand: true,
1229
+ valueText: "authInvoker"
1230
+ };
1231
+ return {
1232
+ isShorthand: false,
1233
+ valueText: sourceText.slice(objProp.value.start, objProp.value.end)
1234
+ };
1235
+ }
1236
+ }
1237
+ }
1238
+ /**
1239
+ * Detect .trigger() calls for known workflows and jobs
1240
+ * Only detects calls where the identifier is in workflowNames or jobNames
1241
+ *
1242
+ * @param program - The parsed AST program
1243
+ * @param sourceText - The source code text
1244
+ * @param workflowNames - Set of known workflow identifier names
1245
+ * @param jobNames - Set of known job identifier names
1246
+ */
1247
+ function detectExtendedTriggerCalls(program, sourceText, workflowNames, jobNames) {
1248
+ const calls = [];
1249
+ function walk(node) {
1250
+ if (!node || typeof node !== "object") return;
1251
+ if (node.type === "CallExpression") {
1252
+ const callExpr = node;
1253
+ const callee = callExpr.callee;
1254
+ if (callee.type === "MemberExpression") {
1255
+ const memberExpr = callee;
1256
+ if (!memberExpr.computed && memberExpr.object.type === "Identifier" && memberExpr.property.name === "trigger") {
1257
+ const identifierName = memberExpr.object.name;
1258
+ const isWorkflow = workflowNames.has(identifierName);
1259
+ const isJob = jobNames.has(identifierName);
1260
+ if (!isWorkflow && !isJob) return;
1261
+ const argCount = callExpr.arguments.length;
1262
+ let argsText = "";
1263
+ if (argCount > 0) {
1264
+ const firstArg = callExpr.arguments[0];
1265
+ if (firstArg && "start" in firstArg && "end" in firstArg) argsText = sourceText.slice(firstArg.start, firstArg.end);
1266
+ }
1267
+ if (isWorkflow && argCount >= 2) {
1268
+ const secondArg = callExpr.arguments[1];
1269
+ const authInvoker = extractAuthInvokerInfo(secondArg, sourceText);
1270
+ if (authInvoker) calls.push({
1271
+ kind: "workflow",
1272
+ identifierName,
1273
+ callRange: {
1274
+ start: callExpr.start,
1275
+ end: callExpr.end
1276
+ },
1277
+ argsText,
1278
+ authInvoker
1279
+ });
1280
+ } else if (isJob) calls.push({
1281
+ kind: "job",
1282
+ identifierName,
1283
+ callRange: {
1284
+ start: callExpr.start,
1285
+ end: callExpr.end
1286
+ },
1287
+ argsText
1288
+ });
1289
+ }
1290
+ }
1291
+ }
1292
+ for (const key of Object.keys(node)) {
1293
+ const child = node[key];
1294
+ if (Array.isArray(child)) child.forEach((c) => walk(c));
1295
+ else if (child && typeof child === "object") walk(child);
1296
+ }
1297
+ }
1298
+ walk(program);
1299
+ return calls;
1300
+ }
1301
+ /**
1302
+ * Transform trigger calls for resolver/executor/workflow functions
1303
+ * Handles both job.trigger() and workflow.trigger() calls
1304
+ *
1305
+ * @param source - The source code to transform
1306
+ * @param workflowNameMap - Map from variable name to workflow name
1307
+ * @param jobNameMap - Map from variable name to job name
1308
+ * @param workflowFileMap - Map from file path (without extension) to workflow name for default exports
1309
+ * @param currentFilePath - Path of the current file being transformed (for resolving relative imports)
1310
+ */
1311
+ function transformFunctionTriggers(source, workflowNameMap, jobNameMap, workflowFileMap, currentFilePath) {
1312
+ const { program } = parseSync("input.ts", source);
1313
+ const localWorkflowNameMap = new Map(workflowNameMap);
1314
+ if (workflowFileMap && currentFilePath) {
1315
+ const defaultImports = detectDefaultImports(program);
1316
+ const currentDir = currentFilePath.replace(/[/\\][^/\\]+$/, "");
1317
+ for (const [localName, importSource] of defaultImports) {
1318
+ if (!importSource.startsWith(".")) continue;
1319
+ const resolvedPath = resolvePath(currentDir, importSource);
1320
+ const workflowName = workflowFileMap.get(resolvedPath);
1321
+ if (workflowName) localWorkflowNameMap.set(localName, workflowName);
1322
+ }
1323
+ }
1324
+ const workflowNames = new Set(localWorkflowNameMap.keys());
1325
+ const jobNames = new Set(jobNameMap.keys());
1326
+ const triggerCalls = detectExtendedTriggerCalls(program, source, workflowNames, jobNames);
1327
+ const replacements = [];
1328
+ for (const call of triggerCalls) if (call.kind === "workflow" && call.authInvoker) {
1329
+ const workflowName = localWorkflowNameMap.get(call.identifierName);
1330
+ if (workflowName) {
1331
+ const authInvokerExpr = call.authInvoker.isShorthand ? "authInvoker" : call.authInvoker.valueText;
1332
+ const transformedCall = `tailor.workflow.triggerWorkflow("${workflowName}", ${call.argsText || "undefined"}, { authInvoker: ${authInvokerExpr} })`;
1333
+ replacements.push({
1334
+ start: call.callRange.start,
1335
+ end: call.callRange.end,
1336
+ text: transformedCall
1337
+ });
1338
+ }
1339
+ } else if (call.kind === "job") {
1340
+ const jobName = jobNameMap.get(call.identifierName);
1341
+ if (jobName) {
1342
+ const transformedCall = `tailor.workflow.triggerJobFunction("${jobName}", ${call.argsText || "undefined"})`;
1343
+ replacements.push({
1344
+ start: call.callRange.start,
1345
+ end: call.callRange.end,
1346
+ text: transformedCall
1347
+ });
1348
+ }
1349
+ }
1350
+ return applyReplacements(source, replacements);
1351
+ }
1352
+
1353
+ //#endregion
1354
+ //#region src/cli/bundler/trigger-context.ts
1355
+ /**
1356
+ * Normalize a file path by removing extension and resolving to absolute path
1357
+ */
1358
+ function normalizeFilePath(filePath) {
1359
+ const absolutePath = path.resolve(filePath);
1360
+ const ext = path.extname(absolutePath);
1361
+ return absolutePath.slice(0, -ext.length);
1362
+ }
1363
+ /**
1364
+ * Build trigger context from workflow configuration
1365
+ * Scans workflow files to collect workflow and job mappings
1366
+ */
1367
+ async function buildTriggerContext(workflowConfig) {
1368
+ const workflowNameMap = /* @__PURE__ */ new Map();
1369
+ const jobNameMap = /* @__PURE__ */ new Map();
1370
+ const workflowFileMap = /* @__PURE__ */ new Map();
1371
+ if (!workflowConfig) return {
1372
+ workflowNameMap,
1373
+ jobNameMap,
1374
+ workflowFileMap
1375
+ };
1376
+ const workflowFiles = loadFilesWithIgnores(workflowConfig);
1377
+ for (const file of workflowFiles) try {
1378
+ const source = await fs.promises.readFile(file, "utf-8");
1379
+ const { program } = parseSync("input.ts", source);
1380
+ const workflows = findAllWorkflows(program, source);
1381
+ const workflowMap = buildWorkflowNameMap(workflows);
1382
+ for (const [exportName, workflowName] of workflowMap) workflowNameMap.set(exportName, workflowName);
1383
+ for (const workflow of workflows) if (workflow.isDefaultExport) {
1384
+ const normalizedPath = normalizeFilePath(file);
1385
+ workflowFileMap.set(normalizedPath, workflow.name);
1386
+ }
1387
+ const jobs = findAllJobs(program, source);
1388
+ const jobMap = buildJobNameMap(jobs);
1389
+ for (const [exportName, jobName] of jobMap) jobNameMap.set(exportName, jobName);
1390
+ } catch (error) {
1391
+ const errorMessage = error instanceof Error ? error.message : String(error);
1392
+ console.warn(styleText("yellow", `Warning: Failed to process workflow file ${file}: ${errorMessage}`));
1393
+ continue;
1394
+ }
1395
+ return {
1396
+ workflowNameMap,
1397
+ jobNameMap,
1398
+ workflowFileMap
1399
+ };
1400
+ }
1401
+ /**
1402
+ * Create a rolldown plugin for transforming trigger calls
1403
+ * Returns undefined if no trigger context is provided
1404
+ */
1405
+ function createTriggerTransformPlugin(triggerContext) {
1406
+ if (!triggerContext) return;
1407
+ return {
1408
+ name: "trigger-transform",
1409
+ transform: {
1410
+ filter: { id: { include: [/\.ts$/, /\.js$/] } },
1411
+ handler(code, id) {
1412
+ if (!code.includes(".trigger(")) return null;
1413
+ return { code: transformFunctionTriggers(code, triggerContext.workflowNameMap, triggerContext.jobNameMap, triggerContext.workflowFileMap, id) };
1414
+ }
1415
+ }
1416
+ };
1417
+ }
1418
+
1419
+ //#endregion
1420
+ //#region src/cli/bundler/executor/loader.ts
1421
+ async function loadExecutor(executorFilePath) {
1422
+ const executor = (await import(`${pathToFileURL(executorFilePath).href}?t=${Date.now()}`)).default;
1423
+ const parseResult = ExecutorSchema.safeParse(executor);
1424
+ if (!parseResult.success) return null;
1425
+ return parseResult.data;
1426
+ }
1427
+
1428
+ //#endregion
1429
+ //#region src/cli/bundler/executor/executor-bundler.ts
1430
+ /**
1431
+ * Bundle executors from the specified configuration
1432
+ *
1433
+ * This function:
1434
+ * 1. Creates entry file that extracts operation.body
1435
+ * 2. Bundles in a single step with tree-shaking
1436
+ */
1437
+ async function bundleExecutors(config, triggerContext) {
1438
+ const files = loadFilesWithIgnores(config);
1439
+ if (files.length === 0) throw new Error(`No files found matching pattern: ${config.files?.join(", ")}`);
1440
+ console.log("");
1441
+ console.log("Bundling", styleText("cyanBright", files.length.toString()), "files for", styleText("cyan", "\"executor\""));
1442
+ const executors = [];
1443
+ for (const file of files) {
1444
+ const executor = await loadExecutor(file);
1445
+ if (!executor) {
1446
+ console.log(styleText("dim", ` Skipping: ${file} (could not be loaded)`));
1447
+ continue;
1448
+ }
1449
+ if (!["function", "jobFunction"].includes(executor.operation.kind)) {
1450
+ console.log(styleText("dim", ` Skipping: ${executor.name} (not a function executor)`));
1451
+ continue;
1452
+ }
1453
+ executors.push({
1454
+ name: executor.name,
1455
+ sourceFile: file
1456
+ });
1457
+ }
1458
+ if (executors.length === 0) {
1459
+ console.log(styleText("dim", " No function executors to bundle"));
1460
+ return;
1461
+ }
1462
+ const outputDir = path.resolve(getDistDir(), "executors");
1463
+ fs.mkdirSync(outputDir, { recursive: true });
1464
+ let tsconfig;
1465
+ try {
1466
+ tsconfig = await resolveTSConfig();
1467
+ } catch {
1468
+ tsconfig = void 0;
1469
+ }
1470
+ await Promise.all(executors.map((executor) => bundleSingleExecutor(executor, outputDir, tsconfig, triggerContext)));
1471
+ console.log(styleText("green", "Bundled"), styleText("cyan", "\"executor\""));
1472
+ }
1473
+ async function bundleSingleExecutor(executor, outputDir, tsconfig, triggerContext) {
1474
+ const entryPath = path.join(outputDir, `${executor.name}.entry.js`);
1475
+ const absoluteSourcePath = path.resolve(executor.sourceFile).replace(/\\/g, "/");
1476
+ const entryContent = ml`
1477
+ import _internalExecutor from "${absoluteSourcePath}";
1478
+
1479
+ const __executor_function = _internalExecutor.operation.body;
1480
+
1481
+ globalThis.main = __executor_function;
1482
+ `;
1483
+ fs.writeFileSync(entryPath, entryContent);
1484
+ const outputPath = path.join(outputDir, `${executor.name}.js`);
1485
+ const triggerPlugin = createTriggerTransformPlugin(triggerContext);
1486
+ const plugins = triggerPlugin ? [triggerPlugin] : [];
1487
+ await rolldown.build(rolldown.defineConfig({
1488
+ input: entryPath,
1489
+ output: {
1490
+ file: outputPath,
1491
+ format: "esm",
1492
+ sourcemap: true,
1493
+ minify: true,
1494
+ inlineDynamicImports: true
1495
+ },
1496
+ tsconfig,
1497
+ plugins,
1498
+ treeshake: {
1499
+ moduleSideEffects: false,
1500
+ annotations: true,
1501
+ unknownGlobalSideEffects: false
1502
+ },
1503
+ logLevel: "silent"
1504
+ }));
1505
+ }
1506
+
1507
+ //#endregion
1508
+ //#region src/cli/bundler/resolver/loader.ts
1509
+ async function loadResolver(resolverFilePath) {
1510
+ const resolver = (await import(`${pathToFileURL(resolverFilePath).href}?t=${Date.now()}`)).default;
1511
+ const parseResult = ResolverSchema.safeParse(resolver);
1512
+ if (!parseResult.success) return null;
1513
+ return parseResult.data;
1514
+ }
1515
+
1516
+ //#endregion
1517
+ //#region src/cli/bundler/resolver/resolver-bundler.ts
1518
+ /**
1519
+ * Bundle resolvers for the specified namespace
1520
+ *
1521
+ * This function:
1522
+ * 1. Uses a transform plugin to add validation wrapper during bundling
1523
+ * 2. Creates entry file
1524
+ * 3. Bundles in a single step with tree-shaking
1525
+ */
1526
+ async function bundleResolvers(namespace, config, triggerContext) {
1527
+ const files = loadFilesWithIgnores(config);
1528
+ if (files.length === 0) throw new Error(`No files found matching pattern: ${config.files?.join(", ")}`);
1529
+ console.log("");
1530
+ console.log("Bundling", styleText("cyanBright", files.length.toString()), "files for", styleText("cyan", `"${namespace}"`));
1531
+ const resolvers = [];
1532
+ for (const file of files) {
1533
+ const resolver = await loadResolver(file);
1534
+ if (!resolver) {
1535
+ console.log(styleText("dim", ` Skipping: ${file} (could not be loaded)`));
1536
+ continue;
1537
+ }
1538
+ resolvers.push({
1539
+ name: resolver.name,
1540
+ sourceFile: file
1541
+ });
1542
+ }
1543
+ const outputDir = path.resolve(getDistDir(), "resolvers");
1544
+ fs.mkdirSync(outputDir, { recursive: true });
1545
+ let tsconfig;
1546
+ try {
1547
+ tsconfig = await resolveTSConfig();
1548
+ } catch {
1549
+ tsconfig = void 0;
1550
+ }
1551
+ await Promise.all(resolvers.map((resolver) => bundleSingleResolver(resolver, outputDir, tsconfig, triggerContext)));
1552
+ console.log(styleText("green", "Bundled"), styleText("cyan", `"${namespace}"`));
1553
+ }
1554
+ async function bundleSingleResolver(resolver, outputDir, tsconfig, triggerContext) {
1555
+ const entryPath = path.join(outputDir, `${resolver.name}.entry.js`);
1556
+ const absoluteSourcePath = path.resolve(resolver.sourceFile).replace(/\\/g, "/");
1557
+ const entryContent = ml`
1558
+ import _internalResolver from "${absoluteSourcePath}";
1559
+ import { t } from "@tailor-platform/sdk";
1560
+
1561
+ const $tailor_resolver_body = async (context) => {
1562
+ if (_internalResolver.input) {
1563
+ const result = t.object(_internalResolver.input).parse({
1564
+ value: context.input,
1565
+ data: context.input,
1566
+ user: context.user,
1567
+ });
1568
+
1569
+ if (result.issues) {
1570
+ const errorMessages = result.issues
1571
+ .map(issue => {
1572
+ const path = issue.path ? issue.path.join('.') : '';
1573
+ return path ? \` \${path}: \${issue.message}\` : issue.message;
1574
+ })
1575
+ .join('\\n');
1576
+ throw new Error(\`Failed to input validation:\\n\${errorMessages}\`);
1577
+ }
1578
+ }
1579
+
1580
+ return _internalResolver.body(context);
1581
+ };
1582
+
1583
+ globalThis.main = $tailor_resolver_body;
1584
+ `;
1585
+ fs.writeFileSync(entryPath, entryContent);
1586
+ const outputPath = path.join(outputDir, `${resolver.name}.js`);
1587
+ const triggerPlugin = createTriggerTransformPlugin(triggerContext);
1588
+ const plugins = triggerPlugin ? [triggerPlugin] : [];
1589
+ await rolldown.build(rolldown.defineConfig({
1590
+ input: entryPath,
1591
+ output: {
1592
+ file: outputPath,
1593
+ format: "esm",
1594
+ sourcemap: true,
1595
+ minify: true,
1596
+ inlineDynamicImports: true
1597
+ },
1598
+ tsconfig,
1599
+ plugins,
1600
+ treeshake: {
1601
+ moduleSideEffects: false,
1602
+ annotations: true,
1603
+ unknownGlobalSideEffects: false
1604
+ },
1605
+ logLevel: "silent"
1606
+ }));
1607
+ }
1608
+
1609
+ //#endregion
1610
+ //#region src/cli/bundler/workflow/source-transformer.ts
1611
+ /**
1134
1612
  * Find variable declarations by export names
1135
1613
  * Returns a map of export name to statement range
1136
1614
  */
@@ -1253,7 +1731,7 @@ function transformWorkflowSource(source, targetJobName, targetJobExportName, oth
1253
1731
  * 2. Uses a transform plugin to transform trigger calls during bundling
1254
1732
  * 3. Creates entry file and bundles with tree-shaking
1255
1733
  */
1256
- async function bundleWorkflowJobs(allJobs, mainJobNames, env = {}) {
1734
+ async function bundleWorkflowJobs(allJobs, mainJobNames, env = {}, triggerContext) {
1257
1735
  if (allJobs.length === 0) {
1258
1736
  console.log(styleText("dim", "No workflow jobs to bundle"));
1259
1737
  return;
@@ -1270,7 +1748,7 @@ async function bundleWorkflowJobs(allJobs, mainJobNames, env = {}) {
1270
1748
  } catch {
1271
1749
  tsconfig = void 0;
1272
1750
  }
1273
- await Promise.all(usedJobs.map((job) => bundleSingleJob(job, usedJobs, outputDir, tsconfig, env)));
1751
+ await Promise.all(usedJobs.map((job) => bundleSingleJob(job, usedJobs, outputDir, tsconfig, env, triggerContext)));
1274
1752
  console.log(styleText("green", "Bundled"), styleText("cyan", "\"workflow-job\""));
1275
1753
  }
1276
1754
  /**
@@ -1328,7 +1806,7 @@ async function filterUsedJobs(allJobs, mainJobNames) {
1328
1806
  for (const mainJobName of mainJobNames) markUsed(mainJobName);
1329
1807
  return allJobs.filter((job) => usedJobNames.has(job.name));
1330
1808
  }
1331
- async function bundleSingleJob(job, allJobs, outputDir, tsconfig, env) {
1809
+ async function bundleSingleJob(job, allJobs, outputDir, tsconfig, env, triggerContext) {
1332
1810
  const entryPath = path.join(outputDir, `${job.name}.entry.js`);
1333
1811
  const absoluteSourcePath = path.resolve(job.sourceFile).replace(/\\/g, "/");
1334
1812
  const entryContent = ml`
@@ -1359,9 +1837,11 @@ async function bundleSingleJob(job, allJobs, outputDir, tsconfig, env) {
1359
1837
  name: "workflow-transform",
1360
1838
  transform: {
1361
1839
  filter: { id: { include: [/\.ts$/, /\.js$/] } },
1362
- handler(code) {
1363
- if (!code.includes("createWorkflowJob") && !code.includes(".trigger(")) return null;
1364
- return { code: transformWorkflowSource(code, job.name, job.exportName, otherJobExportNames, allJobsMap) };
1840
+ handler(code, id) {
1841
+ if (!code.includes("createWorkflowJob") && !code.includes("createWorkflow") && !code.includes(".trigger(")) return null;
1842
+ let transformed = transformWorkflowSource(code, job.name, job.exportName, otherJobExportNames, allJobsMap);
1843
+ if (triggerContext && transformed.includes(".trigger(")) transformed = transformFunctionTriggers(transformed, triggerContext.workflowNameMap, triggerContext.jobNameMap, triggerContext.workflowFileMap, id);
1844
+ return { code: transformed };
1365
1845
  }
1366
1846
  }
1367
1847
  }],
@@ -3937,12 +4417,12 @@ function protoIdPConfig(idpConfig) {
3937
4417
  value: {
3938
4418
  ...idpConfig.metadataURL !== void 0 ? { metadataUrl: idpConfig.metadataURL } : { rawMetadata: idpConfig.rawMetadata },
3939
4419
  ...idpConfig.spCertBase64 && { spCertBase64: {
3940
- vaultName: idpConfig.spCertBase64.VaultName,
3941
- secretKey: idpConfig.spCertBase64.SecretKey
4420
+ vaultName: idpConfig.spCertBase64.vaultName,
4421
+ secretKey: idpConfig.spCertBase64.secretKey
3942
4422
  } },
3943
4423
  ...idpConfig.spKeyBase64 && { spKeyBase64: {
3944
- vaultName: idpConfig.spKeyBase64.VaultName,
3945
- secretKey: idpConfig.spKeyBase64.SecretKey
4424
+ vaultName: idpConfig.spKeyBase64.vaultName,
4425
+ secretKey: idpConfig.spKeyBase64.secretKey
3946
4426
  } }
3947
4427
  }
3948
4428
  } }
@@ -3955,8 +4435,8 @@ function protoIdPConfig(idpConfig) {
3955
4435
  value: {
3956
4436
  clientIdKey: idpConfig.clientID,
3957
4437
  clientSecretKey: {
3958
- vaultName: idpConfig.clientSecret.VaultName,
3959
- secretKey: idpConfig.clientSecret.SecretKey
4438
+ vaultName: idpConfig.clientSecret.vaultName,
4439
+ secretKey: idpConfig.clientSecret.secretKey
3960
4440
  },
3961
4441
  providerUrl: idpConfig.providerURL,
3962
4442
  issuerUrl: idpConfig.issuerURL,
@@ -4392,8 +4872,8 @@ function protoSCIMConfig(scimConfig) {
4392
4872
  authorizationConfig: {
4393
4873
  case: "bearerSecret",
4394
4874
  value: {
4395
- vaultName: scimConfig.authorization.bearerSecret?.VaultName,
4396
- secretKey: scimConfig.authorization.bearerSecret?.SecretKey
4875
+ vaultName: scimConfig.authorization.bearerSecret?.vaultName,
4876
+ secretKey: scimConfig.authorization.bearerSecret?.secretKey
4397
4877
  }
4398
4878
  }
4399
4879
  };
@@ -4780,10 +5260,7 @@ function protoExecutor(appName, executor, env) {
4780
5260
  appName: target.appName ?? appName,
4781
5261
  query: target.query,
4782
5262
  variables: target.variables ? { expr: `(${target.variables.toString()})(args)` } : void 0,
4783
- invoker: target.invoker ? {
4784
- namespace: target.invoker.authName,
4785
- machineUserName: target.invoker.machineUser
4786
- } : void 0
5263
+ invoker: target.authInvoker ?? void 0
4787
5264
  }
4788
5265
  } };
4789
5266
  break;
@@ -4799,10 +5276,7 @@ function protoExecutor(appName, executor, env) {
4799
5276
  name: `${executor.name}__target`,
4800
5277
  script,
4801
5278
  variables: { expr: `({ ...args, appNamespace: args.namespaceName, env: ${JSON.stringify(env)} })` },
4802
- invoker: target.invoker ? {
4803
- namespace: target.invoker.authName,
4804
- machineUserName: target.invoker.machineUser
4805
- } : void 0
5279
+ invoker: target.authInvoker ?? void 0
4806
5280
  }
4807
5281
  } };
4808
5282
  break;
@@ -5905,11 +6379,12 @@ async function apply(options) {
5905
6379
  const application = defineApplication(config);
5906
6380
  let workflowResult;
5907
6381
  if (application.workflowConfig) workflowResult = await loadAndCollectJobs(application.workflowConfig);
5908
- for (const app$1 of application.applications) for (const pipeline$1 of app$1.resolverServices) await buildPipeline(pipeline$1.namespace, pipeline$1.config);
5909
- if (application.executorService) await buildExecutor(application.executorService.config);
6382
+ const triggerContext = await buildTriggerContext(application.workflowConfig);
6383
+ for (const app$1 of application.applications) for (const pipeline$1 of app$1.resolverServices) await buildPipeline(pipeline$1.namespace, pipeline$1.config, triggerContext);
6384
+ if (application.executorService) await buildExecutor(application.executorService.config, triggerContext);
5910
6385
  if (workflowResult && workflowResult.jobs.length > 0) {
5911
6386
  const mainJobNames = workflowResult.workflowSources.map((ws) => ws.workflow.mainJob.name);
5912
- await buildWorkflow(workflowResult.jobs, mainJobNames, application.env);
6387
+ await buildWorkflow(workflowResult.jobs, mainJobNames, application.env, triggerContext);
5913
6388
  }
5914
6389
  if (buildOnly) return;
5915
6390
  const accessToken = await loadAccessToken({
@@ -6009,14 +6484,14 @@ async function apply(options) {
6009
6484
  await applyTailorDB(client, tailorDB, "delete");
6010
6485
  console.log("Successfully applied changes.");
6011
6486
  }
6012
- async function buildPipeline(namespace, config) {
6013
- await bundleResolvers(namespace, config);
6487
+ async function buildPipeline(namespace, config, triggerContext) {
6488
+ await bundleResolvers(namespace, config, triggerContext);
6014
6489
  }
6015
- async function buildExecutor(config) {
6016
- await bundleExecutors(config);
6490
+ async function buildExecutor(config, triggerContext) {
6491
+ await bundleExecutors(config, triggerContext);
6017
6492
  }
6018
- async function buildWorkflow(collectedJobs, mainJobNames, env) {
6019
- await bundleWorkflowJobs(collectedJobs, mainJobNames, env);
6493
+ async function buildWorkflow(collectedJobs, mainJobNames, env, triggerContext) {
6494
+ await bundleWorkflowJobs(collectedJobs, mainJobNames, env, triggerContext);
6020
6495
  }
6021
6496
  const applyCommand = defineCommand({
6022
6497
  meta: {
@@ -7448,4 +7923,4 @@ const listCommand = defineCommand({
7448
7923
 
7449
7924
  //#endregion
7450
7925
  export { PATScope, apply, applyCommand, commonArgs, createCommand, deleteCommand, fetchAll, fetchLatestToken, fetchUserInfo, formatArgs, generate, generateCommand, generateUserTypes, getCommand, initOAuth2Client, initOperatorClient, listCommand, listCommand$1, listCommand$2, loadAccessToken, loadConfig, loadWorkspaceId, machineUserList, machineUserToken, oauth2ClientGet, oauth2ClientList, parseFormat, printWithFormat, readPackageJson, readPlatformConfig, remove, removeCommand, show, showCommand, tokenCommand, withCommonArgs, workspaceCreate, workspaceDelete, workspaceList, writePlatformConfig };
7451
- //# sourceMappingURL=list-D-R1mEOM.mjs.map
7926
+ //# sourceMappingURL=list-B8Uv3SPW.mjs.map