complete-cli 1.3.2 → 1.3.4
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/commands/CheckCommand.js +16 -11
- package/dist/commands/CheckCommand.js.map +1 -0
- package/dist/commands/InitCommand.js +1 -0
- package/dist/commands/InitCommand.js.map +1 -0
- package/dist/commands/MetadataCommand.js +5 -4
- package/dist/commands/MetadataCommand.js.map +1 -0
- package/dist/commands/NukeCommand.js +1 -0
- package/dist/commands/NukeCommand.js.map +1 -0
- package/dist/commands/PublishCommand.js +6 -5
- package/dist/commands/PublishCommand.js.map +1 -0
- package/dist/commands/UpdateCommand.js +1 -0
- package/dist/commands/UpdateCommand.js.map +1 -0
- package/dist/commands/check/check.test.js +1 -0
- package/dist/commands/check/check.test.js.map +1 -0
- package/dist/commands/check/getTruncatedText.js +1 -0
- package/dist/commands/check/getTruncatedText.js.map +1 -0
- package/dist/commands/init/checkIfProjectPathExists.js +12 -5
- package/dist/commands/init/checkIfProjectPathExists.js.map +1 -0
- package/dist/commands/init/createProject.js +53 -32
- package/dist/commands/init/createProject.js.map +1 -0
- package/dist/commands/init/getAuthorName.js +1 -0
- package/dist/commands/init/getAuthorName.js.map +1 -0
- package/dist/commands/init/getProjectPath.js +1 -0
- package/dist/commands/init/getProjectPath.js.map +1 -0
- package/dist/commands/init/lockedDependencies.js +1 -0
- package/dist/commands/init/lockedDependencies.js.map +1 -0
- package/dist/commands/init/packageManager.js +16 -3
- package/dist/commands/init/packageManager.js.map +1 -0
- package/dist/commands/init/vsCodeInit.js +7 -1
- package/dist/commands/init/vsCodeInit.js.map +1 -0
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -0
- package/dist/git.js +4 -3
- package/dist/git.js.map +1 -0
- package/dist/interfaces/GitHubCLIHostsYAML.js +1 -0
- package/dist/interfaces/GitHubCLIHostsYAML.js.map +1 -0
- package/dist/main.js +1 -0
- package/dist/main.js.map +1 -0
- package/dist/prompt.js +2 -1
- package/dist/prompt.js.map +1 -0
- package/file-templates/dynamic/.github/workflows/setup/action.yml +1 -1
- package/file-templates/dynamic/Node.gitignore +3 -1
- package/file-templates/dynamic/package.json +2 -6
- package/file-templates/static/eslint.config.mjs +2 -2
- package/file-templates/static/scripts/lint.ts +1 -1
- package/package.json +9 -12
- package/src/commands/CheckCommand.ts +18 -14
- package/src/commands/MetadataCommand.ts +4 -9
- package/src/commands/PublishCommand.ts +6 -6
- package/src/commands/init/checkIfProjectPathExists.ts +13 -9
- package/src/commands/init/createProject.ts +69 -36
- package/src/commands/init/packageManager.ts +22 -3
- package/src/commands/init/vsCodeInit.ts +9 -1
- package/src/git.ts +3 -3
- package/src/prompt.ts +1 -1
|
@@ -12,10 +12,9 @@ import {
|
|
|
12
12
|
makeDirectory,
|
|
13
13
|
PackageManager,
|
|
14
14
|
readFile,
|
|
15
|
-
|
|
15
|
+
renameFileOrDirectory,
|
|
16
16
|
updatePackageJSONDependencies,
|
|
17
17
|
writeFile,
|
|
18
|
-
writeFileAsync,
|
|
19
18
|
} from "complete-node";
|
|
20
19
|
import path from "node:path";
|
|
21
20
|
import {
|
|
@@ -38,12 +37,12 @@ export async function createProject(
|
|
|
38
37
|
packageManager: PackageManager,
|
|
39
38
|
): Promise<void> {
|
|
40
39
|
if (createNewDir) {
|
|
41
|
-
makeDirectory(projectPath);
|
|
40
|
+
await makeDirectory(projectPath);
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
copyStaticFiles(projectPath);
|
|
45
|
-
copyDynamicFiles(projectName, authorName, projectPath, packageManager);
|
|
46
|
-
copyPackageManagerSpecificFiles(projectPath, packageManager);
|
|
43
|
+
await copyStaticFiles(projectPath);
|
|
44
|
+
await copyDynamicFiles(projectName, authorName, projectPath, packageManager);
|
|
45
|
+
await copyPackageManagerSpecificFiles(projectPath, packageManager);
|
|
47
46
|
|
|
48
47
|
// There is no package manager lock files yet, so we have to pass "false" to this function.
|
|
49
48
|
const updated = await updatePackageJSONDependencies(projectPath, false, true);
|
|
@@ -69,38 +68,44 @@ export async function createProject(
|
|
|
69
68
|
}
|
|
70
69
|
|
|
71
70
|
/** Copy static files, like "eslint.config.mjs", "tsconfig.json", etc. */
|
|
72
|
-
function copyStaticFiles(projectPath: string) {
|
|
73
|
-
copyTemplateDirectoryWithoutOverwriting(
|
|
71
|
+
async function copyStaticFiles(projectPath: string) {
|
|
72
|
+
await copyTemplateDirectoryWithoutOverwriting(
|
|
73
|
+
TEMPLATES_STATIC_DIR,
|
|
74
|
+
projectPath,
|
|
75
|
+
);
|
|
74
76
|
|
|
75
77
|
// Rename "_gitattributes" to ".gitattributes". (If it is kept as ".gitattributes", then it won't
|
|
76
78
|
// be committed to git.)
|
|
77
79
|
const gitAttributesPath = path.join(projectPath, "_gitattributes");
|
|
78
80
|
const correctGitAttributesPath = path.join(projectPath, ".gitattributes");
|
|
79
|
-
|
|
81
|
+
await renameFileOrDirectory(gitAttributesPath, correctGitAttributesPath);
|
|
80
82
|
|
|
81
83
|
// Rename "_cspell.config.jsonc" to "cspell.config.jsonc". (If it is kept as
|
|
82
84
|
// "cspell.config.jsonc", then local spell checking will fail.)
|
|
83
85
|
const cSpellConfigPath = path.join(projectPath, "_cspell.config.jsonc");
|
|
84
86
|
const correctCSpellConfigPath = path.join(projectPath, "cspell.config.jsonc");
|
|
85
|
-
|
|
87
|
+
await renameFileOrDirectory(cSpellConfigPath, correctCSpellConfigPath);
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
function copyTemplateDirectoryWithoutOverwriting(
|
|
90
|
+
async function copyTemplateDirectoryWithoutOverwriting(
|
|
89
91
|
templateDirPath: string,
|
|
90
92
|
projectPath: string,
|
|
91
93
|
) {
|
|
92
|
-
const fileNames = getFileNamesInDirectory(templateDirPath);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
const fileNames = await getFileNamesInDirectory(templateDirPath);
|
|
95
|
+
await Promise.all(
|
|
96
|
+
fileNames.map(async (fileName) => {
|
|
97
|
+
const templateFilePath = path.join(templateDirPath, fileName);
|
|
98
|
+
const destinationFilePath = path.join(projectPath, fileName);
|
|
99
|
+
const file = await isFile(destinationFilePath);
|
|
100
|
+
if (!file) {
|
|
101
|
+
await copyFileOrDirectory(templateFilePath, destinationFilePath);
|
|
102
|
+
}
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
100
105
|
}
|
|
101
106
|
|
|
102
107
|
/** Copy files that need to have text replaced inside of them. */
|
|
103
|
-
function copyDynamicFiles(
|
|
108
|
+
async function copyDynamicFiles(
|
|
104
109
|
projectName: string,
|
|
105
110
|
authorName: string | undefined,
|
|
106
111
|
projectPath: string,
|
|
@@ -110,7 +115,7 @@ function copyDynamicFiles(
|
|
|
110
115
|
{
|
|
111
116
|
const fileName = ACTION_YML;
|
|
112
117
|
const templatePath = ACTION_YML_TEMPLATE_PATH;
|
|
113
|
-
const template = readFile(templatePath);
|
|
118
|
+
const template = await readFile(templatePath);
|
|
114
119
|
|
|
115
120
|
const installCommand = getPackageManagerInstallCICommand(packageManager);
|
|
116
121
|
const actionYML = template
|
|
@@ -118,9 +123,9 @@ function copyDynamicFiles(
|
|
|
118
123
|
.replaceAll("PACKAGE_MANAGER_INSTALL_COMMAND", installCommand);
|
|
119
124
|
|
|
120
125
|
const setupPath = path.join(projectPath, ".github", "workflows", "setup");
|
|
121
|
-
makeDirectory(setupPath);
|
|
126
|
+
await makeDirectory(setupPath);
|
|
122
127
|
const destinationPath = path.join(setupPath, fileName);
|
|
123
|
-
writeFile(destinationPath, actionYML);
|
|
128
|
+
await writeFile(destinationPath, actionYML);
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
// `.gitignore`
|
|
@@ -129,7 +134,7 @@ function copyDynamicFiles(
|
|
|
129
134
|
TEMPLATES_DYNAMIC_DIR,
|
|
130
135
|
"_gitignore", // Not named ".gitignore" to prevent npm from deleting it.
|
|
131
136
|
);
|
|
132
|
-
const template = readFile(templatePath);
|
|
137
|
+
const template = await readFile(templatePath);
|
|
133
138
|
|
|
134
139
|
// Prepend a header with the project name.
|
|
135
140
|
let separatorLine = "# ";
|
|
@@ -142,33 +147,33 @@ function copyDynamicFiles(
|
|
|
142
147
|
TEMPLATES_DYNAMIC_DIR,
|
|
143
148
|
"Node.gitignore",
|
|
144
149
|
);
|
|
145
|
-
const nodeGitIgnore = readFile(nodeGitIgnorePath);
|
|
150
|
+
const nodeGitIgnore = await readFile(nodeGitIgnorePath);
|
|
146
151
|
|
|
147
152
|
// eslint-disable-next-line prefer-template
|
|
148
153
|
const gitignore = gitIgnoreHeader + template + "\n" + nodeGitIgnore;
|
|
149
154
|
|
|
150
155
|
// We need to replace the underscore with a period.
|
|
151
156
|
const destinationPath = path.join(projectPath, ".gitignore");
|
|
152
|
-
writeFile(destinationPath, gitignore);
|
|
157
|
+
await writeFile(destinationPath, gitignore);
|
|
153
158
|
}
|
|
154
159
|
|
|
155
160
|
// `package.json`
|
|
156
161
|
{
|
|
157
162
|
const templatePath = path.join(TEMPLATES_DYNAMIC_DIR, "package.json");
|
|
158
|
-
const template = readFile(templatePath);
|
|
163
|
+
const template = await readFile(templatePath);
|
|
159
164
|
|
|
160
165
|
const packageJSON = template
|
|
161
166
|
.replaceAll("project-name", projectName)
|
|
162
167
|
.replaceAll("author-name", authorName ?? "unknown");
|
|
163
168
|
|
|
164
169
|
const destinationPath = path.join(projectPath, "package.json");
|
|
165
|
-
writeFile(destinationPath, packageJSON);
|
|
170
|
+
await writeFile(destinationPath, packageJSON);
|
|
166
171
|
}
|
|
167
172
|
|
|
168
173
|
// `README.md`
|
|
169
174
|
{
|
|
170
175
|
const templatePath = path.join(TEMPLATES_DYNAMIC_DIR, "README.md");
|
|
171
|
-
const template = readFile(templatePath);
|
|
176
|
+
const template = await readFile(templatePath);
|
|
172
177
|
|
|
173
178
|
// "PROJECT-NAME" must be hyphenated, as using an underscore will break Prettier for some
|
|
174
179
|
// reason.
|
|
@@ -177,11 +182,11 @@ function copyDynamicFiles(
|
|
|
177
182
|
.replaceAll("PROJECT-NAME", projectName)
|
|
178
183
|
.replaceAll("PACKAGE-MANAGER-INSTALL-COMMAND", command);
|
|
179
184
|
const destinationPath = path.join(projectPath, "README.md");
|
|
180
|
-
writeFile(destinationPath, readmeMD);
|
|
185
|
+
await writeFile(destinationPath, readmeMD);
|
|
181
186
|
}
|
|
182
187
|
}
|
|
183
188
|
|
|
184
|
-
function copyPackageManagerSpecificFiles(
|
|
189
|
+
async function copyPackageManagerSpecificFiles(
|
|
185
190
|
projectPath: string,
|
|
186
191
|
packageManager: PackageManager,
|
|
187
192
|
) {
|
|
@@ -189,7 +194,7 @@ function copyPackageManagerSpecificFiles(
|
|
|
189
194
|
case PackageManager.npm: {
|
|
190
195
|
const npmrc = "save-exact=true\n";
|
|
191
196
|
const npmrcPath = path.join(projectPath, ".npmrc");
|
|
192
|
-
writeFile(npmrcPath, npmrc);
|
|
197
|
+
await writeFile(npmrcPath, npmrc);
|
|
193
198
|
break;
|
|
194
199
|
}
|
|
195
200
|
|
|
@@ -198,7 +203,7 @@ function copyPackageManagerSpecificFiles(
|
|
|
198
203
|
case PackageManager.pnpm: {
|
|
199
204
|
const npmrc = "save-exact=true\nshamefully-hoist=true\n";
|
|
200
205
|
const npmrcPath = path.join(projectPath, ".npmrc");
|
|
201
|
-
writeFile(npmrcPath, npmrc);
|
|
206
|
+
await writeFile(npmrcPath, npmrc);
|
|
202
207
|
break;
|
|
203
208
|
}
|
|
204
209
|
|
|
@@ -209,7 +214,35 @@ function copyPackageManagerSpecificFiles(
|
|
|
209
214
|
case PackageManager.bun: {
|
|
210
215
|
const bunfig = "[install]\nexact = true\n";
|
|
211
216
|
const bunfigPath = path.join(projectPath, "bunfig.toml");
|
|
212
|
-
writeFile(bunfigPath, bunfig);
|
|
217
|
+
await writeFile(bunfigPath, bunfig);
|
|
218
|
+
|
|
219
|
+
// Additionally, we assume that if they are using the Bun package manager, they also want to
|
|
220
|
+
// use the Bun runtime. First, replace "complete-tsconfig/tsconfig.node.json" with
|
|
221
|
+
// "complete-tsconfig/tsconfig.bun.json".
|
|
222
|
+
const tsConfigJSONPath = path.join(projectPath, "tsconfig.json");
|
|
223
|
+
const tsConfigJSONScriptsPath = path.join(
|
|
224
|
+
projectPath,
|
|
225
|
+
"scripts",
|
|
226
|
+
"tsconfig.json",
|
|
227
|
+
);
|
|
228
|
+
const filePathsToReplaceNodeWithBun = [
|
|
229
|
+
tsConfigJSONPath,
|
|
230
|
+
tsConfigJSONScriptsPath,
|
|
231
|
+
];
|
|
232
|
+
await Promise.all(
|
|
233
|
+
filePathsToReplaceNodeWithBun.map(async (filePath) => {
|
|
234
|
+
const fileContents = await readFile(filePath);
|
|
235
|
+
const newFileContents = fileContents.replaceAll("node", "bun");
|
|
236
|
+
await writeFile(filePath, newFileContents);
|
|
237
|
+
}),
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
// Second, replace "tsx" with "bun run".
|
|
241
|
+
const packageJSONPath = path.join(projectPath, "package.json");
|
|
242
|
+
const fileContents = await readFile(packageJSONPath);
|
|
243
|
+
const newFileContents = fileContents.replaceAll("tsx", "bun run");
|
|
244
|
+
await writeFile(packageJSONPath, newFileContents);
|
|
245
|
+
|
|
213
246
|
break;
|
|
214
247
|
}
|
|
215
248
|
}
|
|
@@ -228,7 +261,7 @@ async function revertVersionsInPackageJSON(projectPath: string) {
|
|
|
228
261
|
}
|
|
229
262
|
const packageJSONText = JSON.stringify(packageJSON);
|
|
230
263
|
await formatWithPrettier(packageJSONText, "json", projectPath);
|
|
231
|
-
await
|
|
264
|
+
await writeFile(packageJSONPath, packageJSONText);
|
|
232
265
|
}
|
|
233
266
|
|
|
234
267
|
async function createPackageMetadataJSON(projectPath: string) {
|
|
@@ -244,7 +277,7 @@ async function createPackageMetadataJSON(projectPath: string) {
|
|
|
244
277
|
const packageMetadataText = JSON.stringify(packageMetadata);
|
|
245
278
|
await formatWithPrettier(packageMetadataText, "json", projectPath);
|
|
246
279
|
const packageMetadataPath = path.join(projectPath, "package-metadata.json");
|
|
247
|
-
await
|
|
280
|
+
await writeFile(packageMetadataPath, packageMetadataText);
|
|
248
281
|
}
|
|
249
282
|
|
|
250
283
|
async function installNodeModules(
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import type { ReadonlyRecord } from "complete-common";
|
|
3
|
-
import { getEnumValues } from "complete-common";
|
|
4
|
-
import {
|
|
3
|
+
import { assertDefined, getEnumValues } from "complete-common";
|
|
4
|
+
import {
|
|
5
|
+
commandExists,
|
|
6
|
+
getJavaScriptRuntime,
|
|
7
|
+
JavaScriptRuntime,
|
|
8
|
+
PackageManager,
|
|
9
|
+
} from "complete-node";
|
|
5
10
|
import { DEFAULT_PACKAGE_MANAGER } from "../../constants.js";
|
|
6
11
|
import { promptError } from "../../prompt.js";
|
|
7
12
|
|
|
@@ -10,8 +15,21 @@ const PACKAGE_MANAGERS = getEnumValues(PackageManager);
|
|
|
10
15
|
export async function getPackageManagerUsedForNewProject(
|
|
11
16
|
options: ReadonlyRecord<PackageManager, boolean>,
|
|
12
17
|
): Promise<PackageManager> {
|
|
18
|
+
// If the package manager was explicitly specified in the options, use that.
|
|
13
19
|
const packageManagerFromOptions = await getPackageManagerFromOptions(options);
|
|
14
|
-
|
|
20
|
+
if (packageManagerFromOptions !== undefined) {
|
|
21
|
+
return packageManagerFromOptions;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// If `bun` or `bunx` was used to launch this program, assume that they also want to use the Bun
|
|
25
|
+
// package manager.
|
|
26
|
+
const javaScriptRuntime = getJavaScriptRuntime();
|
|
27
|
+
assertDefined(javaScriptRuntime, "Failed to get the JavaScript runtime.");
|
|
28
|
+
if (javaScriptRuntime === JavaScriptRuntime.bun) {
|
|
29
|
+
return PackageManager.bun;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return DEFAULT_PACKAGE_MANAGER;
|
|
15
33
|
}
|
|
16
34
|
|
|
17
35
|
async function getPackageManagerFromOptions(
|
|
@@ -19,6 +37,7 @@ async function getPackageManagerFromOptions(
|
|
|
19
37
|
) {
|
|
20
38
|
for (const packageManager of PACKAGE_MANAGERS) {
|
|
21
39
|
if (options[packageManager]) {
|
|
40
|
+
// Only one package manager flag will be specified at a time.
|
|
22
41
|
// eslint-disable-next-line no-await-in-loop
|
|
23
42
|
const exists = await commandExists(packageManager);
|
|
24
43
|
if (!exists) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertObject } from "complete-common";
|
|
1
2
|
import { $, $q, commandExists, getJSONC, isFile } from "complete-node";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { getInputYesNo, promptError, promptLog } from "../../prompt.js";
|
|
@@ -28,6 +29,8 @@ export async function vsCodeInit(
|
|
|
28
29
|
|
|
29
30
|
async function getVSCodeCommand(): Promise<string | undefined> {
|
|
30
31
|
for (const command of VS_CODE_COMMANDS) {
|
|
32
|
+
// We want to only check for one command at a time, since it is unlikely that the special VSCode
|
|
33
|
+
// commands will exist.
|
|
31
34
|
// eslint-disable-next-line no-await-in-loop
|
|
32
35
|
const exists = await commandExists(command);
|
|
33
36
|
if (exists) {
|
|
@@ -67,11 +70,16 @@ async function getExtensionsFromJSON(
|
|
|
67
70
|
"extensions.json",
|
|
68
71
|
);
|
|
69
72
|
|
|
70
|
-
|
|
73
|
+
const extensionsJSONExists = await isFile(extensionsJSONPath);
|
|
74
|
+
if (!extensionsJSONExists) {
|
|
71
75
|
return [];
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
const extensionsJSON = await getJSONC(extensionsJSONPath);
|
|
79
|
+
assertObject(
|
|
80
|
+
extensionsJSON,
|
|
81
|
+
`The "${extensionsJSONPath}" file is not an object.`,
|
|
82
|
+
);
|
|
75
83
|
|
|
76
84
|
const { recommendations } = extensionsJSON;
|
|
77
85
|
if (!Array.isArray(recommendations)) {
|
package/src/git.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import { $q, commandExists,
|
|
2
|
+
import { $q, commandExists, isFile, readFile } from "complete-node";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import yaml from "yaml";
|
|
5
5
|
import { HOME_DIR, PROJECT_NAME, PROJECT_VERSION } from "./constants.js";
|
|
@@ -21,12 +21,12 @@ export async function getGitHubUsername(): Promise<string | undefined> {
|
|
|
21
21
|
return undefined;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const hostsPathExists = await
|
|
24
|
+
const hostsPathExists = await isFile(githubCLIHostsPath);
|
|
25
25
|
if (!hostsPathExists) {
|
|
26
26
|
return undefined;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const configYAMLRaw = await
|
|
29
|
+
const configYAMLRaw = await readFile(githubCLIHostsPath);
|
|
30
30
|
const configYAML = yaml.parse(configYAMLRaw) as GitHubCLIHostsYAML;
|
|
31
31
|
|
|
32
32
|
const githubCom = configYAML["github.com"];
|