windmill-cli 1.658.0 → 1.659.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/esm/main.js +809 -402
  2. package/package.json +1 -1
package/esm/main.js CHANGED
@@ -11785,7 +11785,7 @@ var init_OpenAPI = __esm(() => {
11785
11785
  PASSWORD: undefined,
11786
11786
  TOKEN: getEnv2("WM_TOKEN"),
11787
11787
  USERNAME: undefined,
11788
- VERSION: "1.658.0",
11788
+ VERSION: "1.659.1",
11789
11789
  WITH_CREDENTIALS: true,
11790
11790
  interceptors: {
11791
11791
  request: new Interceptors,
@@ -12220,6 +12220,7 @@ __export(exports_services_gen, {
12220
12220
  logout: () => logout,
12221
12221
  loginWithOauth: () => loginWithOauth,
12222
12222
  login: () => login,
12223
+ logAiChat: () => logAiChat,
12223
12224
  loadTableRowCount: () => loadTableRowCount,
12224
12225
  loadParquetPreview: () => loadParquetPreview,
12225
12226
  loadGitRepoFilePreview: () => loadGitRepoFilePreview,
@@ -14242,6 +14243,16 @@ var backendVersion = () => {
14242
14243
  404: "protection rule not found"
14243
14244
  }
14244
14245
  });
14246
+ }, logAiChat = (data2) => {
14247
+ return request(OpenAPI, {
14248
+ method: "POST",
14249
+ url: "/w/{workspace}/workspaces/log_chat",
14250
+ path: {
14251
+ workspace: data2.workspace
14252
+ },
14253
+ body: data2.requestBody,
14254
+ mediaType: "application/json"
14255
+ });
14245
14256
  }, setPublicAppRateLimit = (data2) => {
14246
14257
  return request(OpenAPI, {
14247
14258
  method: "POST",
@@ -24318,6 +24329,29 @@ function isRawAppMetadataFile(p) {
24318
24329
  function isRawAppFolderMetadataFile(p) {
24319
24330
  return p.endsWith(getMetadataPathSuffix("raw_app", "yaml")) || p.endsWith(getMetadataPathSuffix("raw_app", "json"));
24320
24331
  }
24332
+ function getModuleFolderSuffix() {
24333
+ return MODULE_SUFFIX;
24334
+ }
24335
+ function isScriptModulePath(p) {
24336
+ return normalizeSep(p).includes(MODULE_SUFFIX + "/");
24337
+ }
24338
+ function isModuleEntryPoint(p) {
24339
+ const norm = normalizeSep(p);
24340
+ const suffix = MODULE_SUFFIX + "/";
24341
+ const idx = norm.indexOf(suffix);
24342
+ if (idx === -1)
24343
+ return false;
24344
+ const rest = norm.slice(idx + suffix.length);
24345
+ return rest.startsWith("script.") && !rest.includes("/");
24346
+ }
24347
+ function getScriptBasePathFromModulePath(p) {
24348
+ const norm = normalizeSep(p);
24349
+ const suffix = MODULE_SUFFIX + "/";
24350
+ const idx = norm.indexOf(suffix);
24351
+ if (idx === -1)
24352
+ return;
24353
+ return norm.slice(0, idx);
24354
+ }
24321
24355
  function getDeleteSuffix(type, format6) {
24322
24356
  return getFolderSuffixes()[type] + "/" + METADATA_FILES[type][format6];
24323
24357
  }
@@ -24333,7 +24367,7 @@ function transformJsonPathToDir(p, type) {
24333
24367
  }
24334
24368
  return p;
24335
24369
  }
24336
- var DOTTED_SUFFIXES, NON_DOTTED_SUFFIXES, _nonDottedPaths = false, _nonDottedPathsLogged = false, METADATA_FILES;
24370
+ var DOTTED_SUFFIXES, NON_DOTTED_SUFFIXES, _nonDottedPaths = false, _nonDottedPathsLogged = false, METADATA_FILES, MODULE_SUFFIX = "__mod";
24337
24371
  var init_resource_folders = __esm(() => {
24338
24372
  init_log();
24339
24373
  init_yaml();
@@ -24959,6 +24993,14 @@ async function readConfigFile() {
24959
24993
  migrationMessages.push("ℹ️ Removing empty 'overrides: {}' from wmill.yaml (migrated to gitBranches format)");
24960
24994
  }
24961
24995
  }
24996
+ if (conf && "environments" in conf) {
24997
+ if (!conf.gitBranches) {
24998
+ conf.gitBranches = conf.environments;
24999
+ } else {
25000
+ warn("⚠️ Both 'environments' and 'gitBranches' found in wmill.yaml. Using 'gitBranches' and ignoring 'environments'.");
25001
+ }
25002
+ delete conf.environments;
25003
+ }
24962
25004
  if (conf && "git_branches" in conf) {
24963
25005
  if (!conf.gitBranches) {
24964
25006
  conf.gitBranches = JSON.parse(JSON.stringify(conf.git_branches));
@@ -25503,7 +25545,7 @@ var init_workspace = __esm(async () => {
25503
25545
  ]);
25504
25546
  command = new Command().alias("profile").description("workspace related commands").action(list).command("switch").complete("workspace", async () => (await allWorkspaces()).map((x) => x.name)).description("Switch to another workspace").arguments("<workspace_name:string:workspace>").action(switchC).command("add").description("Add a workspace").arguments("[workspace_name:string] [workspace_id:string] [remote:string]").option("-c --create", "Create the workspace if it does not exist").option("--create-workspace-name <workspace_name:string>", "Specify the workspace name. Ignored if --create is not specified or the workspace already exists. Will default to the workspace id.").option("--create-username <username:string>", "Specify your own username in the newly created workspace. Ignored if --create is not specified, the workspace already exists or automatic username creation is enabled on the instance.", {
25505
25547
  default: "admin"
25506
- }).action(add).command("remove").description("Remove a workspace").arguments("<workspace_name:string>").action(remove).command("whoami").description("Show the currently active user").action(whoami2).command("list").description("List local workspace profiles").action(list).command("list-remote").description("List workspaces on the remote server that you have access to").action(listRemote).command("bind").description("Bind the current Git branch to the active workspace").option("--branch <branch:string>", "Specify branch (defaults to current)").action((opts) => bind(opts, true)).command("unbind").description("Remove workspace binding from the current Git branch").option("--branch <branch:string>", "Specify branch (defaults to current)").action((opts) => bind(opts, false)).command("fork").description("Create a forked workspace").arguments("[workspace_name:string] [workspace_id:string]").option("--create-workspace-name <workspace_name:string>", "Specify the workspace name. Ignored if --create is not specified or the workspace already exists. Will default to the workspace id.").action(createWorkspaceFork2).command("delete-fork").description("Delete a forked workspace and git branch").arguments("<fork_name:string>").option("-y --yes", "Skip confirmation prompt").action(deleteWorkspaceFork);
25548
+ }).action(add).command("remove").description("Remove a workspace").arguments("<workspace_name:string>").action(remove).command("whoami").description("Show the currently active user").action(whoami2).command("list").description("List local workspace profiles").action(list).command("list-remote").description("List workspaces on the remote server that you have access to").action(listRemote).command("bind").description("Bind the current Git branch to the active workspace").option("--branch, --env <branch:string>", "Specify branch/environment (defaults to current)").action((opts) => bind(opts, true)).command("unbind").description("Remove workspace binding from the current Git branch").option("--branch, --env <branch:string>", "Specify branch/environment (defaults to current)").action((opts) => bind(opts, false)).command("fork").description("Create a forked workspace").arguments("[workspace_name:string] [workspace_id:string]").option("--create-workspace-name <workspace_name:string>", "Specify the workspace name. Ignored if --create is not specified or the workspace already exists. Will default to the workspace id.").action(createWorkspaceFork2).command("delete-fork").description("Delete a forked workspace and git branch").arguments("<fork_name:string>").option("-y --yes", "Skip confirmation prompt").action(deleteWorkspaceFork);
25507
25549
  workspace_default = command;
25508
25550
  });
25509
25551
 
@@ -58802,6 +58844,7 @@ var init_tar = __esm(() => {
58802
58844
  import { readFile as readFile5, writeFile as writeFile4, stat as stat3 } from "node:fs/promises";
58803
58845
  import { Buffer as Buffer4 } from "node:buffer";
58804
58846
  import { sep as SEP4 } from "node:path";
58847
+ import * as path5 from "node:path";
58805
58848
  import fs8 from "node:fs";
58806
58849
  import { execSync as execSync3 } from "node:child_process";
58807
58850
  function isRawAppBackendPath2(filePath) {
@@ -58831,8 +58874,8 @@ async function push(opts, filePath) {
58831
58874
  await handleFile(filePath, workspace, [], undefined, opts, await getRawWorkspaceDependencies(), codebases);
58832
58875
  info(colors.bold.underline.green(`Script ${filePath} pushed`));
58833
58876
  }
58834
- async function findResourceFile(path5) {
58835
- const splitPath = path5.split(".");
58877
+ async function findResourceFile(path6) {
58878
+ const splitPath = path6.split(".");
58836
58879
  let contentBasePathJSON = splitPath[0] + "." + splitPath[1] + ".json";
58837
58880
  let contentBasePathYAML = splitPath[0] + "." + splitPath[1] + ".yaml";
58838
58881
  const currentBranch = getCurrentGitBranch();
@@ -58853,45 +58896,48 @@ async function findResourceFile(path5) {
58853
58896
  throw new Error("Found two resource files for the same resource" + validCandidates.join(", "));
58854
58897
  }
58855
58898
  if (validCandidates.length < 1) {
58856
- throw new Error(`No resource matching file resource: ${path5}.`);
58899
+ throw new Error(`No resource matching file resource: ${path6}.`);
58857
58900
  }
58858
58901
  return validCandidates[0];
58859
58902
  }
58860
- async function handleScriptMetadata(path5, workspace, alreadySynced, message, rawWorkspaceDependencies, codebases, opts) {
58861
- if (path5.endsWith(".script.json") || path5.endsWith(".script.yaml") || path5.endsWith(".script.lock")) {
58862
- const contentPath = await findContentFile(path5);
58903
+ async function handleScriptMetadata(path6, workspace, alreadySynced, message, rawWorkspaceDependencies, codebases, opts) {
58904
+ const isFlatMeta = path6.endsWith(".script.json") || path6.endsWith(".script.yaml") || path6.endsWith(".script.lock");
58905
+ const isFolderMeta = !isFlatMeta && isScriptModulePath(path6) && (path6.endsWith("/script.yaml") || path6.endsWith("/script.json") || path6.endsWith("/script.lock"));
58906
+ if (isFlatMeta || isFolderMeta) {
58907
+ const contentPath = await findContentFile(path6);
58863
58908
  return handleFile(contentPath, workspace, alreadySynced, message, opts, rawWorkspaceDependencies, codebases);
58864
58909
  } else {
58865
58910
  return false;
58866
58911
  }
58867
58912
  }
58868
- async function handleFile(path5, workspace, alreadySynced, message, opts, rawWorkspaceDependencies, codebases) {
58869
- if (!isAppInlineScriptPath2(path5) && !isFlowInlineScriptPath2(path5) && !isRawAppBackendPath2(path5) && exts.some((exts) => path5.endsWith(exts))) {
58870
- if (alreadySynced.includes(path5)) {
58913
+ async function handleFile(path6, workspace, alreadySynced, message, opts, rawWorkspaceDependencies, codebases) {
58914
+ const moduleEntryPoint = isModuleEntryPoint(path6);
58915
+ if (!isAppInlineScriptPath2(path6) && !isFlowInlineScriptPath2(path6) && !isRawAppBackendPath2(path6) && (!isScriptModulePath(path6) || moduleEntryPoint) && exts.some((exts) => path6.endsWith(exts))) {
58916
+ if (alreadySynced.includes(path6)) {
58871
58917
  return true;
58872
58918
  }
58873
- debug(`Processing local script ${path5}`);
58874
- alreadySynced.push(path5);
58875
- const remotePath = path5.substring(0, path5.indexOf(".")).replaceAll(SEP4, "/");
58876
- const language = inferContentTypeFromFilePath(path5, opts?.defaultTs);
58877
- const codebase = language == "bun" ? findCodebase(path5, codebases) : undefined;
58919
+ debug(`Processing local script ${path6}`);
58920
+ alreadySynced.push(path6);
58921
+ const remotePath = moduleEntryPoint ? getScriptBasePathFromModulePath(path6).replaceAll(SEP4, "/") : path6.substring(0, path6.indexOf(".")).replaceAll(SEP4, "/");
58922
+ const language = inferContentTypeFromFilePath(path6, opts?.defaultTs);
58923
+ const codebase = language == "bun" ? findCodebase(path6, codebases) : undefined;
58878
58924
  let bundleContent = undefined;
58879
58925
  let forceTar = false;
58880
58926
  if (codebase) {
58881
58927
  let outputFiles = [];
58882
58928
  if (codebase.customBundler) {
58883
- info(`Using custom bundler ${codebase.customBundler} for ${path5}`);
58884
- bundleContent = execSync3(codebase.customBundler + " " + path5, {
58929
+ info(`Using custom bundler ${codebase.customBundler} for ${path6}`);
58930
+ bundleContent = execSync3(codebase.customBundler + " " + path6, {
58885
58931
  maxBuffer: 1024 * 1024 * 50
58886
58932
  }).toString();
58887
- info("Custom bundler executed for " + path5);
58933
+ info("Custom bundler executed for " + path6);
58888
58934
  } else {
58889
58935
  const esbuild = await import("esbuild");
58890
- info(`Started bundling ${path5} ...`);
58936
+ info(`Started bundling ${path6} ...`);
58891
58937
  const startTime = performance.now();
58892
58938
  const format6 = codebase.format ?? "cjs";
58893
58939
  const out = await esbuild.build({
58894
- entryPoints: [path5],
58940
+ entryPoints: [path6],
58895
58941
  format: format6,
58896
58942
  bundle: true,
58897
58943
  write: false,
@@ -58909,15 +58955,15 @@ async function handleFile(path5, workspace, alreadySynced, message, opts, rawWor
58909
58955
  bundleContent = out.outputFiles[0].text;
58910
58956
  outputFiles = out.outputFiles ?? [];
58911
58957
  if (outputFiles.length == 0) {
58912
- throw new Error(`No output files found for ${path5}`);
58958
+ throw new Error(`No output files found for ${path6}`);
58913
58959
  }
58914
- info(`Finished bundling ${path5}: ${(bundleContent.length / 1024).toFixed(0)}kB (${(endTime - startTime).toFixed(0)}ms)`);
58960
+ info(`Finished bundling ${path6}: ${(bundleContent.length / 1024).toFixed(0)}kB (${(endTime - startTime).toFixed(0)}ms)`);
58915
58961
  }
58916
58962
  if (outputFiles.length > 1) {
58917
- info(`Found multiple output files for ${path5}, creating a tarball... ${outputFiles.map((file) => file.path).join(", ")}`);
58963
+ info(`Found multiple output files for ${path6}, creating a tarball... ${outputFiles.map((file) => file.path).join(", ")}`);
58918
58964
  forceTar = true;
58919
58965
  const startTime = performance.now();
58920
- const mainPath = path5.split(SEP4).pop()?.split(".")[0] + ".js";
58966
+ const mainPath = path6.split(SEP4).pop()?.split(".")[0] + ".js";
58921
58967
  const mainContent = outputFiles.find((file) => file.path == "/" + mainPath)?.text ?? "";
58922
58968
  info(`Main content: ${mainContent.length}chars`);
58923
58969
  const entries = [
@@ -58932,10 +58978,10 @@ async function handleFile(path5, workspace, alreadySynced, message, opts, rawWor
58932
58978
  }
58933
58979
  bundleContent = await createTarBlob(entries);
58934
58980
  const endTime = performance.now();
58935
- info(`Finished creating tarball for ${path5}: ${(bundleContent.size / 1024).toFixed(0)}kB (${(endTime - startTime).toFixed(0)}ms)`);
58981
+ info(`Finished creating tarball for ${path6}: ${(bundleContent.size / 1024).toFixed(0)}kB (${(endTime - startTime).toFixed(0)}ms)`);
58936
58982
  } else {
58937
58983
  if (Array.isArray(codebase.assets) && codebase.assets.length > 0) {
58938
- info(`Using the following asset configuration for ${path5}: ${JSON.stringify(codebase.assets)}`);
58984
+ info(`Using the following asset configuration for ${path6}: ${JSON.stringify(codebase.assets)}`);
58939
58985
  const startTime = performance.now();
58940
58986
  const entries = [
58941
58987
  { name: "main.js", content: bundleContent }
@@ -58946,13 +58992,13 @@ async function handleFile(path5, workspace, alreadySynced, message, opts, rawWor
58946
58992
  }
58947
58993
  bundleContent = await createTarBlob(entries);
58948
58994
  const endTime = performance.now();
58949
- info(`Finished creating tarball for ${path5}: ${(bundleContent.size / 1024).toFixed(0)}kB (${(endTime - startTime).toFixed(0)}ms)`);
58995
+ info(`Finished creating tarball for ${path6}: ${(bundleContent.size / 1024).toFixed(0)}kB (${(endTime - startTime).toFixed(0)}ms)`);
58950
58996
  }
58951
58997
  }
58952
58998
  }
58953
58999
  let typed = opts?.skipScriptsMetadata ? undefined : (await parseMetadataFile(remotePath, opts ? {
58954
59000
  ...opts,
58955
- path: path5,
59001
+ path: path6,
58956
59002
  workspaceRemote: workspace,
58957
59003
  schemaOnly: codebase ? true : undefined,
58958
59004
  rawWorkspaceDependencies,
@@ -58969,13 +59015,16 @@ async function handleFile(path5, workspace, alreadySynced, message, opts, rawWor
58969
59015
  } catch {
58970
59016
  debug(`Script ${remotePath} does not exist on remote`);
58971
59017
  }
58972
- const content = await readFile5(path5, "utf-8");
59018
+ const content = await readFile5(path6, "utf-8");
58973
59019
  if (opts?.skipScriptsMetadata) {
58974
59020
  typed = structuredClone(remote);
58975
59021
  }
58976
59022
  if (typed && codebase) {
58977
59023
  typed.codebase = await codebase.getDigest(forceTar);
58978
59024
  }
59025
+ const scriptBasePath = moduleEntryPoint ? getScriptBasePathFromModulePath(path6) : path6.substring(0, path6.indexOf("."));
59026
+ const moduleFolderPath = scriptBasePath + getModuleFolderSuffix();
59027
+ const modules = await readModulesFromDisk(moduleFolderPath, opts?.defaultTs, moduleEntryPoint);
58979
59028
  const requestBodyCommon = {
58980
59029
  content,
58981
59030
  description: typed?.description ?? "",
@@ -58994,7 +59043,6 @@ async function handleFile(path5, workspace, alreadySynced, message, opts, rawWor
58994
59043
  deployment_message: message,
58995
59044
  restart_unless_cancelled: typed?.restart_unless_cancelled,
58996
59045
  visible_to_runner_only: typed?.visible_to_runner_only,
58997
- no_main_func: typed?.no_main_func,
58998
59046
  has_preprocessor: typed?.has_preprocessor,
58999
59047
  priority: typed?.priority,
59000
59048
  concurrency_key: typed?.concurrency_key,
@@ -59003,12 +59051,13 @@ async function handleFile(path5, workspace, alreadySynced, message, opts, rawWor
59003
59051
  codebase: await codebase?.getDigest(forceTar),
59004
59052
  timeout: typed?.timeout,
59005
59053
  on_behalf_of_email: typed?.on_behalf_of_email,
59006
- envs: typed?.envs
59054
+ envs: typed?.envs,
59055
+ modules
59007
59056
  };
59008
59057
  if (remote) {
59009
59058
  if (content === remote.content) {
59010
59059
  if (typed == undefined || typed.description === remote.description && typed.summary === remote.summary && typed.kind == remote.kind && !remote.archived && (Array.isArray(remote?.lock) ? remote?.lock?.join(`
59011
- `) : remote?.lock ?? "").trim() == (typed?.lock ?? "").trim() && deepEqual(typed.schema, remote.schema) && typed.tag == remote.tag && (typed.ws_error_handler_muted ?? false) == remote.ws_error_handler_muted && typed.dedicated_worker == remote.dedicated_worker && typed.cache_ttl == remote.cache_ttl && typed.concurrency_time_window_s == remote.concurrency_time_window_s && typed.concurrent_limit == remote.concurrent_limit && Boolean(typed.restart_unless_cancelled) == Boolean(remote.restart_unless_cancelled) && Boolean(typed.visible_to_runner_only) == Boolean(remote.visible_to_runner_only) && Boolean(typed.no_main_func) == Boolean(remote.no_main_func) && Boolean(typed.has_preprocessor) == Boolean(remote.has_preprocessor) && typed.priority == Boolean(remote.priority) && typed.timeout == remote.timeout && typed.concurrency_key == remote["concurrency_key"] && typed.debounce_key == remote["debounce_key"] && typed.debounce_delay_s == remote["debounce_delay_s"] && typed.codebase == remote.codebase && typed.on_behalf_of_email == remote.on_behalf_of_email && deepEqual(typed.envs, remote.envs)) {
59060
+ `) : remote?.lock ?? "").trim() == (typed?.lock ?? "").trim() && deepEqual(typed.schema, remote.schema) && typed.tag == remote.tag && (typed.ws_error_handler_muted ?? false) == remote.ws_error_handler_muted && typed.dedicated_worker == remote.dedicated_worker && typed.cache_ttl == remote.cache_ttl && typed.concurrency_time_window_s == remote.concurrency_time_window_s && typed.concurrent_limit == remote.concurrent_limit && Boolean(typed.restart_unless_cancelled) == Boolean(remote.restart_unless_cancelled) && Boolean(typed.visible_to_runner_only) == Boolean(remote.visible_to_runner_only) && Boolean(typed.has_preprocessor) == Boolean(remote.has_preprocessor) && typed.priority == Boolean(remote.priority) && typed.timeout == remote.timeout && typed.concurrency_key == remote["concurrency_key"] && typed.debounce_key == remote["debounce_key"] && typed.debounce_delay_s == remote["debounce_delay_s"] && typed.codebase == remote.codebase && typed.on_behalf_of_email == remote.on_behalf_of_email && deepEqual(typed.envs, remote.envs) && deepEqual(modules ?? null, remote.modules ?? null)) {
59012
59061
  info(colors.green(`Script ${remotePath} is up to date`));
59013
59062
  return true;
59014
59063
  }
@@ -59033,6 +59082,50 @@ async function handleFile(path5, workspace, alreadySynced, message, opts, rawWor
59033
59082
  }
59034
59083
  return false;
59035
59084
  }
59085
+ async function readModulesFromDisk(moduleFolderPath, defaultTs, folderLayout = false) {
59086
+ if (!fs8.existsSync(moduleFolderPath) || !fs8.statSync(moduleFolderPath).isDirectory()) {
59087
+ return;
59088
+ }
59089
+ const modules = {};
59090
+ const isEntryPointFile = (name, isTopLevel) => {
59091
+ if (!folderLayout || !isTopLevel)
59092
+ return false;
59093
+ return name.startsWith("script.") || name === "script.lock" || name === "script.yaml" || name === "script.json";
59094
+ };
59095
+ function readDir2(dirPath, relPrefix) {
59096
+ const entries = fs8.readdirSync(dirPath, { withFileTypes: true });
59097
+ for (const entry of entries) {
59098
+ const fullPath = path5.join(dirPath, entry.name);
59099
+ const relPath = relPrefix ? relPrefix + "/" + entry.name : entry.name;
59100
+ const isTopLevel = relPrefix === "";
59101
+ if (entry.isDirectory()) {
59102
+ readDir2(fullPath, relPath);
59103
+ } else if (entry.isFile() && !entry.name.endsWith(".lock") && !isEntryPointFile(entry.name, isTopLevel)) {
59104
+ if (exts.some((ext2) => entry.name.endsWith(ext2))) {
59105
+ const content = fs8.readFileSync(fullPath, "utf-8");
59106
+ const language = inferContentTypeFromFilePath(entry.name, defaultTs);
59107
+ const baseName = entry.name.replace(/\.[^.]+$/, "");
59108
+ const lockPath = path5.join(dirPath, baseName + ".lock");
59109
+ let lock;
59110
+ if (fs8.existsSync(lockPath)) {
59111
+ lock = fs8.readFileSync(lockPath, "utf-8");
59112
+ }
59113
+ modules[relPath] = {
59114
+ content,
59115
+ language,
59116
+ lock: lock ?? undefined
59117
+ };
59118
+ }
59119
+ }
59120
+ }
59121
+ }
59122
+ readDir2(moduleFolderPath, "");
59123
+ if (Object.keys(modules).length === 0) {
59124
+ return;
59125
+ }
59126
+ debug(`Found ${Object.keys(modules).length} module(s) in ${moduleFolderPath}`);
59127
+ return modules;
59128
+ }
59036
59129
  async function createScript2(bundleContent, workspaceId, body, workspace) {
59037
59130
  const start = performance.now();
59038
59131
  if (!bundleContent) {
@@ -59061,7 +59154,8 @@ async function createScript2(bundleContent, workspaceId, body, workspace) {
59061
59154
  return performance.now() - start;
59062
59155
  }
59063
59156
  async function findContentFile(filePath) {
59064
- const candidates = filePath.endsWith("script.json") ? exts.map((x) => filePath.replace(".script.json", x)) : filePath.endsWith("script.lock") ? exts.map((x) => filePath.replace(".script.lock", x)) : exts.map((x) => filePath.replace(".script.yaml", x));
59157
+ const isModuleFolderMeta = filePath.endsWith("/script.yaml") || filePath.endsWith("/script.json") || filePath.endsWith("/script.lock");
59158
+ const candidates = isModuleFolderMeta ? exts.map((x) => filePath.replace(/\/script\.(yaml|json|lock)$/, "/script" + x)) : filePath.endsWith("script.json") ? exts.map((x) => filePath.replace(".script.json", x)) : filePath.endsWith("script.lock") ? exts.map((x) => filePath.replace(".script.lock", x)) : exts.map((x) => filePath.replace(".script.yaml", x));
59065
59159
  const validCandidates = (await Promise.all(candidates.map((x) => {
59066
59160
  return stat3(x).catch(() => {
59067
59161
  return;
@@ -59134,13 +59228,13 @@ function filePathExtensionFromContentType(language, defaultTs) {
59134
59228
  throw new Error("Invalid language: " + language);
59135
59229
  }
59136
59230
  }
59137
- function removeExtensionToPath(path5) {
59231
+ function removeExtensionToPath(path6) {
59138
59232
  for (const ext2 of exts) {
59139
- if (path5.endsWith(ext2)) {
59140
- return path5.substring(0, path5.length - ext2.length);
59233
+ if (path6.endsWith(ext2)) {
59234
+ return path6.substring(0, path6.length - ext2.length);
59141
59235
  }
59142
59236
  }
59143
- throw new Error("Invalid extension: " + path5);
59237
+ throw new Error("Invalid extension: " + path6);
59144
59238
  }
59145
59239
  async function list2(opts) {
59146
59240
  const workspace = await resolveWorkspace(opts);
@@ -59189,13 +59283,13 @@ async function resolve6(input) {
59189
59283
  throw e;
59190
59284
  }
59191
59285
  }
59192
- async function run2(opts, path5) {
59286
+ async function run2(opts, path6) {
59193
59287
  const workspace = await resolveWorkspace(opts);
59194
59288
  await requireLogin(opts);
59195
59289
  const input = opts.data ? await resolve6(opts.data) : {};
59196
59290
  const id = await runScriptByPath({
59197
59291
  workspace: workspace.workspaceId,
59198
- path: path5,
59292
+ path: path6,
59199
59293
  requestBody: input
59200
59294
  });
59201
59295
  if (!opts.silent) {
@@ -59287,12 +59381,12 @@ async function track_job(workspace, id) {
59287
59381
  info("Job appears to have completed, but no data can be retrieved");
59288
59382
  }
59289
59383
  }
59290
- async function show(opts, path5) {
59384
+ async function show(opts, path6) {
59291
59385
  const workspace = await resolveWorkspace(opts);
59292
59386
  await requireLogin(opts);
59293
59387
  const s = await getScriptByPath({
59294
59388
  workspace: workspace.workspaceId,
59295
- path: path5
59389
+ path: path6
59296
59390
  });
59297
59391
  info(colors.underline(s.path));
59298
59392
  if (s.description)
@@ -59300,12 +59394,12 @@ async function show(opts, path5) {
59300
59394
  info("");
59301
59395
  info(s.content);
59302
59396
  }
59303
- async function get(opts, path5) {
59397
+ async function get(opts, path6) {
59304
59398
  const workspace = await resolveWorkspace(opts);
59305
59399
  await requireLogin(opts);
59306
59400
  const s = await getScriptByPath({
59307
59401
  workspace: workspace.workspaceId,
59308
- path: path5
59402
+ path: path6
59309
59403
  });
59310
59404
  if (opts.json) {
59311
59405
  console.log(JSON.stringify(s));
@@ -59381,7 +59475,7 @@ async function generateMetadata(opts, scriptPath) {
59381
59475
  } else {
59382
59476
  const ignore = await ignoreF(opts);
59383
59477
  const elems = await elementsToMap(await FSFSElement(process.cwd(), codebases, false), (p, isD) => {
59384
- return !isD && !exts.some((ext2) => p.endsWith(ext2)) || ignore(p, isD) || isFlowPath(p) || isAppPath(p) || isRawAppPath(p);
59478
+ return !isD && !exts.some((ext2) => p.endsWith(ext2)) || ignore(p, isD) || isFlowPath(p) || isAppPath(p) || isRawAppPath(p) || isScriptModulePath(p) && !isModuleEntryPoint(p);
59385
59479
  }, false, {});
59386
59480
  let hasAny = false;
59387
59481
  info("Generating metadata for all stale scripts:");
@@ -59430,6 +59524,9 @@ async function preview(opts, filePath) {
59430
59524
  const language = inferContentTypeFromFilePath(filePath, opts?.defaultTs);
59431
59525
  const content = await readFile5(filePath, "utf-8");
59432
59526
  const input = opts.data ? await resolve6(opts.data) : {};
59527
+ const isFolderLayout = isModuleEntryPoint(filePath);
59528
+ const moduleFolderPath = isFolderLayout ? path5.dirname(filePath) : filePath.substring(0, filePath.indexOf(".")) + getModuleFolderSuffix();
59529
+ const modules = await readModulesFromDisk(moduleFolderPath, opts?.defaultTs, isFolderLayout);
59433
59530
  const codebase = language == "bun" ? findCodebase(filePath, codebases) : undefined;
59434
59531
  let bundledContent = undefined;
59435
59532
  let isTar = false;
@@ -59553,7 +59650,8 @@ async function preview(opts, filePath) {
59553
59650
  content,
59554
59651
  path: filePath.substring(0, filePath.indexOf(".")).replaceAll(SEP4, "/"),
59555
59652
  args: input,
59556
- language
59653
+ language,
59654
+ modules: modules ?? undefined
59557
59655
  }
59558
59656
  });
59559
59657
  if (opts.silent) {
@@ -59623,7 +59721,7 @@ var init_script = __esm(async () => {
59623
59721
  // src/commands/lint/lint.ts
59624
59722
  import { stat as stat4, readdir as readdir2 } from "node:fs/promises";
59625
59723
  import process12 from "node:process";
59626
- import * as path5 from "node:path";
59724
+ import * as path6 from "node:path";
59627
59725
  import { sep as SEP5 } from "node:path";
59628
59726
  function normalizePath(p) {
59629
59727
  return p.replaceAll(SEP5, "/");
@@ -59682,7 +59780,7 @@ async function isLockResolved(lockValue, baseDir) {
59682
59780
  return true;
59683
59781
  }
59684
59782
  async function checkInlineFile(relativePath, baseDir) {
59685
- const fullPath = path5.join(baseDir, relativePath.trim());
59783
+ const fullPath = path6.join(baseDir, relativePath.trim());
59686
59784
  try {
59687
59785
  const s = await stat4(fullPath);
59688
59786
  return s.size > 0;
@@ -59772,7 +59870,7 @@ async function checkRawAppRunnables(backendDir, rawAppYamlPath, defaultTs) {
59772
59870
  continue;
59773
59871
  const runnableId = fileName.replace(".yaml", "");
59774
59872
  processedIds.add(runnableId);
59775
- const filePath = path5.join(backendDir, fileName);
59873
+ const filePath = path6.join(backendDir, fileName);
59776
59874
  let runnable;
59777
59875
  try {
59778
59876
  runnable = await yamlParseFile(filePath);
@@ -59790,7 +59888,7 @@ async function checkRawAppRunnables(backendDir, rawAppYamlPath, defaultTs) {
59790
59888
  }
59791
59889
  if (!language || !languageNeedsLock(language))
59792
59890
  continue;
59793
- const lockFile = path5.join(backendDir, `${runnableId}.lock`);
59891
+ const lockFile = path6.join(backendDir, `${runnableId}.lock`);
59794
59892
  let hasLock = false;
59795
59893
  try {
59796
59894
  const s = await stat4(lockFile);
@@ -59837,7 +59935,7 @@ async function checkRawAppRunnables(backendDir, rawAppYamlPath, defaultTs) {
59837
59935
  }
59838
59936
  if (!languageNeedsLock(language))
59839
59937
  continue;
59840
- const lockFile = path5.join(backendDir, `${runnableId}.lock`);
59938
+ const lockFile = path6.join(backendDir, `${runnableId}.lock`);
59841
59939
  let hasLock = false;
59842
59940
  try {
59843
59941
  const s = await stat4(lockFile);
@@ -59857,7 +59955,7 @@ async function checkRawAppRunnables(backendDir, rawAppYamlPath, defaultTs) {
59857
59955
  }
59858
59956
  async function checkMissingLocks(opts, directory) {
59859
59957
  const initialCwd = process12.cwd();
59860
- const targetDirectory = directory ? path5.resolve(initialCwd, directory) : process12.cwd();
59958
+ const targetDirectory = directory ? path6.resolve(initialCwd, directory) : process12.cwd();
59861
59959
  const { ...syncOpts } = opts;
59862
59960
  const mergedOpts = await mergeConfigWithConfigFile(syncOpts);
59863
59961
  const ignore = await ignoreF(mergedOpts);
@@ -59881,19 +59979,19 @@ async function checkMissingLocks(opts, directory) {
59881
59979
  if (normalizedPath.endsWith("/flow.yaml") && normalizedPath.includes(flowSuffix + "/")) {
59882
59980
  flowYamls.push({
59883
59981
  normalizedPath,
59884
- fullPath: path5.join(targetDirectory, entry.path)
59982
+ fullPath: path6.join(targetDirectory, entry.path)
59885
59983
  });
59886
59984
  }
59887
59985
  if (normalizedPath.endsWith("/app.yaml") && normalizedPath.includes(appSuffix + "/")) {
59888
59986
  appYamls.push({
59889
59987
  normalizedPath,
59890
- fullPath: path5.join(targetDirectory, entry.path)
59988
+ fullPath: path6.join(targetDirectory, entry.path)
59891
59989
  });
59892
59990
  }
59893
59991
  if (normalizedPath.endsWith("/raw_app.yaml") && normalizedPath.includes(rawAppSuffix + "/")) {
59894
59992
  rawAppYamls.push({
59895
59993
  normalizedPath,
59896
- fullPath: path5.join(targetDirectory, entry.path)
59994
+ fullPath: path6.join(targetDirectory, entry.path)
59897
59995
  });
59898
59996
  }
59899
59997
  }
@@ -59902,14 +60000,14 @@ async function checkMissingLocks(opts, directory) {
59902
60000
  let language = null;
59903
60001
  for (const ext2 of exts) {
59904
60002
  try {
59905
- await stat4(path5.join(targetDirectory, basePath + ext2));
60003
+ await stat4(path6.join(targetDirectory, basePath + ext2));
59906
60004
  language = inferContentTypeFromFilePath(basePath + ext2, defaultTs);
59907
60005
  break;
59908
60006
  } catch {}
59909
60007
  }
59910
60008
  if (language && languageNeedsLock(language)) {
59911
60009
  try {
59912
- const metadata = await yamlParseFile(path5.join(targetDirectory, yamlPath));
60010
+ const metadata = await yamlParseFile(path6.join(targetDirectory, yamlPath));
59913
60011
  const lockResolved = await isLockResolved(metadata?.lock, targetDirectory);
59914
60012
  if (!lockResolved) {
59915
60013
  issues.push({
@@ -59926,7 +60024,7 @@ async function checkMissingLocks(opts, directory) {
59926
60024
  }
59927
60025
  }
59928
60026
  for (const { normalizedPath: flowYamlPath, fullPath } of flowYamls) {
59929
- const flowDir = path5.dirname(fullPath);
60027
+ const flowDir = path6.dirname(fullPath);
59930
60028
  try {
59931
60029
  const flowFile = await yamlParseFile(fullPath);
59932
60030
  if (!flowFile?.value?.modules)
@@ -59951,7 +60049,7 @@ async function checkMissingLocks(opts, directory) {
59951
60049
  }
59952
60050
  }
59953
60051
  for (const { normalizedPath: appYamlPath, fullPath } of appYamls) {
59954
- const appDir = path5.dirname(fullPath);
60052
+ const appDir = path6.dirname(fullPath);
59955
60053
  try {
59956
60054
  const appFile = await yamlParseFile(fullPath);
59957
60055
  if (!appFile?.value)
@@ -59976,8 +60074,8 @@ async function checkMissingLocks(opts, directory) {
59976
60074
  }
59977
60075
  }
59978
60076
  for (const { normalizedPath: rawAppYamlPath, fullPath } of rawAppYamls) {
59979
- const rawAppDir = path5.dirname(fullPath);
59980
- const backendDir = path5.join(rawAppDir, "backend");
60077
+ const rawAppDir = path6.dirname(fullPath);
60078
+ const backendDir = path6.join(rawAppDir, "backend");
59981
60079
  try {
59982
60080
  await stat4(backendDir);
59983
60081
  } catch {
@@ -59994,7 +60092,7 @@ async function checkMissingLocks(opts, directory) {
59994
60092
  }
59995
60093
  async function runLint(opts, directory) {
59996
60094
  const initialCwd = process12.cwd();
59997
- const explicitTargetDirectory = directory ? path5.resolve(initialCwd, directory) : undefined;
60095
+ const explicitTargetDirectory = directory ? path6.resolve(initialCwd, directory) : undefined;
59998
60096
  const { json: _json, ...syncOpts } = opts;
59999
60097
  const mergedOpts = await mergeConfigWithConfigFile(syncOpts);
60000
60098
  const targetDirectory = explicitTargetDirectory ?? process12.cwd();
@@ -60256,11 +60354,11 @@ async function list3(opts) {
60256
60354
  new Table2().header(["Path", "Resource Type"]).padding(2).border(true).body(total.map((x) => [x.path, x.resource_type])).render();
60257
60355
  }
60258
60356
  }
60259
- async function newResource(opts, path6) {
60260
- if (!validatePath(path6)) {
60357
+ async function newResource(opts, path7) {
60358
+ if (!validatePath(path7)) {
60261
60359
  return;
60262
60360
  }
60263
- const filePath = path6 + ".resource.yaml";
60361
+ const filePath = path7 + ".resource.yaml";
60264
60362
  try {
60265
60363
  await stat5(filePath);
60266
60364
  throw new Error("File already exists: " + filePath);
@@ -60279,12 +60377,12 @@ async function newResource(opts, path6) {
60279
60377
  });
60280
60378
  info(colors.green(`Created ${filePath}`));
60281
60379
  }
60282
- async function get2(opts, path6) {
60380
+ async function get2(opts, path7) {
60283
60381
  const workspace = await resolveWorkspace(opts);
60284
60382
  await requireLogin(opts);
60285
60383
  const r = await getResource({
60286
60384
  workspace: workspace.workspaceId,
60287
- path: path6
60385
+ path: path7
60288
60386
  });
60289
60387
  if (opts.json) {
60290
60388
  console.log(JSON.stringify(r));
@@ -60436,11 +60534,11 @@ var init_path_assigner = __esm(() => {
60436
60534
  // windmill-utils-internal/src/inline-scripts/extractor.ts
60437
60535
  function extractRawscriptInline(id, summary, rawscript, mapping, separator, assigner) {
60438
60536
  const [basePath, ext2] = assigner.assignPath(summary ?? id, rawscript.language);
60439
- const path6 = mapping[id] ?? basePath + ext2;
60537
+ const path7 = mapping[id] ?? basePath + ext2;
60440
60538
  const language = rawscript.language;
60441
60539
  const content = rawscript.content;
60442
- const r = [{ path: path6, content, language, is_lock: false }];
60443
- rawscript.content = "!inline " + path6.replaceAll(separator, "/");
60540
+ const r = [{ path: path7, content, language, is_lock: false }];
60541
+ rawscript.content = "!inline " + path7.replaceAll(separator, "/");
60444
60542
  const lock = rawscript.lock;
60445
60543
  if (lock && lock != "") {
60446
60544
  const lockPath = basePath + "lock";
@@ -60487,13 +60585,13 @@ async function replaceRawscriptInline(id, rawscript, fileReader, logger, separat
60487
60585
  if (!rawscript.content || !rawscript.content.startsWith("!inline")) {
60488
60586
  return;
60489
60587
  }
60490
- const path6 = rawscript.content.split(" ")[1];
60491
- const pathSuffix = path6.split(".").slice(1).join(".");
60588
+ const path7 = rawscript.content.split(" ")[1];
60589
+ const pathSuffix = path7.split(".").slice(1).join(".");
60492
60590
  const newPath = id + "." + pathSuffix;
60493
60591
  try {
60494
- rawscript.content = await fileReader(path6);
60592
+ rawscript.content = await fileReader(path7);
60495
60593
  } catch {
60496
- logger.error(`Script file ${path6} not found`);
60594
+ logger.error(`Script file ${path7} not found`);
60497
60595
  try {
60498
60596
  rawscript.content = await fileReader(newPath);
60499
60597
  } catch {
@@ -60501,7 +60599,7 @@ async function replaceRawscriptInline(id, rawscript, fileReader, logger, separat
60501
60599
  }
60502
60600
  }
60503
60601
  const lock = rawscript.lock;
60504
- if (removeLocks && removeLocks.includes(path6)) {
60602
+ if (removeLocks && removeLocks.includes(path7)) {
60505
60603
  rawscript.lock = undefined;
60506
60604
  } else if (lock && typeof lock === "string" && lock.trimStart().startsWith("!inline ")) {
60507
60605
  const lockPath = lock.split(" ")[1];
@@ -60547,11 +60645,11 @@ async function replaceInlineScripts(modules, fileReader, logger = {
60547
60645
  }
60548
60646
 
60549
60647
  // src/commands/flow/flow_metadata.ts
60550
- import * as path6 from "node:path";
60648
+ import * as path7 from "node:path";
60551
60649
  import { sep as SEP7 } from "node:path";
60552
60650
  import { readFile as readFile7 } from "node:fs/promises";
60553
60651
  async function generateFlowHash(rawWorkspaceDependencies, folder, defaultTs) {
60554
- const elems = await FSFSElement(path6.join(process.cwd(), folder), [], true);
60652
+ const elems = await FSFSElement(path7.join(process.cwd(), folder), [], true);
60555
60653
  const hashes = {};
60556
60654
  for await (const f of elems.getChildren()) {
60557
60655
  if (exts.some((e) => f.path.endsWith(e))) {
@@ -60587,18 +60685,18 @@ async function generateFlowLockInternal(folder, dryRun, workspace, opts, justUpd
60587
60685
  }
60588
60686
  let changedScripts = [];
60589
60687
  if (!justUpdateMetadataLock) {
60590
- for (const [path7, hash2] of Object.entries(hashes)) {
60591
- if (path7 == TOP_HASH) {
60688
+ for (const [path8, hash2] of Object.entries(hashes)) {
60689
+ if (path8 == TOP_HASH) {
60592
60690
  continue;
60593
60691
  }
60594
- if (!await checkifMetadataUptodate(folder, hash2, conf, path7)) {
60595
- changedScripts.push(path7);
60692
+ if (!await checkifMetadataUptodate(folder, hash2, conf, path8)) {
60693
+ changedScripts.push(path8);
60596
60694
  }
60597
60695
  }
60598
60696
  if (!noStaleMessage) {
60599
60697
  info(`Recomputing locks of ${changedScripts.join(", ")} in ${folder}`);
60600
60698
  }
60601
- const fileReader = async (path7) => await readFile7(folder + SEP7 + path7, "utf-8");
60699
+ const fileReader = async (path8) => await readFile7(folder + SEP7 + path8, "utf-8");
60602
60700
  await replaceInlineScripts(flowValue.value.modules, fileReader, exports_log, folder + SEP7, SEP7, changedScripts);
60603
60701
  if (flowValue.value.failure_module) {
60604
60702
  await replaceInlineScripts([flowValue.value.failure_module], fileReader, exports_log, folder + SEP7, SEP7, changedScripts);
@@ -60624,8 +60722,8 @@ async function generateFlowLockInternal(folder, dryRun, workspace, opts, justUpd
60624
60722
  }
60625
60723
  hashes = await generateFlowHash(filteredDeps, folder, opts.defaultTs);
60626
60724
  await clearGlobalLock(folder);
60627
- for (const [path7, hash2] of Object.entries(hashes)) {
60628
- await updateMetadataGlobalLock(folder, hash2, path7);
60725
+ for (const [path8, hash2] of Object.entries(hashes)) {
60726
+ await updateMetadataGlobalLock(folder, hash2, path8);
60629
60727
  }
60630
60728
  if (!noStaleMessage) {
60631
60729
  info(colors.green(`Flow ${remote_path} lockfiles updated`));
@@ -60740,7 +60838,7 @@ __export(exports_sync, {
60740
60838
  FSFSElement: () => FSFSElement
60741
60839
  });
60742
60840
  import { readFile as readFile8, writeFile as writeFile6, readdir as readdir4, stat as stat6, rm, copyFile, mkdir as mkdir3 } from "node:fs/promises";
60743
- import * as path7 from "node:path";
60841
+ import * as path8 from "node:path";
60744
60842
  import { sep as SEP8 } from "node:path";
60745
60843
  function mergeCliWithEffectiveOptions(cliOpts, effectiveOpts) {
60746
60844
  return Object.assign({}, effectiveOpts, cliOpts);
@@ -60748,8 +60846,8 @@ function mergeCliWithEffectiveOptions(cliOpts, effectiveOpts) {
60748
60846
  async function resolveEffectiveSyncOptions(workspace, localConfig, promotion, branchOverride) {
60749
60847
  return await getEffectiveSettings(localConfig, promotion, false, false, branchOverride);
60750
60848
  }
60751
- function findCodebase(path8, codebases) {
60752
- if (!path8.endsWith(".ts")) {
60849
+ function findCodebase(path9, codebases) {
60850
+ if (!path9.endsWith(".ts")) {
60753
60851
  return;
60754
60852
  }
60755
60853
  for (const c of codebases) {
@@ -60765,7 +60863,7 @@ function findCodebase(path8, codebases) {
60765
60863
  if (included) {
60766
60864
  break;
60767
60865
  }
60768
- if (minimatch(path8, r)) {
60866
+ if (minimatch(path9, r)) {
60769
60867
  included = true;
60770
60868
  }
60771
60869
  }
@@ -60773,7 +60871,7 @@ function findCodebase(path8, codebases) {
60773
60871
  c.excludes = [c.excludes];
60774
60872
  }
60775
60873
  for (const r of c.excludes ?? []) {
60776
- if (minimatch(path8, r)) {
60874
+ if (minimatch(path9, r)) {
60777
60875
  excluded = true;
60778
60876
  }
60779
60877
  }
@@ -60782,13 +60880,13 @@ function findCodebase(path8, codebases) {
60782
60880
  }
60783
60881
  }
60784
60882
  }
60785
- async function addCodebaseDigestIfRelevant(path8, content, codebases, ignoreCodebaseChanges) {
60786
- const isScript = path8.endsWith(".script.yaml");
60883
+ async function addCodebaseDigestIfRelevant(path9, content, codebases, ignoreCodebaseChanges) {
60884
+ const isScript = path9.endsWith(".script.yaml");
60787
60885
  if (!isScript) {
60788
60886
  return content;
60789
60887
  }
60790
60888
  let isTs = true;
60791
- const replacedPath = path8.replace(".script.yaml", ".ts");
60889
+ const replacedPath = path9.replace(".script.yaml", ".ts");
60792
60890
  try {
60793
60891
  await stat6(replacedPath);
60794
60892
  } catch {
@@ -60802,9 +60900,9 @@ async function addCodebaseDigestIfRelevant(path8, content, codebases, ignoreCode
60802
60900
  if (c) {
60803
60901
  let parsed;
60804
60902
  try {
60805
- parsed = yamlParseContent(path8, content);
60903
+ parsed = yamlParseContent(path9, content);
60806
60904
  } catch (error2) {
60807
- error(`Failed to parse YAML content for codebase digest at path: ${path8}`);
60905
+ error(`Failed to parse YAML content for codebase digest at path: ${path9}`);
60808
60906
  throw error2;
60809
60907
  }
60810
60908
  if (parsed && typeof parsed == "object") {
@@ -60816,7 +60914,7 @@ async function addCodebaseDigestIfRelevant(path8, content, codebases, ignoreCode
60816
60914
  parsed["lock"] = "";
60817
60915
  return import_yaml10.stringify(parsed, yamlOptions);
60818
60916
  } else {
60819
- throw Error(`Expected local yaml ${path8} to be an object, found: ${content} instead`);
60917
+ throw Error(`Expected local yaml ${path9} to be an object, found: ${content} instead`);
60820
60918
  }
60821
60919
  }
60822
60920
  }
@@ -60833,7 +60931,7 @@ async function FSFSElement(p, codebases, ignoreCodebaseChanges) {
60833
60931
  try {
60834
60932
  const entries = await readdir4(localP, { withFileTypes: true });
60835
60933
  for (const e of entries) {
60836
- yield _internal_element(path7.join(localP, e.name), e.isDirectory(), codebases2);
60934
+ yield _internal_element(path8.join(localP, e.name), e.isDirectory(), codebases2);
60837
60935
  }
60838
60936
  } catch (e) {
60839
60937
  warn(`Error reading dir: ${localP}, ${e}`);
@@ -61071,6 +61169,24 @@ async function findFilesetResourceFile(changePath) {
61071
61169
  throw new Error(`No resource metadata file found for fileset resource: ${changePath}`);
61072
61170
  }
61073
61171
  function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, resourceTypeToIsFileset, ignoreCodebaseChanges) {
61172
+ let _moduleScriptPaths = null;
61173
+ async function getModuleScriptPaths() {
61174
+ if (_moduleScriptPaths === null) {
61175
+ _moduleScriptPaths = new Set;
61176
+ for (const filename in zip.files) {
61177
+ if (filename.endsWith(".script.json") && !zip.files[filename].dir) {
61178
+ try {
61179
+ const content = await zip.files[filename].async("text");
61180
+ const parsed = JSON.parse(content);
61181
+ if (parsed.modules && Object.keys(parsed.modules).length > 0) {
61182
+ _moduleScriptPaths.add(filename.slice(0, -".script.json".length));
61183
+ }
61184
+ } catch {}
61185
+ }
61186
+ }
61187
+ }
61188
+ return _moduleScriptPaths;
61189
+ }
61074
61190
  async function _internal_file(p, f) {
61075
61191
  const kind = isFlowMetadataFile(p) ? "flow" : isAppMetadataFile(p) ? "app" : isRawAppMetadataFile(p) ? "raw_app" : p.endsWith(".script.json") ? "script" : p.endsWith(".resource.json") ? "resource" : p.startsWith("dependencies/") ? "dependencies" : "other";
61076
61192
  const isJson = p.endsWith(".json");
@@ -61087,7 +61203,20 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61087
61203
  return useYaml && isJson ? p.replaceAll(".json", ".yaml") : p;
61088
61204
  }
61089
61205
  }
61090
- const finalPath = transformPath();
61206
+ let finalPath = transformPath();
61207
+ if (kind == "other" && exts.some((ext2) => p.endsWith(ext2))) {
61208
+ const normalizedP = p.replace(/^\.[\\/]/, "");
61209
+ const moduleScripts = await getModuleScriptPaths();
61210
+ for (const basePath of moduleScripts) {
61211
+ if (normalizedP.startsWith(basePath + ".")) {
61212
+ const ext2 = normalizedP.slice(basePath.length);
61213
+ const dir = path8.dirname(finalPath);
61214
+ const base = path8.basename(basePath);
61215
+ finalPath = path8.join(dir, base + getModuleFolderSuffix(), "script" + ext2);
61216
+ break;
61217
+ }
61218
+ }
61219
+ }
61091
61220
  const r = [
61092
61221
  {
61093
61222
  isDirectory: kind == "flow" || kind == "app" || kind == "raw_app",
@@ -61118,7 +61247,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61118
61247
  for (const s of inlineScripts) {
61119
61248
  yield {
61120
61249
  isDirectory: false,
61121
- path: path7.join(finalPath, s.path),
61250
+ path: path8.join(finalPath, s.path),
61122
61251
  async* getChildren() {},
61123
61252
  async getContentText() {
61124
61253
  return s.content;
@@ -61127,7 +61256,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61127
61256
  }
61128
61257
  yield {
61129
61258
  isDirectory: false,
61130
- path: path7.join(finalPath, "flow.yaml"),
61259
+ path: path8.join(finalPath, "flow.yaml"),
61131
61260
  async* getChildren() {},
61132
61261
  async getContentText() {
61133
61262
  return import_yaml10.stringify(flow, yamlOptions);
@@ -61151,7 +61280,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61151
61280
  for (const s of inlineScripts) {
61152
61281
  yield {
61153
61282
  isDirectory: false,
61154
- path: path7.join(finalPath, s.path),
61283
+ path: path8.join(finalPath, s.path),
61155
61284
  async* getChildren() {},
61156
61285
  async getContentText() {
61157
61286
  return s.content;
@@ -61164,7 +61293,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61164
61293
  app.policy = undefined;
61165
61294
  yield {
61166
61295
  isDirectory: false,
61167
- path: path7.join(finalPath, "app.yaml"),
61296
+ path: path8.join(finalPath, "app.yaml"),
61168
61297
  async* getChildren() {},
61169
61298
  async getContentText() {
61170
61299
  return import_yaml10.stringify(app, yamlOptions);
@@ -61219,7 +61348,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61219
61348
  }
61220
61349
  yield {
61221
61350
  isDirectory: false,
61222
- path: path7.join(finalPath, filePath.substring(1)),
61351
+ path: path8.join(finalPath, filePath.substring(1)),
61223
61352
  async* getChildren() {},
61224
61353
  async getContentText() {
61225
61354
  if (typeof content !== "string") {
@@ -61236,7 +61365,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61236
61365
  for (const s of inlineScripts) {
61237
61366
  yield {
61238
61367
  isDirectory: false,
61239
- path: path7.join(finalPath, APP_BACKEND_FOLDER, s.path),
61368
+ path: path8.join(finalPath, APP_BACKEND_FOLDER, s.path),
61240
61369
  async* getChildren() {},
61241
61370
  async getContentText() {
61242
61371
  return s.content;
@@ -61272,7 +61401,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61272
61401
  }
61273
61402
  yield {
61274
61403
  isDirectory: false,
61275
- path: path7.join(finalPath, APP_BACKEND_FOLDER, `${runnableId}.yaml`),
61404
+ path: path8.join(finalPath, APP_BACKEND_FOLDER, `${runnableId}.yaml`),
61276
61405
  async* getChildren() {},
61277
61406
  async getContentText() {
61278
61407
  return import_yaml10.stringify(simplifiedRunnable, yamlOptions);
@@ -61286,7 +61415,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61286
61415
  delete rawApp?.["value"];
61287
61416
  yield {
61288
61417
  isDirectory: false,
61289
- path: path7.join(finalPath, "raw_app.yaml"),
61418
+ path: path8.join(finalPath, "raw_app.yaml"),
61290
61419
  async* getChildren() {},
61291
61420
  async getContentText() {
61292
61421
  return import_yaml10.stringify(rawApp, yamlOptions);
@@ -61294,7 +61423,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61294
61423
  };
61295
61424
  yield {
61296
61425
  isDirectory: false,
61297
- path: path7.join(finalPath, "DATATABLES.md"),
61426
+ path: path8.join(finalPath, "DATATABLES.md"),
61298
61427
  async* getChildren() {},
61299
61428
  async getContentText() {
61300
61429
  return generateDatatablesDocumentation(data3);
@@ -61312,8 +61441,14 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61312
61441
  error(`Failed to parse script.yaml at path: ${p}`);
61313
61442
  throw error2;
61314
61443
  }
61444
+ const hasModules = parsed["modules"] && Object.keys(parsed["modules"]).length > 0;
61315
61445
  if (parsed["lock"] && parsed["lock"] != "" && parsed["codebase"] == undefined) {
61316
- parsed["lock"] = "!inline " + removeSuffix(p.replaceAll(SEP8, "/"), ".json") + ".lock";
61446
+ if (hasModules) {
61447
+ const scriptBase = removeSuffix(removeSuffix(p.replaceAll(SEP8, "/"), ".json"), ".script");
61448
+ parsed["lock"] = "!inline " + scriptBase + getModuleFolderSuffix() + "/script.lock";
61449
+ } else {
61450
+ parsed["lock"] = "!inline " + removeSuffix(p.replaceAll(SEP8, "/"), ".json") + ".lock";
61451
+ }
61317
61452
  } else if (parsed["lock"] == "") {
61318
61453
  parsed["lock"] = "";
61319
61454
  } else {
@@ -61322,6 +61457,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61322
61457
  if (ignoreCodebaseChanges && parsed["codebase"]) {
61323
61458
  parsed["codebase"] = undefined;
61324
61459
  }
61460
+ delete parsed["modules"];
61325
61461
  return useYaml ? import_yaml10.stringify(parsed, yamlOptions) : JSON.stringify(parsed, null, 2);
61326
61462
  }
61327
61463
  if (kind == "resource") {
@@ -61364,16 +61500,56 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61364
61500
  throw error2;
61365
61501
  }
61366
61502
  const lock = parsed["lock"];
61503
+ const scriptModules = parsed["modules"];
61504
+ const hasModules = scriptModules && Object.keys(scriptModules).length > 0;
61505
+ const metaExt = useYaml ? ".yaml" : ".json";
61506
+ const scriptBasePath = removeSuffix(removeSuffix(finalPath, metaExt), ".script");
61507
+ const moduleFolderPath = scriptBasePath + getModuleFolderSuffix();
61508
+ if (hasModules) {
61509
+ r[0].path = path8.join(moduleFolderPath, "script" + metaExt);
61510
+ }
61367
61511
  if (lock && lock != "") {
61368
61512
  r.push({
61369
61513
  isDirectory: false,
61370
- path: removeSuffix(finalPath, ".json") + ".lock",
61514
+ path: hasModules ? path8.join(moduleFolderPath, "script.lock") : removeSuffix(finalPath, metaExt) + ".lock",
61371
61515
  async* getChildren() {},
61372
61516
  async getContentText() {
61373
61517
  return lock;
61374
61518
  }
61375
61519
  });
61376
61520
  }
61521
+ if (hasModules) {
61522
+ r.push({
61523
+ isDirectory: true,
61524
+ path: moduleFolderPath,
61525
+ async* getChildren() {
61526
+ for (const [relPath, mod] of Object.entries(scriptModules)) {
61527
+ yield {
61528
+ isDirectory: false,
61529
+ path: path8.join(moduleFolderPath, relPath),
61530
+ async* getChildren() {},
61531
+ async getContentText() {
61532
+ return mod.content;
61533
+ }
61534
+ };
61535
+ if (mod.lock) {
61536
+ const baseName = relPath.replace(/\.[^.]+$/, "");
61537
+ yield {
61538
+ isDirectory: false,
61539
+ path: path8.join(moduleFolderPath, baseName + ".lock"),
61540
+ async* getChildren() {},
61541
+ async getContentText() {
61542
+ return mod.lock;
61543
+ }
61544
+ };
61545
+ }
61546
+ }
61547
+ },
61548
+ async getContentText() {
61549
+ throw new Error("Cannot get content of directory");
61550
+ }
61551
+ });
61552
+ }
61377
61553
  }
61378
61554
  if (kind == "resource") {
61379
61555
  const content = await f.async("text");
@@ -61397,7 +61573,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61397
61573
  if (typeof fileContent === "string") {
61398
61574
  yield {
61399
61575
  isDirectory: false,
61400
- path: path7.join(filesetBasePath, relPath),
61576
+ path: path8.join(filesetBasePath, relPath),
61401
61577
  async* getChildren() {},
61402
61578
  async getContentText() {
61403
61579
  return fileContent;
@@ -61433,7 +61609,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, re
61433
61609
  async* getChildren() {
61434
61610
  for (const filename in zip2.files) {
61435
61611
  const file = zip2.files[filename];
61436
- const totalPath = path7.join(p, filename);
61612
+ const totalPath = path8.join(p, filename);
61437
61613
  if (file.dir) {
61438
61614
  const e = zip2.folder(file.name);
61439
61615
  yield _internal_folder(totalPath, e);
@@ -61492,11 +61668,15 @@ async function elementsToMap(els, ignore, json, skips, specificItems, branchOver
61492
61668
  if (entry.isDirectory || entry.ignored) {
61493
61669
  continue;
61494
61670
  }
61495
- const path8 = entry.path;
61496
- if (!isFileResource(path8) && !isFilesetResource(path8) && !isRawAppFile(path8) && !isWorkspaceDependencies(path8)) {
61497
- if (json && path8.endsWith(".yaml"))
61671
+ const path9 = entry.path;
61672
+ if (isScriptModulePath(path9)) {
61673
+ map[path9] = await entry.getContentText();
61674
+ continue;
61675
+ }
61676
+ if (!isFileResource(path9) && !isFilesetResource(path9) && !isRawAppFile(path9) && !isWorkspaceDependencies(path9)) {
61677
+ if (json && path9.endsWith(".yaml"))
61498
61678
  continue;
61499
- if (!json && path8.endsWith(".json"))
61679
+ if (!json && path9.endsWith(".json"))
61500
61680
  continue;
61501
61681
  if (![
61502
61682
  "json",
@@ -61517,39 +61697,39 @@ async function elementsToMap(els, ignore, json, skips, specificItems, branchOver
61517
61697
  "nu",
61518
61698
  "java",
61519
61699
  "rb"
61520
- ].includes(path8.split(".").pop() ?? "")) {
61700
+ ].includes(path9.split(".").pop() ?? "")) {
61521
61701
  continue;
61522
61702
  }
61523
61703
  }
61524
- if (isRawAppFile(path8)) {
61525
- const suffix = path8.split(getFolderSuffix("raw_app") + SEP8).pop();
61704
+ if (isRawAppFile(path9)) {
61705
+ const suffix = path9.split(getFolderSuffix("raw_app") + SEP8).pop();
61526
61706
  if (suffix?.startsWith("dist/") || suffix == "wmill.d.ts" || suffix == "package-lock.json" || suffix == "DATATABLES.md") {
61527
61707
  continue;
61528
61708
  }
61529
61709
  }
61530
- if (skips.skipResources && (isFileResource(path8) || isFilesetResource(path8)))
61710
+ if (skips.skipResources && (isFileResource(path9) || isFilesetResource(path9)))
61531
61711
  continue;
61532
61712
  const ext2 = json ? ".json" : ".yaml";
61533
- if (!skips.includeSchedules && path8.endsWith(".schedule" + ext2))
61713
+ if (!skips.includeSchedules && path9.endsWith(".schedule" + ext2))
61534
61714
  continue;
61535
- if (!skips.includeTriggers && (path8.endsWith(".http_trigger" + ext2) || path8.endsWith(".websocket_trigger" + ext2) || path8.endsWith(".kafka_trigger" + ext2) || path8.endsWith(".nats_trigger" + ext2) || path8.endsWith(".postgres_trigger" + ext2) || path8.endsWith(".mqtt_trigger" + ext2) || path8.endsWith(".sqs_trigger" + ext2) || path8.endsWith(".gcp_trigger" + ext2) || path8.endsWith(".email_trigger" + ext2) || path8.endsWith("_native_trigger" + ext2))) {
61715
+ if (!skips.includeTriggers && (path9.endsWith(".http_trigger" + ext2) || path9.endsWith(".websocket_trigger" + ext2) || path9.endsWith(".kafka_trigger" + ext2) || path9.endsWith(".nats_trigger" + ext2) || path9.endsWith(".postgres_trigger" + ext2) || path9.endsWith(".mqtt_trigger" + ext2) || path9.endsWith(".sqs_trigger" + ext2) || path9.endsWith(".gcp_trigger" + ext2) || path9.endsWith(".email_trigger" + ext2) || path9.endsWith("_native_trigger" + ext2))) {
61536
61716
  continue;
61537
61717
  }
61538
- if (!skips.includeUsers && path8.endsWith(".user" + ext2))
61718
+ if (!skips.includeUsers && path9.endsWith(".user" + ext2))
61539
61719
  continue;
61540
- if (!skips.includeGroups && path8.endsWith(".group" + ext2))
61720
+ if (!skips.includeGroups && path9.endsWith(".group" + ext2))
61541
61721
  continue;
61542
- if (!skips.includeSettings && path8 === "settings" + ext2)
61722
+ if (!skips.includeSettings && path9 === "settings" + ext2)
61543
61723
  continue;
61544
- if (!skips.includeKey && path8 === "encryption_key")
61724
+ if (!skips.includeKey && path9 === "encryption_key")
61545
61725
  continue;
61546
- if (skips.skipResources && path8.endsWith(".resource" + ext2))
61726
+ if (skips.skipResources && path9.endsWith(".resource" + ext2))
61547
61727
  continue;
61548
- if (skips.skipResourceTypes && path8.endsWith(".resource-type" + ext2)) {
61728
+ if (skips.skipResourceTypes && path9.endsWith(".resource-type" + ext2)) {
61549
61729
  continue;
61550
61730
  }
61551
61731
  try {
61552
- const fileType = getTypeStrFromPath(path8);
61732
+ const fileType = getTypeStrFromPath(path9);
61553
61733
  if (skips.skipVariables && fileType === "variable")
61554
61734
  continue;
61555
61735
  if (skips.skipScripts && fileType === "script")
@@ -61563,27 +61743,27 @@ async function elementsToMap(els, ignore, json, skips, specificItems, branchOver
61563
61743
  if (skips.skipWorkspaceDependencies && fileType === "workspace_dependencies")
61564
61744
  continue;
61565
61745
  } catch {}
61566
- if (specificItems && isBranchSpecificFile(path8)) {
61567
- if (!isCurrentBranchFile(path8, cachedBranch)) {
61746
+ if (specificItems && isBranchSpecificFile(path9)) {
61747
+ if (!isCurrentBranchFile(path9, cachedBranch)) {
61568
61748
  continue;
61569
61749
  }
61570
61750
  }
61571
61751
  const content = await entry.getContentText();
61572
- if (skips.skipSecrets && path8.endsWith(".variable" + ext2)) {
61752
+ if (skips.skipSecrets && path9.endsWith(".variable" + ext2)) {
61573
61753
  try {
61574
61754
  let o;
61575
61755
  if (json) {
61576
61756
  try {
61577
61757
  o = JSON.parse(content);
61578
61758
  } catch (error2) {
61579
- error(`Failed to parse JSON variable content at path: ${path8}`);
61759
+ error(`Failed to parse JSON variable content at path: ${path9}`);
61580
61760
  throw error2;
61581
61761
  }
61582
61762
  } else {
61583
61763
  try {
61584
- o = yamlParseContent(path8, content);
61764
+ o = yamlParseContent(path9, content);
61585
61765
  } catch (error2) {
61586
- error(`Failed to parse YAML variable content at path: ${path8}`);
61766
+ error(`Failed to parse YAML variable content at path: ${path9}`);
61587
61767
  throw error2;
61588
61768
  }
61589
61769
  }
@@ -61591,12 +61771,12 @@ async function elementsToMap(els, ignore, json, skips, specificItems, branchOver
61591
61771
  continue;
61592
61772
  }
61593
61773
  } catch (e) {
61594
- warn(`Error reading variable ${path8} to check for secrets`);
61774
+ warn(`Error reading variable ${path9} to check for secrets`);
61595
61775
  }
61596
61776
  }
61597
- if (cachedBranch && isCurrentBranchFile(path8, cachedBranch)) {
61777
+ if (cachedBranch && isCurrentBranchFile(path9, cachedBranch)) {
61598
61778
  const currentBranch = cachedBranch;
61599
- const basePath = fromBranchSpecificPath(path8, currentBranch);
61779
+ const basePath = fromBranchSpecificPath(path9, currentBranch);
61600
61780
  if (!isItemTypeConfigured(basePath, specificItems)) {
61601
61781
  continue;
61602
61782
  }
@@ -61605,14 +61785,14 @@ async function elementsToMap(els, ignore, json, skips, specificItems, branchOver
61605
61785
  }
61606
61786
  map[basePath] = content;
61607
61787
  processedBasePaths.add(basePath);
61608
- } else if (!isBranchSpecificFile(path8)) {
61609
- if (processedBasePaths.has(path8)) {
61788
+ } else if (!isBranchSpecificFile(path9)) {
61789
+ if (processedBasePaths.has(path9)) {
61610
61790
  continue;
61611
61791
  }
61612
- if (!isRemote && isSpecificItem(path8, specificItems)) {
61792
+ if (!isRemote && isSpecificItem(path9, specificItems)) {
61613
61793
  continue;
61614
61794
  }
61615
- map[path8] = content;
61795
+ map[path9] = content;
61616
61796
  }
61617
61797
  }
61618
61798
  return map;
@@ -61869,6 +62049,31 @@ async function addToChangedIfNotExists(p, tracker) {
61869
62049
  if (!tracker.rawApps.includes(folder)) {
61870
62050
  tracker.rawApps.push(folder);
61871
62051
  }
62052
+ } else if (isScriptModulePath(p)) {
62053
+ if (isModuleEntryPoint(p)) {
62054
+ if (!tracker.scripts.includes(p)) {
62055
+ tracker.scripts.push(p);
62056
+ }
62057
+ } else {
62058
+ const moduleSuffix = getModuleFolderSuffix() + "/";
62059
+ const idx = p.indexOf(moduleSuffix);
62060
+ if (idx !== -1) {
62061
+ const scriptBasePath = p.substring(0, idx);
62062
+ try {
62063
+ const contentPath = await findContentFile(scriptBasePath + getModuleFolderSuffix() + "/script.yaml");
62064
+ if (contentPath && !tracker.scripts.includes(contentPath)) {
62065
+ tracker.scripts.push(contentPath);
62066
+ }
62067
+ } catch {
62068
+ try {
62069
+ const contentPath = await findContentFile(scriptBasePath + ".script.yaml");
62070
+ if (contentPath && !tracker.scripts.includes(contentPath)) {
62071
+ tracker.scripts.push(contentPath);
62072
+ }
62073
+ } catch {}
62074
+ }
62075
+ }
62076
+ }
61872
62077
  } else {
61873
62078
  if (!tracker.scripts.includes(p)) {
61874
62079
  tracker.scripts.push(p);
@@ -61899,6 +62104,29 @@ async function buildTracker(changes) {
61899
62104
  }
61900
62105
  return tracker;
61901
62106
  }
62107
+ async function pushParentScriptForModule(modulePath, workspace, alreadySynced, message, opts, rawWorkspaceDependencies, codebases) {
62108
+ const moduleSuffix = getModuleFolderSuffix() + "/";
62109
+ const idx = modulePath.indexOf(moduleSuffix);
62110
+ if (idx === -1)
62111
+ return;
62112
+ const scriptBasePath = modulePath.substring(0, idx);
62113
+ const moduleFolderPath = scriptBasePath + getModuleFolderSuffix();
62114
+ try {
62115
+ const entryPoint = await findContentFile(moduleFolderPath + "/script.yaml");
62116
+ if (entryPoint) {
62117
+ await handleFile(entryPoint, workspace, alreadySynced, message, opts, rawWorkspaceDependencies, codebases);
62118
+ return;
62119
+ }
62120
+ } catch {}
62121
+ try {
62122
+ const contentPath = await findContentFile(scriptBasePath + ".script.yaml");
62123
+ if (contentPath) {
62124
+ await handleFile(contentPath, workspace, alreadySynced, message, opts, rawWorkspaceDependencies, codebases);
62125
+ }
62126
+ } catch {
62127
+ debug(`Could not find parent script for module: ${modulePath}`);
62128
+ }
62129
+ }
61902
62130
  async function pull(opts) {
61903
62131
  const originalCliOpts = { ...opts };
61904
62132
  opts = await mergeConfigWithConfigFile(opts);
@@ -61912,7 +62140,7 @@ async function pull(opts) {
61912
62140
  throw error2;
61913
62141
  }
61914
62142
  if (opts.stateful) {
61915
- await mkdir3(path7.join(process.cwd(), ".wmill"), { recursive: true });
62143
+ await mkdir3(path8.join(process.cwd(), ".wmill"), { recursive: true });
61916
62144
  }
61917
62145
  const workspace = await resolveWorkspace(opts, opts.branch);
61918
62146
  await requireLogin(opts);
@@ -61933,7 +62161,7 @@ async function pull(opts) {
61933
62161
  } catch {}
61934
62162
  const zipFile = await downloadZip(workspace, opts.plainSecrets, opts.skipVariables, opts.skipResources, opts.skipResourceTypes, opts.skipSecrets, opts.includeSchedules, opts.includeTriggers, opts.includeUsers, opts.includeGroups, opts.includeSettings, opts.includeKey, opts.skipWorkspaceDependencies, opts.defaultTs);
61935
62163
  const remote = ZipFSElement(zipFile, !opts.json, opts.defaultTs ?? "bun", resourceTypeToFormatExtension, resourceTypeToIsFileset, true);
61936
- const local = !opts.stateful ? await FSFSElement(process.cwd(), codebases, true) : await FSFSElement(path7.join(process.cwd(), ".wmill"), [], true);
62164
+ const local = !opts.stateful ? await FSFSElement(process.cwd(), codebases, true) : await FSFSElement(path8.join(process.cwd(), ".wmill"), [], true);
61937
62165
  const changes = await compareDynFSElement(remote, local, await ignoreF(opts), opts.json ?? false, opts, false, codebases, true, specificItems, opts.branch, true);
61938
62166
  info(`remote (${workspace.name}) -> local: ${changes.length} changes to apply`);
61939
62167
  if (opts.dryRun && opts.jsonOutput) {
@@ -61977,8 +62205,8 @@ async function pull(opts) {
61977
62205
  targetPath = branchSpecificPath;
61978
62206
  }
61979
62207
  }
61980
- const target = path7.join(process.cwd(), targetPath);
61981
- const stateTarget = path7.join(process.cwd(), ".wmill", targetPath);
62208
+ const target = path8.join(process.cwd(), targetPath);
62209
+ const stateTarget = path8.join(process.cwd(), ".wmill", targetPath);
61982
62210
  if (change.name === "edited") {
61983
62211
  if (opts.stateful) {
61984
62212
  try {
@@ -62011,13 +62239,13 @@ Both local and remote have been modified.`));
62011
62239
  }
62012
62240
  await writeFile6(target, change.after, "utf-8");
62013
62241
  if (opts.stateful) {
62014
- await mkdir3(path7.dirname(stateTarget), { recursive: true });
62242
+ await mkdir3(path8.dirname(stateTarget), { recursive: true });
62015
62243
  await copyFile(target, stateTarget);
62016
62244
  }
62017
62245
  } else if (change.name === "added") {
62018
- await mkdir3(path7.dirname(target), { recursive: true });
62246
+ await mkdir3(path8.dirname(target), { recursive: true });
62019
62247
  if (opts.stateful) {
62020
- await mkdir3(path7.dirname(stateTarget), { recursive: true });
62248
+ await mkdir3(path8.dirname(stateTarget), { recursive: true });
62021
62249
  info(`Adding ${getTypeStrFromPath(change.path)} ${targetPath}${targetPath !== change.path ? colors.gray(` (branch-specific override for ${change.path})`) : ""}`);
62022
62250
  }
62023
62251
  await writeFile6(target, change.content, "utf-8");
@@ -62199,7 +62427,7 @@ Push aborted: ${lockIssues.length} script(s) missing locks.`));
62199
62427
  resourceTypeToIsFileset = parsed.filesetMap;
62200
62428
  } catch {}
62201
62429
  const remote = ZipFSElement(await downloadZip(workspace, opts.plainSecrets, opts.skipVariables, opts.skipResources, opts.skipResourceTypes, opts.skipSecrets, opts.includeSchedules, opts.includeTriggers, opts.includeUsers, opts.includeGroups, opts.includeSettings, opts.includeKey, opts.skipWorkspaceDependencies, opts.defaultTs), !opts.json, opts.defaultTs ?? "bun", resourceTypeToFormatExtension, resourceTypeToIsFileset, false);
62202
- const local = await FSFSElement(path7.join(process.cwd(), ""), codebases, false);
62430
+ const local = await FSFSElement(path8.join(process.cwd(), ""), codebases, false);
62203
62431
  const changes = await compareDynFSElement(local, remote, await ignoreF(opts), opts.json ?? false, opts, true, codebases, false, specificItems, opts.branch, false);
62204
62432
  const rawWorkspaceDependencies = await getRawWorkspaceDependencies();
62205
62433
  const tracker = await buildTracker(changes);
@@ -62265,7 +62493,7 @@ Push aborted: ${lockIssues.length} script(s) missing locks.`));
62265
62493
  }
62266
62494
  for (const folderName of folderNames) {
62267
62495
  try {
62268
- await stat6(path7.join("f", folderName, "folder.meta.yaml"));
62496
+ await stat6(path8.join("f", folderName, "folder.meta.yaml"));
62269
62497
  } catch {
62270
62498
  missingFolders.push(folderName);
62271
62499
  }
@@ -62327,7 +62555,7 @@ ${folderList}
62327
62555
  let stateful = opts.stateful;
62328
62556
  if (stateful) {
62329
62557
  try {
62330
- await stat6(path7.join(process.cwd(), ".wmill"));
62558
+ await stat6(path8.join(process.cwd(), ".wmill"));
62331
62559
  } catch {
62332
62560
  stateful = false;
62333
62561
  }
@@ -62371,7 +62599,7 @@ ${folderList}
62371
62599
  let stateTarget = undefined;
62372
62600
  if (stateful) {
62373
62601
  try {
62374
- stateTarget = path7.join(process.cwd(), ".wmill", change.path);
62602
+ stateTarget = path8.join(process.cwd(), ".wmill", change.path);
62375
62603
  await stat6(stateTarget);
62376
62604
  } catch {
62377
62605
  stateTarget = undefined;
@@ -62388,9 +62616,15 @@ ${folderList}
62388
62616
  await writeFile6(stateTarget, change.after, "utf-8");
62389
62617
  }
62390
62618
  continue;
62619
+ } else if (isScriptModulePath(change.path)) {
62620
+ await pushParentScriptForModule(change.path, workspace, alreadySynced, opts.message, opts, rawWorkspaceDependencies, codebases);
62621
+ if (stateTarget) {
62622
+ await writeFile6(stateTarget, change.after, "utf-8");
62623
+ }
62624
+ continue;
62391
62625
  }
62392
62626
  if (stateTarget) {
62393
- await mkdir3(path7.dirname(stateTarget), { recursive: true });
62627
+ await mkdir3(path8.dirname(stateTarget), { recursive: true });
62394
62628
  info(`Editing ${getTypeStrFromPath(change.path)} ${change.path}`);
62395
62629
  }
62396
62630
  if (isFileResource(change.path)) {
@@ -62442,9 +62676,12 @@ ${folderList}
62442
62676
  continue;
62443
62677
  } else if (await handleFile(change.path, workspace, alreadySynced, opts.message, opts, rawWorkspaceDependencies, codebases)) {
62444
62678
  continue;
62679
+ } else if (isScriptModulePath(change.path)) {
62680
+ await pushParentScriptForModule(change.path, workspace, alreadySynced, opts.message, opts, rawWorkspaceDependencies, codebases);
62681
+ continue;
62445
62682
  }
62446
62683
  if (stateTarget) {
62447
- await mkdir3(path7.dirname(stateTarget), { recursive: true });
62684
+ await mkdir3(path8.dirname(stateTarget), { recursive: true });
62448
62685
  info(`Adding ${getTypeStrFromPath(change.path)} ${change.path}`);
62449
62686
  }
62450
62687
  const obj = parseFromPath(change.path, change.content);
@@ -62463,6 +62700,10 @@ ${folderList}
62463
62700
  if (change.path.endsWith(".lock")) {
62464
62701
  continue;
62465
62702
  }
62703
+ if (isScriptModulePath(change.path)) {
62704
+ await pushParentScriptForModule(change.path, workspace, alreadySynced, opts.message, opts, rawWorkspaceDependencies, codebases);
62705
+ continue;
62706
+ }
62466
62707
  const typ = getTypeStrFromPath(change.path);
62467
62708
  if (typ == "script") {
62468
62709
  info(`Archiving ${typ} ${change.path}`);
@@ -62721,6 +62962,9 @@ var import_yaml10, yamlOptions, isNotWmillFile = (p, isDirectory2) => {
62721
62962
  if (isDirectory2) {
62722
62963
  return !p.startsWith("u" + SEP8) && !p.startsWith("f" + SEP8) && !p.startsWith("g" + SEP8) && !p.startsWith("users" + SEP8) && !p.startsWith("groups" + SEP8) && !p.startsWith("dependencies" + SEP8);
62723
62964
  }
62965
+ if (isScriptModulePath(p)) {
62966
+ return false;
62967
+ }
62724
62968
  try {
62725
62969
  const typ = getTypeStrFromPath(p);
62726
62970
  if (typ == "resource-type" || typ == "settings" || typ == "encryption_key") {
@@ -62773,7 +63017,7 @@ var init_sync = __esm(async () => {
62773
63017
  aliasDuplicateObjects: false,
62774
63018
  singleQuote: true
62775
63019
  };
62776
- command6 = new Command().description("sync local with a remote workspaces or the opposite (push or pull)").action(() => info("2 actions available, pull and push. Use -h to display help.")).command("pull").description("Pull any remote changes and apply them locally.").option("--yes", "Pull without needing confirmation").option("--dry-run", "Show changes that would be pulled without actually pushing").option("--plain-secrets", "Pull secrets as plain text").option("--json", "Use JSON instead of YAML").option("--skip-variables", "Skip syncing variables (including secrets)").option("--skip-secrets", "Skip syncing only secrets variables").option("--skip-resources", "Skip syncing resources").option("--skip-resource-types", "Skip syncing resource types").option("--skip-scripts", "Skip syncing scripts").option("--skip-flows", "Skip syncing flows").option("--skip-apps", "Skip syncing apps").option("--skip-folders", "Skip syncing folders").option("--skip-workspace-dependencies", "Skip syncing workspace dependencies").option("--include-schedules", "Include syncing schedules").option("--include-triggers", "Include syncing triggers").option("--include-users", "Include syncing users").option("--include-groups", "Include syncing groups").option("--include-settings", "Include syncing workspace settings").option("--include-key", "Include workspace encryption key").option("--skip-branch-validation", "Skip git branch validation and prompts").option("--json-output", "Output results in JSON format").option("-i --includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string). Overrides wmill.yaml includes").option("-e --excludes <patterns:file[]>", "Comma separated patterns to specify which file to NOT take into account. Overrides wmill.yaml excludes").option("--extra-includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string). Useful to still take wmill.yaml into account and act as a second pattern to satisfy").option("--repository <repo:string>", "Specify repository path (e.g., u/user/repo) when multiple repositories exist").option("--promotion <branch:string>", "Use promotionOverrides from the specified branch instead of regular overrides").option("--branch <branch:string>", "Override the current git branch (works even outside a git repository)").action(pull).command("push").description("Push any local changes and apply them remotely.").option("--yes", "Push without needing confirmation").option("--dry-run", "Show changes that would be pushed without actually pushing").option("--plain-secrets", "Push secrets as plain text").option("--json", "Use JSON instead of YAML").option("--skip-variables", "Skip syncing variables (including secrets)").option("--skip-secrets", "Skip syncing only secrets variables").option("--skip-resources", "Skip syncing resources").option("--skip-resource-types", "Skip syncing resource types").option("--skip-scripts", "Skip syncing scripts").option("--skip-flows", "Skip syncing flows").option("--skip-apps", "Skip syncing apps").option("--skip-folders", "Skip syncing folders").option("--skip-workspace-dependencies", "Skip syncing workspace dependencies").option("--include-schedules", "Include syncing schedules").option("--include-triggers", "Include syncing triggers").option("--include-users", "Include syncing users").option("--include-groups", "Include syncing groups").option("--include-settings", "Include syncing workspace settings").option("--include-key", "Include workspace encryption key").option("--skip-branch-validation", "Skip git branch validation and prompts").option("--json-output", "Output results in JSON format").option("-i --includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string)").option("-e --excludes <patterns:file[]>", "Comma separated patterns to specify which file to NOT take into account.").option("--extra-includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string). Useful to still take wmill.yaml into account and act as a second pattern to satisfy").option("--message <message:string>", "Include a message that will be added to all scripts/flows/apps updated during this push").option("--parallel <number>", "Number of changes to process in parallel").option("--repository <repo:string>", "Specify repository path (e.g., u/user/repo) when multiple repositories exist").option("--branch <branch:string>", "Override the current git branch (works even outside a git repository)").option("--lint", "Run lint validation before pushing").option("--locks-required", "Fail if scripts or flow inline scripts that need locks have no locks").action(push3);
63020
+ command6 = new Command().description("sync local with a remote workspaces or the opposite (push or pull)").action(() => info("2 actions available, pull and push. Use -h to display help.")).command("pull").description("Pull any remote changes and apply them locally.").option("--yes", "Pull without needing confirmation").option("--dry-run", "Show changes that would be pulled without actually pushing").option("--plain-secrets", "Pull secrets as plain text").option("--json", "Use JSON instead of YAML").option("--skip-variables", "Skip syncing variables (including secrets)").option("--skip-secrets", "Skip syncing only secrets variables").option("--skip-resources", "Skip syncing resources").option("--skip-resource-types", "Skip syncing resource types").option("--skip-scripts", "Skip syncing scripts").option("--skip-flows", "Skip syncing flows").option("--skip-apps", "Skip syncing apps").option("--skip-folders", "Skip syncing folders").option("--skip-workspace-dependencies", "Skip syncing workspace dependencies").option("--include-schedules", "Include syncing schedules").option("--include-triggers", "Include syncing triggers").option("--include-users", "Include syncing users").option("--include-groups", "Include syncing groups").option("--include-settings", "Include syncing workspace settings").option("--include-key", "Include workspace encryption key").option("--skip-branch-validation", "Skip git branch validation and prompts").option("--json-output", "Output results in JSON format").option("-i --includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string). Overrides wmill.yaml includes").option("-e --excludes <patterns:file[]>", "Comma separated patterns to specify which file to NOT take into account. Overrides wmill.yaml excludes").option("--extra-includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string). Useful to still take wmill.yaml into account and act as a second pattern to satisfy").option("--repository <repo:string>", "Specify repository path (e.g., u/user/repo) when multiple repositories exist").option("--promotion <branch:string>", "Use promotionOverrides from the specified branch instead of regular overrides").option("--branch, --env <branch:string>", "Override the current git branch/environment (works even outside a git repository)").action(pull).command("push").description("Push any local changes and apply them remotely.").option("--yes", "Push without needing confirmation").option("--dry-run", "Show changes that would be pushed without actually pushing").option("--plain-secrets", "Push secrets as plain text").option("--json", "Use JSON instead of YAML").option("--skip-variables", "Skip syncing variables (including secrets)").option("--skip-secrets", "Skip syncing only secrets variables").option("--skip-resources", "Skip syncing resources").option("--skip-resource-types", "Skip syncing resource types").option("--skip-scripts", "Skip syncing scripts").option("--skip-flows", "Skip syncing flows").option("--skip-apps", "Skip syncing apps").option("--skip-folders", "Skip syncing folders").option("--skip-workspace-dependencies", "Skip syncing workspace dependencies").option("--include-schedules", "Include syncing schedules").option("--include-triggers", "Include syncing triggers").option("--include-users", "Include syncing users").option("--include-groups", "Include syncing groups").option("--include-settings", "Include syncing workspace settings").option("--include-key", "Include workspace encryption key").option("--skip-branch-validation", "Skip git branch validation and prompts").option("--json-output", "Output results in JSON format").option("-i --includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string)").option("-e --excludes <patterns:file[]>", "Comma separated patterns to specify which file to NOT take into account.").option("--extra-includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string). Useful to still take wmill.yaml into account and act as a second pattern to satisfy").option("--message <message:string>", "Include a message that will be added to all scripts/flows/apps updated during this push").option("--parallel <number>", "Number of changes to process in parallel").option("--repository <repo:string>", "Specify repository path (e.g., u/user/repo) when multiple repositories exist").option("--branch, --env <branch:string>", "Override the current git branch/environment (works even outside a git repository)").option("--lint", "Run lint validation before pushing").option("--locks-required", "Fail if scripts or flow inline scripts that need locks have no locks").action(push3);
62777
63021
  sync_default = command6;
62778
63022
  });
62779
63023
 
@@ -63004,7 +63248,8 @@ __export(exports_metadata, {
63004
63248
  });
63005
63249
  import { sep as SEP9 } from "node:path";
63006
63250
  import { readFile as readFile9, writeFile as writeFile7, stat as stat7, rm as rm2, readdir as readdir5 } from "node:fs/promises";
63007
- import { readFileSync as readFileSync3 } from "node:fs";
63251
+ import { readFileSync as readFileSync3, existsSync as existsSync4, readdirSync, statSync, writeFileSync as writeFileSync2 } from "node:fs";
63252
+ import * as path9 from "node:path";
63008
63253
  import { createRequire as createRequire2 } from "node:module";
63009
63254
  function loadParser(pkgName) {
63010
63255
  let p = _parserCache.get(pkgName);
@@ -63042,8 +63287,8 @@ async function getRawWorkspaceDependencies() {
63042
63287
  } catch {}
63043
63288
  return rawWorkspaceDeps;
63044
63289
  }
63045
- function workspaceDependenciesPathToLanguageAndFilename(path8) {
63046
- const relativePath = path8.replace("dependencies/", "");
63290
+ function workspaceDependenciesPathToLanguageAndFilename(path10) {
63291
+ const relativePath = path10.replace("dependencies/", "");
63047
63292
  for (const { filename, language } of workspaceDependenciesLanguages) {
63048
63293
  if (relativePath.endsWith(filename)) {
63049
63294
  return {
@@ -63090,20 +63335,48 @@ async function blueColor() {
63090
63335
  return isWin2 ? colors.black : colors.blue;
63091
63336
  }
63092
63337
  async function generateScriptMetadataInternal(scriptPath, workspace, opts, dryRun, noStaleMessage, rawWorkspaceDependencies, codebases, justUpdateMetadataLock) {
63093
- const remotePath = scriptPath.substring(0, scriptPath.indexOf(".")).replaceAll(SEP9, "/");
63338
+ const isFolderLayout = isModuleEntryPoint(scriptPath);
63339
+ const remotePath = isFolderLayout ? getScriptBasePathFromModulePath(scriptPath).replaceAll(SEP9, "/") : scriptPath.substring(0, scriptPath.indexOf(".")).replaceAll(SEP9, "/");
63094
63340
  const language = inferContentTypeFromFilePath(scriptPath, opts.defaultTs);
63095
63341
  const metadataWithType = await parseMetadataFile(remotePath, undefined);
63096
63342
  const scriptContent = await readFile9(scriptPath, "utf-8");
63097
63343
  const metadataContent = await readFile9(metadataWithType.path, "utf-8");
63098
63344
  const filteredRawWorkspaceDependencies = filterWorkspaceDependencies(rawWorkspaceDependencies, scriptContent, language);
63345
+ const moduleFolderPath = isFolderLayout ? path9.dirname(scriptPath) : scriptPath.substring(0, scriptPath.indexOf(".")) + getModuleFolderSuffix();
63346
+ const hasModules = existsSync4(moduleFolderPath) && statSync(moduleFolderPath).isDirectory();
63099
63347
  let hash2 = await generateScriptHash(filteredRawWorkspaceDependencies, scriptContent, metadataContent);
63100
- if (await checkifMetadataUptodate(remotePath, hash2, undefined)) {
63348
+ let moduleHashes = {};
63349
+ if (hasModules) {
63350
+ moduleHashes = await computeModuleHashes(moduleFolderPath, opts.defaultTs, rawWorkspaceDependencies, isFolderLayout);
63351
+ }
63352
+ const hasModuleHashes = Object.keys(moduleHashes).length > 0;
63353
+ let checkHash = hash2;
63354
+ let checkSubpath;
63355
+ if (hasModuleHashes) {
63356
+ const sortedEntries = Object.entries(moduleHashes).sort(([a], [b]) => a.localeCompare(b));
63357
+ checkHash = await generateHash(hash2 + JSON.stringify(sortedEntries));
63358
+ checkSubpath = SCRIPT_TOP_HASH;
63359
+ }
63360
+ const conf = await readLockfile();
63361
+ if (await checkifMetadataUptodate(remotePath, checkHash, conf, checkSubpath)) {
63101
63362
  if (!noStaleMessage) {
63102
63363
  info(colors.green(`Script ${remotePath} metadata is up-to-date, skipping`));
63103
63364
  }
63104
63365
  return;
63105
63366
  } else if (dryRun) {
63106
- return `${remotePath} (${language})`;
63367
+ let detail = `${remotePath} (${language})`;
63368
+ if (hasModuleHashes) {
63369
+ const changed = [];
63370
+ for (const [modulePath, moduleHash] of Object.entries(moduleHashes)) {
63371
+ if (!await checkifMetadataUptodate(remotePath, moduleHash, conf, modulePath)) {
63372
+ changed.push(modulePath);
63373
+ }
63374
+ }
63375
+ if (changed.length > 0) {
63376
+ detail += ` [changed modules: ${changed.join(", ")}]`;
63377
+ }
63378
+ }
63379
+ return detail;
63107
63380
  }
63108
63381
  if (!justUpdateMetadataLock && !noStaleMessage) {
63109
63382
  info(colors.gray(`Generating metadata for ${scriptPath}`));
@@ -63115,40 +63388,79 @@ async function generateScriptMetadataInternal(scriptPath, workspace, opts, dryRu
63115
63388
  if (!opts.schemaOnly && !justUpdateMetadataLock) {
63116
63389
  const hasCodebase = findCodebase(scriptPath, codebases) != null;
63117
63390
  if (!hasCodebase) {
63118
- await updateScriptLock(workspace, scriptContent, language, remotePath, metadataParsedContent, filteredRawWorkspaceDependencies);
63391
+ const lockPathOverride = isFolderLayout ? path9.dirname(scriptPath) + "/script.lock" : undefined;
63392
+ await updateScriptLock(workspace, scriptContent, language, remotePath, metadataParsedContent, filteredRawWorkspaceDependencies, lockPathOverride);
63119
63393
  } else {
63120
63394
  metadataParsedContent.lock = "";
63121
63395
  }
63396
+ if (hasModules) {
63397
+ let changedModules;
63398
+ if (hasModuleHashes) {
63399
+ changedModules = [];
63400
+ for (const [modulePath, moduleHash] of Object.entries(moduleHashes)) {
63401
+ if (!await checkifMetadataUptodate(remotePath, moduleHash, conf, modulePath)) {
63402
+ changedModules.push(modulePath);
63403
+ }
63404
+ }
63405
+ if (changedModules.length === 0) {
63406
+ changedModules = undefined;
63407
+ }
63408
+ }
63409
+ await updateModuleLocks(workspace, moduleFolderPath, "", remotePath, rawWorkspaceDependencies, opts.defaultTs, changedModules);
63410
+ }
63122
63411
  } else {
63123
- metadataParsedContent.lock = "!inline " + remotePath.replaceAll(SEP9, "/") + ".script.lock";
63412
+ if (isFolderLayout) {
63413
+ metadataParsedContent.lock = "!inline " + remotePath.replaceAll(SEP9, "/") + getModuleFolderSuffix() + "/script.lock";
63414
+ } else {
63415
+ metadataParsedContent.lock = "!inline " + remotePath.replaceAll(SEP9, "/") + ".script.lock";
63416
+ }
63124
63417
  }
63125
- let metaPath = remotePath + ".script.yaml";
63126
- let newMetadataContent = import_yaml12.stringify(metadataParsedContent, yamlOptions);
63127
- if (metadataWithType.isJson) {
63128
- metaPath = remotePath + ".script.json";
63129
- newMetadataContent = JSON.stringify(metadataParsedContent);
63418
+ let metaPath;
63419
+ let newMetadataContent;
63420
+ if (isFolderLayout) {
63421
+ if (metadataWithType.isJson) {
63422
+ metaPath = path9.dirname(scriptPath) + "/script.json";
63423
+ newMetadataContent = JSON.stringify(metadataParsedContent);
63424
+ } else {
63425
+ metaPath = path9.dirname(scriptPath) + "/script.yaml";
63426
+ newMetadataContent = import_yaml12.stringify(metadataParsedContent, yamlOptions);
63427
+ }
63428
+ } else {
63429
+ if (metadataWithType.isJson) {
63430
+ metaPath = remotePath + ".script.json";
63431
+ newMetadataContent = JSON.stringify(metadataParsedContent);
63432
+ } else {
63433
+ metaPath = remotePath + ".script.yaml";
63434
+ newMetadataContent = import_yaml12.stringify(metadataParsedContent, yamlOptions);
63435
+ }
63130
63436
  }
63131
63437
  const metadataContentUsedForHash = newMetadataContent;
63132
63438
  hash2 = await generateScriptHash(filteredRawWorkspaceDependencies, scriptContent, metadataContentUsedForHash);
63133
- await updateMetadataGlobalLock(remotePath, hash2);
63439
+ if (hasModuleHashes) {
63440
+ const sortedEntries = Object.entries(moduleHashes).sort(([a], [b]) => a.localeCompare(b));
63441
+ const metaHash = await generateHash(hash2 + JSON.stringify(sortedEntries));
63442
+ await clearGlobalLock(remotePath);
63443
+ await updateMetadataGlobalLock(remotePath, metaHash, SCRIPT_TOP_HASH);
63444
+ for (const [modulePath, moduleHash] of Object.entries(moduleHashes)) {
63445
+ await updateMetadataGlobalLock(remotePath, moduleHash, modulePath);
63446
+ }
63447
+ } else {
63448
+ await updateMetadataGlobalLock(remotePath, hash2);
63449
+ }
63134
63450
  if (!justUpdateMetadataLock) {
63135
63451
  await writeFile7(metaPath, newMetadataContent, "utf-8");
63136
63452
  }
63137
63453
  return `${remotePath} (${language})`;
63138
63454
  }
63139
- async function updateScriptSchema(scriptContent, language, metadataContent, path8) {
63140
- const result = await inferSchema(language, scriptContent, metadataContent.schema, path8);
63455
+ async function updateScriptSchema(scriptContent, language, metadataContent, path10) {
63456
+ const result = await inferSchema(language, scriptContent, metadataContent.schema, path10);
63141
63457
  metadataContent.schema = result.schema;
63142
63458
  if (result.has_preprocessor) {
63143
63459
  metadataContent.has_preprocessor = result.has_preprocessor;
63144
63460
  } else {
63145
63461
  delete metadataContent.has_preprocessor;
63146
63462
  }
63147
- if (result.no_main_func) {
63148
- metadataContent.no_main_func = result.no_main_func;
63149
- } else {
63150
- delete metadataContent.no_main_func;
63151
- }
63463
+ delete metadataContent.auto_kind;
63152
63464
  }
63153
63465
  function extractWorkspaceDepsAnnotation(scriptContent, language) {
63154
63466
  const config = LANG_ANNOTATION_CONFIG[language];
@@ -63268,7 +63580,7 @@ async function fetchScriptLock(workspace, scriptContent, language, remotePath, r
63268
63580
  throw new LockfileGenerationError(`Failed to generate lockfile:${rawResponse.statusText}, ${responseText}, ${e}`);
63269
63581
  }
63270
63582
  }
63271
- async function updateScriptLock(workspace, scriptContent, language, remotePath, metadataContent, rawWorkspaceDependencies) {
63583
+ async function updateScriptLock(workspace, scriptContent, language, remotePath, metadataContent, rawWorkspaceDependencies, lockPathOverride) {
63272
63584
  if (!(workspaceDependenciesLanguages.some((l) => l.language == language) && language !== "powershell" || language == "deno" || language == "rust" || language == "ansible")) {
63273
63585
  return;
63274
63586
  }
@@ -63277,7 +63589,7 @@ async function updateScriptLock(workspace, scriptContent, language, remotePath,
63277
63589
  info(`Generating script lock for ${remotePath} with raw workspace dependencies: ${dependencyPaths}`);
63278
63590
  }
63279
63591
  const lock = await fetchScriptLock(workspace, scriptContent, language, remotePath, rawWorkspaceDependencies);
63280
- const lockPath = remotePath + ".script.lock";
63592
+ const lockPath = lockPathOverride ?? remotePath + ".script.lock";
63281
63593
  if (lock != "") {
63282
63594
  await writeFile7(lockPath, lock, "utf-8");
63283
63595
  metadataContent.lock = "!inline " + lockPath.replaceAll(SEP9, "/");
@@ -63292,7 +63604,51 @@ async function updateScriptLock(workspace, scriptContent, language, remotePath,
63292
63604
  metadataContent.lock = "";
63293
63605
  }
63294
63606
  }
63295
- async function inferSchema(language, content, currentSchema, path8) {
63607
+ async function updateModuleLocks(workspace, dirPath, relPrefix, scriptRemotePath, rawWorkspaceDependencies, defaultTs, changedModules) {
63608
+ const entries = readdirSync(dirPath, { withFileTypes: true });
63609
+ for (const entry of entries) {
63610
+ const fullPath = path9.join(dirPath, entry.name);
63611
+ const relPath = relPrefix ? relPrefix + "/" + entry.name : entry.name;
63612
+ if (entry.isDirectory()) {
63613
+ await updateModuleLocks(workspace, fullPath, relPath, scriptRemotePath, rawWorkspaceDependencies, defaultTs, changedModules);
63614
+ } else if (entry.isFile() && !entry.name.endsWith(".lock") && !(relPrefix === "" && entry.name.startsWith("script."))) {
63615
+ let modLanguage;
63616
+ try {
63617
+ modLanguage = inferContentTypeFromFilePath(entry.name, defaultTs);
63618
+ } catch {
63619
+ continue;
63620
+ }
63621
+ if (!languageNeedsLock(modLanguage))
63622
+ continue;
63623
+ if (changedModules) {
63624
+ const normalizedRelPath = normalizeLockPath(relPath);
63625
+ if (!changedModules.includes(normalizedRelPath))
63626
+ continue;
63627
+ }
63628
+ const moduleContent = readFileSync3(fullPath, "utf-8");
63629
+ const moduleRemotePath = scriptRemotePath + "/" + relPath;
63630
+ info(colors.gray(`Generating lock for module ${relPath}`));
63631
+ try {
63632
+ const lock = await fetchScriptLock(workspace, moduleContent, modLanguage, moduleRemotePath, rawWorkspaceDependencies);
63633
+ const baseName = entry.name.replace(/\.[^.]+$/, "");
63634
+ const lockPath = path9.join(dirPath, baseName + ".lock");
63635
+ if (lock != "") {
63636
+ writeFileSync2(lockPath, lock, "utf-8");
63637
+ } else {
63638
+ try {
63639
+ if (existsSync4(lockPath)) {
63640
+ const { rm: rmAsync } = await import("node:fs/promises");
63641
+ await rmAsync(lockPath);
63642
+ }
63643
+ } catch {}
63644
+ }
63645
+ } catch (e) {
63646
+ info(colors.yellow(`Failed to generate lock for module ${relPath}: ${e}`));
63647
+ }
63648
+ }
63649
+ }
63650
+ }
63651
+ async function inferSchema(language, content, currentSchema, path10) {
63296
63652
  let inferedSchema;
63297
63653
  if (language === "python3") {
63298
63654
  const { parse_python } = await loadParser("windmill-parser-wasm-py");
@@ -63392,11 +63748,11 @@ async function inferSchema(language, content, currentSchema, path8) {
63392
63748
  throw new Error("Invalid language: " + language);
63393
63749
  }
63394
63750
  if (inferedSchema.type == "Invalid") {
63395
- info(colors.yellow(`Script ${path8} invalid, it cannot be parsed to infer schema.`));
63751
+ info(colors.yellow(`Script ${path10} invalid, it cannot be parsed to infer schema.`));
63396
63752
  return {
63397
63753
  schema: defaultScriptMetadata().schema,
63398
63754
  has_preprocessor: false,
63399
- no_main_func: false
63755
+ auto_kind: undefined
63400
63756
  };
63401
63757
  }
63402
63758
  if (!currentSchema) {
@@ -63424,7 +63780,7 @@ async function inferSchema(language, content, currentSchema, path8) {
63424
63780
  return {
63425
63781
  schema: currentSchema,
63426
63782
  has_preprocessor: inferedSchema.has_preprocessor,
63427
- no_main_func: inferedSchema.no_main_func
63783
+ auto_kind: inferedSchema.auto_kind
63428
63784
  };
63429
63785
  }
63430
63786
  function sortObject(obj) {
@@ -63469,33 +63825,55 @@ async function parseMetadataFile(scriptPath, generateMetadataIfMissing) {
63469
63825
  isJson: false
63470
63826
  };
63471
63827
  } catch {
63472
- info((await blueColor())(`Creating script metadata file for ${metadataFilePath}`));
63473
- metadataFilePath = scriptPath + ".script.yaml";
63474
- let scriptInitialMetadata = defaultScriptMetadata();
63475
- const lockPath = scriptPath + ".script.lock";
63476
- scriptInitialMetadata.lock = "!inline " + lockPath;
63477
- const scriptInitialMetadataYaml = import_yaml12.stringify(scriptInitialMetadata, yamlOptions);
63478
- await writeFile7(metadataFilePath, scriptInitialMetadataYaml, { flag: "wx", encoding: "utf-8" });
63479
- await writeFile7(lockPath, "", { flag: "wx", encoding: "utf-8" });
63480
- if (generateMetadataIfMissing) {
63481
- info((await blueColor())(`Generating lockfile and schema for ${metadataFilePath}`));
63828
+ const moduleFolderMeta = scriptPath + getModuleFolderSuffix();
63829
+ try {
63830
+ metadataFilePath = moduleFolderMeta + "/script.json";
63831
+ await stat7(metadataFilePath);
63832
+ return {
63833
+ path: metadataFilePath,
63834
+ payload: JSON.parse(await readFile9(metadataFilePath, "utf-8")),
63835
+ isJson: true
63836
+ };
63837
+ } catch {
63482
63838
  try {
63483
- await generateScriptMetadataInternal(generateMetadataIfMissing.path, generateMetadataIfMissing.workspaceRemote, generateMetadataIfMissing, false, false, generateMetadataIfMissing.rawWorkspaceDependencies, generateMetadataIfMissing.codebases, false);
63484
- scriptInitialMetadata = await yamlParseFile(metadataFilePath);
63485
- if (!generateMetadataIfMissing.schemaOnly) {
63486
- replaceLock(scriptInitialMetadata);
63487
- }
63488
- } catch (e) {
63489
- info(colors.yellow(`Failed to generate lockfile and schema for ${metadataFilePath}: ${e}`));
63490
- }
63839
+ metadataFilePath = moduleFolderMeta + "/script.yaml";
63840
+ await stat7(metadataFilePath);
63841
+ const payload = await yamlParseFile(metadataFilePath);
63842
+ replaceLock(payload);
63843
+ return {
63844
+ path: metadataFilePath,
63845
+ payload,
63846
+ isJson: false
63847
+ };
63848
+ } catch {}
63491
63849
  }
63492
- return {
63493
- path: metadataFilePath,
63494
- payload: scriptInitialMetadata,
63495
- isJson: false
63496
- };
63497
63850
  }
63498
63851
  }
63852
+ info((await blueColor())(`Creating script metadata file for ${metadataFilePath}`));
63853
+ metadataFilePath = scriptPath + ".script.yaml";
63854
+ let scriptInitialMetadata = defaultScriptMetadata();
63855
+ const lockPath = scriptPath + ".script.lock";
63856
+ scriptInitialMetadata.lock = "!inline " + lockPath;
63857
+ const scriptInitialMetadataYaml = import_yaml12.stringify(scriptInitialMetadata, yamlOptions);
63858
+ await writeFile7(metadataFilePath, scriptInitialMetadataYaml, { flag: "wx", encoding: "utf-8" });
63859
+ await writeFile7(lockPath, "", { flag: "wx", encoding: "utf-8" });
63860
+ if (generateMetadataIfMissing) {
63861
+ info((await blueColor())(`Generating lockfile and schema for ${metadataFilePath}`));
63862
+ try {
63863
+ await generateScriptMetadataInternal(generateMetadataIfMissing.path, generateMetadataIfMissing.workspaceRemote, generateMetadataIfMissing, false, false, generateMetadataIfMissing.rawWorkspaceDependencies, generateMetadataIfMissing.codebases, false);
63864
+ scriptInitialMetadata = await yamlParseFile(metadataFilePath);
63865
+ if (!generateMetadataIfMissing.schemaOnly) {
63866
+ replaceLock(scriptInitialMetadata);
63867
+ }
63868
+ } catch (e) {
63869
+ info(colors.yellow(`Failed to generate lockfile and schema for ${metadataFilePath}: ${e}`));
63870
+ }
63871
+ }
63872
+ return {
63873
+ path: metadataFilePath,
63874
+ payload: scriptInitialMetadata,
63875
+ isJson: false
63876
+ };
63499
63877
  }
63500
63878
  function normalizeLockPath(p) {
63501
63879
  return p.replace(/\\/g, "/");
@@ -63515,15 +63893,15 @@ async function readLockfile() {
63515
63893
  return lock;
63516
63894
  }
63517
63895
  }
63518
- function v2LockPath(path8, subpath) {
63519
- const normalizedPath = normalizeLockPath(path8);
63896
+ function v2LockPath(path10, subpath) {
63897
+ const normalizedPath = normalizeLockPath(path10);
63520
63898
  if (subpath) {
63521
63899
  return `${normalizedPath}+${normalizeLockPath(subpath)}`;
63522
63900
  } else {
63523
63901
  return normalizedPath;
63524
63902
  }
63525
63903
  }
63526
- async function checkifMetadataUptodate(path8, hash2, conf, subpath) {
63904
+ async function checkifMetadataUptodate(path10, hash2, conf, subpath) {
63527
63905
  if (!conf) {
63528
63906
  conf = await readLockfile();
63529
63907
  }
@@ -63532,10 +63910,10 @@ async function checkifMetadataUptodate(path8, hash2, conf, subpath) {
63532
63910
  }
63533
63911
  const isV2 = conf?.version == "v2";
63534
63912
  if (isV2) {
63535
- const current = conf.locks?.[v2LockPath(path8, subpath)];
63913
+ const current = conf.locks?.[v2LockPath(path10, subpath)];
63536
63914
  return current == hash2;
63537
63915
  } else {
63538
- const obj = conf.locks?.[path8];
63916
+ const obj = conf.locks?.[path10];
63539
63917
  const current = subpath && typeof obj == "object" ? obj?.[subpath] : obj;
63540
63918
  return current == hash2;
63541
63919
  }
@@ -63543,14 +63921,39 @@ async function checkifMetadataUptodate(path8, hash2, conf, subpath) {
63543
63921
  async function generateScriptHash(rawWorkspaceDependencies, scriptContent, newMetadataContent) {
63544
63922
  return await generateHash(JSON.stringify(rawWorkspaceDependencies) + scriptContent + newMetadataContent);
63545
63923
  }
63546
- async function clearGlobalLock(path8) {
63924
+ async function computeModuleHashes(moduleFolderPath, defaultTs, rawWorkspaceDependencies, isFolderLayout) {
63925
+ const hashes = {};
63926
+ async function readDir2(dirPath, relPrefix) {
63927
+ const entries = readdirSync(dirPath, { withFileTypes: true });
63928
+ for (const entry of entries) {
63929
+ const fullPath = path9.join(dirPath, entry.name);
63930
+ const relPath = relPrefix ? relPrefix + "/" + entry.name : entry.name;
63931
+ const isTopLevel = relPrefix === "";
63932
+ if (entry.isDirectory()) {
63933
+ await readDir2(fullPath, relPath);
63934
+ } else if (entry.isFile() && !entry.name.endsWith(".lock") && !(isFolderLayout && isTopLevel && entry.name.startsWith("script."))) {
63935
+ try {
63936
+ inferContentTypeFromFilePath(entry.name, defaultTs);
63937
+ } catch {
63938
+ continue;
63939
+ }
63940
+ const content = readFileSync3(fullPath, "utf-8");
63941
+ const normalizedPath = normalizeLockPath(relPath);
63942
+ hashes[normalizedPath] = await generateHash(content + JSON.stringify(rawWorkspaceDependencies));
63943
+ }
63944
+ }
63945
+ }
63946
+ await readDir2(moduleFolderPath, "");
63947
+ return hashes;
63948
+ }
63949
+ async function clearGlobalLock(path10) {
63547
63950
  const conf = await readLockfile();
63548
63951
  if (!conf?.locks) {
63549
63952
  conf.locks = {};
63550
63953
  }
63551
63954
  const isV2 = conf?.version == "v2";
63552
63955
  if (isV2) {
63553
- const key = v2LockPath(path8);
63956
+ const key = v2LockPath(path10);
63554
63957
  if (conf.locks) {
63555
63958
  Object.keys(conf.locks).forEach((k) => {
63556
63959
  if (conf.locks) {
@@ -63563,29 +63966,29 @@ async function clearGlobalLock(path8) {
63563
63966
  await writeFile7(WMILL_LOCKFILE, import_yaml12.stringify(conf, yamlOptions), "utf-8");
63564
63967
  }
63565
63968
  }
63566
- async function updateMetadataGlobalLock(path8, hash2, subpath) {
63969
+ async function updateMetadataGlobalLock(path10, hash2, subpath) {
63567
63970
  const conf = await readLockfile();
63568
63971
  if (!conf?.locks) {
63569
63972
  conf.locks = {};
63570
63973
  }
63571
63974
  const isV2 = conf?.version == "v2";
63572
63975
  if (isV2) {
63573
- conf.locks[v2LockPath(path8, subpath)] = hash2;
63976
+ conf.locks[v2LockPath(path10, subpath)] = hash2;
63574
63977
  } else {
63575
63978
  if (subpath) {
63576
- let prev = conf.locks[path8];
63979
+ let prev = conf.locks[path10];
63577
63980
  if (!prev || typeof prev != "object") {
63578
63981
  prev = {};
63579
- conf.locks[path8] = prev;
63982
+ conf.locks[path10] = prev;
63580
63983
  }
63581
63984
  prev[subpath] = hash2;
63582
63985
  } else {
63583
- conf.locks[path8] = hash2;
63986
+ conf.locks[path10] = hash2;
63584
63987
  }
63585
63988
  }
63586
63989
  await writeFile7(WMILL_LOCKFILE, import_yaml12.stringify(conf, yamlOptions), "utf-8");
63587
63990
  }
63588
- var import_yaml12, _require, _parserCache, LockfileGenerationError, LANG_ANNOTATION_CONFIG, lockCache, WMILL_LOCKFILE = "wmill-lock.yaml";
63991
+ var import_yaml12, _require, _parserCache, LockfileGenerationError, LANG_ANNOTATION_CONFIG, lockCache, WMILL_LOCKFILE = "wmill-lock.yaml", SCRIPT_TOP_HASH = "__script_hash";
63589
63992
  var init_metadata = __esm(async () => {
63590
63993
  init_colors2();
63591
63994
  init_log();
@@ -63593,6 +63996,7 @@ var init_metadata = __esm(async () => {
63593
63996
  init_script_bootstrap();
63594
63997
  init_script_common();
63595
63998
  init_script_common();
63999
+ init_resource_folders();
63596
64000
  init_parse_schema();
63597
64001
  await __promiseAll([
63598
64002
  init_sync(),
@@ -63621,7 +64025,7 @@ var init_metadata = __esm(async () => {
63621
64025
 
63622
64026
  // src/commands/app/raw_apps.ts
63623
64027
  import { sep as SEP10 } from "node:path";
63624
- import path8 from "node:path";
64028
+ import path10 from "node:path";
63625
64029
  import { readFile as readFile10, readdir as readdir6 } from "node:fs/promises";
63626
64030
  async function findRunnableContentFile(backendPath, runnableId, allFiles) {
63627
64031
  for (const fileName of allFiles) {
@@ -63634,7 +64038,7 @@ async function findRunnableContentFile(backendPath, runnableId, allFiles) {
63634
64038
  const ext2 = fileName.substring(runnableId.length + 1);
63635
64039
  if (EXTENSION_TO_LANGUAGE[ext2]) {
63636
64040
  try {
63637
- const content = await readFile10(path8.join(backendPath, fileName), "utf-8");
64041
+ const content = await readFile10(path10.join(backendPath, fileName), "utf-8");
63638
64042
  return { ext: ext2, content };
63639
64043
  } catch {
63640
64044
  continue;
@@ -63671,7 +64075,7 @@ async function loadRunnablesFromBackend(backendPath, defaultTs = "bun") {
63671
64075
  }
63672
64076
  const runnableId = fileName.replace(".yaml", "");
63673
64077
  processedIds.add(runnableId);
63674
- const filePath = path8.join(backendPath, fileName);
64078
+ const filePath = path10.join(backendPath, fileName);
63675
64079
  const runnable = await yamlParseFile(filePath);
63676
64080
  if (runnable?.type === "inline") {
63677
64081
  const contentFile = await findRunnableContentFile(backendPath, runnableId, allFiles);
@@ -63679,7 +64083,7 @@ async function loadRunnablesFromBackend(backendPath, defaultTs = "bun") {
63679
64083
  const language = getLanguageFromExtension(contentFile.ext, defaultTs);
63680
64084
  let lock;
63681
64085
  try {
63682
- lock = await readFile10(path8.join(backendPath, `${runnableId}.lock`), "utf-8");
64086
+ lock = await readFile10(path10.join(backendPath, `${runnableId}.lock`), "utf-8");
63683
64087
  } catch {}
63684
64088
  runnable.inlineScript = {
63685
64089
  content: contentFile.content,
@@ -63710,7 +64114,7 @@ async function loadRunnablesFromBackend(backendPath, defaultTs = "bun") {
63710
64114
  const language = getLanguageFromExtension(contentFile.ext, defaultTs);
63711
64115
  let lock;
63712
64116
  try {
63713
- lock = await readFile10(path8.join(backendPath, `${runnableId}.lock`), "utf-8");
64117
+ lock = await readFile10(path10.join(backendPath, `${runnableId}.lock`), "utf-8");
63714
64118
  } catch {}
63715
64119
  runnables[runnableId] = {
63716
64120
  type: "inline",
@@ -63738,7 +64142,7 @@ function writeRunnableToBackend(backendPath, runnableId, runnable) {
63738
64142
  ...rest
63739
64143
  };
63740
64144
  }
63741
- const filePath = path8.join(backendPath, `${runnableId}.yaml`);
64145
+ const filePath = path10.join(backendPath, `${runnableId}.yaml`);
63742
64146
  writeIfChanged(filePath, import_yaml15.stringify(runnableToWrite, yamlOptions));
63743
64147
  }
63744
64148
  async function collectAppFiles(localPath) {
@@ -63789,7 +64193,7 @@ async function pushRawApp(workspace, remotePath, localPath, message) {
63789
64193
  }
63790
64194
  const appFilePath = localPath + "raw_app.yaml";
63791
64195
  const localApp = await yamlParseFile(appFilePath);
63792
- const backendPath = path8.join(localPath, APP_BACKEND_FOLDER);
64196
+ const backendPath = path10.join(localPath, APP_BACKEND_FOLDER);
63793
64197
  const runnablesFromBackend = await loadRunnablesFromBackend(backendPath);
63794
64198
  let runnables;
63795
64199
  if (Object.keys(runnablesFromBackend).length > 0) {
@@ -63865,13 +64269,13 @@ async function pushRawApp(workspace, remotePath, localPath, message) {
63865
64269
  });
63866
64270
  }
63867
64271
  }
63868
- async function generatingPolicy(app, path9, publicApp) {
63869
- info(colors.gray(`Generating fresh policy for app ${path9}...`));
64272
+ async function generatingPolicy(app, path11, publicApp) {
64273
+ info(colors.gray(`Generating fresh policy for app ${path11}...`));
63870
64274
  try {
63871
64275
  app.policy = await updateRawAppPolicy(app.runnables, app.policy);
63872
64276
  app.policy.execution_mode = publicApp ? "anonymous" : "publisher";
63873
64277
  } catch (e) {
63874
- error(colors.red(`Error generating policy for app ${path9}: ${e}`));
64278
+ error(colors.red(`Error generating policy for app ${path11}: ${e}`));
63875
64279
  throw e;
63876
64280
  }
63877
64281
  }
@@ -63908,11 +64312,11 @@ __export(exports_app_metadata, {
63908
64312
  filterWorkspaceDependenciesForApp: () => filterWorkspaceDependenciesForApp,
63909
64313
  APP_BACKEND_FOLDER: () => APP_BACKEND_FOLDER
63910
64314
  });
63911
- import path9 from "node:path";
64315
+ import path11 from "node:path";
63912
64316
  import { readFile as readFile11, mkdir as mkdir4 } from "node:fs/promises";
63913
64317
  import { sep as SEP11 } from "node:path";
63914
64318
  async function generateAppHash(rawReqs, folder, rawApp, defaultTs) {
63915
- const runnablesFolder = rawApp ? path9.join(folder, APP_BACKEND_FOLDER) : folder;
64319
+ const runnablesFolder = rawApp ? path11.join(folder, APP_BACKEND_FOLDER) : folder;
63916
64320
  const hashes = {};
63917
64321
  try {
63918
64322
  const elems = await FSFSElement(runnablesFolder, [], true);
@@ -63944,7 +64348,7 @@ async function generateAppLocksInternal(appFolder, rawApp, dryRun, workspace, op
63944
64348
  info(`Generating locks for app ${appFolder} at ${remote_path}`);
63945
64349
  }
63946
64350
  const rawWorkspaceDependencies = await getRawWorkspaceDependencies();
63947
- const appFilePath = path9.join(appFolder, rawApp ? "raw_app.yaml" : "app.yaml");
64351
+ const appFilePath = path11.join(appFolder, rawApp ? "raw_app.yaml" : "app.yaml");
63948
64352
  const appFile = await yamlParseFile(appFilePath);
63949
64353
  const appValue = rawApp ? appFile.runnables : appFile.value;
63950
64354
  const filteredDeps = await filterWorkspaceDependenciesForApp(appValue, rawWorkspaceDependencies, appFolder);
@@ -63977,7 +64381,7 @@ async function generateAppLocksInternal(appFolder, rawApp, dryRun, workspace, op
63977
64381
  info(`Recomputing locks of ${changedScripts.join(", ")} in ${appFolder}`);
63978
64382
  }
63979
64383
  if (rawApp) {
63980
- const runnablesPath = path9.join(appFolder, APP_BACKEND_FOLDER);
64384
+ const runnablesPath = path11.join(appFolder, APP_BACKEND_FOLDER);
63981
64385
  const rawAppFile = appFile;
63982
64386
  let runnables = await loadRunnablesFromBackend(runnablesPath);
63983
64387
  if (Object.keys(runnables).length === 0 && rawAppFile.runnables) {
@@ -64049,7 +64453,7 @@ async function traverseAndProcessInlineScripts(obj, processor, currentPath = [])
64049
64453
  }
64050
64454
  async function updateRawAppRunnables(workspace, runnables, remotePath, appFolder, rawDeps, defaultTs = "bun", noStaleMessage) {
64051
64455
  const updatedRunnables = [];
64052
- const runnablesFolder = path9.join(appFolder, APP_BACKEND_FOLDER);
64456
+ const runnablesFolder = path11.join(appFolder, APP_BACKEND_FOLDER);
64053
64457
  try {
64054
64458
  await mkdir4(runnablesFolder, { recursive: true });
64055
64459
  } catch {}
@@ -64074,7 +64478,7 @@ async function updateRawAppRunnables(workspace, runnables, remotePath, appFolder
64074
64478
  if (language === "frontend") {
64075
64479
  const [basePathO, ext2] = pathAssigner.assignPath(runnable.name ?? runnableId, language);
64076
64480
  const basePath = basePathO.replaceAll(SEP11, "/");
64077
- const contentPath = path9.join(runnablesFolder, `${basePath}${ext2}`);
64481
+ const contentPath = path11.join(runnablesFolder, `${basePath}${ext2}`);
64078
64482
  writeIfChanged(contentPath, content);
64079
64483
  const simplifiedRunnable = { type: "inline" };
64080
64484
  for (const [key, value] of Object.entries(runnable)) {
@@ -64092,8 +64496,8 @@ async function updateRawAppRunnables(workspace, runnables, remotePath, appFolder
64092
64496
  const lock = await generateInlineScriptLock(workspace, content, language, `${remotePath}/${runnableId}`, rawDeps);
64093
64497
  const [basePathO, ext2] = pathAssigner.assignPath(runnable.name ?? runnableId, language);
64094
64498
  const basePath = basePathO.replaceAll(SEP11, "/");
64095
- const contentPath = path9.join(runnablesFolder, `${basePath}${ext2}`);
64096
- const lockPath = path9.join(runnablesFolder, `${basePath}lock`);
64499
+ const contentPath = path11.join(runnablesFolder, `${basePath}${ext2}`);
64500
+ const lockPath = path11.join(runnablesFolder, `${basePath}lock`);
64097
64501
  writeIfChanged(contentPath, content);
64098
64502
  if (lock && lock !== "") {
64099
64503
  writeIfChanged(lockPath, lock);
@@ -64141,8 +64545,8 @@ async function updateAppInlineScripts(workspace, appValue, remotePath, appFolder
64141
64545
  }
64142
64546
  const [basePathO, ext2] = pathAssigner.assignPath(scriptName, language);
64143
64547
  const basePath = basePathO.replaceAll(SEP11, "/");
64144
- const contentPath = path9.join(appFolder, `${basePath}${ext2}`);
64145
- const lockPath = path9.join(appFolder, `${basePath}lock`);
64548
+ const contentPath = path11.join(appFolder, `${basePath}${ext2}`);
64549
+ const lockPath = path11.join(appFolder, `${basePath}lock`);
64146
64550
  writeIfChanged(contentPath, content);
64147
64551
  if (lock && lock !== "") {
64148
64552
  writeIfChanged(lockPath, lock);
@@ -64212,7 +64616,7 @@ ${text}`);
64212
64616
  }
64213
64617
  }
64214
64618
  async function inferRunnableSchemaFromFile(appFolder, runnableFilePath) {
64215
- const fileName = path9.basename(runnableFilePath);
64619
+ const fileName = path11.basename(runnableFilePath);
64216
64620
  if (fileName.endsWith(".lock") || fileName.endsWith(".yaml")) {
64217
64621
  return;
64218
64622
  }
@@ -64221,13 +64625,13 @@ async function inferRunnableSchemaFromFile(appFolder, runnableFilePath) {
64221
64625
  return;
64222
64626
  }
64223
64627
  const runnableId = match2[1];
64224
- const runnableFilePath2 = path9.join(appFolder, APP_BACKEND_FOLDER, `${runnableId}.yaml`);
64628
+ const runnableFilePath2 = path11.join(appFolder, APP_BACKEND_FOLDER, `${runnableId}.yaml`);
64225
64629
  let runnable;
64226
64630
  try {
64227
64631
  runnable = await yamlParseFile(runnableFilePath2);
64228
64632
  } catch {
64229
64633
  try {
64230
- const appFilePath = path9.join(appFolder, "raw_app.yaml");
64634
+ const appFilePath = path11.join(appFolder, "raw_app.yaml");
64231
64635
  const appFile = await yamlParseFile(appFilePath);
64232
64636
  if (!appFile.runnables?.[runnableId]) {
64233
64637
  warn(colors.yellow(`Runnable ${runnableId} not found in backend folder or raw_app.yaml`));
@@ -64244,7 +64648,7 @@ async function inferRunnableSchemaFromFile(appFolder, runnableFilePath) {
64244
64648
  }
64245
64649
  const inlineScript = runnable.inlineScript;
64246
64650
  const language = inlineScript.language;
64247
- const fullFilePath = path9.join(appFolder, APP_BACKEND_FOLDER, runnableFilePath);
64651
+ const fullFilePath = path11.join(appFolder, APP_BACKEND_FOLDER, runnableFilePath);
64248
64652
  let content;
64249
64653
  try {
64250
64654
  content = await readFile11(fullFilePath, "utf-8");
@@ -64353,7 +64757,7 @@ var init_app_metadata = __esm(async () => {
64353
64757
  // src/commands/app/generate_agents.ts
64354
64758
  import * as fs9 from "node:fs";
64355
64759
  import { writeFile as writeFile8 } from "node:fs/promises";
64356
- import path10 from "node:path";
64760
+ import path12 from "node:path";
64357
64761
  import process13 from "node:process";
64358
64762
  function generateDatatablesMarkdown(schemas, localData) {
64359
64763
  const defaultDatatable = localData?.datatable;
@@ -64453,7 +64857,7 @@ Configure datatables in Workspace Settings > Windmill Data Tables.
64453
64857
  return content;
64454
64858
  }
64455
64859
  async function regenerateAgentDocs(workspaceId, targetDir, silent = false) {
64456
- const rawAppPath = path10.join(targetDir, "raw_app.yaml");
64860
+ const rawAppPath = path12.join(targetDir, "raw_app.yaml");
64457
64861
  if (!fs9.existsSync(rawAppPath)) {
64458
64862
  if (!silent) {
64459
64863
  error(colors.red(`Error: raw_app.yaml not found in ${targetDir}`));
@@ -64480,11 +64884,11 @@ async function regenerateAgentDocs(workspaceId, targetDir, silent = false) {
64480
64884
  }
64481
64885
  } catch {}
64482
64886
  const agentsContent = generateAgentsDocumentation(localData);
64483
- await writeFile8(path10.join(targetDir, "AGENTS.md"), agentsContent, "utf-8");
64484
- await writeFile8(path10.join(targetDir, "CLAUDE.md"), `Instructions are in @AGENTS.md
64887
+ await writeFile8(path12.join(targetDir, "AGENTS.md"), agentsContent, "utf-8");
64888
+ await writeFile8(path12.join(targetDir, "CLAUDE.md"), `Instructions are in @AGENTS.md
64485
64889
  `, "utf-8");
64486
64890
  const datatablesContent = generateDatatablesMarkdown(schemas, localData);
64487
- await writeFile8(path10.join(targetDir, "DATATABLES.md"), datatablesContent, "utf-8");
64891
+ await writeFile8(path12.join(targetDir, "DATATABLES.md"), datatablesContent, "utf-8");
64488
64892
  if (!silent) {
64489
64893
  info(colors.green(`✓ Generated AGENTS.md, CLAUDE.md, and DATATABLES.md`));
64490
64894
  const datatableCount = schemas.length;
@@ -64505,18 +64909,18 @@ async function generateAgents(opts, appFolder) {
64505
64909
  const cwd = process13.cwd();
64506
64910
  let targetDir = cwd;
64507
64911
  if (appFolder) {
64508
- targetDir = path10.isAbsolute(appFolder) ? appFolder : path10.join(cwd, appFolder);
64912
+ targetDir = path12.isAbsolute(appFolder) ? appFolder : path12.join(cwd, appFolder);
64509
64913
  }
64510
64914
  await loadNonDottedPathsSetting();
64511
- const dirName = path10.basename(targetDir);
64915
+ const dirName = path12.basename(targetDir);
64512
64916
  if (!hasFolderSuffix(dirName, "raw_app")) {
64513
- if (!hasFolderSuffix(path10.basename(cwd), "raw_app") && !appFolder) {
64917
+ if (!hasFolderSuffix(path12.basename(cwd), "raw_app") && !appFolder) {
64514
64918
  error(colors.red(`Error: Must be run inside a ${getFolderSuffix("raw_app")} folder or specify one as argument.`));
64515
64919
  info(colors.gray("Usage: wmill app generate-agents [app_folder]"));
64516
64920
  process13.exit(1);
64517
64921
  }
64518
64922
  }
64519
- const rawAppPath = path10.join(targetDir, "raw_app.yaml");
64923
+ const rawAppPath = path12.join(targetDir, "raw_app.yaml");
64520
64924
  if (!fs9.existsSync(rawAppPath)) {
64521
64925
  error(colors.red(`Error: raw_app.yaml not found in ${targetDir}`));
64522
64926
  process13.exit(1);
@@ -64546,9 +64950,9 @@ var init_generate_agents = __esm(async () => {
64546
64950
  import { sep as SEP12 } from "node:path";
64547
64951
  import * as http2 from "node:http";
64548
64952
  import * as fs10 from "node:fs";
64549
- import * as path11 from "node:path";
64953
+ import * as path13 from "node:path";
64550
64954
  import process14 from "node:process";
64551
- import { writeFileSync as writeFileSync2 } from "node:fs";
64955
+ import { writeFileSync as writeFileSync3 } from "node:fs";
64552
64956
  import { readFile as readFile12 } from "node:fs/promises";
64553
64957
  async function dev(opts, appFolder) {
64554
64958
  GLOBAL_CONFIG_OPT.noCdToRoot = true;
@@ -64556,20 +64960,20 @@ async function dev(opts, appFolder) {
64556
64960
  const originalCwd = process14.cwd();
64557
64961
  let targetDir = originalCwd;
64558
64962
  if (appFolder) {
64559
- targetDir = path11.isAbsolute(appFolder) ? appFolder : path11.join(originalCwd, appFolder);
64963
+ targetDir = path13.isAbsolute(appFolder) ? appFolder : path13.join(originalCwd, appFolder);
64560
64964
  if (!fs10.existsSync(targetDir)) {
64561
64965
  error(colors.red(`Error: Directory not found: ${targetDir}`));
64562
64966
  process14.exit(1);
64563
64967
  }
64564
64968
  }
64565
- const targetDirName = path11.basename(targetDir);
64969
+ const targetDirName = path13.basename(targetDir);
64566
64970
  if (!hasFolderSuffix(targetDirName, "raw_app")) {
64567
64971
  error(colors.red(`Error: The dev command must be run inside a ${getFolderSuffix("raw_app")} folder.
64568
64972
  ` + `Target directory: ${targetDirName}
64569
64973
  ` + `Please navigate to a folder ending with '${getFolderSuffix("raw_app")}' or specify one as argument.`));
64570
64974
  process14.exit(1);
64571
64975
  }
64572
- const rawAppPath = path11.join(targetDir, "raw_app.yaml");
64976
+ const rawAppPath = path13.join(targetDir, "raw_app.yaml");
64573
64977
  if (!fs10.existsSync(rawAppPath)) {
64574
64978
  error(colors.red(`Error: raw_app.yaml not found in ${targetDir}.
64575
64979
  ` + `The dev command requires a ${getFolderSuffix("raw_app")} folder containing a raw_app.yaml file.`));
@@ -64596,11 +65000,11 @@ async function dev(opts, appFolder) {
64596
65000
  error(colors.red(`Entry point "${entryPoint}" not found. Please specify a valid entry point with --entry.`));
64597
65001
  process14.exit(1);
64598
65002
  }
64599
- const appDir = path11.dirname(entryPoint) || process14.cwd();
65003
+ const appDir = path13.dirname(entryPoint) || process14.cwd();
64600
65004
  await ensureNodeModules(appDir);
64601
65005
  const inferredSchemas = {};
64602
65006
  genRunnablesTs(inferredSchemas);
64603
- const distDir = path11.join(process14.cwd(), "dist");
65007
+ const distDir = path13.join(process14.cwd(), "dist");
64604
65008
  if (!fs10.existsSync(distDir)) {
64605
65009
  fs10.mkdirSync(distDir);
64606
65010
  }
@@ -64663,7 +65067,7 @@ data: reload
64663
65067
  info(colors.blue(`\uD83D\uDC40 Watching for file changes...
64664
65068
  `));
64665
65069
  await ctx.rebuild();
64666
- const runnablesPath = path11.join(process14.cwd(), APP_BACKEND_FOLDER);
65070
+ const runnablesPath = path13.join(process14.cwd(), APP_BACKEND_FOLDER);
64667
65071
  let runnablesWatcher;
64668
65072
  if (fs10.existsSync(runnablesPath)) {
64669
65073
  info(colors.blue(`\uD83D\uDC41️ Watching runnables folder at: ${runnablesPath}
@@ -64675,8 +65079,8 @@ data: reload
64675
65079
  if (!filename)
64676
65080
  return;
64677
65081
  const fileStr = typeof filename === "string" ? filename : filename.toString();
64678
- const changedPath = path11.join(runnablesPath, fileStr);
64679
- const relativePath = path11.relative(process14.cwd(), changedPath);
65082
+ const changedPath = path13.join(runnablesPath, fileStr);
65083
+ const relativePath = path13.relative(process14.cwd(), changedPath);
64680
65084
  const relativeToRunnables = fileStr;
64681
65085
  if (changedPath.endsWith(".lock")) {
64682
65086
  return;
@@ -64727,7 +65131,7 @@ data: reload
64727
65131
  return;
64728
65132
  }
64729
65133
  if (url === "/dist/bundle.js" || url === "/bundle.js") {
64730
- const jsPath = path11.join(process14.cwd(), "dist/bundle.js");
65134
+ const jsPath = path13.join(process14.cwd(), "dist/bundle.js");
64731
65135
  if (fs10.existsSync(jsPath)) {
64732
65136
  res.writeHead(200, { "Content-Type": "application/javascript" });
64733
65137
  res.end(fs10.readFileSync(jsPath));
@@ -64738,7 +65142,7 @@ data: reload
64738
65142
  return;
64739
65143
  }
64740
65144
  if (url === "/dist/bundle.css" || url === "/bundle.css") {
64741
- const cssPath = path11.join(process14.cwd(), "dist/bundle.css");
65145
+ const cssPath = path13.join(process14.cwd(), "dist/bundle.css");
64742
65146
  if (fs10.existsSync(cssPath)) {
64743
65147
  res.writeHead(200, { "Content-Type": "text/css" });
64744
65148
  res.end(fs10.readFileSync(cssPath));
@@ -64749,7 +65153,7 @@ data: reload
64749
65153
  return;
64750
65154
  }
64751
65155
  if (url === "/dist/bundle.js.map" || url === "/bundle.js.map") {
64752
- const mapPath = path11.join(process14.cwd(), "dist/bundle.js.map");
65156
+ const mapPath = path13.join(process14.cwd(), "dist/bundle.js.map");
64753
65157
  if (fs10.existsSync(mapPath)) {
64754
65158
  res.writeHead(200, { "Content-Type": "application/json" });
64755
65159
  res.end(fs10.readFileSync(mapPath));
@@ -64760,7 +65164,7 @@ data: reload
64760
65164
  return;
64761
65165
  }
64762
65166
  if (url === "/dist/bundle.css.map" || url === "/bundle.css.map") {
64763
- const mapPath = path11.join(process14.cwd(), "dist/bundle.css.map");
65167
+ const mapPath = path13.join(process14.cwd(), "dist/bundle.css.map");
64764
65168
  if (fs10.existsSync(mapPath)) {
64765
65169
  res.writeHead(200, { "Content-Type": "application/json" });
64766
65170
  res.end(fs10.readFileSync(mapPath));
@@ -64774,12 +65178,12 @@ data: reload
64774
65178
  res.end(createHTML("/dist/bundle.js", "/dist/bundle.css"));
64775
65179
  });
64776
65180
  const wss = new import_websocket_server.default({ server });
64777
- const sqlToApplyPath = path11.join(process14.cwd(), "sql_to_apply");
65181
+ const sqlToApplyPath = path13.join(process14.cwd(), "sql_to_apply");
64778
65182
  const sqlFileQueue = [];
64779
65183
  let currentSqlFile = null;
64780
65184
  async function getDatatableConfig() {
64781
65185
  try {
64782
- const rawApp2 = await yamlParseFile(path11.join(process14.cwd(), "raw_app.yaml"));
65186
+ const rawApp2 = await yamlParseFile(path13.join(process14.cwd(), "raw_app.yaml"));
64783
65187
  return rawApp2?.data?.datatable;
64784
65188
  } catch {
64785
65189
  return;
@@ -64816,12 +65220,12 @@ data: reload
64816
65220
  }
64817
65221
  const filePath = sqlFileQueue.shift();
64818
65222
  if (!fs10.existsSync(filePath)) {
64819
- info(colors.gray(`File no longer exists: ${path11.basename(filePath)}`));
65223
+ info(colors.gray(`File no longer exists: ${path13.basename(filePath)}`));
64820
65224
  await processNextSqlFile();
64821
65225
  return;
64822
65226
  }
64823
65227
  currentSqlFile = filePath;
64824
- const fileName = path11.basename(filePath);
65228
+ const fileName = path13.basename(filePath);
64825
65229
  try {
64826
65230
  const sqlContent = await readFile12(filePath, "utf-8");
64827
65231
  if (!sqlContent.trim()) {
@@ -64843,9 +65247,9 @@ data: reload
64843
65247
  if (deleteFile && fs10.existsSync(filePath)) {
64844
65248
  try {
64845
65249
  fs10.unlinkSync(filePath);
64846
- info(colors.green(`✓ Deleted: ${path11.basename(filePath)}`));
65250
+ info(colors.green(`✓ Deleted: ${path13.basename(filePath)}`));
64847
65251
  } catch (error2) {
64848
- error(colors.red(`Failed to delete ${path11.basename(filePath)}: ${error2.message}`));
65252
+ error(colors.red(`Failed to delete ${path13.basename(filePath)}: ${error2.message}`));
64849
65253
  }
64850
65254
  }
64851
65255
  currentSqlFile = null;
@@ -64857,7 +65261,7 @@ data: reload
64857
65261
  try {
64858
65262
  const sqlContent = await readFile12(currentSqlFile, "utf-8");
64859
65263
  const datatable = await getDatatableConfig();
64860
- const fileName = path11.basename(currentSqlFile);
65264
+ const fileName = path13.basename(currentSqlFile);
64861
65265
  ws.send(JSON.stringify({
64862
65266
  type: "sqlMigration",
64863
65267
  fileName,
@@ -64871,7 +65275,7 @@ data: reload
64871
65275
  const sqlFiles = entries.filter((entry) => entry.endsWith(".sql"));
64872
65276
  if (sqlFiles.length > 0 && sqlFileQueue.length === 0) {
64873
65277
  for (const sqlFile of sqlFiles.sort()) {
64874
- queueSqlFile(path11.join(sqlToApplyPath, sqlFile));
65278
+ queueSqlFile(path13.join(sqlToApplyPath, sqlFile));
64875
65279
  }
64876
65280
  await processNextSqlFile();
64877
65281
  }
@@ -65050,7 +65454,7 @@ data: reload
65050
65454
  }
65051
65455
  info(colors.blue(`\uD83D\uDD0D Found ${sqlFiles.length} SQL file(s) in sql_to_apply/`));
65052
65456
  for (const sqlFile of sqlFiles) {
65053
- const filePath = path11.join(sqlToApplyPath, sqlFile);
65457
+ const filePath = path13.join(sqlToApplyPath, sqlFile);
65054
65458
  queueSqlFile(filePath);
65055
65459
  }
65056
65460
  await processNextSqlFile();
@@ -65068,11 +65472,11 @@ data: reload
65068
65472
  if (!filename)
65069
65473
  return;
65070
65474
  const fileStr = typeof filename === "string" ? filename : filename.toString();
65071
- const changedPath = path11.join(sqlToApplyPath, fileStr);
65475
+ const changedPath = path13.join(sqlToApplyPath, fileStr);
65072
65476
  if (!changedPath.endsWith(".sql")) {
65073
65477
  return;
65074
65478
  }
65075
- const fileName = path11.basename(changedPath);
65479
+ const fileName = path13.basename(changedPath);
65076
65480
  if (sqlDebounceTimeouts[changedPath]) {
65077
65481
  clearTimeout(sqlDebounceTimeouts[changedPath]);
65078
65482
  }
@@ -65130,11 +65534,11 @@ data: reload
65130
65534
  async function genRunnablesTs(schemaOverrides = {}) {
65131
65535
  info(colors.blue("\uD83D\uDD04 Generating wmill.d.ts..."));
65132
65536
  const localPath = process14.cwd();
65133
- const backendPath = path11.join(localPath, APP_BACKEND_FOLDER);
65537
+ const backendPath = path13.join(localPath, APP_BACKEND_FOLDER);
65134
65538
  let runnables = await loadRunnablesFromBackend(backendPath);
65135
65539
  if (Object.keys(runnables).length === 0) {
65136
65540
  try {
65137
- const rawApp = await yamlParseFile(path11.join(localPath, "raw_app.yaml"));
65541
+ const rawApp = await yamlParseFile(path13.join(localPath, "raw_app.yaml"));
65138
65542
  runnables = rawApp?.["runnables"] ?? {};
65139
65543
  } catch {
65140
65544
  runnables = {};
@@ -65150,7 +65554,7 @@ async function genRunnablesTs(schemaOverrides = {}) {
65150
65554
  }
65151
65555
  try {
65152
65556
  const newWmillTs = genWmillTs(runnables);
65153
- writeFileSync2(path11.join(process14.cwd(), "wmill.d.ts"), newWmillTs);
65557
+ writeFileSync3(path13.join(process14.cwd(), "wmill.d.ts"), newWmillTs);
65154
65558
  } catch (error2) {
65155
65559
  error(colors.red(`Failed to generate wmill.d.ts: ${error2.message}`));
65156
65560
  }
@@ -65168,10 +65572,10 @@ function convertRunnablesToApiFormat(runnables) {
65168
65572
  async function loadRunnables() {
65169
65573
  try {
65170
65574
  const localPath = process14.cwd();
65171
- const backendPath = path11.join(localPath, APP_BACKEND_FOLDER);
65575
+ const backendPath = path13.join(localPath, APP_BACKEND_FOLDER);
65172
65576
  let runnables = await loadRunnablesFromBackend(backendPath);
65173
65577
  if (Object.keys(runnables).length === 0) {
65174
- const rawApp = await yamlParseFile(path11.join(localPath, "raw_app.yaml"));
65578
+ const rawApp = await yamlParseFile(path13.join(localPath, "raw_app.yaml"));
65175
65579
  runnables = rawApp?.runnables ?? {};
65176
65580
  }
65177
65581
  convertRunnablesToApiFormat(runnables);
@@ -65652,7 +66056,7 @@ var init_dev = __esm(async () => {
65652
66056
 
65653
66057
  // src/commands/app/lint.ts
65654
66058
  import * as fs11 from "node:fs";
65655
- import * as path12 from "node:path";
66059
+ import * as path14 from "node:path";
65656
66060
  import process15 from "node:process";
65657
66061
  function validateRawAppYaml(appData) {
65658
66062
  const errors = [];
@@ -65667,7 +66071,7 @@ function validateRawAppYaml(appData) {
65667
66071
  async function validateRunnables(appDir, appData) {
65668
66072
  const errors = [];
65669
66073
  const warnings = [];
65670
- const backendPath = path12.join(appDir, APP_BACKEND_FOLDER);
66074
+ const backendPath = path14.join(appDir, APP_BACKEND_FOLDER);
65671
66075
  const runnablesFromBackend = await loadRunnablesFromBackend(backendPath);
65672
66076
  const hasBackendRunnables = Object.keys(runnablesFromBackend).length > 0;
65673
66077
  const hasYamlRunnables = appData.runnables && typeof appData.runnables === "object" && !Array.isArray(appData.runnables) && Object.keys(appData.runnables).length > 0;
@@ -65701,12 +66105,12 @@ async function validateBuild(appDir) {
65701
66105
  async function lintRawApp(appDir, opts) {
65702
66106
  const errors = [];
65703
66107
  const warnings = [];
65704
- const currentDirName = path12.basename(appDir);
66108
+ const currentDirName = path14.basename(appDir);
65705
66109
  if (!hasFolderSuffix(currentDirName, "raw_app")) {
65706
66110
  errors.push(`Not a raw app folder: '${currentDirName}' does not end with '${getFolderSuffix("raw_app")}'`);
65707
66111
  return { valid: false, errors, warnings };
65708
66112
  }
65709
- const rawAppPath = path12.join(appDir, "raw_app.yaml");
66113
+ const rawAppPath = path14.join(appDir, "raw_app.yaml");
65710
66114
  if (!fs11.existsSync(rawAppPath)) {
65711
66115
  errors.push("Missing raw_app.yaml file");
65712
66116
  return { valid: false, errors, warnings };
@@ -65790,7 +66194,7 @@ var init_lint2 = __esm(async () => {
65790
66194
 
65791
66195
  // src/commands/app/new.ts
65792
66196
  import { stat as stat8, writeFile as writeFile9, mkdir as mkdir5 } from "node:fs/promises";
65793
- import path13 from "node:path";
66197
+ import path15 from "node:path";
65794
66198
  function validateAppPath(appPath) {
65795
66199
  if (!appPath.startsWith("u/") && !appPath.startsWith("f/")) {
65796
66200
  return {
@@ -65995,7 +66399,7 @@ CREATE SCHEMA IF NOT EXISTS ${schemaName};
65995
66399
  }
65996
66400
  await loadNonDottedPathsSetting();
65997
66401
  const folderName = buildFolderPath(appPath, "raw_app");
65998
- const appDir = path13.join(process.cwd(), folderName);
66402
+ const appDir = path15.join(process.cwd(), folderName);
65999
66403
  try {
66000
66404
  await stat8(appDir);
66001
66405
  const overwrite = await Confirm.prompt({
@@ -66008,17 +66412,17 @@ CREATE SCHEMA IF NOT EXISTS ${schemaName};
66008
66412
  }
66009
66413
  } catch {}
66010
66414
  await mkdir5(appDir, { recursive: true });
66011
- await mkdir5(path13.join(appDir, "backend"), { recursive: true });
66012
- await mkdir5(path13.join(appDir, "sql_to_apply"), { recursive: true });
66415
+ await mkdir5(path15.join(appDir, "backend"), { recursive: true });
66416
+ await mkdir5(path15.join(appDir, "sql_to_apply"), { recursive: true });
66013
66417
  const rawAppConfig = {
66014
66418
  summary
66015
66419
  };
66016
66420
  if (dataConfig.datatable) {
66017
66421
  rawAppConfig.data = dataConfig;
66018
66422
  }
66019
- await writeFile9(path13.join(appDir, "raw_app.yaml"), import_yaml21.stringify(rawAppConfig, yamlOptions), "utf-8");
66423
+ await writeFile9(path15.join(appDir, "raw_app.yaml"), import_yaml21.stringify(rawAppConfig, yamlOptions), "utf-8");
66020
66424
  for (const [filePath, content] of Object.entries(template.files)) {
66021
- const fullPath = path13.join(appDir, filePath.slice(1));
66425
+ const fullPath = path15.join(appDir, filePath.slice(1));
66022
66426
  await writeFile9(fullPath, content.trim() + `
66023
66427
  `, "utf-8");
66024
66428
  }
@@ -66028,21 +66432,21 @@ CREATE SCHEMA IF NOT EXISTS ${schemaName};
66028
66432
  schema: dataConfig.schema
66029
66433
  } : undefined;
66030
66434
  const agentsContent = generateAgentsDocumentation(dataForDocs);
66031
- await writeFile9(path13.join(appDir, "AGENTS.md"), agentsContent, "utf-8");
66032
- await writeFile9(path13.join(appDir, "CLAUDE.md"), `Instructions are in @AGENTS.md
66435
+ await writeFile9(path15.join(appDir, "AGENTS.md"), agentsContent, "utf-8");
66436
+ await writeFile9(path15.join(appDir, "CLAUDE.md"), `Instructions are in @AGENTS.md
66033
66437
  `, "utf-8");
66034
66438
  const datatablesContent = generateDatatablesDocumentation(dataForDocs);
66035
- await writeFile9(path13.join(appDir, "DATATABLES.md"), datatablesContent, "utf-8");
66439
+ await writeFile9(path15.join(appDir, "DATATABLES.md"), datatablesContent, "utf-8");
66036
66440
  const exampleRunnable = {
66037
66441
  type: "inline",
66038
66442
  path: undefined
66039
66443
  };
66040
- await writeFile9(path13.join(appDir, "backend", "a.yaml"), import_yaml21.stringify(exampleRunnable, yamlOptions), "utf-8");
66041
- await writeFile9(path13.join(appDir, "backend", "a.ts"), `export async function main(x: number): Promise<string> {
66444
+ await writeFile9(path15.join(appDir, "backend", "a.yaml"), import_yaml21.stringify(exampleRunnable, yamlOptions), "utf-8");
66445
+ await writeFile9(path15.join(appDir, "backend", "a.ts"), `export async function main(x: number): Promise<string> {
66042
66446
  return \`Hello from backend! x = \${x}\`;
66043
66447
  }
66044
66448
  `, "utf-8");
66045
- await writeFile9(path13.join(appDir, "sql_to_apply", "README.md"), `# SQL Migrations Folder
66449
+ await writeFile9(path15.join(appDir, "sql_to_apply", "README.md"), `# SQL Migrations Folder
66046
66450
 
66047
66451
  This folder is for SQL migration files that will be applied to datatables during development.
66048
66452
 
@@ -66070,7 +66474,7 @@ This folder is for SQL migration files that will be applied to datatables during
66070
66474
  - Use idempotent SQL (\`CREATE TABLE IF NOT EXISTS\`, etc.)
66071
66475
  `);
66072
66476
  if (createSchemaSQL && schemaName) {
66073
- await writeFile9(path13.join(appDir, "sql_to_apply", `000_create_schema_${schemaName}.sql`), createSchemaSQL, "utf-8");
66477
+ await writeFile9(path15.join(appDir, "sql_to_apply", `000_create_schema_${schemaName}.sql`), createSchemaSQL, "utf-8");
66074
66478
  }
66075
66479
  info("");
66076
66480
  info(colors.bold.green(`App created successfully at ${folderName}/`));
@@ -66364,8 +66768,8 @@ async function pushApp(workspace, remotePath, localPath, message) {
66364
66768
  if (!localPath.endsWith(SEP13)) {
66365
66769
  localPath += SEP13;
66366
66770
  }
66367
- const path14 = localPath + "app.yaml";
66368
- const localApp = await yamlParseFile(path14);
66771
+ const path16 = localPath + "app.yaml";
66772
+ const localApp = await yamlParseFile(path16);
66369
66773
  replaceInlineScripts2(localApp.value, localPath, true);
66370
66774
  await generatingPolicy2(localApp, remotePath, localApp?.["public"] ?? localApp?.["policy"]?.["execution_mode"] == "anonymous");
66371
66775
  if (app) {
@@ -66394,13 +66798,13 @@ async function pushApp(workspace, remotePath, localPath, message) {
66394
66798
  });
66395
66799
  }
66396
66800
  }
66397
- async function generatingPolicy2(app, path14, publicApp) {
66398
- info(colors.gray(`Generating fresh policy for app ${path14}...`));
66801
+ async function generatingPolicy2(app, path16, publicApp) {
66802
+ info(colors.gray(`Generating fresh policy for app ${path16}...`));
66399
66803
  try {
66400
66804
  app.policy = await updatePolicy(app.value, undefined);
66401
66805
  app.policy.execution_mode = publicApp ? "anonymous" : "publisher";
66402
66806
  } catch (e) {
66403
- error(colors.red(`Error generating policy for app ${path14}: ${e}`));
66807
+ error(colors.red(`Error generating policy for app ${path16}: ${e}`));
66404
66808
  throw e;
66405
66809
  }
66406
66810
  }
@@ -66429,12 +66833,12 @@ async function list4(opts) {
66429
66833
  new Table2().header(["path", "summary"]).padding(2).border(true).body(total.map((x) => [x.path, x.summary])).render();
66430
66834
  }
66431
66835
  }
66432
- async function get3(opts, path14) {
66836
+ async function get3(opts, path16) {
66433
66837
  const workspace = await resolveWorkspace(opts);
66434
66838
  await requireLogin(opts);
66435
66839
  const a = await getAppByPath({
66436
66840
  workspace: workspace.workspaceId,
66437
- path: path14
66841
+ path: path16
66438
66842
  });
66439
66843
  if (opts.json) {
66440
66844
  console.log(JSON.stringify(a));
@@ -66695,9 +67099,9 @@ function compileResourceTypeToTsType(schema) {
66695
67099
  }
66696
67100
 
66697
67101
  // src/commands/resource-type/resource-type.ts
66698
- import { writeFileSync as writeFileSync3 } from "node:fs";
67102
+ import { writeFileSync as writeFileSync4 } from "node:fs";
66699
67103
  import { stat as stat10, writeFile as writeFile11 } from "node:fs/promises";
66700
- import path14 from "node:path";
67104
+ import path16 from "node:path";
66701
67105
  import process16 from "node:process";
66702
67106
  async function pushResourceType(workspace, remotePath, resource, localResource) {
66703
67107
  remotePath = removeType(remotePath, "resource-type");
@@ -66777,12 +67181,12 @@ async function newResourceType(opts, name) {
66777
67181
  });
66778
67182
  info(colors.green(`Created ${filePath}`));
66779
67183
  }
66780
- async function get5(opts, path15) {
67184
+ async function get5(opts, path17) {
66781
67185
  const workspace = await resolveWorkspace(opts);
66782
67186
  await requireLogin(opts);
66783
67187
  const rt = await getResourceType({
66784
67188
  workspace: workspace.workspaceId,
66785
- path: path15
67189
+ path: path17
66786
67190
  });
66787
67191
  if (opts.json) {
66788
67192
  console.log(JSON.stringify(rt));
@@ -66812,7 +67216,7 @@ async function generateRTNamespace(opts) {
66812
67216
  `);
66813
67217
  namespaceContent += `
66814
67218
  }`;
66815
- writeFileSync3(path14.join(process16.cwd(), "rt.d.ts"), namespaceContent);
67219
+ writeFileSync4(path16.join(process16.cwd(), "rt.d.ts"), namespaceContent);
66816
67220
  info(colors.green("Created rt.d.ts with resource types namespace (RT) for TypeScript."));
66817
67221
  }
66818
67222
  var import_yaml24, command13, resource_type_default;
@@ -66853,11 +67257,11 @@ async function list7(opts) {
66853
67257
  ])).render();
66854
67258
  }
66855
67259
  }
66856
- async function newVariable(opts, path15) {
66857
- if (!validatePath(path15)) {
67260
+ async function newVariable(opts, path17) {
67261
+ if (!validatePath(path17)) {
66858
67262
  return;
66859
67263
  }
66860
- const filePath = path15 + ".variable.yaml";
67264
+ const filePath = path17 + ".variable.yaml";
66861
67265
  try {
66862
67266
  await stat11(filePath);
66863
67267
  throw new Error("File already exists: " + filePath);
@@ -66876,12 +67280,12 @@ async function newVariable(opts, path15) {
66876
67280
  });
66877
67281
  info(colors.green(`Created ${filePath}`));
66878
67282
  }
66879
- async function get6(opts, path15) {
67283
+ async function get6(opts, path17) {
66880
67284
  const workspace = await resolveWorkspace(opts);
66881
67285
  await requireLogin(opts);
66882
67286
  const v = await getVariable({
66883
67287
  workspace: workspace.workspaceId,
66884
- path: path15
67288
+ path: path17
66885
67289
  });
66886
67290
  if (opts.json) {
66887
67291
  console.log(JSON.stringify(v));
@@ -67007,11 +67411,11 @@ async function list8(opts) {
67007
67411
  new Table2().header(["Path", "Schedule"]).padding(2).border(true).body(schedules.map((x) => [x.path, x.schedule])).render();
67008
67412
  }
67009
67413
  }
67010
- async function newSchedule(opts, path15) {
67011
- if (!validatePath(path15)) {
67414
+ async function newSchedule(opts, path17) {
67415
+ if (!validatePath(path17)) {
67012
67416
  return;
67013
67417
  }
67014
- const filePath = path15 + ".schedule.yaml";
67418
+ const filePath = path17 + ".schedule.yaml";
67015
67419
  try {
67016
67420
  await stat12(filePath);
67017
67421
  throw new Error("File already exists: " + filePath);
@@ -67034,12 +67438,12 @@ async function newSchedule(opts, path15) {
67034
67438
  });
67035
67439
  info(colors.green(`Created ${filePath}`));
67036
67440
  }
67037
- async function get7(opts, path15) {
67441
+ async function get7(opts, path17) {
67038
67442
  const workspace = await resolveWorkspace(opts);
67039
67443
  await requireLogin(opts);
67040
67444
  const s = await getSchedule({
67041
67445
  workspace: workspace.workspaceId,
67042
- path: path15
67446
+ path: path17
67043
67447
  });
67044
67448
  if (opts.json) {
67045
67449
  console.log(JSON.stringify(s));
@@ -67052,35 +67456,35 @@ async function get7(opts, path15) {
67052
67456
  console.log(colors.bold("Enabled:") + " " + (s.enabled ? "true" : "false"));
67053
67457
  }
67054
67458
  }
67055
- async function pushSchedule(workspace, path15, schedule, localSchedule) {
67056
- path15 = removeType(path15, "schedule").replaceAll(SEP16, "/");
67057
- debug(`Processing local schedule ${path15}`);
67459
+ async function pushSchedule(workspace, path17, schedule, localSchedule) {
67460
+ path17 = removeType(path17, "schedule").replaceAll(SEP16, "/");
67461
+ debug(`Processing local schedule ${path17}`);
67058
67462
  try {
67059
- schedule = await getSchedule({ workspace, path: path15 });
67060
- debug(`Schedule ${path15} exists on remote`);
67463
+ schedule = await getSchedule({ workspace, path: path17 });
67464
+ debug(`Schedule ${path17} exists on remote`);
67061
67465
  } catch {
67062
- debug(`Schedule ${path15} does not exist on remote`);
67466
+ debug(`Schedule ${path17} does not exist on remote`);
67063
67467
  }
67064
67468
  if (schedule) {
67065
67469
  if (isSuperset(localSchedule, schedule)) {
67066
- debug(`Schedule ${path15} is up to date`);
67470
+ debug(`Schedule ${path17} is up to date`);
67067
67471
  return;
67068
67472
  }
67069
- debug(`Updating schedule ${path15}`);
67473
+ debug(`Updating schedule ${path17}`);
67070
67474
  try {
67071
- info(colors.bold.yellow(`Updating schedule ${path15}`));
67475
+ info(colors.bold.yellow(`Updating schedule ${path17}`));
67072
67476
  await updateSchedule({
67073
67477
  workspace,
67074
- path: path15,
67478
+ path: path17,
67075
67479
  requestBody: {
67076
67480
  ...localSchedule
67077
67481
  }
67078
67482
  });
67079
67483
  if (localSchedule.enabled != schedule.enabled) {
67080
- info(colors.bold.yellow(`Schedule ${path15} is ${localSchedule.enabled ? "enabled" : "disabled"} locally but not on remote, updating remote`));
67484
+ info(colors.bold.yellow(`Schedule ${path17} is ${localSchedule.enabled ? "enabled" : "disabled"} locally but not on remote, updating remote`));
67081
67485
  await setScheduleEnabled({
67082
67486
  workspace,
67083
- path: path15,
67487
+ path: path17,
67084
67488
  requestBody: {
67085
67489
  enabled: localSchedule.enabled
67086
67490
  }
@@ -67091,12 +67495,12 @@ async function pushSchedule(workspace, path15, schedule, localSchedule) {
67091
67495
  throw e;
67092
67496
  }
67093
67497
  } else {
67094
- console.log(colors.bold.yellow("Creating new schedule " + path15));
67498
+ console.log(colors.bold.yellow("Creating new schedule " + path17));
67095
67499
  try {
67096
67500
  await createSchedule({
67097
67501
  workspace,
67098
67502
  requestBody: {
67099
- path: path15,
67503
+ path: path17,
67100
67504
  ...localSchedule
67101
67505
  }
67102
67506
  });
@@ -67764,7 +68168,7 @@ var init_settings = __esm(async () => {
67764
68168
  // src/commands/instance/instance.ts
67765
68169
  import { readFile as readFile13, writeFile as writeFile15, readdir as readdir8, mkdir as mkdir7, rm as rm3, stat as stat13 } from "node:fs/promises";
67766
68170
  import { appendFile } from "node:fs/promises";
67767
- import * as path15 from "node:path";
68171
+ import * as path17 from "node:path";
67768
68172
  async function allInstances() {
67769
68173
  try {
67770
68174
  const file = await getInstancesConfigFilePath();
@@ -67941,7 +68345,7 @@ async function instancePull(opts) {
67941
68345
  if (confirm) {
67942
68346
  if (uChanges > 0) {
67943
68347
  if (opts.folderPerInstance && opts.prefixSettings) {
67944
- await mkdir7(path15.join(rootDir, opts.prefix), {
68348
+ await mkdir7(path17.join(rootDir, opts.prefix), {
67945
68349
  recursive: true
67946
68350
  });
67947
68351
  }
@@ -67975,10 +68379,10 @@ Pulling all workspaces`);
67975
68379
  info(`
67976
68380
  Pulling workspace ` + remoteWorkspace.id);
67977
68381
  const workspaceName = opts?.folderPerInstance ? instance.prefix + "/" + remoteWorkspace.id : instance.prefix + "_" + remoteWorkspace.id;
67978
- await mkdir7(path15.join(rootDir, workspaceName), {
68382
+ await mkdir7(path17.join(rootDir, workspaceName), {
67979
68383
  recursive: true
67980
68384
  });
67981
- process.chdir(path15.join(rootDir, workspaceName));
68385
+ process.chdir(path17.join(rootDir, workspaceName));
67982
68386
  await addWorkspace({
67983
68387
  remote: instance.remote,
67984
68388
  name: workspaceName,
@@ -68013,7 +68417,7 @@ Pulling workspace ` + remoteWorkspace.id);
68013
68417
  if (confirmDelete) {
68014
68418
  for (const workspace of localWorkspacesToDelete) {
68015
68419
  await removeWorkspace(workspace.id, false, {});
68016
- await rm3(path15.join(rootDir, workspace.dir), {
68420
+ await rm3(path17.join(rootDir, workspace.dir), {
68017
68421
  recursive: true
68018
68422
  });
68019
68423
  }
@@ -68102,12 +68506,12 @@ Pushing all workspaces: ${localWorkspaces.map((x) => x.id).join(", ")}`);
68102
68506
  info(`
68103
68507
  Pushing workspace ` + localWorkspace.id);
68104
68508
  try {
68105
- process.chdir(path15.join(rootDir, localWorkspace.dir));
68509
+ process.chdir(path17.join(rootDir, localWorkspace.dir));
68106
68510
  } catch (_) {
68107
68511
  throw new Error("Workspace folder not found, are you in the right directory?");
68108
68512
  }
68109
68513
  try {
68110
- const workspaceSettings = await yamlParseFile(path15.join(process.cwd(), "settings.yaml"));
68514
+ const workspaceSettings = await yamlParseFile(path17.join(process.cwd(), "settings.yaml"));
68111
68515
  await add({
68112
68516
  token: instance.token,
68113
68517
  workspace: undefined,
@@ -68355,8 +68759,8 @@ async function createToken2(opts) {
68355
68759
  }
68356
68760
  info("Token: " + await createToken({ requestBody: {} }));
68357
68761
  }
68358
- async function pushWorkspaceUser(workspace, path16, user, localUser) {
68359
- const email = removePathPrefix(removeType(path16, "user"), "users");
68762
+ async function pushWorkspaceUser(workspace, path18, user, localUser) {
68763
+ const email = removePathPrefix(removeType(path18, "user"), "users");
68360
68764
  debug(`Processing local user ${email}`);
68361
68765
  if (!["operator", "developer", "admin"].includes(localUser.role)) {
68362
68766
  throw new Error(`Invalid role for user ${email}: ${localUser.role}`);
@@ -68419,8 +68823,8 @@ async function pushWorkspaceUser(workspace, path16, user, localUser) {
68419
68823
  }
68420
68824
  }
68421
68825
  }
68422
- async function pushGroup(workspace, path16, group, localGroup) {
68423
- const name = removePathPrefix(removeType(path16, "group"), "groups");
68826
+ async function pushGroup(workspace, path18, group, localGroup) {
68827
+ const name = removePathPrefix(removeType(path18, "group"), "groups");
68424
68828
  debug(`Processing local group ${name}`);
68425
68829
  try {
68426
68830
  const remoteGroup = await getGroup({
@@ -68671,11 +69075,11 @@ async function push9(opts, filePath) {
68671
69075
  const content = fs12.readFileSync(filePath, "utf8");
68672
69076
  await pushWorkspaceDependencies(workspace.workspaceId, filePath, null, content);
68673
69077
  }
68674
- async function pushWorkspaceDependencies(workspace, path16, _befObj, newDependenciesContent) {
69078
+ async function pushWorkspaceDependencies(workspace, path18, _befObj, newDependenciesContent) {
68675
69079
  try {
68676
- const res = workspaceDependenciesPathToLanguageAndFilename(path16);
69080
+ const res = workspaceDependenciesPathToLanguageAndFilename(path18);
68677
69081
  if (!res) {
68678
- throw new Error(`Unknown workspace dependencies file format: ${path16}`);
69082
+ throw new Error(`Unknown workspace dependencies file format: ${path18}`);
68679
69083
  }
68680
69084
  const { language, name } = res;
68681
69085
  const displayName = name ? `named dependencies "${name}"` : `workspace default dependencies`;
@@ -68729,7 +69133,7 @@ var init_dependencies = __esm(async () => {
68729
69133
  // src/commands/trigger/trigger.ts
68730
69134
  import { stat as stat14, writeFile as writeFile17 } from "node:fs/promises";
68731
69135
  import { sep as SEP17 } from "node:path";
68732
- async function getTrigger(triggerType, workspace, path16) {
69136
+ async function getTrigger(triggerType, workspace, path18) {
68733
69137
  const triggerFunctions = {
68734
69138
  http: getHttpTrigger,
68735
69139
  websocket: getWebsocketTrigger,
@@ -68742,10 +69146,10 @@ async function getTrigger(triggerType, workspace, path16) {
68742
69146
  email: getEmailTrigger
68743
69147
  };
68744
69148
  const triggerFunction = triggerFunctions[triggerType];
68745
- const trigger = await triggerFunction({ workspace, path: path16 });
69149
+ const trigger = await triggerFunction({ workspace, path: path18 });
68746
69150
  return trigger;
68747
69151
  }
68748
- async function updateTrigger(triggerType, workspace, path16, trigger) {
69152
+ async function updateTrigger(triggerType, workspace, path18, trigger) {
68749
69153
  const triggerFunctions = {
68750
69154
  http: updateHttpTrigger,
68751
69155
  websocket: updateWebsocketTrigger,
@@ -68758,9 +69162,9 @@ async function updateTrigger(triggerType, workspace, path16, trigger) {
68758
69162
  email: updateEmailTrigger
68759
69163
  };
68760
69164
  const triggerFunction = triggerFunctions[triggerType];
68761
- await triggerFunction({ workspace, path: path16, requestBody: trigger });
69165
+ await triggerFunction({ workspace, path: path18, requestBody: trigger });
68762
69166
  }
68763
- async function createTrigger(triggerType, workspace, path16, trigger) {
69167
+ async function createTrigger(triggerType, workspace, path18, trigger) {
68764
69168
  const triggerFunctions = {
68765
69169
  http: createHttpTrigger,
68766
69170
  websocket: createWebsocketTrigger,
@@ -68773,38 +69177,38 @@ async function createTrigger(triggerType, workspace, path16, trigger) {
68773
69177
  email: createEmailTrigger
68774
69178
  };
68775
69179
  const triggerFunction = triggerFunctions[triggerType];
68776
- await triggerFunction({ workspace, path: path16, requestBody: trigger });
69180
+ await triggerFunction({ workspace, path: path18, requestBody: trigger });
68777
69181
  }
68778
- async function pushTrigger(triggerType, workspace, path16, trigger, localTrigger) {
68779
- path16 = removeType(path16, triggerType + "_trigger").replaceAll(SEP17, "/");
68780
- debug(`Processing local ${triggerType} trigger ${path16}`);
69182
+ async function pushTrigger(triggerType, workspace, path18, trigger, localTrigger) {
69183
+ path18 = removeType(path18, triggerType + "_trigger").replaceAll(SEP17, "/");
69184
+ debug(`Processing local ${triggerType} trigger ${path18}`);
68781
69185
  try {
68782
- trigger = await getTrigger(triggerType, workspace, path16);
68783
- debug(`${triggerType} trigger ${path16} exists on remote`);
69186
+ trigger = await getTrigger(triggerType, workspace, path18);
69187
+ debug(`${triggerType} trigger ${path18} exists on remote`);
68784
69188
  } catch {
68785
- debug(`${triggerType} trigger ${path16} does not exist on remote`);
69189
+ debug(`${triggerType} trigger ${path18} does not exist on remote`);
68786
69190
  }
68787
69191
  if (trigger) {
68788
69192
  if (isSuperset(localTrigger, trigger)) {
68789
- debug(`${triggerType} trigger ${path16} is up to date`);
69193
+ debug(`${triggerType} trigger ${path18} is up to date`);
68790
69194
  return;
68791
69195
  }
68792
- debug(`${triggerType} trigger ${path16} is not up-to-date, updating...`);
69196
+ debug(`${triggerType} trigger ${path18} is not up-to-date, updating...`);
68793
69197
  try {
68794
- await updateTrigger(triggerType, workspace, path16, {
69198
+ await updateTrigger(triggerType, workspace, path18, {
68795
69199
  ...localTrigger,
68796
- path: path16
69200
+ path: path18
68797
69201
  });
68798
69202
  } catch (e) {
68799
69203
  console.error(e.body);
68800
69204
  throw e;
68801
69205
  }
68802
69206
  } else {
68803
- console.log(colors.bold.yellow(`Creating new ${triggerType} trigger: ${path16}`));
69207
+ console.log(colors.bold.yellow(`Creating new ${triggerType} trigger: ${path18}`));
68804
69208
  try {
68805
- await createTrigger(triggerType, workspace, path16, {
69209
+ await createTrigger(triggerType, workspace, path18, {
68806
69210
  ...localTrigger,
68807
- path: path16
69211
+ path: path18
68808
69212
  });
68809
69213
  } catch (e) {
68810
69214
  console.error(e.body);
@@ -68885,8 +69289,8 @@ async function pushNativeTrigger(workspace, filePath, _remoteTrigger, localTrigg
68885
69289
  }
68886
69290
  }
68887
69291
  }
68888
- async function newTrigger(opts, path16) {
68889
- if (!validatePath(path16)) {
69292
+ async function newTrigger(opts, path18) {
69293
+ if (!validatePath(path18)) {
68890
69294
  return;
68891
69295
  }
68892
69296
  if (!opts.kind) {
@@ -68896,7 +69300,7 @@ async function newTrigger(opts, path16) {
68896
69300
  throw new Error("Invalid trigger kind: " + opts.kind + ". Valid kinds: " + TRIGGER_TYPES.join(", "));
68897
69301
  }
68898
69302
  const kind = opts.kind;
68899
- const filePath = `${path16}.${kind}_trigger.yaml`;
69303
+ const filePath = `${path18}.${kind}_trigger.yaml`;
68900
69304
  try {
68901
69305
  await stat14(filePath);
68902
69306
  throw new Error("File already exists: " + filePath);
@@ -68911,14 +69315,14 @@ async function newTrigger(opts, path16) {
68911
69315
  });
68912
69316
  info(colors.green(`Created ${filePath}`));
68913
69317
  }
68914
- async function get8(opts, path16) {
69318
+ async function get8(opts, path18) {
68915
69319
  const workspace = await resolveWorkspace(opts);
68916
69320
  await requireLogin(opts);
68917
69321
  if (opts.kind) {
68918
69322
  if (!checkIfValidTrigger(opts.kind)) {
68919
69323
  throw new Error("Invalid trigger kind: " + opts.kind + ". Valid kinds: " + TRIGGER_TYPES.join(", "));
68920
69324
  }
68921
- const trigger = await getTrigger(opts.kind, workspace.workspaceId, path16);
69325
+ const trigger = await getTrigger(opts.kind, workspace.workspaceId, path18);
68922
69326
  if (opts.json) {
68923
69327
  console.log(JSON.stringify(trigger));
68924
69328
  } else {
@@ -68933,12 +69337,12 @@ async function get8(opts, path16) {
68933
69337
  const matches = [];
68934
69338
  for (const kind of TRIGGER_TYPES) {
68935
69339
  try {
68936
- const trigger = await getTrigger(kind, workspace.workspaceId, path16);
69340
+ const trigger = await getTrigger(kind, workspace.workspaceId, path18);
68937
69341
  matches.push({ kind, trigger });
68938
69342
  } catch {}
68939
69343
  }
68940
69344
  if (matches.length === 0) {
68941
- throw new Error("No trigger found at path: " + path16);
69345
+ throw new Error("No trigger found at path: " + path18);
68942
69346
  }
68943
69347
  if (matches.length === 1) {
68944
69348
  const { kind, trigger } = matches[0];
@@ -68953,7 +69357,7 @@ async function get8(opts, path16) {
68953
69357
  }
68954
69358
  return;
68955
69359
  }
68956
- console.log("Multiple triggers found at path " + path16 + ":");
69360
+ console.log("Multiple triggers found at path " + path18 + ":");
68957
69361
  for (const m of matches) {
68958
69362
  console.log(" - " + m.kind);
68959
69363
  }
@@ -69131,7 +69535,7 @@ var init_trigger = __esm(async () => {
69131
69535
  });
69132
69536
 
69133
69537
  // src/types.ts
69134
- import * as path16 from "node:path";
69538
+ import * as path18 from "node:path";
69135
69539
  import { sep as SEP18 } from "node:path";
69136
69540
  import { readFileSync as readFileSync5 } from "node:fs";
69137
69541
  function isSuperset(subset, superset) {
@@ -69176,8 +69580,8 @@ function showDiff(local, remote) {
69176
69580
  }
69177
69581
  info(finalString);
69178
69582
  }
69179
- function showConflict(path17, local, remote) {
69180
- info(colors.yellow(`- ${path17}`));
69583
+ function showConflict(path19, local, remote) {
69584
+ info(colors.yellow(`- ${path19}`));
69181
69585
  showDiff(local, remote);
69182
69586
  info("\x1B[31mlocal\x1B[31m - \x1B[32mremote\x1B[32m");
69183
69587
  info(`
@@ -69254,6 +69658,9 @@ function parseFromFile(p) {
69254
69658
  }
69255
69659
  }
69256
69660
  function getTypeStrFromPath(p) {
69661
+ if (isScriptModulePath(p)) {
69662
+ return "script";
69663
+ }
69257
69664
  if (isFlowPath(p)) {
69258
69665
  return "flow";
69259
69666
  }
@@ -69266,7 +69673,7 @@ function getTypeStrFromPath(p) {
69266
69673
  if (p.startsWith("dependencies" + SEP18)) {
69267
69674
  return "workspace_dependencies";
69268
69675
  }
69269
- const parsed = path16.parse(p);
69676
+ const parsed = path18.parse(p);
69270
69677
  if (parsed.ext == ".go" || parsed.ext == ".ts" || parsed.ext == ".sh" || parsed.ext == ".py" || parsed.ext == ".sql" || parsed.ext == ".gql" || parsed.ext == ".ps1" || parsed.ext == ".js" || parsed.ext == ".php" || parsed.ext == ".rs" || parsed.ext == ".cs" || parsed.ext == ".nu" || parsed.ext == ".java" || parsed.ext == ".rb" || parsed.ext == ".yml" && parsed.name.split(".").pop() == "playbook") {
69271
69678
  return "script";
69272
69679
  }
@@ -69293,14 +69700,14 @@ function getTypeStrFromPath(p) {
69293
69700
  }
69294
69701
  }
69295
69702
  function removeType(str, type) {
69296
- const normalizedStr = path16.normalize(str).replaceAll(SEP18, "/");
69703
+ const normalizedStr = path18.normalize(str).replaceAll(SEP18, "/");
69297
69704
  if (!normalizedStr.endsWith("." + type + ".yaml") && !normalizedStr.endsWith("." + type + ".json")) {
69298
69705
  throw new Error(str + " does not end with ." + type + ".(yaml|json)");
69299
69706
  }
69300
69707
  return normalizedStr.slice(0, normalizedStr.length - type.length - 6);
69301
69708
  }
69302
69709
  function extractNativeTriggerInfo(p) {
69303
- const normalizedPath = path16.normalize(p).replaceAll(SEP18, "/");
69710
+ const normalizedPath = path18.normalize(p).replaceAll(SEP18, "/");
69304
69711
  const withoutExt = normalizedPath.replace(/\.(json|yaml)$/, "");
69305
69712
  const match2 = withoutExt.match(/^(.+)\.(flow|script)\.([^.]+)\.(\w+)_native_trigger$/);
69306
69713
  if (!match2) {
@@ -69314,8 +69721,8 @@ function extractNativeTriggerInfo(p) {
69314
69721
  };
69315
69722
  }
69316
69723
  function removePathPrefix(str, prefix) {
69317
- const normalizedStr = path16.normalize(str).replaceAll(SEP18, "/");
69318
- const normalizedPrefix = path16.normalize(prefix).replaceAll(SEP18, "/");
69724
+ const normalizedStr = path18.normalize(str).replaceAll(SEP18, "/");
69725
+ const normalizedPrefix = path18.normalize(prefix).replaceAll(SEP18, "/");
69319
69726
  if (normalizedStr === normalizedPrefix) {
69320
69727
  return "";
69321
69728
  }
@@ -69385,7 +69792,7 @@ function defaultFlowDefinition() {
69385
69792
  // src/commands/flow/flow.ts
69386
69793
  import { sep as SEP19 } from "node:path";
69387
69794
  import { readFile as readFile14 } from "node:fs/promises";
69388
- import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "node:fs";
69795
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
69389
69796
  async function pushFlow(workspace, remotePath, localPath, message) {
69390
69797
  if (alreadySynced3.includes(localPath)) {
69391
69798
  return;
@@ -69403,7 +69810,7 @@ async function pushFlow(workspace, remotePath, localPath, message) {
69403
69810
  localPath += SEP19;
69404
69811
  }
69405
69812
  const localFlow = await yamlParseFile(localPath + "flow.yaml");
69406
- const fileReader = async (path17) => await readFile14(localPath + path17, "utf-8");
69813
+ const fileReader = async (path19) => await readFile14(localPath + path19, "utf-8");
69407
69814
  await replaceInlineScripts(localFlow.value.modules, fileReader, exports_log, localPath, SEP19);
69408
69815
  if (localFlow.value.failure_module) {
69409
69816
  await replaceInlineScripts([localFlow.value.failure_module], fileReader, exports_log, localPath, SEP19);
@@ -69477,12 +69884,12 @@ async function list11(opts) {
69477
69884
  new Table2().header(["path", "summary", "edited by"]).padding(2).border(true).body(total.map((x) => [x.path, x.summary, x.edited_by])).render();
69478
69885
  }
69479
69886
  }
69480
- async function get9(opts, path17) {
69887
+ async function get9(opts, path19) {
69481
69888
  const workspace = await resolveWorkspace(opts);
69482
69889
  await requireLogin(opts);
69483
69890
  const f = await getFlowByPath({
69484
69891
  workspace: workspace.workspaceId,
69485
- path: path17
69892
+ path: path19
69486
69893
  });
69487
69894
  if (opts.json) {
69488
69895
  console.log(JSON.stringify(f));
@@ -69494,13 +69901,13 @@ async function get9(opts, path17) {
69494
69901
  console.log(colors.bold("Edited at:") + " " + (f.edited_at ?? ""));
69495
69902
  }
69496
69903
  }
69497
- async function run3(opts, path17) {
69904
+ async function run3(opts, path19) {
69498
69905
  const workspace = await resolveWorkspace(opts);
69499
69906
  await requireLogin(opts);
69500
69907
  const input = opts.data ? await resolve6(opts.data) : {};
69501
69908
  const id = await runFlowByPath({
69502
69909
  workspace: workspace.workspaceId,
69503
- path: path17,
69910
+ path: path19,
69504
69911
  requestBody: input
69505
69912
  });
69506
69913
  let i = 0;
@@ -69552,7 +69959,7 @@ async function preview2(opts, flowPath) {
69552
69959
  flowPath += SEP19;
69553
69960
  }
69554
69961
  const localFlow = await yamlParseFile(flowPath + "flow.yaml");
69555
- const fileReader = async (path17) => await readFile14(flowPath + path17, "utf-8");
69962
+ const fileReader = async (path19) => await readFile14(flowPath + path19, "utf-8");
69556
69963
  await replaceInlineScripts(localFlow.value.modules, fileReader, exports_log, flowPath, SEP19);
69557
69964
  if (localFlow.value.failure_module) {
69558
69965
  await replaceInlineScripts([localFlow.value.failure_module], fileReader, exports_log, flowPath, SEP19);
@@ -69629,7 +70036,7 @@ function bootstrap2(opts, flowPath) {
69629
70036
  return;
69630
70037
  }
69631
70038
  const flowDirFullPath = `${flowPath}.flow`;
69632
- mkdirSync3(flowDirFullPath, { recursive: false });
70039
+ mkdirSync4(flowDirFullPath, { recursive: false });
69633
70040
  const newFlowDefinition = defaultFlowDefinition();
69634
70041
  if (opts.summary !== undefined) {
69635
70042
  newFlowDefinition.summary = opts.summary;
@@ -69639,7 +70046,7 @@ function bootstrap2(opts, flowPath) {
69639
70046
  }
69640
70047
  const newFlowDefinitionYaml = import_yaml36.stringify(newFlowDefinition);
69641
70048
  const flowYamlPath = `${flowDirFullPath}/flow.yaml`;
69642
- writeFileSync4(flowYamlPath, newFlowDefinitionYaml, { flag: "wx", encoding: "utf-8" });
70049
+ writeFileSync5(flowYamlPath, newFlowDefinitionYaml, { flag: "wx", encoding: "utf-8" });
69643
70050
  }
69644
70051
  var import_yaml36, alreadySynced3, command21, flow_default;
69645
70052
  var init_flow = __esm(async () => {
@@ -69960,8 +70367,8 @@ function outputResult(opts, result) {
69960
70367
  error(colors.red(result.error));
69961
70368
  }
69962
70369
  }
69963
- function normalizeRepoPath(path17) {
69964
- return path17.replace(/^\$res:/, "");
70370
+ function normalizeRepoPath(path19) {
70371
+ return path19.replace(/^\$res:/, "");
69965
70372
  }
69966
70373
  function getOrCreateBranchConfig(config, branchName) {
69967
70374
  if (!config.gitBranches) {
@@ -71958,7 +72365,7 @@ async function dev2(opts) {
71958
72365
  const flowFolderSuffix = getFolderSuffixWithSep("flow");
71959
72366
  const flowMetadataFile = getMetadataFileName("flow", "yaml");
71960
72367
  async function loadPaths(pathsToLoad) {
71961
- const paths = pathsToLoad.filter((path17) => exts.some((ext2) => path17.endsWith(ext2) || path17.endsWith(flowFolderSuffix + flowMetadataFile)));
72368
+ const paths = pathsToLoad.filter((path19) => exts.some((ext2) => path19.endsWith(ext2) || path19.endsWith(flowFolderSuffix + flowMetadataFile)));
71962
72369
  if (paths.length == 0) {
71963
72370
  return;
71964
72371
  }
@@ -71970,7 +72377,7 @@ async function dev2(opts) {
71970
72377
  if (typ == "flow") {
71971
72378
  const localPath = extractFolderPath(cpath, "flow");
71972
72379
  const localFlow = await yamlParseFile(localPath + "flow.yaml");
71973
- await replaceInlineScripts(localFlow.value.modules, async (path17) => await readFile15(localPath + path17, "utf-8"), exports_log, localPath, SEP20, undefined);
72380
+ await replaceInlineScripts(localFlow.value.modules, async (path19) => await readFile15(localPath + path19, "utf-8"), exports_log, localPath, SEP20, undefined);
71974
72381
  currentLastEdit = {
71975
72382
  type: "flow",
71976
72383
  flow: localFlow,
@@ -77617,7 +78024,7 @@ sync local with a remote workspaces or the opposite (push or pull)
77617
78024
  - \`--extra-includes <patterns:file[]>\` - Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string). Useful to still take wmill.yaml into account and act as a second pattern to satisfy
77618
78025
  - \`--repository <repo:string>\` - Specify repository path (e.g., u/user/repo) when multiple repositories exist
77619
78026
  - \`--promotion <branch:string>\` - Use promotionOverrides from the specified branch instead of regular overrides
77620
- - \`--branch <branch:string>\` - Override the current git branch (works even outside a git repository)
78027
+ - \`--branch, --env <branch:string>\` - Override the current git branch/environment (works even outside a git repository)
77621
78028
  - \`sync push\` - Push any local changes and apply them remotely.
77622
78029
  - \`--yes\` - Push without needing confirmation
77623
78030
  - \`--dry-run\` - Show changes that would be pushed without actually pushing
@@ -77647,7 +78054,7 @@ sync local with a remote workspaces or the opposite (push or pull)
77647
78054
  - \`--message <message:string>\` - Include a message that will be added to all scripts/flows/apps updated during this push
77648
78055
  - \`--parallel <number>\` - Number of changes to process in parallel
77649
78056
  - \`--repository <repo:string>\` - Specify repository path (e.g., u/user/repo) when multiple repositories exist
77650
- - \`--branch <branch:string>\` - Override the current git branch (works even outside a git repository)
78057
+ - \`--branch, --env <branch:string>\` - Override the current git branch/environment (works even outside a git repository)
77651
78058
  - \`--lint\` - Run lint validation before pushing
77652
78059
  - \`--locks-required\` - Fail if scripts or flow inline scripts that need locks have no locks
77653
78060
 
@@ -77749,9 +78156,9 @@ workspace related commands
77749
78156
  - \`workspace list\` - List local workspace profiles
77750
78157
  - \`workspace list-remote\` - List workspaces on the remote server that you have access to
77751
78158
  - \`workspace bind\` - Bind the current Git branch to the active workspace
77752
- - \`--branch <branch:string>\` - Specify branch (defaults to current)
78159
+ - \`--branch, --env <branch:string>\` - Specify branch/environment (defaults to current)
77753
78160
  - \`workspace unbind\` - Remove workspace binding from the current Git branch
77754
- - \`--branch <branch:string>\` - Specify branch (defaults to current)
78161
+ - \`--branch, --env <branch:string>\` - Specify branch/environment (defaults to current)
77755
78162
  - \`workspace fork [workspace_name:string] [workspace_id:string]\` - Create a forked workspace
77756
78163
  - \`--create-workspace-name <workspace_name:string>\` - Specify the workspace name. Ignored if --create is not specified or the workspace already exists. Will default to the workspace id.
77757
78164
  - \`workspace delete-fork <fork_name:string>\` - Delete a forked workspace and git branch
@@ -79063,7 +79470,7 @@ async function generateMetadata2(opts, folder) {
79063
79470
  info(colors.gray(`Checking ${checking.join(", ")}...`));
79064
79471
  if (!skipScripts) {
79065
79472
  const scriptElems = await elementsToMap(await FSFSElement(process.cwd(), codebases, false), (p, isD) => {
79066
- return !isD && !exts.some((ext2) => p.endsWith(ext2)) || ignore(p, isD) || isFlowPath(p) || isAppPath(p) || isRawAppPath(p);
79473
+ return !isD && !exts.some((ext2) => p.endsWith(ext2)) || ignore(p, isD) || isFlowPath(p) || isAppPath(p) || isRawAppPath(p) || isScriptModulePath(p) && !isModuleEntryPoint(p);
79067
79474
  }, false, {});
79068
79475
  for (const e of Object.keys(scriptElems)) {
79069
79476
  const candidate = await generateScriptMetadataInternal(e, workspace, opts, true, true, rawWorkspaceDependencies, codebases, false);
@@ -79256,7 +79663,7 @@ var docs_default = command30;
79256
79663
 
79257
79664
  // src/main.ts
79258
79665
  await init_context();
79259
- var VERSION = "1.658.0";
79666
+ var VERSION = "1.659.1";
79260
79667
  var command31 = new Command().name("wmill").action(() => info(`Welcome to Windmill CLI ${VERSION}. Use -h for help.`)).description("Windmill CLI").globalOption("--workspace <workspace:string>", "Specify the target workspace. This overrides the default workspace.").globalOption("--debug --verbose", "Show debug/verbose logs").globalOption("--show-diffs", "Show diff informations when syncing (may show sensitive informations)").globalOption("--token <token:string>", "Specify an API token. This will override any stored token.").globalOption("--base-url <baseUrl:string>", "Specify the base URL of the API. If used, --token and --workspace are required and no local remote/workspace already set will be used.").globalOption("--config-dir <configDir:string>", "Specify a custom config directory. Overrides WMILL_CONFIG_DIR environment variable and default ~/.config location.").env("HEADERS <headers:string>", `Specify headers to use for all requests. e.g: "HEADERS='h1: v1, h2: v2'"`).version(VERSION).versionOption(false).command("init", init_default).command("app", app_default).command("flow", flow_default).command("script", script_default).command("workspace", workspace_default).command("resource", resource_default).command("resource-type", resource_type_default).command("user", user_default).command("variable", variable_default).command("hub", hub_default).command("folder", folder_default).command("schedule", schedule_default).command("trigger", trigger_default).command("dev", dev_default2).command("sync", sync_default).command("lint", lint_default).command("gitsync-settings", gitsync_settings_default).command("instance", instance_default).command("worker-groups", worker_groups_default).command("workers", workers_default).command("queues", queues_default).command("dependencies", dependencies_default).command("jobs", jobs_default).command("generate-metadata", generate_metadata_default).command("docs", docs_default).command("version --version", "Show version information").action(async (opts) => {
79261
79668
  console.log("CLI version: " + VERSION);
79262
79669
  try {