create-astro 4.0.1 → 4.1.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 CHANGED
@@ -14,17 +14,23 @@ npm create astro@latest
14
14
  yarn create astro
15
15
  ```
16
16
 
17
- `create-astro` automatically runs in _interactive_ mode, but you can also specify your project name and template with command line arguments.
17
+ **With PNPM:**
18
18
 
19
19
  ```bash
20
- # npm 6.x
21
- npm create astro@latest my-astro-project --template minimal
20
+ pnpm create astro
21
+ ```
22
+
23
+ `create-astro` automatically runs in _interactive_ mode, but you can also specify your project name and template with command line arguments.
22
24
 
23
- # npm 7+, extra double-dash is needed:
25
+ ```bash
26
+ # npm
24
27
  npm create astro@latest my-astro-project -- --template minimal
25
28
 
26
29
  # yarn
27
30
  yarn create astro my-astro-project --template minimal
31
+
32
+ # pnpm
33
+ pnpm create astro my-astro-project --template minimal
28
34
  ```
29
35
 
30
36
  [Check out the full list][examples] of example templates, available on GitHub.
package/create-astro.mjs CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  const currentVersion = process.versions.node;
6
6
  const requiredMajorVersion = parseInt(currentVersion.split('.')[0], 10);
7
- const minimumMajorVersion = 14;
7
+ const minimumMajorVersion = 18;
8
8
 
9
9
  if (requiredMajorVersion < minimumMajorVersion) {
10
10
  console.error(`Node.js v${currentVersion} is out of date and unsupported!`);
@@ -0,0 +1,24 @@
1
+ import { prompt } from '@astrojs/cli-kit';
2
+ export interface Context {
3
+ help: boolean;
4
+ prompt: typeof prompt;
5
+ cwd: string;
6
+ packageManager: string;
7
+ username: Promise<string>;
8
+ version: Promise<string>;
9
+ skipHouston: boolean;
10
+ fancy?: boolean;
11
+ dryRun?: boolean;
12
+ yes?: boolean;
13
+ projectName?: string;
14
+ template?: string;
15
+ ref: string;
16
+ install?: boolean;
17
+ git?: boolean;
18
+ typescript?: string;
19
+ stdin?: typeof process.stdin;
20
+ stdout?: typeof process.stdout;
21
+ exit(code: number): never;
22
+ hat?: string;
23
+ }
24
+ export declare function getContext(argv: string[]): Promise<Context>;
@@ -0,0 +1,2 @@
1
+ import type { Context } from './context.js';
2
+ export declare function dependencies(ctx: Pick<Context, 'install' | 'yes' | 'prompt' | 'packageManager' | 'cwd' | 'dryRun'>): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { Context } from './context.js';
2
+ export declare function git(ctx: Pick<Context, 'cwd' | 'git' | 'yes' | 'prompt' | 'dryRun'>): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare function help(): void;
@@ -0,0 +1,2 @@
1
+ import type { Context } from './context.js';
2
+ export declare function intro(ctx: Pick<Context, 'hat' | 'skipHouston' | 'version' | 'username' | 'fancy'>): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { Context } from './context.js';
2
+ export declare function next(ctx: Pick<Context, 'hat' | 'cwd' | 'packageManager' | 'skipHouston'>): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { Context } from './context.js';
2
+ export declare function projectName(ctx: Pick<Context, 'cwd' | 'prompt' | 'projectName' | 'exit'>): Promise<void>;
@@ -0,0 +1,3 @@
1
+ export declare function isEmpty(dirPath: string): boolean;
2
+ export declare function isValidName(projectName: string): boolean;
3
+ export declare function toValidName(projectName: string): string;
@@ -0,0 +1,4 @@
1
+ import type { Context } from './context.js';
2
+ export declare function template(ctx: Pick<Context, 'template' | 'prompt' | 'dryRun' | 'exit'>): Promise<void>;
3
+ export declare function getTemplateTarget(tmpl: string, ref?: string): string;
4
+ export default function copyTemplate(tmpl: string, ctx: Context): Promise<void>;
@@ -0,0 +1,5 @@
1
+ import type { Context } from './context.js';
2
+ export declare function typescript(ctx: Pick<Context, 'typescript' | 'yes' | 'prompt' | 'dryRun' | 'cwd' | 'exit'>): Promise<void>;
3
+ export declare function setupTypeScript(value: string, { cwd }: {
4
+ cwd: string;
5
+ }): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { Context } from './context.js';
2
+ export declare function verify(ctx: Pick<Context, 'version' | 'dryRun' | 'template' | 'ref' | 'exit'>): Promise<void>;
@@ -0,0 +1,12 @@
1
+ import { getContext } from './actions/context.js';
2
+ import { dependencies } from './actions/dependencies.js';
3
+ import { git } from './actions/git.js';
4
+ import { intro } from './actions/intro.js';
5
+ import { next } from './actions/next-steps.js';
6
+ import { projectName } from './actions/project-name.js';
7
+ import { template } from './actions/template.js';
8
+ import { setupTypeScript, typescript } from './actions/typescript.js';
9
+ import { verify } from './actions/verify.js';
10
+ import { setStdout } from './messages.js';
11
+ export declare function main(): Promise<void>;
12
+ export { dependencies, getContext, git, intro, next, projectName, setStdout, setupTypeScript, template, typescript, verify, };
package/dist/index.js CHANGED
@@ -171,13 +171,12 @@ var require_arg = __commonJS({
171
171
  // src/actions/context.ts
172
172
  var import_arg = __toESM(require_arg(), 1);
173
173
  import { prompt } from "@astrojs/cli-kit";
174
+ import { random } from "@astrojs/cli-kit/utils";
174
175
  import os from "node:os";
175
- import detectPackageManager2 from "which-pm-runs";
176
176
 
177
177
  // src/messages.ts
178
178
  import { color, say as houston, label, spinner as load } from "@astrojs/cli-kit";
179
179
  import { align, sleep } from "@astrojs/cli-kit/utils";
180
- import fetch from "node-fetch-native";
181
180
  import { exec } from "node:child_process";
182
181
 
183
182
  // ../../node_modules/.pnpm/ansi-regex@6.0.1/node_modules/ansi-regex/index.js
@@ -198,9 +197,6 @@ function stripAnsi(string) {
198
197
  return string.replace(regex, "");
199
198
  }
200
199
 
201
- // src/messages.ts
202
- import detectPackageManager from "which-pm-runs";
203
-
204
200
  // src/shell.ts
205
201
  import { spawn } from "node:child_process";
206
202
  import { text as textFromStream } from "node:stream/consumers";
@@ -233,8 +229,7 @@ async function shell(command, flags, opts = {}) {
233
229
  }
234
230
 
235
231
  // src/messages.ts
236
- async function getRegistry() {
237
- const packageManager = detectPackageManager()?.name || "npm";
232
+ async function getRegistry(packageManager) {
238
233
  try {
239
234
  const { stdout: stdout2 } = await shell(packageManager, ["config", "get", "registry"]);
240
235
  return stdout2?.trim()?.replace(/\/$/, "") || "https://registry.npmjs.org";
@@ -287,10 +282,10 @@ var getName = () => new Promise((resolve) => {
287
282
  });
288
283
  });
289
284
  var v;
290
- var getVersion = () => new Promise(async (resolve) => {
285
+ var getVersion = (packageManager) => new Promise(async (resolve) => {
291
286
  if (v)
292
287
  return resolve(v);
293
- let registry = await getRegistry();
288
+ let registry = await getRegistry(packageManager);
294
289
  const { version } = await fetch(`${registry}/astro/latest`, { redirect: "follow" }).then(
295
290
  (res) => res.json(),
296
291
  () => ({ version: "" })
@@ -299,10 +294,11 @@ var getVersion = () => new Promise(async (resolve) => {
299
294
  resolve(version);
300
295
  });
301
296
  var log = (message) => stdout.write(message + "\n");
302
- var banner = async (version) => log(
303
- `
304
- ${label("astro", color.bgGreen, color.black)}${version ? " " + color.green(color.bold(`v${version}`)) : ""} ${color.bold("Launch sequence initiated.")}`
305
- );
297
+ var banner = () => {
298
+ const prefix = `astro`;
299
+ const suffix = `Launch sequence initiated.`;
300
+ log(`${label(prefix, color.bgGreen, color.black)} ${suffix}`);
301
+ };
306
302
  var bannerAbort = () => log(`
