create-astro 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,6 +42,7 @@ May be provided in place of prompts
42
42
  |:-------------|:----------------------------------------------------|
43
43
  | `--template` | Specify the template name ([list][examples]) |
44
44
  | `--commit` | Specify a specific Git commit or branch to use from this repo (by default, `main` branch of this repo will be used) |
45
+ | `--fancy` | For Windows users, `--fancy` will enable full unicode support |
45
46
 
46
47
  ### Debugging
47
48
 
package/dist/index.js CHANGED
@@ -1,27 +1,33 @@
1
+ import { color, generateProjectName, label, say } from "@astrojs/cli-kit";
2
+ import { forceUnicode, random } from "@astrojs/cli-kit/utils";
1
3
  import { assign, parse, stringify } from "comment-json";
2
- import degit from "degit";
3
4
  import { execa, execaCommand } from "execa";
4
5
  import fs from "fs";
5
- import { bgCyan, black, bold, cyan, dim, gray, green, red, reset, yellow } from "kleur/colors";
6
+ import { downloadTemplate } from "giget";
7
+ import { bold, dim, green, reset, yellow } from "kleur/colors";
6
8
  import ora from "ora";
7
- import os from "os";
8
9
  import path from "path";
9
10
  import prompts from "prompts";
10
11
  import detectPackageManager from "which-pm-runs";
11
12
  import yargs from "yargs-parser";
12
13
  import { loadWithRocketGradient, rocketAscii } from "./gradient.js";
13
- import { defaultLogLevel, logger } from "./logger.js";
14
+ import { logger } from "./logger.js";
15
+ import {
16
+ banner,
17
+ getName,
18
+ getVersion,
19
+ info,
20
+ nextSteps,
21
+ typescriptByDefault,
22
+ welcome
23
+ } from "./messages.js";
14
24
  import { TEMPLATES } from "./templates.js";
15
- function wait(ms) {
16
- return new Promise((resolve) => setTimeout(resolve, ms));
17
- }
18
- function logAndWait(message, ms = 100) {
19
- console.log(message);
20
- return wait(ms);
21
- }
22
25
  const cleanArgv = process.argv.filter((arg) => arg !== "--");
23
- const args = yargs(cleanArgv);
26
+ const args = yargs(cleanArgv, { boolean: ["fancy"] });
24
27
  prompts.override(args);
28
+ if (args.fancy) {
29
+ forceUnicode();
30
+ }
25
31
  function mkdirp(dir) {
26
32
  try {
27
33
  fs.mkdirSync(dir, { recursive: true });
@@ -31,9 +37,6 @@ function mkdirp(dir) {
31
37
  throw e;
32
38
  }
33
39
  }
34
- function isEmpty(dirPath) {
35
- return !fs.existsSync(dirPath) || fs.readdirSync(dirPath).length === 0;
36
- }
37
40
  const VALID_PROJECT_DIRECTORY_SAFE_LIST = [
38
41
  ".DS_Store",
39
42
  ".git",
@@ -68,18 +71,28 @@ function isValidProjectDirectory(dirPath) {
68
71
  });
69
72
  return conflicts.length === 0;
70
73
  }
71
- const { version } = JSON.parse(
72
- fs.readFileSync(new URL("../package.json", import.meta.url), "utf-8")
73
- );
74
74
  const FILES_TO_REMOVE = [".stackblitzrc", "sandbox.config.json", "CHANGELOG.md"];
