complete-cli 1.0.8 → 1.0.9

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,7 @@
1
1
  import chalk from "chalk";
2
2
  import { Command, Option } from "clipanion";
3
3
  import { ReadonlySet } from "complete-common";
4
- import { $, deleteFileOrDirectory, fatalError, isDirectory, isFile, readFile, writeFile, } from "complete-node";
4
+ import { $, deleteFileOrDirectoryAsync, fatalError, isDirectory, isFileAsync, readFile, readFileAsync, writeFileAsync, } from "complete-node";
5
5
  import klawSync from "klaw-sync";
6
6
  import path from "node:path";
7
7
  import { ACTION_YML, ACTION_YML_TEMPLATE_PATH, CWD, TEMPLATES_DYNAMIC_DIR, TEMPLATES_STATIC_DIR, } from "../constants.js";
@@ -18,18 +18,19 @@ export class CheckCommand extends Command {
18
18
  static usage = Command.Usage({
19
19
  description: "Check the template files of the current TypeScript project to see if they are up to date.",
20
20
  });
21
- // eslint-disable-next-line @typescript-eslint/require-await
22
21
  async execute() {
23
22
  let oneOrMoreErrors = false;
24
23
  const ignore = this.ignore ?? "";
25
24
  const ignoreFileNames = ignore.split(",");
26
25
  const ignoreFileNamesSet = new ReadonlySet(ignoreFileNames);
27
26
  // First, check the static files.
28
- if (checkTemplateDirectory(TEMPLATES_STATIC_DIR, ignoreFileNamesSet, this.verbose)) {
27
+ const staticTemplatesValid = await checkTemplateDirectory(TEMPLATES_STATIC_DIR, ignoreFileNamesSet, this.verbose);
28
+ if (!staticTemplatesValid) {
29
29
  oneOrMoreErrors = true;
30
30
  }
31
31
  // Second, check dynamic files that require specific logic.
32
- if (checkIndividualFiles(ignoreFileNamesSet, this.verbose)) {
32
+ const dynamicFilesValid = await checkDynamicFiles(ignoreFileNamesSet, this.verbose);
33
+ if (!dynamicFilesValid) {
33
34
  oneOrMoreErrors = true;
34
35
  }
35
36
  if (oneOrMoreErrors) {
@@ -37,7 +38,8 @@ export class CheckCommand extends Command {
37
38
  }
38
39
  }
39
40
  }
40
- function checkTemplateDirectory(templateDirectory, ignoreFileNamesSet, verbose) {
41
+ /** @returns Whether the directory was valid. */
42
+ async function checkTemplateDirectory(templateDirectory, ignoreFileNamesSet, verbose) {
41
43
  let oneOrMoreErrors = false;
42
44
  for (const klawItem of klawSync(templateDirectory)) {
43
45
  const templateFilePath = klawItem.path;
@@ -68,33 +70,38 @@ function checkTemplateDirectory(templateDirectory, ignoreFileNamesSet, verbose)
68
70
  if (ignoreFileNamesSet.has(projectFileName)) {
69
71
  continue;
70
72
  }
71
- if (!compareTextFiles(projectFilePath, templateFilePath, verbose)) {
73
+ // eslint-disable-next-line no-await-in-loop
74
+ const fileValid = await compareTextFiles(projectFilePath, templateFilePath, verbose);
75
+ if (!fileValid) {
72
76
  oneOrMoreErrors = true;
73
77
  }
74
78
  }
75
- return oneOrMoreErrors;
79
+ return !oneOrMoreErrors;
76
80
  }
77
- function checkIndividualFiles(ignoreFileNamesSet, verbose) {
81
+ /** @returns Whether the dynamic files were valid. */
82
+ async function checkDynamicFiles(ignoreFileNamesSet, verbose) {
78
83
  let oneOrMoreErrors = false;
79
84
  if (!ignoreFileNamesSet.has(ACTION_YML)) {
80
85
  const templateFilePath = ACTION_YML_TEMPLATE_PATH;
81
86
  const relativeTemplateFilePath = path.relative(TEMPLATES_DYNAMIC_DIR, templateFilePath);
82
87
  const projectFilePath = path.join(CWD, relativeTemplateFilePath);
83
- if (!compareTextFiles(projectFilePath, templateFilePath, verbose)) {
88
+ const fileValid = await compareTextFiles(projectFilePath, templateFilePath, verbose);
89
+ if (!fileValid) {
84
90
  oneOrMoreErrors = true;
85
91
  }
86
92
  }
87
- return oneOrMoreErrors;
93
+ return !oneOrMoreErrors;
88
94
  }
89
95
  /** @returns Whether the project file is valid in reference to the template file. */
90
- function compareTextFiles(projectFilePath, templateFilePath, verbose) {
91
- if (!isFile(projectFilePath)) {
96
+ async function compareTextFiles(projectFilePath, templateFilePath, verbose) {
97
+ const fileExists = await isFileAsync(projectFilePath);
98
+ if (!fileExists) {
92
99
  console.log(`Failed to find the following file: ${projectFilePath}`);
93
100
  printTemplateLocation(templateFilePath);
94
101
  return false;
95
102
  }
96
- const projectFileObject = getTruncatedFileText(projectFilePath, new Set(), new Set());
97
- const templateFileObject = getTruncatedFileText(templateFilePath, projectFileObject.ignoreLines, projectFileObject.linesBeforeIgnore);
103
+ const projectFileObject = await getTruncatedFileText(projectFilePath, new Set(), new Set());
104
+ const templateFileObject = await getTruncatedFileText(templateFilePath, projectFileObject.ignoreLines, projectFileObject.linesBeforeIgnore);
98
105
  if (projectFileObject.text === templateFileObject.text) {
99
106
  return true;
100
107
  }
@@ -118,16 +125,16 @@ function compareTextFiles(projectFilePath, templateFilePath, verbose) {
118
125
  }
119
126
  const tempProjectFilePath = path.join(CWD, "tempProjectFile.txt");
120
127
  const tempTemplateFilePath = path.join(CWD, "tempTemplateFile.txt");
121
- writeFile(tempProjectFilePath, projectFileObject.text);
122
- writeFile(tempTemplateFilePath, templateFileObject.text);
123
- $.sync `diff ${tempProjectFilePath} ${tempTemplateFilePath} --ignore-blank-lines`;
124
- deleteFileOrDirectory(tempProjectFilePath);
125
- deleteFileOrDirectory(tempTemplateFilePath);
128
+ await writeFileAsync(tempProjectFilePath, projectFileObject.text);
129
+ await writeFileAsync(tempTemplateFilePath, templateFileObject.text);
130
+ await $ `diff ${tempProjectFilePath} ${tempTemplateFilePath} --ignore-blank-lines`;
131
+ await deleteFileOrDirectoryAsync(tempProjectFilePath);
132
+ await deleteFileOrDirectoryAsync(tempTemplateFilePath);
126
133
  return false;
127
134
  }
128
- function getTruncatedFileText(filePath, ignoreLines, linesBeforeIgnore) {
135
+ async function getTruncatedFileText(filePath, ignoreLines, linesBeforeIgnore) {
129
136
  const fileName = path.basename(filePath);
130
- const fileContents = readFile(filePath);
137
+ const fileContents = await readFileAsync(filePath);
131
138
  return getTruncatedText(fileName, fileContents, ignoreLines, linesBeforeIgnore);
132
139
  }
133
140
  function printTemplateLocation(templateFilePath) {
@@ -21,5 +21,5 @@
21
21
  "pnpm-lock.yaml",
22
22
  "yarn.lock",
23
23
  ],
24
- "words": ["dbaeumer", "esbenp", "lockb", "sarisia", "tseslint", "Zamiell"],
24
+ "words": ["dbaeumer", "esbenp", "sarisia", "tseslint", "Zamiell"],
25
25
  }
@@ -34,4 +34,4 @@ tsconfig*.json linguist-language=JSON-with-Comments
34
34
  package-lock.json linguist-generated=true
35
35
  yarn.lock linguist-generated=true
36
36
  pnpm-lock.yaml linguist-generated=true
37
- bun.lockb linguist-generated=true
37
+ bun.lock linguist-generated=true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "complete-cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
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.1.1",
41
- "complete-node": "^3.0.1",
41
+ "complete-node": "^3.1.0",
42
42
  "klaw-sync": "6.0.0",
43
43
  "yaml": "2.7.0"
44
44
  },
@@ -3,12 +3,13 @@ import { Command, Option } from "clipanion";
3
3
  import { ReadonlySet } from "complete-common";
4
4
  import {
5
5
  $,
6
- deleteFileOrDirectory,
6
+ deleteFileOrDirectoryAsync,
7
7
  fatalError,
8
8
  isDirectory,
9
- isFile,
9
+ isFileAsync,
10
10
  readFile,
11
- writeFile,
11
+ readFileAsync,
12
+ writeFileAsync,
12
13
  } from "complete-node";
13
14
  import klawSync from "klaw-sync";
14
15
  import path from "node:path";
@@ -40,7 +41,6 @@ export class CheckCommand extends Command {
40
41
  "Check the template files of the current TypeScript project to see if they are up to date.",
41
42
  });
42
43
 
43
- // eslint-disable-next-line @typescript-eslint/require-await
44
44
  async execute(): Promise<void> {
45
45
  let oneOrMoreErrors = false;
46
46
  const ignore = this.ignore ?? "";
@@ -48,18 +48,21 @@ export class CheckCommand extends Command {
48
48
  const ignoreFileNamesSet = new ReadonlySet(ignoreFileNames);
49
49
 
50
50
  // First, check the static files.
51
- if (
52
- checkTemplateDirectory(
53
- TEMPLATES_STATIC_DIR,
54
- ignoreFileNamesSet,
55
- this.verbose,
56
- )
57
- ) {
51
+ const staticTemplatesValid = await checkTemplateDirectory(
52
+ TEMPLATES_STATIC_DIR,
53
+ ignoreFileNamesSet,
54
+ this.verbose,
55
+ );
56
+ if (!staticTemplatesValid) {
58
57
  oneOrMoreErrors = true;
59
58
  }
60
59
 
61
60
  // Second, check dynamic files that require specific logic.
62
- if (checkIndividualFiles(ignoreFileNamesSet, this.verbose)) {
61
+ const dynamicFilesValid = await checkDynamicFiles(
62
+ ignoreFileNamesSet,
63
+ this.verbose,
64
+ );
65
+ if (!dynamicFilesValid) {
63
66
  oneOrMoreErrors = true;
64
67
  }
65
68
 
@@ -69,11 +72,12 @@ export class CheckCommand extends Command {
69
72
  }
70
73
  }
71
74
 
72
- function checkTemplateDirectory(
75
+ /** @returns Whether the directory was valid. */
76
+ async function checkTemplateDirectory(
73
77
  templateDirectory: string,
74
78
  ignoreFileNamesSet: ReadonlySet<string>,
75
79
  verbose: boolean,
76
- ): boolean {
80
+ ): Promise<boolean> {
77
81
  let oneOrMoreErrors = false;
78
82
 
79
83
  for (const klawItem of klawSync(templateDirectory)) {
@@ -120,15 +124,22 @@ function checkTemplateDirectory(
120
124
  continue;
121
125
  }
122
126
 
123
- if (!compareTextFiles(projectFilePath, templateFilePath, verbose)) {
127
+ // eslint-disable-next-line no-await-in-loop
128
+ const fileValid = await compareTextFiles(
129
+ projectFilePath,
130
+ templateFilePath,
131
+ verbose,
132
+ );
133
+ if (!fileValid) {
124
134
  oneOrMoreErrors = true;
125
135
  }
126
136
  }
127
137
 
128
- return oneOrMoreErrors;
138
+ return !oneOrMoreErrors;
129
139
  }
130
140
 
131
- function checkIndividualFiles(
141
+ /** @returns Whether the dynamic files were valid. */
142
+ async function checkDynamicFiles(
132
143
  ignoreFileNamesSet: ReadonlySet<string>,
133
144
  verbose: boolean,
134
145
  ) {
@@ -141,34 +152,40 @@ function checkIndividualFiles(
141
152
  templateFilePath,
142
153
  );
143
154
  const projectFilePath = path.join(CWD, relativeTemplateFilePath);
144
- if (!compareTextFiles(projectFilePath, templateFilePath, verbose)) {
155
+ const fileValid = await compareTextFiles(
156
+ projectFilePath,
157
+ templateFilePath,
158
+ verbose,
159
+ );
160
+ if (!fileValid) {
145
161
  oneOrMoreErrors = true;
146
162
  }
147
163
  }
148
164
 
149
- return oneOrMoreErrors;
165
+ return !oneOrMoreErrors;
150
166
  }
151
167
 
152
168
  /** @returns Whether the project file is valid in reference to the template file. */
153
- function compareTextFiles(
169
+ async function compareTextFiles(
154
170
  projectFilePath: string,
155
171
  templateFilePath: string,
156
172
  verbose: boolean,
157
- ): boolean {
158
- if (!isFile(projectFilePath)) {
173
+ ): Promise<boolean> {
174
+ const fileExists = await isFileAsync(projectFilePath);
175
+ if (!fileExists) {
159
176
  console.log(`Failed to find the following file: ${projectFilePath}`);
160
177
  printTemplateLocation(templateFilePath);
161
178
 
162
179
  return false;
163
180
  }
164
181
 
165
- const projectFileObject = getTruncatedFileText(
182
+ const projectFileObject = await getTruncatedFileText(
166
183
  projectFilePath,
167
184
  new Set(),
168
185
  new Set(),
169
186
  );
170
187
 
171
- const templateFileObject = getTruncatedFileText(
188
+ const templateFileObject = await getTruncatedFileText(
172
189
  templateFilePath,
173
190
  projectFileObject.ignoreLines,
174
191
  projectFileObject.linesBeforeIgnore,
@@ -206,24 +223,24 @@ function compareTextFiles(
206
223
  const tempProjectFilePath = path.join(CWD, "tempProjectFile.txt");
207
224
  const tempTemplateFilePath = path.join(CWD, "tempTemplateFile.txt");
208
225
 
209
- writeFile(tempProjectFilePath, projectFileObject.text);
210
- writeFile(tempTemplateFilePath, templateFileObject.text);
226
+ await writeFileAsync(tempProjectFilePath, projectFileObject.text);
227
+ await writeFileAsync(tempTemplateFilePath, templateFileObject.text);
211
228
 
212
- $.sync`diff ${tempProjectFilePath} ${tempTemplateFilePath} --ignore-blank-lines`;
229
+ await $`diff ${tempProjectFilePath} ${tempTemplateFilePath} --ignore-blank-lines`;
213
230
 
214
- deleteFileOrDirectory(tempProjectFilePath);
215
- deleteFileOrDirectory(tempTemplateFilePath);
231
+ await deleteFileOrDirectoryAsync(tempProjectFilePath);
232
+ await deleteFileOrDirectoryAsync(tempTemplateFilePath);
216
233
 
217
234
  return false;
218
235
  }
219
236
 
220
- function getTruncatedFileText(
237
+ async function getTruncatedFileText(
221
238
  filePath: string,
222
239
  ignoreLines: ReadonlySet<string>,
223
240
  linesBeforeIgnore: ReadonlySet<string>,
224
241
  ) {
225
242
  const fileName = path.basename(filePath);
226
- const fileContents = readFile(filePath);
243
+ const fileContents = await readFileAsync(filePath);
227
244
 
228
245
  return getTruncatedText(
229
246
  fileName,