complete-cli 1.0.26 → 1.0.27
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/PublishCommand.js +3 -4
- package/dist/commands/init/createProject.js +35 -2
- package/dist/commands/init/lockedDependencies.js +8 -0
- package/dist/constants.js +1 -1
- package/file-templates/dynamic/package.json +1 -1
- package/file-templates/static/.github/workflows/ci.yml +12 -0
- package/package.json +2 -2
- package/src/commands/PublishCommand.ts +7 -5
- package/src/commands/init/createProject.ts +43 -1
- package/src/commands/init/lockedDependencies.ts +15 -0
- package/src/constants.ts +1 -1
- package/file-templates/static/package-metadata.json +0 -8
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command, Option } from "clipanion";
|
|
2
2
|
import { isSemanticVersion } from "complete-common";
|
|
3
|
-
import { $, fatalError,
|
|
3
|
+
import { $, fatalError, getPackageJSONFieldsMandatory, getPackageManagerInstallCommand, getPackageManagerLockFileName, getPackageManagersForProject, isFileAsync, isGitRepository, isGitRepositoryClean, isLoggedInToNPM, readFile, updatePackageJSONDependencies, writeFileAsync, } from "complete-node";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { CWD, DEFAULT_PACKAGE_MANAGER } from "../constants.js";
|
|
6
6
|
export class PublishCommand extends Command {
|
|
@@ -140,8 +140,7 @@ async function tryRunNPMScript(scriptName) {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
async function publish(dryRun) {
|
|
143
|
-
const
|
|
144
|
-
const version = getPackageJSONVersion(undefined);
|
|
143
|
+
const { name, version } = await getPackageJSONFieldsMandatory(undefined, "name", "version");
|
|
145
144
|
if (dryRun) {
|
|
146
145
|
await $ `git reset --hard`; // Revert the version changes.
|
|
147
146
|
}
|
|
@@ -155,7 +154,7 @@ async function publish(dryRun) {
|
|
|
155
154
|
await $ `npm publish --access=public --ignore-scripts`;
|
|
156
155
|
}
|
|
157
156
|
const dryRunSuffix = dryRun ? " (dry-run)" : "";
|
|
158
|
-
console.log(`Published ${
|
|
157
|
+
console.log(`Published ${name} version ${version} successfully${dryRunSuffix}.`);
|
|
159
158
|
}
|
|
160
159
|
function getReleaseGitCommitMessage(version) {
|
|
161
160
|
return `chore: release ${version}`;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import { repeat } from "complete-common";
|
|
3
|
-
import { $q, copyFileOrDirectory, getFileNamesInDirectory, getPackageManagerInstallCICommand, getPackageManagerInstallCommand, isFile, makeDirectory, readFile, renameFile, updatePackageJSONDependencies, writeFile, } from "complete-node";
|
|
2
|
+
import { assertObject, repeat } from "complete-common";
|
|
3
|
+
import { $q, copyFileOrDirectory, formatWithPrettier, getFileNamesInDirectory, getPackageJSON, getPackageManagerInstallCICommand, getPackageManagerInstallCommand, isFile, makeDirectory, readFile, renameFile, updatePackageJSONDependencies, writeFile, writeFileAsync, } from "complete-node";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { ACTION_YML, ACTION_YML_TEMPLATE_PATH, TEMPLATES_DYNAMIC_DIR, TEMPLATES_STATIC_DIR, } from "../../constants.js";
|
|
6
6
|
import { initGitRepository } from "../../git.js";
|
|
7
7
|
import { promptError, promptLog, promptSpinnerStart } from "../../prompt.js";
|
|
8
|
+
import { LOCKED_DEPENDENCIES } from "./lockedDependencies.js";
|
|
8
9
|
export async function createProject(projectName, authorName, projectPath, createNewDir, gitRemoteURL, skipInstall, packageManager) {
|
|
9
10
|
if (createNewDir) {
|
|
10
11
|
makeDirectory(projectPath);
|
|
@@ -16,6 +17,11 @@ export async function createProject(projectName, authorName, projectPath, create
|
|
|
16
17
|
if (!updated) {
|
|
17
18
|
promptError('Failed to update the dependencies in the "package.json" file.');
|
|
18
19
|
}
|
|
20
|
+
// There may be one or more dependencies that should not be updated to the latest version.
|
|
21
|
+
if (LOCKED_DEPENDENCIES.length > 0) {
|
|
22
|
+
await revertVersionsInPackageJSON(projectPath);
|
|
23
|
+
await createPackageMetadataJSON(projectPath);
|
|
24
|
+
}
|
|
19
25
|
await installNodeModules(projectPath, skipInstall, packageManager);
|
|
20
26
|
await formatFiles(projectPath);
|
|
21
27
|
// Only make the initial commit once all of the files have been copied and formatted.
|
|
@@ -107,6 +113,33 @@ function copyDynamicFiles(projectName, authorName, projectPath, packageManager)
|
|
|
107
113
|
const srcPath = path.join(projectPath, "src");
|
|
108
114
|
makeDirectory(srcPath);
|
|
109
115
|
}
|
|
116
|
+
async function revertVersionsInPackageJSON(projectPath) {
|
|
117
|
+
const packageJSONPath = path.join(projectPath, "package.json");
|
|
118
|
+
const packageJSON = await getPackageJSON(packageJSONPath);
|
|
119
|
+
const { devDependencies } = packageJSON;
|
|
120
|
+
assertObject(devDependencies, 'The "devDependencies" in the "package.json" file was not an object.');
|
|
121
|
+
for (const { name, version } of LOCKED_DEPENDENCIES) {
|
|
122
|
+
devDependencies[name] = version;
|
|
123
|
+
}
|
|
124
|
+
const packageJSONText = JSON.stringify(packageJSON);
|
|
125
|
+
await formatWithPrettier(packageJSONText, "json", projectPath);
|
|
126
|
+
await writeFileAsync(packageJSONPath, packageJSONText);
|
|
127
|
+
}
|
|
128
|
+
async function createPackageMetadataJSON(projectPath) {
|
|
129
|
+
const packageMetadata = {
|
|
130
|
+
devDependencies: {},
|
|
131
|
+
};
|
|
132
|
+
for (const { name, reason } of LOCKED_DEPENDENCIES) {
|
|
133
|
+
packageMetadata.devDependencies[name] = {
|
|
134
|
+
"lock-version": true,
|
|
135
|
+
"lock-reason": reason,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const packageMetadataText = JSON.stringify(packageMetadata);
|
|
139
|
+
await formatWithPrettier(packageMetadataText, "json", projectPath);
|
|
140
|
+
const packageMetadataPath = path.join(projectPath, "package-metadata.json");
|
|
141
|
+
await writeFileAsync(packageMetadataPath, packageMetadataText);
|
|
142
|
+
}
|
|
110
143
|
async function installNodeModules(projectPath, skipInstall, packageManager) {
|
|
111
144
|
if (skipInstall) {
|
|
112
145
|
return;
|
package/dist/constants.js
CHANGED
|
@@ -5,7 +5,7 @@ export const CWD = process.cwd();
|
|
|
5
5
|
export const CURRENT_DIRECTORY_NAME = path.basename(CWD);
|
|
6
6
|
export const HOME_DIR = os.homedir();
|
|
7
7
|
const packageRoot = findPackageRoot();
|
|
8
|
-
const { name, version } = getPackageJSONFieldsMandatory(packageRoot, "name", "version");
|
|
8
|
+
const { name, version } = await getPackageJSONFieldsMandatory(packageRoot, "name", "version");
|
|
9
9
|
export const PROJECT_NAME = name;
|
|
10
10
|
export const PROJECT_VERSION = version;
|
|
11
11
|
export const DEFAULT_PACKAGE_MANAGER = PackageManager.npm;
|
|
@@ -16,3 +16,15 @@ jobs:
|
|
|
16
16
|
- uses: actions/checkout@v4
|
|
17
17
|
- uses: ./.github/workflows/setup
|
|
18
18
|
- run: npm run lint
|
|
19
|
+
|
|
20
|
+
discord:
|
|
21
|
+
name: Discord Failure Notification
|
|
22
|
+
needs: [build, lint]
|
|
23
|
+
if: failure()
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- uses: sarisia/actions-status-discord@v1
|
|
27
|
+
with:
|
|
28
|
+
webhook: ${{ secrets.DISCORD_WEBHOOK }}
|
|
29
|
+
status: failure
|
|
30
|
+
title: ""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "complete-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.27",
|
|
4
4
|
"description": "A command line tool for bootstrapping TypeScript projects.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"chalk": "5.4.1",
|
|
39
39
|
"clipanion": "4.0.0-rc.4",
|
|
40
40
|
"complete-common": "1.3.0",
|
|
41
|
-
"complete-node": "
|
|
41
|
+
"complete-node": "4.0.1",
|
|
42
42
|
"klaw-sync": "6.0.0",
|
|
43
43
|
"yaml": "2.7.0"
|
|
44
44
|
},
|
|
@@ -4,8 +4,7 @@ import type { PackageManager } from "complete-node";
|
|
|
4
4
|
import {
|
|
5
5
|
$,
|
|
6
6
|
fatalError,
|
|
7
|
-
|
|
8
|
-
getPackageJSONVersion,
|
|
7
|
+
getPackageJSONFieldsMandatory,
|
|
9
8
|
getPackageManagerInstallCommand,
|
|
10
9
|
getPackageManagerLockFileName,
|
|
11
10
|
getPackageManagersForProject,
|
|
@@ -218,8 +217,11 @@ async function tryRunNPMScript(scriptName: string) {
|
|
|
218
217
|
}
|
|
219
218
|
|
|
220
219
|
async function publish(dryRun: boolean) {
|
|
221
|
-
const
|
|
222
|
-
|
|
220
|
+
const { name, version } = await getPackageJSONFieldsMandatory(
|
|
221
|
+
undefined,
|
|
222
|
+
"name",
|
|
223
|
+
"version",
|
|
224
|
+
);
|
|
223
225
|
|
|
224
226
|
if (dryRun) {
|
|
225
227
|
await $`git reset --hard`; // Revert the version changes.
|
|
@@ -236,7 +238,7 @@ async function publish(dryRun: boolean) {
|
|
|
236
238
|
|
|
237
239
|
const dryRunSuffix = dryRun ? " (dry-run)" : "";
|
|
238
240
|
console.log(
|
|
239
|
-
`Published ${
|
|
241
|
+
`Published ${name} version ${version} successfully${dryRunSuffix}.`,
|
|
240
242
|
);
|
|
241
243
|
}
|
|
242
244
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import { repeat } from "complete-common";
|
|
2
|
+
import { assertObject, repeat } from "complete-common";
|
|
3
3
|
import type { PackageManager } from "complete-node";
|
|
4
4
|
import {
|
|
5
5
|
$q,
|
|
6
6
|
copyFileOrDirectory,
|
|
7
|
+
formatWithPrettier,
|
|
7
8
|
getFileNamesInDirectory,
|
|
9
|
+
getPackageJSON,
|
|
8
10
|
getPackageManagerInstallCICommand,
|
|
9
11
|
getPackageManagerInstallCommand,
|
|
10
12
|
isFile,
|
|
@@ -13,6 +15,7 @@ import {
|
|
|
13
15
|
renameFile,
|
|
14
16
|
updatePackageJSONDependencies,
|
|
15
17
|
writeFile,
|
|
18
|
+
writeFileAsync,
|
|
16
19
|
} from "complete-node";
|
|
17
20
|
import path from "node:path";
|
|
18
21
|
import {
|
|
@@ -23,6 +26,7 @@ import {
|
|
|
23
26
|
} from "../../constants.js";
|
|
24
27
|
import { initGitRepository } from "../../git.js";
|
|
25
28
|
import { promptError, promptLog, promptSpinnerStart } from "../../prompt.js";
|
|
29
|
+
import { LOCKED_DEPENDENCIES } from "./lockedDependencies.js";
|
|
26
30
|
|
|
27
31
|
export async function createProject(
|
|
28
32
|
projectName: string,
|
|
@@ -48,6 +52,12 @@ export async function createProject(
|
|
|
48
52
|
);
|
|
49
53
|
}
|
|
50
54
|
|
|
55
|
+
// There may be one or more dependencies that should not be updated to the latest version.
|
|
56
|
+
if (LOCKED_DEPENDENCIES.length > 0) {
|
|
57
|
+
await revertVersionsInPackageJSON(projectPath);
|
|
58
|
+
await createPackageMetadataJSON(projectPath);
|
|
59
|
+
}
|
|
60
|
+
|
|
51
61
|
await installNodeModules(projectPath, skipInstall, packageManager);
|
|
52
62
|
await formatFiles(projectPath);
|
|
53
63
|
|
|
@@ -173,6 +183,38 @@ function copyDynamicFiles(
|
|
|
173
183
|
makeDirectory(srcPath);
|
|
174
184
|
}
|
|
175
185
|
|
|
186
|
+
async function revertVersionsInPackageJSON(projectPath: string) {
|
|
187
|
+
const packageJSONPath = path.join(projectPath, "package.json");
|
|
188
|
+
const packageJSON = await getPackageJSON(packageJSONPath);
|
|
189
|
+
const { devDependencies } = packageJSON;
|
|
190
|
+
assertObject(
|
|
191
|
+
devDependencies,
|
|
192
|
+
'The "devDependencies" in the "package.json" file was not an object.',
|
|
193
|
+
);
|
|
194
|
+
for (const { name, version } of LOCKED_DEPENDENCIES) {
|
|
195
|
+
devDependencies[name] = version;
|
|
196
|
+
}
|
|
197
|
+
const packageJSONText = JSON.stringify(packageJSON);
|
|
198
|
+
await formatWithPrettier(packageJSONText, "json", projectPath);
|
|
199
|
+
await writeFileAsync(packageJSONPath, packageJSONText);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function createPackageMetadataJSON(projectPath: string) {
|
|
203
|
+
const packageMetadata = {
|
|
204
|
+
devDependencies: {} as Record<string, unknown>,
|
|
205
|
+
};
|
|
206
|
+
for (const { name, reason } of LOCKED_DEPENDENCIES) {
|
|
207
|
+
packageMetadata.devDependencies[name] = {
|
|
208
|
+
"lock-version": true,
|
|
209
|
+
"lock-reason": reason,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const packageMetadataText = JSON.stringify(packageMetadata);
|
|
213
|
+
await formatWithPrettier(packageMetadataText, "json", projectPath);
|
|
214
|
+
const packageMetadataPath = path.join(projectPath, "package-metadata.json");
|
|
215
|
+
await writeFileAsync(packageMetadataPath, packageMetadataText);
|
|
216
|
+
}
|
|
217
|
+
|
|
176
218
|
async function installNodeModules(
|
|
177
219
|
projectPath: string,
|
|
178
220
|
skipInstall: boolean,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface LockedDependency {
|
|
2
|
+
name: string;
|
|
3
|
+
version: string;
|
|
4
|
+
reason: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line complete/require-capital-const-assertions
|
|
8
|
+
export const LOCKED_DEPENDENCIES: readonly LockedDependency[] = [
|
|
9
|
+
{
|
|
10
|
+
name: "typescript",
|
|
11
|
+
version: "5.7.3",
|
|
12
|
+
reason:
|
|
13
|
+
"https://github.com/typescript-eslint/typescript-eslint/issues/10884",
|
|
14
|
+
},
|
|
15
|
+
];
|
package/src/constants.ts
CHANGED
|
@@ -12,7 +12,7 @@ export const CURRENT_DIRECTORY_NAME = path.basename(CWD);
|
|
|
12
12
|
export const HOME_DIR = os.homedir();
|
|
13
13
|
|
|
14
14
|
const packageRoot = findPackageRoot();
|
|
15
|
-
const { name, version } = getPackageJSONFieldsMandatory(
|
|
15
|
+
const { name, version } = await getPackageJSONFieldsMandatory(
|
|
16
16
|
packageRoot,
|
|
17
17
|
"name",
|
|
18
18
|
"version",
|