307
303
  ${label("astro", color.bgRed)} ${color.bold("Launch sequence aborted.")}`);
308
304
  var info = async (prefix, text2) => {
@@ -388,7 +384,7 @@ function printHelp({
388
384
  if (headline) {
389
385
  message.push(
390
386
  linebreak(),
391
- `${title(commandName)} ${color.green(`v${"4.0.1"}`)} ${headline}`
387
+ `${title(commandName)} ${color.green(`v${"4.1.0"}`)} ${headline}`
392
388
  );
393
389
  }
394
390
  if (usage) {
@@ -434,8 +430,7 @@ async function getContext(argv) {
434
430
  },
435
431
  { argv, permissive: true }
436
432
  );
437
- const pkgManager = detectPackageManager2()?.name ?? "npm";
438
- const [username, version] = await Promise.all([getName(), getVersion()]);
433
+ const packageManager = detectPackageManager() ?? "npm";
439
434
  let cwd = flags["_"][0];
440
435
  let {
441
436
  "--help": help2 = false,
@@ -466,15 +461,16 @@ async function getContext(argv) {
466
461
  const context = {
467
462
  help: help2,
468
463
  prompt,
469
- pkgManager,
470
- username,
471
- version,
464
+ packageManager,
465
+ username: getName(),
466
+ version: getVersion(packageManager),
472
467
  skipHouston,
473
468
  fancy,
474
469
  dryRun,
475
470
  projectName: projectName2,
476
471
  template: template2,
477
472
  ref: ref ?? "latest",
473
+ hat: fancy ? random(["\u{1F3A9}", "\u{1F3A9}", "\u{1F3A9}", "\u{1F3A9}", "\u{1F393}", "\u{1F451}", "\u{1F9E2}", "\u{1F366}"]) : void 0,
478
474
  yes,
479
475
  install: install2 ?? (noInstall ? false : void 0),
480
476
  git: git2 ?? (noGit ? false : void 0),
@@ -486,6 +482,13 @@ async function getContext(argv) {
486
482
  };
487
483
  return context;
488
484
  }
485
+ function detectPackageManager() {
486
+ if (!process.env.npm_config_user_agent)
487
+ return;
488
+ const specifier = process.env.npm_config_user_agent.split(" ")[0];
489
+ const name = specifier.substring(0, specifier.lastIndexOf("/"));
490
+ return name === "npminstall" ? "cnpm" : name;
491
+ }
489
492
 
490
493
  // src/actions/dependencies.ts
491
494
  import { color as color2 } from "@astrojs/cli-kit";
@@ -508,15 +511,15 @@ async function dependencies(ctx) {
508
511
  await info("--dry-run", `Skipping dependency installation`);
509
512
  } else if (deps) {
510
513
  await spinner({
511
- start: `Installing dependencies with ${ctx.pkgManager}...`,
514
+ start: `Installing dependencies with ${ctx.packageManager}...`,
512
515
  end: "Dependencies installed",
513
516
  while: () => {
514
- return install({ pkgManager: ctx.pkgManager, cwd: ctx.cwd }).catch((e) => {
517
+ return install({ packageManager: ctx.packageManager, cwd: ctx.cwd }).catch((e) => {
515
518
  error("error", e);
516
519
  error(
517
520
  "error",
518
521
  `Dependencies failed to install, please run ${color2.bold(
519
- ctx.pkgManager + " install"
522
+ ctx.packageManager + " install"
520
523
  )} to install them manually after setup.`
521
524
  );
522
525
  });
@@ -529,10 +532,10 @@ async function dependencies(ctx) {
529
532
  );
530
533
  }
531
534
  }
532
- async function install({ pkgManager, cwd }) {
533
- if (pkgManager === "yarn")
535
+ async function install({ packageManager, cwd }) {
536
+ if (packageManager === "yarn")
534
537
  await ensureYarnLock({ cwd });
535
- return shell(pkgManager, ["install"], { cwd, timeout: 9e4, stdio: "ignore" });
538
+ return shell(packageManager, ["install"], { cwd, timeout: 9e4, stdio: "ignore" });
536
539
  }
537
540
  async function ensureYarnLock({ cwd }) {
538
541
  const yarnLock = path.join(cwd, "yarn.lock");
@@ -623,26 +626,25 @@ function help() {
623
626
 
624
627
  // src/actions/intro.ts
625
628
  import { color as color4, label as label2 } from "@astrojs/cli-kit";
626
- import { random } from "@astrojs/cli-kit/utils";
629
+ import { random as random2 } from "@astrojs/cli-kit/utils";
627
630
  async function intro(ctx) {
631
+ banner();
628
632
  if (!ctx.skipHouston) {
629
- const hat = ctx.fancy ? random(["\u{1F3A9}", "\u{1F3A9}", "\u{1F451}", "\u{1F9E2}", "\u{1F366}"]) : void 0;
630
633
  await say(
631
634
  [
632
635
  [
633
636
  "Welcome",
634
637
  "to",
635
638
  label2("astro", color4.bgGreen, color4.black),
636
- (ctx.version ? color4.green(`v${ctx.version}`) : "") + ",",
637
- `${ctx.username}!`
639
+ Promise.resolve(ctx.version).then(
640
+ (version) => (version ? color4.green(`v${version}`) : "") + ","
641
+ ),
642
+ Promise.resolve(ctx.username).then((username) => `${username}!`)
638
643
  ],
639
- random(welcome)
644
+ random2(welcome)
640
645
  ],
641
- { hat }
646
+ { clear: true, hat: ctx.hat }
642
647
  );
643
- await banner(ctx.version);
644
- } else {
645
- await banner(ctx.version);
646
648
  }
647
649
  }
648
650
 
@@ -650,10 +652,16 @@ async function intro(ctx) {
650
652
  import path3 from "node:path";
651
653
  async function next(ctx) {
652
654
  let projectDir = path3.relative(process.cwd(), ctx.cwd);
653
- const devCmd = ctx.pkgManager === "npm" ? "npm run dev" : ctx.pkgManager === "bun" ? "bun run dev" : `${ctx.pkgManager} dev`;
655
+ const commandMap = {
656
+ npm: "npm run dev",
657
+ bun: "bun run dev",
658
+ yarn: "yarn dev",
659
+ pnpm: "pnpm dev"
660
+ };
661
+ const devCmd = commandMap[ctx.packageManager] || "npm run dev";
654
662
  await nextSteps({ projectDir, devCmd });
655
663
  if (!ctx.skipHouston) {
656
- await say(["Good luck out there, astronaut! \u{1F680}"]);
664
+ await say(["Good luck out there, astronaut! \u{1F680}"], { hat: ctx.hat });
657
665
  }
658
666
  return;
659
667
  }
@@ -730,7 +738,7 @@ async function projectName(ctx) {
730
738
  return true;
731
739
  }
732
740
  });
733
- ctx.cwd = name;
741
+ ctx.cwd = name.trim();
734
742
  ctx.projectName = toValidName(name);
735
743
  } else {
736
744
  let name = ctx.cwd;
@@ -1041,7 +1049,6 @@ async function setupTypeScript(value, { cwd }) {
1041
1049
 
1042
1050
  // src/actions/verify.ts
1043
1051
  import { color as color8 } from "@astrojs/cli-kit";
1044
- import fetch2 from "node-fetch-native";
1045
1052
  import dns from "node:dns/promises";
1046
1053
  async function verify(ctx) {
1047
1054
  if (!ctx.dryRun) {
@@ -1074,14 +1081,14 @@ async function verifyTemplate(tmpl, ref) {
1074
1081
  const target = getTemplateTarget(tmpl, ref);
1075
1082
  const { repo, subdir, ref: branch } = parseGitURI(target.replace("github:", ""));
1076
1083
  const url = new URL(`/repos/${repo}/contents${subdir}?ref=${branch}`, "https://api.github.com/");
1077
- let res = await fetch2(url.toString(), {
1084
+ let res = await fetch(url.toString(), {
1078
1085
  headers: {
1079
1086
  Accept: "application/vnd.github+json",
1080
1087
  "X-GitHub-Api-Version": "2022-11-28"
1081
1088
  }
1082
1089
  });
1083
1090
  if (res.status === 403) {
1084
- res = await fetch2(`https://github.com/${repo}/tree/${branch}${subdir}`);
1091
+ res = await fetch(`https://github.com/${repo}/tree/${branch}${subdir}`);
1085
1092
  }
