@toolstackhq/create-qa-patterns 1.0.1 → 1.0.3
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/README.md +21 -0
- package/index.js +376 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,3 +29,24 @@ create-qa-patterns playwright-template my-project
|
|
|
29
29
|
## Supported templates
|
|
30
30
|
|
|
31
31
|
- `playwright-template`
|
|
32
|
+
|
|
33
|
+
## Interactive flow
|
|
34
|
+
|
|
35
|
+
When run in a terminal, the CLI shows:
|
|
36
|
+
|
|
37
|
+
- a template picker with keyboard selection
|
|
38
|
+
- short template descriptions
|
|
39
|
+
- scaffold progress while files are generated
|
|
40
|
+
- optional post-generate actions for:
|
|
41
|
+
- `npm install`
|
|
42
|
+
- `npx playwright install`
|
|
43
|
+
- `npm test`
|
|
44
|
+
|
|
45
|
+
## Prerequisite checks
|
|
46
|
+
|
|
47
|
+
The CLI checks:
|
|
48
|
+
|
|
49
|
+
- required Node.js version
|
|
50
|
+
- `npm` availability for install and test actions
|
|
51
|
+
- `npx` availability for Playwright browser installation
|
|
52
|
+
- `docker` availability and warns if it is missing
|
package/index.js
CHANGED
|
@@ -2,8 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require("node:fs");
|
|
4
4
|
const path = require("node:path");
|
|
5
|
+
const readline = require("node:readline");
|
|
6
|
+
const { spawn, spawnSync } = require("node:child_process");
|
|
5
7
|
|
|
6
8
|
const DEFAULT_TEMPLATE = "playwright-template";
|
|
9
|
+
const MIN_NODE_VERSION = {
|
|
10
|
+
major: 18,
|
|
11
|
+
minor: 18,
|
|
12
|
+
patch: 0
|
|
13
|
+
};
|
|
7
14
|
const DEFAULT_GITIGNORE = `node_modules/
|
|
8
15
|
|
|
9
16
|
.env
|
|
@@ -16,11 +23,22 @@ allure-report/
|
|
|
16
23
|
test-results/
|
|
17
24
|
playwright-report/
|
|
18
25
|
`;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
]
|
|
26
|
+
|
|
27
|
+
const TEMPLATES = [
|
|
28
|
+
{
|
|
29
|
+
id: DEFAULT_TEMPLATE,
|
|
30
|
+
aliases: ["playwright", "pw"],
|
|
31
|
+
label: "Playwright Template",
|
|
32
|
+
description: "TypeScript starter with page objects, fixtures, multi-environment config, reporting, linting, CI and Docker."
|
|
33
|
+
}
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const TEMPLATE_ALIASES = new Map(
|
|
37
|
+
TEMPLATES.flatMap((template) => [
|
|
38
|
+
[template.id, template.id],
|
|
39
|
+
...template.aliases.map((alias) => [alias, template.id])
|
|
40
|
+
])
|
|
41
|
+
);
|
|
24
42
|
|
|
25
43
|
function printHelp() {
|
|
26
44
|
process.stdout.write(`create-qa-patterns
|
|
@@ -30,6 +48,9 @@ Usage:
|
|
|
30
48
|
create-qa-patterns <target-directory>
|
|
31
49
|
create-qa-patterns <template> [target-directory]
|
|
32
50
|
|
|
51
|
+
Interactive mode:
|
|
52
|
+
When run without an explicit template, the CLI shows an interactive template picker.
|
|
53
|
+
|
|
33
54
|
Supported templates:
|
|
34
55
|
playwright-template
|
|
35
56
|
playwright
|
|
@@ -37,11 +58,209 @@ Supported templates:
|
|
|
37
58
|
`);
|
|
38
59
|
}
|
|
39
60
|
|
|
61
|
+
function parseNodeVersion(version) {
|
|
62
|
+
const normalized = version.replace(/^v/, "");
|
|
63
|
+
const [major = "0", minor = "0", patch = "0"] = normalized.split(".");
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
major: Number.parseInt(major, 10),
|
|
67
|
+
minor: Number.parseInt(minor, 10),
|
|
68
|
+
patch: Number.parseInt(patch, 10)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isNodeVersionSupported(version) {
|
|
73
|
+
if (version.major !== MIN_NODE_VERSION.major) {
|
|
74
|
+
return version.major > MIN_NODE_VERSION.major;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (version.minor !== MIN_NODE_VERSION.minor) {
|
|
78
|
+
return version.minor > MIN_NODE_VERSION.minor;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return version.patch >= MIN_NODE_VERSION.patch;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function assertSupportedNodeVersion() {
|
|
85
|
+
const currentVersion = parseNodeVersion(process.version);
|
|
86
|
+
|
|
87
|
+
if (!isNodeVersionSupported(currentVersion)) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`Node ${MIN_NODE_VERSION.major}.${MIN_NODE_VERSION.minor}.${MIN_NODE_VERSION.patch}+ is required. Current version: ${process.version}`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
40
94
|
function resolveTemplate(value) {
|
|
41
95
|
return TEMPLATE_ALIASES.get(value);
|
|
42
96
|
}
|
|
43
97
|
|
|
44
|
-
function
|
|
98
|
+
function getTemplate(templateId) {
|
|
99
|
+
return TEMPLATES.find((template) => template.id === templateId);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function sleep(ms) {
|
|
103
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function commandExists(command) {
|
|
107
|
+
const result = spawnSync(getCommandName(command), ["--version"], {
|
|
108
|
+
stdio: "ignore"
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return !result.error && result.status === 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function collectPrerequisites() {
|
|
115
|
+
return {
|
|
116
|
+
npm: commandExists("npm"),
|
|
117
|
+
npx: commandExists("npx"),
|
|
118
|
+
docker: commandExists("docker")
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function printPrerequisiteWarnings(prerequisites) {
|
|
123
|
+
if (!prerequisites.npm) {
|
|
124
|
+
process.stdout.write("Warning: npm was not found. Automated install and test steps will be unavailable.\n");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!prerequisites.npx) {
|
|
128
|
+
process.stdout.write("Warning: npx was not found. Playwright browser installation will be unavailable.\n");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!prerequisites.docker) {
|
|
132
|
+
process.stdout.write("Warning: docker was not found. Docker-based template flows will not run until Docker is installed.\n");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!prerequisites.npm || !prerequisites.npx || !prerequisites.docker) {
|
|
136
|
+
process.stdout.write("\n");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function createLineInterface() {
|
|
141
|
+
return readline.createInterface({
|
|
142
|
+
input: process.stdin,
|
|
143
|
+
output: process.stdout
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function askQuestion(prompt) {
|
|
148
|
+
const lineInterface = createLineInterface();
|
|
149
|
+
|
|
150
|
+
return new Promise((resolve) => {
|
|
151
|
+
lineInterface.question(prompt, (answer) => {
|
|
152
|
+
lineInterface.close();
|
|
153
|
+
resolve(answer.trim());
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function askYesNo(prompt, defaultValue = true) {
|
|
159
|
+
const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
|
|
160
|
+
|
|
161
|
+
while (true) {
|
|
162
|
+
const answer = (await askQuestion(`${prompt}${suffix}`)).toLowerCase();
|
|
163
|
+
|
|
164
|
+
if (!answer) {
|
|
165
|
+
return defaultValue;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (["y", "yes"].includes(answer)) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (["n", "no"].includes(answer)) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
process.stdout.write("Please answer yes or no.\n");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function selectTemplateInteractively() {
|
|
181
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
182
|
+
return DEFAULT_TEMPLATE;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
readline.emitKeypressEvents(process.stdin);
|
|
186
|
+
|
|
187
|
+
if (typeof process.stdin.setRawMode === "function") {
|
|
188
|
+
process.stdin.setRawMode(true);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let selectedIndex = 0;
|
|
192
|
+
let renderedLines = 0;
|
|
193
|
+
|
|
194
|
+
const render = () => {
|
|
195
|
+
if (renderedLines > 0) {
|
|
196
|
+
readline.moveCursor(process.stdout, 0, -renderedLines);
|
|
197
|
+
readline.clearScreenDown(process.stdout);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const lines = [
|
|
201
|
+
"Select a template",
|
|
202
|
+
"Use ↑/↓ to choose and press Enter to continue.",
|
|
203
|
+
""
|
|
204
|
+
];
|
|
205
|
+
|
|
206
|
+
for (let index = 0; index < TEMPLATES.length; index += 1) {
|
|
207
|
+
const template = TEMPLATES[index];
|
|
208
|
+
const marker = index === selectedIndex ? ">" : " ";
|
|
209
|
+
lines.push(`${marker} ${template.label}`);
|
|
210
|
+
lines.push(` ${template.description}`);
|
|
211
|
+
lines.push("");
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
renderedLines = lines.length;
|
|
215
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
render();
|
|
219
|
+
|
|
220
|
+
return new Promise((resolve) => {
|
|
221
|
+
const handleKeypress = (_, key) => {
|
|
222
|
+
if (!key) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (key.name === "up") {
|
|
227
|
+
selectedIndex = (selectedIndex - 1 + TEMPLATES.length) % TEMPLATES.length;
|
|
228
|
+
render();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (key.name === "down") {
|
|
233
|
+
selectedIndex = (selectedIndex + 1) % TEMPLATES.length;
|
|
234
|
+
render();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (key.name === "return") {
|
|
239
|
+
process.stdin.off("keypress", handleKeypress);
|
|
240
|
+
if (typeof process.stdin.setRawMode === "function") {
|
|
241
|
+
process.stdin.setRawMode(false);
|
|
242
|
+
}
|
|
243
|
+
readline.clearScreenDown(process.stdout);
|
|
244
|
+
process.stdout.write(`Selected: ${TEMPLATES[selectedIndex].label}\n\n`);
|
|
245
|
+
resolve(TEMPLATES[selectedIndex].id);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (key.ctrl && key.name === "c") {
|
|
250
|
+
process.stdin.off("keypress", handleKeypress);
|
|
251
|
+
if (typeof process.stdin.setRawMode === "function") {
|
|
252
|
+
process.stdin.setRawMode(false);
|
|
253
|
+
}
|
|
254
|
+
process.stdout.write("\n");
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
process.stdin.on("keypress", handleKeypress);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function resolveNonInteractiveArgs(args) {
|
|
45
264
|
if (args.length === 0) {
|
|
46
265
|
return {
|
|
47
266
|
templateName: DEFAULT_TEMPLATE,
|
|
@@ -52,6 +271,7 @@ function resolveScaffoldArgs(args) {
|
|
|
52
271
|
|
|
53
272
|
if (args.length === 1) {
|
|
54
273
|
const templateName = resolveTemplate(args[0]);
|
|
274
|
+
|
|
55
275
|
if (templateName) {
|
|
56
276
|
return {
|
|
57
277
|
templateName,
|
|
@@ -69,6 +289,7 @@ function resolveScaffoldArgs(args) {
|
|
|
69
289
|
|
|
70
290
|
if (args.length === 2) {
|
|
71
291
|
const templateName = resolveTemplate(args[0]);
|
|
292
|
+
|
|
72
293
|
if (!templateName) {
|
|
73
294
|
throw new Error(`Unsupported template "${args[0]}". Use "playwright-template".`);
|
|
74
295
|
}
|
|
@@ -83,6 +304,30 @@ function resolveScaffoldArgs(args) {
|
|
|
83
304
|
throw new Error("Too many arguments. Run `create-qa-patterns --help` for usage.");
|
|
84
305
|
}
|
|
85
306
|
|
|
307
|
+
async function resolveScaffoldArgs(args) {
|
|
308
|
+
const explicitTemplate = args[0] && resolveTemplate(args[0]);
|
|
309
|
+
|
|
310
|
+
if (explicitTemplate) {
|
|
311
|
+
return resolveNonInteractiveArgs(args);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
315
|
+
return resolveNonInteractiveArgs(args);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const templateName = await selectTemplateInteractively();
|
|
319
|
+
const defaultTarget = args[0] ? args[0] : ".";
|
|
320
|
+
const targetAnswer = await askQuestion(`Target directory (${defaultTarget}): `);
|
|
321
|
+
const targetValue = targetAnswer || defaultTarget;
|
|
322
|
+
const targetDirectory = path.resolve(process.cwd(), targetValue);
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
templateName,
|
|
326
|
+
targetDirectory,
|
|
327
|
+
generatedInCurrentDirectory: targetDirectory === process.cwd()
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
86
331
|
function ensureScaffoldTarget(targetDirectory) {
|
|
87
332
|
if (!fs.existsSync(targetDirectory)) {
|
|
88
333
|
fs.mkdirSync(targetDirectory, { recursive: true });
|
|
@@ -148,52 +393,159 @@ function customizeProject(targetDirectory) {
|
|
|
148
393
|
}
|
|
149
394
|
}
|
|
150
395
|
|
|
151
|
-
function
|
|
396
|
+
function renderProgress(completed, total, label) {
|
|
397
|
+
const width = 24;
|
|
398
|
+
const filled = Math.round((completed / total) * width);
|
|
399
|
+
const empty = width - filled;
|
|
400
|
+
const bar = `${"=".repeat(filled)}${" ".repeat(empty)}`;
|
|
401
|
+
const percentage = `${Math.round((completed / total) * 100)}`.padStart(3, " ");
|
|
402
|
+
process.stdout.write(`\r[${bar}] ${percentage}% ${label}`);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
async function scaffoldProject(templateName, targetDirectory) {
|
|
152
406
|
const templateDirectory = path.resolve(__dirname, "templates", templateName);
|
|
153
407
|
|
|
154
408
|
if (!fs.existsSync(templateDirectory)) {
|
|
155
409
|
throw new Error(`Template files are missing for "${templateName}".`);
|
|
156
410
|
}
|
|
157
411
|
|
|
412
|
+
const steps = [
|
|
413
|
+
"Validating target directory",
|
|
414
|
+
"Copying template files",
|
|
415
|
+
"Customizing project files",
|
|
416
|
+
"Finalizing scaffold"
|
|
417
|
+
];
|
|
418
|
+
|
|
419
|
+
renderProgress(0, steps.length, "Preparing scaffold");
|
|
158
420
|
ensureScaffoldTarget(targetDirectory);
|
|
421
|
+
await sleep(60);
|
|
422
|
+
|
|
423
|
+
renderProgress(1, steps.length, steps[0]);
|
|
424
|
+
await sleep(80);
|
|
425
|
+
|
|
159
426
|
fs.cpSync(templateDirectory, targetDirectory, { recursive: true });
|
|
427
|
+
renderProgress(2, steps.length, steps[1]);
|
|
428
|
+
await sleep(80);
|
|
429
|
+
|
|
160
430
|
customizeProject(targetDirectory);
|
|
431
|
+
renderProgress(3, steps.length, steps[2]);
|
|
432
|
+
await sleep(80);
|
|
433
|
+
|
|
434
|
+
renderProgress(4, steps.length, steps[3]);
|
|
435
|
+
await sleep(60);
|
|
436
|
+
process.stdout.write("\n");
|
|
161
437
|
}
|
|
162
438
|
|
|
163
|
-
function
|
|
164
|
-
process.
|
|
439
|
+
function getCommandName(base) {
|
|
440
|
+
if (process.platform === "win32") {
|
|
441
|
+
return `${base}.cmd`;
|
|
442
|
+
}
|
|
165
443
|
|
|
166
|
-
|
|
167
|
-
|
|
444
|
+
return base;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function runCommand(command, args, cwd) {
|
|
448
|
+
return new Promise((resolve, reject) => {
|
|
449
|
+
const child = spawn(getCommandName(command), args, {
|
|
450
|
+
cwd,
|
|
451
|
+
stdio: "inherit"
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
child.on("close", (code) => {
|
|
455
|
+
if (code === 0) {
|
|
456
|
+
resolve();
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
child.on("error", reject);
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function printSuccess(templateName, targetDirectory, generatedInCurrentDirectory) {
|
|
468
|
+
const template = getTemplate(templateName);
|
|
469
|
+
|
|
470
|
+
process.stdout.write(`\nSuccess
|
|
471
|
+
Generated ${template ? template.label : templateName} in ${targetDirectory}
|
|
472
|
+
\n`);
|
|
168
473
|
|
|
169
474
|
if (!generatedInCurrentDirectory) {
|
|
170
|
-
process.stdout.write(` cd ${path.relative(process.cwd(), targetDirectory) || "."}
|
|
171
|
-
`);
|
|
475
|
+
process.stdout.write(`Change directory first:\n cd ${path.relative(process.cwd(), targetDirectory) || "."}\n\n`);
|
|
172
476
|
}
|
|
477
|
+
}
|
|
173
478
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
479
|
+
function printNextSteps(targetDirectory, generatedInCurrentDirectory) {
|
|
480
|
+
process.stdout.write("Next steps:\n");
|
|
481
|
+
|
|
482
|
+
if (!generatedInCurrentDirectory) {
|
|
483
|
+
process.stdout.write(` cd ${path.relative(process.cwd(), targetDirectory) || "."}\n`);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
process.stdout.write(" npm install\n");
|
|
487
|
+
process.stdout.write(" npx playwright install\n");
|
|
488
|
+
process.stdout.write(" npm test\n");
|
|
178
489
|
}
|
|
179
490
|
|
|
180
|
-
function
|
|
491
|
+
async function runPostGenerateActions(targetDirectory) {
|
|
492
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const prerequisites = collectPrerequisites();
|
|
497
|
+
|
|
498
|
+
if (prerequisites.npm) {
|
|
499
|
+
const shouldInstallDependencies = await askYesNo("Run npm install now?", true);
|
|
500
|
+
|
|
501
|
+
if (shouldInstallDependencies) {
|
|
502
|
+
await runCommand("npm", ["install"], targetDirectory);
|
|
503
|
+
}
|
|
504
|
+
} else {
|
|
505
|
+
process.stdout.write("Skipping npm install prompt because npm is not available.\n");
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (prerequisites.npx) {
|
|
509
|
+
const shouldInstallPlaywright = await askYesNo("Run npx playwright install now?", true);
|
|
510
|
+
|
|
511
|
+
if (shouldInstallPlaywright) {
|
|
512
|
+
await runCommand("npx", ["playwright", "install"], targetDirectory);
|
|
513
|
+
}
|
|
514
|
+
} else {
|
|
515
|
+
process.stdout.write("Skipping Playwright browser install prompt because npx is not available.\n");
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
if (prerequisites.npm) {
|
|
519
|
+
const shouldRunTests = await askYesNo("Run npm test now?", false);
|
|
520
|
+
|
|
521
|
+
if (shouldRunTests) {
|
|
522
|
+
await runCommand("npm", ["test"], targetDirectory);
|
|
523
|
+
}
|
|
524
|
+
} else {
|
|
525
|
+
process.stdout.write("Skipping npm test prompt because npm is not available.\n");
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
async function main() {
|
|
181
530
|
const args = process.argv.slice(2);
|
|
182
531
|
|
|
532
|
+
assertSupportedNodeVersion();
|
|
533
|
+
|
|
183
534
|
if (args.includes("--help") || args.includes("-h")) {
|
|
184
535
|
printHelp();
|
|
185
536
|
return;
|
|
186
537
|
}
|
|
187
538
|
|
|
188
|
-
const { templateName, targetDirectory, generatedInCurrentDirectory } = resolveScaffoldArgs(args);
|
|
189
|
-
|
|
539
|
+
const { templateName, targetDirectory, generatedInCurrentDirectory } = await resolveScaffoldArgs(args);
|
|
540
|
+
printPrerequisiteWarnings(collectPrerequisites());
|
|
541
|
+
await scaffoldProject(templateName, targetDirectory);
|
|
542
|
+
printSuccess(templateName, targetDirectory, generatedInCurrentDirectory);
|
|
543
|
+
await runPostGenerateActions(targetDirectory);
|
|
190
544
|
printNextSteps(targetDirectory, generatedInCurrentDirectory);
|
|
191
545
|
}
|
|
192
546
|
|
|
193
|
-
|
|
194
|
-
main();
|
|
195
|
-
} catch (error) {
|
|
547
|
+
main().catch((error) => {
|
|
196
548
|
const message = error instanceof Error ? error.message : String(error);
|
|
197
549
|
process.stderr.write(`${message}\n`);
|
|
198
550
|
process.exit(1);
|
|
199
|
-
}
|
|
551
|
+
});
|