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/dist/index.js CHANGED
@@ -1,48 +1,628 @@
1
- import { color, generateProjectName, label, say } from "@astrojs/cli-kit";
2
- import { forceUnicode, random } from "@astrojs/cli-kit/utils";
3
- import { assign, parse, stringify } from "comment-json";
4
- import { execa, execaCommand } from "execa";
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 prompts from "prompts";
12
- import detectPackageManager from "which-pm-runs";
13
- import yargs from "yargs-parser";
14
- import { loadWithRocketGradient, rocketAscii } from "./gradient.js";
15
- import { logger } from "./logger.js";
16
- import {
17
- banner,
18
- getName,
19
- getVersion,
20
- info,
21
- nextSteps,
22
- typescriptByDefault,
23
- welcome
24
- } from "./messages.js";
25
- import { TEMPLATES } from "./templates.js";
26
- const cleanArgv = process.argv.filter((arg) => arg !== "--");
27
- const args = yargs(cleanArgv, { boolean: ["fancy", "y"], alias: { y: "yes" } });
28
- if (platform() === "win32")
29
- args.skipHouston = true;
30
- prompts.override(args);
31
- if (args.fancy) {
32
- forceUnicode();
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 mkdirp(dir) {
545
+ async function init({ cwd }) {
35
546
  try {
36
- fs.mkdirSync(dir, { recursive: true });
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
- const VALID_PROJECT_DIRECTORY_SAFE_LIST = [
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 isValidProjectDirectory(dirPath) {
67
- if (!fs.existsSync(dirPath)) {
646
+ function isEmpty(dirPath) {
647
+ if (!fs2.existsSync(dirPath)) {
68
648
  return true;
69
649
  }
70
- const conflicts = fs.readdirSync(dirPath).filter((content) => {
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
- const FILES_TO_REMOVE = [".stackblitzrc", "sandbox.config.json", "CHANGELOG.md"];
78
- async function main() {
79
- var _a;
80
- const pkgManager = ((_a = detectPackageManager()) == null ? void 0 : _a.name) || "npm";
81
- const [username, version] = await Promise.all([getName(), getVersion()]);
82
- logger.debug("Verbose logging turned on");
83
- if (!args.skipHouston) {
84
- await say(
85
- [
86
- [
87
- "Welcome",
88
- "to",
89
- label("astro", color.bgGreen, color.black),
90
- color.green(`v${version}`) + ",",
91
- `${username}!`
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 dirResponse = await prompts(
114
- {
115
- type: "text",
116
- name: "directory",
117
- message: "Where would you like to create your new project?",
118
- initial: generateProjectName(),
119
- validate(value) {
120
- if (!isValidProjectDirectory(value)) {
121
- return notEmptyMsg(value);
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
- { onCancel: () => ora().info(dim("Operation cancelled. See you later, astronaut!")) }
144
- );
145
- if (!options.template || options.template === true) {
146
- ora().info(dim("No template provided. See you later, astronaut!"));
147
- process.exit(1);
148
- }
149
- let templateSpinner = await loadWithRocketGradient("Copying project files...");
150
- const hash = args.commit ? `#${args.commit}` : "";
151
- const isThirdParty = options.template.includes("/");
152
- const templateTarget = isThirdParty ? options.template : `withastro/astro/examples/${options.template}#latest`;
153
- if (!args.dryRun) {
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(`${templateTarget}${hash}`, {
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
- fs.rmdirSync(cwd);
777
+ fs3.rmdirSync(ctx.cwd);
163
778
  if (err.message.includes("404")) {
164
- console.error(`Could not find template ${color.underline(options.template)}!`);
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
- process.exit(1);
783
+ ctx.exit(1);
181
784
  }
182
- await Promise.all(
183
- FILES_TO_REMOVE.map(async (file) => {
184
- const fileLoc = path.resolve(path.join(cwd, file));
185
- if (fs.existsSync(fileLoc)) {
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
- installSpinner.text = green("Packages installed!");
231
- installSpinner.succeed();
232
- } else {
233
- await info("No problem!", "Remember to install dependencies after setup.");
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
- const gitResponse = args.y ? true : (await prompts(
236
- {
237
- type: "confirm",
238
- name: "git",
239
- message: `Would you like to initialize a new git repository? ${reset(
240
- dim("(optional)")
241
- )}`,
242
- initial: true
243
- },
244
- {
245
- onCancel: () => {
246
- ora().info(
247
- dim("Operation cancelled. No worries, your project folder has already been created")
248
- );
249
- process.exit(1);
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
- )).git;
253
- if (args.dryRun) {
254
- ora().info(dim(`--dry-run enabled, skipping.`));
255
- } else if (gitResponse) {
256
- const gitDir = "./.git";
257
- if (fs.existsSync(gitDir)) {
258
- ora().info(dim("A .git directory already exists. Skipping creating a new Git repository."));
259
- } else {
260
- await execaCommand("git init", { cwd });
261
- ora().succeed("Git repository created!");
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
- let tsResponse = args.typescript || (await prompts(
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
- name: "typescript",
277
- message: "How would you like to setup TypeScript?",
913
+ label: title("use"),
914
+ message: `How strict should TypeScript be?`,
915
+ initial: "strict",
278
916
  choices: [
279
- { value: "strict", title: "Strict", description: "(recommended)" },
280
- { value: "strictest", title: "Strictest" },
281
- { value: "base", title: "Relaxed" },
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
- onCancel: () => {
287
- ora().info(
288
- dim(
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
- )).typescript;
296
- if (tsResponse === "unsure") {
297
- await typescriptByDefault();
298
- tsResponse = "base";
299
- }
300
- if (args.dryRun) {
301
- ora().info(dim(`--dry-run enabled, skipping.`));
302
- } else if (tsResponse) {
303
- const templateTSConfigPath = path.join(cwd, "tsconfig.json");
304
- fs.readFile(templateTSConfigPath, (err, data) => {
305
- if (err && err.code === "ENOENT") {
306
- fs.writeFileSync(
307
- templateTSConfigPath,
308
- stringify({ extends: `astro/tsconfigs/${tsResponse ?? "base"}` }, null, 2)
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
- ora().succeed("TypeScript settings applied!");
951
+ } else {
327
952
  }
328
- let projectDir = path.relative(process.cwd(), cwd);
329
- const devCmd = pkgManager === "npm" ? "npm run dev" : `${pkgManager} dev`;
330
- await nextSteps({ projectDir, devCmd });
331
- if (!args.skipHouston) {
332
- await say(["Good luck out there, astronaut!"]);
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
- function emojiWithFallback(char, fallback) {
336
- return process.platform !== "win32" ? char : fallback;
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
- mkdirp
1002
+ next,
1003
+ projectName,
1004
+ setStdout,
1005
+ setupTypeScript,
1006
+ template,
1007
+ typescript
341
1008
  };