windmill-cli 1.667.0 → 1.668.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/esm/main.js +1082 -197
  2. package/package.json +1 -1
package/esm/main.js CHANGED
@@ -4244,6 +4244,7 @@ var exports_log = {};
4244
4244
  __export(exports_log, {
4245
4245
  warn: () => warn,
4246
4246
  setup: () => setup,
4247
+ setSilent: () => setSilent,
4247
4248
  info: () => info,
4248
4249
  error: () => error,
4249
4250
  debug: () => debug
@@ -4251,20 +4252,27 @@ __export(exports_log, {
4251
4252
  function setup(level) {
4252
4253
  logLevel = level;
4253
4254
  }
4255
+ function setSilent(silent) {
4256
+ silentMode = silent;
4257
+ }
4254
4258
  function debug(msg) {
4255
4259
  if (levels[logLevel] <= levels.DEBUG)
4256
4260
  console.log(`\x1B[90m${String(msg)}\x1B[39m`);
4257
4261
  }
4258
4262
  function info(msg) {
4263
+ if (silentMode)
4264
+ return;
4259
4265
  console.log(`\x1B[34m${String(msg)}\x1B[39m`);
4260
4266
  }
4261
4267
  function warn(msg) {
4268
+ if (silentMode)
4269
+ return;
4262
4270
  console.log(`\x1B[33m${String(msg)}\x1B[39m`);
4263
4271
  }
4264
4272
  function error(msg) {
4265
- console.log(`\x1B[31m${String(msg)}\x1B[39m`);
4273
+ console.error(`\x1B[31m${String(msg)}\x1B[39m`);
4266
4274
  }
4267
- var logLevel = "INFO", levels;
4275
+ var logLevel = "INFO", silentMode = false, levels;
4268
4276
  var init_log = __esm(() => {
4269
4277
  levels = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3 };
4270
4278
  });
@@ -11804,7 +11812,7 @@ var init_OpenAPI = __esm(() => {
11804
11812
  PASSWORD: undefined,
11805
11813
  TOKEN: getEnv2("WM_TOKEN"),
11806
11814
  USERNAME: undefined,
11807
- VERSION: "1.667.0",
11815
+ VERSION: "1.668.0",
11808
11816
  WITH_CREDENTIALS: true,
11809
11817
  interceptors: {
11810
11818
  request: new Interceptors,
@@ -19503,6 +19511,10 @@ var init_gen = __esm(() => {
19503
19511
  });
19504
19512
 
19505
19513
  // src/core/client.ts
19514
+ var exports_client = {};
19515
+ __export(exports_client, {
19516
+ setClient: () => setClient
19517
+ });
19506
19518
  function setClient(token, baseUrl2) {
19507
19519
  if (baseUrl2 === undefined) {
19508
19520
  baseUrl2 = process.env["BASE_INTERNAL_URL"] ?? process.env["BASE_URL"] ?? "http://localhost:8000";
@@ -24762,6 +24774,9 @@ function toCamel(s) {
24762
24774
  function capitalize(str) {
24763
24775
  return str.charAt(0).toUpperCase() + str.slice(1);
24764
24776
  }
24777
+ function formatTimestamp(ts) {
24778
+ return new Date(ts).toISOString().replace("T", " ").substring(0, 19);
24779
+ }
24765
24780
  var isWin = undefined;
24766
24781
  var init_utils = __esm(async () => {
24767
24782
  init_colors2();
@@ -25030,28 +25045,46 @@ async function createWorkspaceFork2(opts, workspaceName, workspaceId = undefined
25030
25045
  }
25031
25046
  const newBranchName = `${WM_FORK_PREFIX}/${clonedBranchName}/${workspaceId}`;
25032
25047
  info(`Created forked workspace ${trueWorkspaceId}. To start contributing to your fork, create and push edits to the branch \`${newBranchName}\` by using the command:
25033
-
25048
+
25034
25049
  ` + colors.white(`git checkout -b ${newBranchName}`) + `
25035
-
25036
- When doing operations on the forked workspace, it will use the remote setup in gitBranches for the branch it was forked from.`);
25050
+
25051
+ When doing operations on the forked workspace, it will use the remote setup in gitBranches for the branch it was forked from.
25052
+
25053
+ To merge changes back to the parent workspace, you can:
25054
+ - Use the Merge UI from the forked workspace home page
25055
+ - Deploy individual items via the Deploy to staging/prod UI
25056
+ - Use git: ` + colors.white(`git checkout ${clonedBranchName} && git merge ${newBranchName} && wmill sync push`) + `
25057
+ See: https://www.windmill.dev/docs/advanced/workspace_forks`);
25037
25058
  }
25038
25059
  async function deleteWorkspaceFork(opts, name) {
25060
+ let forkWorkspaceId;
25061
+ let token;
25062
+ let remote;
25063
+ let hasLocalProfile = false;
25039
25064
  const orgWorkspaces = await allWorkspaces(opts.configDir);
25040
25065
  const idxOf = orgWorkspaces.findIndex((x) => x.name === name);
25041
- if (idxOf === -1) {
25042
- info(colors.red.bold(`! Workspace profile ${name} does not exist locally`));
25043
- info("available workspace profiles:");
25044
- await list(opts);
25045
- return;
25046
- }
25047
- const workspace = orgWorkspaces[idxOf];
25048
- if (!workspace.workspaceId.startsWith(WM_FORK_PREFIX)) {
25049
- throw new Error(`You can only delete forked workspaces where the workspace id starts with \`${WM_FORK_PREFIX}.\` Failed while attempting to delete \`${workspace.workspaceId}\``);
25066
+ if (idxOf !== -1) {
25067
+ const workspace = orgWorkspaces[idxOf];
25068
+ if (!workspace.workspaceId.startsWith(WM_FORK_PREFIX)) {
25069
+ throw new Error(`You can only delete forked workspaces where the workspace id starts with \`${WM_FORK_PREFIX}.\` Failed while attempting to delete \`${workspace.workspaceId}\``);
25070
+ }
25071
+ forkWorkspaceId = workspace.workspaceId;
25072
+ token = workspace.token;
25073
+ remote = workspace.remote;
25074
+ hasLocalProfile = true;
25075
+ } else {
25076
+ const parentWorkspace = await tryResolveBranchWorkspace(opts);
25077
+ if (!parentWorkspace) {
25078
+ throw new Error("Could not resolve parent workspace. Make sure you are in a git repo with gitBranches configured in wmill.yaml, or create a local workspace profile for the fork.");
25079
+ }
25080
+ forkWorkspaceId = name.startsWith(`${WM_FORK_PREFIX}-`) ? name : `${WM_FORK_PREFIX}-${name}`;
25081
+ token = parentWorkspace.token;
25082
+ remote = parentWorkspace.remote;
25050
25083
  }
25051
25084
  if (!opts.yes) {
25052
25085
  const { Select: Select2 } = await init_select().then(() => exports_select);
25053
25086
  const choice = await Select2.prompt({
25054
- message: `Are you sure you want to delete the forked workspace with id: \`${workspace.workspaceId}\`? This action will delete the workspace `,
25087
+ message: `Are you sure you want to delete the forked workspace \`${forkWorkspaceId}\`?`,
25055
25088
  options: [
25056
25089
  { name: "Yes", value: "confirm" },
25057
25090
  { name: "No", value: "cancel" }
@@ -25062,14 +25095,15 @@ async function deleteWorkspaceFork(opts, name) {
25062
25095
  return;
25063
25096
  }
25064
25097
  }
25065
- const remote = workspace.remote;
25066
- setClient(workspace.token, remote.endsWith("/") ? remote.substring(0, remote.length - 1) : remote);
25098
+ setClient(token, remote.endsWith("/") ? remote.substring(0, remote.length - 1) : remote);
25067
25099
  const result = await deleteWorkspace({
25068
- workspace: workspace.workspaceId
25100
+ workspace: forkWorkspaceId
25069
25101
  });
25070
- info(colors.green(`✅ Forked workspace '${workspace.workspaceId}' deleted successfully!
25102
+ info(colors.green(`✅ Forked workspace '${forkWorkspaceId}' deleted successfully!
25071
25103
  ${result}`));
25072
- await removeWorkspace(name, false, opts);
25104
+ if (hasLocalProfile) {
25105
+ await removeWorkspace(name, false, opts);
25106
+ }
25073
25107
  }
25074
25108
  var init_fork = __esm(async () => {
25075
25109
  init_colors2();
@@ -25148,11 +25182,14 @@ function findWmillYaml() {
25148
25182
  function getWmillYamlPath() {
25149
25183
  return findWmillYaml();
25150
25184
  }
25151
- async function readConfigFile() {
25185
+ async function readConfigFile(opts) {
25186
+ const warnIfMissing = opts?.warnIfMissing ?? true;
25152
25187
  try {
25153
25188
  const wmillYamlPath = findWmillYaml();
25154
25189
  if (!wmillYamlPath) {
25155
- warn("No wmill.yaml found. Use 'wmill init' to bootstrap it.");
25190
+ if (warnIfMissing) {
25191
+ warn("No wmill.yaml found. Use 'wmill init' to bootstrap it.");
25192
+ }
25156
25193
  return {};
25157
25194
  }
25158
25195
  const conf = await yamlParseFile(wmillYamlPath);
@@ -25382,7 +25419,7 @@ var exports_workspace = {};
25382
25419
  __export(exports_workspace, {
25383
25420
  setActiveWorkspace: () => setActiveWorkspace,
25384
25421
  removeWorkspace: () => removeWorkspace,
25385
- list: () => list,
25422
+ list: () => list2,
25386
25423
  getWorkspaceByName: () => getWorkspaceByName,
25387
25424
  getActiveWorkspaceOrFallback: () => getActiveWorkspaceOrFallback,
25388
25425
  getActiveWorkspace: () => getActiveWorkspace,
@@ -25436,7 +25473,7 @@ async function getWorkspaceByName(workspaceName, configDirOverride) {
25436
25473
  }
25437
25474
  return;
25438
25475
  }
25439
- async function list(opts) {
25476
+ async function list2(opts) {
25440
25477
  const workspaces = await allWorkspaces(opts.configDir);
25441
25478
  const activeName = await getActiveWorkspaceName(opts);
25442
25479
  new Table2().header(["name", "remote", "workspace id"]).padding(2).border(true).body(workspaces.map((x) => {
@@ -25539,8 +25576,12 @@ async function add(opts, workspaceName, workspaceId, remote) {
25539
25576
  info(colors.red.bold(`! Workspace at id ${workspaceId} on ${remote} does not exist. Re-run with --create to create it. Aborting.`));
25540
25577
  info("On that instance and with those credentials, the workspaces that you can access are:");
25541
25578
  const workspaces = await listWorkspaces();
25542
- for (const workspace of workspaces) {
25543
- info(`- ${workspace.id} (name: ${workspace.name})`);
25579
+ if (workspaces.length === 0) {
25580
+ info(" (none)");
25581
+ } else {
25582
+ for (const workspace of workspaces) {
25583
+ info(`- ${workspace.id} (name: ${workspace.name})`);
25584
+ }
25544
25585
  }
25545
25586
  process10.exit(1);
25546
25587
  }
@@ -25608,7 +25649,7 @@ async function removeWorkspace(name, silent, opts) {
25608
25649
  if (!silent) {
25609
25650
  info(colors.red.bold(`! Workspace profile ${name} does not exist locally`));
25610
25651
  info("available workspace profiles:");
25611
- await list(opts);
25652
+ await list2(opts);
25612
25653
  }
25613
25654
  return;
25614
25655
  }
@@ -25631,21 +25672,67 @@ async function whoami2(_opts) {
25631
25672
  const whoamiInfo = await globalWhoami();
25632
25673
  info(JSON.stringify(whoamiInfo, null, 2));
25633
25674
  const activeName = await getActiveWorkspaceName(_opts);
25634
- info("Active: " + colors.green.bold(activeName || "none"));
25675
+ const { getCurrentGitBranch: getCurrentGitBranch2, getOriginalBranchForWorkspaceForks: getOriginalBranchForWorkspaceForks2 } = await Promise.resolve().then(() => (init_git(), exports_git));
25676
+ const branch = getCurrentGitBranch2();
25677
+ const originalBranch = branch ? getOriginalBranchForWorkspaceForks2(branch) : null;
25678
+ if (originalBranch) {
25679
+ const { resolveWorkspace } = await init_context().then(() => exports_context);
25680
+ try {
25681
+ const ws = await resolveWorkspace(_opts);
25682
+ info("Active: " + colors.green.bold(`${activeName || "none"}`) + ` (fork workspace: ${ws.workspaceId})`);
25683
+ } catch {
25684
+ info("Active: " + colors.green.bold(activeName || "none") + " (fork branch)");
25685
+ }
25686
+ } else {
25687
+ info("Active: " + colors.green.bold(activeName || "none"));
25688
+ }
25635
25689
  }
25636
25690
  async function listRemote(_opts) {
25691
+ let remote;
25692
+ if (_opts.baseUrl && _opts.token && !_opts.workspace) {
25693
+ const { setClient: setClient2 } = await Promise.resolve().then(() => (init_client(), exports_client));
25694
+ remote = new URL(_opts.baseUrl).toString();
25695
+ setClient2(_opts.token, remote.replace(/\/$/, ""));
25696
+ } else {
25697
+ const { resolveWorkspace } = await init_context().then(() => exports_context);
25698
+ const workspace = await resolveWorkspace(_opts);
25699
+ await requireLogin(_opts);
25700
+ remote = workspace.remote;
25701
+ }
25702
+ const userWorkspaces = await listUserWorkspaces();
25703
+ const hasForks = userWorkspaces.workspaces.some((x) => x.parent_workspace_id);
25704
+ const headers = hasForks ? ["id", "name", "username", "fork of", "disabled"] : ["id", "name", "username", "disabled"];
25705
+ new Table2().header(headers).padding(2).border(true).body(userWorkspaces.workspaces.map((x) => {
25706
+ const row = [
25707
+ x.id,
25708
+ x.name,
25709
+ x.username
25710
+ ];
25711
+ if (hasForks)
25712
+ row.push(x.parent_workspace_id ?? "-");
25713
+ row.push(x.disabled ? colors.red("true") : "false");
25714
+ return row;
25715
+ })).render();
25716
+ info(`Remote: ${colors.bold(remote)}`);
25717
+ info(`Logged in as: ${colors.green.bold(userWorkspaces.email)}`);
25718
+ }
25719
+ async function listForks(_opts) {
25637
25720
  const { resolveWorkspace } = await init_context().then(() => exports_context);
25638
25721
  const workspace = await resolveWorkspace(_opts);
25639
25722
  await requireLogin(_opts);
25640
25723
  const userWorkspaces = await listUserWorkspaces();
25641
- new Table2().header(["id", "name", "username", "disabled"]).padding(2).border(true).body(userWorkspaces.workspaces.map((x) => [
25724
+ const forks = userWorkspaces.workspaces.filter((w) => w.parent_workspace_id);
25725
+ if (forks.length === 0) {
25726
+ info("No forked workspaces found.");
25727
+ return;
25728
+ }
25729
+ new Table2().header(["id", "name", "fork of", "username"]).padding(2).border(true).body(forks.map((x) => [
25642
25730
  x.id,
25643
25731
  x.name,
25644
- x.username,
25645
- x.disabled ? colors.red("true") : "false"
25732
+ x.parent_workspace_id ?? "",
25733
+ x.username
25646
25734
  ])).render();
25647
25735
  info(`Remote: ${colors.bold(workspace.remote)}`);
25648
- info(`Logged in as: ${colors.green.bold(userWorkspaces.email)}`);
25649
25736
  }
25650
25737
  async function getActiveWorkspaceOrFallback(opts) {
25651
25738
  let activeWorkspace = await getActiveWorkspace(opts);
@@ -25721,9 +25808,9 @@ var init_workspace = __esm(async () => {
25721
25808
  init_auth(),
25722
25809
  init_fork()
25723
25810
  ]);
25724
- 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.", {
25811
+ command = new Command().alias("profile").description("workspace related commands").action(list2).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.", {
25725
25812
  default: "admin"
25726
- }).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);
25813
+ }).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(list2).command("list-remote").description("List workspaces on the remote server that you have access to").action(listRemote).command("list-forks").description("List forked workspaces on the remote server").action(listForks).command("bind").description("Bind the current Git branch to the active workspace. This adds the branch to gitBranches in wmill.yaml so sync operations use the correct workspace for each branch.").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);
25727
25814
  workspace_default = command;
25728
25815
  });
25729
25816
 
@@ -25922,7 +26009,7 @@ async function tryResolveBranchWorkspace(opts, branchOverride) {
25922
26009
  currentBranch = rawBranch;
25923
26010
  }
25924
26011
  }
25925
- const config = await readConfigFile();
26012
+ const config = await readConfigFile({ warnIfMissing: false });
25926
26013
  const branchConfig = config.gitBranches?.[currentBranch];
25927
26014
  if (!branchConfig?.baseUrl || !branchConfig?.workspaceId) {
25928
26015
  return;
@@ -26014,10 +26101,10 @@ async function resolveWorkspace(opts, branchOverride) {
26014
26101
  const res = await tryResolveWorkspace(opts);
26015
26102
  if (!res.isError) {
26016
26103
  const workspace = res.value;
26017
- if (branchOverride || !branch || !branch.startsWith(WM_FORK_PREFIX)) {
26104
+ if (branchOverride || opts.workspace || !branch || !branch.startsWith(WM_FORK_PREFIX)) {
26018
26105
  return workspace;
26019
26106
  } else {
26020
- info(`Found an active workspace \`${workspace.name}\` but the branch name indicates this is a forked workspace. Ignoring active workspace and trying to resolve the correct workspace from the branch name \`${branch}\``);
26107
+ info(`Found an active workspace \`${workspace.name}\` but the branch name indicates this is a forked workspace. Ignoring active workspace and trying to resolve the correct workspace from the branch name \`${branch}\`. Use --workspace to override.`);
26021
26108
  }
26022
26109
  } else if (opts.workspace) {
26023
26110
  const workspaces = await allWorkspaces(opts.configDir);
@@ -28192,15 +28279,15 @@ var require_constants2 = __commonJS((exports, module) => {
28192
28279
  var require_buffer_util = __commonJS((exports, module) => {
28193
28280
  var { EMPTY_BUFFER } = require_constants2();
28194
28281
  var FastBuffer = Buffer[Symbol.species];
28195
- function concat(list2, totalLength) {
28196
- if (list2.length === 0)
28282
+ function concat(list3, totalLength) {
28283
+ if (list3.length === 0)
28197
28284
  return EMPTY_BUFFER;
28198
- if (list2.length === 1)
28199
- return list2[0];
28285
+ if (list3.length === 1)
28286
+ return list3[0];
28200
28287
  const target = Buffer.allocUnsafe(totalLength);
28201
28288
  let offset = 0;
28202
- for (let i = 0;i < list2.length; i++) {
28203
- const buf = list2[i];
28289
+ for (let i = 0;i < list3.length; i++) {
28290
+ const buf = list3[i];
28204
28291
  target.set(buf, offset);
28205
28292
  offset += buf.length;
28206
28293
  }
@@ -29452,14 +29539,14 @@ var require_sender = __commonJS((exports, module) => {
29452
29539
  this._bufferedBytes += params[3][kByteLength];
29453
29540
  this._queue.push(params);
29454
29541
  }
29455
- sendFrame(list2, cb) {
29456
- if (list2.length === 2) {
29542
+ sendFrame(list3, cb) {
29543
+ if (list3.length === 2) {
29457
29544
  this._socket.cork();
29458
- this._socket.write(list2[0]);
29459
- this._socket.write(list2[1], cb);
29545
+ this._socket.write(list3[0]);
29546
+ this._socket.write(list3[1], cb);
29460
29547
  this._socket.uncork();
29461
29548
  } else {
29462
- this._socket.write(list2[0], cb);
29549
+ this._socket.write(list3[0], cb);
29463
29550
  }
29464
29551
  }
29465
29552
  }
@@ -32790,7 +32877,7 @@ var minimatch = (p, pattern, options = {}) => {
32790
32877
  defaults: (options) => orig.defaults(ext(def, options)),
32791
32878
  makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
32792
32879
  braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
32793
- match: (list2, pattern, options = {}) => orig.match(list2, pattern, ext(def, options)),
32880
+ match: (list3, pattern, options = {}) => orig.match(list3, pattern, ext(def, options)),
32794
32881
  sep: orig.sep,
32795
32882
  GLOBSTAR
32796
32883
  });
@@ -32800,13 +32887,13 @@ var minimatch = (p, pattern, options = {}) => {
32800
32887
  return [pattern];
32801
32888
  }
32802
32889
  return expand(pattern, { max: options.braceExpandMax });
32803
- }, makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe(), match = (list2, pattern, options = {}) => {
32890
+ }, makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe(), match = (list3, pattern, options = {}) => {
32804
32891
  const mm = new Minimatch(pattern, options);
32805
- list2 = list2.filter((f) => mm.match(f));
32806
- if (mm.options.nonull && !list2.length) {
32807
- list2.push(pattern);
32892
+ list3 = list3.filter((f) => mm.match(f));
32893
+ if (mm.options.nonull && !list3.length) {
32894
+ list3.push(pattern);
32808
32895
  }
32809
- return list2;
32896
+ return list3;
32810
32897
  }, globMagic, regExpEscape2 = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
32811
32898
  var init_esm2 = __esm(() => {
32812
32899
  init_esm();
@@ -34653,20 +34740,20 @@ var require__stream_readable = __commonJS((exports, module) => {
34653
34740
  }
34654
34741
  return ret;
34655
34742
  }
34656
- function fromListPartial(n, list2, hasStrings) {
34743
+ function fromListPartial(n, list3, hasStrings) {
34657
34744
  var ret;
34658
- if (n < list2.head.data.length) {
34659
- ret = list2.head.data.slice(0, n);
34660
- list2.head.data = list2.head.data.slice(n);
34661
- } else if (n === list2.head.data.length) {
34662
- ret = list2.shift();
34745
+ if (n < list3.head.data.length) {
34746
+ ret = list3.head.data.slice(0, n);
34747
+ list3.head.data = list3.head.data.slice(n);
34748
+ } else if (n === list3.head.data.length) {
34749
+ ret = list3.shift();
34663
34750
  } else {
34664
- ret = hasStrings ? copyFromBufferString(n, list2) : copyFromBuffer(n, list2);
34751
+ ret = hasStrings ? copyFromBufferString(n, list3) : copyFromBuffer(n, list3);
34665
34752
  }
34666
34753
  return ret;
34667
34754
  }
34668
- function copyFromBufferString(n, list2) {
34669
- var p = list2.head;
34755
+ function copyFromBufferString(n, list3) {
34756
+ var p = list3.head;
34670
34757
  var c = 1;
34671
34758
  var ret = p.data;
34672
34759
  n -= ret.length;
@@ -34682,23 +34769,23 @@ var require__stream_readable = __commonJS((exports, module) => {
34682
34769
  if (nb === str.length) {
34683
34770
  ++c;
34684
34771
  if (p.next)
34685
- list2.head = p.next;
34772
+ list3.head = p.next;
34686
34773
  else
34687
- list2.head = list2.tail = null;
34774
+ list3.head = list3.tail = null;
34688
34775
  } else {
34689
- list2.head = p;
34776
+ list3.head = p;
34690
34777
  p.data = str.slice(nb);
34691
34778
  }
34692
34779
  break;
34693
34780
  }
34694
34781
  ++c;
34695
34782
  }
34696
- list2.length -= c;
34783
+ list3.length -= c;
34697
34784
  return ret;
34698
34785
  }
34699
- function copyFromBuffer(n, list2) {
34786
+ function copyFromBuffer(n, list3) {
34700
34787
  var ret = Buffer4.allocUnsafe(n);
34701
- var p = list2.head;
34788
+ var p = list3.head;
34702
34789
  var c = 1;
34703
34790
  p.data.copy(ret);
34704
34791
  n -= p.data.length;
@@ -34711,18 +34798,18 @@ var require__stream_readable = __commonJS((exports, module) => {
34711
34798
  if (nb === buf.length) {
34712
34799
  ++c;
34713
34800
  if (p.next)
34714
- list2.head = p.next;
34801
+ list3.head = p.next;
34715
34802
  else
34716
- list2.head = list2.tail = null;
34803
+ list3.head = list3.tail = null;
34717
34804
  } else {
34718
- list2.head = p;
34805
+ list3.head = p;
34719
34806
  p.data = buf.slice(nb);
34720
34807
  }
34721
34808
  break;
34722
34809
  }
34723
34810
  ++c;
34724
34811
  }
34725
- list2.length -= c;
34812
+ list3.length -= c;
34726
34813
  return ret;
34727
34814
  }
34728
34815
  function endReadable(stream) {
@@ -59431,7 +59518,9 @@ function removeExtensionToPath(path6) {
59431
59518
  }
59432
59519
  throw new Error("Invalid extension: " + path6);
59433
59520
  }
59434
- async function list2(opts) {
59521
+ async function list3(opts) {
59522
+ if (opts.json)
59523
+ setSilent(true);
59435
59524
  const workspace = await resolveWorkspace(opts);
59436
59525
  await requireLogin(opts);
59437
59526
  let page = 0;
@@ -59479,14 +59568,40 @@ async function resolve6(input) {
59479
59568
  }
59480
59569
  }
59481
59570
  async function run2(opts, path6) {
59571
+ if (opts.silent) {
59572
+ setSilent(true);
59573
+ }
59482
59574
  const workspace = await resolveWorkspace(opts);
59483
59575
  await requireLogin(opts);
59484
59576
  const input = opts.data ? await resolve6(opts.data) : {};
59485
- const id = await runScriptByPath({
59486
- workspace: workspace.workspaceId,
59487
- path: path6,
59488
- requestBody: input
59489
- });
59577
+ let id;
59578
+ try {
59579
+ id = await runScriptByPath({
59580
+ workspace: workspace.workspaceId,
59581
+ path: path6,
59582
+ requestBody: input
59583
+ });
59584
+ } catch (e) {
59585
+ if (e?.status === 404) {
59586
+ try {
59587
+ const script = await getScriptByPath({
59588
+ workspace: workspace.workspaceId,
59589
+ path: path6
59590
+ });
59591
+ if (script.lock_error_logs) {
59592
+ throw new Error(`Script '${path6}' has a deployment error and cannot be run:
59593
+ ${script.lock_error_logs}`);
59594
+ }
59595
+ } catch (lookupErr) {
59596
+ if (lookupErr?.message?.includes("deployment error"))
59597
+ throw lookupErr;
59598
+ if (lookupErr?.status && lookupErr.status !== 404)
59599
+ throw lookupErr;
59600
+ }
59601
+ throw new Error(`Script '${path6}' not found. Run 'wmill script list' to see available scripts.`);
59602
+ }
59603
+ throw e;
59604
+ }
59490
59605
  if (!opts.silent) {
59491
59606
  await track_job(workspace.workspaceId, id);
59492
59607
  }
@@ -59497,7 +59612,7 @@ async function run2(opts, path6) {
59497
59612
  id
59498
59613
  })).result ?? {};
59499
59614
  if (opts.silent) {
59500
- console.log(result);
59615
+ console.log(JSON.stringify(result));
59501
59616
  } else {
59502
59617
  info(JSON.stringify(result, null, 2));
59503
59618
  }
@@ -59615,7 +59730,8 @@ async function bootstrap(opts, scriptPath, language) {
59615
59730
  const resolvedLanguage = languageAliases[language] ?? language;
59616
59731
  const scriptInitialCode = scriptBootstrapCode[resolvedLanguage];
59617
59732
  if (scriptInitialCode === undefined) {
59618
- throw new Error("Language unknown");
59733
+ const validLanguages = Object.keys(scriptBootstrapCode).sort().join(", ");
59734
+ throw new Error(`Unknown language '${language}'. Valid languages: ${validLanguages}`);
59619
59735
  }
59620
59736
  const config = await readConfigFile();
59621
59737
  const extension = filePathExtensionFromContentType(resolvedLanguage, config.defaultTs);
@@ -59705,6 +59821,9 @@ async function generateMetadata(opts, scriptPath) {
59705
59821
  }
59706
59822
  }
59707
59823
  async function preview(opts, filePath) {
59824
+ if (opts.silent) {
59825
+ setSilent(true);
59826
+ }
59708
59827
  opts = await mergeConfigWithConfigFile(opts);
59709
59828
  const workspace = await resolveWorkspace(opts);
59710
59829
  await requireLogin(opts);
@@ -59860,6 +59979,30 @@ async function preview(opts, filePath) {
59860
59979
  }
59861
59980
  }
59862
59981
  }
59982
+ async function history(opts, scriptPath) {
59983
+ if (opts.json)
59984
+ setSilent(true);
59985
+ opts = await mergeConfigWithConfigFile(opts);
59986
+ const workspace = await resolveWorkspace(opts);
59987
+ await requireLogin(opts);
59988
+ const versions = await getScriptHistoryByPath({
59989
+ workspace: workspace.workspaceId,
59990
+ path: scriptPath
59991
+ });
59992
+ if (opts.json) {
59993
+ console.log(JSON.stringify(versions));
59994
+ } else {
59995
+ if (versions.length === 0) {
59996
+ info("No version history found for " + scriptPath);
59997
+ return;
59998
+ }
59999
+ new Table2().header(["#", "Hash", "Deployment Message"]).padding(2).border(true).body(versions.map((v, i) => [
60000
+ String(versions.length - i),
60001
+ v.script_hash,
60002
+ v.deployment_msg ?? "-"
60003
+ ])).render();
60004
+ }
60005
+ }
59863
60006
  var import_yaml5, exts, languageAliases, command3, script_default;
59864
60007
  var init_script = __esm(async () => {
59865
60008
  init_colors2();
@@ -59915,7 +60058,7 @@ var init_script = __esm(async () => {
59915
60058
  languageAliases = {
59916
60059
  python: "python3"
59917
60060
  };
59918
- command3 = new Command().description("script related commands").option("--show-archived", "Enable archived scripts in output").option("--json", "Output as JSON (for piping to jq)").action(list2).command("list", "list all scripts").option("--show-archived", "Enable archived scripts in output").option("--json", "Output as JSON (for piping to jq)").action(list2).command("push", "push a local script spec. This overrides any remote versions. Use the script file (.ts, .js, .py, .sh)").arguments("<path:file>").action(push).command("get", "get a script's details").arguments("<path:file>").option("--json", "Output as JSON (for piping to jq)").action(get).command("show", "show a script's content (alias for get)").arguments("<path:file>").action(show).command("run", "run a script by path").arguments("<path:file>").option("-d --data <data:file>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not output anything other then the final output. Useful for scripting.").action(run2).command("preview", "preview a local script without deploying it. Supports both regular and codebase scripts.").arguments("<path:file>").option("-d --data <data:file>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not output anything other than the final output. Useful for scripting.").action(preview).command("new", "create a new script").arguments("<path:file> <language:string>").option("--summary <summary:string>", "script summary").option("--description <description:string>", "script description").action(bootstrap).command("bootstrap", "create a new script (alias for new)").arguments("<path:file> <language:string>").option("--summary <summary:string>", "script summary").option("--description <description:string>", "script description").action(bootstrap).command("generate-metadata", "re-generate the metadata file updating the lock and the script schema (for flows, use `wmill flow generate-locks`)").arguments("[script:file]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Perform a dry run without making changes").option("--lock-only", "re-generate only the lock").option("--schema-only", "re-generate only script schema").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.").action(generateMetadata);
60061
+ command3 = new Command().description("script related commands").option("--show-archived", "Enable archived scripts in output").option("--json", "Output as JSON (for piping to jq)").action(list3).command("list", "list all scripts").option("--show-archived", "Enable archived scripts in output").option("--json", "Output as JSON (for piping to jq)").action(list3).command("push", "push a local script spec. This overrides any remote versions. Use the script file (.ts, .js, .py, .sh)").arguments("<path:file>").action(push).command("get", "get a script's details").arguments("<path:file>").option("--json", "Output as JSON (for piping to jq)").action(get).command("show", "show a script's content (alias for get)").arguments("<path:file>").action(show).command("run", "run a script by path").arguments("<path:file>").option("-d --data <data:file>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not output anything other then the final output. Useful for scripting.").action(run2).command("preview", "preview a local script without deploying it. Supports both regular and codebase scripts.").arguments("<path:file>").option("-d --data <data:file>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not output anything other than the final output. Useful for scripting.").action(preview).command("new", "create a new script").arguments("<path:file> <language:string>").option("--summary <summary:string>", "script summary").option("--description <description:string>", "script description").action(bootstrap).command("bootstrap", "create a new script (alias for new)").arguments("<path:file> <language:string>").option("--summary <summary:string>", "script summary").option("--description <description:string>", "script description").action(bootstrap).command("generate-metadata", "re-generate the metadata file updating the lock and the script schema (for flows, use `wmill flow generate-locks`)").arguments("[script:file]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Perform a dry run without making changes").option("--lock-only", "re-generate only the lock").option("--schema-only", "re-generate only script schema").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.").action(generateMetadata).command("history", "show version history for a script").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(history);
59919
60062
  script_default = command3;
59920
60063
  });
59921
60064
 
@@ -60531,7 +60674,9 @@ async function push2(opts, filePath, remotePath) {
60531
60674
  await pushResource(workspace.workspaceId, remotePath, undefined, parseFromFile(filePath), filePath);
60532
60675
  info(colors.bold.underline.green(`Resource ${remotePath} pushed`));
60533
60676
  }
60534
- async function list3(opts) {
60677
+ async function list4(opts) {
60678
+ if (opts.json)
60679
+ setSilent(true);
60535
60680
  const workspace = await resolveWorkspace(opts);
60536
60681
  await requireLogin(opts);
60537
60682
  let page = 0;
@@ -60610,7 +60755,7 @@ var init_resource = __esm(async () => {
60610
60755
  init_specific_items()
60611
60756
  ]);
60612
60757
  import_yaml7 = __toESM(require_dist(), 1);
60613
- command5 = new Command().description("resource related commands").option("--json", "Output as JSON (for piping to jq)").action(list3).command("list", "list all resources").option("--json", "Output as JSON (for piping to jq)").action(list3).command("get", "get a resource's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get2).command("new", "create a new resource locally").arguments("<path:string>").action(newResource).command("push", "push a local resource spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").action(push2);
60758
+ command5 = new Command().description("resource related commands").option("--json", "Output as JSON (for piping to jq)").action(list4).command("list", "list all resources").option("--json", "Output as JSON (for piping to jq)").action(list4).command("get", "get a resource's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get2).command("new", "create a new resource locally").arguments("<path:string>").action(newResource).command("push", "push a local resource spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").action(push2);
60614
60759
  resource_default = command5;
60615
60760
  });
60616
60761
 
@@ -62568,8 +62713,13 @@ async function pushParentScriptForModule(modulePath, workspace, alreadySynced, m
62568
62713
  }
62569
62714
  }
62570
62715
  async function pull(opts) {
62716
+ if (opts.jsonOutput)
62717
+ setSilent(true);
62571
62718
  const originalCliOpts = { ...opts };
62572
62719
  opts = await mergeConfigWithConfigFile(opts);
62720
+ if (originalCliOpts.includeSecrets) {
62721
+ opts.skipSecrets = false;
62722
+ }
62573
62723
  try {
62574
62724
  await validateBranchConfiguration(opts, opts.branch);
62575
62725
  } catch (error2) {
@@ -62802,8 +62952,13 @@ function removeSuffix(str, suffix) {
62802
62952
  return str.slice(0, str.length - suffix.length);
62803
62953
  }
62804
62954
  async function push3(opts) {
62955
+ if (opts.jsonOutput)
62956
+ setSilent(true);
62805
62957
  const originalCliOpts = { ...opts };
62806
62958
  opts = await mergeConfigWithConfigFile(opts);
62959
+ if (originalCliOpts.includeSecrets) {
62960
+ opts.skipSecrets = false;
62961
+ }
62807
62962
  try {
62808
62963
  await validateBranchConfiguration(opts, opts.branch);
62809
62964
  } catch (error2) {
@@ -62871,55 +63026,104 @@ Push aborted: ${lockIssues.length} script(s) missing locks.`));
62871
63026
  const changes = await compareDynFSElement(local, remote, await ignoreF(opts), opts.json ?? false, opts, true, codebases, false, specificItems, opts.branch, false);
62872
63027
  const rawWorkspaceDependencies = await getRawWorkspaceDependencies(true);
62873
63028
  const tracker = await buildTracker(changes);
63029
+ const autoRegenerate = !!opts.autoMetadata;
62874
63030
  const staleScripts = [];
62875
63031
  const staleFlows = [];
62876
63032
  const staleApps = [];
62877
63033
  for (const change of tracker.scripts) {
62878
- const stale = await generateScriptMetadataInternal(change, workspace, opts, true, true, rawWorkspaceDependencies, codebases, false);
63034
+ const stale = await generateScriptMetadataInternal(change, workspace, opts, !autoRegenerate, true, rawWorkspaceDependencies, codebases, false);
62879
63035
  if (stale) {
62880
63036
  staleScripts.push(stale);
62881
63037
  }
62882
63038
  }
62883
63039
  if (staleScripts.length > 0) {
62884
63040
  info("");
62885
- warn("Stale scripts metadata found, you may want to update them using 'wmill script generate-metadata' before pushing:");
63041
+ if (autoRegenerate) {
63042
+ info("Auto-regenerated metadata for stale scripts:");
63043
+ } else {
63044
+ warn("Stale scripts metadata found, you may want to update them using 'wmill script generate-metadata' before pushing:");
63045
+ }
62886
63046
  for (const stale of staleScripts) {
62887
- warn(stale);
63047
+ if (autoRegenerate) {
63048
+ info(` ${stale}`);
63049
+ } else {
63050
+ warn(stale);
63051
+ }
62888
63052
  }
62889
63053
  info("");
62890
63054
  }
62891
63055
  for (const change of tracker.flows) {
62892
- const stale = await generateFlowLockInternal(change, true, workspace, opts, false, true);
63056
+ const stale = await generateFlowLockInternal(change, !autoRegenerate, workspace, opts, false, true);
62893
63057
  if (stale) {
62894
63058
  staleFlows.push(stale);
62895
63059
  }
62896
63060
  }
62897
63061
  if (staleFlows.length > 0) {
62898
- warn("Stale flows locks found, you may want to update them using 'wmill flow generate-locks' before pushing:");
63062
+ if (autoRegenerate) {
63063
+ info("Auto-regenerated locks for stale flows:");
63064
+ } else {
63065
+ warn("Stale flows locks found, you may want to update them using 'wmill flow generate-locks' before pushing:");
63066
+ }
62899
63067
  for (const stale of staleFlows) {
62900
- warn(stale);
63068
+ if (autoRegenerate) {
63069
+ info(` ${stale}`);
63070
+ } else {
63071
+ warn(stale);
63072
+ }
62901
63073
  }
62902
63074
  info("");
62903
63075
  }
62904
63076
  for (const change of tracker.apps) {
62905
- const stale = await generateAppLocksInternal(change, false, true, workspace, opts, true, true);
63077
+ const stale = await generateAppLocksInternal(change, false, !autoRegenerate, workspace, opts, true, true);
62906
63078
  if (stale) {
62907
63079
  staleApps.push(stale);
62908
63080
  }
62909
63081
  }
62910
63082
  for (const change of tracker.rawApps) {
62911
- const stale = await generateAppLocksInternal(change, true, true, workspace, opts, true, true);
63083
+ const stale = await generateAppLocksInternal(change, true, !autoRegenerate, workspace, opts, true, true);
62912
63084
  if (stale) {
62913
63085
  staleApps.push(stale);
62914
63086
  }
62915
63087
  }
62916
63088
  if (staleApps.length > 0) {
62917
- warn("Stale apps locks found, you may want to update them using 'wmill app generate-locks' before pushing:");
63089
+ if (autoRegenerate) {
63090
+ info("Auto-regenerated locks for stale apps:");
63091
+ } else {
63092
+ warn("Stale apps locks found, you may want to update them using 'wmill app generate-locks' before pushing:");
63093
+ }
62918
63094
  for (const stale of staleApps) {
62919
- warn(stale);
63095
+ if (autoRegenerate) {
63096
+ info(` ${stale}`);
63097
+ } else {
63098
+ warn(stale);
63099
+ }
62920
63100
  }
62921
63101
  info("");
62922
63102
  }
63103
+ {
63104
+ const skippedWarnings = [];
63105
+ let scheduleCount = 0;
63106
+ let triggerCount = 0;
63107
+ for await (const entry of readDirRecursiveWithIgnore2(() => false, local)) {
63108
+ if (entry.isDirectory)
63109
+ continue;
63110
+ if (!opts.includeSchedules && entry.path.endsWith(".schedule.yaml"))
63111
+ scheduleCount++;
63112
+ if (!opts.includeTriggers && entry.path.endsWith("_trigger.yaml"))
63113
+ triggerCount++;
63114
+ }
63115
+ if (scheduleCount > 0) {
63116
+ skippedWarnings.push(`Skipping ${scheduleCount} schedule file(s). Use --include-schedules or set includeSchedules: true in wmill.yaml`);
63117
+ }
63118
+ if (triggerCount > 0) {
63119
+ skippedWarnings.push(`Skipping ${triggerCount} trigger file(s). Use --include-triggers or set includeTriggers: true in wmill.yaml`);
63120
+ }
63121
+ for (const warning of skippedWarnings) {
63122
+ warn(warning);
63123
+ }
63124
+ if (skippedWarnings.length > 0)
63125
+ info("");
63126
+ }
62923
63127
  await fetchRemoteVersion(workspace);
62924
63128
  info(`remote (${workspace.name}) <- local: ${changes.length} changes to apply`);
62925
63129
  const missingFolders = [];
@@ -63501,7 +63705,7 @@ var init_sync = __esm(async () => {
63501
63705
  aliasDuplicateObjects: false,
63502
63706
  singleQuote: true
63503
63707
  };
63504
- 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);
63708
+ 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("--include-secrets", "Include secrets in sync (overrides skipSecrets in wmill.yaml)").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("--include-secrets", "Include secrets in sync (overrides skipSecrets in wmill.yaml)").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").option("--auto-metadata", "Automatically regenerate stale metadata (locks and schemas) before pushing").action(push3);
63505
63709
  sync_default = command6;
63506
63710
  });
63507
63711
 
@@ -64528,6 +64732,13 @@ var init_metadata = __esm(async () => {
64528
64732
  });
64529
64733
 
64530
64734
  // src/commands/app/raw_apps.ts
64735
+ var exports_raw_apps = {};
64736
+ __export(exports_raw_apps, {
64737
+ writeRunnableToBackend: () => writeRunnableToBackend,
64738
+ pushRawApp: () => pushRawApp,
64739
+ loadRunnablesFromBackend: () => loadRunnablesFromBackend,
64740
+ generatingPolicy: () => generatingPolicy
64741
+ });
64531
64742
  import { sep as SEP10 } from "node:path";
64532
64743
  import path10 from "node:path";
64533
64744
  import { readFile as readFile10, readdir as readdir6 } from "node:fs/promises";
@@ -67230,6 +67441,7 @@ var init_new = __esm(async () => {
67230
67441
 
67231
67442
  // src/commands/app/app.ts
67232
67443
  import { sep as SEP13 } from "node:path";
67444
+ import { stat as stat9 } from "node:fs/promises";
67233
67445
  function respecializeFields(fields) {
67234
67446
  Object.entries(fields).forEach(([k, v]) => {
67235
67447
  if (typeof v == "object") {
@@ -67359,7 +67571,7 @@ async function generatingPolicy2(app, path16, publicApp) {
67359
67571
  throw e;
67360
67572
  }
67361
67573
  }
67362
- async function list4(opts) {
67574
+ async function list5(opts) {
67363
67575
  const workspace = await resolveWorkspace(opts);
67364
67576
  await requireLogin(opts);
67365
67577
  let page = 0;
@@ -67405,8 +67617,24 @@ async function push4(opts, filePath, remotePath) {
67405
67617
  }
67406
67618
  const workspace = await resolveWorkspace(opts);
67407
67619
  await requireLogin(opts);
67408
- await pushApp(workspace.workspaceId, remotePath, filePath);
67409
- info(colors.bold.underline.green("App pushed"));
67620
+ const normalizedPath = filePath.endsWith(SEP13) ? filePath.slice(0, -1) : filePath;
67621
+ const isRawApp = normalizedPath.endsWith("__raw_app") || normalizedPath.endsWith(".raw_app");
67622
+ let hasRawAppYaml = false;
67623
+ if (!isRawApp) {
67624
+ try {
67625
+ const rawAppPath = (filePath.endsWith(SEP13) ? filePath : filePath + SEP13) + "raw_app.yaml";
67626
+ await stat9(rawAppPath);
67627
+ hasRawAppYaml = true;
67628
+ } catch {}
67629
+ }
67630
+ if (isRawApp || hasRawAppYaml) {
67631
+ const { pushRawApp: pushRawApp2 } = await init_raw_apps().then(() => exports_raw_apps);
67632
+ await pushRawApp2(workspace.workspaceId, remotePath, filePath);
67633
+ info(colors.bold.underline.green("Raw app pushed"));
67634
+ } else {
67635
+ await pushApp(workspace.workspaceId, remotePath, filePath);
67636
+ info(colors.bold.underline.green("App pushed"));
67637
+ }
67410
67638
  }
67411
67639
  var alreadySynced2, command11, app_default;
67412
67640
  var init_app = __esm(async () => {
@@ -67429,7 +67657,7 @@ var init_app = __esm(async () => {
67429
67657
  init_generate_agents()
67430
67658
  ]);
67431
67659
  alreadySynced2 = [];
67432
- command11 = new Command().description("app related commands").option("--json", "Output as JSON (for piping to jq)").action(list4).command("list", "list all apps").option("--json", "Output as JSON (for piping to jq)").action(list4).command("get", "get an app's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get3).command("push", "push a local app ").arguments("<file_path:string> <remote_path:string>").action(push4).command("dev", dev_default).command("lint", lint_default2).command("new", new_default).command("generate-agents", generate_agents_default).command("generate-locks", "re-generate the lockfiles for app runnables inline scripts that have changed").arguments("[app_folder:string]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Perform a dry run without making changes").option("--default-ts <runtime:string>", "Default TypeScript runtime (bun or deno)").action(async (opts, appFolder) => {
67660
+ command11 = new Command().description("app related commands").option("--json", "Output as JSON (for piping to jq)").action(list5).command("list", "list all apps").option("--json", "Output as JSON (for piping to jq)").action(list5).command("get", "get an app's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get3).command("push", "push a local app ").arguments("<file_path:string> <remote_path:string>").action(push4).command("dev", dev_default).command("lint", lint_default2).command("new", new_default).command("generate-agents", generate_agents_default).command("generate-locks", "re-generate the lockfiles for app runnables inline scripts that have changed").arguments("[app_folder:string]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Perform a dry run without making changes").option("--default-ts <runtime:string>", "Default TypeScript runtime (bun or deno)").action(async (opts, appFolder) => {
67433
67661
  warn(colors.yellow('This command is deprecated. Use "wmill generate-metadata" instead.'));
67434
67662
  const { generateLocksCommand: generateLocksCommand2 } = await init_app_metadata().then(() => exports_app_metadata);
67435
67663
  await generateLocksCommand2(opts, appFolder);
@@ -67438,9 +67666,11 @@ var init_app = __esm(async () => {
67438
67666
  });
67439
67667
 
67440
67668
  // src/commands/folder/folder.ts
67441
- import { stat as stat9, readdir as readdir7, writeFile as writeFile10, mkdir as mkdir7 } from "node:fs/promises";
67669
+ import { stat as stat10, readdir as readdir7, writeFile as writeFile10, mkdir as mkdir7 } from "node:fs/promises";
67442
67670
  import { sep as SEP14 } from "node:path";
67443
- async function list5(opts) {
67671
+ async function list6(opts) {
67672
+ if (opts.json)
67673
+ setSilent(true);
67444
67674
  const workspace = await resolveWorkspace(opts);
67445
67675
  await requireLogin(opts);
67446
67676
  const folders = await listFolders({
@@ -67460,7 +67690,7 @@ async function newFolder(opts, name) {
67460
67690
  const dirPath = `f${SEP14}${name}`;
67461
67691
  const filePath = `${dirPath}${SEP14}folder.meta.yaml`;
67462
67692
  try {
67463
- await stat9(filePath);
67693
+ await stat10(filePath);
67464
67694
  throw new Error("File already exists: " + filePath);
67465
67695
  } catch (e) {
67466
67696
  if (e.message?.startsWith("File already exists"))
@@ -67548,7 +67778,7 @@ async function push5(opts, name) {
67548
67778
  await requireLogin(opts);
67549
67779
  const metaPath = `f${SEP14}${name}${SEP14}folder.meta.yaml`;
67550
67780
  try {
67551
- await stat9(metaPath);
67781
+ await stat10(metaPath);
67552
67782
  } catch {
67553
67783
  throw new Error(`Could not find ${metaPath}. Does the folder exist locally?`);
67554
67784
  }
@@ -67559,7 +67789,7 @@ async function push5(opts, name) {
67559
67789
  async function addMissing(opts) {
67560
67790
  const fDir = `f`;
67561
67791
  try {
67562
- await stat9(fDir);
67792
+ await stat10(fDir);
67563
67793
  } catch {
67564
67794
  info("No 'f/' directory found. Nothing to do.");
67565
67795
  return;
@@ -67571,7 +67801,7 @@ async function addMissing(opts) {
67571
67801
  continue;
67572
67802
  const metaPath = `${fDir}${SEP14}${entry.name}${SEP14}folder.meta.yaml`;
67573
67803
  try {
67574
- await stat9(metaPath);
67804
+ await stat10(metaPath);
67575
67805
  } catch {
67576
67806
  missing.push(entry.name);
67577
67807
  }
@@ -67610,7 +67840,7 @@ var init_folder = __esm(async () => {
67610
67840
  init_types()
67611
67841
  ]);
67612
67842
  import_yaml23 = __toESM(require_dist(), 1);
67613
- command12 = new Command().description("folder related commands").option("--json", "Output as JSON (for piping to jq)").action(list5).command("list", "list all folders").option("--json", "Output as JSON (for piping to jq)").action(list5).command("get", "get a folder's details").arguments("<name:string>").option("--json", "Output as JSON (for piping to jq)").action(get4).command("new", "create a new folder locally").arguments("<name:string>").option("--summary <summary:string>", "folder summary").action(newFolder).command("push", "push a local folder to the remote by name. This overrides any remote versions.").arguments("<name:string>").action(push5).command("add-missing", "create default folder.meta.yaml for all subdirectories of f/ that are missing one").option("-y, --yes", "skip confirmation prompt").action(addMissing);
67843
+ command12 = new Command().description("folder related commands").option("--json", "Output as JSON (for piping to jq)").action(list6).command("list", "list all folders").option("--json", "Output as JSON (for piping to jq)").action(list6).command("get", "get a folder's details").arguments("<name:string>").option("--json", "Output as JSON (for piping to jq)").action(get4).command("new", "create a new folder locally").arguments("<name:string>").option("--summary <summary:string>", "folder summary").action(newFolder).command("push", "push a local folder to the remote by name. This overrides any remote versions.").arguments("<name:string>").action(push5).command("add-missing", "create default folder.meta.yaml for all subdirectories of f/ that are missing one").option("-y, --yes", "skip confirmation prompt").action(addMissing);
67614
67844
  folder_default = command12;
67615
67845
  });
67616
67846
 
@@ -67651,7 +67881,7 @@ function compileResourceTypeToTsType(schema) {
67651
67881
 
67652
67882
  // src/commands/resource-type/resource-type.ts
67653
67883
  import { writeFileSync as writeFileSync4 } from "node:fs";
67654
- import { stat as stat10, writeFile as writeFile11 } from "node:fs/promises";
67884
+ import { stat as stat11, writeFile as writeFile11 } from "node:fs/promises";
67655
67885
  import path16 from "node:path";
67656
67886
  import process16 from "node:process";
67657
67887
  async function pushResourceType(workspace, remotePath, resource, localResource) {
@@ -67685,7 +67915,7 @@ async function pushResourceType(workspace, remotePath, resource, localResource)
67685
67915
  }
67686
67916
  }
67687
67917
  async function push6(opts, filePath, name) {
67688
- const fstat = await stat10(filePath);
67918
+ const fstat = await stat11(filePath);
67689
67919
  if (!fstat.isFile()) {
67690
67920
  throw new Error("file path must refer to a file.");
67691
67921
  }
@@ -67695,7 +67925,9 @@ async function push6(opts, filePath, name) {
67695
67925
  await pushResourceType(workspace.workspaceId, name, undefined, parseFromFile(filePath));
67696
67926
  info(colors.bold.underline.green("Resource pushed"));
67697
67927
  }
67698
- async function list6(opts) {
67928
+ async function list7(opts) {
67929
+ if (opts.json)
67930
+ setSilent(true);
67699
67931
  const workspace = await resolveWorkspace(opts);
67700
67932
  await requireLogin(opts);
67701
67933
  const res = await listResourceType({
@@ -67716,7 +67948,7 @@ async function list6(opts) {
67716
67948
  async function newResourceType(opts, name) {
67717
67949
  const filePath = name + ".resource-type.yaml";
67718
67950
  try {
67719
- await stat10(filePath);
67951
+ await stat11(filePath);
67720
67952
  throw new Error("File already exists: " + filePath);
67721
67953
  } catch (e) {
67722
67954
  if (e.message?.startsWith("File already exists"))
@@ -67784,14 +68016,16 @@ var init_resource_type = __esm(async () => {
67784
68016
  init_utils()
67785
68017
  ]);
67786
68018
  import_yaml24 = __toESM(require_dist(), 1);
67787
- command13 = new Command().description("resource type related commands").option("--json", "Output as JSON (for piping to jq)").action(list6).command("list", "list all resource types").option("--schema", "Show schema in the output").option("--json", "Output as JSON (for piping to jq)").action(list6).command("get", "get a resource type's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get5).command("new", "create a new resource type locally").arguments("<name:string>").action(newResourceType).command("push", "push a local resource spec. This overrides any remote versions.").arguments("<file_path:string> <name:string>").action(push6).command("generate-namespace", "Create a TypeScript definition file with the RT namespace generated from the resource types").action(generateRTNamespace);
68019
+ command13 = new Command().description("resource type related commands").option("--json", "Output as JSON (for piping to jq)").action(list7).command("list", "list all resource types").option("--schema", "Show schema in the output").option("--json", "Output as JSON (for piping to jq)").action(list7).command("get", "get a resource type's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get5).command("new", "create a new resource type locally").arguments("<name:string>").action(newResourceType).command("push", "push a local resource spec. This overrides any remote versions.").arguments("<file_path:string> <name:string>").action(push6).command("generate-namespace", "Create a TypeScript definition file with the RT namespace generated from the resource types").action(generateRTNamespace);
67788
68020
  resource_type_default = command13;
67789
68021
  });
67790
68022
 
67791
68023
  // src/commands/variable/variable.ts
67792
- import { stat as stat11, writeFile as writeFile12 } from "node:fs/promises";
68024
+ import { stat as stat12, writeFile as writeFile12 } from "node:fs/promises";
67793
68025
  import { sep as SEP15 } from "node:path";
67794
- async function list7(opts) {
68026
+ async function list8(opts) {
68027
+ if (opts.json)
68028
+ setSilent(true);
67795
68029
  const workspace = await resolveWorkspace(opts);
67796
68030
  await requireLogin(opts);
67797
68031
  const variables = await listVariable({
@@ -67814,7 +68048,7 @@ async function newVariable(opts, path17) {
67814
68048
  }
67815
68049
  const filePath = path17 + ".variable.yaml";
67816
68050
  try {
67817
- await stat11(filePath);
68051
+ await stat12(filePath);
67818
68052
  throw new Error("File already exists: " + filePath);
67819
68053
  } catch (e) {
67820
68054
  if (e.message?.startsWith("File already exists"))
@@ -67895,7 +68129,7 @@ async function push7(opts, filePath, remotePath) {
67895
68129
  if (!validatePath(remotePath)) {
67896
68130
  return;
67897
68131
  }
67898
- const fstat = await stat11(filePath);
68132
+ const fstat = await stat12(filePath);
67899
68133
  if (!fstat.isFile()) {
67900
68134
  throw new Error("file path must refer to a file.");
67901
68135
  }
@@ -67943,14 +68177,16 @@ var init_variable = __esm(async () => {
67943
68177
  init_confirm()
67944
68178
  ]);
67945
68179
  import_yaml25 = __toESM(require_dist(), 1);
67946
- command14 = new Command().description("variable related commands").option("--json", "Output as JSON (for piping to jq)").action(list7).command("list", "list all variables").option("--json", "Output as JSON (for piping to jq)").action(list7).command("get", "get a variable's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get6).command("new", "create a new variable locally").arguments("<path:string>").action(newVariable).command("push", "Push a local variable spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").option("--plain-secrets", "Push secrets as plain text").action(push7).command("add", "Create a new variable on the remote. This will update the variable if it already exists.").arguments("<value:string> <remote_path:string>").option("--plain-secrets", "Push secrets as plain text").option("--public", "Legacy option, use --plain-secrets instead").action(add2);
68180
+ command14 = new Command().description("variable related commands").option("--json", "Output as JSON (for piping to jq)").action(list8).command("list", "list all variables").option("--json", "Output as JSON (for piping to jq)").action(list8).command("get", "get a variable's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get6).command("new", "create a new variable locally").arguments("<path:string>").action(newVariable).command("push", "Push a local variable spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").option("--plain-secrets", "Push secrets as plain text").action(push7).command("add", "Create a new variable on the remote. This will update the variable if it already exists.").arguments("<value:string> <remote_path:string>").option("--plain-secrets", "Push secrets as plain text").option("--public", "Legacy option, use --plain-secrets instead").action(add2);
67947
68181
  variable_default = command14;
67948
68182
  });
67949
68183
 
67950
68184
  // src/commands/schedule/schedule.ts
67951
- import { stat as stat12, writeFile as writeFile13 } from "node:fs/promises";
68185
+ import { stat as stat13, writeFile as writeFile13 } from "node:fs/promises";
67952
68186
  import { sep as SEP16 } from "node:path";
67953
- async function list8(opts) {
68187
+ async function list9(opts) {
68188
+ if (opts.json)
68189
+ setSilent(true);
67954
68190
  const workspace = await resolveWorkspace(opts);
67955
68191
  await requireLogin(opts);
67956
68192
  const schedules = await listSchedules({
@@ -67968,14 +68204,14 @@ async function newSchedule(opts, path17) {
67968
68204
  }
67969
68205
  const filePath = path17 + ".schedule.yaml";
67970
68206
  try {
67971
- await stat12(filePath);
68207
+ await stat13(filePath);
67972
68208
  throw new Error("File already exists: " + filePath);
67973
68209
  } catch (e) {
67974
68210
  if (e.message?.startsWith("File already exists"))
67975
68211
  throw e;
67976
68212
  }
67977
68213
  const template = {
67978
- schedule: "0 */6 * * *",
68214
+ schedule: "0 0 */6 * * *",
67979
68215
  on_failure: "",
67980
68216
  script_path: "",
67981
68217
  args: {},
@@ -68061,13 +68297,35 @@ async function pushSchedule(workspace, path17, schedule, localSchedule) {
68061
68297
  }
68062
68298
  }
68063
68299
  }
68300
+ async function enable(opts, path17) {
68301
+ opts = await mergeConfigWithConfigFile(opts);
68302
+ const workspace = await resolveWorkspace(opts);
68303
+ await requireLogin(opts);
68304
+ await setScheduleEnabled({
68305
+ workspace: workspace.workspaceId,
68306
+ path: path17,
68307
+ requestBody: { enabled: true }
68308
+ });
68309
+ info(colors.green(`Schedule ${path17} enabled.`));
68310
+ }
68311
+ async function disable(opts, path17) {
68312
+ opts = await mergeConfigWithConfigFile(opts);
68313
+ const workspace = await resolveWorkspace(opts);
68314
+ await requireLogin(opts);
68315
+ await setScheduleEnabled({
68316
+ workspace: workspace.workspaceId,
68317
+ path: path17,
68318
+ requestBody: { enabled: false }
68319
+ });
68320
+ info(colors.yellow(`Schedule ${path17} disabled.`));
68321
+ }
68064
68322
  async function push8(opts, filePath, remotePath) {
68065
68323
  const workspace = await resolveWorkspace(opts);
68066
68324
  await requireLogin(opts);
68067
68325
  if (!validatePath(remotePath)) {
68068
68326
  return;
68069
68327
  }
68070
- const fstat = await stat12(filePath);
68328
+ const fstat = await stat13(filePath);
68071
68329
  if (!fstat.isFile()) {
68072
68330
  throw new Error("file path must refer to a file.");
68073
68331
  }
@@ -68085,10 +68343,11 @@ var init_schedule = __esm(async () => {
68085
68343
  await __promiseAll([
68086
68344
  init_auth(),
68087
68345
  init_context(),
68346
+ init_conf(),
68088
68347
  init_types()
68089
68348
  ]);
68090
68349
  import_yaml26 = __toESM(require_dist(), 1);
68091
- command15 = new Command().description("schedule related commands").option("--json", "Output as JSON (for piping to jq)").action(list8).command("list", "list all schedules").option("--json", "Output as JSON (for piping to jq)").action(list8).command("get", "get a schedule's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get7).command("new", "create a new schedule locally").arguments("<path:string>").action(newSchedule).command("push", "push a local schedule spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").action(push8);
68350
+ command15 = new Command().description("schedule related commands").option("--json", "Output as JSON (for piping to jq)").action(list9).command("list", "list all schedules").option("--json", "Output as JSON (for piping to jq)").action(list9).command("get", "get a schedule's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get7).command("new", "create a new schedule locally").arguments("<path:string>").action(newSchedule).command("push", "push a local schedule spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").action(push8).command("enable", "Enable a schedule").arguments("<path:string>").action(enable).command("disable", "Disable a schedule").arguments("<path:string>").action(disable);
68092
68351
  schedule_default = command15;
68093
68352
  });
68094
68353
 
@@ -68717,7 +68976,7 @@ var init_settings = __esm(async () => {
68717
68976
  });
68718
68977
 
68719
68978
  // src/commands/instance/instance.ts
68720
- import { readFile as readFile13, writeFile as writeFile15, readdir as readdir8, mkdir as mkdir8, rm as rm3, stat as stat13 } from "node:fs/promises";
68979
+ import { readFile as readFile13, writeFile as writeFile15, readdir as readdir8, mkdir as mkdir8, rm as rm3, stat as stat14 } from "node:fs/promises";
68721
68980
  import { appendFile } from "node:fs/promises";
68722
68981
  import * as path17 from "node:path";
68723
68982
  async function allInstances() {
@@ -68827,6 +69086,21 @@ async function pickInstance(opts, allowNew) {
68827
69086
  prefix: opts.prefix ?? "custom"
68828
69087
  };
68829
69088
  }
69089
+ if (instances.length < 1) {
69090
+ try {
69091
+ const ws = await getActiveWorkspace({});
69092
+ if (ws?.remote && ws?.token) {
69093
+ const remote = ws.remote.endsWith("/") ? ws.remote.slice(0, -1) : ws.remote;
69094
+ setClient(ws.token, remote);
69095
+ return {
69096
+ name: ws.name,
69097
+ remote: ws.remote,
69098
+ token: ws.token,
69099
+ prefix: ws.name
69100
+ };
69101
+ }
69102
+ } catch {}
69103
+ }
68830
69104
  if (!allowNew && instances.length < 1) {
68831
69105
  throw new Error("No instance found, please add one first");
68832
69106
  }
@@ -69113,7 +69387,7 @@ Pushing workspace ` + localWorkspace.id);
69113
69387
  }
69114
69388
  async function getLocalWorkspaces(rootDir, localPrefix, folderPerInstance) {
69115
69389
  const localWorkspaces = [];
69116
- if (!await stat13(localPrefix).catch(() => null)) {
69390
+ if (!await stat14(localPrefix).catch(() => null)) {
69117
69391
  await mkdir8(localPrefix);
69118
69392
  }
69119
69393
  if (folderPerInstance) {
@@ -69168,6 +69442,21 @@ async function getActiveInstance(opts) {
69168
69442
  async function getConfig2(opts) {
69169
69443
  await pickInstance(opts, false);
69170
69444
  const config = await getInstanceConfig();
69445
+ const hasSecrets = config?.global_settings?.license_key || config?.global_settings?.jwt_secret;
69446
+ let showSecrets = opts.showSecrets ?? false;
69447
+ if (!showSecrets && hasSecrets && process.stdout.isTTY && !opts.outputFile) {
69448
+ warn("Config contains sensitive fields (license_key, jwt_secret). They are masked by default.");
69449
+ warn("Use --show-secrets to include them, or press Y to show them now.");
69450
+ showSecrets = await Confirm.prompt({ message: "Show secrets?", default: false });
69451
+ } else if (!process.stdout.isTTY || opts.outputFile) {
69452
+ showSecrets = true;
69453
+ }
69454
+ if (!showSecrets && config?.global_settings) {
69455
+ if (config.global_settings.license_key)
69456
+ config.global_settings.license_key = "***";
69457
+ if (config.global_settings.jwt_secret)
69458
+ config.global_settings.jwt_secret = "***";
69459
+ }
69171
69460
  const yaml = import_yaml29.stringify(config);
69172
69461
  if (opts.outputFile) {
69173
69462
  await writeFile15(opts.outputFile, yaml, "utf-8");
@@ -69235,7 +69524,7 @@ var init_instance = __esm(async () => {
69235
69524
  });
69236
69525
  await removeInstance(choice);
69237
69526
  info(colors.green.underline(`Removed instance ${choice}`));
69238
- }).command("switch").complete("instance", async () => (await allInstances()).map((x) => x.name)).arguments("<instance:string:instance>").description("Switch the current instance").action(switchI).command("pull").description("Pull instance settings, users, configs, instance groups and overwrite local").option("--yes", "Pull without needing confirmation").option("--dry-run", "Perform a dry run without making changes").option("--skip-users", "Skip pulling users").option("--skip-settings", "Skip pulling settings").option("--skip-configs", "Skip pulling configs (worker groups and SMTP)").option("--skip-groups", "Skip pulling instance groups").option("--include-workspaces", "Also pull workspaces").option("--folder-per-instance", "Create a folder per instance").option("--instance <instance:string>", "Name of the instance to pull from, override the active instance").option("--prefix <prefix:string>", "Prefix of the local workspaces to pull, used to create the folders when using --include-workspaces").option("--prefix-settings", "Store instance yamls inside prefixed folders when using --prefix and --folder-per-instance").action(instancePull).command("push").description("Push instance settings, users, configs, group and overwrite remote").option("--yes", "Push without needing confirmation").option("--dry-run", "Perform a dry run without making changes").option("--skip-users", "Skip pushing users").option("--skip-settings", "Skip pushing settings").option("--skip-configs", "Skip pushing configs (worker groups and SMTP)").option("--skip-groups", "Skip pushing instance groups").option("--include-workspaces", "Also push workspaces").option("--folder-per-instance", "Create a folder per instance").option("--instance <instance:string>", "Name of the instance to push to, override the active instance").option("--prefix <prefix:string>", "Prefix of the local workspaces folders to push").option("--prefix-settings", "Store instance yamls inside prefixed folders when using --prefix and --folder-per-instance").action(instancePush).command("whoami").description("Display information about the currently logged-in user").action(whoami3).command("get-config").description("Dump the current instance config (global settings + worker configs) as YAML").option("-o, --output-file <file:string>", "Write YAML to a file instead of stdout").option("--instance <instance:string>", "Name of the instance, override the active instance").action(getConfig2);
69527
+ }).command("switch").complete("instance", async () => (await allInstances()).map((x) => x.name)).arguments("<instance:string:instance>").description("Switch the current instance").action(switchI).command("pull").description("Pull instance settings, users, configs, instance groups and overwrite local").option("--yes", "Pull without needing confirmation").option("--dry-run", "Perform a dry run without making changes").option("--skip-users", "Skip pulling users").option("--skip-settings", "Skip pulling settings").option("--skip-configs", "Skip pulling configs (worker groups and SMTP)").option("--skip-groups", "Skip pulling instance groups").option("--include-workspaces", "Also pull workspaces").option("--folder-per-instance", "Create a folder per instance").option("--instance <instance:string>", "Name of the instance to pull from, override the active instance").option("--prefix <prefix:string>", "Prefix of the local workspaces to pull, used to create the folders when using --include-workspaces").option("--prefix-settings", "Store instance yamls inside prefixed folders when using --prefix and --folder-per-instance").action(instancePull).command("push").description("Push instance settings, users, configs, group and overwrite remote").option("--yes", "Push without needing confirmation").option("--dry-run", "Perform a dry run without making changes").option("--skip-users", "Skip pushing users").option("--skip-settings", "Skip pushing settings").option("--skip-configs", "Skip pushing configs (worker groups and SMTP)").option("--skip-groups", "Skip pushing instance groups").option("--include-workspaces", "Also push workspaces").option("--folder-per-instance", "Create a folder per instance").option("--instance <instance:string>", "Name of the instance to push to, override the active instance").option("--prefix <prefix:string>", "Prefix of the local workspaces folders to push").option("--prefix-settings", "Store instance yamls inside prefixed folders when using --prefix and --folder-per-instance").action(instancePush).command("whoami").description("Display information about the currently logged-in user").action(whoami3).command("get-config").description("Dump the current instance config (global settings + worker configs) as YAML").option("-o, --output-file <file:string>", "Write YAML to a file instead of stdout").option("--show-secrets", "Include sensitive fields (license key, JWT secret) without prompting").option("--instance <instance:string>", "Name of the instance, override the active instance").action(getConfig2);
69239
69528
  instance_default = command17;
69240
69529
  });
69241
69530
 
@@ -69251,7 +69540,7 @@ function checkInstanceGroupsPath(opts) {
69251
69540
  instanceGroupsPath = `${opts.prefix}/${INSTANCE_GROUPS_PATH}`;
69252
69541
  }
69253
69542
  }
69254
- async function list9(opts) {
69543
+ async function list10(opts) {
69255
69544
  await requireLogin(opts);
69256
69545
  const perPage = 10;
69257
69546
  let page = 0;
@@ -69607,7 +69896,7 @@ var init_user = __esm(async () => {
69607
69896
  import_yaml31 = __toESM(require_dist(), 1);
69608
69897
  instanceUsersPath = INSTANCE_USERS_PATH;
69609
69898
  instanceGroupsPath = INSTANCE_GROUPS_PATH;
69610
- command18 = new Command().description("user related commands").action(list9).command("add", "Create a user").arguments("<email:string> [password:string]").option("--superadmin", "Specify to make the new user superadmin.").option("--company <company:string>", "Specify to set the company of the new user.").option("--name <name:string>", "Specify to set the name of the new user.").action(add3).command("remove", "Delete a user").arguments("<email:string>").action(remove2).command("create-token").option("--email <email:string>", "Specify credentials to use for authentication. This will not be stored. It will only be used to exchange for a token with the API server, which will not be stored either.", {
69899
+ command18 = new Command().description("user related commands").action(list10).command("add", "Create a user").arguments("<email:string> [password:string]").option("--superadmin", "Specify to make the new user superadmin.").option("--company <company:string>", "Specify to set the company of the new user.").option("--name <name:string>", "Specify to set the name of the new user.").action(add3).command("remove", "Delete a user").arguments("<email:string>").action(remove2).command("create-token", "Create a new API token for the authenticated user").option("--email <email:string>", "Specify credentials to use for authentication. This will not be stored. It will only be used to exchange for a token with the API server, which will not be stored either.", {
69611
69900
  depends: ["password"]
69612
69901
  }).option("--password <password:string>", "Specify credentials to use for authentication. This will not be stored. It will only be used to exchange for a token with the API server, which will not be stored either.", {
69613
69902
  depends: ["email"]
@@ -69682,7 +69971,7 @@ var init_dependencies = __esm(async () => {
69682
69971
  });
69683
69972
 
69684
69973
  // src/commands/trigger/trigger.ts
69685
- import { stat as stat14, writeFile as writeFile17 } from "node:fs/promises";
69974
+ import { stat as stat15, writeFile as writeFile17 } from "node:fs/promises";
69686
69975
  import { sep as SEP17 } from "node:path";
69687
69976
  async function getTrigger(triggerType, workspace, path18) {
69688
69977
  const triggerFunctions = {
@@ -69857,7 +70146,7 @@ async function newTrigger(opts, path18) {
69857
70146
  const kind = opts.kind;
69858
70147
  const filePath = `${path18}.${kind}_trigger.yaml`;
69859
70148
  try {
69860
- await stat14(filePath);
70149
+ await stat15(filePath);
69861
70150
  throw new Error("File already exists: " + filePath);
69862
70151
  } catch (e) {
69863
70152
  if (e.message?.startsWith("File already exists"))
@@ -69906,7 +70195,7 @@ async function get8(opts, path18) {
69906
70195
  } else {
69907
70196
  console.log(colors.bold("Path:") + " " + trigger.path);
69908
70197
  console.log(colors.bold("Kind:") + " " + kind);
69909
- console.log(colors.bold("Enabled:") + " " + (trigger.enabled ?? "-"));
70198
+ console.log(colors.bold("Enabled:") + " " + (trigger.enabled ?? trigger.mode ?? "-"));
69910
70199
  console.log(colors.bold("Script Path:") + " " + (trigger.script_path ?? ""));
69911
70200
  console.log(colors.bold("Is Flow:") + " " + (trigger.is_flow ? "true" : "false"));
69912
70201
  }
@@ -69925,7 +70214,9 @@ async function listOrEmpty(fn) {
69925
70214
  return [];
69926
70215
  }
69927
70216
  }
69928
- async function list10(opts) {
70217
+ async function list11(opts) {
70218
+ if (opts.json)
70219
+ setSilent(true);
69929
70220
  const workspace = await resolveWorkspace(opts);
69930
70221
  await requireLogin(opts);
69931
70222
  const ws = workspace.workspaceId;
@@ -69991,7 +70282,7 @@ async function push10(opts, filePath, remotePath) {
69991
70282
  if (!validatePath(remotePath)) {
69992
70283
  return;
69993
70284
  }
69994
- const fstat = await stat14(filePath);
70285
+ const fstat = await stat15(filePath);
69995
70286
  if (!fstat.isFile()) {
69996
70287
  throw new Error("file path must refer to a file.");
69997
70288
  }
@@ -70025,12 +70316,21 @@ var init_trigger = __esm(async () => {
70025
70316
  route_path: "",
70026
70317
  http_method: "get",
70027
70318
  is_async: false,
70028
- requires_auth: true
70319
+ requires_auth: true,
70320
+ request_type: "sync",
70321
+ authentication_method: "none",
70322
+ is_static_website: false,
70323
+ workspaced_route: false,
70324
+ wrap_body: false,
70325
+ raw_string: false
70029
70326
  },
70030
70327
  websocket: {
70031
70328
  script_path: "",
70032
70329
  is_flow: false,
70033
70330
  url: "",
70331
+ filters: [],
70332
+ can_return_message: false,
70333
+ can_return_error_result: false,
70034
70334
  enabled: false
70035
70335
  },
70036
70336
  kafka: {
@@ -70039,6 +70339,7 @@ var init_trigger = __esm(async () => {
70039
70339
  kafka_resource_path: "",
70040
70340
  group_id: "",
70041
70341
  topics: [],
70342
+ filters: [],
70042
70343
  enabled: false
70043
70344
  },
70044
70345
  nats: {
@@ -70046,6 +70347,7 @@ var init_trigger = __esm(async () => {
70046
70347
  is_flow: false,
70047
70348
  nats_resource_path: "",
70048
70349
  subjects: [],
70350
+ use_jetstream: false,
70049
70351
  enabled: false
70050
70352
  },
70051
70353
  postgres: {
@@ -70060,23 +70362,25 @@ var init_trigger = __esm(async () => {
70060
70362
  script_path: "",
70061
70363
  is_flow: false,
70062
70364
  mqtt_resource_path: "",
70063
- topics: [],
70064
- subscribe_qos: 0,
70365
+ subscribe_topics: [],
70065
70366
  enabled: false
70066
70367
  },
70067
70368
  sqs: {
70068
70369
  script_path: "",
70069
70370
  is_flow: false,
70070
- sqs_resource_path: "",
70071
70371
  queue_url: "",
70372
+ aws_resource_path: "",
70373
+ aws_auth_resource_type: "credentials",
70072
70374
  enabled: false
70073
70375
  },
70074
70376
  gcp: {
70075
70377
  script_path: "",
70076
70378
  is_flow: false,
70077
70379
  gcp_resource_path: "",
70078
- subscription_id: "",
70079
70380
  topic_id: "",
70381
+ subscription_id: "",
70382
+ delivery_type: "pull",
70383
+ subscription_mode: "create_update",
70080
70384
  enabled: false
70081
70385
  },
70082
70386
  email: {
@@ -70085,7 +70389,7 @@ var init_trigger = __esm(async () => {
70085
70389
  enabled: false
70086
70390
  }
70087
70391
  };
70088
- command20 = new Command().description("trigger related commands").option("--json", "Output as JSON (for piping to jq)").action(list10).command("list", "list all triggers").option("--json", "Output as JSON (for piping to jq)").action(list10).command("get", "get a trigger's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").option("--kind <kind:string>", "Trigger kind (http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, email). Recommended for faster lookup").action(get8).command("new", "create a new trigger locally").arguments("<path:string>").option("--kind <kind:string>", "Trigger kind (required: http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, email)").action(newTrigger).command("push", "push a local trigger spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").action(push10);
70392
+ command20 = new Command().description("trigger related commands").option("--json", "Output as JSON (for piping to jq)").action(list11).command("list", "list all triggers").option("--json", "Output as JSON (for piping to jq)").action(list11).command("get", "get a trigger's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").option("--kind <kind:string>", "Trigger kind (http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, email). Recommended for faster lookup").action(get8).command("new", "create a new trigger locally").arguments("<path:string>").option("--kind <kind:string>", "Trigger kind (required: http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, email)").action(newTrigger).command("push", "push a local trigger spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").action(push10);
70089
70393
  trigger_default = command20;
70090
70394
  });
70091
70395
 
@@ -70265,10 +70569,13 @@ function getTypeStrFromPath(p) {
70265
70569
  }
70266
70570
  function removeType(str, type) {
70267
70571
  const normalizedStr = path18.normalize(str).replaceAll(SEP18, "/");
70268
- if (!normalizedStr.endsWith("." + type + ".yaml") && !normalizedStr.endsWith("." + type + ".json")) {
70269
- throw new Error(str + " does not end with ." + type + ".(yaml|json)");
70572
+ if (normalizedStr.endsWith("." + type + ".yaml") || normalizedStr.endsWith("." + type + ".json")) {
70573
+ return normalizedStr.slice(0, normalizedStr.length - type.length - 6);
70270
70574
  }
70271
- return normalizedStr.slice(0, normalizedStr.length - type.length - 6);
70575
+ if (normalizedStr.includes("." + type)) {
70576
+ debug(`Path '${str}' contains '.${type}' but doesn't end with '.${type}.(yaml|json)' — treating as clean path`);
70577
+ }
70578
+ return normalizedStr;
70272
70579
  }
70273
70580
  function extractNativeTriggerInfo(p) {
70274
70581
  const normalizedPath = path18.normalize(p).replaceAll(SEP18, "/");
@@ -70348,14 +70655,13 @@ function defaultFlowDefinition() {
70348
70655
  order: [],
70349
70656
  properties: {},
70350
70657
  required: []
70351
- },
70352
- ws_error_handler_muted: false
70658
+ }
70353
70659
  };
70354
70660
  }
70355
70661
 
70356
70662
  // src/utils/local_path_scripts.ts
70357
70663
  import { execFileSync as execFileSync2 } from "node:child_process";
70358
- import { readFile as readFile14, stat as stat15 } from "node:fs/promises";
70664
+ import { readFile as readFile14, stat as stat16 } from "node:fs/promises";
70359
70665
  async function readOptionalLock(scriptPath) {
70360
70666
  try {
70361
70667
  return await readFile14(scriptPath + ".script.lock", "utf-8");
@@ -70419,7 +70725,7 @@ async function resolvePreviewLocalScriptState(scriptPath, opts) {
70419
70725
  const filePath = scriptPath + ext2;
70420
70726
  let fileStat;
70421
70727
  try {
70422
- fileStat = await stat15(filePath);
70728
+ fileStat = await stat16(filePath);
70423
70729
  } catch {
70424
70730
  continue;
70425
70731
  }
@@ -70579,7 +70885,9 @@ async function push11(opts, filePath, remotePath) {
70579
70885
  await pushFlow(workspace.workspaceId, remotePath, filePath);
70580
70886
  info(colors.bold.underline.green("Flow pushed"));
70581
70887
  }
70582
- async function list11(opts) {
70888
+ async function list12(opts) {
70889
+ if (opts.json)
70890
+ setSilent(true);
70583
70891
  const workspace = await resolveWorkspace(opts);
70584
70892
  await requireLogin(opts);
70585
70893
  let page = 0;
@@ -70620,9 +70928,21 @@ async function get9(opts, path19) {
70620
70928
  console.log(colors.bold("Description:") + " " + (f.description ?? ""));
70621
70929
  console.log(colors.bold("Edited by:") + " " + (f.edited_by ?? ""));
70622
70930
  console.log(colors.bold("Edited at:") + " " + (f.edited_at ?? ""));
70931
+ const modules = f.value?.modules;
70932
+ if (modules && Array.isArray(modules) && modules.length > 0) {
70933
+ console.log(colors.bold("Steps:"));
70934
+ for (const mod of modules) {
70935
+ const type = mod.value?.type ?? "unknown";
70936
+ const detail = mod.value?.language ?? mod.value?.path ?? "";
70937
+ console.log(` ${mod.id}: ${type}${detail ? " (" + detail + ")" : ""}`);
70938
+ }
70939
+ }
70623
70940
  }
70624
70941
  }
70625
70942
  async function run3(opts, path19) {
70943
+ if (opts.silent) {
70944
+ setSilent(true);
70945
+ }
70626
70946
  const workspace = await resolveWorkspace(opts);
70627
70947
  await requireLogin(opts);
70628
70948
  const input = opts.data ? await resolve6(opts.data) : {};
@@ -70664,9 +70984,16 @@ async function run3(opts, path19) {
70664
70984
  workspace: workspace.workspaceId,
70665
70985
  id
70666
70986
  });
70667
- info(JSON.stringify(jobInfo.result ?? {}, null, 2));
70987
+ if (opts.silent) {
70988
+ console.log(JSON.stringify(jobInfo.result ?? {}));
70989
+ } else {
70990
+ info(JSON.stringify(jobInfo.result ?? {}, null, 2));
70991
+ }
70668
70992
  }
70669
70993
  async function preview2(opts, flowPath) {
70994
+ if (opts.silent) {
70995
+ setSilent(true);
70996
+ }
70670
70997
  const useLocalPathScripts = !opts.remote;
70671
70998
  if (useLocalPathScripts) {
70672
70999
  opts = await mergeConfigWithConfigFile(opts);
@@ -70674,11 +71001,12 @@ async function preview2(opts, flowPath) {
70674
71001
  const workspace = await resolveWorkspace(opts);
70675
71002
  await requireLogin(opts);
70676
71003
  const codebases = useLocalPathScripts ? listSyncCodebases(opts) : [];
70677
- if (!flowPath.endsWith(".flow") && !flowPath.endsWith(".flow" + SEP19)) {
71004
+ const isFlowDir = flowPath.endsWith(".flow") || flowPath.endsWith(".flow" + SEP19) || flowPath.endsWith("__flow") || flowPath.endsWith("__flow" + SEP19);
71005
+ if (!isFlowDir) {
70678
71006
  if (flowPath.endsWith("flow.yaml") || flowPath.endsWith("flow.json")) {
70679
71007
  flowPath = flowPath.substring(0, flowPath.lastIndexOf(SEP19));
70680
71008
  } else {
70681
- throw new Error("Flow path must be a .flow directory or a flow.yaml file");
71009
+ throw new Error("Flow path must be a .flow/__flow directory or a flow.yaml file");
70682
71010
  }
70683
71011
  }
70684
71012
  if (!flowPath.endsWith(SEP19)) {
@@ -70734,7 +71062,7 @@ async function preview2(opts, flowPath) {
70734
71062
  throw e;
70735
71063
  }
70736
71064
  if (opts.silent) {
70737
- console.log(JSON.stringify(result, null, 2));
71065
+ console.log(JSON.stringify(result));
70738
71066
  } else {
70739
71067
  info(colors.bold.underline.green("Flow preview completed"));
70740
71068
  info(JSON.stringify(result, null, 2));
@@ -70799,6 +71127,53 @@ async function bootstrap2(opts, flowPath) {
70799
71127
  const flowYamlPath = `${flowDirFullPath}/${metadataFile}`;
70800
71128
  writeFileSync5(flowYamlPath, newFlowDefinitionYaml, { flag: "wx", encoding: "utf-8" });
70801
71129
  }
71130
+ async function history2(opts, flowPath) {
71131
+ if (opts.json)
71132
+ setSilent(true);
71133
+ opts = await mergeConfigWithConfigFile(opts);
71134
+ const workspace = await resolveWorkspace(opts);
71135
+ await requireLogin(opts);
71136
+ const versions = await getFlowHistory({
71137
+ workspace: workspace.workspaceId,
71138
+ path: flowPath
71139
+ });
71140
+ if (opts.json) {
71141
+ console.log(JSON.stringify(versions));
71142
+ } else {
71143
+ if (versions.length === 0) {
71144
+ info("No version history found for " + flowPath);
71145
+ return;
71146
+ }
71147
+ new Table2().header(["Version", "Created At", "Deployment Message"]).padding(2).border(true).body(versions.map((v) => [
71148
+ String(v.id),
71149
+ new Date(v.created_at).toISOString().replace("T", " ").substring(0, 19),
71150
+ v.deployment_msg ?? "-"
71151
+ ])).render();
71152
+ }
71153
+ }
71154
+ async function showVersion(opts, flowPath, version) {
71155
+ if (opts.json)
71156
+ setSilent(true);
71157
+ opts = await mergeConfigWithConfigFile(opts);
71158
+ const workspace = await resolveWorkspace(opts);
71159
+ await requireLogin(opts);
71160
+ const flow = await getFlowVersion({
71161
+ workspace: workspace.workspaceId,
71162
+ path: flowPath,
71163
+ version: parseInt(version, 10)
71164
+ });
71165
+ if (opts.json) {
71166
+ console.log(JSON.stringify(flow));
71167
+ } else {
71168
+ console.log(colors.bold("Path:") + " " + flow.path);
71169
+ console.log(colors.bold("Summary:") + " " + (flow.summary ?? "-"));
71170
+ console.log(colors.bold("Description:") + " " + (flow.description ?? "-"));
71171
+ console.log(colors.bold("Schema:"));
71172
+ console.log(JSON.stringify(flow.schema, null, 2));
71173
+ console.log(colors.bold("Value:"));
71174
+ console.log(JSON.stringify(flow.value, null, 2));
71175
+ }
71176
+ }
70802
71177
  var import_yaml36, alreadySynced3, command21, flow_default;
70803
71178
  var init_flow = __esm(async () => {
70804
71179
  init_colors2();
@@ -70823,7 +71198,7 @@ var init_flow = __esm(async () => {
70823
71198
  ]);
70824
71199
  import_yaml36 = __toESM(require_dist(), 1);
70825
71200
  alreadySynced3 = [];
70826
- command21 = new Command().description("flow related commands").option("--show-archived", "Enable archived flows in output").option("--json", "Output as JSON (for piping to jq)").action(list11).command("list", "list all flows").option("--show-archived", "Enable archived flows in output").option("--json", "Output as JSON (for piping to jq)").action(list11).command("get", "get a flow's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get9).command("push", "push a local flow spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").action(push11).command("run", "run a flow by path.").arguments("<path:string>").option("-d --data <data:string>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not ouput anything other then the final output. Useful for scripting.").action(run3).command("preview", "preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default.").arguments("<flow_path:string>").option("-d --data <data:string>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not output anything other then the final output. Useful for scripting.").option("--remote", "Use deployed workspace scripts for PathScript steps instead of local files.").action(preview2).command("generate-locks", "re-generate the lock files of all inline scripts of all updated flows").arguments("[flow:file]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Perform a dry run without making changes").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.").action(generateLocks).command("new", "create a new empty flow").arguments("<flow_path:string>").option("--summary <summary:string>", "flow summary").option("--description <description:string>", "flow description").action(bootstrap2).command("bootstrap", "create a new empty flow (alias for new)").arguments("<flow_path:string>").option("--summary <summary:string>", "flow summary").option("--description <description:string>", "flow description").action(bootstrap2);
71201
+ command21 = new Command().description("flow related commands").option("--show-archived", "Enable archived flows in output").option("--json", "Output as JSON (for piping to jq)").action(list12).command("list", "list all flows").option("--show-archived", "Enable archived flows in output").option("--json", "Output as JSON (for piping to jq)").action(list12).command("get", "get a flow's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get9).command("push", "push a local flow spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").action(push11).command("run", "run a flow by path.").arguments("<path:string>").option("-d --data <data:string>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not ouput anything other then the final output. Useful for scripting.").action(run3).command("preview", "preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default.").arguments("<flow_path:string>").option("-d --data <data:string>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not output anything other then the final output. Useful for scripting.").option("--remote", "Use deployed workspace scripts for PathScript steps instead of local files.").action(preview2).command("generate-locks", "re-generate the lock files of all inline scripts of all updated flows").arguments("[flow:file]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Perform a dry run without making changes").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.").action(generateLocks).command("new", "create a new empty flow").arguments("<flow_path:string>").option("--summary <summary:string>", "flow summary").option("--description <description:string>", "flow description").action(bootstrap2).command("bootstrap", "create a new empty flow (alias for new)").arguments("<flow_path:string>").option("--summary <summary:string>", "flow summary").option("--description <description:string>", "flow description").action(bootstrap2).command("history", "Show version history for a flow").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(history2).command("show-version", "Show a specific version of a flow").arguments("<path:string> <version:string>").option("--json", "Output as JSON (for piping to jq)").action(showVersion);
70827
71202
  flow_default = command21;
70828
71203
  });
70829
71204
 
@@ -72007,22 +72382,22 @@ class DoubleLinkedDependencyTree {
72007
72382
  return this.nodes.has(path19);
72008
72383
  }
72009
72384
  getMismatchedWorkspaceDeps() {
72010
- const result = {};
72385
+ const result2 = {};
72011
72386
  for (const [path19, node] of this.nodes.entries()) {
72012
72387
  if (node.itemType === "dependencies" && node.contentHash && node.content !== undefined) {
72013
- result[path19] = node.content;
72388
+ result2[path19] = node.content;
72014
72389
  }
72015
72390
  }
72016
- return result;
72391
+ return result2;
72017
72392
  }
72018
72393
  getTempScriptRefs(scriptPath) {
72019
- const result = {};
72394
+ const result2 = {};
72020
72395
  this.traverseTransitive(scriptPath, (_path, node) => {
72021
72396
  if (node.contentHash) {
72022
- result[_path] = node.contentHash;
72397
+ result2[_path] = node.contentHash;
72023
72398
  }
72024
72399
  });
72025
- return result;
72400
+ return result2;
72026
72401
  }
72027
72402
  async persistDepsHashes(depsPaths) {
72028
72403
  for (const path19 of depsPaths) {
@@ -73289,8 +73664,8 @@ async function pull2(opts) {
73289
73664
  throw new Error("Couldn't fetch resource types from hub " + hubBaseUrl + ": " + await res1.text());
73290
73665
  }
73291
73666
  }
73292
- let list12 = await res1.json();
73293
- if (list12 && list12.length === 0 && hubBaseUrl !== DEFAULT_HUB_BASE_URL) {
73667
+ let list13 = await res1.json();
73668
+ if (list13 && list13.length === 0 && hubBaseUrl !== DEFAULT_HUB_BASE_URL) {
73294
73669
  info("No resource types found in private hub, fetching from public hub");
73295
73670
  delete headers["X-api-secret"];
73296
73671
  const res2 = await fetch(DEFAULT_HUB_BASE_URL + "/resource_types/list", {
@@ -73299,12 +73674,12 @@ async function pull2(opts) {
73299
73674
  if (!res2.ok) {
73300
73675
  throw new Error("Couldn't fetch resource types from public hub: " + await res2.text());
73301
73676
  }
73302
- list12 = await res2.json();
73677
+ list13 = await res2.json();
73303
73678
  }
73304
73679
  const resourceTypes = await listResourceType({
73305
73680
  workspace: workspace.workspaceId
73306
73681
  });
73307
- for (const x of list12) {
73682
+ for (const x of list13) {
73308
73683
  try {
73309
73684
  x.schema = JSON.parse(x.schema);
73310
73685
  } catch (e) {
@@ -73496,7 +73871,7 @@ async function dev2(opts) {
73496
73871
  await Promise.all([startApp(), watchChanges()]);
73497
73872
  console.log("Stopped dev mode");
73498
73873
  }
73499
- var command24 = new Command().description("Launch a dev server that will spawn a webserver with HMR").option("--includes <pattern...:string>", "Filter paths givena glob pattern or path").action(dev2);
73874
+ var command24 = new Command().description("Launch a dev server that watches for local file changes and auto-pushes them to the remote workspace. Provides live reload for scripts and flows during development.").option("--includes <pattern...:string>", "Filter paths givena glob pattern or path").action(dev2);
73500
73875
  var dev_default2 = command24;
73501
73876
 
73502
73877
  // src/main.ts
@@ -73736,7 +74111,7 @@ await __promiseAll([
73736
74111
  init_workspace(),
73737
74112
  init_resource_type()
73738
74113
  ]);
73739
- import { stat as stat16, writeFile as writeFile19, rm as rm4, mkdir as mkdir9 } from "node:fs/promises";
74114
+ import { stat as stat17, writeFile as writeFile19, rm as rm4, mkdir as mkdir9 } from "node:fs/promises";
73740
74115
 
73741
74116
  // src/guidance/skills.ts
73742
74117
  var SKILLS = [
@@ -78730,6 +79105,16 @@ app related commands
78730
79105
  - \`--dry-run\` - Perform a dry run without making changes
78731
79106
  - \`--default-ts <runtime:string>\` - Default TypeScript runtime (bun or deno)
78732
79107
 
79108
+ ### audit
79109
+
79110
+ View audit logs (requires admin)
79111
+
79112
+ **Subcommands:**
79113
+
79114
+ - \`audit list\` - List audit log entries
79115
+ - \`audit get <id:string>\` - Get a specific audit log entry
79116
+ - \`--json\` - Output as JSON (for piping to jq)
79117
+
78733
79118
  ### config
78734
79119
 
78735
79120
  Show all available wmill.yaml configuration options
@@ -78749,14 +79134,14 @@ workspace dependencies related commands
78749
79134
 
78750
79135
  ### dev
78751
79136
 
78752
- Launch a dev server that will spawn a webserver with HMR
79137
+ Launch a dev server that watches for local file changes and auto-pushes them to the remote workspace. Provides live reload for scripts and flows during development.
78753
79138
 
78754
79139
  **Options:**
78755
79140
  - \`--includes <pattern...:string>\` - Filter paths givena glob pattern or path
78756
79141
 
78757
79142
  ### docs
78758
79143
 
78759
- Search Windmill documentation. Requires Enterprise Edition.
79144
+ Search Windmill documentation.
78760
79145
 
78761
79146
  **Arguments:** \`<query:string>\`
78762
79147
 
@@ -78797,6 +79182,10 @@ flow related commands
78797
79182
  - \`flow bootstrap <flow_path:string>\` - create a new empty flow (alias for new
78798
79183
  - \`--summary <summary:string>\` - flow summary
78799
79184
  - \`--description <description:string>\` - flow description
79185
+ - \`flow history <path:string>\` - Show version history for a flow
79186
+ - \`--json\` - Output as JSON (for piping to jq)
79187
+ - \`flow show-version <path:string> <version:string>\` - Show a specific version of a flow
79188
+ - \`--json\` - Output as JSON (for piping to jq)
78800
79189
 
78801
79190
  ### folder
78802
79191
 
@@ -78859,6 +79248,25 @@ Manage git-sync settings between local wmill.yaml and Windmill backend
78859
79248
  - \`--yes\` - Skip interactive prompts and use default behavior
78860
79249
  - \`--promotion <branch:string>\` - Use promotionOverrides from the specified branch instead of regular overrides
78861
79250
 
79251
+ ### group
79252
+
79253
+ Manage workspace groups
79254
+
79255
+ **Options:**
79256
+ - \`--json\` - Output as JSON (for piping to jq)
79257
+
79258
+ **Subcommands:**
79259
+
79260
+ - \`group list\` - List all groups in the workspace
79261
+ - \`--json\` - Output as JSON (for piping to jq)
79262
+ - \`group get <name:string>\` - Get group details and members
79263
+ - \`--json\` - Output as JSON (for piping to jq)
79264
+ - \`group create <name:string>\` - Create a new group
79265
+ - \`--summary <summary:string>\` - Group summary/description
79266
+ - \`group delete <name:string>\` - Delete a group
79267
+ - \`group add-user <name:string> <username:string>\` - Add a user to a group
79268
+ - \`group remove-user <name:string> <username:string>\` - Remove a user from a group
79269
+
78862
79270
  ### hub
78863
79271
 
78864
79272
  Hub related commands. EXPERIMENTAL. INTERNAL USE ONLY.
@@ -78914,8 +79322,23 @@ sync local with a remote instance or the opposite (push or pull)
78914
79322
  - \`instance whoami\` - Display information about the currently logged-in user
78915
79323
  - \`instance get-config\` - Dump the current instance config (global settings + worker configs) as YAML
78916
79324
  - \`-o, --output-file <file:string>\` - Write YAML to a file instead of stdout
79325
+ - \`--show-secrets\` - Include sensitive fields (license key, JWT secret) without prompting
78917
79326
  - \`--instance <instance:string>\` - Name of the instance, override the active instance
78918
79327
 
79328
+ ### job
79329
+
79330
+ Manage jobs (list, inspect, cancel)
79331
+
79332
+ **Subcommands:**
79333
+
79334
+ - \`job list\` - List recent jobs
79335
+ - \`job get <id:string>\` - Get job details and result
79336
+ - \`--json\` - Output as JSON (for piping to jq)
79337
+ - \`job result <id:string>\` - Get the result of a completed job (machine-friendly
79338
+ - \`job logs <id:string>\` - Get job logs
79339
+ - \`job cancel <id:string>\` - Cancel a running or queued job
79340
+ - \`--reason <reason:string>\` - Reason for cancellation
79341
+
78919
79342
  ### jobs
78920
79343
 
78921
79344
  Pull completed and queued jobs from workspace
@@ -79002,6 +79425,8 @@ schedule related commands
79002
79425
  - \`--json\` - Output as JSON (for piping to jq)
79003
79426
  - \`schedule new <path:string>\` - create a new schedule locally
79004
79427
  - \`schedule push <file_path:string> <remote_path:string>\` - push a local schedule spec. This overrides any remote versions.
79428
+ - \`schedule enable <path:string>\` - Enable a schedule
79429
+ - \`schedule disable <path:string>\` - Disable a schedule
79005
79430
 
79006
79431
  ### script
79007
79432
 
@@ -79039,6 +79464,8 @@ script related commands
79039
79464
  - \`--schema-only\` - re-generate only script schema
79040
79465
  - \`-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)
79041
79466
  - \`-e --excludes <patterns:file[]>\` - Comma separated patterns to specify which file to NOT take into account.
79467
+ - \`script history <path:string>\` - show version history for a script
79468
+ - \`--json\` - Output as JSON (for piping to jq)
79042
79469
 
79043
79470
  ### sync
79044
79471
 
@@ -79053,6 +79480,7 @@ sync local with a remote workspaces or the opposite (push or pull)
79053
79480
  - \`--json\` - Use JSON instead of YAML
79054
79481
  - \`--skip-variables\` - Skip syncing variables (including secrets)
79055
79482
  - \`--skip-secrets\` - Skip syncing only secrets variables
79483
+ - \`--include-secrets\` - Include secrets in sync (overrides skipSecrets in wmill.yaml)
79056
79484
  - \`--skip-resources\` - Skip syncing resources
79057
79485
  - \`--skip-resource-types\` - Skip syncing resource types
79058
79486
  - \`--skip-scripts\` - Skip syncing scripts
@@ -79082,6 +79510,7 @@ sync local with a remote workspaces or the opposite (push or pull)
79082
79510
  - \`--json\` - Use JSON instead of YAML
79083
79511
  - \`--skip-variables\` - Skip syncing variables (including secrets)
79084
79512
  - \`--skip-secrets\` - Skip syncing only secrets variables
79513
+ - \`--include-secrets\` - Include secrets in sync (overrides skipSecrets in wmill.yaml)
79085
79514
  - \`--skip-resources\` - Skip syncing resources
79086
79515
  - \`--skip-resource-types\` - Skip syncing resource types
79087
79516
  - \`--skip-scripts\` - Skip syncing scripts
@@ -79107,6 +79536,23 @@ sync local with a remote workspaces or the opposite (push or pull)
79107
79536
  - \`--branch, --env <branch:string>\` - Override the current git branch/environment (works even outside a git repository)
79108
79537
  - \`--lint\` - Run lint validation before pushing
79109
79538
  - \`--locks-required\` - Fail if scripts or flow inline scripts that need locks have no locks
79539
+ - \`--auto-metadata\` - Automatically regenerate stale metadata (locks and schemas) before pushing
79540
+
79541
+ ### token
79542
+
79543
+ Manage API tokens
79544
+
79545
+ **Options:**
79546
+ - \`--json\` - Output as JSON (for piping to jq)
79547
+
79548
+ **Subcommands:**
79549
+
79550
+ - \`token list\` - List API tokens
79551
+ - \`--json\` - Output as JSON (for piping to jq)
79552
+ - \`token create\` - Create a new API token
79553
+ - \`--label <label:string>\` - Token label
79554
+ - \`--expiration <expiration:string>\` - Token expiration (ISO 8601 timestamp)
79555
+ - \`token delete <token_prefix:string>\` - Delete a token by its prefix
79110
79556
 
79111
79557
  ### trigger
79112
79558
 
@@ -79137,7 +79583,7 @@ user related commands
79137
79583
  - \`--company <company:string>\` - Specify to set the company of the new user.
79138
79584
  - \`--name <name:string>\` - Specify to set the name of the new user.
79139
79585
  - \`user remove <email:string>\` - Delete a user
79140
- - \`user create-token\`
79586
+ - \`user create-token\` - Create a new API token for the authenticated user
79141
79587
  - \`--email <email:string>\` - Specify credentials to use for authentication. This will not be stored. It will only be used to exchange for a token with the API server, which will not be stored either.
79142
79588
  - \`--password <password:string>\` - Specify credentials to use for authentication. This will not be stored. It will only be used to exchange for a token with the API server, which will not be stored either.
79143
79589
 
@@ -79205,7 +79651,8 @@ workspace related commands
79205
79651
  - \`workspace whoami\` - Show the currently active user
79206
79652
  - \`workspace list\` - List local workspace profiles
79207
79653
  - \`workspace list-remote\` - List workspaces on the remote server that you have access to
79208
- - \`workspace bind\` - Bind the current Git branch to the active workspace
79654
+ - \`workspace list-forks\` - List forked workspaces on the remote server
79655
+ - \`workspace bind\` - Bind the current Git branch to the active workspace. This adds the branch to gitBranches in wmill.yaml so sync operations use the correct workspace for each branch.
79209
79656
  - \`--branch, --env <branch:string>\` - Specify branch/environment (defaults to current)
79210
79657
  - \`workspace unbind\` - Remove workspace binding from the current Git branch
79211
79658
  - \`--branch, --env <branch:string>\` - Specify branch/environment (defaults to current)
@@ -80543,7 +80990,7 @@ ${schemaYaml.trim()}
80543
80990
  \`\`\``;
80544
80991
  }
80545
80992
  async function initAction(opts) {
80546
- if (await stat16("wmill.yaml").catch(() => null)) {
80993
+ if (await stat17("wmill.yaml").catch(() => null)) {
80547
80994
  error(colors.red("wmill.yaml already exists"));
80548
80995
  } else {
80549
80996
  const { isGitRepository: isGitRepository2, getCurrentGitBranch: getCurrentGitBranch2 } = await Promise.resolve().then(() => (init_git(), exports_git));
@@ -80664,11 +81111,11 @@ Current Git branch: ${colors.bold(branchName)}`));
80664
81111
  const skills_base_dir = ".claude/skills";
80665
81112
  const skillsReference = SKILLS.map((s) => `- \`${skills_base_dir}/${s.name}/SKILL.md\` - ${s.description}`).join(`
80666
81113
  `);
80667
- if (!await stat16("AGENTS.md").catch(() => null)) {
81114
+ if (!await stat17("AGENTS.md").catch(() => null)) {
80668
81115
  await writeFile19("AGENTS.md", generateAgentsMdContent(skillsReference), "utf-8");
80669
81116
  info(colors.green("Created AGENTS.md"));
80670
81117
  }
80671
- if (!await stat16("CLAUDE.md").catch(() => null)) {
81118
+ if (!await stat17("CLAUDE.md").catch(() => null)) {
80672
81119
  await writeFile19("CLAUDE.md", `Instructions are in @AGENTS.md
80673
81120
  `, "utf-8");
80674
81121
  info(colors.green("Created CLAUDE.md"));
@@ -80895,6 +81342,400 @@ var push12 = new Command().description("Push completed and queued jobs to worksp
80895
81342
  var command28 = new Command().description("Manage jobs (import/export)").command("pull", pull3).command("push", push12);
80896
81343
  var jobs_default = command28;
80897
81344
 
81345
+ // src/commands/job/job.ts
81346
+ init_mod3();
81347
+ init_mod6();
81348
+ init_colors2();
81349
+ init_log();
81350
+ init_services_gen();
81351
+ await __promiseAll([
81352
+ init_auth(),
81353
+ init_context(),
81354
+ init_conf(),
81355
+ init_utils()
81356
+ ]);
81357
+ function formatDuration(ms) {
81358
+ if (ms < 1000)
81359
+ return `${ms}ms`;
81360
+ const seconds = Math.floor(ms / 1000);
81361
+ if (seconds < 60)
81362
+ return `${seconds}s`;
81363
+ const minutes = Math.floor(seconds / 60);
81364
+ const remainingSeconds = seconds % 60;
81365
+ if (minutes < 60)
81366
+ return `${minutes}m${remainingSeconds}s`;
81367
+ const hours = Math.floor(minutes / 60);
81368
+ const remainingMinutes = minutes % 60;
81369
+ return `${hours}h${remainingMinutes}m`;
81370
+ }
81371
+ function getJobStatus2(job) {
81372
+ if (job.type === "QueuedJob") {
81373
+ if (job.canceled)
81374
+ return colors.red("canceled");
81375
+ if (job.running)
81376
+ return colors.blue("running");
81377
+ return colors.yellow("queued");
81378
+ }
81379
+ if (job.canceled)
81380
+ return colors.red("canceled");
81381
+ if (job.success)
81382
+ return colors.green("success");
81383
+ return colors.red("failure");
81384
+ }
81385
+ function getJobStatusPlain(job) {
81386
+ if (job.type === "QueuedJob") {
81387
+ if (job.canceled)
81388
+ return "canceled";
81389
+ if (job.running)
81390
+ return "running";
81391
+ return "queued";
81392
+ }
81393
+ if (job.canceled)
81394
+ return "canceled";
81395
+ if (job.success)
81396
+ return "success";
81397
+ return "failure";
81398
+ }
81399
+ async function list13(opts) {
81400
+ if (opts.json)
81401
+ setSilent(true);
81402
+ opts = await mergeConfigWithConfigFile(opts);
81403
+ const workspace = await resolveWorkspace(opts);
81404
+ await requireLogin(opts);
81405
+ let successFilter = opts.success;
81406
+ if (opts.failed)
81407
+ successFilter = false;
81408
+ const jobs = await listJobs({
81409
+ workspace: workspace.workspaceId,
81410
+ scriptPathExact: opts.scriptPath,
81411
+ createdBy: opts.createdBy,
81412
+ running: opts.running,
81413
+ success: successFilter,
81414
+ perPage: Math.min(opts.limit ?? 30, 100),
81415
+ jobKinds: opts.jobKinds ?? "script,flow,singlestepflow",
81416
+ label: opts.label,
81417
+ hasNullParent: opts.all ? undefined : true
81418
+ });
81419
+ if (opts.json) {
81420
+ console.log(JSON.stringify(jobs));
81421
+ } else {
81422
+ if (jobs.length === 0) {
81423
+ info("No jobs found.");
81424
+ return;
81425
+ }
81426
+ new Table2().header(["ID", "Status", "Script/Flow", "Created By", "Duration", "Created At"]).padding(2).border(true).body(jobs.map((j) => [
81427
+ j.id.substring(0, 8),
81428
+ getJobStatus2(j),
81429
+ j.script_path ?? j.raw_code?.substring(0, 30) ?? "-",
81430
+ j.created_by ?? j.email ?? "-",
81431
+ j.duration_ms != null ? formatDuration(j.duration_ms) : j.running ? "running" : "-",
81432
+ j.created_at ? formatTimestamp(j.created_at) : "-"
81433
+ ])).render();
81434
+ info(`
81435
+ Showing ${jobs.length} job(s). Use --limit to show more.`);
81436
+ }
81437
+ }
81438
+ async function get10(opts, id) {
81439
+ if (opts.json)
81440
+ setSilent(true);
81441
+ opts = await mergeConfigWithConfigFile(opts);
81442
+ const workspace = await resolveWorkspace(opts);
81443
+ await requireLogin(opts);
81444
+ const job = await getJob({
81445
+ workspace: workspace.workspaceId,
81446
+ id
81447
+ });
81448
+ if (opts.json) {
81449
+ console.log(JSON.stringify(job));
81450
+ } else {
81451
+ const j = job;
81452
+ console.log(colors.bold("ID:") + " " + j.id);
81453
+ console.log(colors.bold("Status:") + " " + getJobStatusPlain(j));
81454
+ console.log(colors.bold("Kind:") + " " + j.job_kind);
81455
+ console.log(colors.bold("Script Path:") + " " + (j.script_path ?? "-"));
81456
+ console.log(colors.bold("Created By:") + " " + (j.created_by ?? "-"));
81457
+ console.log(colors.bold("Created At:") + " " + (j.created_at ? formatTimestamp(j.created_at) : "-"));
81458
+ if (j.started_at) {
81459
+ console.log(colors.bold("Started At:") + " " + formatTimestamp(j.started_at));
81460
+ }
81461
+ if (j.duration_ms != null) {
81462
+ console.log(colors.bold("Duration:") + " " + formatDuration(j.duration_ms));
81463
+ }
81464
+ if (j.schedule_path) {
81465
+ console.log(colors.bold("Schedule:") + " " + j.schedule_path);
81466
+ }
81467
+ if (j.result !== undefined) {
81468
+ console.log(colors.bold("Result:"));
81469
+ console.log(JSON.stringify(j.result, null, 2));
81470
+ }
81471
+ }
81472
+ }
81473
+ async function result(opts, id) {
81474
+ setSilent(true);
81475
+ opts = await mergeConfigWithConfigFile(opts);
81476
+ const workspace = await resolveWorkspace(opts);
81477
+ await requireLogin(opts);
81478
+ const jobResult = await getCompletedJobResult({
81479
+ workspace: workspace.workspaceId,
81480
+ id
81481
+ });
81482
+ console.log(JSON.stringify(jobResult));
81483
+ }
81484
+ async function logs(opts, id) {
81485
+ opts = await mergeConfigWithConfigFile(opts);
81486
+ const workspace = await resolveWorkspace(opts);
81487
+ await requireLogin(opts);
81488
+ const jobLogs = await getJobLogs({
81489
+ workspace: workspace.workspaceId,
81490
+ id
81491
+ });
81492
+ console.log(jobLogs);
81493
+ }
81494
+ async function cancel(opts, id) {
81495
+ opts = await mergeConfigWithConfigFile(opts);
81496
+ const workspace = await resolveWorkspace(opts);
81497
+ await requireLogin(opts);
81498
+ await cancelQueuedJob({
81499
+ workspace: workspace.workspaceId,
81500
+ id,
81501
+ requestBody: {
81502
+ reason: opts.reason ?? "Canceled via CLI"
81503
+ }
81504
+ });
81505
+ info(colors.green(`Job ${id} canceled.`));
81506
+ }
81507
+ var listOptions = (cmd) => cmd.option("--json", "Output as JSON (for piping to jq)").option("--script-path <scriptPath:string>", "Filter by exact script/flow path").option("--created-by <createdBy:string>", "Filter by creator username").option("--running", "Show only running jobs").option("--failed", "Show only failed jobs").option("--success <success:boolean>", "Filter by success status (true/false)").option("--limit <limit:number>", "Number of jobs to return (default 30, max 100)").option("--job-kinds <jobKinds:string>", "Filter by job kinds (default: script,flow,singlestepflow)").option("--label <label:string>", "Filter by job label").option("--all", "Include sub-jobs (flow steps). By default only top-level jobs are shown");
81508
+ var command29 = listOptions(new Command().description("Manage jobs (list, inspect, cancel)")).action(list13).command("list", listOptions(new Command().description("List recent jobs"))).action(list13).command("get", "Get job details and result").arguments("<id:string>").option("--json", "Output as JSON (for piping to jq)").action(get10).command("result", "Get the result of a completed job (machine-friendly)").arguments("<id:string>").action(result).command("logs", "Get job logs").arguments("<id:string>").action(logs).command("cancel", "Cancel a running or queued job").arguments("<id:string>").option("--reason <reason:string>", "Reason for cancellation").action(cancel);
81509
+ var job_default = command29;
81510
+
81511
+ // src/commands/group/group.ts
81512
+ init_mod3();
81513
+ init_mod6();
81514
+ init_colors2();
81515
+ init_log();
81516
+ init_services_gen();
81517
+ await __promiseAll([
81518
+ init_auth(),
81519
+ init_context(),
81520
+ init_conf()
81521
+ ]);
81522
+ async function list14(opts) {
81523
+ if (opts.json)
81524
+ setSilent(true);
81525
+ opts = await mergeConfigWithConfigFile(opts);
81526
+ const workspace = await resolveWorkspace(opts);
81527
+ await requireLogin(opts);
81528
+ const groups = await listGroups({
81529
+ workspace: workspace.workspaceId
81530
+ });
81531
+ if (opts.json) {
81532
+ console.log(JSON.stringify(groups));
81533
+ } else {
81534
+ if (groups.length === 0) {
81535
+ info("No groups found.");
81536
+ return;
81537
+ }
81538
+ new Table2().header(["Name", "Summary", "Members"]).padding(2).border(true).body(groups.map((g) => [
81539
+ g.name,
81540
+ g.summary ?? "-",
81541
+ String(g.members?.length ?? 0)
81542
+ ])).render();
81543
+ }
81544
+ }
81545
+ async function get11(opts, name) {
81546
+ if (opts.json)
81547
+ setSilent(true);
81548
+ opts = await mergeConfigWithConfigFile(opts);
81549
+ const workspace = await resolveWorkspace(opts);
81550
+ await requireLogin(opts);
81551
+ const group = await getGroup({
81552
+ workspace: workspace.workspaceId,
81553
+ name
81554
+ });
81555
+ if (opts.json) {
81556
+ console.log(JSON.stringify(group));
81557
+ } else {
81558
+ console.log(colors.bold("Name:") + " " + group.name);
81559
+ console.log(colors.bold("Summary:") + " " + (group.summary ?? "-"));
81560
+ console.log(colors.bold("Members:") + " " + (group.members && group.members.length > 0 ? group.members.join(", ") : "(none)"));
81561
+ }
81562
+ }
81563
+ async function create(opts, name) {
81564
+ opts = await mergeConfigWithConfigFile(opts);
81565
+ const workspace = await resolveWorkspace(opts);
81566
+ await requireLogin(opts);
81567
+ await createGroup({
81568
+ workspace: workspace.workspaceId,
81569
+ requestBody: {
81570
+ name,
81571
+ summary: opts.summary
81572
+ }
81573
+ });
81574
+ info(colors.green(`Group '${name}' created.`));
81575
+ }
81576
+ async function deleteGroup2(opts, name) {
81577
+ opts = await mergeConfigWithConfigFile(opts);
81578
+ const workspace = await resolveWorkspace(opts);
81579
+ await requireLogin(opts);
81580
+ await deleteGroup({
81581
+ workspace: workspace.workspaceId,
81582
+ name
81583
+ });
81584
+ info(colors.green(`Group '${name}' deleted.`));
81585
+ }
81586
+ async function addUser2(opts, name, username) {
81587
+ opts = await mergeConfigWithConfigFile(opts);
81588
+ const workspace = await resolveWorkspace(opts);
81589
+ await requireLogin(opts);
81590
+ await addUserToGroup({
81591
+ workspace: workspace.workspaceId,
81592
+ name,
81593
+ requestBody: { username }
81594
+ });
81595
+ info(colors.green(`User '${username}' added to group '${name}'.`));
81596
+ }
81597
+ async function removeUser(opts, name, username) {
81598
+ opts = await mergeConfigWithConfigFile(opts);
81599
+ const workspace = await resolveWorkspace(opts);
81600
+ await requireLogin(opts);
81601
+ await removeUserToGroup({
81602
+ workspace: workspace.workspaceId,
81603
+ name,
81604
+ requestBody: { username }
81605
+ });
81606
+ info(colors.green(`User '${username}' removed from group '${name}'.`));
81607
+ }
81608
+ var command30 = new Command().description("Manage workspace groups").option("--json", "Output as JSON (for piping to jq)").action(list14).command("list", "List all groups in the workspace").option("--json", "Output as JSON (for piping to jq)").action(list14).command("get", "Get group details and members").arguments("<name:string>").option("--json", "Output as JSON (for piping to jq)").action(get11).command("create", "Create a new group").arguments("<name:string>").option("--summary <summary:string>", "Group summary/description").action(create).command("delete", "Delete a group").arguments("<name:string>").action(deleteGroup2).command("add-user", "Add a user to a group").arguments("<name:string> <username:string>").action(addUser2).command("remove-user", "Remove a user from a group").arguments("<name:string> <username:string>").action(removeUser);
81609
+ var group_default = command30;
81610
+
81611
+ // src/commands/audit/audit.ts
81612
+ init_mod3();
81613
+ init_mod6();
81614
+ init_colors2();
81615
+ init_log();
81616
+ init_services_gen();
81617
+ await __promiseAll([
81618
+ init_auth(),
81619
+ init_context(),
81620
+ init_conf(),
81621
+ init_utils()
81622
+ ]);
81623
+ async function list15(opts) {
81624
+ if (opts.json)
81625
+ setSilent(true);
81626
+ opts = await mergeConfigWithConfigFile(opts);
81627
+ const workspace = await resolveWorkspace(opts);
81628
+ await requireLogin(opts);
81629
+ const logs2 = await listAuditLogs({
81630
+ workspace: workspace.workspaceId,
81631
+ username: opts.username,
81632
+ operation: opts.operation,
81633
+ actionKind: opts.actionKind,
81634
+ before: opts.before,
81635
+ after: opts.after,
81636
+ perPage: opts.limit ?? 30
81637
+ });
81638
+ if (opts.json) {
81639
+ console.log(JSON.stringify(logs2));
81640
+ } else {
81641
+ if (logs2.length === 0) {
81642
+ info("No audit logs found.");
81643
+ return;
81644
+ }
81645
+ new Table2().header(["ID", "Timestamp", "Username", "Operation", "Action", "Resource"]).padding(2).border(true).body(logs2.map((l) => [
81646
+ String(l.id),
81647
+ formatTimestamp(l.timestamp),
81648
+ l.username,
81649
+ l.operation,
81650
+ l.action_kind,
81651
+ l.resource ?? "-"
81652
+ ])).render();
81653
+ }
81654
+ }
81655
+ async function get12(opts, id) {
81656
+ if (opts.json)
81657
+ setSilent(true);
81658
+ opts = await mergeConfigWithConfigFile(opts);
81659
+ const workspace = await resolveWorkspace(opts);
81660
+ await requireLogin(opts);
81661
+ const auditLog = await getAuditLog({
81662
+ workspace: workspace.workspaceId,
81663
+ id: parseInt(id, 10)
81664
+ });
81665
+ if (opts.json) {
81666
+ console.log(JSON.stringify(auditLog));
81667
+ } else {
81668
+ console.log(colors.bold("ID:") + " " + auditLog.id);
81669
+ console.log(colors.bold("Timestamp:") + " " + formatTimestamp(auditLog.timestamp));
81670
+ console.log(colors.bold("Username:") + " " + auditLog.username);
81671
+ console.log(colors.bold("Operation:") + " " + auditLog.operation);
81672
+ console.log(colors.bold("Action Kind:") + " " + auditLog.action_kind);
81673
+ console.log(colors.bold("Resource:") + " " + (auditLog.resource ?? "-"));
81674
+ if (auditLog.parameters && Object.keys(auditLog.parameters).length > 0) {
81675
+ console.log(colors.bold("Parameters:"));
81676
+ console.log(JSON.stringify(auditLog.parameters, null, 2));
81677
+ }
81678
+ }
81679
+ }
81680
+ var auditListOptions = (cmd) => cmd.option("--json", "Output as JSON (for piping to jq)").option("--username <username:string>", "Filter by username").option("--operation <operation:string>", "Filter by operation (exact or prefix)").option("--action-kind <actionKind:string>", "Filter by action kind (Create, Update, Delete, Execute)").option("--before <before:string>", "Filter events before this timestamp").option("--after <after:string>", "Filter events after this timestamp").option("--limit <limit:number>", "Number of entries to return (default 30, max 100)");
81681
+ var command31 = auditListOptions(new Command().description("View audit logs (requires admin)")).action(list15).command("list", auditListOptions(new Command().description("List audit log entries"))).action(list15).command("get", "Get a specific audit log entry").arguments("<id:string>").option("--json", "Output as JSON (for piping to jq)").action(get12);
81682
+ var audit_default = command31;
81683
+
81684
+ // src/commands/token/token.ts
81685
+ init_mod3();
81686
+ init_mod6();
81687
+ init_colors2();
81688
+ init_log();
81689
+ init_services_gen();
81690
+ await __promiseAll([
81691
+ init_auth(),
81692
+ init_conf(),
81693
+ init_utils()
81694
+ ]);
81695
+ async function list16(opts) {
81696
+ if (opts.json)
81697
+ setSilent(true);
81698
+ opts = await mergeConfigWithConfigFile(opts);
81699
+ await requireLogin(opts);
81700
+ const tokens = await listTokens({
81701
+ excludeEphemeral: true
81702
+ });
81703
+ if (opts.json) {
81704
+ console.log(JSON.stringify(tokens));
81705
+ } else {
81706
+ if (tokens.length === 0) {
81707
+ info("No tokens found.");
81708
+ return;
81709
+ }
81710
+ new Table2().header(["Prefix", "Label", "Created At", "Last Used", "Expiration"]).padding(2).border(true).body(tokens.map((t) => [
81711
+ t.token_prefix,
81712
+ t.label ?? "-",
81713
+ formatTimestamp(t.created_at),
81714
+ formatTimestamp(t.last_used_at),
81715
+ t.expiration ? formatTimestamp(t.expiration) : "never"
81716
+ ])).render();
81717
+ }
81718
+ }
81719
+ async function create2(opts) {
81720
+ opts = await mergeConfigWithConfigFile(opts);
81721
+ await requireLogin(opts);
81722
+ const token = await createToken({
81723
+ requestBody: {
81724
+ label: opts.label,
81725
+ expiration: opts.expiration
81726
+ }
81727
+ });
81728
+ console.log(token);
81729
+ }
81730
+ async function deleteToken2(opts, tokenPrefix) {
81731
+ opts = await mergeConfigWithConfigFile(opts);
81732
+ await requireLogin(opts);
81733
+ await deleteToken({ tokenPrefix });
81734
+ info(colors.green(`Token with prefix '${tokenPrefix}' deleted.`));
81735
+ }
81736
+ var command32 = new Command().description("Manage API tokens").option("--json", "Output as JSON (for piping to jq)").action(list16).command("list", "List API tokens").option("--json", "Output as JSON (for piping to jq)").action(list16).command("create", "Create a new API token").option("--label <label:string>", "Token label").option("--expiration <expiration:string>", "Token expiration (ISO 8601 timestamp)").action(create2).command("delete", "Delete a token by its prefix").arguments("<token_prefix:string>").action(deleteToken2);
81737
+ var token_default = command32;
81738
+
80898
81739
  // src/commands/generate-metadata/generate-metadata.ts
80899
81740
  init_mod3();
80900
81741
  init_colors2();
@@ -81082,32 +81923,62 @@ async function generateMetadata2(opts, folder) {
81082
81923
  const formatProgress = (n) => {
81083
81924
  return colors.dim(colors.white(`[${n}/${total}]`.padEnd(maxWidth, " ")));
81084
81925
  };
81926
+ const errors = [];
81085
81927
  for (const item of scripts) {
81086
81928
  current++;
81087
81929
  info(`${formatProgress(current)} script ${item.path}`);
81088
- await generateScriptMetadataInternal(item.path, workspace, opts, false, true, mismatchedWorkspaceDeps, codebases, false, false, tree);
81930
+ try {
81931
+ await generateScriptMetadataInternal(item.path, workspace, opts, false, true, mismatchedWorkspaceDeps, codebases, false, false, tree);
81932
+ } catch (e) {
81933
+ const msg = e instanceof Error ? e.message : String(e);
81934
+ errors.push({ path: item.path, error: msg });
81935
+ error(` Failed: ${msg}`);
81936
+ }
81089
81937
  }
81090
81938
  for (const item of flows) {
81091
81939
  current++;
81092
- const result = await generateFlowLockInternal(item.folder.replaceAll("/", SEP21), false, workspace, opts, false, true, false, tree);
81093
- const flowResult = result;
81094
- const scriptsInfo = flowResult?.updatedScripts?.length ? colors.dim(colors.white(`: ${flowResult.updatedScripts.join(", ")}`)) : "";
81095
- info(`${formatProgress(current)} flow ${item.path}${scriptsInfo}`);
81940
+ try {
81941
+ const result2 = await generateFlowLockInternal(item.folder.replaceAll("/", SEP21), false, workspace, opts, false, true, false, tree);
81942
+ const flowResult = result2;
81943
+ const scriptsInfo = flowResult?.updatedScripts?.length ? colors.dim(colors.white(`: ${flowResult.updatedScripts.join(", ")}`)) : "";
81944
+ info(`${formatProgress(current)} flow ${item.path}${scriptsInfo}`);
81945
+ } catch (e) {
81946
+ const msg = e instanceof Error ? e.message : String(e);
81947
+ errors.push({ path: item.path, error: msg });
81948
+ info(`${formatProgress(current)} flow ${item.path}`);
81949
+ error(` Failed: ${msg}`);
81950
+ }
81096
81951
  }
81097
81952
  for (const item of apps2) {
81098
81953
  current++;
81099
- const result = await generateAppLocksInternal(item.folder.replaceAll("/", SEP21), item.isRawApp, false, workspace, opts, false, true, false, tree);
81100
- const appResult = result;
81101
- const scriptsInfo = appResult?.updatedScripts?.length ? colors.dim(colors.white(`: ${appResult.updatedScripts.join(", ")}`)) : "";
81102
- info(`${formatProgress(current)} app ${item.path}${scriptsInfo}`);
81954
+ try {
81955
+ const result2 = await generateAppLocksInternal(item.folder.replaceAll("/", SEP21), item.isRawApp, false, workspace, opts, false, true, false, tree);
81956
+ const appResult = result2;
81957
+ const scriptsInfo = appResult?.updatedScripts?.length ? colors.dim(colors.white(`: ${appResult.updatedScripts.join(", ")}`)) : "";
81958
+ info(`${formatProgress(current)} app ${item.path}${scriptsInfo}`);
81959
+ } catch (e) {
81960
+ const msg = e instanceof Error ? e.message : String(e);
81961
+ errors.push({ path: item.path, error: msg });
81962
+ info(`${formatProgress(current)} app ${item.path}`);
81963
+ error(` Failed: ${msg}`);
81964
+ }
81103
81965
  }
81104
81966
  const allStaleDeps = staleItems.filter((i) => i.type === "dependencies");
81105
81967
  await tree.persistDepsHashes(allStaleDeps.map((d) => d.path));
81968
+ const succeeded = total - errors.length;
81106
81969
  info("");
81107
- info(`Done. Updated ${colors.bold(String(total))} item(s).`);
81970
+ if (errors.length > 0) {
81971
+ info(`Done. Updated ${colors.bold(String(succeeded))}/${total} item(s). ${colors.red(String(errors.length) + " failed")}:`);
81972
+ for (const { path: path19, error: error2 } of errors) {
81973
+ error(` ${path19}: ${error2}`);
81974
+ }
81975
+ process.exitCode = 1;
81976
+ } else {
81977
+ info(`Done. Updated ${colors.bold(String(total))} item(s).`);
81978
+ }
81108
81979
  }
81109
- var command29 = new Command().description("Generate metadata (locks, schemas) for all scripts, flows, and apps").arguments("[folder:string]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Show what would be updated without making changes").option("--lock-only", "Re-generate only the lock files").option("--schema-only", "Re-generate only script schemas (skips flows and apps)").option("--skip-scripts", "Skip processing scripts").option("--skip-flows", "Skip processing flows").option("--skip-apps", "Skip processing apps").option("--strict-folder-boundaries", "Only update items inside the specified folder (requires folder argument)").option("-i --includes <patterns:file[]>", "Comma separated patterns to specify which files to include").option("-e --excludes <patterns:file[]>", "Comma separated patterns to specify which files to exclude").action(generateMetadata2);
81110
- var generate_metadata_default = command29;
81980
+ var command33 = new Command().description("Generate metadata (locks, schemas) for all scripts, flows, and apps").arguments("[folder:string]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Show what would be updated without making changes").option("--lock-only", "Re-generate only the lock files").option("--schema-only", "Re-generate only script schemas (skips flows and apps)").option("--skip-scripts", "Skip processing scripts").option("--skip-flows", "Skip processing flows").option("--skip-apps", "Skip processing apps").option("--strict-folder-boundaries", "Only update items inside the specified folder (requires folder argument)").option("-i --includes <patterns:file[]>", "Comma separated patterns to specify which files to include").option("-e --excludes <patterns:file[]>", "Comma separated patterns to specify which files to exclude").action(generateMetadata2);
81981
+ var generate_metadata_default = command33;
81111
81982
 
81112
81983
  // src/commands/docs/docs.ts
81113
81984
  init_mod3();
@@ -81179,8 +82050,8 @@ ${await res.text()}`);
81179
82050
  console.log();
81180
82051
  }
81181
82052
  }
81182
- var command30 = new Command().name("docs").description("Search Windmill documentation. Requires Enterprise Edition.").arguments("<query:string>").option("--json", "Output results as JSON.").action(docs);
81183
- var docs_default = command30;
82053
+ var command34 = new Command().name("docs").description("Search Windmill documentation.").arguments("<query:string>").option("--json", "Output results as JSON.").action(docs);
82054
+ var docs_default = command34;
81184
82055
 
81185
82056
  // src/commands/config/config.ts
81186
82057
  init_mod3();
@@ -81192,13 +82063,13 @@ async function configAction(opts) {
81192
82063
  info(formatConfigReference());
81193
82064
  }
81194
82065
  }
81195
- var command31 = new Command().name("config").description("Show all available wmill.yaml configuration options").option("--json", "Output as JSON for programmatic consumption").action(configAction);
81196
- var config_default = command31;
82066
+ var command35 = new Command().name("config").description("Show all available wmill.yaml configuration options").option("--json", "Output as JSON for programmatic consumption").action(configAction);
82067
+ var config_default = command35;
81197
82068
 
81198
82069
  // src/main.ts
81199
82070
  await init_context();
81200
- var VERSION = "1.667.0";
81201
- var command32 = 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("config", config_default).command("version --version", "Show version information").action(async (opts) => {
82071
+ var VERSION = "1.668.0";
82072
+ var command36 = 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("job", job_default).command("group", group_default).command("audit", audit_default).command("token", token_default).command("generate-metadata", generate_metadata_default).command("docs", docs_default).command("config", config_default).command("version --version", "Show version information").action(async (opts) => {
81202
82073
  console.log("CLI version: " + VERSION);
81203
82074
  try {
81204
82075
  const provider = new NpmProvider({ package: "windmill-cli" });
@@ -81228,20 +82099,20 @@ var command32 = new Command().name("wmill").action(() => info(`Welcome to Windmi
81228
82099
  error(e);
81229
82100
  info("Try running with sudo and otherwise check the result of the command: npm uninstall windmill-cli && npm install -g windmill-cli");
81230
82101
  })).command("completions", new Command().description("Generate shell completions.").command("bash", new Command().description("Generate bash completions.").action(() => {
81231
- process.stdout.write(generateShellCompletions(command32, "bash") + `
82102
+ process.stdout.write(generateShellCompletions(command36, "bash") + `
81232
82103
  `);
81233
82104
  })).command("zsh", new Command().description("Generate zsh completions.").action(() => {
81234
- process.stdout.write(generateShellCompletions(command32, "zsh") + `
82105
+ process.stdout.write(generateShellCompletions(command36, "zsh") + `
81235
82106
  `);
81236
82107
  })).command("fish", new Command().description("Generate fish completions.").action(() => {
81237
- process.stdout.write(generateShellCompletions(command32, "fish") + `
82108
+ process.stdout.write(generateShellCompletions(command36, "fish") + `
81238
82109
  `);
81239
82110
  })));
81240
82111
  async function main2() {
81241
82112
  try {
81242
82113
  const args = process.argv.slice(2);
81243
82114
  if (args.length === 0) {
81244
- command32.showHelp();
82115
+ command36.showHelp();
81245
82116
  }
81246
82117
  const LOG_LEVEL = args.includes("--verbose") || args.includes("--debug") ? "DEBUG" : "INFO";
81247
82118
  setShowDiffs(args.includes("--show-diffs"));
@@ -81251,12 +82122,22 @@ async function main2() {
81251
82122
  if (extraHeaders) {
81252
82123
  OpenAPI.HEADERS = extraHeaders;
81253
82124
  }
81254
- await command32.parse(args);
82125
+ await command36.parse(args);
81255
82126
  } catch (e) {
81256
82127
  if (e && typeof e === "object" && "name" in e && e.name === "ApiError") {
81257
- console.log("Server failed. " + e.statusText + ": " + e.body);
82128
+ const body = e.body;
82129
+ const bodyStr = typeof body === "object" && body !== null ? JSON.stringify(body) : body;
82130
+ error("Server failed. " + e.statusText + ": " + bodyStr);
82131
+ } else if (e instanceof Error) {
82132
+ error(e.message);
82133
+ } else if (e !== undefined && e !== null) {
82134
+ error(String(e));
82135
+ }
82136
+ const isDebug = process.argv.includes("--verbose") || process.argv.includes("--debug");
82137
+ if (isDebug) {
82138
+ throw e;
81258
82139
  }
81259
- throw e;
82140
+ process.exitCode = 1;
81260
82141
  }
81261
82142
  }
81262
82143
  function isMain() {
@@ -81276,13 +82157,14 @@ if (isMain()) {
81276
82157
  process.stdin.destroy();
81277
82158
  });
81278
82159
  }
81279
- var main_default = command32;
82160
+ var main_default = command36;
81280
82161
  export {
81281
82162
  add as workspaceAdd,
81282
82163
  workspace_default as workspace,
81283
82164
  variable_default as variable,
81284
82165
  user_default as user,
81285
82166
  trigger_default as trigger,
82167
+ token_default as token,
81286
82168
  sync_default as sync,
81287
82169
  script_default as script,
81288
82170
  schedule_default as schedule,
@@ -81291,9 +82173,11 @@ export {
81291
82173
  push3 as push,
81292
82174
  pull,
81293
82175
  lint_default as lint,
82176
+ job_default as job,
81294
82177
  instance_default as instance,
81295
82178
  pull2 as hubPull,
81296
82179
  hub_default as hub,
82180
+ group_default as group,
81297
82181
  gitsync_settings_default as gitsyncSettings,
81298
82182
  folder_default as folder,
81299
82183
  flow_default as flow,
@@ -81301,6 +82185,7 @@ export {
81301
82185
  dev_default2 as dev,
81302
82186
  main_default as default,
81303
82187
  config_default as config,
82188
+ audit_default as audit,
81304
82189
  app_default as app,
81305
82190
  WM_FORK_PREFIX,
81306
82191
  VERSION