create-windy 0.6.15 → 0.6.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -33,7 +33,7 @@ var __toESM = (mod, isNodeMode, target) => {
33
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
34
  var __require = import.meta.require;
35
35
 
36
- // ../../node_modules/cli-width/index.js
36
+ // ../../node_modules/.bun/cli-width@4.1.0/node_modules/cli-width/index.js
37
37
  var require_cli_width = __commonJS((exports, module2) => {
38
38
  module2.exports = cliWidth;
39
39
  function normalizeOpts(options) {
@@ -73,7 +73,7 @@ var require_cli_width = __commonJS((exports, module2) => {
73
73
  }
74
74
  });
75
75
 
76
- // ../../node_modules/mute-stream/lib/index.js
76
+ // ../../node_modules/.bun/mute-stream@3.0.0/node_modules/mute-stream/lib/index.js
77
77
  var require_lib = __commonJS((exports, module2) => {
78
78
  var Stream = __require("stream");
79
79
 
@@ -4666,7 +4666,7 @@ function isMissing6(error) {
4666
4666
  import { createInterface as createInterface2 } from "readline/promises";
4667
4667
  import { stdin, stdout } from "process";
4668
4668
 
4669
- // ../../node_modules/@inquirer/core/dist/lib/key.js
4669
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/key.js
4670
4670
  var keybindings = ["emacs", "vim"];
4671
4671
  var keybindingLookup = new Set(keybindings);
4672
4672
  function isKeybinding(value) {
@@ -4683,7 +4683,7 @@ var isDownKey = (key, keybindings2 = []) => key.name === "down" || keybindings2.
4683
4683
  var isSpaceKey = (key) => key.name === "space";
4684
4684
  var isNumberKey = (key) => "1234567890".includes(key.name);
4685
4685
  var isEnterKey = (key) => key.name === "enter" || key.name === "return";
4686
- // ../../node_modules/@inquirer/core/dist/lib/errors.js
4686
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/errors.js
4687
4687
  class AbortPromptError extends Error {
4688
4688
  name = "AbortPromptError";
4689
4689
  message = "Prompt was aborted";
@@ -4709,10 +4709,10 @@ class HookError extends Error {
4709
4709
  class ValidationError extends Error {
4710
4710
  name = "ValidationError";
4711
4711
  }
4712
- // ../../node_modules/@inquirer/core/dist/lib/use-state.js
4712
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-state.js
4713
4713
  import { AsyncResource as AsyncResource2 } from "async_hooks";
4714
4714
 
4715
- // ../../node_modules/@inquirer/core/dist/lib/hook-engine.js
4715
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/hook-engine.js
4716
4716
  import { AsyncLocalStorage, AsyncResource } from "async_hooks";
4717
4717
  var hookStorage = new AsyncLocalStorage;
4718
4718
  function createStore(rl) {
@@ -4817,7 +4817,7 @@ var effectScheduler = {
4817
4817
  }
4818
4818
  };
4819
4819
 
4820
- // ../../node_modules/@inquirer/core/dist/lib/use-state.js
4820
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-state.js
4821
4821
  function isFactory(value) {
4822
4822
  return typeof value === "function";
4823
4823
  }
@@ -4838,7 +4838,7 @@ function useState(defaultValue) {
4838
4838
  });
4839
4839
  }
4840
4840
 
4841
- // ../../node_modules/@inquirer/core/dist/lib/use-effect.js
4841
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-effect.js
4842
4842
  function useEffect(cb, depArray) {
4843
4843
  withPointer((pointer) => {
4844
4844
  const oldDeps = pointer.get();
@@ -4850,10 +4850,10 @@ function useEffect(cb, depArray) {
4850
4850
  });
4851
4851
  }
4852
4852
 
4853
- // ../../node_modules/@inquirer/core/dist/lib/theme.js
4853
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/theme.js
4854
4854
  import { styleText } from "util";
4855
4855
 
4856
- // ../../node_modules/@inquirer/figures/dist/index.js
4856
+ // ../../node_modules/.bun/@inquirer+figures@2.0.7/node_modules/@inquirer/figures/dist/index.js
4857
4857
  import process2 from "process";
4858
4858
  function isUnicodeSupported() {
4859
4859
  if (!process2.platform.startsWith("win")) {
@@ -5142,7 +5142,7 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
5142
5142
  var dist_default = figures;
5143
5143
  var replacements = Object.entries(specialMainSymbols);
5144
5144
 
5145
- // ../../node_modules/@inquirer/core/dist/lib/theme.js
5145
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/theme.js
5146
5146
  var defaultTheme = {
5147
5147
  prefix: {
5148
5148
  idle: styleText("blue", "?"),
@@ -5170,7 +5170,7 @@ function getDefaultTheme() {
5170
5170
  };
5171
5171
  }
5172
5172
 
5173
- // ../../node_modules/@inquirer/core/dist/lib/make-theme.js
5173
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/make-theme.js
5174
5174
  function isPlainObject(value) {
5175
5175
  if (typeof value !== "object" || value === null)
5176
5176
  return false;
@@ -5198,7 +5198,7 @@ function makeTheme(...themes) {
5198
5198
  return deepMerge(...themesToMerge);
5199
5199
  }
5200
5200
 
5201
- // ../../node_modules/@inquirer/core/dist/lib/use-prefix.js
5201
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-prefix.js
5202
5202
  function usePrefix({ status = "idle", theme }) {
5203
5203
  const [showLoader, setShowLoader] = useState(false);
5204
5204
  const [tick, setTick] = useState(0);
@@ -5228,7 +5228,7 @@ function usePrefix({ status = "idle", theme }) {
5228
5228
  const iconName = status === "loading" ? "idle" : status;
5229
5229
  return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
5230
5230
  }
5231
- // ../../node_modules/@inquirer/core/dist/lib/use-memo.js
5231
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-memo.js
5232
5232
  function useMemo(fn, dependencies) {
5233
5233
  return withPointer((pointer) => {
5234
5234
  const prev = pointer.get();
@@ -5240,12 +5240,12 @@ function useMemo(fn, dependencies) {
5240
5240
  return prev.value;
5241
5241
  });
5242
5242
  }
5243
- // ../../node_modules/@inquirer/core/dist/lib/use-ref.js
5243
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-ref.js
5244
5244
  function useRef(val) {
5245
5245
  return useState({ current: val })[0];
5246
5246
  }
5247
5247
 
5248
- // ../../node_modules/@inquirer/core/dist/lib/use-keypress.js
5248
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-keypress.js
5249
5249
  function useKeypress(userHandler) {
5250
5250
  const signal = useRef(userHandler);
5251
5251
  signal.current = userHandler;
@@ -5263,10 +5263,10 @@ function useKeypress(userHandler) {
5263
5263
  };
5264
5264
  }, []);
5265
5265
  }
5266
- // ../../node_modules/@inquirer/core/dist/lib/utils.js
5266
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/utils.js
5267
5267
  var import_cli_width = __toESM(require_cli_width(), 1);
5268
5268
 
5269
- // ../../node_modules/fast-string-truncated-width/dist/utils.js
5269
+ // ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
5270
5270
  var getCodePointsLength = (() => {
5271
5271
  const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
5272
5272
  return (input) => {
@@ -5285,7 +5285,7 @@ var isWideNotCJKTNotEmoji = (x) => {
5285
5285
  return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
5286
5286
  };
5287
5287
 
5288
- // ../../node_modules/fast-string-truncated-width/dist/index.js
5288
+ // ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
5289
5289
  var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
5290
5290
  var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
5291
5291
  var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
@@ -5384,7 +5384,7 @@ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {})
5384
5384
  };
5385
5385
  var dist_default2 = getStringTruncatedWidth;
5386
5386
 
5387
- // ../../node_modules/fast-string-width/dist/index.js
5387
+ // ../../node_modules/.bun/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
5388
5388
  var NO_TRUNCATION2 = {
5389
5389
  limit: Infinity,
5390
5390
  ellipsis: "",
@@ -5395,7 +5395,7 @@ var fastStringWidth = (input, options = {}) => {
5395
5395
  };
5396
5396
  var dist_default3 = fastStringWidth;
5397
5397
 
5398
- // ../../node_modules/fast-wrap-ansi/lib/main.js
5398
+ // ../../node_modules/.bun/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
5399
5399
  var ESC = "\x1B";
5400
5400
  var CSI = "\x9B";
5401
5401
  var END_CODE = 39;
@@ -5607,7 +5607,7 @@ function wrapAnsi(string, columns, options) {
5607
5607
  `);
5608
5608
  }
5609
5609
 
5610
- // ../../node_modules/@inquirer/core/dist/lib/utils.js
5610
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/utils.js
5611
5611
  function breakLines(content, width) {
5612
5612
  return content.split(`
5613
5613
  `).flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split(`
@@ -5618,7 +5618,7 @@ function readlineWidth() {
5618
5618
  return import_cli_width.default({ defaultWidth: 80, output: readline().output });
5619
5619
  }
5620
5620
 
5621
- // ../../node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
5621
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
5622
5622
  function usePointerPosition({ active, renderedItems, pageSize, loop }) {
5623
5623
  const state = useRef({
5624
5624
  lastPointer: active,
@@ -5684,12 +5684,12 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
5684
5684
  return pageBuffer.filter((line) => typeof line === "string").join(`
5685
5685
  `);
5686
5686
  }
5687
- // ../../node_modules/@inquirer/core/dist/lib/create-prompt.js
5687
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/create-prompt.js
5688
5688
  var import_mute_stream = __toESM(require_lib(), 1);
5689
5689
  import * as readline2 from "readline";
5690
5690
  import { AsyncResource as AsyncResource3 } from "async_hooks";
5691
5691
 
5692
- // ../../node_modules/signal-exit/dist/mjs/signals.js
5692
+ // ../../node_modules/.bun/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js
5693
5693
  var signals = [];
5694
5694
  signals.push("SIGHUP", "SIGINT", "SIGTERM");
5695
5695
  if (process.platform !== "win32") {
@@ -5699,7 +5699,7 @@ if (process.platform === "linux") {
5699
5699
  signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
5700
5700
  }
5701
5701
 
5702
- // ../../node_modules/signal-exit/dist/mjs/index.js
5702
+ // ../../node_modules/.bun/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
5703
5703
  var processOk = (process3) => !!process3 && typeof process3 === "object" && typeof process3.removeListener === "function" && typeof process3.emit === "function" && typeof process3.reallyExit === "function" && typeof process3.listeners === "function" && typeof process3.kill === "function" && typeof process3.pid === "number" && typeof process3.on === "function";
5704
5704
  var kExitEmitter = Symbol.for("signal-exit emitter");
5705
5705
  var global = globalThis;
@@ -5897,10 +5897,10 @@ var {
5897
5897
  unload
5898
5898
  } = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback);
5899
5899
 
5900
- // ../../node_modules/@inquirer/core/dist/lib/screen-manager.js
5900
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/screen-manager.js
5901
5901
  import { stripVTControlCharacters } from "util";
5902
5902
 
5903
- // ../../node_modules/@inquirer/ansi/dist/index.js
5903
+ // ../../node_modules/.bun/@inquirer+ansi@2.0.7/node_modules/@inquirer/ansi/dist/index.js
5904
5904
  var ESC2 = "\x1B[";
5905
5905
  var cursorLeft = ESC2 + "G";
5906
5906
  var cursorHide = ESC2 + "?25l";
@@ -5916,7 +5916,7 @@ var cursorTo = (x, y) => {
5916
5916
  var eraseLine = ESC2 + "2K";
5917
5917
  var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
5918
5918
 
5919
- // ../../node_modules/@inquirer/core/dist/lib/screen-manager.js
5919
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/screen-manager.js
5920
5920
  var height = (content) => content.split(`
5921
5921
  `).length;
5922
5922
  var lastLine = (content) => content.split(`
@@ -5982,7 +5982,7 @@ class ScreenManager {
5982
5982
  }
5983
5983
  }
5984
5984
 
5985
- // ../../node_modules/@inquirer/core/dist/lib/promise-polyfill.js
5985
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/promise-polyfill.js
5986
5986
  class PromisePolyfill extends Promise {
5987
5987
  static withResolver() {
5988
5988
  let resolve6;
@@ -5995,7 +5995,7 @@ class PromisePolyfill extends Promise {
5995
5995
  }
5996
5996
  }
5997
5997
 
5998
- // ../../node_modules/@inquirer/core/dist/lib/create-prompt.js
5998
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/create-prompt.js
5999
5999
  import path from "path";
6000
6000
  var nativeSetImmediate = globalThis.setImmediate;
6001
6001
  function getCallSites() {
@@ -6106,7 +6106,7 @@ function createPrompt(view) {
6106
6106
  };
6107
6107
  return prompt;
6108
6108
  }
6109
- // ../../node_modules/@inquirer/core/dist/lib/Separator.js
6109
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/Separator.js
6110
6110
  import { styleText as styleText2 } from "util";
6111
6111
  class Separator {
6112
6112
  separator = styleText2("dim", Array.from({ length: 15 }).join(dist_default.line));
@@ -6120,7 +6120,7 @@ class Separator {
6120
6120
  return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
6121
6121
  }
6122
6122
  }
6123
- // ../../node_modules/@inquirer/checkbox/dist/index.js
6123
+ // ../../node_modules/.bun/@inquirer+checkbox@5.2.1+7cb241fc07b679d9/node_modules/@inquirer/checkbox/dist/index.js
6124
6124
  import { styleText as styleText3 } from "util";
6125
6125
  var checkboxTheme = {
6126
6126
  icon: {
@@ -7473,11 +7473,14 @@ async function retainTransactionConflicts(root, paths, conflictArtifacts = []) {
7473
7473
  const current = await readTransactionState(root);
7474
7474
  if (!current)
7475
7475
  throw new Error("\u7F3A\u5C11\u53EF\u4FDD\u7559\u7684\u66F4\u65B0\u4E8B\u52A1\u72B6\u6001");
7476
+ const preservePaths = [
7477
+ ...new Set([...current.preservePaths ?? [], ...paths])
7478
+ ].filter((path2) => path2 !== updateStatePath);
7476
7479
  const next = {
7477
7480
  ...current,
7478
- preservePaths: [...new Set([...current.preservePaths ?? [], ...paths])],
7481
+ preservePaths: preservePaths.length ? preservePaths : undefined,
7479
7482
  conflictArtifacts: [
7480
- ...new Map([...current.conflictArtifacts ?? [], ...conflictArtifacts].map((artifact) => [artifact.artifactPath, artifact])).values()
7483
+ ...new Map([...current.conflictArtifacts ?? [], ...conflictArtifacts].filter((artifact) => artifact.path !== updateStatePath).map((artifact) => [artifact.artifactPath, artifact])).values()
7481
7484
  ]
7482
7485
  };
7483
7486
  await publishTransactionState(root, current, next);
@@ -7729,6 +7732,8 @@ async function assertRestoredEntries(root, state, backups) {
7729
7732
  async function unresolvedPreservePaths(root, backupPath, state) {
7730
7733
  const unresolved = [];
7731
7734
  for (const path2 of state.preservePaths ?? []) {
7735
+ if (path2 === updateStatePath)
7736
+ continue;
7732
7737
  const entry = state.entries.find((candidate) => candidate.path === path2);
7733
7738
  if (!entry) {
7734
7739
  unresolved.push(path2);
@@ -8472,6 +8477,11 @@ var recipes = [
8472
8477
  id: "starter-0.6.14-to-0.6.15",
8473
8478
  from: "0.6.14",
8474
8479
  to: "0.6.15"
8480
+ },
8481
+ {
8482
+ id: "starter-0.6.15-to-0.6.16",
8483
+ from: "0.6.15",
8484
+ to: "0.6.16"
8475
8485
  }
8476
8486
  ];
8477
8487
  function resolveRecipeChain(sourceVersion, targetVersion) {
@@ -11461,7 +11471,7 @@ function assertKnownModuleArguments(args) {
11461
11471
 
11462
11472
  // src/module-lifecycle-confirmation.ts
11463
11473
  import { createInterface as createInterface3 } from "readline/promises";
11464
- async function confirmModuleMutation(args, dependencies, log) {
11474
+ async function confirmModuleMutation(args, dependencies, log, message = "\u786E\u8BA4\u6267\u884C\u4EE5\u4E0A\u6A21\u5757\u8BA1\u5212\uFF1F") {
11465
11475
  if (args.includes("--yes"))
11466
11476
  return true;
11467
11477
  const isTTY = dependencies.isTTY ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
@@ -11469,7 +11479,7 @@ async function confirmModuleMutation(args, dependencies, log) {
11469
11479
  throw new Error("\u975E\u4EA4\u4E92\u73AF\u5883\u6B63\u5F0F\u53D8\u66F4\u5FC5\u987B\u4F20\u5165 --yes");
11470
11480
  }
11471
11481
  const confirm = dependencies.confirm ?? promptForConfirmation;
11472
- const accepted = await confirm("\u786E\u8BA4\u6267\u884C\u4EE5\u4E0A\u6A21\u5757\u8BA1\u5212\uFF1F");
11482
+ const accepted = await confirm(message);
11473
11483
  if (!accepted)
11474
11484
  log("\u5DF2\u53D6\u6D88\uFF1A\u9879\u76EE\u672A\u88AB\u4FEE\u6539");
11475
11485
  return accepted;
@@ -12180,6 +12190,750 @@ function readValue4(args, flag) {
12180
12190
  return index >= 0 ? args[index + 1] : undefined;
12181
12191
  }
12182
12192
 
12193
+ // src/package-command.ts
12194
+ import { resolve as resolve14 } from "path";
12195
+
12196
+ // src/package-configuration.ts
12197
+ import { createHash as createHash5 } from "crypto";
12198
+ import { readFile as readFile27 } from "fs/promises";
12199
+ import { isAbsolute as isAbsolute3, normalize, relative as relative8, resolve as resolve11, sep as sep6 } from "path";
12200
+
12201
+ // src/package-types.ts
12202
+ var packagePlatforms = ["linux/amd64", "linux/arm64"];
12203
+
12204
+ // src/package-configuration.ts
12205
+ var configurationFile = "windy.build.json";
12206
+ var shellCharacters = /[;&|`><\r\n$()'"]/u;
12207
+ var placeholder = /\$\{(platform|output\.directory|input\.([a-z][a-z0-9-]*))\}/gu;
12208
+ var secretName = /secret|token|password|credential|private[-_]?key|api[-_]?key/iu;
12209
+ var shellExecutables = new Set([
12210
+ "sh",
12211
+ "bash",
12212
+ "zsh",
12213
+ "fish",
12214
+ "cmd",
12215
+ "powershell",
12216
+ "pwsh"
12217
+ ]);
12218
+ async function readPackageConfiguration(projectDirectory) {
12219
+ const path2 = resolve11(projectDirectory, configurationFile);
12220
+ let source;
12221
+ try {
12222
+ source = await readFile27(path2, "utf8");
12223
+ } catch (error) {
12224
+ if (error.code === "ENOENT") {
12225
+ throw new Error("\u672A\u58F0\u660E\u6253\u5305\u9002\u914D\u5668\uFF1A\u9879\u76EE\u6839\u76EE\u5F55\u7F3A\u5C11 windy.build.json", {
12226
+ cause: error
12227
+ });
12228
+ }
12229
+ throw error;
12230
+ }
12231
+ try {
12232
+ const configuration = parsePackageConfiguration(JSON.parse(source));
12233
+ return { configuration, digest: sha256(canonicalJson(configuration)) };
12234
+ } catch (error) {
12235
+ if (error instanceof SyntaxError)
12236
+ throw new Error("windy.build.json \u4E0D\u662F\u6709\u6548 JSON", { cause: error });
12237
+ throw error;
12238
+ }
12239
+ }
12240
+ function parsePackageConfiguration(value) {
12241
+ const root = object(value, "windy.build.json");
12242
+ rejectUnknown(root, ["schemaVersion", "product", "platforms", "profiles"], "windy.build.json");
12243
+ if (root.schemaVersion !== 1)
12244
+ throw new Error("windy.build.json \u53EA\u652F\u6301 schemaVersion: 1");
12245
+ const platforms = array(root.platforms, "platforms").map((item) => {
12246
+ const platform = string(item, "platforms[]");
12247
+ if (!packagePlatforms.includes(platform)) {
12248
+ throw new Error(`\u4E0D\u652F\u6301\u7684\u76EE\u6807\u5E73\u53F0\uFF1A${platform}`);
12249
+ }
12250
+ return platform;
12251
+ });
12252
+ unique2(platforms, "platforms");
12253
+ if (!platforms.length)
12254
+ throw new Error("platforms \u4E0D\u80FD\u4E3A\u7A7A");
12255
+ const profiles = array(root.profiles, "profiles").map(parseProfile);
12256
+ unique2(profiles.map(({ key }) => key), "profile key");
12257
+ if (!profiles.length)
12258
+ throw new Error("profiles \u4E0D\u80FD\u4E3A\u7A7A");
12259
+ return {
12260
+ schemaVersion: 1,
12261
+ product: string(root.product, "product"),
12262
+ platforms,
12263
+ profiles
12264
+ };
12265
+ }
12266
+ function parseProfile(value) {
12267
+ const profile = object(value, "profile");
12268
+ rejectUnknown(profile, [
12269
+ "key",
12270
+ "label",
12271
+ "description",
12272
+ "inputs",
12273
+ "command",
12274
+ "output",
12275
+ "requirements"
12276
+ ], "profile");
12277
+ const key = identifier(profile.key, "profile key");
12278
+ const inputs = array(profile.inputs, `profile ${key}.inputs`).map((item) => parseInput(item, key));
12279
+ unique2(inputs.map(({ key: inputKey }) => inputKey), `profile ${key} input key`);
12280
+ const command = object(profile.command, `profile ${key}.command`);
12281
+ rejectUnknown(command, ["executable", "arguments"], `profile ${key}.command`);
12282
+ const executable = string(command.executable, `profile ${key}.command.executable`);
12283
+ if (shellExecutables.has(executable.toLowerCase()) || shellCharacters.test(executable) || !/^[a-zA-Z0-9._-]+$/u.test(executable)) {
12284
+ throw new Error(`profile ${key} \u7684 command.executable \u5FC5\u987B\u662F PATH \u4E2D\u7684\u5B89\u5168\u7A0B\u5E8F\u540D`);
12285
+ }
12286
+ const commandArguments = array(command.arguments, `profile ${key}.command.arguments`).map((item) => {
12287
+ const argument = string(item, `profile ${key}.command.arguments[]`);
12288
+ validatePlaceholders(argument, inputs, key);
12289
+ if (shellCharacters.test(argument.replace(placeholder, ""))) {
12290
+ throw new Error(`profile ${key} \u7684 command.arguments \u4E0D\u5141\u8BB8 Shell \u5B57\u7B26\u4E32`);
12291
+ }
12292
+ return argument;
12293
+ });
12294
+ const output = object(profile.output, `profile ${key}.output`);
12295
+ rejectUnknown(output, ["directory", "artifactSuffix"], `profile ${key}.output`);
12296
+ const directory = string(output.directory, `profile ${key}.output.directory`);
12297
+ if (!isSafeRelativePath(directory) || !/^[a-zA-Z0-9._/-]+$/u.test(directory))
12298
+ throw new Error(`profile ${key} \u7684 output.directory \u8D8A\u51FA\u9879\u76EE\u8FB9\u754C`);
12299
+ const artifactSuffix = string(output.artifactSuffix, `profile ${key}.output.artifactSuffix`);
12300
+ if (!artifactSuffix.startsWith(".") || shellCharacters.test(artifactSuffix) || !/^\.[a-zA-Z0-9._-]+$/u.test(artifactSuffix)) {
12301
+ throw new Error(`profile ${key} \u7684 output.artifactSuffix \u975E\u6CD5`);
12302
+ }
12303
+ const requirements = object(profile.requirements, `profile ${key}.requirements`);
12304
+ rejectUnknown(requirements, ["docker", "buildx"], `profile ${key}.requirements`);
12305
+ const docker = boolean(requirements.docker, `profile ${key}.requirements.docker`);
12306
+ const buildx = boolean(requirements.buildx, `profile ${key}.requirements.buildx`);
12307
+ if (buildx && !docker)
12308
+ throw new Error(`profile ${key} \u7684 buildx \u9700\u8981 docker`);
12309
+ return {
12310
+ key,
12311
+ label: string(profile.label, `profile ${key}.label`),
12312
+ description: string(profile.description, `profile ${key}.description`),
12313
+ inputs,
12314
+ command: { executable, arguments: commandArguments },
12315
+ output: { directory, artifactSuffix },
12316
+ requirements: { docker, buildx }
12317
+ };
12318
+ }
12319
+ function parseInput(value, profile) {
12320
+ const input = object(value, `profile ${profile}.input`);
12321
+ rejectUnknown(input, ["key", "label", "required", "pattern"], `profile ${profile}.input`);
12322
+ const key = identifier(input.key, `profile ${profile}.input.key`);
12323
+ if (secretName.test(key))
12324
+ throw new Error(`profile ${profile} \u4E0D\u5141\u8BB8 secret \u8F93\u5165\uFF1A${key}`);
12325
+ const pattern = input.pattern === undefined ? undefined : string(input.pattern, `profile ${profile}.input.pattern`);
12326
+ if (pattern) {
12327
+ try {
12328
+ new RegExp(pattern, "u");
12329
+ } catch {
12330
+ throw new Error(`profile ${profile} \u7684\u8F93\u5165 pattern \u975E\u6CD5`);
12331
+ }
12332
+ }
12333
+ return {
12334
+ key,
12335
+ label: string(input.label, `profile ${profile}.input.label`),
12336
+ required: boolean(input.required, `profile ${profile}.input.required`),
12337
+ pattern
12338
+ };
12339
+ }
12340
+ function validatePlaceholders(value, inputs, profile) {
12341
+ const tokens = [...value.matchAll(placeholder)];
12342
+ for (const token of tokens) {
12343
+ const inputKey = token[2];
12344
+ if (inputKey && !inputs.some(({ key }) => key === inputKey)) {
12345
+ throw new Error(`profile ${profile} \u4F7F\u7528\u672A\u58F0\u660E\u5360\u4F4D\u7B26\uFF1Ainput.${inputKey}`);
12346
+ }
12347
+ }
12348
+ if (value.replace(placeholder, "").includes("${"))
12349
+ throw new Error(`profile ${profile} \u5305\u542B\u672A\u58F0\u660E\u5360\u4F4D\u7B26`);
12350
+ }
12351
+ function object(value, label) {
12352
+ if (!value || typeof value !== "object" || Array.isArray(value))
12353
+ throw new Error(`${label} \u5FC5\u987B\u662F\u5BF9\u8C61`);
12354
+ return value;
12355
+ }
12356
+ function array(value, label) {
12357
+ if (!Array.isArray(value))
12358
+ throw new Error(`${label} \u5FC5\u987B\u662F\u6570\u7EC4`);
12359
+ return value;
12360
+ }
12361
+ function string(value, label) {
12362
+ if (typeof value !== "string" || !value.trim())
12363
+ throw new Error(`${label} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
12364
+ return value;
12365
+ }
12366
+ function boolean(value, label) {
12367
+ if (typeof value !== "boolean")
12368
+ throw new Error(`${label} \u5FC5\u987B\u662F\u5E03\u5C14\u503C`);
12369
+ return value;
12370
+ }
12371
+ function identifier(value, label) {
12372
+ const result2 = string(value, label);
12373
+ if (!/^[a-z][a-z0-9-]*$/u.test(result2))
12374
+ throw new Error(`${label} \u5FC5\u987B\u662F\u5C0F\u5199 kebab-case`);
12375
+ return result2;
12376
+ }
12377
+ function unique2(values, label) {
12378
+ if (new Set(values).size !== values.length)
12379
+ throw new Error(`${label} \u4E0D\u80FD\u91CD\u590D`);
12380
+ }
12381
+ function rejectUnknown(source, allowed, label) {
12382
+ for (const key of Object.keys(source))
12383
+ if (!allowed.includes(key))
12384
+ throw new Error(`${label} \u5305\u542B\u672A\u77E5\u5B57\u6BB5\uFF1A${key}`);
12385
+ }
12386
+ function isSafeRelativePath(value) {
12387
+ return Boolean(value) && normalize(value) !== "." && !isAbsolute3(value) && !value.includes("\\") && !relative8(".", resolve11(".", value)).split(sep6).includes("..") && !normalize(value).startsWith("..");
12388
+ }
12389
+ function canonicalJson(value) {
12390
+ if (Array.isArray(value))
12391
+ return `[${value.map(canonicalJson).join(",")}]`;
12392
+ if (value && typeof value === "object")
12393
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
12394
+ return JSON.stringify(value);
12395
+ }
12396
+ function sha256(value) {
12397
+ return createHash5("sha256").update(value).digest("hex");
12398
+ }
12399
+
12400
+ // src/package-execution.ts
12401
+ import { createHash as createHash6 } from "crypto";
12402
+ import { readdir as readdir10, realpath as realpath2, stat as stat3 } from "fs/promises";
12403
+ import { relative as relative9, resolve as resolve12 } from "path";
12404
+ var bunPackageProcess = {
12405
+ async run(command, args, cwd) {
12406
+ const child = Bun.spawn([command, ...args], {
12407
+ cwd,
12408
+ env: withoutParentGitRepository(process.env),
12409
+ stdin: "inherit",
12410
+ stdout: "pipe",
12411
+ stderr: "pipe"
12412
+ });
12413
+ const [stdout2, stderr, code] = await Promise.all([
12414
+ new Response(child.stdout).text(),
12415
+ new Response(child.stderr).text(),
12416
+ child.exited
12417
+ ]);
12418
+ return { code, stdout: stdout2, stderr };
12419
+ }
12420
+ };
12421
+ async function readPackageSource(projectDirectory, process4 = bunPackageProcess, ignoredPaths = []) {
12422
+ const revision = await currentGitRevision(projectDirectory, process4);
12423
+ const status = await assertCommand(process4, "git", ["status", "--porcelain"], projectDirectory, "\u65E0\u6CD5\u8BFB\u53D6 Git \u5DE5\u4F5C\u533A\u72B6\u6001");
12424
+ const root = await realpath2(projectDirectory);
12425
+ const ignored = new Set(ignoredPaths.map((path2) => relative9(root, path2)));
12426
+ const dirty = status.stdout.trim().split(`
12427
+ `).filter(Boolean).filter((line) => !ignored.has(line.slice(3)));
12428
+ if (dirty.length)
12429
+ throw new Error("Git \u5DE5\u4F5C\u533A\u5FC5\u987B\u5E72\u51C0\u624D\u80FD\u51BB\u7ED3\u6216\u6267\u884C\u6253\u5305\u8BA1\u5212");
12430
+ return revision;
12431
+ }
12432
+ async function currentGitRevision(projectDirectory, process4 = bunPackageProcess) {
12433
+ const revision = await assertCommand(process4, "git", ["rev-parse", "HEAD"], projectDirectory, "\u65E0\u6CD5\u8BFB\u53D6 Git SHA");
12434
+ return revision.stdout.trim();
12435
+ }
12436
+ async function preflightPackage(plan, projectDirectory, process4 = bunPackageProcess, ignoredPaths = []) {
12437
+ const sourceRevision = await readPackageSource(projectDirectory, process4, ignoredPaths);
12438
+ if (sourceRevision !== plan.source.revision)
12439
+ throw new Error("\u6267\u884C\u524D\u6E90\u7801 SHA \u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD\u6267\u884C");
12440
+ await assertCommand(process4, "bun", ["--version"], projectDirectory, "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684 Bun");
12441
+ if (!plan.requirements.docker)
12442
+ return;
12443
+ await assertCommand(process4, "docker", ["version", "--format", "{{.Server.Version}}"], projectDirectory, "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684 Docker Server");
12444
+ if (!plan.requirements.buildx)
12445
+ return;
12446
+ const buildx = await assertCommand(process4, "docker", ["buildx", "inspect"], projectDirectory, "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684 Docker Buildx builder");
12447
+ if (!buildx.stdout.includes(plan.platform) && !buildx.stderr.includes(plan.platform)) {
12448
+ throw new Error(`\u5F53\u524D Buildx builder \u4E0D\u652F\u6301 ${plan.platform}`);
12449
+ }
12450
+ }
12451
+ async function executePackagePlan(plan, projectDirectory, process4 = bunPackageProcess, ignoredPaths = []) {
12452
+ const beforeRevision = await readPackageSource(projectDirectory, process4, ignoredPaths);
12453
+ if (beforeRevision !== plan.source.revision)
12454
+ throw new Error("\u6267\u884C\u524D\u6E90\u7801 SHA \u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD\u6267\u884C");
12455
+ const projectRoot = await realpath2(projectDirectory);
12456
+ const outputDirectory = await guardedOutputDirectory(projectDirectory, plan.output.directory, false);
12457
+ const before = new Map((await artifacts(outputDirectory, plan.output.artifactSuffix, projectRoot)).map(({ path: path2, sha256: sha2562 }) => [path2, sha2562]));
12458
+ const command = await process4.run(plan.command.executable, plan.command.arguments, projectDirectory);
12459
+ if (command.code !== 0)
12460
+ return failed(beforeRevision, `\u6784\u5EFA\u547D\u4EE4\u9000\u51FA\u7801 ${command.code}\uFF1A${details(command)}`);
12461
+ const afterRevision = await currentGitRevision(projectDirectory, process4);
12462
+ if (afterRevision !== beforeRevision)
12463
+ return failed(afterRevision, "\u6784\u5EFA\u671F\u95F4\u6E90\u7801 SHA \u53D1\u751F\u6F02\u79FB");
12464
+ const finalOutput = await guardedOutputDirectory(projectDirectory, plan.output.directory, true);
12465
+ const after = await artifacts(finalOutput, plan.output.artifactSuffix, projectRoot);
12466
+ const changed = after.filter((artifact) => before.get(artifact.path) !== artifact.sha256);
12467
+ const sourceDrift = await sourceDriftAfterBuild(process4, projectDirectory, ignoredPaths, changed.map(({ path: path2 }) => path2));
12468
+ if (sourceDrift)
12469
+ return failed(afterRevision, sourceDrift, changed);
12470
+ if (changed.length !== 1)
12471
+ return failed(afterRevision, `\u9884\u671F\u6070\u597D\u4E00\u4E2A\u65B0\u589E\u6216\u53D8\u66F4\u4EA7\u7269\uFF0C\u5B9E\u9645\u53D1\u73B0 ${changed.length} \u4E2A`, changed);
12472
+ return {
12473
+ status: "succeeded",
12474
+ completedAt: new Date().toISOString(),
12475
+ sourceRevision: afterRevision,
12476
+ artifacts: changed
12477
+ };
12478
+ }
12479
+ async function assertCommand(process4, command, args, cwd, message) {
12480
+ const result2 = await process4.run(command, args, cwd);
12481
+ if (result2.code !== 0)
12482
+ throw new Error(`${message}\uFF1A${details(result2)}`);
12483
+ return result2;
12484
+ }
12485
+ async function guardedOutputDirectory(projectDirectory, directory, mustExist) {
12486
+ const root = await realpath2(projectDirectory);
12487
+ const output = resolve12(root, directory);
12488
+ if (!within(root, output))
12489
+ throw new Error("\u8F93\u51FA\u76EE\u5F55\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12490
+ try {
12491
+ const actual = await realpath2(output);
12492
+ if (!within(root, actual))
12493
+ throw new Error("\u8F93\u51FA\u76EE\u5F55\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12494
+ return actual;
12495
+ } catch (error) {
12496
+ if (error instanceof Error && error.message === "\u8F93\u51FA\u76EE\u5F55\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C")
12497
+ throw error;
12498
+ if (mustExist)
12499
+ throw new Error("\u6784\u5EFA\u6CA1\u6709\u4EA7\u751F\u58F0\u660E\u7684\u8F93\u51FA\u76EE\u5F55", { cause: error });
12500
+ return output;
12501
+ }
12502
+ }
12503
+ async function artifacts(directory, suffix, projectDirectory) {
12504
+ try {
12505
+ await stat3(directory);
12506
+ } catch {
12507
+ return [];
12508
+ }
12509
+ const entries = await readdir10(directory, {
12510
+ recursive: true,
12511
+ withFileTypes: true
12512
+ });
12513
+ return await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(suffix)).map(async (entry) => {
12514
+ const path2 = resolve12(directory, entry.parentPath, entry.name);
12515
+ return {
12516
+ path: relative9(projectDirectory, path2),
12517
+ sha256: createHash6("sha256").update(Buffer.from(await Bun.file(path2).arrayBuffer())).digest("hex")
12518
+ };
12519
+ }));
12520
+ }
12521
+ async function sourceDriftAfterBuild(process4, projectDirectory, ignoredPaths, generatedArtifacts) {
12522
+ const status = await process4.run("git", ["status", "--porcelain"], projectDirectory);
12523
+ if (status.code !== 0)
12524
+ return `\u65E0\u6CD5\u68C0\u67E5\u6784\u5EFA\u540E\u7684\u6E90\u7801\u6F02\u79FB\uFF1A${details(status)}`;
12525
+ const root = await realpath2(projectDirectory);
12526
+ const ignored = new Set(ignoredPaths.map((path2) => relative9(root, path2)));
12527
+ const generated = new Set(generatedArtifacts);
12528
+ const drift = status.stdout.trim().split(`
12529
+ `).filter(Boolean).filter((line) => {
12530
+ const path2 = line.slice(3);
12531
+ return !ignored.has(path2) && !(line.startsWith("?? ") && generated.has(path2));
12532
+ });
12533
+ return drift.length ? "\u6784\u5EFA\u671F\u95F4\u6E90\u7801\u5DE5\u4F5C\u533A\u53D1\u751F\u6F02\u79FB" : undefined;
12534
+ }
12535
+ function within(root, path2) {
12536
+ const result2 = relative9(root, path2);
12537
+ return Boolean(result2) && !result2.startsWith("..") && result2 !== "..";
12538
+ }
12539
+ function details(result2) {
12540
+ return (result2.stderr || result2.stdout).trim() || "\u672A\u63D0\u4F9B\u8BCA\u65AD\u4FE1\u606F";
12541
+ }
12542
+ function failed(sourceRevision, diagnostic, artifacts2 = []) {
12543
+ return {
12544
+ status: "failed",
12545
+ completedAt: new Date().toISOString(),
12546
+ sourceRevision,
12547
+ artifacts: artifacts2,
12548
+ diagnostic
12549
+ };
12550
+ }
12551
+
12552
+ // src/package-plan.ts
12553
+ import { readFile as readFile28, realpath as realpath3, writeFile as writeFile15 } from "fs/promises";
12554
+ import { dirname as dirname12, relative as relative10, resolve as resolve13 } from "path";
12555
+ function resolvePackageProfile(configuration, profileKey) {
12556
+ const profile = configuration.profiles.find(({ key }) => key === profileKey);
12557
+ if (!profile)
12558
+ throw new Error(`\u672A\u58F0\u660E\u7684\u6253\u5305 profile\uFF1A${profileKey}`);
12559
+ return profile;
12560
+ }
12561
+ function validatePackageInputs(profile, supplied) {
12562
+ for (const key of Object.keys(supplied)) {
12563
+ if (!profile.inputs.some((input) => input.key === key)) {
12564
+ throw new Error(`profile ${profile.key} \u4E0D\u63A5\u53D7\u8F93\u5165\uFF1A${key}`);
12565
+ }
12566
+ }
12567
+ const validated = {};
12568
+ for (const input of profile.inputs) {
12569
+ const value = supplied[input.key];
12570
+ if (input.required && !value)
12571
+ throw new Error(`profile ${profile.key} \u7F3A\u5C11\u5FC5\u586B\u8F93\u5165\uFF1A${input.key}`);
12572
+ if (value === undefined)
12573
+ continue;
12574
+ if (input.pattern && !new RegExp(input.pattern, "u").test(value)) {
12575
+ throw new Error(`\u8F93\u5165 ${input.key} \u4E0D\u7B26\u5408\u58F0\u660E\u7684\u683C\u5F0F`);
12576
+ }
12577
+ validated[input.key] = value;
12578
+ }
12579
+ return validated;
12580
+ }
12581
+ function createFrozenPackagePlan(input) {
12582
+ const {
12583
+ configuration,
12584
+ configDigest,
12585
+ sourceRevision,
12586
+ profile,
12587
+ platform,
12588
+ inputs
12589
+ } = input;
12590
+ return {
12591
+ schemaVersion: 1,
12592
+ product: configuration.product,
12593
+ configDigest,
12594
+ source: { revision: sourceRevision, clean: true },
12595
+ profile: profile.key,
12596
+ platform,
12597
+ inputs,
12598
+ command: {
12599
+ executable: profile.command.executable,
12600
+ arguments: profile.command.arguments.map((argument) => expand(argument, platform, profile.output.directory, inputs))
12601
+ },
12602
+ output: profile.output,
12603
+ requirements: profile.requirements,
12604
+ createdAt: new Date().toISOString()
12605
+ };
12606
+ }
12607
+ function assertFrozenPlanCurrent(input) {
12608
+ const { plan, configuration, configDigest, sourceRevision } = input;
12609
+ if (plan.product !== configuration.product)
12610
+ throw new Error("\u51BB\u7ED3\u8BA1\u5212\u7684\u4EA7\u54C1\u6807\u8BC6\u4E0E\u5F53\u524D\u9879\u76EE\u4E0D\u4E00\u81F4");
12611
+ if (plan.configDigest !== configDigest)
12612
+ throw new Error("windy.build.json \u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD\u6267\u884C\u51BB\u7ED3\u8BA1\u5212");
12613
+ if (plan.source.revision !== sourceRevision)
12614
+ throw new Error("\u6E90\u7801 SHA \u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD\u6267\u884C\u51BB\u7ED3\u8BA1\u5212");
12615
+ if (!configuration.platforms.includes(plan.platform))
12616
+ throw new Error("\u51BB\u7ED3\u8BA1\u5212\u7684\u76EE\u6807\u5E73\u53F0\u5DF2\u4E0D\u88AB\u5F53\u524D\u914D\u7F6E\u652F\u6301");
12617
+ const profile = resolvePackageProfile(configuration, plan.profile);
12618
+ const inputs = validatePackageInputs(profile, plan.inputs);
12619
+ const expected = createFrozenPackagePlan({
12620
+ configuration,
12621
+ configDigest,
12622
+ sourceRevision,
12623
+ profile,
12624
+ platform: plan.platform,
12625
+ inputs
12626
+ });
12627
+ if (canonicalJson(withoutCreatedAt(expected)) !== canonicalJson(withoutCreatedAt(plan))) {
12628
+ throw new Error("\u51BB\u7ED3\u8BA1\u5212\u4E0E\u5F53\u524D\u6784\u5EFA\u914D\u7F6E\u4E0D\u4E00\u81F4\uFF0C\u62D2\u7EDD\u6267\u884C");
12629
+ }
12630
+ }
12631
+ async function readFrozenPackagePlan(path2) {
12632
+ try {
12633
+ return parseFrozenPackagePlan(JSON.parse(await readFile28(path2, "utf8")));
12634
+ } catch (error) {
12635
+ if (error instanceof Error && error.message.startsWith("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212"))
12636
+ throw error;
12637
+ throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u6709\u6548\u7684\u51BB\u7ED3\u6253\u5305\u8BA1\u5212", { cause: error });
12638
+ }
12639
+ }
12640
+ async function writeFrozenPackagePlan(path2, plan) {
12641
+ await writeFile15(path2, `${JSON.stringify(plan, null, 2)}
12642
+ `, "utf8");
12643
+ }
12644
+ async function resolvePackagePlanPath(projectDirectory, requested) {
12645
+ if (!isSafeRelativePath(requested) || !/^[a-zA-Z0-9._/-]+$/u.test(requested))
12646
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12647
+ const root = await realpath3(projectDirectory);
12648
+ const path2 = resolve13(root, requested);
12649
+ if (relative10(root, path2).startsWith(".."))
12650
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12651
+ let parent;
12652
+ try {
12653
+ parent = await realpath3(dirname12(path2));
12654
+ } catch {
12655
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u7236\u76EE\u5F55\u5FC5\u987B\u5DF2\u5B58\u5728\u4E14\u4F4D\u4E8E\u9879\u76EE\u8FB9\u754C\u5185");
12656
+ }
12657
+ if (!withinOrEqual(root, parent))
12658
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12659
+ try {
12660
+ if (!withinOrEqual(root, await realpath3(path2))) {
12661
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12662
+ }
12663
+ } catch (error) {
12664
+ if (error instanceof Error && error.message === "\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C")
12665
+ throw error;
12666
+ }
12667
+ return path2;
12668
+ }
12669
+ function expand(value, platform, outputDirectory, inputs) {
12670
+ return value.replace(/\$\{(platform|output\.directory|input\.([a-z][a-z0-9-]*))\}/gu, (_, token, inputKey) => {
12671
+ if (token === "platform")
12672
+ return platform;
12673
+ if (token === "output.directory")
12674
+ return outputDirectory;
12675
+ return inputs[inputKey] ?? "";
12676
+ });
12677
+ }
12678
+ function withoutCreatedAt(plan) {
12679
+ const { createdAt: _createdAt, ...rest } = plan;
12680
+ return rest;
12681
+ }
12682
+ function withinOrEqual(root, path2) {
12683
+ const result2 = relative10(root, path2);
12684
+ return !result2 || !result2.startsWith("..") && result2 !== "..";
12685
+ }
12686
+ function parseFrozenPackagePlan(value) {
12687
+ const plan = record(value, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212");
12688
+ rejectUnknown2(plan, [
12689
+ "schemaVersion",
12690
+ "product",
12691
+ "configDigest",
12692
+ "source",
12693
+ "profile",
12694
+ "platform",
12695
+ "inputs",
12696
+ "command",
12697
+ "output",
12698
+ "requirements",
12699
+ "createdAt",
12700
+ "result"
12701
+ ], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212");
12702
+ if (plan.result !== undefined)
12703
+ throw new Error("\u5DF2\u5B8C\u6210\u7684\u6253\u5305\u8BA1\u5212\u4E0D\u80FD\u518D\u6B21\u6267\u884C");
12704
+ const source = record(plan.source, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 source");
12705
+ rejectUnknown2(source, ["revision", "clean"], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 source");
12706
+ const command = record(plan.command, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 command");
12707
+ rejectUnknown2(command, ["executable", "arguments"], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 command");
12708
+ const output = record(plan.output, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 output");
12709
+ rejectUnknown2(output, ["directory", "artifactSuffix"], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 output");
12710
+ const requirements = record(plan.requirements, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 requirements");
12711
+ rejectUnknown2(requirements, ["docker", "buildx"], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 requirements");
12712
+ const inputs = record(plan.inputs, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 inputs");
12713
+ for (const [key, input] of Object.entries(inputs)) {
12714
+ if (!/^[a-z][a-z0-9-]*$/u.test(key) || typeof input !== "string") {
12715
+ throw new Error("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 inputs \u975E\u6CD5");
12716
+ }
12717
+ }
12718
+ const arguments_ = array2(command.arguments, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 command.arguments");
12719
+ if (!arguments_.every((argument) => typeof argument === "string")) {
12720
+ throw new Error("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 command.arguments \u975E\u6CD5");
12721
+ }
12722
+ if (plan.schemaVersion !== 1 || !nonEmptyString(plan.product) || !nonEmptyString(plan.configDigest) || !nonEmptyString(plan.profile) || !nonEmptyString(plan.platform) || !nonEmptyString(plan.createdAt) || !nonEmptyString(source.revision) || source.clean !== true || !nonEmptyString(command.executable) || !nonEmptyString(output.directory) || !nonEmptyString(output.artifactSuffix) || typeof requirements.docker !== "boolean" || typeof requirements.buildx !== "boolean") {
12723
+ throw new Error("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212\u7F3A\u5C11\u5FC5\u8981\u5B57\u6BB5");
12724
+ }
12725
+ return {
12726
+ schemaVersion: 1,
12727
+ product: plan.product,
12728
+ configDigest: plan.configDigest,
12729
+ source: { revision: source.revision, clean: true },
12730
+ profile: plan.profile,
12731
+ platform: plan.platform,
12732
+ inputs,
12733
+ command: { executable: command.executable, arguments: arguments_ },
12734
+ output: {
12735
+ directory: output.directory,
12736
+ artifactSuffix: output.artifactSuffix
12737
+ },
12738
+ requirements: { docker: requirements.docker, buildx: requirements.buildx },
12739
+ createdAt: plan.createdAt
12740
+ };
12741
+ }
12742
+ function record(value, label) {
12743
+ if (!value || typeof value !== "object" || Array.isArray(value))
12744
+ throw new Error(`${label} \u5FC5\u987B\u662F\u5BF9\u8C61`);
12745
+ return value;
12746
+ }
12747
+ function array2(value, label) {
12748
+ if (!Array.isArray(value))
12749
+ throw new Error(`${label} \u5FC5\u987B\u662F\u6570\u7EC4`);
12750
+ return value;
12751
+ }
12752
+ function rejectUnknown2(source, allowed, label) {
12753
+ for (const key of Object.keys(source)) {
12754
+ if (!allowed.includes(key))
12755
+ throw new Error(`${label} \u5305\u542B\u672A\u77E5\u5B57\u6BB5\uFF1A${key}`);
12756
+ }
12757
+ }
12758
+ function nonEmptyString(value) {
12759
+ return typeof value === "string" && Boolean(value.trim());
12760
+ }
12761
+
12762
+ // src/package-command.ts
12763
+ async function runPackageCommand(args, dependencies = {}) {
12764
+ if (args[0] !== "package")
12765
+ return false;
12766
+ const log = dependencies.log ?? console.log;
12767
+ if (args.includes("--help") || args.includes("-h")) {
12768
+ log(packageHelpText);
12769
+ return true;
12770
+ }
12771
+ const options = await parsePackageArguments(args.slice(1), dependencies.cwd ?? process.cwd());
12772
+ const planPath = options.fromPlan ?? options.plan;
12773
+ const config = await readPackageConfiguration(options.projectDirectory);
12774
+ const sourceRevision = await readPackageSource(options.projectDirectory, dependencies.process, planPath ? [planPath] : []);
12775
+ let plan;
12776
+ if (options.fromPlan) {
12777
+ plan = await readFrozenPackagePlan(options.fromPlan);
12778
+ assertFrozenPlanCurrent({
12779
+ plan,
12780
+ configuration: config.configuration,
12781
+ configDigest: config.digest,
12782
+ sourceRevision
12783
+ });
12784
+ } else {
12785
+ const profile = resolvePackageProfile(config.configuration, options.profile);
12786
+ if (!config.configuration.platforms.includes(options.platform))
12787
+ throw new Error(`profile ${profile.key} \u4E0D\u652F\u6301\u76EE\u6807\u5E73\u53F0\uFF1A${options.platform}`);
12788
+ const inputs = validatePackageInputs(profile, options.inputs);
12789
+ plan = createFrozenPackagePlan({
12790
+ configuration: config.configuration,
12791
+ configDigest: config.digest,
12792
+ sourceRevision,
12793
+ profile,
12794
+ platform: options.platform,
12795
+ inputs
12796
+ });
12797
+ if (options.plan)
12798
+ await writeFrozenPackagePlan(options.plan, plan);
12799
+ }
12800
+ printPlan2(plan, log);
12801
+ if (!options.execute)
12802
+ return true;
12803
+ if (!planPath)
12804
+ throw new Error("\u6267\u884C\u6253\u5305\u5FC5\u987B\u63D0\u4F9B --plan <\u6587\u4EF6> \u6216 --from-plan <\u6587\u4EF6>\uFF0C\u7528\u4E8E\u5199\u56DE\u7ED3\u679C");
12805
+ let persisted = false;
12806
+ try {
12807
+ await preflightPackage(plan, options.projectDirectory, dependencies.process, [planPath]);
12808
+ const current = await readPackageConfiguration(options.projectDirectory);
12809
+ const currentSource = await readPackageSource(options.projectDirectory, dependencies.process, [planPath]);
12810
+ assertFrozenPlanCurrent({
12811
+ plan,
12812
+ configuration: current.configuration,
12813
+ configDigest: current.digest,
12814
+ sourceRevision: currentSource
12815
+ });
12816
+ const accepted = await confirmModuleMutation(args, dependencies, log, "\u786E\u8BA4\u6267\u884C\u4EE5\u4E0A\u51BB\u7ED3\u6253\u5305\u8BA1\u5212\uFF1F");
12817
+ if (!accepted)
12818
+ return true;
12819
+ const result2 = await executePackagePlan(plan, options.projectDirectory, dependencies.process, [planPath]);
12820
+ await persistPackageResult(planPath, plan, result2);
12821
+ persisted = true;
12822
+ logResult(result2, log);
12823
+ if (result2.status === "failed")
12824
+ throw new Error(result2.diagnostic);
12825
+ } catch (error) {
12826
+ if (!persisted) {
12827
+ const result2 = failedResult(plan, error);
12828
+ await persistPackageResult(planPath, plan, result2);
12829
+ logResult(result2, log);
12830
+ }
12831
+ throw error;
12832
+ }
12833
+ return true;
12834
+ }
12835
+ async function persistPackageResult(planPath, plan, result2) {
12836
+ await writeFrozenPackagePlan(planPath, { ...plan, result: result2 });
12837
+ }
12838
+ function failedResult(plan, error) {
12839
+ return {
12840
+ status: "failed",
12841
+ completedAt: new Date().toISOString(),
12842
+ sourceRevision: plan.source.revision,
12843
+ artifacts: [],
12844
+ diagnostic: error instanceof Error ? error.message : String(error)
12845
+ };
12846
+ }
12847
+ function logResult(result2, log) {
12848
+ log(result2.status === "succeeded" ? `\u6253\u5305\u5B8C\u6210\uFF1A${result2.artifacts.map(({ path: path2, sha256: sha2562 }) => `${path2} sha256:${sha2562}`).join("\uFF0C")}` : `\u6253\u5305\u5931\u8D25\uFF1A${result2.diagnostic}`);
12849
+ }
12850
+ async function parsePackageArguments(args, workingDirectory) {
12851
+ const allowed = new Set([
12852
+ "--profile",
12853
+ "--platform",
12854
+ "--input",
12855
+ "--plan",
12856
+ "--from-plan",
12857
+ "--execute",
12858
+ "--yes",
12859
+ "--cwd"
12860
+ ]);
12861
+ const values = new Map;
12862
+ for (let index = 0;index < args.length; index += 1) {
12863
+ const argument = args[index];
12864
+ if (!allowed.has(argument))
12865
+ throw new Error(`\u672A\u77E5 package \u53C2\u6570\uFF1A${argument}`);
12866
+ if (argument === "--execute" || argument === "--yes")
12867
+ continue;
12868
+ const value = args[index + 1];
12869
+ if (!value || value.startsWith("--"))
12870
+ throw new Error(`${argument} \u9700\u8981\u4E00\u4E2A\u503C`);
12871
+ values.set(argument, [...values.get(argument) ?? [], value]);
12872
+ index += 1;
12873
+ }
12874
+ const single = (name) => {
12875
+ const entries = values.get(name) ?? [];
12876
+ if (entries.length > 1)
12877
+ throw new Error(`${name} \u4E0D\u80FD\u91CD\u590D`);
12878
+ return entries[0];
12879
+ };
12880
+ const plan = single("--plan");
12881
+ const fromPlan = single("--from-plan");
12882
+ if (plan && fromPlan)
12883
+ throw new Error("--plan \u4E0D\u80FD\u4E0E --from-plan \u540C\u65F6\u4F7F\u7528");
12884
+ const projectDirectory = resolve14(workingDirectory, single("--cwd") ?? ".");
12885
+ const inputEntries = values.get("--input") ?? [];
12886
+ const inputs = {};
12887
+ for (const entry of inputEntries) {
12888
+ const match = /^([a-z][a-z0-9-]*)=(.*)$/u.exec(entry);
12889
+ if (!match)
12890
+ throw new Error("--input \u5FC5\u987B\u4E3A key=value\uFF0C\u4E14 key \u4F7F\u7528\u5C0F\u5199 kebab-case");
12891
+ const [, key, value] = match;
12892
+ if (inputs[key] !== undefined)
12893
+ throw new Error(`--input ${key} \u4E0D\u80FD\u91CD\u590D`);
12894
+ inputs[key] = value;
12895
+ }
12896
+ const profile = single("--profile");
12897
+ const platform = single("--platform");
12898
+ if (fromPlan && (profile || platform || inputEntries.length))
12899
+ throw new Error("--from-plan \u4E0D\u63A5\u53D7 --profile\u3001--platform \u6216 --input");
12900
+ if (!fromPlan && (!profile || !platform))
12901
+ throw new Error("\u65B0\u5EFA\u51BB\u7ED3\u8BA1\u5212\u5FC5\u987B\u540C\u65F6\u63D0\u4F9B --profile \u548C --platform");
12902
+ if (platform && !packagePlatforms.includes(platform))
12903
+ throw new Error(`\u4E0D\u652F\u6301\u7684\u76EE\u6807\u5E73\u53F0\uFF1A${platform}`);
12904
+ return {
12905
+ projectDirectory,
12906
+ profile,
12907
+ platform,
12908
+ inputs,
12909
+ plan: plan ? await resolvePackagePlanPath(projectDirectory, plan) : undefined,
12910
+ fromPlan: fromPlan ? await resolvePackagePlanPath(projectDirectory, fromPlan) : undefined,
12911
+ execute: args.includes("--execute")
12912
+ };
12913
+ }
12914
+ function printPlan2(plan, log) {
12915
+ log("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212\uFF1A");
12916
+ log(` \u4EA7\u54C1\uFF1A${plan.product}`);
12917
+ log(` profile\uFF1A${plan.profile}`);
12918
+ log(` \u5E73\u53F0\uFF1A${plan.platform}`);
12919
+ log(` \u6E90\u7801\uFF1A${plan.source.revision}`);
12920
+ log(` \u547D\u4EE4\uFF1A${[plan.command.executable, ...plan.command.arguments].join(" ")}`);
12921
+ log(` \u8F93\u51FA\uFF1A${plan.output.directory}/*${plan.output.artifactSuffix}`);
12922
+ }
12923
+ var packageHelpText = `\u7528\u6CD5\uFF1Acreate-windy package [\u9009\u9879]
12924
+
12925
+ --profile <key> \u58F0\u660E\u7684\u6253\u5305 profile
12926
+ --platform <platform> linux/amd64 \u6216 linux/arm64
12927
+ --input key=value \u4E3A\u58F0\u660E\u7684\u975E secret \u8F93\u5165\u8D4B\u503C\uFF0C\u53EF\u91CD\u590D\u4F7F\u7528
12928
+ --plan <\u6587\u4EF6> \u4FDD\u5B58\u65B0\u5EFA\u51BB\u7ED3\u8BA1\u5212\uFF08\u9879\u76EE\u76EE\u5F55\u5185\uFF09
12929
+ --from-plan <\u6587\u4EF6> \u8BFB\u53D6\u51BB\u7ED3\u8BA1\u5212\uFF08\u9879\u76EE\u76EE\u5F55\u5185\uFF09
12930
+ --execute \u901A\u8FC7\u9884\u68C0\u5E76\u786E\u8BA4\u540E\u6267\u884C
12931
+ --yes \u975E\u4EA4\u4E92\u6267\u884C\u65F6\u786E\u8BA4\u8BA1\u5212
12932
+ --cwd <\u76EE\u5F55> \u6307\u5B9A\u9879\u76EE\u76EE\u5F55
12933
+
12934
+ \u6253\u5305\u9002\u914D\u5668\u5FC5\u987B\u7531\u9879\u76EE\u6839\u76EE\u5F55\u7684 windy.build.json \u660E\u786E\u58F0\u660E\u3002\u6267\u884C\u5FC5\u987B\u4F7F\u7528 --plan \u6216
12935
+ --from-plan\uFF0C\u4EE5\u4FBF\u628A\u4EA7\u7269 SHA-256 \u4E0E\u6E90\u7801\u6F02\u79FB\u7ED3\u679C\u5199\u56DE\u51BB\u7ED3\u8BA1\u5212\u3002`;
12936
+
12183
12937
  // src/cli.ts
12184
12938
  async function main() {
12185
12939
  const args = process.argv.slice(2);
@@ -12187,6 +12941,8 @@ async function main() {
12187
12941
  return;
12188
12942
  if (await runLifecycleCommand(args))
12189
12943
  return;
12944
+ if (await runPackageCommand(args))
12945
+ return;
12190
12946
  const options = parseArguments(args);
12191
12947
  if (options === "help") {
12192
12948
  console.log(helpText);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-windy",
3
- "version": "0.6.15",
3
+ "version": "0.6.16",
4
4
  "description": "创建单组织、单租户、私有部署优先的 Windy 企业 Dashboard Starter",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "templateCommit": "270df5f3da5ba6512a0f305109d874f2c8bf757e",
4
- "generatorVersion": "0.6.15",
3
+ "templateCommit": "8e1d09815139887e150b7ed51d5b974879b1ec54",
4
+ "generatorVersion": "0.6.16",
5
5
  "modules": [
6
6
  {
7
7
  "name": "system",
@@ -55,7 +55,8 @@ function searchActors() {
55
55
  :key="item.value"
56
56
  size="sm"
57
57
  class="h-8 px-3"
58
- :variant="range === item.value ? 'secondary' : 'ghost'"
58
+ :variant="range === item.value ? 'default' : 'ghost'"
59
+ :aria-pressed="range === item.value"
59
60
  :disabled="disabled"
60
61
  @click="emit('update:range', item.value)"
61
62
  >
@@ -6,6 +6,22 @@ import AiRuntimeFilters from "./AiRuntimeFilters.vue";
6
6
  afterEach(() => document.body.replaceChildren());
7
7
 
8
8
  describe("AI Runtime 操作者筛选", () => {
9
+ test("当前时间范围使用主按钮样式并暴露选中状态", () => {
10
+ const wrapper = mount(AiRuntimeFilters, {
11
+ props: {
12
+ range: "month",
13
+ actors: [],
14
+ },
15
+ });
16
+
17
+ const selectedRange = wrapper.get("button[data-variant='default']");
18
+ const unselectedRange = wrapper.get("button[data-variant='ghost']");
19
+
20
+ expect(selectedRange.text()).toContain("近 30 天");
21
+ expect(selectedRange.attributes("aria-pressed")).toBe("true");
22
+ expect(unselectedRange.attributes("aria-pressed")).toBe("false");
23
+ });
24
+
9
25
  test("按姓名搜索后通过设计系统 Select 选择服务端返回的操作者", async () => {
10
26
  const wrapper = mount(AiRuntimeFilters, {
11
27
  props: {