create-astro 2.0.2 → 3.0.1
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 +11 -24
- package/dist/index.js +937 -270
- package/package.json +15 -23
- package/dist/gradient.js +0 -70
- package/dist/logger.js +0 -98
- package/dist/messages.js +0 -134
- package/dist/templates.js +0 -8
- package/dist/types/gradient.d.ts +0 -8
- package/dist/types/index.d.ts +0 -2
- package/dist/types/logger.d.ts +0 -38
- package/dist/types/messages.d.ts +0 -11
- package/dist/types/templates.d.ts +0 -4
package/dist/index.js
CHANGED
|
@@ -1,48 +1,628 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
19
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
20
|
+
mod
|
|
21
|
+
));
|
|
22
|
+
|
|
23
|
+
// ../../node_modules/.pnpm/arg@5.0.2/node_modules/arg/index.js
|
|
24
|
+
var require_arg = __commonJS({
|
|
25
|
+
"../../node_modules/.pnpm/arg@5.0.2/node_modules/arg/index.js"(exports, module) {
|
|
26
|
+
var flagSymbol = Symbol("arg flag");
|
|
27
|
+
var ArgError = class extends Error {
|
|
28
|
+
constructor(msg, code) {
|
|
29
|
+
super(msg);
|
|
30
|
+
this.name = "ArgError";
|
|
31
|
+
this.code = code;
|
|
32
|
+
Object.setPrototypeOf(this, ArgError.prototype);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
function arg2(opts, {
|
|
36
|
+
argv = process.argv.slice(2),
|
|
37
|
+
permissive = false,
|
|
38
|
+
stopAtPositional = false
|
|
39
|
+
} = {}) {
|
|
40
|
+
if (!opts) {
|
|
41
|
+
throw new ArgError(
|
|
42
|
+
"argument specification object is required",
|
|
43
|
+
"ARG_CONFIG_NO_SPEC"
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
const result = { _: [] };
|
|
47
|
+
const aliases = {};
|
|
48
|
+
const handlers = {};
|
|
49
|
+
for (const key of Object.keys(opts)) {
|
|
50
|
+
if (!key) {
|
|
51
|
+
throw new ArgError(
|
|
52
|
+
"argument key cannot be an empty string",
|
|
53
|
+
"ARG_CONFIG_EMPTY_KEY"
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
if (key[0] !== "-") {
|
|
57
|
+
throw new ArgError(
|
|
58
|
+
`argument key must start with '-' but found: '${key}'`,
|
|
59
|
+
"ARG_CONFIG_NONOPT_KEY"
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
if (key.length === 1) {
|
|
63
|
+
throw new ArgError(
|
|
64
|
+
`argument key must have a name; singular '-' keys are not allowed: ${key}`,
|
|
65
|
+
"ARG_CONFIG_NONAME_KEY"
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
if (typeof opts[key] === "string") {
|
|
69
|
+
aliases[key] = opts[key];
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
let type = opts[key];
|
|
73
|
+
let isFlag = false;
|
|
74
|
+
if (Array.isArray(type) && type.length === 1 && typeof type[0] === "function") {
|
|
75
|
+
const [fn] = type;
|
|
76
|
+
type = (value, name, prev = []) => {
|
|
77
|
+
prev.push(fn(value, name, prev[prev.length - 1]));
|
|
78
|
+
return prev;
|
|
79
|
+
};
|
|
80
|
+
isFlag = fn === Boolean || fn[flagSymbol] === true;
|
|
81
|
+
} else if (typeof type === "function") {
|
|
82
|
+
isFlag = type === Boolean || type[flagSymbol] === true;
|
|
83
|
+
} else {
|
|
84
|
+
throw new ArgError(
|
|
85
|
+
`type missing or not a function or valid array type: ${key}`,
|
|
86
|
+
"ARG_CONFIG_VAD_TYPE"
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
if (key[1] !== "-" && key.length > 2) {
|
|
90
|
+
throw new ArgError(
|
|
91
|
+
`short argument keys (with a single hyphen) must have only one character: ${key}`,
|
|
92
|
+
"ARG_CONFIG_SHORTOPT_TOOLONG"
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
handlers[key] = [type, isFlag];
|
|
96
|
+
}
|
|
97
|
+
for (let i = 0, len = argv.length; i < len; i++) {
|
|
98
|
+
const wholeArg = argv[i];
|
|
99
|
+
if (stopAtPositional && result._.length > 0) {
|
|
100
|
+
result._ = result._.concat(argv.slice(i));
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
if (wholeArg === "--") {
|
|
104
|
+
result._ = result._.concat(argv.slice(i + 1));
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
if (wholeArg.length > 1 && wholeArg[0] === "-") {
|
|
108
|
+
const separatedArguments = wholeArg[1] === "-" || wholeArg.length === 2 ? [wholeArg] : wholeArg.slice(1).split("").map((a) => `-${a}`);
|
|
109
|
+
for (let j = 0; j < separatedArguments.length; j++) {
|
|
110
|
+
const arg3 = separatedArguments[j];
|
|
111
|
+
const [originalArgName, argStr] = arg3[1] === "-" ? arg3.split(/=(.*)/, 2) : [arg3, void 0];
|
|
112
|
+
let argName = originalArgName;
|
|
113
|
+
while (argName in aliases) {
|
|
114
|
+
argName = aliases[argName];
|
|
115
|
+
}
|
|
116
|
+
if (!(argName in handlers)) {
|
|
117
|
+
if (permissive) {
|
|
118
|
+
result._.push(arg3);
|
|
119
|
+
continue;
|
|
120
|
+
} else {
|
|
121
|
+
throw new ArgError(
|
|
122
|
+
`unknown or unexpected option: ${originalArgName}`,
|
|
123
|
+
"ARG_UNKNOWN_OPTION"
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const [type, isFlag] = handlers[argName];
|
|
128
|
+
if (!isFlag && j + 1 < separatedArguments.length) {
|
|
129
|
+
throw new ArgError(
|
|
130
|
+
`option requires argument (but was followed by another short argument): ${originalArgName}`,
|
|
131
|
+
"ARG_MISSING_REQUIRED_SHORTARG"
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
if (isFlag) {
|
|
135
|
+
result[argName] = type(true, argName, result[argName]);
|
|
136
|
+
} else if (argStr === void 0) {
|
|
137
|
+
if (argv.length < i + 2 || argv[i + 1].length > 1 && argv[i + 1][0] === "-" && !(argv[i + 1].match(/^-?\d*(\.(?=\d))?\d*$/) && (type === Number || typeof BigInt !== "undefined" && type === BigInt))) {
|
|
138
|
+
const extended = originalArgName === argName ? "" : ` (alias for ${argName})`;
|
|
139
|
+
throw new ArgError(
|
|
140
|
+
`option requires argument: ${originalArgName}${extended}`,
|
|
141
|
+
"ARG_MISSING_REQUIRED_LONGARG"
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
result[argName] = type(argv[i + 1], argName, result[argName]);
|
|
145
|
+
++i;
|
|
146
|
+
} else {
|
|
147
|
+
result[argName] = type(argStr, argName, result[argName]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
result._.push(wholeArg);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
arg2.flag = (fn) => {
|
|
157
|
+
fn[flagSymbol] = true;
|
|
158
|
+
return fn;
|
|
159
|
+
};
|
|
160
|
+
arg2.COUNT = arg2.flag((v2, name, existingCount) => (existingCount || 0) + 1);
|
|
161
|
+
arg2.ArgError = ArgError;
|
|
162
|
+
module.exports = arg2;
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// ../../node_modules/.pnpm/which-pm-runs@1.1.0/node_modules/which-pm-runs/index.js
|
|
167
|
+
var require_which_pm_runs = __commonJS({
|
|
168
|
+
"../../node_modules/.pnpm/which-pm-runs@1.1.0/node_modules/which-pm-runs/index.js"(exports, module) {
|
|
169
|
+
"use strict";
|
|
170
|
+
module.exports = function() {
|
|
171
|
+
if (!process.env.npm_config_user_agent) {
|
|
172
|
+
return void 0;
|
|
173
|
+
}
|
|
174
|
+
return pmFromUserAgent(process.env.npm_config_user_agent);
|
|
175
|
+
};
|
|
176
|
+
function pmFromUserAgent(userAgent) {
|
|
177
|
+
const pmSpec = userAgent.split(" ")[0];
|
|
178
|
+
const separatorPos = pmSpec.lastIndexOf("/");
|
|
179
|
+
const name = pmSpec.substring(0, separatorPos);
|
|
180
|
+
return {
|
|
181
|
+
name: name === "npminstall" ? "cnpm" : name,
|
|
182
|
+
version: pmSpec.substring(separatorPos + 1)
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// src/actions/context.ts
|
|
189
|
+
var import_arg = __toESM(require_arg(), 1);
|
|
190
|
+
var import_which_pm_runs = __toESM(require_which_pm_runs(), 1);
|
|
191
|
+
import { prompt } from "@astrojs/cli-kit";
|
|
192
|
+
import os from "os";
|
|
193
|
+
|
|
194
|
+
// src/messages.ts
|
|
195
|
+
import { color, label, say as houston, spinner as load } from "@astrojs/cli-kit";
|
|
196
|
+
import { align, sleep } from "@astrojs/cli-kit/utils";
|
|
197
|
+
import { exec } from "child_process";
|
|
198
|
+
import { get } from "https";
|
|
199
|
+
|
|
200
|
+
// ../../node_modules/.pnpm/ansi-regex@6.0.1/node_modules/ansi-regex/index.js
|
|
201
|
+
function ansiRegex({ onlyFirst = false } = {}) {
|
|
202
|
+
const pattern = [
|
|
203
|
+
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
|
|
204
|
+
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"
|
|
205
|
+
].join("|");
|
|
206
|
+
return new RegExp(pattern, onlyFirst ? void 0 : "g");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ../../node_modules/.pnpm/strip-ansi@7.0.1/node_modules/strip-ansi/index.js
|
|
210
|
+
function stripAnsi(string) {
|
|
211
|
+
if (typeof string !== "string") {
|
|
212
|
+
throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
|
|
213
|
+
}
|
|
214
|
+
return string.replace(ansiRegex(), "");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// src/messages.ts
|
|
218
|
+
var stdout = process.stdout;
|
|
219
|
+
function setStdout(writable) {
|
|
220
|
+
stdout = writable;
|
|
221
|
+
}
|
|
222
|
+
async function say(messages, { clear = false, hat = "" } = {}) {
|
|
223
|
+
return houston(messages, { clear, hat, stdout });
|
|
224
|
+
}
|
|
225
|
+
async function spinner(args) {
|
|
226
|
+
await load(args, { stdout });
|
|
227
|
+
}
|
|
228
|
+
var title = (text) => align(label(text), "end", 7) + " ";
|
|
229
|
+
var welcome = [
|
|
230
|
+
`Let's claim your corner of the internet.`,
|
|
231
|
+
`I'll be your assistant today.`,
|
|
232
|
+
`Let's build something awesome!`,
|
|
233
|
+
`Let's build something great!`,
|
|
234
|
+
`Let's build something fast!`,
|
|
235
|
+
`Let's build the web we want.`,
|
|
236
|
+
`Let's make the web weird!`,
|
|
237
|
+
`Let's make the web a better place!`,
|
|
238
|
+
`Let's create a new project!`,
|
|
239
|
+
`Let's create something unique!`,
|
|
240
|
+
`Time to build a new website.`,
|
|
241
|
+
`Time to build a faster website.`,
|
|
242
|
+
`Time to build a sweet new website.`,
|
|
243
|
+
`We're glad to have you on board.`,
|
|
244
|
+
`Keeping the internet weird since 2021.`,
|
|
245
|
+
`Initiating launch sequence...`,
|
|
246
|
+
`Initiating launch sequence... right... now!`,
|
|
247
|
+
`Awaiting further instructions.`
|
|
248
|
+
];
|
|
249
|
+
var getName = () => new Promise((resolve) => {
|
|
250
|
+
exec("git config user.name", { encoding: "utf-8" }, (_1, gitName, _2) => {
|
|
251
|
+
if (gitName.trim()) {
|
|
252
|
+
return resolve(gitName.split(" ")[0].trim());
|
|
253
|
+
}
|
|
254
|
+
exec("whoami", { encoding: "utf-8" }, (_3, whoami, _4) => {
|
|
255
|
+
if (whoami.trim()) {
|
|
256
|
+
return resolve(whoami.split(" ")[0].trim());
|
|
257
|
+
}
|
|
258
|
+
return resolve("astronaut");
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
var v;
|
|
263
|
+
var getVersion = () => new Promise((resolve) => {
|
|
264
|
+
if (v)
|
|
265
|
+
return resolve(v);
|
|
266
|
+
get("https://registry.npmjs.org/astro/latest", (res) => {
|
|
267
|
+
let body = "";
|
|
268
|
+
res.on("data", (chunk) => body += chunk);
|
|
269
|
+
res.on("end", () => {
|
|
270
|
+
const { version } = JSON.parse(body);
|
|
271
|
+
v = version;
|
|
272
|
+
resolve(version);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
var log = (message) => stdout.write(message + "\n");
|
|
277
|
+
var banner = async (version) => log(
|
|
278
|
+
`
|
|
279
|
+
${label("astro", color.bgGreen, color.black)} ${color.green(
|
|
280
|
+
color.bold(`v${version}`)
|
|
281
|
+
)} ${color.bold("Launch sequence initiated.")}`
|
|
282
|
+
);
|
|
283
|
+
var info = async (prefix, text) => {
|
|
284
|
+
await sleep(100);
|
|
285
|
+
if (stdout.columns < 80) {
|
|
286
|
+
log(`${" ".repeat(5)} ${color.cyan("\u25FC")} ${color.cyan(prefix)}`);
|
|
287
|
+
log(`${" ".repeat(9)}${color.dim(text)}`);
|
|
288
|
+
} else {
|
|
289
|
+
log(`${" ".repeat(5)} ${color.cyan("\u25FC")} ${color.cyan(prefix)} ${color.dim(text)}`);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
var error = async (prefix, text) => {
|
|
293
|
+
if (stdout.columns < 80) {
|
|
294
|
+
log(`${" ".repeat(5)} ${color.red("\u25B2")} ${color.red(prefix)}`);
|
|
295
|
+
log(`${" ".repeat(9)}${color.dim(text)}`);
|
|
296
|
+
} else {
|
|
297
|
+
log(`${" ".repeat(5)} ${color.red("\u25B2")} ${color.red(prefix)} ${color.dim(text)}`);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
var typescriptByDefault = async () => {
|
|
301
|
+
await info(`No worries!`, "TypeScript is supported in Astro by default,");
|
|
302
|
+
log(`${" ".repeat(9)}${color.dim("but you are free to continue writing JavaScript instead.")}`);
|
|
303
|
+
await sleep(1e3);
|
|
304
|
+
};
|
|
305
|
+
var nextSteps = async ({ projectDir, devCmd }) => {
|
|
306
|
+
const max = stdout.columns;
|
|
307
|
+
const prefix = max < 80 ? " " : " ".repeat(9);
|
|
308
|
+
await sleep(200);
|
|
309
|
+
log(
|
|
310
|
+
`
|
|
311
|
+
${color.bgCyan(` ${color.black("next")} `)} ${color.bold(
|
|
312
|
+
"Liftoff confirmed. Explore your project!"
|
|
313
|
+
)}`
|
|
314
|
+
);
|
|
315
|
+
await sleep(100);
|
|
316
|
+
if (projectDir !== "") {
|
|
317
|
+
const enter = [
|
|
318
|
+
`
|
|
319
|
+
${prefix}Enter your project directory using`,
|
|
320
|
+
color.cyan(`cd ./${projectDir}`, "")
|
|
321
|
+
];
|
|
322
|
+
const len = enter[0].length + stripAnsi(enter[1]).length;
|
|
323
|
+
log(enter.join(len > max ? "\n" + prefix : " "));
|
|
324
|
+
}
|
|
325
|
+
log(
|
|
326
|
+
`${prefix}Run ${color.cyan(devCmd)} to start the dev server. ${color.cyan("CTRL+C")} to stop.`
|
|
327
|
+
);
|
|
328
|
+
await sleep(100);
|
|
329
|
+
log(
|
|
330
|
+
`${prefix}Add frameworks like ${color.cyan(`react`)} or ${color.cyan(
|
|
331
|
+
"tailwind"
|
|
332
|
+
)} using ${color.cyan("astro add")}.`
|
|
333
|
+
);
|
|
334
|
+
await sleep(100);
|
|
335
|
+
log(`
|
|
336
|
+
${prefix}Stuck? Join us at ${color.cyan(`https://astro.build/chat`)}`);
|
|
337
|
+
await sleep(200);
|
|
338
|
+
};
|
|
339
|
+
function printHelp({
|
|
340
|
+
commandName,
|
|
341
|
+
headline,
|
|
342
|
+
usage,
|
|
343
|
+
tables,
|
|
344
|
+
description
|
|
345
|
+
}) {
|
|
346
|
+
const linebreak = () => "";
|
|
347
|
+
const table = (rows, { padding }) => {
|
|
348
|
+
const split = stdout.columns < 60;
|
|
349
|
+
let raw = "";
|
|
350
|
+
for (const row of rows) {
|
|
351
|
+
if (split) {
|
|
352
|
+
raw += ` ${row[0]}
|
|
353
|
+
`;
|
|
354
|
+
} else {
|
|
355
|
+
raw += `${`${row[0]}`.padStart(padding)}`;
|
|
356
|
+
}
|
|
357
|
+
raw += " " + color.dim(row[1]) + "\n";
|
|
358
|
+
}
|
|
359
|
+
return raw.slice(0, -1);
|
|
360
|
+
};
|
|
361
|
+
let message = [];
|
|
362
|
+
if (headline) {
|
|
363
|
+
message.push(
|
|
364
|
+
linebreak(),
|
|
365
|
+
`${title(commandName)} ${color.green(`v${"3.0.1"}`)} ${headline}`
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
if (usage) {
|
|
369
|
+
message.push(linebreak(), `${color.green(commandName)} ${color.bold(usage)}`);
|
|
370
|
+
}
|
|
371
|
+
if (tables) {
|
|
372
|
+
let calculateTablePadding2 = function(rows) {
|
|
373
|
+
return rows.reduce((val, [first]) => Math.max(val, first.length), 0);
|
|
374
|
+
};
|
|
375
|
+
var calculateTablePadding = calculateTablePadding2;
|
|
376
|
+
const tableEntries = Object.entries(tables);
|
|
377
|
+
const padding = Math.max(...tableEntries.map(([, rows]) => calculateTablePadding2(rows)));
|
|
378
|
+
for (const [, tableRows] of tableEntries) {
|
|
379
|
+
message.push(linebreak(), table(tableRows, { padding }));
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (description) {
|
|
383
|
+
message.push(linebreak(), `${description}`);
|
|
384
|
+
}
|
|
385
|
+
log(message.join("\n") + "\n");
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/actions/context.ts
|
|
389
|
+
async function getContext(argv) {
|
|
390
|
+
var _a;
|
|
391
|
+
const flags = (0, import_arg.default)(
|
|
392
|
+
{
|
|
393
|
+
"--template": String,
|
|
394
|
+
"--ref": String,
|
|
395
|
+
"--yes": Boolean,
|
|
396
|
+
"--no": Boolean,
|
|
397
|
+
"--install": Boolean,
|
|
398
|
+
"--no-install": Boolean,
|
|
399
|
+
"--git": Boolean,
|
|
400
|
+
"--no-git": Boolean,
|
|
401
|
+
"--typescript": String,
|
|
402
|
+
"--skip-houston": Boolean,
|
|
403
|
+
"--dry-run": Boolean,
|
|
404
|
+
"--help": Boolean,
|
|
405
|
+
"--fancy": Boolean,
|
|
406
|
+
"-y": "--yes",
|
|
407
|
+
"-n": "--no",
|
|
408
|
+
"-h": "--help"
|
|
409
|
+
},
|
|
410
|
+
{ argv, permissive: true }
|
|
411
|
+
);
|
|
412
|
+
const pkgManager = ((_a = (0, import_which_pm_runs.default)()) == null ? void 0 : _a.name) ?? "npm";
|
|
413
|
+
const [username, version] = await Promise.all([getName(), getVersion()]);
|
|
414
|
+
let cwd = flags["_"][0];
|
|
415
|
+
let {
|
|
416
|
+
"--help": help2 = false,
|
|
417
|
+
"--template": template2,
|
|
418
|
+
"--no": no,
|
|
419
|
+
"--yes": yes,
|
|
420
|
+
"--install": install2,
|
|
421
|
+
"--no-install": noInstall,
|
|
422
|
+
"--git": git2,
|
|
423
|
+
"--no-git": noGit,
|
|
424
|
+
"--typescript": typescript2,
|
|
425
|
+
"--fancy": fancy,
|
|
426
|
+
"--skip-houston": skipHouston,
|
|
427
|
+
"--dry-run": dryRun,
|
|
428
|
+
"--ref": ref
|
|
429
|
+
} = flags;
|
|
430
|
+
let projectName2 = cwd;
|
|
431
|
+
if (no) {
|
|
432
|
+
yes = false;
|
|
433
|
+
if (install2 == void 0)
|
|
434
|
+
install2 = false;
|
|
435
|
+
if (git2 == void 0)
|
|
436
|
+
git2 = false;
|
|
437
|
+
if (typescript2 == void 0)
|
|
438
|
+
typescript2 = "strict";
|
|
439
|
+
}
|
|
440
|
+
skipHouston = (os.platform() === "win32" && !fancy || skipHouston) ?? [yes, no, install2, git2, typescript2].some((v2) => v2 !== void 0);
|
|
441
|
+
const context = {
|
|
442
|
+
help: help2,
|
|
443
|
+
prompt,
|
|
444
|
+
pkgManager,
|
|
445
|
+
username,
|
|
446
|
+
version,
|
|
447
|
+
skipHouston,
|
|
448
|
+
dryRun,
|
|
449
|
+
projectName: projectName2,
|
|
450
|
+
template: template2,
|
|
451
|
+
ref: ref ?? "latest",
|
|
452
|
+
yes,
|
|
453
|
+
install: install2 ?? (noInstall ? false : void 0),
|
|
454
|
+
git: git2 ?? (noGit ? false : void 0),
|
|
455
|
+
typescript: typescript2,
|
|
456
|
+
cwd,
|
|
457
|
+
exit(code) {
|
|
458
|
+
process.exit(code);
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
return context;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// src/actions/dependencies.ts
|
|
465
|
+
import { execa } from "execa";
|
|
466
|
+
async function dependencies(ctx) {
|
|
467
|
+
let deps = ctx.install ?? ctx.yes;
|
|
468
|
+
if (deps === void 0) {
|
|
469
|
+
({ deps } = await ctx.prompt({
|
|
470
|
+
name: "deps",
|
|
471
|
+
type: "confirm",
|
|
472
|
+
label: title("deps"),
|
|
473
|
+
message: `Install dependencies?`,
|
|
474
|
+
hint: "recommended",
|
|
475
|
+
initial: true
|
|
476
|
+
}));
|
|
477
|
+
ctx.install = deps;
|
|
478
|
+
}
|
|
479
|
+
if (ctx.dryRun) {
|
|
480
|
+
await info("--dry-run", `Skipping dependency installation`);
|
|
481
|
+
} else if (deps) {
|
|
482
|
+
await spinner({
|
|
483
|
+
start: `Dependencies installing with ${ctx.pkgManager}...`,
|
|
484
|
+
end: "Dependencies installed",
|
|
485
|
+
while: () => install({ pkgManager: ctx.pkgManager, cwd: ctx.cwd }).catch((e) => {
|
|
486
|
+
error("error", e);
|
|
487
|
+
process.exit(1);
|
|
488
|
+
})
|
|
489
|
+
});
|
|
490
|
+
} else {
|
|
491
|
+
await info(
|
|
492
|
+
ctx.yes === false ? "deps [skip]" : "No problem!",
|
|
493
|
+
"Remember to install dependencies after setup."
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
async function install({ pkgManager, cwd }) {
|
|
498
|
+
const installExec = execa(pkgManager, ["install"], { cwd });
|
|
499
|
+
return new Promise((resolve, reject) => {
|
|
500
|
+
setTimeout(() => reject(`Request timed out after one minute`), 6e4);
|
|
501
|
+
installExec.on("error", (e) => reject(e));
|
|
502
|
+
installExec.on("close", () => resolve());
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// src/actions/git.ts
|
|
5
507
|
import fs from "fs";
|
|
6
|
-
import { downloadTemplate } from "giget";
|
|
7
|
-
import { bold, dim, green, reset, yellow } from "kleur/colors";
|
|
8
|
-
import ora from "ora";
|
|
9
|
-
import { platform } from "os";
|
|
10
508
|
import path from "path";
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (
|
|
32
|
-
|
|
509
|
+
import { color as color2 } from "@astrojs/cli-kit";
|
|
510
|
+
import { execa as execa2 } from "execa";
|
|
511
|
+
async function git(ctx) {
|
|
512
|
+
if (fs.existsSync(path.join(ctx.cwd, ".git"))) {
|
|
513
|
+
await info("Nice!", `Git has already been initialized`);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
let _git = ctx.git ?? ctx.yes;
|
|
517
|
+
if (_git === void 0) {
|
|
518
|
+
({ git: _git } = await ctx.prompt({
|
|
519
|
+
name: "git",
|
|
520
|
+
type: "confirm",
|
|
521
|
+
label: title("git"),
|
|
522
|
+
message: `Initialize a new git repository?`,
|
|
523
|
+
hint: "optional",
|
|
524
|
+
initial: true
|
|
525
|
+
}));
|
|
526
|
+
}
|
|
527
|
+
if (ctx.dryRun) {
|
|
528
|
+
await info("--dry-run", `Skipping Git initialization`);
|
|
529
|
+
} else if (_git) {
|
|
530
|
+
await spinner({
|
|
531
|
+
start: "Git initializing...",
|
|
532
|
+
end: "Git initialized",
|
|
533
|
+
while: () => init({ cwd: ctx.cwd }).catch((e) => {
|
|
534
|
+
error("error", e);
|
|
535
|
+
process.exit(1);
|
|
536
|
+
})
|
|
537
|
+
});
|
|
538
|
+
} else {
|
|
539
|
+
await info(
|
|
540
|
+
ctx.yes === false ? "git [skip]" : "Sounds good!",
|
|
541
|
+
`You can always run ${color2.reset("git init")}${color2.dim(" manually.")}`
|
|
542
|
+
);
|
|
543
|
+
}
|
|
33
544
|
}
|
|
34
|
-
function
|
|
545
|
+
async function init({ cwd }) {
|
|
35
546
|
try {
|
|
36
|
-
|
|
547
|
+
await execa2("git", ["init"], { cwd, stdio: "ignore" });
|
|
548
|
+
await execa2("git", ["add", "-A"], { cwd, stdio: "ignore" });
|
|
549
|
+
await execa2(
|
|
550
|
+
"git",
|
|
551
|
+
[
|
|
552
|
+
"commit",
|
|
553
|
+
"-m",
|
|
554
|
+
"Initial commit from Astro",
|
|
555
|
+
'--author="houston[bot] <astrobot-houston@users.noreply.github.com>"'
|
|
556
|
+
],
|
|
557
|
+
{ cwd, stdio: "ignore" }
|
|
558
|
+
);
|
|
37
559
|
} catch (e) {
|
|
38
|
-
if (e.code === "EEXIST")
|
|
39
|
-
return;
|
|
40
|
-
throw e;
|
|
41
560
|
}
|
|
42
561
|
}
|
|
43
|
-
|
|
562
|
+
|
|
563
|
+
// src/actions/help.ts
|
|
564
|
+
function help() {
|
|
565
|
+
printHelp({
|
|
566
|
+
commandName: "create-astro",
|
|
567
|
+
usage: "[dir] [...flags]",
|
|
568
|
+
headline: "Scaffold Astro projects.",
|
|
569
|
+
tables: {
|
|
570
|
+
Flags: [
|
|
571
|
+
["--template <name>", "Specify your template."],
|
|
572
|
+
["--install / --no-install", "Install dependencies (or not)."],
|
|
573
|
+
["--git / --no-git", "Initialize git repo (or not)."],
|
|
574
|
+
["--yes (-y)", "Skip all prompt by accepting defaults."],
|
|
575
|
+
["--no (-n)", "Skip all prompt by declining defaults."],
|
|
576
|
+
["--dry-run", "Walk through steps without executing."],
|
|
577
|
+
["--skip-houston", "Skip Houston animation."]
|
|
578
|
+
]
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// src/actions/intro.ts
|
|
584
|
+
import { color as color3, label as label2 } from "@astrojs/cli-kit";
|
|
585
|
+
import { random } from "@astrojs/cli-kit/utils";
|
|
586
|
+
async function intro(ctx) {
|
|
587
|
+
if (!ctx.skipHouston) {
|
|
588
|
+
await say([
|
|
589
|
+
[
|
|
590
|
+
"Welcome",
|
|
591
|
+
"to",
|
|
592
|
+
label2("astro", color3.bgGreen, color3.black),
|
|
593
|
+
color3.green(`v${ctx.version}`) + ",",
|
|
594
|
+
`${ctx.username}!`
|
|
595
|
+
],
|
|
596
|
+
random(welcome)
|
|
597
|
+
]);
|
|
598
|
+
await banner(ctx.version);
|
|
599
|
+
} else {
|
|
600
|
+
await banner(ctx.version);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// src/actions/next-steps.ts
|
|
605
|
+
import path2 from "path";
|
|
606
|
+
async function next(ctx) {
|
|
607
|
+
let projectDir = path2.relative(process.cwd(), ctx.cwd);
|
|
608
|
+
const devCmd = ctx.pkgManager === "npm" ? "npm run dev" : `${ctx.pkgManager} dev`;
|
|
609
|
+
await nextSteps({ projectDir, devCmd });
|
|
610
|
+
if (!ctx.skipHouston) {
|
|
611
|
+
await say(["Good luck out there, astronaut! \u{1F680}"]);
|
|
612
|
+
}
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// src/actions/project-name.ts
|
|
617
|
+
import { color as color4, generateProjectName } from "@astrojs/cli-kit";
|
|
618
|
+
import path3 from "path";
|
|
619
|
+
|
|
620
|
+
// src/actions/shared.ts
|
|
621
|
+
import fs2 from "fs";
|
|
622
|
+
var VALID_PROJECT_DIRECTORY_SAFE_LIST = [
|
|
44
623
|
".DS_Store",
|
|
45
624
|
".git",
|
|
625
|
+
".gitkeep",
|
|
46
626
|
".gitattributes",
|
|
47
627
|
".gitignore",
|
|
48
628
|
".gitlab-ci.yml",
|
|
@@ -63,279 +643,366 @@ const VALID_PROJECT_DIRECTORY_SAFE_LIST = [
|
|
|
63
643
|
/^yarn-debug\.log/,
|
|
64
644
|
/^yarn-error\.log/
|
|
65
645
|
];
|
|
66
|
-
function
|
|
67
|
-
if (!
|
|
646
|
+
function isEmpty(dirPath) {
|
|
647
|
+
if (!fs2.existsSync(dirPath)) {
|
|
68
648
|
return true;
|
|
69
649
|
}
|
|
70
|
-
const conflicts =
|
|
650
|
+
const conflicts = fs2.readdirSync(dirPath).filter((content) => {
|
|
71
651
|
return !VALID_PROJECT_DIRECTORY_SAFE_LIST.some((safeContent) => {
|
|
72
652
|
return typeof safeContent === "string" ? content === safeContent : safeContent.test(content);
|
|
73
653
|
});
|
|
74
654
|
});
|
|
75
655
|
return conflicts.length === 0;
|
|
76
656
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
],
|
|
93
|
-
random(welcome)
|
|
94
|
-
],
|
|
95
|
-
{ hat: args.fancy ? "\u{1F3A9}" : void 0 }
|
|
96
|
-
);
|
|
97
|
-
await banner(version);
|
|
98
|
-
}
|
|
99
|
-
let cwd = args["_"][2];
|
|
100
|
-
if (cwd && isValidProjectDirectory(cwd)) {
|
|
101
|
-
let acknowledgeProjectDir = ora({
|
|
102
|
-
color: "green",
|
|
103
|
-
text: `Using ${bold(cwd)} as project directory.`
|
|
104
|
-
});
|
|
105
|
-
acknowledgeProjectDir.succeed();
|
|
106
|
-
}
|
|
107
|
-
if (!cwd || !isValidProjectDirectory(cwd)) {
|
|
108
|
-
const notEmptyMsg = (dirPath) => `"${bold(dirPath)}" is not empty!`;
|
|
109
|
-
if (!isValidProjectDirectory(cwd)) {
|
|
110
|
-
let rejectProjectDir = ora({ color: "red", text: notEmptyMsg(cwd) });
|
|
111
|
-
rejectProjectDir.fail();
|
|
657
|
+
function isValidName(projectName2) {
|
|
658
|
+
return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(projectName2);
|
|
659
|
+
}
|
|
660
|
+
function toValidName(projectName2) {
|
|
661
|
+
if (isValidName(projectName2))
|
|
662
|
+
return projectName2;
|
|
663
|
+
return projectName2.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z\d\-~]+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// src/actions/project-name.ts
|
|
667
|
+
async function projectName(ctx) {
|
|
668
|
+
await checkCwd(ctx.cwd);
|
|
669
|
+
if (!ctx.cwd || !isEmpty(ctx.cwd)) {
|
|
670
|
+
if (!isEmpty(ctx.cwd)) {
|
|
671
|
+
await info("Hmm...", `${color4.reset(`"${ctx.cwd}"`)}${color4.dim(` is not empty!`)}`);
|
|
112
672
|
}
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
return true;
|
|
673
|
+
const { name } = await ctx.prompt({
|
|
674
|
+
name: "name",
|
|
675
|
+
type: "text",
|
|
676
|
+
label: title("dir"),
|
|
677
|
+
message: "Where should we create your new project?",
|
|
678
|
+
initial: `./${generateProjectName()}`,
|
|
679
|
+
validate(value) {
|
|
680
|
+
if (!isEmpty(value)) {
|
|
681
|
+
return `Directory is not empty!`;
|
|
124
682
|
}
|
|
125
|
-
|
|
126
|
-
{ onCancel: () => ora().info(dim("Operation cancelled. See you later, astronaut!")) }
|
|
127
|
-
);
|
|
128
|
-
cwd = dirResponse.directory;
|
|
129
|
-
}
|
|
130
|
-
if (!cwd) {
|
|
131
|
-
ora().info(dim("No directory provided. See you later, astronaut!"));
|
|
132
|
-
process.exit(1);
|
|
133
|
-
}
|
|
134
|
-
const options = await prompts(
|
|
135
|
-
[
|
|
136
|
-
{
|
|
137
|
-
type: "select",
|
|
138
|
-
name: "template",
|
|
139
|
-
message: "How would you like to setup your new project?",
|
|
140
|
-
choices: TEMPLATES
|
|
683
|
+
return true;
|
|
141
684
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
685
|
+
});
|
|
686
|
+
ctx.cwd = name;
|
|
687
|
+
ctx.projectName = toValidName(name);
|
|
688
|
+
} else {
|
|
689
|
+
let name = ctx.cwd;
|
|
690
|
+
if (name === "." || name === "./") {
|
|
691
|
+
const parts = process.cwd().split(path3.sep);
|
|
692
|
+
name = parts[parts.length - 1];
|
|
693
|
+
} else if (name.startsWith("./") || name.startsWith("../")) {
|
|
694
|
+
const parts = name.split("/");
|
|
695
|
+
name = parts[parts.length - 1];
|
|
696
|
+
}
|
|
697
|
+
ctx.projectName = toValidName(name);
|
|
698
|
+
}
|
|
699
|
+
if (!ctx.cwd) {
|
|
700
|
+
ctx.exit(1);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
async function checkCwd(cwd) {
|
|
704
|
+
const empty = cwd && isEmpty(cwd);
|
|
705
|
+
if (empty) {
|
|
706
|
+
log("");
|
|
707
|
+
await info("dir", `Using ${color4.reset(cwd)}${color4.dim(" as project directory")}`);
|
|
708
|
+
}
|
|
709
|
+
return empty;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// src/actions/template.ts
|
|
713
|
+
import { color as color5 } from "@astrojs/cli-kit";
|
|
714
|
+
import { downloadTemplate } from "giget";
|
|
715
|
+
import fs3 from "fs";
|
|
716
|
+
import path4 from "path";
|
|
717
|
+
async function template(ctx) {
|
|
718
|
+
if (!ctx.template) {
|
|
719
|
+
const { template: tmpl } = await ctx.prompt({
|
|
720
|
+
name: "template",
|
|
721
|
+
type: "select",
|
|
722
|
+
label: title("tmpl"),
|
|
723
|
+
message: "How would you like to start your new project?",
|
|
724
|
+
initial: "basics",
|
|
725
|
+
choices: [
|
|
726
|
+
{ value: "basics", label: "Include sample files", hint: "(recommended)" },
|
|
727
|
+
{ value: "blog", label: "Use blog template" },
|
|
728
|
+
{ value: "minimal", label: "Empty" }
|
|
729
|
+
]
|
|
730
|
+
});
|
|
731
|
+
ctx.template = tmpl;
|
|
732
|
+
} else {
|
|
733
|
+
await info("tmpl", `Using ${color5.reset(ctx.template)}${color5.dim(" as project template")}`);
|
|
734
|
+
}
|
|
735
|
+
if (ctx.dryRun) {
|
|
736
|
+
await info("--dry-run", `Skipping template copying`);
|
|
737
|
+
} else if (ctx.template) {
|
|
738
|
+
await spinner({
|
|
739
|
+
start: "Template copying...",
|
|
740
|
+
end: "Template copied",
|
|
741
|
+
while: () => copyTemplate(ctx.template, ctx).catch((e) => {
|
|
742
|
+
error("error", e);
|
|
743
|
+
process.exit(1);
|
|
744
|
+
})
|
|
745
|
+
});
|
|
746
|
+
} else {
|
|
747
|
+
ctx.exit(1);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
var FILES_TO_REMOVE = ["sandbox.config.json", "CHANGELOG.md"];
|
|
751
|
+
var FILES_TO_UPDATE = {
|
|
752
|
+
"package.json": (file, overrides) => fs3.promises.readFile(file, "utf-8").then(
|
|
753
|
+
(value) => fs3.promises.writeFile(
|
|
754
|
+
file,
|
|
755
|
+
JSON.stringify(
|
|
756
|
+
Object.assign(JSON.parse(value), Object.assign(overrides, { private: void 0 })),
|
|
757
|
+
null,
|
|
758
|
+
" "
|
|
759
|
+
),
|
|
760
|
+
"utf-8"
|
|
761
|
+
)
|
|
762
|
+
)
|
|
763
|
+
};
|
|
764
|
+
async function copyTemplate(tmpl, ctx) {
|
|
765
|
+
const ref = ctx.ref || "latest";
|
|
766
|
+
const isThirdParty = tmpl.includes("/");
|
|
767
|
+
const templateTarget = isThirdParty ? tmpl : `github:withastro/astro/examples/${tmpl}#${ref}`;
|
|
768
|
+
if (!ctx.dryRun) {
|
|
154
769
|
try {
|
|
155
|
-
await downloadTemplate(
|
|
770
|
+
await downloadTemplate(templateTarget, {
|
|
156
771
|
force: true,
|
|
157
772
|
provider: "github",
|
|
158
|
-
cwd,
|
|
773
|
+
cwd: ctx.cwd,
|
|
159
774
|
dir: "."
|
|
160
775
|
});
|
|
161
776
|
} catch (err) {
|
|
162
|
-
|
|
777
|
+
fs3.rmdirSync(ctx.cwd);
|
|
163
778
|
if (err.message.includes("404")) {
|
|
164
|
-
|
|
165
|
-
if (isThirdParty) {
|
|
166
|
-
const hasBranch = options.template.includes("#");
|
|
167
|
-
if (hasBranch) {
|
|
168
|
-
console.error("Are you sure this GitHub repo and branch exist?");
|
|
169
|
-
} else {
|
|
170
|
-
console.error(
|
|
171
|
-
`Are you sure this GitHub repo exists?This command uses the ${color.bold("main")} branch by default.
|
|
172
|
-
If the repo doesn't have a main branch, specify a custom branch name:
|
|
173
|
-
` + color.underline(options.template + color.bold("#branch-name"))
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
779
|
+
await error("Error", `Template ${color5.reset(tmpl)} ${color5.dim("does not exist!")}`);
|
|
177
780
|
} else {
|
|
178
781
|
console.error(err.message);
|
|
179
782
|
}
|
|
180
|
-
|
|
783
|
+
ctx.exit(1);
|
|
181
784
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
return fs.promises.rm(fileLoc, {});
|
|
187
|
-
}
|
|
188
|
-
})
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
templateSpinner.text = green("Template copied!");
|
|
192
|
-
templateSpinner.succeed();
|
|
193
|
-
const install = args.y ? true : (await prompts(
|
|
194
|
-
{
|
|
195
|
-
type: "confirm",
|
|
196
|
-
name: "install",
|
|
197
|
-
message: `Would you like to install ${pkgManager} dependencies? ${reset(
|
|
198
|
-
dim("(recommended)")
|
|
199
|
-
)}`,
|
|
200
|
-
initial: true
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
onCancel: () => {
|
|
204
|
-
ora().info(
|
|
205
|
-
dim(
|
|
206
|
-
"Operation cancelled. Your project folder has already been created, however no dependencies have been installed"
|
|
207
|
-
)
|
|
208
|
-
);
|
|
209
|
-
process.exit(1);
|
|
785
|
+
const removeFiles = FILES_TO_REMOVE.map(async (file) => {
|
|
786
|
+
const fileLoc = path4.resolve(path4.join(ctx.cwd, file));
|
|
787
|
+
if (fs3.existsSync(fileLoc)) {
|
|
788
|
+
return fs3.promises.rm(fileLoc, { recursive: true });
|
|
210
789
|
}
|
|
211
|
-
}
|
|
212
|
-
)).install;
|
|
213
|
-
if (args.dryRun) {
|
|
214
|
-
ora().info(dim(`--dry-run enabled, skipping.`));
|
|
215
|
-
} else if (install) {
|
|
216
|
-
const installExec = execa(pkgManager, ["install"], { cwd });
|
|
217
|
-
const installingPackagesMsg = `Installing packages${emojiWithFallback(" \u{1F4E6}", "...")}`;
|
|
218
|
-
const installSpinner = await loadWithRocketGradient(installingPackagesMsg);
|
|
219
|
-
await new Promise((resolve, reject) => {
|
|
220
|
-
var _a2;
|
|
221
|
-
(_a2 = installExec.stdout) == null ? void 0 : _a2.on("data", function(data) {
|
|
222
|
-
installSpinner.text = `${rocketAscii} ${installingPackagesMsg}
|
|
223
|
-
${bold(
|
|
224
|
-
`[${pkgManager}]`
|
|
225
|
-
)} ${data}`;
|
|
226
|
-
});
|
|
227
|
-
installExec.on("error", (error) => reject(error));
|
|
228
|
-
installExec.on("close", () => resolve());
|
|
229
790
|
});
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
791
|
+
const updateFiles = Object.entries(FILES_TO_UPDATE).map(async ([file, update]) => {
|
|
792
|
+
const fileLoc = path4.resolve(path4.join(ctx.cwd, file));
|
|
793
|
+
if (fs3.existsSync(fileLoc)) {
|
|
794
|
+
return update(fileLoc, { name: ctx.projectName });
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
await Promise.all([...removeFiles, ...updateFiles]);
|
|
234
798
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// src/actions/typescript.ts
|
|
802
|
+
import { color as color6 } from "@astrojs/cli-kit";
|
|
803
|
+
import fs4 from "fs";
|
|
804
|
+
import { readFile } from "fs/promises";
|
|
805
|
+
import path5 from "path";
|
|
806
|
+
|
|
807
|
+
// ../../node_modules/.pnpm/strip-json-comments@5.0.0/node_modules/strip-json-comments/index.js
|
|
808
|
+
var singleComment = Symbol("singleComment");
|
|
809
|
+
var multiComment = Symbol("multiComment");
|
|
810
|
+
var stripWithoutWhitespace = () => "";
|
|
811
|
+
var stripWithWhitespace = (string, start, end) => string.slice(start, end).replace(/\S/g, " ");
|
|
812
|
+
var isEscaped = (jsonString, quotePosition) => {
|
|
813
|
+
let index = quotePosition - 1;
|
|
814
|
+
let backslashCount = 0;
|
|
815
|
+
while (jsonString[index] === "\\") {
|
|
816
|
+
index -= 1;
|
|
817
|
+
backslashCount += 1;
|
|
818
|
+
}
|
|
819
|
+
return Boolean(backslashCount % 2);
|
|
820
|
+
};
|
|
821
|
+
function stripJsonComments(jsonString, { whitespace = true, trailingCommas = false } = {}) {
|
|
822
|
+
if (typeof jsonString !== "string") {
|
|
823
|
+
throw new TypeError(`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``);
|
|
824
|
+
}
|
|
825
|
+
const strip = whitespace ? stripWithWhitespace : stripWithoutWhitespace;
|
|
826
|
+
let isInsideString = false;
|
|
827
|
+
let isInsideComment = false;
|
|
828
|
+
let offset = 0;
|
|
829
|
+
let buffer = "";
|
|
830
|
+
let result = "";
|
|
831
|
+
let commaIndex = -1;
|
|
832
|
+
for (let index = 0; index < jsonString.length; index++) {
|
|
833
|
+
const currentCharacter = jsonString[index];
|
|
834
|
+
const nextCharacter = jsonString[index + 1];
|
|
835
|
+
if (!isInsideComment && currentCharacter === '"') {
|
|
836
|
+
const escaped = isEscaped(jsonString, index);
|
|
837
|
+
if (!escaped) {
|
|
838
|
+
isInsideString = !isInsideString;
|
|
250
839
|
}
|
|
251
840
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
841
|
+
if (isInsideString) {
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
844
|
+
if (!isInsideComment && currentCharacter + nextCharacter === "//") {
|
|
845
|
+
buffer += jsonString.slice(offset, index);
|
|
846
|
+
offset = index;
|
|
847
|
+
isInsideComment = singleComment;
|
|
848
|
+
index++;
|
|
849
|
+
} else if (isInsideComment === singleComment && currentCharacter + nextCharacter === "\r\n") {
|
|
850
|
+
index++;
|
|
851
|
+
isInsideComment = false;
|
|
852
|
+
buffer += strip(jsonString, offset, index);
|
|
853
|
+
offset = index;
|
|
854
|
+
continue;
|
|
855
|
+
} else if (isInsideComment === singleComment && currentCharacter === "\n") {
|
|
856
|
+
isInsideComment = false;
|
|
857
|
+
buffer += strip(jsonString, offset, index);
|
|
858
|
+
offset = index;
|
|
859
|
+
} else if (!isInsideComment && currentCharacter + nextCharacter === "/*") {
|
|
860
|
+
buffer += jsonString.slice(offset, index);
|
|
861
|
+
offset = index;
|
|
862
|
+
isInsideComment = multiComment;
|
|
863
|
+
index++;
|
|
864
|
+
continue;
|
|
865
|
+
} else if (isInsideComment === multiComment && currentCharacter + nextCharacter === "*/") {
|
|
866
|
+
index++;
|
|
867
|
+
isInsideComment = false;
|
|
868
|
+
buffer += strip(jsonString, offset, index + 1);
|
|
869
|
+
offset = index + 1;
|
|
870
|
+
continue;
|
|
871
|
+
} else if (trailingCommas && !isInsideComment) {
|
|
872
|
+
if (commaIndex !== -1) {
|
|
873
|
+
if (currentCharacter === "}" || currentCharacter === "]") {
|
|
874
|
+
buffer += jsonString.slice(offset, index);
|
|
875
|
+
result += strip(buffer, 0, 1) + buffer.slice(1);
|
|
876
|
+
buffer = "";
|
|
877
|
+
offset = index;
|
|
878
|
+
commaIndex = -1;
|
|
879
|
+
} else if (currentCharacter !== " " && currentCharacter !== " " && currentCharacter !== "\r" && currentCharacter !== "\n") {
|
|
880
|
+
buffer += jsonString.slice(offset, index);
|
|
881
|
+
offset = index;
|
|
882
|
+
commaIndex = -1;
|
|
883
|
+
}
|
|
884
|
+
} else if (currentCharacter === ",") {
|
|
885
|
+
result += buffer + jsonString.slice(offset, index);
|
|
886
|
+
buffer = "";
|
|
887
|
+
offset = index;
|
|
888
|
+
commaIndex = index;
|
|
889
|
+
}
|
|
262
890
|
}
|
|
263
|
-
} else {
|
|
264
|
-
await info(
|
|
265
|
-
"Sounds good!",
|
|
266
|
-
`You can come back and run ${color.reset(`git init`)}${color.dim(" later.")}`
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
if (args.y && !args.typescript) {
|
|
270
|
-
ora().warn(dim('--typescript <choice> missing. Defaulting to "strict"'));
|
|
271
|
-
args.typescript = "strict";
|
|
272
891
|
}
|
|
273
|
-
|
|
274
|
-
|
|
892
|
+
return result + buffer + (isInsideComment ? strip(jsonString.slice(offset)) : jsonString.slice(offset));
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// src/actions/typescript.ts
|
|
896
|
+
async function typescript(ctx) {
|
|
897
|
+
let ts = ctx.typescript ?? (typeof ctx.yes !== "undefined" ? "strict" : void 0);
|
|
898
|
+
if (ts === void 0) {
|
|
899
|
+
const { useTs } = await ctx.prompt({
|
|
900
|
+
name: "useTs",
|
|
901
|
+
type: "confirm",
|
|
902
|
+
label: title("ts"),
|
|
903
|
+
message: `Do you plan to write TypeScript?`,
|
|
904
|
+
initial: true
|
|
905
|
+
});
|
|
906
|
+
if (!useTs) {
|
|
907
|
+
await typescriptByDefault();
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
({ ts } = await ctx.prompt({
|
|
911
|
+
name: "ts",
|
|
275
912
|
type: "select",
|
|
276
|
-
|
|
277
|
-
message:
|
|
913
|
+
label: title("use"),
|
|
914
|
+
message: `How strict should TypeScript be?`,
|
|
915
|
+
initial: "strict",
|
|
278
916
|
choices: [
|
|
279
|
-
{ value: "strict",
|
|
280
|
-
{ value: "strictest",
|
|
281
|
-
{ value: "base",
|
|
282
|
-
{ value: "unsure", title: "Help me choose" }
|
|
917
|
+
{ value: "strict", label: "Strict", hint: `(recommended)` },
|
|
918
|
+
{ value: "strictest", label: "Strictest" },
|
|
919
|
+
{ value: "base", label: "Relaxed" }
|
|
283
920
|
]
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
"Operation cancelled. Your project folder has been created but no TypeScript configuration file was created."
|
|
290
|
-
)
|
|
291
|
-
);
|
|
292
|
-
process.exit(1);
|
|
921
|
+
}));
|
|
922
|
+
} else {
|
|
923
|
+
if (!["strict", "strictest", "relaxed", "default", "base"].includes(ts)) {
|
|
924
|
+
if (!ctx.dryRun) {
|
|
925
|
+
fs4.rmSync(ctx.cwd, { recursive: true, force: true });
|
|
293
926
|
}
|
|
927
|
+
error(
|
|
928
|
+
"Error",
|
|
929
|
+
`Unknown TypeScript option ${color6.reset(ts)}${color6.dim(
|
|
930
|
+
"! Expected strict | strictest | relaxed"
|
|
931
|
+
)}`
|
|
932
|
+
);
|
|
933
|
+
ctx.exit(1);
|
|
294
934
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
const templateTSConfig = parse(data.toString());
|
|
313
|
-
if (templateTSConfig && typeof templateTSConfig === "object") {
|
|
314
|
-
const result = assign(templateTSConfig, {
|
|
315
|
-
extends: `astro/tsconfigs/${tsResponse ?? "base"}`
|
|
316
|
-
});
|
|
317
|
-
fs.writeFileSync(templateTSConfigPath, stringify(result, null, 2));
|
|
318
|
-
} else {
|
|
319
|
-
console.log(
|
|
320
|
-
yellow(
|
|
321
|
-
"There was an error applying the requested TypeScript settings. This could be because the template's tsconfig.json is malformed"
|
|
322
|
-
)
|
|
323
|
-
);
|
|
324
|
-
}
|
|
935
|
+
await info("ts", `Using ${color6.reset(ts)}${color6.dim(" TypeScript configuration")}`);
|
|
936
|
+
}
|
|
937
|
+
if (ctx.dryRun) {
|
|
938
|
+
await info("--dry-run", `Skipping TypeScript setup`);
|
|
939
|
+
} else if (ts && ts !== "unsure") {
|
|
940
|
+
if (ts === "relaxed" || ts === "default") {
|
|
941
|
+
ts = "base";
|
|
942
|
+
}
|
|
943
|
+
await spinner({
|
|
944
|
+
start: "TypeScript customizing...",
|
|
945
|
+
end: "TypeScript customized",
|
|
946
|
+
while: () => setupTypeScript(ts, { cwd: ctx.cwd }).catch((e) => {
|
|
947
|
+
error("error", e);
|
|
948
|
+
process.exit(1);
|
|
949
|
+
})
|
|
325
950
|
});
|
|
326
|
-
|
|
951
|
+
} else {
|
|
327
952
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
await
|
|
953
|
+
}
|
|
954
|
+
async function setupTypeScript(value, { cwd }) {
|
|
955
|
+
const templateTSConfigPath = path5.join(cwd, "tsconfig.json");
|
|
956
|
+
try {
|
|
957
|
+
const data = await readFile(templateTSConfigPath, { encoding: "utf-8" });
|
|
958
|
+
const templateTSConfig = JSON.parse(stripJsonComments(data));
|
|
959
|
+
if (templateTSConfig && typeof templateTSConfig === "object") {
|
|
960
|
+
const result = Object.assign(templateTSConfig, {
|
|
961
|
+
extends: `astro/tsconfigs/${value}`
|
|
962
|
+
});
|
|
963
|
+
fs4.writeFileSync(templateTSConfigPath, JSON.stringify(result, null, 2));
|
|
964
|
+
} else {
|
|
965
|
+
throw new Error(
|
|
966
|
+
"There was an error applying the requested TypeScript settings. This could be because the template's tsconfig.json is malformed"
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
} catch (err) {
|
|
970
|
+
if (err && err.code === "ENOENT") {
|
|
971
|
+
fs4.writeFileSync(
|
|
972
|
+
templateTSConfigPath,
|
|
973
|
+
JSON.stringify({ extends: `astro/tsconfigs/${value}` }, null, 2)
|
|
974
|
+
);
|
|
975
|
+
}
|
|
333
976
|
}
|
|
334
977
|
}
|
|
335
|
-
|
|
336
|
-
|
|
978
|
+
|
|
979
|
+
// src/index.ts
|
|
980
|
+
var exit = () => process.exit(0);
|
|
981
|
+
process.on("SIGINT", exit);
|
|
982
|
+
process.on("SIGTERM", exit);
|
|
983
|
+
async function main() {
|
|
984
|
+
const cleanArgv = process.argv.slice(2).filter((arg2) => arg2 !== "--");
|
|
985
|
+
const ctx = await getContext(cleanArgv);
|
|
986
|
+
if (ctx.help) {
|
|
987
|
+
help();
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
const steps = [intro, projectName, template, dependencies, git, typescript, next];
|
|
991
|
+
for (const step of steps) {
|
|
992
|
+
await step(ctx);
|
|
993
|
+
}
|
|
994
|
+
process.exit(0);
|
|
337
995
|
}
|
|
338
996
|
export {
|
|
997
|
+
dependencies,
|
|
998
|
+
getContext,
|
|
999
|
+
git,
|
|
1000
|
+
intro,
|
|
339
1001
|
main,
|
|
340
|
-
|
|
1002
|
+
next,
|
|
1003
|
+
projectName,
|
|
1004
|
+
setStdout,
|
|
1005
|
+
setupTypeScript,
|
|
1006
|
+
template,
|
|
1007
|
+
typescript
|
|
341
1008
|
};
|