75
75
  async function main() {
76
76
  var _a;
77
77
  const pkgManager = ((_a = detectPackageManager()) == null ? void 0 : _a.name) || "npm";
78
+ const [username, version] = await Promise.all([getName(), getVersion()]);
78
79
  logger.debug("Verbose logging turned on");
79
- console.log(`
80
- ${bold("Welcome to Astro!")} ${gray(`(create-astro v${version})`)}`);
81
- console.log(`Lets walk through setting up your new Astro project.
82
- `);
80
+ if (!args.skipHouston) {
81
+ await say(
82
+ [
83
+ [
84
+ "Welcome",
85
+ "to",
86
+ label("astro", color.bgGreen, color.black),
87
+ color.green(`v${version}`) + ",",
88
+ `${username}!`
89
+ ],
90
+ random(welcome)
91
+ ],
92
+ { hat: args.fancy ? "\u{1F3A9}" : void 0 }
93
+ );
94
+ await banner(version);
95
+ }
83
96
  let cwd = args["_"][2];
84
97
  if (cwd && isValidProjectDirectory(cwd)) {
85
98
  let acknowledgeProjectDir = ora({
@@ -99,7 +112,7 @@ ${bold("Welcome to Astro!")} ${gray(`(create-astro v${version})`)}`);
99
112
  type: "text",
100
113
  name: "directory",
101
114
  message: "Where would you like to create your new project?",
102
- initial: "./my-astro-site",
115
+ initial: `./${generateProjectName()}`,
103
116
  validate(value) {
104
117
  if (!isValidProjectDirectory(value)) {
105
118
  return notEmptyMsg(value);
@@ -112,6 +125,7 @@ ${bold("Welcome to Astro!")} ${gray(`(create-astro v${version})`)}`);
112
125
  cwd = dirResponse.directory;
113
126
  }
114
127
  if (!cwd) {
128
+ ora().info(dim("No directory provided. See you later, astronaut!"));
115
129
  process.exit(1);
116
130
  }
117
131
  const options = await prompts(
@@ -119,85 +133,34 @@ ${bold("Welcome to Astro!")} ${gray(`(create-astro v${version})`)}`);
119
133
  {
120
134
  type: "select",
121
135
  name: "template",
122
- message: "Which template would you like to use?",
136
+ message: "How would you like to setup your new project?",
123
137
  choices: TEMPLATES
124
138
  }
125
139
  ],
126
140
  { onCancel: () => ora().info(dim("Operation cancelled. See you later, astronaut!")) }
127
141
  );
128
142
  if (!options.template) {
143
+ ora().info(dim("No template provided. See you later, astronaut!"));
129
144
  process.exit(1);
130
145
  }
131
146
  let templateSpinner = await loadWithRocketGradient("Copying project files...");
132
147
  const hash = args.commit ? `#${args.commit}` : "";
133
148
  const isThirdParty = options.template.includes("/");
134
149
  const templateTarget = isThirdParty ? options.template : `withastro/astro/examples/${options.template}#latest`;
135
- const emitter = degit(`${templateTarget}${hash}`, {
136
- cache: false,
137
- force: true,
138
- verbose: defaultLogLevel === "debug" ? true : false
139
- });
140
- logger.debug("Initialized degit with following config:", `${templateTarget}${hash}`, {
141
- cache: false,
142
- force: true,
143
- verbose: defaultLogLevel === "debug" ? true : false
144
- });
145
150
  if (!args.dryRun) {
146
151
  try {
147
- emitter.on("info", (info) => {
148
- logger.debug(info.message);
152
+ await downloadTemplate(`${templateTarget}${hash}`, {
153
+ force: true,
154
+ provider: "github",
155
+ cwd,
156
+ dir: "."
149
157
  });
150
- await emitter.clone(cwd);
151
- if (isValidProjectDirectory(cwd)) {
152
- if (isEmpty(cwd)) {
153
- fs.rmdirSync(cwd);
154
- }
155
- throw new Error(`Error: The provided template (${cyan(options.template)}) does not exist`);
156
- }
157
158
  } catch (err) {
158
- templateSpinner.fail();
159
- logger.debug(err);
160
- console.error(red(err.message));
161
- if (err.message === "zlib: unexpected end of file" || err.message === "TAR_BAD_ARCHIVE: Unrecognized archive format") {
162
- console.log(
163
- yellow(
164
- "Local degit cache seems to be corrupted. For more information check out this issue: https://github.com/withastro/astro/issues/655. "
165
- )
166
- );
167
- const cacheIssueResponse = await prompts({
168
- type: "confirm",
169
- name: "cache",
170
- message: "Would you like us to clear the cache and try again?",
171
- initial: true
172
- });
173
- if (cacheIssueResponse.cache) {
174
- const homeDirectory = os.homedir();
175
- const cacheDir = path.join(homeDirectory, ".degit", "github", "withastro");
176
- fs.rmSync(cacheDir, { recursive: true, force: true, maxRetries: 3 });
177
- templateSpinner = await loadWithRocketGradient("Copying project files...");
178
- try {
179
- await emitter.clone(cwd);
180
- } catch (e) {
181
- logger.debug(e);
182
- console.error(red(e.message));
183
- }
184
- } else {
185
- console.log(
186
- "Okay, no worries! To fix this manually, remove the folder '~/.degit/github/withastro' and rerun the command."
187
- );
188
- }
189
- }
190
- if (err.code === "MISSING_REF") {
191
- console.log(
192
- yellow(
193
- "This seems to be an issue with degit. Please check if you have 'git' installed on your system, and install it if you don't have (https://git-scm.com)."
194
- )
195
- );
196
- console.log(
197
- yellow(
198
- "If you do have 'git' installed, please run this command with the --verbose flag and file a new issue with the command output here: https://github.com/withastro/astro/issues"
199
- )
200
- );
159
+ fs.rmdirSync(cwd);
160
+ if (err.message.includes("404")) {
161
+ console.error(`Template ${color.underline(options.template)} does not exist!`);
162
+ } else {
163
+ console.error(err.message);
201
164
  }
202
165
  process.exit(1);
203
166
  }
@@ -252,7 +215,7 @@ ${bold(
252
215
  installSpinner.text = green("Packages installed!");
253
216
  installSpinner.succeed();
254
217
  } else {
255
- ora().info(dim(`No problem! Remember to install dependencies after setup.`));
218
+ await info("No problem!", "Remember to install dependencies after setup.");
256
219
  }
257
220
  const gitResponse = await prompts(
258
221
  {
@@ -276,7 +239,10 @@ ${bold(
276
239
  await execaCommand("git init", { cwd });
277
240
  ora().succeed("Git repository created!");
278
241
  } else {
279
- ora().info(dim(`Sounds good! You can come back and run ${cyan(`git init`)} later.`));
242
+ await info(
243
+ "Sounds good!",
244
+ `You can come back and run ${color.reset(`git init`)}${color.dim(" later.")}`
245
+ );
280
246
  }
281
247
  const tsResponse = await prompts(
282
248
  {
@@ -284,25 +250,10 @@ ${bold(
284
250
  name: "typescript",
285
251
  message: "How would you like to setup TypeScript?",
286
252
  choices: [
287
- {
288
- title: "Relaxed",
289
- value: "base"
290
- },
291
- {
292
- title: "Strict (recommended)",
293
- description: "Enable `strict` typechecking rules",
294
- value: "strict"
295
- },
296
- {
297
- title: "Strictest",
298
- description: "Enable all typechecking rules",
299
- value: "strictest"
300
- },
301
- {
302
- title: "I prefer not to use TypeScript",
303
- description: `That's cool too!`,
304
- value: "optout"
305
- }
253
+ { value: "strict", title: "Strict", description: "(recommended)" },
254
+ { value: "strictest", title: "Strictest" },
255
+ { value: "base", title: "Relaxed" },
256
+ { value: "unsure", title: "Help me choose" }
306
257
  ]
307
258
  },
308
259
  {
@@ -316,16 +267,9 @@ ${bold(
316
267
  }
317
268
  }
318
269
  );
319
- if (tsResponse.typescript === "optout") {
320
- console.log(``);
321
- ora().warn(yellow(bold(`Astro \u2764\uFE0F TypeScript!`)));
322
- console.log(` Astro supports TypeScript inside of ".astro" component scripts, so`);
323
- console.log(` we still need to create some TypeScript-related files in your project.`);
324
- console.log(` You can safely ignore these files, but don't delete them!`);
325
- console.log(dim(" (ex: tsconfig.json, src/env.d.ts)"));
326
- console.log(``);
270
+ if (tsResponse.typescript === "unsure") {
271
+ await typescriptByDefault();
327
272
  tsResponse.typescript = "base";
328
- await wait(300);
329
273
  }
330
274
  if (args.dryRun) {
331
275
  ora().info(dim(`--dry-run enabled, skipping.`));
@@ -355,31 +299,10 @@ ${bold(
355
299
  });
356
300
  ora().succeed("TypeScript settings applied!");
357
301
  }
358
- ora().succeed("Setup complete.");
359
- ora({ text: green("Ready for liftoff!") }).succeed();
360
- await wait(300);
361
- console.log(`
362
- ${bgCyan(black(" Next steps "))}
363
- `);
364
302
  let projectDir = path.relative(process.cwd(), cwd);
365
303
  const devCmd = pkgManager === "npm" ? "npm run dev" : `${pkgManager} dev`;
366
- if (projectDir !== "/") {
367
- await logAndWait(
368
- `You can now ${bold(cyan("cd"))} into the ${bold(cyan(projectDir))} project directory.`
369
- );
370
- }
371
- await logAndWait(
372
- `Run ${bold(cyan(devCmd))} to start the Astro dev server. ${bold(cyan("CTRL-C"))} to close.`
373
- );
374
- await logAndWait(
375
- `Add frameworks like ${bold(cyan("react"))} and ${bold(
376
- cyan("tailwind")
377
- )} to your project using ${bold(cyan("astro add"))}`
378
- );
379
- await logAndWait("");
380
- await logAndWait(`Stuck? Come join us at ${bold(cyan("https://astro.build/chat"))}`, 750);
381
- await logAndWait(dim("Good luck out there, astronaut."));
382
- await logAndWait("", 300);
304
+ await nextSteps({ projectDir, devCmd });
305
+ await say(["Good luck out there, astronaut!"]);
383
306
  }
384
307
  function emojiWithFallback(char, fallback) {
385
308
  return process.platform !== "win32" ? char : fallback;
@@ -0,0 +1,134 @@
1
+ import { color, label } from "@astrojs/cli-kit";
2
+ import { sleep } from "@astrojs/cli-kit/utils";
3
+ import { exec } from "node:child_process";
4
+ import { get } from "node:https";
5
+ import stripAnsi from "strip-ansi";
6
+ const welcome = [
7
+ `Let's claim your corner of the internet.`,
8
+ `I'll be your assistant today.`,
9
+ `Let's build something awesome!`,
10
+ `Let's build something great!`,
11
+ `Let's build something fast!`,
12
+ `Let's make the web weird!`,
13
+ `Let's make the web a better place!`,
14
+ `Let's create a new project!`,
15
+ `Let's create something unqiue!`,
16
+ `Time to build a new website.`,
17
+ `Time to build a faster website.`,
18
+ `Time to build a sweet new website.`,
19
+ `We're glad to have you on board.`,
20
+ `Keeping the internet weird since 2021.`,
21
+ `Initiating launch sequence...`,
22
+ `Initiating launch sequence... right... now!`,
23
+ `Awaiting further instructions.`
24
+ ];
25
+ function getName() {
26
+ return new Promise((resolve) => {
27
+ exec("git config user.name", { encoding: "utf-8" }, (_1, gitName, _2) => {
28
+ if (gitName.trim()) {
29
+ return resolve(gitName.split(" ")[0].trim());
30
+ }
31
+ exec("whoami", { encoding: "utf-8" }, (_3, whoami, _4) => {
32
+ if (whoami.trim()) {
33
+ return resolve(whoami.split(" ")[0].trim());
34
+ }
35
+ return resolve("astronaut");
36
+ });
37
+ });
38
+ });
39
+ }
40
+ let v;
41
+ function getVersion() {
42
+ return new Promise((resolve) => {
43
+ if (v)
44
+ return resolve(v);
45
+ get("https://registry.npmjs.org/astro/latest", (res) => {
46
+ let body = "";
47
+ res.on("data", (chunk) => body += chunk);
48
+ res.on("end", () => {
49
+ const { version } = JSON.parse(body);
50
+ v = version;
51
+ resolve(version);
52
+ });
53
+ });
54
+ });
55
+ }
56
+ async function banner(version) {
57
+ return console.log(
58
+ `
59
+ ${label("astro", color.bgGreen, color.black)} ${color.green(
60
+ color.bold(`v${version}`)
61
+ )} ${color.bold("Launch sequence initiated.")}
62
+ `
63
+ );
64
+ }
65
+ async function info(prefix, text) {
66
+ await sleep(100);
67
+ if (process.stdout.columns < 80) {
68
+ console.log(`${color.cyan("\u25FC")} ${color.cyan(prefix)}`);
69
+ console.log(`${" ".repeat(3)}${color.dim(text)}
70
+ `);
71
+ } else {
72
+ console.log(`${color.cyan("\u25FC")} ${color.cyan(prefix)} ${color.dim(text)}
73
+ `);
74
+ }
75
+ }
76
+ async function error(prefix, text) {
77
+ if (process.stdout.columns < 80) {
78
+ console.log(`${" ".repeat(5)} ${color.red("\u25B2")} ${color.red(prefix)}`);
79
+ console.log(`${" ".repeat(9)}${color.dim(text)}`);
80
+ } else {
81
+ console.log(`${" ".repeat(5)} ${color.red("\u25B2")} ${color.red(prefix)} ${color.dim(text)}`);
82
+ }
83
+ }
84
+ async function typescriptByDefault() {
85
+ await info(`Cool!`, "Astro comes with TypeScript support enabled by default.");
86
+ console.log(
87
+ `${" ".repeat(3)}${color.dim(`We'll default to the most relaxed settings for you.`)}`
88
+ );
89
+ await sleep(300);
90
+ }
91
+ async function nextSteps({ projectDir, devCmd }) {
92
+ const max = process.stdout.columns;
93
+ const prefix = max < 80 ? " " : " ".repeat(9);
94
+ await sleep(200);
95
+ console.log(
96
+ `
97
+ ${color.bgCyan(` ${color.black("next")} `)} ${color.bold(
98
+ "Liftoff confirmed. Explore your project!"
99
+ )}`
100
+ );
101
+ await sleep(100);
102
+ if (projectDir !== "") {
103
+ const enter = [
104
+ `
105
+ ${prefix}Enter your project directory using`,
106
+ color.cyan(`cd ./${projectDir}`, "")
107
+ ];
108
+ const len = enter[0].length + stripAnsi(enter[1]).length;
109
+ console.log(enter.join(len > max ? "\n" + prefix : " "));
110
+ }
111
+ console.log(
112
+ `${prefix}Run ${color.cyan(devCmd)} to start the dev server. ${color.cyan("CTRL+C")} to stop.`
113
+ );
114
+ await sleep(100);
115
+ console.log(
116
+ `${prefix}Add frameworks like ${color.cyan(`react`)} or ${color.cyan(
117
+ "tailwind"
118
+ )} using ${color.cyan("astro add")}.`
119
+ );
120
+ await sleep(100);
121
+ console.log(`
122
+ ${prefix}Stuck? Join us at ${color.cyan(`https://astro.build/chat`)}`);
123
+ await sleep(200);
124
+ }
125
+ export {
126
+ banner,
127
+ error,
128
+ getName,
129
+ getVersion,
130
+ info,
131
+ nextSteps,
132
+ typescriptByDefault,
133
+ welcome
134
+ };
package/dist/templates.js CHANGED
@@ -1,24 +1,7 @@
1
1
  const TEMPLATES = [
2
- {
3
- title: "Just the basics (recommended)",
4
- value: "basics"
5
- },
6
- {
7
- title: "Blog",
8
- value: "blog"
9
- },
10
- {
11
- title: "Portfolio",
12
- value: "portfolio"
13
- },
14
- {
15
- title: "Documentation Site",
16
- value: "docs"
17
- },
18
- {
19
- title: "Empty project",
20
- value: "minimal"
21
- }
2
+ { value: "basics", title: "a few best practices (recommended)" },
3
+ { value: "blog", title: "a personal website starter kit" },
4
+ { value: "minimal", title: "an empty project" }
22
5
  ];
23
6
  export {
24
7
  TEMPLATES
@@ -0,0 +1,11 @@
1
+ export declare const welcome: string[];
2
+ export declare function getName(): Promise<unknown>;
3
+ export declare function getVersion(): Promise<string>;
4
+ export declare function banner(version: string): Promise<void>;
5
+ export declare function info(prefix: string, text: string): Promise<void>;
6
+ export declare function error(prefix: string, text: string): Promise<void>;
7
+ export declare function typescriptByDefault(): Promise<void>;
8
+ export declare function nextSteps({ projectDir, devCmd }: {
9
+ projectDir: string;
10
+ devCmd: string;
11
+ }): Promise<void>;
@@ -1,4 +1,4 @@
1
1
  export declare const TEMPLATES: {
2
- title: string;
3
2
  value: string;
3
+ title: string;
4
4
  }[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-astro",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "author": "withastro",
6
6
  "license": "MIT",
@@ -23,10 +23,11 @@
23
23
  "tsconfigs"
24
24
  ],
25
25
  "dependencies": {
26
+ "@astrojs/cli-kit": "^0.1.3",
26
27
  "chalk": "^5.0.1",
27
28
  "comment-json": "^4.2.3",
28
- "degit": "^2.8.4",
29
29
  "execa": "^6.1.0",
30
+ "giget": "^0.1.7",
30
31
  "kleur": "^4.1.4",
31
32
  "ora": "^6.1.0",
32
33
  "prompts": "^2.4.2",
@@ -41,7 +42,7 @@
41
42
  "@types/prompts": "^2.0.14",
42
43
  "@types/which-pm-runs": "^1.0.0",
43
44
  "@types/yargs-parser": "^21.0.0",
44
- "astro-scripts": "0.0.8",
45
+ "astro-scripts": "0.0.9",
45
46
  "chai": "^4.3.6",
46
47
  "mocha": "^9.2.2",
47
48
  "uvu": "^0.5.3"