create-windy 0.3.8 → 0.3.10

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
@@ -2851,8 +2851,22 @@ function isMissing(error) {
2851
2851
  // src/docker-copy-sync.ts
2852
2852
  var webDockerfilePath = "apps/web/Dockerfile";
2853
2853
  var webEntryDirectory = "apps/web";
2854
+ var serverDockerfilePath = "apps/server/Dockerfile";
2855
+ var serverEntryDirectory = "apps/server";
2854
2856
  var depsCopyAnchor = "windy-copy:deps";
2855
2857
  var buildCopyAnchor = "windy-copy:build";
2858
+ var dockerfileCopyTargets = [
2859
+ {
2860
+ dockerfilePath: serverDockerfilePath,
2861
+ entryDirectory: serverEntryDirectory,
2862
+ includeBuildClosure: false
2863
+ },
2864
+ {
2865
+ dockerfilePath: webDockerfilePath,
2866
+ entryDirectory: webEntryDirectory,
2867
+ includeBuildClosure: true
2868
+ }
2869
+ ];
2856
2870
  async function snapshotWorkspacePackages(root, options = {}) {
2857
2871
  const rootContent = await readSafeOptional(root, "package.json");
2858
2872
  if (!rootContent) {
@@ -2885,10 +2899,8 @@ async function snapshotWorkspacePackages(root, options = {}) {
2885
2899
  packages.push({
2886
2900
  name: value.name,
2887
2901
  directory: path.slice(0, -"/package.json".length),
2888
- dependencies: [
2889
- ...Object.keys(value.dependencies ?? {}),
2890
- ...Object.keys(value.devDependencies ?? {})
2891
- ]
2902
+ dependencies: dependencyNames(value),
2903
+ workspaceDependencies: workspaceDependencyNames(value)
2892
2904
  });
2893
2905
  }
2894
2906
  }
@@ -2911,6 +2923,9 @@ function workspaceDependencyClosure(packages, entryDirectory) {
2911
2923
  directoryByName.set(pkg.name, pkg.directory);
2912
2924
  packageByDirectory.set(pkg.directory, pkg);
2913
2925
  }
2926
+ if (!packageByDirectory.has(entryDirectory)) {
2927
+ throw new Error(`Docker \u5165\u53E3\u4E0D\u662F root workspace: ${entryDirectory}`);
2928
+ }
2914
2929
  const visited = new Set([entryDirectory]);
2915
2930
  const queue = [entryDirectory];
2916
2931
  while (queue.length) {
@@ -2924,6 +2939,11 @@ function workspaceDependencyClosure(packages, entryDirectory) {
2924
2939
  queue.push(directory);
2925
2940
  }
2926
2941
  }
2942
+ for (const dependency of current.workspaceDependencies ?? []) {
2943
+ if (!directoryByName.has(dependency)) {
2944
+ throw new Error(`${current.directory} \u5F15\u7528\u672A\u77E5\u6216\u8D8A\u754C workspace dependency: ${dependency}`);
2945
+ }
2946
+ }
2927
2947
  }
2928
2948
  return [...visited].sort((a, b) => a.localeCompare(b));
2929
2949
  }
@@ -2940,15 +2960,16 @@ function rewriteAnchoredSection(source, anchor, lines) {
2940
2960
  return [...all.slice(0, begin + 1), ...lines, ...all.slice(end)].join(`
2941
2961
  `);
2942
2962
  }
