complete-cli 1.0.1-dev.3 → 1.0.1-dev.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,8 @@
1
1
  import chalk from "chalk";
2
2
  import { Command, Option } from "clipanion";
3
3
  import { ReadonlySet } from "complete-common";
4
- import { $s, deleteFileOrDirectory, fatalError, isDirectory, isFile, readFile, writeFile, } from "complete-node";
4
+ import { deleteFileOrDirectory, fatalError, isDirectory, isFile, readFile, writeFile, } from "complete-node";
5
+ import { $ } from "execa";
5
6
  import klawSync from "klaw-sync";
6
7
  import path from "node:path";
7
8
  import { ACTION_YML, ACTION_YML_TEMPLATE_PATH, CWD, TEMPLATES_DYNAMIC_DIR, TEMPLATES_STATIC_DIR, } from "../constants.js";
@@ -120,7 +121,7 @@ function compareTextFiles(projectFilePath, templateFilePath, verbose) {
120
121
  const tempTemplateFilePath = path.join(CWD, "tempTemplateFile.txt");
121
122
  writeFile(tempProjectFilePath, projectFileObject.text);
122
123
  writeFile(tempTemplateFilePath, templateFileObject.text);
123
- $s `diff ${tempProjectFilePath} ${tempTemplateFilePath} --ignore-blank-lines`;
124
+ $.sync `diff ${tempProjectFilePath} ${tempTemplateFilePath} --ignore-blank-lines`;
124
125
  deleteFileOrDirectory(tempProjectFilePath);
125
126
  deleteFileOrDirectory(tempTemplateFilePath);
126
127
  return false;
@@ -1,6 +1,7 @@
1
1
  import { Command, Option } from "clipanion";
2
2
  import { isSemanticVersion } from "complete-common";
3
- import { $, $s, fatalError, getPackageJSONField, getPackageJSONVersion, getPackageManagerInstallCommand, getPackageManagerLockFileName, getPackageManagersForProject, isFile, isGitRepository, isGitRepositoryClean, isLoggedInToNPM, readFile, updatePackageJSONDependencies, writeFile, } from "complete-node";
3
+ import { fatalError, getPackageJSONField, getPackageJSONVersion, getPackageManagerInstallCommand, getPackageManagerLockFileName, getPackageManagersForProject, isFileAsync, isGitRepository, isGitRepositoryClean, isLoggedInToNPM, readFile, updatePackageJSONDependencies, writeFileAsync, } from "complete-node";
4
+ import { $ } from "execa";
4
5
  import path from "node:path";
5
6
  import { CWD, DEFAULT_PACKAGE_MANAGER } from "../constants.js";
6
7
  export class PublishCommand extends Command {
@@ -21,24 +22,27 @@ export class PublishCommand extends Command {
21
22
  static usage = Command.Usage({
22
23
  description: "Bump the version & publish a new release.",
23
24
  });
24
- // eslint-disable-next-line @typescript-eslint/require-await
25
25
  async execute() {
26
- validate();
27
- prePublish(this.versionBumpType, this.dryRun, this.skipLint, this.skipUpdate);
28
- publish(this.dryRun);
26
+ await validate();
27
+ await prePublish(this.versionBumpType, this.dryRun, this.skipLint, this.skipUpdate);
28
+ await publish(this.dryRun);
29
29
  }
30
30
  }
31
- function validate() {
32
- if (!isGitRepository(CWD)) {
31
+ async function validate() {
32
+ const isRepository = await isGitRepository(CWD);
33
+ if (!isRepository) {
33
34
  fatalError("Failed to publish since the current working directory is not inside of a git repository.");
34
35
  }
35
- if (!isGitRepositoryClean(CWD)) {
36
+ const isRepositoryClean = await isGitRepositoryClean(CWD);
37
+ if (!isRepositoryClean) {
36
38
  fatalError("Failed to publish since the Git repository was dirty. Before publishing, you must push any current changes to git. (Version commits should not contain any code changes.)");
37
39
  }
38
- if (!isFile("package.json")) {
40
+ const packageJSONExists = await isFileAsync("package.json");
41
+ if (!packageJSONExists) {
39
42
  fatalError('Failed to find the "package.json" file in the current working directory.');
40
43
  }
41
- if (!isLoggedInToNPM()) {
44
+ const isLoggedIn = await isLoggedInToNPM();
45
+ if (!isLoggedIn) {
42
46
  fatalError('Failed to publish since you are not logged in to npm. Try doing "npm login".');
43
47
  }
44
48
  }
@@ -46,16 +50,16 @@ function validate() {
46
50
  * Before uploading the project, we want to update dependencies, increment the version, and perform
47
51
  * some other steps.
48
52
  */
49
- function prePublish(versionBumpType, dryRun, skipLint, skipUpdate) {
53
+ async function prePublish(versionBumpType, dryRun, skipLint, skipUpdate) {
50
54
  const packageManager = getPackageManagerUsedForExistingProject();
51
- $s `git pull --rebase`;
52
- $s `git push`;
53
- updateDependencies(skipUpdate, dryRun, packageManager);
54
- incrementVersion(versionBumpType);
55
- unsetDevelopmentConstants();
56
- tryRunNPMScript("build");
55
+ await $ `git pull --rebase`;
56
+ await $ `git push`;
57
+ await updateDependencies(skipUpdate, dryRun, packageManager);
58
+ await incrementVersion(versionBumpType);
59
+ await unsetDevelopmentConstants();
60
+ await tryRunNPMScript("build");
57
61
  if (!skipLint) {
58
- tryRunNPMScript("lint");
62
+ await tryRunNPMScript("lint");
59
63
  }
60
64
  }
61
65
  function getPackageManagerUsedForExistingProject() {
@@ -73,7 +77,7 @@ function getPackageManagerUsedForExistingProject() {
73
77
  }
74
78
  return DEFAULT_PACKAGE_MANAGER;
75
79
  }
76
- function updateDependencies(skipUpdate, dryRun, packageManager) {
80
+ async function updateDependencies(skipUpdate, dryRun, packageManager) {
77
81
  if (skipUpdate) {
78
82
  return;
79
83
  }
@@ -82,19 +86,19 @@ function updateDependencies(skipUpdate, dryRun, packageManager) {
82
86
  if (hasNewDependencies) {
83
87
  const command = getPackageManagerInstallCommand(packageManager);
84
88
  const commandParts = command.split(" ");
85
- $s `${commandParts}`;
89
+ await $ `${commandParts}`;
86
90
  if (!dryRun) {
87
- gitCommitAllAndPush("chore: update dependencies");
91
+ await gitCommitAllAndPush("chore: update dependencies");
88
92
  }
89
93
  }
90
94
  }
91
- function gitCommitAllAndPush(message) {
92
- $s `git add --all`;
93
- $s `git commit --message ${message}`;
94
- $s `git push`;
95
+ async function gitCommitAllAndPush(message) {
96
+ await $ `git add --all`;
97
+ await $ `git commit --message ${message}`;
98
+ await $ `git push`;
95
99
  console.log(`Committed and pushed to the git repository with a message of: ${message}`);
96
100
  }
97
- function incrementVersion(versionBumpType) {
101
+ async function incrementVersion(versionBumpType) {
98
102
  if (versionBumpType === "none") {
99
103
  return;
100
104
  }
@@ -111,44 +115,45 @@ function incrementVersion(versionBumpType) {
111
115
  // We always use `npm` here to avoid differences with the version command between package
112
116
  // managers. The "--no-git-tag-version" flag will prevent npm from both making a commit and adding
113
117
  // a tag.
114
- $s `npm version ${versionBumpType} --no-git-tag-version`;
118
+ await $ `npm version ${versionBumpType} --no-git-tag-version`;
115
119
  }
116
- function unsetDevelopmentConstants() {
120
+ async function unsetDevelopmentConstants() {
117
121
  const constantsTSPath = path.join(CWD, "src", "constants.ts");
118
- if (!isFile(constantsTSPath)) {
122
+ const constantsTSExists = await isFileAsync(constantsTSPath);
123
+ if (!constantsTSExists) {
119
124
  return;
120
125
  }
121
126
  const constantsTS = readFile(constantsTSPath);
122
127
  const newConstantsTS = constantsTS
123
128
  .replace("const IS_DEV = true", "const IS_DEV = false")
124
129
  .replace("const DEBUG = true", "const DEBUG = false");
125
- writeFile(constantsTSPath, newConstantsTS);
130
+ await writeFileAsync(constantsTSPath, newConstantsTS);
126
131
  }
127
- function tryRunNPMScript(scriptName) {
132
+ async function tryRunNPMScript(scriptName) {
128
133
  console.log(`Running: ${scriptName}`);
129
134
  const $$ = $({
130
135
  reject: false,
131
136
  });
132
- const { exitCode } = $$.sync `npm run ${scriptName}`;
137
+ const { exitCode } = await $$ `npm run ${scriptName}`;
133
138
  if (exitCode !== 0) {
134
- $s `git reset --hard`; // Revert the version changes.
139
+ await $ `git reset --hard`; // Revert the version changes.
135
140
  fatalError(`Failed to run "${scriptName}".`);
136
141
  }
137
142
  }
138
- function publish(dryRun) {
143
+ async function publish(dryRun) {
139
144
  const projectName = getPackageJSONField(undefined, "name");
140
145
  const version = getPackageJSONVersion(undefined);
141
146
  if (dryRun) {
142
- $s `git reset --hard`; // Revert the version changes.
147
+ await $ `git reset --hard`; // Revert the version changes.
143
148
  }
144
149
  else {
145
150
  const releaseGitCommitMessage = getReleaseGitCommitMessage(version);
146
- gitCommitAllAndPush(releaseGitCommitMessage);
151
+ await gitCommitAllAndPush(releaseGitCommitMessage);
147
152
  // - The "--access=public" flag is only technically needed for the first publish (unless the
148
153
  // package is a scoped package), but it is saved here for posterity.
149
154
  // - The "--ignore-scripts" flag is needed since the "npm publish" command will run the
150
155
  // "publish" script in the "package.json" file, causing an infinite loop.
151
- $s `npm publish --access=public --ignore-scripts`;
156
+ await $ `npm publish --access=public --ignore-scripts`;
152
157
  }
153
158
  const dryRunSuffix = dryRun ? " (dry-run)" : "";
154
159
  console.log(`Published ${projectName} version ${version} successfully${dryRunSuffix}.`);
@@ -1,6 +1,7 @@
1
1
  import chalk from "chalk";
2
2
  import { repeat } from "complete-common";
3
- import { $, copyFileOrDirectory, getFileNamesInDirectory, getPackageManagerInstallCICommand, getPackageManagerInstallCommand, isFile, makeDirectory, readFile, renameFile, updatePackageJSONDependencies, writeFile, } from "complete-node";
3
+ import { copyFileOrDirectory, getFileNamesInDirectory, getPackageManagerInstallCICommand, getPackageManagerInstallCommand, isFile, makeDirectory, readFile, renameFile, updatePackageJSONDependencies, writeFile, } from "complete-node";
4
+ import { $ } from "execa";
4
5
  import path from "node:path";
5
6
  import { ACTION_YML, ACTION_YML_TEMPLATE_PATH, TEMPLATES_DYNAMIC_DIR, TEMPLATES_STATIC_DIR, } from "../../constants.js";
6
7
  import { initGitRepository } from "../../git.js";
@@ -1,4 +1,5 @@
1
- import { $, commandExists, getJSONC, isFile } from "complete-node";
1
+ import { commandExists, getJSONC, isFile } from "complete-node";
2
+ import { $ } from "execa";
2
3
  import path from "node:path";
3
4
  import { getInputYesNo, promptError, promptLog } from "../../prompt.js";
4
5
  const VS_CODE_COMMANDS = [
package/dist/git.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import chalk from "chalk";
2
- import { $, commandExists, isFile, readFile } from "complete-node";
2
+ import { commandExists, isFile, readFile } from "complete-node";
3
+ import { $ } from "execa";
3
4
  import path from "node:path";
4
5
  import yaml from "yaml";
5
6
  import { HOME_DIR, PROJECT_NAME, PROJECT_VERSION } from "./constants.js";
@@ -32,6 +32,7 @@
32
32
  "complete-cli": "^0.0.1",
33
33
  "complete-lint": "^0.0.1",
34
34
  "complete-node": "^0.0.1",
35
- "typescript": "5.5.4"
35
+ "execa": "^0.0.1",
36
+ "typescript": "^0.0.1"
36
37
  }
37
38
  }
@@ -1,5 +1,6 @@
1
- import { $s, buildScript } from "complete-node";
1
+ import { buildScript } from "complete-node";
2
+ import { $ } from "execa";
2
3
 
3
- await buildScript(() => {
4
- $s`tsc`;
4
+ await buildScript(async () => {
5
+ await $`tsc`;
5
6
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "complete-cli",
3
- "version": "1.0.1-dev.3",
3
+ "version": "1.0.1-dev.5",
4
4
  "description": "A command line tool for bootstrapping TypeScript projects.",
5
5
  "keywords": [
6
6
  "typescript"
@@ -39,6 +39,7 @@
39
39
  "clipanion": "^4.0.0-rc.4",
40
40
  "complete-common": "^1.0.1",
41
41
  "complete-node": "^1.7.4",
42
+ "execa": "^9.5.2",
42
43
  "klaw-sync": "^6.0.0",
43
44
  "yaml": "^2.7.0"
44
45
  },
@@ -2,7 +2,6 @@ import chalk from "chalk";
2
2
  import { Command, Option } from "clipanion";
3
3
  import { ReadonlySet } from "complete-common";
4
4
  import {
5
- $s,
6
5
  deleteFileOrDirectory,
7
6
  fatalError,
8
7
  isDirectory,
@@ -10,6 +9,7 @@ import {
10
9
  readFile,
11
10
  writeFile,
12
11
  } from "complete-node";
12
+ import { $ } from "execa";
13
13
  import klawSync from "klaw-sync";
14
14
  import path from "node:path";
15
15
  import {
@@ -209,7 +209,7 @@ function compareTextFiles(
209
209
  writeFile(tempProjectFilePath, projectFileObject.text);
210
210
  writeFile(tempTemplateFilePath, templateFileObject.text);
211
211
 
212
- $s`diff ${tempProjectFilePath} ${tempTemplateFilePath} --ignore-blank-lines`;
212
+ $.sync`diff ${tempProjectFilePath} ${tempTemplateFilePath} --ignore-blank-lines`;
213
213
 
214
214
  deleteFileOrDirectory(tempProjectFilePath);
215
215
  deleteFileOrDirectory(tempTemplateFilePath);
@@ -2,22 +2,21 @@ import { Command, Option } from "clipanion";
2
2
  import { isSemanticVersion } from "complete-common";
3
3
  import type { PackageManager } from "complete-node";
4
4
  import {
5
- $,
6
- $s,
7
5
  fatalError,
8
6
  getPackageJSONField,
9
7
  getPackageJSONVersion,
10
8
  getPackageManagerInstallCommand,
11
9
  getPackageManagerLockFileName,
12
10
  getPackageManagersForProject,
13
- isFile,
11
+ isFileAsync,
14
12
  isGitRepository,
15
13
  isGitRepositoryClean,
16
14
  isLoggedInToNPM,
17
15
  readFile,
18
16
  updatePackageJSONDependencies,
19
- writeFile,
17
+ writeFileAsync,
20
18
  } from "complete-node";
19
+ import { $ } from "execa";
21
20
  import path from "node:path";
22
21
  import { CWD, DEFAULT_PACKAGE_MANAGER } from "../constants.js";
23
22
 
@@ -45,39 +44,42 @@ export class PublishCommand extends Command {
45
44
  description: "Bump the version & publish a new release.",
46
45
  });
47
46
 
48
- // eslint-disable-next-line @typescript-eslint/require-await
49
47
  async execute(): Promise<void> {
50
- validate();
51
- prePublish(
48
+ await validate();
49
+ await prePublish(
52
50
  this.versionBumpType,
53
51
  this.dryRun,
54
52
  this.skipLint,
55
53
  this.skipUpdate,
56
54
  );
57
- publish(this.dryRun);
55
+ await publish(this.dryRun);
58
56
  }
59
57
  }
60
58
 
61
- function validate() {
62
- if (!isGitRepository(CWD)) {
59
+ async function validate() {
60
+ const isRepository = await isGitRepository(CWD);
61
+ if (!isRepository) {
63
62
  fatalError(
64
63
  "Failed to publish since the current working directory is not inside of a git repository.",
65
64
  );
66
65
  }
67
66
 
68
- if (!isGitRepositoryClean(CWD)) {
67
+ const isRepositoryClean = await isGitRepositoryClean(CWD);
68
+ if (!isRepositoryClean) {
69
69
  fatalError(
70
70
  "Failed to publish since the Git repository was dirty. Before publishing, you must push any current changes to git. (Version commits should not contain any code changes.)",
71
71
  );
72
72
  }
73
73
 
74
- if (!isFile("package.json")) {
74
+ const packageJSONExists = await isFileAsync("package.json");
75
+ if (!packageJSONExists) {
75
76
  fatalError(
76
77
  'Failed to find the "package.json" file in the current working directory.',
77
78
  );
78
79
  }
79
80
 
80
- if (!isLoggedInToNPM()) {
81
+ const isLoggedIn = await isLoggedInToNPM();
82
+ if (!isLoggedIn) {
81
83
  fatalError(
82
84
  'Failed to publish since you are not logged in to npm. Try doing "npm login".',
83
85
  );
@@ -88,7 +90,7 @@ function validate() {
88
90
  * Before uploading the project, we want to update dependencies, increment the version, and perform
89
91
  * some other steps.
90
92
  */
91
- function prePublish(
93
+ async function prePublish(
92
94
  versionBumpType: string,
93
95
  dryRun: boolean,
94
96
  skipLint: boolean,
@@ -96,15 +98,15 @@ function prePublish(
96
98
  ) {
97
99
  const packageManager = getPackageManagerUsedForExistingProject();
98
100
 
99
- $s`git pull --rebase`;
100
- $s`git push`;
101
- updateDependencies(skipUpdate, dryRun, packageManager);
102
- incrementVersion(versionBumpType);
103
- unsetDevelopmentConstants();
101
+ await $`git pull --rebase`;
102
+ await $`git push`;
103
+ await updateDependencies(skipUpdate, dryRun, packageManager);
104
+ await incrementVersion(versionBumpType);
105
+ await unsetDevelopmentConstants();
104
106
 
105
- tryRunNPMScript("build");
107
+ await tryRunNPMScript("build");
106
108
  if (!skipLint) {
107
- tryRunNPMScript("lint");
109
+ await tryRunNPMScript("lint");
108
110
  }
109
111
  }
110
112
 
@@ -128,7 +130,7 @@ function getPackageManagerUsedForExistingProject(): PackageManager {
128
130
  return DEFAULT_PACKAGE_MANAGER;
129
131
  }
130
132
 
131
- function updateDependencies(
133
+ async function updateDependencies(
132
134
  skipUpdate: boolean,
133
135
  dryRun: boolean,
134
136
  packageManager: PackageManager,
@@ -142,23 +144,23 @@ function updateDependencies(
142
144
  if (hasNewDependencies) {
143
145
  const command = getPackageManagerInstallCommand(packageManager);
144
146
  const commandParts = command.split(" ");
145
- $s`${commandParts}`;
147
+ await $`${commandParts}`;
146
148
  if (!dryRun) {
147
- gitCommitAllAndPush("chore: update dependencies");
149
+ await gitCommitAllAndPush("chore: update dependencies");
148
150
  }
149
151
  }
150
152
  }
151
153
 
152
- function gitCommitAllAndPush(message: string) {
153
- $s`git add --all`;
154
- $s`git commit --message ${message}`;
155
- $s`git push`;
154
+ async function gitCommitAllAndPush(message: string) {
155
+ await $`git add --all`;
156
+ await $`git commit --message ${message}`;
157
+ await $`git push`;
156
158
  console.log(
157
159
  `Committed and pushed to the git repository with a message of: ${message}`,
158
160
  );
159
161
  }
160
162
 
161
- function incrementVersion(versionBumpType: string) {
163
+ async function incrementVersion(versionBumpType: string) {
162
164
  if (versionBumpType === "none") {
163
165
  return;
164
166
  }
@@ -184,12 +186,13 @@ function incrementVersion(versionBumpType: string) {
184
186
  // We always use `npm` here to avoid differences with the version command between package
185
187
  // managers. The "--no-git-tag-version" flag will prevent npm from both making a commit and adding
186
188
  // a tag.
187
- $s`npm version ${versionBumpType} --no-git-tag-version`;
189
+ await $`npm version ${versionBumpType} --no-git-tag-version`;
188
190
  }
189
191
 
190
- function unsetDevelopmentConstants() {
192
+ async function unsetDevelopmentConstants() {
191
193
  const constantsTSPath = path.join(CWD, "src", "constants.ts");
192
- if (!isFile(constantsTSPath)) {
194
+ const constantsTSExists = await isFileAsync(constantsTSPath);
195
+ if (!constantsTSExists) {
193
196
  return;
194
197
  }
195
198
 
@@ -197,38 +200,38 @@ function unsetDevelopmentConstants() {
197
200
  const newConstantsTS = constantsTS
198
201
  .replace("const IS_DEV = true", "const IS_DEV = false")
199
202
  .replace("const DEBUG = true", "const DEBUG = false");
200
- writeFile(constantsTSPath, newConstantsTS);
203
+ await writeFileAsync(constantsTSPath, newConstantsTS);
201
204
  }
202
205
 
203
- function tryRunNPMScript(scriptName: string) {
206
+ async function tryRunNPMScript(scriptName: string) {
204
207
  console.log(`Running: ${scriptName}`);
205
208
 
206
209
  const $$ = $({
207
210
  reject: false,
208
211
  });
209
- const { exitCode } = $$.sync`npm run ${scriptName}`;
212
+ const { exitCode } = await $$`npm run ${scriptName}`;
210
213
 
211
214
  if (exitCode !== 0) {
212
- $s`git reset --hard`; // Revert the version changes.
215
+ await $`git reset --hard`; // Revert the version changes.
213
216
  fatalError(`Failed to run "${scriptName}".`);
214
217
  }
215
218
  }
216
219
 
217
- function publish(dryRun: boolean) {
220
+ async function publish(dryRun: boolean) {
218
221
  const projectName = getPackageJSONField(undefined, "name");
219
222
  const version = getPackageJSONVersion(undefined);
220
223
 
221
224
  if (dryRun) {
222
- $s`git reset --hard`; // Revert the version changes.
225
+ await $`git reset --hard`; // Revert the version changes.
223
226
  } else {
224
227
  const releaseGitCommitMessage = getReleaseGitCommitMessage(version);
225
- gitCommitAllAndPush(releaseGitCommitMessage);
228
+ await gitCommitAllAndPush(releaseGitCommitMessage);
226
229
 
227
230
  // - The "--access=public" flag is only technically needed for the first publish (unless the
228
231
  // package is a scoped package), but it is saved here for posterity.
229
232
  // - The "--ignore-scripts" flag is needed since the "npm publish" command will run the
230
233
  // "publish" script in the "package.json" file, causing an infinite loop.
231
- $s`npm publish --access=public --ignore-scripts`;
234
+ await $`npm publish --access=public --ignore-scripts`;
232
235
  }
233
236
 
234
237
  const dryRunSuffix = dryRun ? " (dry-run)" : "";
@@ -2,7 +2,6 @@ import chalk from "chalk";
2
2
  import { repeat } from "complete-common";
3
3
  import type { PackageManager } from "complete-node";
4
4
  import {
5
- $,
6
5
  copyFileOrDirectory,
7
6
  getFileNamesInDirectory,
8
7
  getPackageManagerInstallCICommand,
@@ -14,6 +13,7 @@ import {
14
13
  updatePackageJSONDependencies,
15
14
  writeFile,
16
15
  } from "complete-node";
16
+ import { $ } from "execa";
17
17
  import path from "node:path";
18
18
  import {
19
19
  ACTION_YML,
@@ -1,4 +1,5 @@
1
- import { $, commandExists, getJSONC, isFile } from "complete-node";
1
+ import { commandExists, getJSONC, isFile } from "complete-node";
2
+ import { $ } from "execa";
2
3
  import path from "node:path";
3
4
  import { getInputYesNo, promptError, promptLog } from "../../prompt.js";
4
5
 
package/src/git.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import chalk from "chalk";
2
- import { $, commandExists, isFile, readFile } from "complete-node";
2
+ import { commandExists, isFile, readFile } from "complete-node";
3
+ import { $ } from "execa";
3
4
  import path from "node:path";
4
5
  import yaml from "yaml";
5
6
  import { HOME_DIR, PROJECT_NAME, PROJECT_VERSION } from "./constants.js";