1086
1093
  return res.status === 200;
1087
1094
  }
@@ -1102,6 +1109,7 @@ var exit = () => process.exit(0);
1102
1109
  process.on("SIGINT", exit);
1103
1110
  process.on("SIGTERM", exit);
1104
1111
  async function main() {
1112
+ console.clear();
1105
1113
  const cleanArgv = process.argv.slice(2).filter((arg2) => arg2 !== "--");
1106
1114
  const ctx = await getContext(cleanArgv);
1107
1115
  if (ctx.help) {
@@ -0,0 +1,32 @@
1
+ /** @internal Used to mock `process.stdout.write` for testing purposes */
2
+ export declare function setStdout(writable: typeof process.stdout): void;
3
+ export declare function say(messages: string | string[], { clear, hat }?: {
4
+ clear?: boolean | undefined;
5
+ hat?: string | undefined;
6
+ }): Promise<void>;
7
+ export declare function spinner(args: {
8
+ start: string;
9
+ end: string;
10
+ while: (...args: any) => Promise<any>;
11
+ }): Promise<void>;
12
+ export declare const title: (text: string) => string;
13
+ export declare const welcome: string[];
14
+ export declare const getName: () => Promise<string>;
15
+ export declare const getVersion: (packageManager: string) => Promise<string>;
16
+ export declare const log: (message: string) => boolean;
17
+ export declare const banner: () => void;
18
+ export declare const bannerAbort: () => boolean;
19
+ export declare const info: (prefix: string, text: string) => Promise<void>;
20
+ export declare const error: (prefix: string, text: string) => Promise<void>;
21
+ export declare const typescriptByDefault: () => Promise<void>;
22
+ export declare const nextSteps: ({ projectDir, devCmd }: {
23
+ projectDir: string;
24
+ devCmd: string;
25
+ }) => Promise<void>;
26
+ export declare function printHelp({ commandName, headline, usage, tables, description, }: {
27
+ commandName: string;
28
+ headline?: string;
29
+ usage?: string;
30
+ tables?: Record<string, [command: string, help: string][]>;
31
+ description?: string;
32
+ }): void;
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import type { StdioOptions } from 'node:child_process';
3
+ export interface ExecaOptions {
4
+ cwd?: string | URL;
5
+ stdio?: StdioOptions;
6
+ timeout?: number;
7
+ }
8
+ export interface Output {
9
+ stdout: string;
10
+ stderr: string;
11
+ exitCode: number;
12
+ }
13
+ export declare function shell(command: string, flags: string[], opts?: ExecaOptions): Promise<Output>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-astro",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "type": "module",
5
5
  "author": "withastro",
6
6
  "license": "MIT",
@@ -25,14 +25,10 @@
25
25
  "//a": "MOST PACKAGES SHOULD GO IN DEV_DEPENDENCIES! THEY WILL BE BUNDLED.",
26
26
  "//b": "DEPENDENCIES IS FOR UNBUNDLED PACKAGES",
27
27
  "dependencies": {
28
- "@astrojs/cli-kit": "^0.2.3",
29
- "execa": "^8.0.1",
30
- "giget": "1.1.2",
31
- "node-fetch-native": "^1.4.0",
32
- "which-pm-runs": "^1.1.0"
28
+ "@astrojs/cli-kit": "^0.3.0",
29
+ "giget": "1.1.2"
33
30
  },
34
31
  "devDependencies": {
35
- "@types/which-pm-runs": "^1.0.0",
36
32
  "arg": "^5.0.2",
37
33
  "chai": "^4.3.7",
38
34
  "mocha": "^10.2.0",