create-stardrive 1.0.0 → 1.0.2
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/bin/index.js +132 -21
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -3,12 +3,50 @@
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import os from "node:os";
|
|
6
|
+
import readline from "node:readline/promises";
|
|
7
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
6
8
|
import { execSync, spawnSync } from "node:child_process";
|
|
7
9
|
|
|
8
10
|
const args = process.argv.slice(2);
|
|
9
11
|
|
|
10
12
|
const skipInstall = args.includes("--no-install");
|
|
11
13
|
|
|
14
|
+
//
|
|
15
|
+
// Pretty logging helpers
|
|
16
|
+
//
|
|
17
|
+
|
|
18
|
+
const supportsColor =
|
|
19
|
+
output.isTTY && process.env.TERM !== "dumb" && !process.env.NO_COLOR;
|
|
20
|
+
|
|
21
|
+
const paint = (code, text) =>
|
|
22
|
+
supportsColor ? `\x1b[${code}m${text}\x1b[0m` : text;
|
|
23
|
+
|
|
24
|
+
const c = {
|
|
25
|
+
dim: (t) => paint("2", t),
|
|
26
|
+
bold: (t) => paint("1", t),
|
|
27
|
+
cyan: (t) => paint("36", t),
|
|
28
|
+
magenta: (t) => paint("35", t),
|
|
29
|
+
green: (t) => paint("32", t),
|
|
30
|
+
yellow: (t) => paint("33", t),
|
|
31
|
+
red: (t) => paint("31", t),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const banner = `
|
|
35
|
+
${c.magenta("★")} ${c.bold(c.cyan("Stardrive Launchpad"))} ${c.magenta("★")}
|
|
36
|
+
${c.dim("Fueling your next Astro project...")}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
let stepNum = 0;
|
|
40
|
+
const step = (msg) =>
|
|
41
|
+
console.log(`\n${c.cyan(`[${++stepNum}]`)} ${c.bold(msg)}`);
|
|
42
|
+
const info = (msg) => console.log(` ${c.dim(msg)}`);
|
|
43
|
+
const ok = (msg) => console.log(` ${c.green("✓")} ${msg}`);
|
|
44
|
+
const fail = (msg) => console.error(`\n${c.red("✗")} ${msg}\n`);
|
|
45
|
+
|
|
46
|
+
//
|
|
47
|
+
// Argument parsing
|
|
48
|
+
//
|
|
49
|
+
|
|
12
50
|
function parseFlag(name) {
|
|
13
51
|
const eqIndex = args.findIndex((a) => a.startsWith(`${name}=`));
|
|
14
52
|
|
|
@@ -34,9 +72,6 @@ const positional = args.filter((a, i) => {
|
|
|
34
72
|
return true;
|
|
35
73
|
});
|
|
36
74
|
|
|
37
|
-
const projectName = positional[0] || "my-stardrive";
|
|
38
|
-
const targetDir = path.resolve(projectName);
|
|
39
|
-
|
|
40
75
|
function detectPackageManager() {
|
|
41
76
|
const ua = process.env.npm_config_user_agent || "";
|
|
42
77
|
|
|
@@ -56,17 +91,72 @@ function commandExists(cmd) {
|
|
|
56
91
|
const pm = detectPackageManager();
|
|
57
92
|
|
|
58
93
|
if (!commandExists(pm)) {
|
|
59
|
-
|
|
94
|
+
fail(`${pm} is not installed`);
|
|
60
95
|
process.exit(1);
|
|
61
96
|
}
|
|
62
97
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
98
|
+
//
|
|
99
|
+
// Project name (interactive if not provided)
|
|
100
|
+
//
|
|
101
|
+
|
|
102
|
+
function isValidProjectName(name) {
|
|
103
|
+
return /^[a-z0-9._-]+$/i.test(name) && !/^[._]/.test(name);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function askProjectName(initial) {
|
|
107
|
+
if (initial && isValidProjectName(initial)) {
|
|
108
|
+
const targetDir = path.resolve(initial);
|
|
109
|
+
if (!fs.existsSync(targetDir)) return initial;
|
|
110
|
+
fail(`Directory "${initial}" already exists.`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!input.isTTY) {
|
|
114
|
+
fail(
|
|
115
|
+
`Project name "${initial || ""}" is missing or invalid and stdin is not interactive.`
|
|
116
|
+
);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const rl = readline.createInterface({ input, output });
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
while (true) {
|
|
124
|
+
const answer = (
|
|
125
|
+
await rl.question(
|
|
126
|
+
`${c.cyan("?")} ${c.bold("Project name:")} ${c.dim("(my-stardrive) ")}`
|
|
127
|
+
)
|
|
128
|
+
).trim();
|
|
129
|
+
|
|
130
|
+
const name = answer || "my-stardrive";
|
|
131
|
+
|
|
132
|
+
if (!isValidProjectName(name)) {
|
|
133
|
+
console.log(
|
|
134
|
+
` ${c.yellow("!")} Use letters, digits, dots, dashes or underscores.`
|
|
135
|
+
);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const targetDir = path.resolve(name);
|
|
140
|
+
|
|
141
|
+
if (fs.existsSync(targetDir)) {
|
|
142
|
+
console.log(` ${c.yellow("!")} "${name}" already exists. Try another.`);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return name;
|
|
147
|
+
}
|
|
148
|
+
} finally {
|
|
149
|
+
rl.close();
|
|
150
|
+
}
|
|
66
151
|
}
|
|
67
152
|
|
|
153
|
+
console.log(banner);
|
|
154
|
+
|
|
155
|
+
const projectName = await askProjectName(positional[0]);
|
|
156
|
+
const targetDir = path.resolve(projectName);
|
|
157
|
+
|
|
68
158
|
//
|
|
69
|
-
//
|
|
159
|
+
// Resolve which tag to clone
|
|
70
160
|
//
|
|
71
161
|
|
|
72
162
|
const repo = "https://github.com/Peltmonger/stardrive.git";
|
|
@@ -102,7 +192,7 @@ function resolveTag() {
|
|
|
102
192
|
const wanted = normalizeTag(requestedVersion);
|
|
103
193
|
|
|
104
194
|
if (!tags.includes(wanted)) {
|
|
105
|
-
|
|
195
|
+
fail(`Version "${requestedVersion}" not found in ${repo}`);
|
|
106
196
|
process.exit(1);
|
|
107
197
|
}
|
|
108
198
|
|
|
@@ -112,20 +202,30 @@ function resolveTag() {
|
|
|
112
202
|
const stable = tags.filter((t) => /^v?\d+\.\d+\.\d+$/.test(t));
|
|
113
203
|
|
|
114
204
|
if (stable.length === 0) {
|
|
115
|
-
|
|
205
|
+
fail(`No tagged releases found in ${repo}`);
|
|
116
206
|
process.exit(1);
|
|
117
207
|
}
|
|
118
208
|
|
|
119
209
|
return stable.sort(compareSemver).pop();
|
|
120
210
|
}
|
|
121
211
|
|
|
212
|
+
step("Locating the latest Stardrive release");
|
|
122
213
|
const tag = resolveTag();
|
|
214
|
+
ok(`Selected ${c.bold(tag)}`);
|
|
123
215
|
|
|
124
|
-
|
|
216
|
+
//
|
|
217
|
+
// Clone
|
|
218
|
+
//
|
|
125
219
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
220
|
+
step(`Beaming ${c.bold(tag)} down from orbit`);
|
|
221
|
+
info(repo);
|
|
222
|
+
|
|
223
|
+
execSync(
|
|
224
|
+
`git -c advice.detachedHead=false clone --depth=1 --branch ${tag} --quiet ${repo} "${tempDir}"`,
|
|
225
|
+
{
|
|
226
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
227
|
+
}
|
|
228
|
+
);
|
|
129
229
|
|
|
130
230
|
fs.rmSync(path.join(tempDir, ".git"), {
|
|
131
231
|
recursive: true,
|
|
@@ -135,11 +235,14 @@ fs.rmSync(path.join(tempDir, ".git"), {
|
|
|
135
235
|
fs.cpSync(tempDir, targetDir, {
|
|
136
236
|
recursive: true,
|
|
137
237
|
});
|
|
238
|
+
ok(`Landed in ${c.bold(projectName)}/`);
|
|
138
239
|
|
|
139
240
|
//
|
|
140
|
-
//
|
|
241
|
+
// Trim files not needed in the generated project
|
|
141
242
|
//
|
|
142
243
|
|
|
244
|
+
step("Trimming unused boosters");
|
|
245
|
+
|
|
143
246
|
[
|
|
144
247
|
"scripts/syncVersion.js",
|
|
145
248
|
"SECURITY.md",
|
|
@@ -165,11 +268,14 @@ fs.cpSync(tempDir, targetDir, {
|
|
|
165
268
|
force: true,
|
|
166
269
|
});
|
|
167
270
|
});
|
|
271
|
+
ok("Stripped extras and stale lockfiles");
|
|
168
272
|
|
|
169
273
|
//
|
|
170
274
|
// Update package.json
|
|
171
275
|
//
|
|
172
276
|
|
|
277
|
+
step("Calibrating package.json");
|
|
278
|
+
|
|
173
279
|
const packageJsonPath = path.join(targetDir, "package.json");
|
|
174
280
|
|
|
175
281
|
const pkg = JSON.parse(
|
|
@@ -199,22 +305,27 @@ fs.writeFileSync(
|
|
|
199
305
|
packageJsonPath,
|
|
200
306
|
JSON.stringify(pkg, null, 2)
|
|
201
307
|
);
|
|
308
|
+
ok(`Named your ship ${c.bold(projectName)}`);
|
|
202
309
|
|
|
203
310
|
//
|
|
204
311
|
// Install dependencies
|
|
205
312
|
//
|
|
206
313
|
|
|
207
314
|
if (!skipInstall) {
|
|
208
|
-
|
|
315
|
+
step(`Loading dependencies with ${c.bold(pm)}`);
|
|
209
316
|
|
|
210
317
|
execSync(`${pm} install`, {
|
|
211
318
|
cwd: targetDir,
|
|
212
319
|
stdio: "inherit",
|
|
213
320
|
});
|
|
321
|
+
ok("Engines online");
|
|
322
|
+
} else {
|
|
323
|
+
step("Skipping dependency install");
|
|
324
|
+
info(`Run "${pm} install" inside ${projectName}/ when you're ready.`);
|
|
214
325
|
}
|
|
215
326
|
|
|
216
327
|
//
|
|
217
|
-
//
|
|
328
|
+
// Lift off
|
|
218
329
|
//
|
|
219
330
|
|
|
220
331
|
const devCommands = {
|
|
@@ -225,10 +336,10 @@ const devCommands = {
|
|
|
225
336
|
};
|
|
226
337
|
|
|
227
338
|
console.log(`
|
|
228
|
-
|
|
339
|
+
${c.green("All systems go.")} ${c.dim("Pre-flight checklist complete.")}
|
|
229
340
|
|
|
230
|
-
|
|
341
|
+
${c.dim("$")} ${c.cyan(`cd ${projectName}`)}
|
|
342
|
+
${c.dim("$")} ${c.cyan(devCommands[pm])}
|
|
231
343
|
|
|
232
|
-
|
|
233
|
-
${devCommands[pm]}
|
|
344
|
+
${c.bold("Happy launching!")} ${c.magenta("🚀")}
|
|
234
345
|
`);
|