2943
- function hasCopyAnchors(source) {
2944
- return source.includes(`# ${depsCopyAnchor} begin`) && source.includes(`# ${buildCopyAnchor} begin`);
2963
+ function hasDockerfileCopyAnchors(source, target) {
2964
+ return source.includes(`# ${depsCopyAnchor} begin`) && source.includes(`# ${depsCopyAnchor} end`) && (!target.includeBuildClosure || source.includes(`# ${buildCopyAnchor} begin`) && source.includes(`# ${buildCopyAnchor} end`));
2945
2965
  }
2946
- function syncWebDockerfileSource(source, workspaceDirectories, buildDirectories) {
2947
- const withDeps = rewriteAnchoredSection(source, depsCopyAnchor, dockerManifestCopyLines(workspaceDirectories));
2948
- return rewriteAnchoredSection(withDeps, buildCopyAnchor, dockerCopyLines(buildDirectories));
2966
+ function syncDockerfileSource(source, target, packages) {
2967
+ const closure = workspaceDependencyClosure(packages, target.entryDirectory);
2968
+ const withDeps = rewriteAnchoredSection(source, depsCopyAnchor, dockerManifestCopyLines(packages.map(({ directory }) => directory)));
2969
+ return target.includeBuildClosure ? rewriteAnchoredSection(withDeps, buildCopyAnchor, dockerCopyLines(closure)) : withDeps;
2949
2970
  }
2950
- async function planWebDockerfileInProject(root, options = {}) {
2951
- const dockerfile = await readSafeOptional(root, webDockerfilePath);
2971
+ async function planDockerfileInProject(root, target, options = {}) {
2972
+ const dockerfile = await readSafeOptional(root, target.dockerfilePath);
2952
2973
  if (!dockerfile) {
2953
2974
  return {
2954
2975
  synced: false,
@@ -2958,27 +2979,27 @@ async function planWebDockerfileInProject(root, options = {}) {
2958
2979
  };
2959
2980
  }
2960
2981
  const source = new TextDecoder().decode(dockerfile);
2961
- if (!hasCopyAnchors(source)) {
2982
+ if (!hasDockerfileCopyAnchors(source, target)) {
2962
2983
  if (!options.requireAnchors) {
2963
2984
  return {
2964
2985
  synced: false,
2965
2986
  changed: false,
2966
- expectations: [expectation(webDockerfilePath, dockerfile)],
2987
+ expectations: [expectation(target.dockerfilePath, dockerfile)],
2967
2988
  membershipExpectations: []
2968
2989
  };
2969
2990
  }
2970
- throw new Error(`${webDockerfilePath} \u7F3A\u5C11 # ${depsCopyAnchor} / # ${buildCopyAnchor} \u951A\u70B9\u6BB5\uFF0C` + `\u8BF7\u5148\u6309\u6700\u65B0\u6A21\u677F\u4E3A deps \u4E0E build \u9636\u6BB5\u7684 COPY \u6BB5\u6DFB\u52A0\u951A\u70B9\u540E\u518D\u540C\u6B65`);
2991
+ throw new Error(`${target.dockerfilePath} \u7F3A\u5C11\u5FC5\u9700\u7684 Docker COPY \u951A\u70B9\u6BB5\uFF0C` + `\u8BF7\u5148\u6309\u6700\u65B0\u6A21\u677F\u8FC1\u79FB\u540E\u518D\u540C\u6B65`);
2971
2992
  }
2972
2993
  const snapshot = await snapshotWorkspacePackages(root);
2973
2994
  await options.afterWorkspaceSnapshot?.();
2974
2995
  const packages = snapshot.packages;
2975
- const next = syncWebDockerfileSource(source, packages.map(({ directory }) => directory), workspaceDependencyClosure(packages, webEntryDirectory));
2996
+ const next = syncDockerfileSource(source, target, packages);
2976
2997
  return {
2977
2998
  synced: true,
2978
2999
  changed: next !== source,
2979
3000
  content: next,
2980
3001
  expectations: [
2981
- expectation(webDockerfilePath, dockerfile),
3002
+ expectation(target.dockerfilePath, dockerfile),
2982
3003
  ...snapshot.expectations
2983
3004
  ],
2984
3005
  membershipExpectations: snapshot.membershipExpectations
@@ -3002,6 +3023,18 @@ function locateAnchoredSection(source, anchor) {
3002
3023
  function parseManifest(content) {
3003
3024
  return JSON.parse(new TextDecoder().decode(content));
3004
3025
  }
3026
+ function dependencyNames(manifest) {
3027
+ return Object.keys({
3028
+ ...manifest.dependencies,
3029
+ ...manifest.devDependencies
3030
+ });
3031
+ }
3032
+ function workspaceDependencyNames(manifest) {
3033
+ return Object.entries({
3034
+ ...manifest.dependencies,
3035
+ ...manifest.devDependencies
3036
+ }).filter(([, range]) => range.startsWith("workspace:")).map(([name]) => name);
3037
+ }
3005
3038
  function expectation(path, content) {
3006
3039
  return content ? { path, hash: hashContent(content) } : { path, hash: undefined };
3007
3040
  }
@@ -3019,11 +3052,13 @@ async function prepareCustomerDockerfiles(root) {
3019
3052
  const source = await readFile5(absolutePath, "utf8");
3020
3053
  await writeFile2(absolutePath, rewriteCustomerDockerfile(source));
3021
3054
  }));
3022
- const webPlan = await planWebDockerfileInProject(root, {
3023
- requireAnchors: true
3024
- });
3025
- if (webPlan.changed && webPlan.content !== undefined) {
3026
- await writeFile2(join6(root, webDockerfilePath), webPlan.content);
3055
+ for (const target of dockerfileCopyTargets) {
3056
+ const plan = await planDockerfileInProject(root, target, {
3057
+ requireAnchors: true
3058
+ });
3059
+ if (plan.changed && plan.content !== undefined) {
3060
+ await writeFile2(join6(root, target.dockerfilePath), plan.content);
3061
+ }
3027
3062
  }
3028
3063
  }
3029
3064
  function rewriteCustomerDockerfile(source) {
@@ -7867,23 +7902,21 @@ import { readFile as readFile17 } from "fs/promises";
7867
7902
  import { dirname as dirname6, join as join22 } from "path";
7868
7903
 
7869
7904
  // src/update/docker-copy-update-plan.ts
7870
- function deriveWebDockerfilePlan(files, snapshots, paths) {
7871
- const dockerPlan = files.find(({ path: path2 }) => path2 === webDockerfilePath);
7872
- if (!dockerPlan || dockerPlan.conflict)
7873
- return;
7874
- const dockerSource = virtualContent(dockerPlan, snapshots);
7875
- const rootPackage = virtualPathContent("package.json", files, snapshots);
7876
- if (!dockerSource || !rootPackage)
7905
+ function deriveDockerfilePlans(files, snapshots, paths, targetWorkspaceManifests) {
7906
+ const rootPackage = virtualPathContent("package.json", files, snapshots, targetWorkspaceManifests);
7907
+ if (!rootPackage)
7877
7908
  return;
7878
7909
  const rootManifest = parsePackage(rootPackage, "package.json");
7879
7910
  const workspacePatterns = rootManifest.workspaces ?? [];
7880
7911
  const packages = [];
7881
- for (const path2 of [...paths].filter((path3) => path3.endsWith("package.json"))) {
7912
+ for (const path2 of [
7913
+ ...new Set([...paths, ...targetWorkspaceManifests.keys()])
7914
+ ].filter((path3) => path3.endsWith("package.json"))) {
7882
7915
  const directory = path2 === "package.json" ? "." : path2.slice(0, -13);
7883
7916
  if (directory !== "." && !workspacePatterns.some((pattern) => matchesWorkspace(pattern, directory))) {
7884
7917
  continue;
7885
7918
  }
7886
- const content = virtualPathContent(path2, files, snapshots);
7919
+ const content = virtualPathContent(path2, files, snapshots, targetWorkspaceManifests);
7887
7920
  if (!content)
7888
7921
  continue;
7889
7922
  const manifest = parsePackage(content, path2);
@@ -7893,20 +7926,32 @@ function deriveWebDockerfilePlan(files, snapshots, paths) {
7893
7926
  dependencies: [
7894
7927
  ...Object.keys(manifest.dependencies ?? {}),
7895
7928
  ...Object.keys(manifest.devDependencies ?? {})
7896
- ]
7929
+ ],
7930
+ workspaceDependencies: Object.entries({
7931
+ ...manifest.dependencies,
7932
+ ...manifest.devDependencies
7933
+ }).filter(([, range]) => range.startsWith("workspace:")).map(([name]) => name)
7897
7934
  });
7898
7935
  }
7899
- const source = new TextDecoder().decode(dockerSource);
7900
- const next = syncWebDockerfileSource(source, packages.filter(({ directory }) => directory !== ".").map(({ directory }) => directory).sort(), workspaceDependencyClosure(packages, webEntryDirectory));
7901
- if (next === source)
7902
- return;
7903
- dockerPlan.action = "update";
7904
- dockerPlan.reason = "\u6309\u4E8B\u52A1\u5B89\u5168 workspace \u89C6\u56FE\u540C\u6B65 Docker COPY \u6E05\u5355";
7905
- dockerPlan.content = new TextEncoder().encode(next);
7936
+ for (const target of dockerfileCopyTargets) {
7937
+ const dockerPlan = files.find(({ path: path2 }) => path2 === target.dockerfilePath);
7938
+ if (!dockerPlan || dockerPlan.conflict)
7939
+ continue;
7940
+ const dockerSource = virtualContent(dockerPlan, snapshots);
7941
+ if (!dockerSource)
7942
+ continue;
7943
+ const source = new TextDecoder().decode(dockerSource);
7944
+ const next = syncDockerfileSource(source, target, packages);
7945
+ if (next === source)
7946
+ continue;
7947
+ dockerPlan.action = "update";
7948
+ dockerPlan.reason = "\u6309\u4E8B\u52A1\u5B89\u5168 workspace \u89C6\u56FE\u540C\u6B65 Docker COPY \u6E05\u5355";
7949
+ dockerPlan.content = new TextEncoder().encode(next);
7950
+ }
7906
7951
  }
7907
- function virtualPathContent(path2, files, snapshots) {
7952
+ function virtualPathContent(path2, files, snapshots, targetWorkspaceManifests) {
7908
7953
  const plan = files.find((item) => item.path === path2);
7909
- return plan ? virtualContent(plan, snapshots) : snapshots.get(path2);
7954
+ return plan ? virtualContent(plan, snapshots) : snapshots.get(path2) ?? targetWorkspaceManifests.get(path2);
7910
7955
  }
7911
7956
  function virtualContent(plan, snapshots) {
7912
7957
  if (plan.action === "delete")
@@ -8772,12 +8817,17 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
8772
8817
  const oursChanged = hashContent(ours) !== source.hash;
8773
8818
  const sourceArtifactHash = artifactHashOf(source);
8774
8819
  const targetChanged = targetChangedSinceBase(sourceArtifactHash, base, theirs);
8775
- if (shouldForcePlatformBaseline({
8820
+ const forceTargetBaseline = shouldForcePlatformBaseline({
8776
8821
  forcePlatformBaseline,
8777
8822
  oursChanged,
8778
8823
  sourceArtifactHash,
8779
8824
  base
8780
- })) {
8825
+ });
8826
+ if (forceTargetBaseline && path2.endsWith("package.json") && base) {
8827
+ const merged = mergePackageJson(base, ours, theirs);
8828
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict2(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
8829
+ }
8830
+ if (forceTargetBaseline) {
8781
8831
  return readyPlannedFile(path2, ownership, "update", "\u5F3A\u5236\u91C7\u7528\u76EE\u6807\u5E73\u53F0\u57FA\u7EBF", expected, theirs);
8782
8832
  }
8783
8833
  if (!oursChanged && !targetChanged) {
@@ -9008,7 +9058,9 @@ var recipes = [
9008
9058
  { id: "starter-0.3.4-to-0.3.5", from: "0.3.4", to: "0.3.5" },
9009
9059
  { id: "starter-0.3.5-to-0.3.6", from: "0.3.5", to: "0.3.6" },
9010
9060
  { id: "starter-0.3.6-to-0.3.7", from: "0.3.6", to: "0.3.7" },
9011
- { id: "starter-0.3.7-to-0.3.8", from: "0.3.7", to: "0.3.8" }
9061
+ { id: "starter-0.3.7-to-0.3.8", from: "0.3.7", to: "0.3.8" },
9062
+ { id: "starter-0.3.8-to-0.3.9", from: "0.3.8", to: "0.3.9" },
9063
+ { id: "starter-0.3.9-to-0.3.10", from: "0.3.9", to: "0.3.10" }
9012
9064
  ];
9013
9065
  function resolveRecipeChain(sourceVersion, targetVersion) {
9014
9066
  if (sourceVersion === targetVersion)
@@ -9106,7 +9158,11 @@ async function createUpdatePlan(request, artifacts) {
9106
9158
  manageGeneratedProjectOwned: request.targetModules !== undefined,
9107
9159
  forcePlatformBaseline: request.forcePlatformBaseline === true
9108
9160
  });
9109
- deriveWebDockerfilePlan(files, projectSnapshots, new Set([...paths, ...workspaceSnapshot.manifests.keys()]));
9161
+ deriveDockerfilePlans(files, projectSnapshots, new Set([
9162
+ ...paths,
9163
+ ...workspaceSnapshot.manifests.keys(),
9164
+ ...targetWorkspaceSnapshot.manifests.keys()
9165
+ ]), targetWorkspaceSnapshot.manifests);
9110
9166
  for (const file of files) {
9111
9167
  file.expectedProjectMode = projectModes.get(file.path);
9112
9168
  if (file.action === "create" || file.action === "update") {
@@ -10235,13 +10291,27 @@ class DefaultStarterUpdater {
10235
10291
  const steps = [];
10236
10292
  let verificationExpectationsFrozen = false;
10237
10293
  try {
10238
- const dockerSync = await planWebDockerfileInProject(result2.plan.projectDirectory, { requireAnchors: true });
10239
- if (dockerSync.changed) {
10240
- throw new TransactionCasError("Web Dockerfile COPY \u6E05\u5355\u672A\u5728\u66F4\u65B0\u8BA1\u5212\u4E2D\u540C\u6B65", "apps/web/Dockerfile");
10294
+ const dockerSync = await Promise.all(dockerfileCopyTargets.map((target) => planDockerfileInProject(result2.plan.projectDirectory, target, {
10295
+ requireAnchors: true
10296
+ }).then((sync) => ({ target, sync }))));
10297
+ const staleDockerfile = dockerSync.find(({ sync }) => sync.changed);
10298
+ if (staleDockerfile) {
10299
+ const plannedDockerfile = result2.plan.files.find(({ path: path2 }) => path2 === staleDockerfile.target.dockerfilePath);
10300
+ if (plannedDockerfile && plannedDockerfile.action !== "preserve" && staleDockerfile.sync.content !== undefined) {
10301
+ const content = new TextEncoder().encode(staleDockerfile.sync.content);
10302
+ await writeOwnedTransactionFile(result2.plan.projectDirectory, plannedDockerfile.path, content, expectedForPath(result2, plannedDockerfile.path));
10303
+ plannedDockerfile.action = "update";
10304
+ plannedDockerfile.content = content;
10305
+ replaceExpectations(result2, [
10306
+ expectationForContent(plannedDockerfile.path, content)
10307
+ ]);
10308
+ } else {
10309
+ throw new TransactionCasError("Dockerfile COPY \u6E05\u5355\u672A\u5728\u66F4\u65B0\u8BA1\u5212\u4E2D\u540C\u6B65", staleDockerfile.target.dockerfilePath);
10310
+ }
10241
10311
  }
10242
10312
  steps.push({
10243
- name: "\u540C\u6B65 Web Dockerfile workspace COPY \u6E05\u5355",
10244
- status: dockerSync.synced ? "passed" : "skipped"
10313
+ name: "\u540C\u6B65 Server \u4E0E Web Dockerfile workspace COPY \u6E05\u5355",
10314
+ status: dockerSync.every(({ sync }) => sync.synced) ? "passed" : "skipped"
10245
10315
  });
10246
10316
  await this.#execute("bun", ["install", "--force"], result2.plan.projectDirectory);
10247
10317
  steps.push({ name: "bun install --force", status: "passed" });
@@ -10644,36 +10714,43 @@ async function runLifecycleCommand(args) {
10644
10714
  return true;
10645
10715
  }
10646
10716
  if (command === "sync-docker") {
10647
- const result2 = await planWebDockerfileInProject(projectDirectory, {
10648
- requireAnchors: true
10649
- });
10650
- if (!result2.synced) {
10651
- throw new Error("\u9879\u76EE\u7F3A\u5C11 apps/web/Dockerfile\uFF0C\u65E0\u6CD5\u540C\u6B65 COPY \u6E05\u5355");
10717
+ if (args.includes("--help") || args.includes("-h")) {
10718
+ console.log("\u7528\u6CD5\uFF1Acreate-windy sync-docker [--cwd <project-directory>]");
10719
+ return true;
10652
10720
  }
10653
- if (result2.changed && result2.content !== undefined) {
10654
- await assertWorkspaceMembership(projectDirectory, result2.membershipExpectations);
10721
+ const plans = await Promise.all(dockerfileCopyTargets.map((target) => planDockerfileInProject(projectDirectory, target, {
10722
+ requireAnchors: true
10723
+ }).then((result2) => ({ target, result: result2 }))));
10724
+ if (plans.some(({ result: result2 }) => !result2.synced)) {
10725
+ throw new Error("\u9879\u76EE\u7F3A\u5C11\u53D7\u652F\u6301\u7684 Dockerfile\uFF0C\u65E0\u6CD5\u540C\u6B65 COPY \u6E05\u5355");
10726
+ }
10727
+ const changed = plans.filter(({ result: result2 }) => result2.changed && result2.content !== undefined);
10728
+ if (changed.length) {
10729
+ const membershipExpectations = plans.flatMap(({ result: result2 }) => result2.membershipExpectations);
10730
+ await assertWorkspaceMembership(projectDirectory, membershipExpectations);
10655
10731
  const state = await applyMetadataTransaction({
10656
10732
  id: `sync-docker-${Date.now()}`,
10657
10733
  projectDirectory,
10658
- guards: result2.expectations,
10659
- writes: [{ path: "apps/web/Dockerfile", content: result2.content }]
10734
+ guards: plans.flatMap(({ result: result2 }) => result2.expectations),
10735
+ writes: changed.map(({ target, result: result2 }) => ({
10736
+ path: target.dockerfilePath,
10737
+ content: result2.content
10738
+ }))
10660
10739
  });
10661
10740
  await finalizeOwnedTransaction({
10662
10741
  projectDirectory,
10663
10742
  ownerToken: state.ownerToken,
10664
- expectations: [
10665
- {
10666
- path: "apps/web/Dockerfile",
10667
- expected: {
10668
- kind: "hash",
10669
- value: hashContent(result2.content)
10670
- }
10743
+ expectations: changed.map(({ target, result: result2 }) => ({
10744
+ path: target.dockerfilePath,
10745
+ expected: {
10746
+ kind: "hash",
10747
+ value: hashContent(result2.content)
10671
10748
  }
10672
- ],
10673
- workspaceMembershipExpectations: result2.membershipExpectations
10749
+ })),
10750
+ workspaceMembershipExpectations: membershipExpectations
10674
10751
  });
10675
10752
  }
10676
- console.log(result2.changed ? "\u5DF2\u540C\u6B65 apps/web/Dockerfile workspace COPY \u6E05\u5355" : "apps/web/Dockerfile workspace COPY \u6E05\u5355\u5DF2\u662F\u6700\u65B0");
10753
+ console.log(changed.length ? "\u5DF2\u540C\u6B65 Server \u4E0E Web Dockerfile workspace COPY \u6E05\u5355" : "Server \u4E0E Web Dockerfile workspace COPY \u6E05\u5355\u5DF2\u662F\u6700\u65B0");
10677
10754
  return true;
10678
10755
  }
10679
10756
  if (command === "doctor") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-windy",
3
- "version": "0.3.8",
3
+ "version": "0.3.10",
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": "25260c844c95d14d4ac3ccae6e7553dbde2fd9c6",
4
- "generatorVersion": "0.3.8",
3
+ "templateCommit": "3bbd8ca1fcd1fca58daeba2e800510e42db191b0",
4
+ "generatorVersion": "0.3.10",
5
5
  "modules": [
6
6
  {
7
7
  "name": "system",
@@ -4,10 +4,11 @@ FROM oven/bun:1.3.14-alpine AS deps
4
4
  WORKDIR /app
5
5
 
6
6
  COPY package.json bun.lock ./
7
- COPY apps/server/package.json apps/server/package.json
8
- COPY apps/web/package.json apps/web/package.json
7
+ # windy-copy:deps begin
9
8
  COPY apps/license/package.json apps/license/package.json
9
+ COPY apps/server/package.json apps/server/package.json
10
10
  COPY apps/signing-service/package.json apps/signing-service/package.json
11
+ COPY apps/web/package.json apps/web/package.json
11
12
  COPY packages/ai-client/package.json packages/ai-client/package.json
12
13
  COPY packages/config/package.json packages/config/package.json
13
14
  COPY packages/create-windy/package.json packages/create-windy/package.json
@@ -20,6 +21,7 @@ COPY packages/modules/package.json packages/modules/package.json
20
21
  COPY packages/server-sdk/package.json packages/server-sdk/package.json
21
22
  COPY packages/shared/package.json packages/shared/package.json
22
23
  COPY packages/storage/package.json packages/storage/package.json
24
+ # windy-copy:deps end
23
25
  RUN bun install --frozen-lockfile
24
26
 
25
27
  FROM deps AS runner
@@ -51,6 +51,8 @@
51
51
  "ops:release": "bun run scripts/production-release.ts",
52
52
  "test:merge": "bun run scripts/merge-gate.ts",
53
53
  "release:verify": "bun run scripts/release-verify.ts",
54
+ "release:candidate": "bun run scripts/release-candidate.ts",
55
+ "release:verify:full": "bun run scripts/release-verify.ts --full",
54
56
  "test:packages:pack": "bun run scripts/platform-package-release.ts",
55
57
  "test:agent": "uv run --directory apps/agent-server pytest",
56
58
  "test:document": "uv run --directory apps/document-server pytest",