create-astro 5.0.2 → 5.0.3

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.
@@ -1,2 +1,2 @@
1
1
  import type { Context } from './context.js';
2
- export declare function dependencies(ctx: Pick<Context, 'install' | 'yes' | 'prompt' | 'packageManager' | 'cwd' | 'dryRun' | 'tasks' | 'add'>): Promise<void>;
2
+ export declare function dependencies(ctx: Pick<Context, 'install' | 'yes' | 'prompt' | 'packageManager' | 'cwd' | 'dryRun' | 'tasks' | 'add' | 'template'>): Promise<void>;
@@ -15,3 +15,4 @@ export declare function removeTemplateMarkerSections(content: string): string;
15
15
  export declare function processTemplateReadme(content: string, packageManager: string): string;
16
16
  export declare function template(ctx: Pick<Context, 'template' | 'prompt' | 'yes' | 'dryRun' | 'exit' | 'tasks'>): Promise<void>;
17
17
  export declare function getTemplateTarget(tmpl: string, ref?: string): string;
18
+ export declare function isThirdPartyTemplate(tmpl: string): boolean;
package/dist/index.js CHANGED
@@ -459,7 +459,7 @@ function printHelp({
459
459
  if (headline) {
460
460
  message.push(
461
461
  linebreak(),
462
- `${title(commandName)} ${color.green(`v${"5.0.2"}`)} ${headline}`
462
+ `${title(commandName)} ${color.green(`v${"5.0.3"}`)} ${headline}`
463
463
  );
464
464
  }
465
465
  if (usage) {
@@ -558,7 +558,7 @@ async function getContext(argv) {
558
558
  packageManager,
559
559
  "astro",
560
560
  getPackageTag(packageSpecifier),
561
- "6.0.6"
561
+ "6.0.7"
562
562
  ),
563
563
  skipHouston,
564
564
  fancy,
@@ -589,8 +589,8 @@ function detectPackageManager() {
589
589
  }
590
590
 
591
591
  // src/actions/dependencies.ts
592
- import fs from "node:fs";
593
- import path from "node:path";
592
+ import fs2 from "node:fs";
593
+ import path2 from "node:path";
594
594
 
595
595
  // ../internal-helpers/dist/cli.js
596
596
  var NPM_PACKAGE_NAME_REGEX = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
@@ -606,7 +606,154 @@ function assertValidPackageName(packageName) {
606
606
  }
607
607
 
608
608
  // src/actions/dependencies.ts
609
+ import { color as color3 } from "@astrojs/cli-kit";
610
+
611
+ // src/actions/template.ts
612
+ import fs from "node:fs";
613
+ import path from "node:path";
609
614
  import { color as color2 } from "@astrojs/cli-kit";
615
+ import { downloadTemplate } from "@bluwy/giget-core";
616
+ function removeTemplateMarkerSections(content) {
617
+ const pattern = /<!--\s*ASTRO:REMOVE:START\s*-->[\s\S]*?<!--\s*ASTRO:REMOVE:END\s*-->/gi;
618
+ let result = content.replace(pattern, "");
619
+ result = result.replace(/\n{3,}/g, "\n\n");
620
+ return result;
621
+ }
622
+ function processTemplateReadme(content, packageManager) {
623
+ let processed = removeTemplateMarkerSections(content);
624
+ if (packageManager !== "npm") {
625
+ processed = processed.replace(/\bnpm run\b/g, packageManager).replace(/\bnpm\b/g, packageManager);
626
+ }
627
+ return processed;
628
+ }
629
+ async function template(ctx) {
630
+ if (!ctx.template && ctx.yes) ctx.template = "basics";
631
+ if (ctx.template) {
632
+ await info("tmpl", `Using ${color2.reset(ctx.template)}${color2.dim(" as project template")}`);
633
+ } else {
634
+ const { template: tmpl } = await ctx.prompt({
635
+ name: "template",
636
+ type: "select",
637
+ label: title("tmpl"),
638
+ message: "How would you like to start your new project?",
639
+ initial: "basics",
640
+ choices: [
641
+ { value: "basics", label: "A basic, helpful starter project", hint: "(recommended)" },
642
+ { value: "blog", label: "Use blog template" },
643
+ { value: "starlight", label: "Use docs (Starlight) template" },
644
+ { value: "minimal", label: "Use minimal (empty) template" }
645
+ ]
646
+ });
647
+ ctx.template = tmpl;
648
+ }
649
+ if (ctx.dryRun) {
650
+ await info("--dry-run", `Skipping template copying`);
651
+ } else if (ctx.template) {
652
+ ctx.tasks.push({
653
+ pending: "Template",
654
+ start: "Template copying...",
655
+ end: "Template copied",
656
+ while: () => copyTemplate(ctx.template, ctx).catch((e) => {
657
+ if (e instanceof Error) {
658
+ error("error", e.message);
659
+ process.exit(1);
660
+ } else {
661
+ error("error", "Unable to clone template.");
662
+ process.exit(1);
663
+ }
664
+ })
665
+ });
666
+ } else {
667
+ ctx.exit(1);
668
+ }
669
+ }
670
+ var FILES_TO_REMOVE = ["CHANGELOG.md", ".codesandbox"];
671
+ var FILES_TO_UPDATE = {
672
+ "package.json": (file, overrides) => fs.promises.readFile(file, "utf-8").then((value) => {
673
+ const indent = /(^\s+)/m.exec(value)?.[1] ?? " ";
674
+ return fs.promises.writeFile(
675
+ file,
676
+ JSON.stringify(
677
+ Object.assign(JSON.parse(value), Object.assign(overrides, { private: void 0 })),
678
+ null,
679
+ indent
680
+ ),
681
+ "utf-8"
682
+ );
683
+ })
684
+ };
685
+ function getTemplateTarget(tmpl, ref = "latest") {
686
+ if (tmpl === "starlight" || tmpl.startsWith("starlight/")) {
687
+ const [, starter = "basics"] = tmpl.split("/");
688
+ return `github:withastro/starlight/examples/${starter}`;
689
+ }
690
+ if (isThirdPartyTemplate(tmpl)) return tmpl;
691
+ if (ref === "latest") {
692
+ return `github:withastro/astro#examples/${tmpl}`;
693
+ } else {
694
+ return `github:withastro/astro/examples/${tmpl}#${ref}`;
695
+ }
696
+ }
697
+ function isThirdPartyTemplate(tmpl) {
698
+ if (tmpl === "starlight" || tmpl.startsWith("starlight/")) return false;
699
+ return tmpl.includes("/");
700
+ }
701
+ async function copyTemplate(tmpl, ctx) {
702
+ const templateTarget = getTemplateTarget(tmpl, ctx.ref);
703
+ if (!ctx.dryRun) {
704
+ try {
705
+ await downloadTemplate(templateTarget, {
706
+ force: true,
707
+ cwd: ctx.cwd,
708
+ dir: "."
709
+ });
710
+ const readmePath = path.resolve(ctx.cwd, "README.md");
711
+ if (fs.existsSync(readmePath)) {
712
+ const readme = fs.readFileSync(readmePath, "utf8");
713
+ const processedReadme = processTemplateReadme(readme, ctx.packageManager);
714
+ fs.writeFileSync(readmePath, processedReadme);
715
+ }
716
+ } catch (err) {
717
+ if (ctx.cwd !== "." && ctx.cwd !== "./" && !ctx.cwd.startsWith("../")) {
718
+ try {
719
+ fs.rmdirSync(ctx.cwd);
720
+ } catch (_) {
721
+ }
722
+ }
723
+ if (err.message?.includes("404")) {
724
+ throw new Error(`Template ${color2.reset(tmpl)} ${color2.dim("does not exist!")}`);
725
+ }
726
+ if (err.message) {
727
+ error("error", err.message);
728
+ }
729
+ try {
730
+ if ("cause" in err) {
731
+ error("error", err.cause);
732
+ if ("cause" in err.cause) {
733
+ error("error", err.cause?.cause);
734
+ }
735
+ }
736
+ } catch {
737
+ }
738
+ throw new Error(`Unable to download template ${color2.reset(tmpl)}`);
739
+ }
740
+ const removeFiles = FILES_TO_REMOVE.map(async (file) => {
741
+ const fileLoc = path.resolve(path.join(ctx.cwd, file));
742
+ if (fs.existsSync(fileLoc)) {
743
+ return fs.promises.rm(fileLoc, { recursive: true });
744
+ }
745
+ });
746
+ const updateFiles = Object.entries(FILES_TO_UPDATE).map(async ([file, update]) => {
747
+ const fileLoc = path.resolve(path.join(ctx.cwd, file));
748
+ if (fs.existsSync(fileLoc)) {
749
+ return update(fileLoc, { name: ctx.projectName });
750
+ }
751
+ });
752
+ await Promise.all([...removeFiles, ...updateFiles]);
753
+ }
754
+ }
755
+
756
+ // src/actions/dependencies.ts
610
757
  async function dependencies(ctx) {
611
758
  let deps = ctx.install ?? ctx.yes;
612
759
  if (deps === void 0) {
@@ -626,6 +773,12 @@ async function dependencies(ctx) {
626
773
  assertValidPackageName(addValue);
627
774
  }
628
775
  }
776
+ if (deps && ctx.template && isThirdPartyTemplate(ctx.template)) {
777
+ await info(
778
+ "warn",
779
+ `Third-party template detected. Installing dependencies may run lifecycle scripts. Continue only if you trust this template. Use ${color3.bold("--no-install")} to skip automatic install.`
780
+ );
781
+ }
629
782
  if (ctx.dryRun) {
630
783
  await info(
631
784
  "--dry-run",
@@ -640,7 +793,7 @@ async function dependencies(ctx) {
640
793
  error("error", e);
641
794
  error(
642
795
  "error",
643
- `Dependencies failed to install, please run ${color2.bold(
796
+ `Dependencies failed to install, please run ${color3.bold(
644
797
  ctx.packageManager + " install"
645
798
  )} to install them manually after setup.`
646
799
  );
@@ -657,7 +810,7 @@ async function dependencies(ctx) {
657
810
  error("error", e);
658
811
  error(
659
812
  "error",
660
- `Failed to add integrations, please run ${color2.bold(
813
+ `Failed to add integrations, please run ${color3.bold(
661
814
  `astro add ${add.join(" ")}`
662
815
  )} to install them manually after setup.`
663
816
  );
@@ -687,17 +840,17 @@ async function install({ packageManager, cwd }) {
687
840
  return shell(packageManager, ["install"], { cwd, timeout: 9e4, stdio: "ignore" });
688
841
  }
689
842
  async function ensureYarnLock({ cwd }) {
690
- const yarnLock = path.join(cwd, "yarn.lock");
691
- if (fs.existsSync(yarnLock)) return;
692
- return fs.promises.writeFile(yarnLock, "", { encoding: "utf-8" });
843
+ const yarnLock = path2.join(cwd, "yarn.lock");
844
+ if (fs2.existsSync(yarnLock)) return;
845
+ return fs2.promises.writeFile(yarnLock, "", { encoding: "utf-8" });
693
846
  }
694
847
 
695
848
  // src/actions/git.ts
696
- import fs2 from "node:fs";
697
- import path2 from "node:path";
698
- import { color as color3 } from "@astrojs/cli-kit";
849
+ import fs3 from "node:fs";
850
+ import path3 from "node:path";
851
+ import { color as color4 } from "@astrojs/cli-kit";
699
852
  async function git(ctx) {
700
- if (fs2.existsSync(path2.join(ctx.cwd, ".git"))) {
853
+ if (fs3.existsSync(path3.join(ctx.cwd, ".git"))) {
701
854
  await info("Nice!", `Git has already been initialized`);
702
855
  return;
703
856
  }
@@ -727,7 +880,7 @@ async function git(ctx) {
727
880
  } else {
728
881
  await info(
729
882
  ctx.yes === false ? "git [skip]" : "Sounds good!",
730
- `You can always run ${color3.reset("git init")}${color3.dim(" manually.")}`
883
+ `You can always run ${color4.reset("git init")}${color4.dim(" manually.")}`
731
884
  );
732
885
  }
733
886
  }
@@ -774,7 +927,7 @@ function help() {
774
927
  }
775
928
 
776
929
  // src/actions/intro.ts
777
- import { color as color4, label as label2 } from "@astrojs/cli-kit";
930
+ import { color as color5, label as label2 } from "@astrojs/cli-kit";
778
931
  async function intro(ctx) {
779
932
  banner();
780
933
  if (!ctx.skipHouston) {
@@ -784,9 +937,9 @@ async function intro(ctx) {
784
937
  [
785
938
  "Welcome",
786
939
  "to",
787
- label2("astro", color4.bgGreen, color4.black),
940
+ label2("astro", color5.bgGreen, color5.black),
788
941
  Promise.resolve(ctx.version).then(
789
- (version) => (version ? color4.green(`v${version}`) : "") + ","
942
+ (version) => (version ? color5.green(`v${version}`) : "") + ","
790
943
  ),
791
944
  Promise.resolve(ctx.username).then((username) => `${username}!`)
792
945
  ],
@@ -798,9 +951,9 @@ async function intro(ctx) {
798
951
  }
799
952
 
800
953
  // src/actions/next-steps.ts
801
- import path3 from "node:path";
954
+ import path4 from "node:path";
802
955
  async function next(ctx) {
803
- let projectDir = path3.relative(process.cwd(), ctx.cwd);
956
+ let projectDir = path4.relative(process.cwd(), ctx.cwd);
804
957
  const commandMap = {
805
958
  npm: "npm run dev",
806
959
  bun: "bun run dev",
@@ -816,11 +969,11 @@ async function next(ctx) {
816
969
  }
817
970
 
818
971
  // src/actions/project-name.ts
819
- import path4 from "node:path";
820
- import { color as color5, generateProjectName } from "@astrojs/cli-kit";
972
+ import path5 from "node:path";
973
+ import { color as color6, generateProjectName } from "@astrojs/cli-kit";
821
974
 
822
975
  // src/actions/shared.ts
823
- import fs3 from "node:fs";
976
+ import fs4 from "node:fs";
824
977
  var VALID_PROJECT_DIRECTORY_SAFE_LIST = [
825
978
  ".DS_Store",
826
979
  ".git",
@@ -846,10 +999,10 @@ var VALID_PROJECT_DIRECTORY_SAFE_LIST = [
846
999
  /^yarn-error\.log/
847
1000
  ];
848
1001
  function isEmpty(dirPath) {
849
- if (!fs3.existsSync(dirPath)) {
1002
+ if (!fs4.existsSync(dirPath)) {
850
1003
  return true;
851
1004
  }
852
- const conflicts = fs3.readdirSync(dirPath).filter((content) => {
1005
+ const conflicts = fs4.readdirSync(dirPath).filter((content) => {
853
1006
  return !VALID_PROJECT_DIRECTORY_SAFE_LIST.some((safeContent) => {
854
1007
  return typeof safeContent === "string" ? content === safeContent : safeContent.test(content);
855
1008
  });
@@ -869,7 +1022,7 @@ async function projectName(ctx) {
869
1022
  await checkCwd(ctx.cwd);
870
1023
  if (!ctx.cwd || !isEmpty(ctx.cwd)) {
871
1024
  if (ctx.cwd && !isEmpty(ctx.cwd)) {
872
- await info("Hmm...", `${color5.reset(`"${ctx.cwd}"`)}${color5.dim(` is not empty!`)}`);
1025
+ await info("Hmm...", `${color6.reset(`"${ctx.cwd}"`)}${color6.dim(` is not empty!`)}`);
873
1026
  }
874
1027
  if (ctx.yes) {
875
1028
  ctx.projectName = generateProjectName();
@@ -901,7 +1054,7 @@ async function projectName(ctx) {
901
1054
  } else {
902
1055
  let name = ctx.cwd;
903
1056
  if (name === "." || name === "./") {
904
- const parts = process.cwd().split(path4.sep);
1057
+ const parts = process.cwd().split(path5.sep);
905
1058
  name = parts[parts.length - 1];
906
1059
  } else if (name.startsWith("./") || name.startsWith("../")) {
907
1060
  const parts = name.split("/");
@@ -917,153 +1070,11 @@ async function checkCwd(cwd) {
917
1070
  const empty = cwd && isEmpty(cwd);
918
1071
  if (empty) {
919
1072
  log("");
920
- await info("dir", `Using ${color5.reset(cwd)}${color5.dim(" as project directory")}`);
1073
+ await info("dir", `Using ${color6.reset(cwd)}${color6.dim(" as project directory")}`);
921
1074
  }
922
1075
  return empty;
923
1076
  }
924
1077
 
925
- // src/actions/template.ts
926
- import fs4 from "node:fs";
927
- import path5 from "node:path";
928
- import { color as color6 } from "@astrojs/cli-kit";
929
- import { downloadTemplate } from "@bluwy/giget-core";
930
- function removeTemplateMarkerSections(content) {
931
- const pattern = /<!--\s*ASTRO:REMOVE:START\s*-->[\s\S]*?<!--\s*ASTRO:REMOVE:END\s*-->/gi;
932
- let result = content.replace(pattern, "");
933
- result = result.replace(/\n{3,}/g, "\n\n");
934
- return result;
935
- }
936
- function processTemplateReadme(content, packageManager) {
937
- let processed = removeTemplateMarkerSections(content);
938
- if (packageManager !== "npm") {
939
- processed = processed.replace(/\bnpm run\b/g, packageManager).replace(/\bnpm\b/g, packageManager);
940
- }
941
- return processed;
942
- }
943
- async function template(ctx) {
944
- if (!ctx.template && ctx.yes) ctx.template = "basics";
945
- if (ctx.template) {
946
- await info("tmpl", `Using ${color6.reset(ctx.template)}${color6.dim(" as project template")}`);
947
- } else {
948
- const { template: tmpl } = await ctx.prompt({
949
- name: "template",
950
- type: "select",
951
- label: title("tmpl"),
952
- message: "How would you like to start your new project?",
953
- initial: "basics",
954
- choices: [
955
- { value: "basics", label: "A basic, helpful starter project", hint: "(recommended)" },
956
- { value: "blog", label: "Use blog template" },
957
- { value: "starlight", label: "Use docs (Starlight) template" },
958
- { value: "minimal", label: "Use minimal (empty) template" }
959
- ]
960
- });
961
- ctx.template = tmpl;
962
- }
963
- if (ctx.dryRun) {
964
- await info("--dry-run", `Skipping template copying`);
965
- } else if (ctx.template) {
966
- ctx.tasks.push({
967
- pending: "Template",
968
- start: "Template copying...",
969
- end: "Template copied",
970
- while: () => copyTemplate(ctx.template, ctx).catch((e) => {
971
- if (e instanceof Error) {
972
- error("error", e.message);
973
- process.exit(1);
974
- } else {
975
- error("error", "Unable to clone template.");
976
- process.exit(1);
977
- }
978
- })
979
- });
980
- } else {
981
- ctx.exit(1);
982
- }
983
- }
984
- var FILES_TO_REMOVE = ["CHANGELOG.md", ".codesandbox"];
985
- var FILES_TO_UPDATE = {
986
- "package.json": (file, overrides) => fs4.promises.readFile(file, "utf-8").then((value) => {
987
- const indent = /(^\s+)/m.exec(value)?.[1] ?? " ";
988
- return fs4.promises.writeFile(
989
- file,
990
- JSON.stringify(
991
- Object.assign(JSON.parse(value), Object.assign(overrides, { private: void 0 })),
992
- null,
993
- indent
994
- ),
995
- "utf-8"
996
- );
997
- })
998
- };
999
- function getTemplateTarget(tmpl, ref = "latest") {
1000
- if (tmpl.startsWith("starlight")) {
1001
- const [, starter = "basics"] = tmpl.split("/");
1002
- return `github:withastro/starlight/examples/${starter}`;
1003
- }
1004
- const isThirdParty = tmpl.includes("/");
1005
- if (isThirdParty) return tmpl;
1006
- if (ref === "latest") {
1007
- return `github:withastro/astro#examples/${tmpl}`;
1008
- } else {
1009
- return `github:withastro/astro/examples/${tmpl}#${ref}`;
1010
- }
1011
- }
1012
- async function copyTemplate(tmpl, ctx) {
1013
- const templateTarget = getTemplateTarget(tmpl, ctx.ref);
1014
- if (!ctx.dryRun) {
1015
- try {
1016
- await downloadTemplate(templateTarget, {
1017
- force: true,
1018
- cwd: ctx.cwd,
1019
- dir: "."
1020
- });
1021
- const readmePath = path5.resolve(ctx.cwd, "README.md");
1022
- if (fs4.existsSync(readmePath)) {
1023
- const readme = fs4.readFileSync(readmePath, "utf8");
1024
- const processedReadme = processTemplateReadme(readme, ctx.packageManager);
1025
- fs4.writeFileSync(readmePath, processedReadme);
1026
- }
1027
- } catch (err) {
1028
- if (ctx.cwd !== "." && ctx.cwd !== "./" && !ctx.cwd.startsWith("../")) {
1029
- try {
1030
- fs4.rmdirSync(ctx.cwd);
1031
- } catch (_) {
1032
- }
1033
- }
1034
- if (err.message?.includes("404")) {
1035
- throw new Error(`Template ${color6.reset(tmpl)} ${color6.dim("does not exist!")}`);
1036
- }
1037
- if (err.message) {
1038
- error("error", err.message);
1039
- }
1040
- try {
1041
- if ("cause" in err) {
1042
- error("error", err.cause);
1043
- if ("cause" in err.cause) {
1044
- error("error", err.cause?.cause);
1045
- }
1046
- }
1047
- } catch {
1048
- }
1049
- throw new Error(`Unable to download template ${color6.reset(tmpl)}`);
1050
- }
1051
- const removeFiles = FILES_TO_REMOVE.map(async (file) => {
1052
- const fileLoc = path5.resolve(path5.join(ctx.cwd, file));
1053
- if (fs4.existsSync(fileLoc)) {
1054
- return fs4.promises.rm(fileLoc, { recursive: true });
1055
- }
1056
- });
1057
- const updateFiles = Object.entries(FILES_TO_UPDATE).map(async ([file, update]) => {
1058
- const fileLoc = path5.resolve(path5.join(ctx.cwd, file));
1059
- if (fs4.existsSync(fileLoc)) {
1060
- return update(fileLoc, { name: ctx.projectName });
1061
- }
1062
- });
1063
- await Promise.all([...removeFiles, ...updateFiles]);
1064
- }
1065
- }
1066
-
1067
1078
  // src/actions/verify.ts
1068
1079
  import dns from "node:dns/promises";
1069
1080
  import { color as color7 } from "@astrojs/cli-kit";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-astro",
3
- "version": "5.0.2",
3
+ "version": "5.0.3",
4
4
  "type": "module",
5
5
  "author": "withastro",
6
6
  "license": "MIT",