create-astro 2.0.1 → 3.0.0
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 +924 -265
- 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,621 @@
|
|
|
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.0"}`)} ${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 })
|
|
486
|
+
});
|
|
487
|
+
} else {
|
|
488
|
+
await info(
|
|
489
|
+
ctx.yes === false ? "deps [skip]" : "No problem!",
|
|
490
|
+
"Remember to install dependencies after setup."
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
async function install({ pkgManager, cwd }) {
|
|
495
|
+
const installExec = execa(pkgManager, ["install"], { cwd });
|
|
496
|
+
return new Promise((resolve, reject) => {
|
|
497
|
+
installExec.on("error", (error2) => reject(error2));
|
|
498
|
+
installExec.on("close", () => resolve());
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// src/actions/git.ts
|
|
5
503
|
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
504
|
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
|
-
|
|
505
|
+
import { color as color2 } from "@astrojs/cli-kit";
|
|
506
|
+
import { execa as execa2 } from "execa";
|
|
507
|
+
async function git(ctx) {
|
|
508
|
+
if (fs.existsSync(path.join(ctx.cwd, ".git"))) {
|
|
509
|
+
await info("Nice!", `Git has already been initialized`);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
let _git = ctx.git ?? ctx.yes;
|
|
513
|
+
if (_git === void 0) {
|
|
514
|
+
({ git: _git } = await ctx.prompt({
|
|
515
|
+
name: "git",
|
|
516
|
+
type: "confirm",
|
|
517
|
+
label: title("git"),
|
|
518
|
+
message: `Initialize a new git repository?`,
|
|
519
|
+
hint: "optional",
|
|
520
|
+
initial: true
|
|
521
|
+
}));
|
|
522
|
+
}
|
|
523
|
+
if (ctx.dryRun) {
|
|
524
|
+
await info("--dry-run", `Skipping Git initialization`);
|
|
525
|
+
} else if (_git) {
|
|
526
|
+
await spinner({
|
|
527
|
+
start: "Git initializing...",
|
|
528
|
+
end: "Git initialized",
|
|
529
|
+
while: () => init({ cwd: ctx.cwd })
|
|
530
|
+
});
|
|
531
|
+
} else {
|
|
532
|
+
await info(
|
|
533
|
+
ctx.yes === false ? "git [skip]" : "Sounds good!",
|
|
534
|
+
`You can always run ${color2.reset("git init")}${color2.dim(" manually.")}`
|
|
535
|
+
);
|
|
536
|
+
}
|
|
33
537
|
}
|
|
34
|
-
function
|
|
538
|
+
async function init({ cwd }) {
|
|
35
539
|
try {
|
|
36
|
-
|
|
540
|
+
await execa2("git", ["init"], { cwd, stdio: "ignore" });
|
|
541
|
+
await execa2("git", ["add", "-A"], { cwd, stdio: "ignore" });
|
|
542
|
+
await execa2(
|
|
543
|
+
"git",
|
|
544
|
+
[
|
|
545
|
+
"commit",
|
|
546
|
+
"-m",
|
|
547
|
+
"Initial commit from Astro",
|
|
548
|
+
'--author="houston[bot] <astrobot-houston@users.noreply.github.com>"'
|
|
549
|
+
],
|
|
550
|
+
{ cwd, stdio: "ignore" }
|
|
551
|
+
);
|
|
37
552
|
} catch (e) {
|
|
38
|
-
if (e.code === "EEXIST")
|
|
39
|
-
return;
|
|
40
|
-
throw e;
|
|
41
553
|
}
|
|
42
554
|
}
|
|
43
|
-
|
|
555
|
+
|
|
556
|
+
// src/actions/help.ts
|
|
557
|
+
function help() {
|
|
558
|
+
printHelp({
|
|
559
|
+
commandName: "create-astro",
|
|
560
|
+
usage: "[dir] [...flags]",
|
|
561
|
+
headline: "Scaffold Astro projects.",
|
|
562
|
+
tables: {
|
|
563
|
+
Flags: [
|
|
564
|
+
["--template <name>", "Specify your template."],
|
|
565
|
+
["--install / --no-install", "Install dependencies (or not)."],
|
|
566
|
+
["--git / --no-git", "Initialize git repo (or not)."],
|
|
567
|
+
["--yes (-y)", "Skip all prompt by accepting defaults."],
|
|
568
|
+
["--no (-n)", "Skip all prompt by declining defaults."],
|
|
569
|
+
["--dry-run", "Walk through steps without executing."],
|
|
570
|
+
["--skip-houston", "Skip Houston animation."]
|
|
571
|
+
]
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// src/actions/intro.ts
|
|
577
|
+
import { color as color3, label as label2 } from "@astrojs/cli-kit";
|
|
578
|
+
import { random } from "@astrojs/cli-kit/utils";
|
|
579
|
+
async function intro(ctx) {
|
|
580
|
+
if (!ctx.skipHouston) {
|
|
581
|
+
await say([
|
|
582
|
+
[
|
|
583
|
+
"Welcome",
|
|
584
|
+
"to",
|
|
585
|
+
label2("astro", color3.bgGreen, color3.black),
|
|
586
|
+
color3.green(`v${ctx.version}`) + ",",
|
|
587
|
+
`${ctx.username}!`
|
|
588
|
+
],
|
|
589
|
+
random(welcome)
|
|
590
|
+
]);
|
|
591
|
+
await banner(ctx.version);
|
|
592
|
+
} else {
|
|
593
|
+
await banner(ctx.version);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// src/actions/next-steps.ts
|
|
598
|
+
import path2 from "path";
|
|
599
|
+
async function next(ctx) {
|
|
600
|
+
let projectDir = path2.relative(process.cwd(), ctx.cwd);
|
|
601
|
+
const devCmd = ctx.pkgManager === "npm" ? "npm run dev" : `${ctx.pkgManager} dev`;
|
|
602
|
+
await nextSteps({ projectDir, devCmd });
|
|
603
|
+
if (!ctx.skipHouston) {
|
|
604
|
+
await say(["Good luck out there, astronaut! \u{1F680}"]);
|
|
605
|
+
}
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// src/actions/project-name.ts
|
|
610
|
+
import { color as color4, generateProjectName } from "@astrojs/cli-kit";
|
|
611
|
+
import path3 from "path";
|
|
612
|
+
|
|
613
|
+
// src/actions/shared.ts
|
|
614
|
+
import fs2 from "fs";
|
|
615
|
+
var VALID_PROJECT_DIRECTORY_SAFE_LIST = [
|
|
44
616
|
".DS_Store",
|
|
45
617
|
".git",
|
|
618
|
+
".gitkeep",
|
|
46
619
|
".gitattributes",
|
|
47
620
|
".gitignore",
|
|
48
621
|
".gitlab-ci.yml",
|
|
@@ -63,274 +636,360 @@ const VALID_PROJECT_DIRECTORY_SAFE_LIST = [
|
|
|
63
636
|
/^yarn-debug\.log/,
|
|
64
637
|
/^yarn-error\.log/
|
|
65
638
|
];
|
|
66
|
-
function
|
|
67
|
-
if (!
|
|
639
|
+
function isEmpty(dirPath) {
|
|
640
|
+
if (!fs2.existsSync(dirPath)) {
|
|
68
641
|
return true;
|
|
69
642
|
}
|
|
70
|
-
const conflicts =
|
|
643
|
+
const conflicts = fs2.readdirSync(dirPath).filter((content) => {
|
|
71
644
|
return !VALID_PROJECT_DIRECTORY_SAFE_LIST.some((safeContent) => {
|
|
72
645
|
return typeof safeContent === "string" ? content === safeContent : safeContent.test(content);
|
|
73
646
|
});
|
|
74
647
|
});
|
|
75
648
|
return conflicts.length === 0;
|
|
76
649
|
}
|
|
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();
|
|
650
|
+
function isValidName(projectName2) {
|
|
651
|
+
return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(projectName2);
|
|
652
|
+
}
|
|
653
|
+
function toValidName(projectName2) {
|
|
654
|
+
if (isValidName(projectName2))
|
|
655
|
+
return projectName2;
|
|
656
|
+
return projectName2.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z\d\-~]+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// src/actions/project-name.ts
|
|
660
|
+
async function projectName(ctx) {
|
|
661
|
+
await checkCwd(ctx.cwd);
|
|
662
|
+
if (!ctx.cwd || !isEmpty(ctx.cwd)) {
|
|
663
|
+
if (!isEmpty(ctx.cwd)) {
|
|
664
|
+
await info("Hmm...", `${color4.reset(`"${ctx.cwd}"`)}${color4.dim(` is not empty!`)}`);
|
|
112
665
|
}
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
return true;
|
|
666
|
+
const { name } = await ctx.prompt({
|
|
667
|
+
name: "name",
|
|
668
|
+
type: "text",
|
|
669
|
+
label: title("dir"),
|
|
670
|
+
message: "Where should we create your new project?",
|
|
671
|
+
initial: `./${generateProjectName()}`,
|
|
672
|
+
validate(value) {
|
|
673
|
+
if (!isEmpty(value)) {
|
|
674
|
+
return `Directory is not empty!`;
|
|
124
675
|
}
|
|
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
|
|
676
|
+
return true;
|
|
141
677
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
678
|
+
});
|
|
679
|
+
ctx.cwd = name;
|
|
680
|
+
ctx.projectName = toValidName(name);
|
|
681
|
+
} else {
|
|
682
|
+
let name = ctx.cwd;
|
|
683
|
+
if (name === "." || name === "./") {
|
|
684
|
+
const parts = process.cwd().split(path3.sep);
|
|
685
|
+
name = parts[parts.length - 1];
|
|
686
|
+
} else if (name.startsWith("./") || name.startsWith("../")) {
|
|
687
|
+
const parts = name.split("/");
|
|
688
|
+
name = parts[parts.length - 1];
|
|
689
|
+
}
|
|
690
|
+
ctx.projectName = toValidName(name);
|
|
691
|
+
}
|
|
692
|
+
if (!ctx.cwd) {
|
|
693
|
+
ctx.exit(1);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
async function checkCwd(cwd) {
|
|
697
|
+
const empty = cwd && isEmpty(cwd);
|
|
698
|
+
if (empty) {
|
|
699
|
+
log("");
|
|
700
|
+
await info("dir", `Using ${color4.reset(cwd)}${color4.dim(" as project directory")}`);
|
|
701
|
+
}
|
|
702
|
+
return empty;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// src/actions/template.ts
|
|
706
|
+
import { color as color5 } from "@astrojs/cli-kit";
|
|
707
|
+
import { downloadTemplate } from "giget";
|
|
708
|
+
import fs3 from "fs";
|
|
709
|
+
import path4 from "path";
|
|
710
|
+
async function template(ctx) {
|
|
711
|
+
if (!ctx.template) {
|
|
712
|
+
const { template: tmpl } = await ctx.prompt({
|
|
713
|
+
name: "template",
|
|
714
|
+
type: "select",
|
|
715
|
+
label: title("tmpl"),
|
|
716
|
+
message: "How would you like to start your new project?",
|
|
717
|
+
initial: "basics",
|
|
718
|
+
choices: [
|
|
719
|
+
{ value: "basics", label: "Include sample files", hint: "(recommended)" },
|
|
720
|
+
{ value: "blog", label: "Use blog template" },
|
|
721
|
+
{ value: "minimal", label: "Empty" }
|
|
722
|
+
]
|
|
723
|
+
});
|
|
724
|
+
ctx.template = tmpl;
|
|
725
|
+
} else {
|
|
726
|
+
await info("tmpl", `Using ${color5.reset(ctx.template)}${color5.dim(" as project template")}`);
|
|
727
|
+
}
|
|
728
|
+
if (ctx.dryRun) {
|
|
729
|
+
await info("--dry-run", `Skipping template copying`);
|
|
730
|
+
} else if (ctx.template) {
|
|
731
|
+
await spinner({
|
|
732
|
+
start: "Template copying...",
|
|
733
|
+
end: "Template copied",
|
|
734
|
+
while: () => copyTemplate(ctx.template, ctx)
|
|
735
|
+
});
|
|
736
|
+
} else {
|
|
737
|
+
ctx.exit(1);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
var FILES_TO_REMOVE = ["sandbox.config.json", "CHANGELOG.md"];
|
|
741
|
+
var FILES_TO_UPDATE = {
|
|
742
|
+
"package.json": (file, overrides) => fs3.promises.readFile(file, "utf-8").then(
|
|
743
|
+
(value) => fs3.promises.writeFile(
|
|
744
|
+
file,
|
|
745
|
+
JSON.stringify(
|
|
746
|
+
Object.assign(JSON.parse(value), Object.assign(overrides, { private: void 0 })),
|
|
747
|
+
null,
|
|
748
|
+
" "
|
|
749
|
+
),
|
|
750
|
+
"utf-8"
|
|
751
|
+
)
|
|
752
|
+
)
|
|
753
|
+
};
|
|
754
|
+
async function copyTemplate(tmpl, ctx) {
|
|
755
|
+
const ref = ctx.ref || "latest";
|
|
756
|
+
const isThirdParty = tmpl.includes("/");
|
|
757
|
+
const templateTarget = isThirdParty ? tmpl : `github:withastro/astro/examples/${tmpl}#${ref}`;
|
|
758
|
+
if (!ctx.dryRun) {
|
|
154
759
|
try {
|
|
155
|
-
await downloadTemplate(
|
|
760
|
+
await downloadTemplate(templateTarget, {
|
|
156
761
|
force: true,
|
|
157
762
|
provider: "github",
|
|
158
|
-
cwd,
|
|
763
|
+
cwd: ctx.cwd,
|
|
159
764
|
dir: "."
|
|
160
765
|
});
|
|
161
766
|
} catch (err) {
|
|
162
|
-
|
|
767
|
+
fs3.rmdirSync(ctx.cwd);
|
|
163
768
|
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
|
-
}
|
|
769
|
+
await error("Error", `Template ${color5.reset(tmpl)} ${color5.dim("does not exist!")}`);
|
|
177
770
|
} else {
|
|
178
771
|
console.error(err.message);
|
|
179
772
|
}
|
|
180
|
-
|
|
773
|
+
ctx.exit(1);
|
|
181
774
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
775
|
+
const removeFiles = FILES_TO_REMOVE.map(async (file) => {
|
|
776
|
+
const fileLoc = path4.resolve(path4.join(ctx.cwd, file));
|
|
777
|
+
if (fs3.existsSync(fileLoc)) {
|
|
778
|
+
return fs3.promises.rm(fileLoc, { recursive: true });
|
|
779
|
+
}
|
|
780
|
+
});
|
|
781
|
+
const updateFiles = Object.entries(FILES_TO_UPDATE).map(async ([file, update]) => {
|
|
782
|
+
const fileLoc = path4.resolve(path4.join(ctx.cwd, file));
|
|
783
|
+
if (fs3.existsSync(fileLoc)) {
|
|
784
|
+
return update(fileLoc, { name: ctx.projectName });
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
await Promise.all([...removeFiles, ...updateFiles]);
|
|
190
788
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// src/actions/typescript.ts
|
|
792
|
+
import { color as color6 } from "@astrojs/cli-kit";
|
|
793
|
+
import fs4 from "fs";
|
|
794
|
+
import { readFile } from "fs/promises";
|
|
795
|
+
import path5 from "path";
|
|
796
|
+
|
|
797
|
+
// ../../node_modules/.pnpm/strip-json-comments@5.0.0/node_modules/strip-json-comments/index.js
|
|
798
|
+
var singleComment = Symbol("singleComment");
|
|
799
|
+
var multiComment = Symbol("multiComment");
|
|
800
|
+
var stripWithoutWhitespace = () => "";
|
|
801
|
+
var stripWithWhitespace = (string, start, end) => string.slice(start, end).replace(/\S/g, " ");
|
|
802
|
+
var isEscaped = (jsonString, quotePosition) => {
|
|
803
|
+
let index = quotePosition - 1;
|
|
804
|
+
let backslashCount = 0;
|
|
805
|
+
while (jsonString[index] === "\\") {
|
|
806
|
+
index -= 1;
|
|
807
|
+
backslashCount += 1;
|
|
808
|
+
}
|
|
809
|
+
return Boolean(backslashCount % 2);
|
|
810
|
+
};
|
|
811
|
+
function stripJsonComments(jsonString, { whitespace = true, trailingCommas = false } = {}) {
|
|
812
|
+
if (typeof jsonString !== "string") {
|
|
813
|
+
throw new TypeError(`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``);
|
|
814
|
+
}
|
|
815
|
+
const strip = whitespace ? stripWithWhitespace : stripWithoutWhitespace;
|
|
816
|
+
let isInsideString = false;
|
|
817
|
+
let isInsideComment = false;
|
|
818
|
+
let offset = 0;
|
|
819
|
+
let buffer = "";
|
|
820
|
+
let result = "";
|
|
821
|
+
let commaIndex = -1;
|
|
822
|
+
for (let index = 0; index < jsonString.length; index++) {
|
|
823
|
+
const currentCharacter = jsonString[index];
|
|
824
|
+
const nextCharacter = jsonString[index + 1];
|
|
825
|
+
if (!isInsideComment && currentCharacter === '"') {
|
|
826
|
+
const escaped = isEscaped(jsonString, index);
|
|
827
|
+
if (!escaped) {
|
|
828
|
+
isInsideString = !isInsideString;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
if (isInsideString) {
|
|
832
|
+
continue;
|
|
833
|
+
}
|
|
834
|
+
if (!isInsideComment && currentCharacter + nextCharacter === "//") {
|
|
835
|
+
buffer += jsonString.slice(offset, index);
|
|
836
|
+
offset = index;
|
|
837
|
+
isInsideComment = singleComment;
|
|
838
|
+
index++;
|
|
839
|
+
} else if (isInsideComment === singleComment && currentCharacter + nextCharacter === "\r\n") {
|
|
840
|
+
index++;
|
|
841
|
+
isInsideComment = false;
|
|
842
|
+
buffer += strip(jsonString, offset, index);
|
|
843
|
+
offset = index;
|
|
844
|
+
continue;
|
|
845
|
+
} else if (isInsideComment === singleComment && currentCharacter === "\n") {
|
|
846
|
+
isInsideComment = false;
|
|
847
|
+
buffer += strip(jsonString, offset, index);
|
|
848
|
+
offset = index;
|
|
849
|
+
} else if (!isInsideComment && currentCharacter + nextCharacter === "/*") {
|
|
850
|
+
buffer += jsonString.slice(offset, index);
|
|
851
|
+
offset = index;
|
|
852
|
+
isInsideComment = multiComment;
|
|
853
|
+
index++;
|
|
854
|
+
continue;
|
|
855
|
+
} else if (isInsideComment === multiComment && currentCharacter + nextCharacter === "*/") {
|
|
856
|
+
index++;
|
|
857
|
+
isInsideComment = false;
|
|
858
|
+
buffer += strip(jsonString, offset, index + 1);
|
|
859
|
+
offset = index + 1;
|
|
860
|
+
continue;
|
|
861
|
+
} else if (trailingCommas && !isInsideComment) {
|
|
862
|
+
if (commaIndex !== -1) {
|
|
863
|
+
if (currentCharacter === "}" || currentCharacter === "]") {
|
|
864
|
+
buffer += jsonString.slice(offset, index);
|
|
865
|
+
result += strip(buffer, 0, 1) + buffer.slice(1);
|
|
866
|
+
buffer = "";
|
|
867
|
+
offset = index;
|
|
868
|
+
commaIndex = -1;
|
|
869
|
+
} else if (currentCharacter !== " " && currentCharacter !== " " && currentCharacter !== "\r" && currentCharacter !== "\n") {
|
|
870
|
+
buffer += jsonString.slice(offset, index);
|
|
871
|
+
offset = index;
|
|
872
|
+
commaIndex = -1;
|
|
873
|
+
}
|
|
874
|
+
} else if (currentCharacter === ",") {
|
|
875
|
+
result += buffer + jsonString.slice(offset, index);
|
|
876
|
+
buffer = "";
|
|
877
|
+
offset = index;
|
|
878
|
+
commaIndex = index;
|
|
210
879
|
}
|
|
211
880
|
}
|
|
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
|
-
});
|
|
230
|
-
installSpinner.text = green("Packages installed!");
|
|
231
|
-
installSpinner.succeed();
|
|
232
|
-
} else {
|
|
233
|
-
await info("No problem!", "Remember to install dependencies after setup.");
|
|
234
881
|
}
|
|
235
|
-
|
|
236
|
-
|
|
882
|
+
return result + buffer + (isInsideComment ? strip(jsonString.slice(offset)) : jsonString.slice(offset));
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// src/actions/typescript.ts
|
|
886
|
+
async function typescript(ctx) {
|
|
887
|
+
let ts = ctx.typescript ?? (typeof ctx.yes !== "undefined" ? "strict" : void 0);
|
|
888
|
+
if (ts === void 0) {
|
|
889
|
+
const { useTs } = await ctx.prompt({
|
|
890
|
+
name: "useTs",
|
|
237
891
|
type: "confirm",
|
|
238
|
-
|
|
239
|
-
message: `
|
|
240
|
-
dim("(optional)")
|
|
241
|
-
)}`,
|
|
892
|
+
label: title("ts"),
|
|
893
|
+
message: `Do you plan to write TypeScript?`,
|
|
242
894
|
initial: true
|
|
243
|
-
}
|
|
244
|
-
{
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
dim("Operation cancelled. No worries, your project folder has already been created")
|
|
248
|
-
);
|
|
249
|
-
process.exit(1);
|
|
250
|
-
}
|
|
895
|
+
});
|
|
896
|
+
if (!useTs) {
|
|
897
|
+
await typescriptByDefault();
|
|
898
|
+
return;
|
|
251
899
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
ora().info(dim(`--dry-run enabled, skipping.`));
|
|
255
|
-
} else if (gitResponse) {
|
|
256
|
-
await execaCommand("git init", { cwd });
|
|
257
|
-
ora().succeed("Git repository created!");
|
|
258
|
-
} else {
|
|
259
|
-
await info(
|
|
260
|
-
"Sounds good!",
|
|
261
|
-
`You can come back and run ${color.reset(`git init`)}${color.dim(" later.")}`
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
if (args.y && !args.typescript) {
|
|
265
|
-
ora().warn(dim('--typescript <choice> missing. Defaulting to "strict"'));
|
|
266
|
-
args.typescript = "strict";
|
|
267
|
-
}
|
|
268
|
-
let tsResponse = args.typescript || (await prompts(
|
|
269
|
-
{
|
|
900
|
+
({ ts } = await ctx.prompt({
|
|
901
|
+
name: "ts",
|
|
270
902
|
type: "select",
|
|
271
|
-
|
|
272
|
-
message:
|
|
903
|
+
label: title("use"),
|
|
904
|
+
message: `How strict should TypeScript be?`,
|
|
905
|
+
initial: "strict",
|
|
273
906
|
choices: [
|
|
274
|
-
{ value: "strict",
|
|
275
|
-
{ value: "strictest",
|
|
276
|
-
{ value: "base",
|
|
277
|
-
{ value: "unsure", title: "Help me choose" }
|
|
907
|
+
{ value: "strict", label: "Strict", hint: `(recommended)` },
|
|
908
|
+
{ value: "strictest", label: "Strictest" },
|
|
909
|
+
{ value: "base", label: "Relaxed" }
|
|
278
910
|
]
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
"Operation cancelled. Your project folder has been created but no TypeScript configuration file was created."
|
|
285
|
-
)
|
|
286
|
-
);
|
|
287
|
-
process.exit(1);
|
|
911
|
+
}));
|
|
912
|
+
} else {
|
|
913
|
+
if (!["strict", "strictest", "relaxed", "default", "base"].includes(ts)) {
|
|
914
|
+
if (!ctx.dryRun) {
|
|
915
|
+
fs4.rmSync(ctx.cwd, { recursive: true, force: true });
|
|
288
916
|
}
|
|
917
|
+
error(
|
|
918
|
+
"Error",
|
|
919
|
+
`Unknown TypeScript option ${color6.reset(ts)}${color6.dim(
|
|
920
|
+
"! Expected strict | strictest | relaxed"
|
|
921
|
+
)}`
|
|
922
|
+
);
|
|
923
|
+
ctx.exit(1);
|
|
289
924
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
templateTSConfigPath,
|
|
303
|
-
stringify({ extends: `astro/tsconfigs/${tsResponse ?? "base"}` }, null, 2)
|
|
304
|
-
);
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
const templateTSConfig = parse(data.toString());
|
|
308
|
-
if (templateTSConfig && typeof templateTSConfig === "object") {
|
|
309
|
-
const result = assign(templateTSConfig, {
|
|
310
|
-
extends: `astro/tsconfigs/${tsResponse ?? "base"}`
|
|
311
|
-
});
|
|
312
|
-
fs.writeFileSync(templateTSConfigPath, stringify(result, null, 2));
|
|
313
|
-
} else {
|
|
314
|
-
console.log(
|
|
315
|
-
yellow(
|
|
316
|
-
"There was an error applying the requested TypeScript settings. This could be because the template's tsconfig.json is malformed"
|
|
317
|
-
)
|
|
318
|
-
);
|
|
319
|
-
}
|
|
925
|
+
await info("ts", `Using ${color6.reset(ts)}${color6.dim(" TypeScript configuration")}`);
|
|
926
|
+
}
|
|
927
|
+
if (ctx.dryRun) {
|
|
928
|
+
await info("--dry-run", `Skipping TypeScript setup`);
|
|
929
|
+
} else if (ts && ts !== "unsure") {
|
|
930
|
+
if (ts === "relaxed" || ts === "default") {
|
|
931
|
+
ts = "base";
|
|
932
|
+
}
|
|
933
|
+
await spinner({
|
|
934
|
+
start: "TypeScript customizing...",
|
|
935
|
+
end: "TypeScript customized",
|
|
936
|
+
while: () => setupTypeScript(ts, { cwd: ctx.cwd })
|
|
320
937
|
});
|
|
321
|
-
|
|
938
|
+
} else {
|
|
322
939
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
await
|
|
940
|
+
}
|
|
941
|
+
async function setupTypeScript(value, { cwd }) {
|
|
942
|
+
const templateTSConfigPath = path5.join(cwd, "tsconfig.json");
|
|
943
|
+
try {
|
|
944
|
+
const data = await readFile(templateTSConfigPath, { encoding: "utf-8" });
|
|
945
|
+
const templateTSConfig = JSON.parse(stripJsonComments(data));
|
|
946
|
+
if (templateTSConfig && typeof templateTSConfig === "object") {
|
|
947
|
+
const result = Object.assign(templateTSConfig, {
|
|
948
|
+
extends: `astro/tsconfigs/${value}`
|
|
949
|
+
});
|
|
950
|
+
fs4.writeFileSync(templateTSConfigPath, JSON.stringify(result, null, 2));
|
|
951
|
+
} else {
|
|
952
|
+
throw new Error(
|
|
953
|
+
"There was an error applying the requested TypeScript settings. This could be because the template's tsconfig.json is malformed"
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
} catch (err) {
|
|
957
|
+
if (err && err.code === "ENOENT") {
|
|
958
|
+
fs4.writeFileSync(
|
|
959
|
+
templateTSConfigPath,
|
|
960
|
+
JSON.stringify({ extends: `astro/tsconfigs/${value}` }, null, 2)
|
|
961
|
+
);
|
|
962
|
+
}
|
|
328
963
|
}
|
|
329
964
|
}
|
|
330
|
-
|
|
331
|
-
|
|
965
|
+
|
|
966
|
+
// src/index.ts
|
|
967
|
+
var exit = () => process.exit(0);
|
|
968
|
+
process.on("SIGINT", exit);
|
|
969
|
+
process.on("SIGTERM", exit);
|
|
970
|
+
async function main() {
|
|
971
|
+
const cleanArgv = process.argv.slice(2).filter((arg2) => arg2 !== "--");
|
|
972
|
+
const ctx = await getContext(cleanArgv);
|
|
973
|
+
if (ctx.help) {
|
|
974
|
+
help();
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
const steps = [intro, projectName, template, dependencies, git, typescript, next];
|
|
978
|
+
for (const step of steps) {
|
|
979
|
+
await step(ctx);
|
|
980
|
+
}
|
|
981
|
+
process.exit(0);
|
|
332
982
|
}
|
|
333
983
|
export {
|
|
984
|
+
dependencies,
|
|
985
|
+
getContext,
|
|
986
|
+
git,
|
|
987
|
+
intro,
|
|
334
988
|
main,
|
|
335
|
-
|
|
989
|
+
next,
|
|
990
|
+
projectName,
|
|
991
|
+
setStdout,
|
|
992
|
+
setupTypeScript,
|
|
993
|
+
template,
|
|
994
|
+
typescript
|
|
336
995
|
};
|