create-zenith 1.3.18 → 1.3.19

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
@@ -17,7 +17,7 @@ The official CLI for scaffolding new Zenith applications. Fast, animated, and de
17
17
  - **Interactive UX**: Built with `@clack/prompts` for intuitive arrow-key navigation and clear visual indicators.
18
18
  - **Reliable Fallbacks**: Automatically detects CI environments and non-TTY pipes to provide clean, static output.
19
19
  - **Smart Detection**: automatically detects your preferred package manager (Bun, pnpm, Yarn, or npm).
20
- - **Batteries Included**: Optional setup for ESLint, Prettier, and TypeScript path aliases.
20
+ - **Tool-Agnostic Output**: ESLint, Prettier, and TypeScript path aliases are opt-in. If you answer `No`, the generated project contains no scripts, dependencies, config files, or ignore files for that tool.
21
21
 
22
22
  ## Quick Start
23
23
 
@@ -40,6 +40,21 @@ pnpm create zenith
40
40
  | `-h, --help` | Show usage information |
41
41
  | `-v, --version` | Show version number |
42
42
 
43
+ ## Optional Tooling Contract
44
+
45
+ During scaffold, `create-zenith` asks whether to include:
46
+
47
+ - ESLint
48
+ - Prettier
49
+ - TypeScript path aliases
50
+
51
+ Tooling behavior is strict:
52
+
53
+ - If you enable ESLint, the project gets `eslint.config.js`, lint scripts, and matching ESLint dependencies.
54
+ - If you disable ESLint, the project contains zero ESLint references.
55
+ - If you enable Prettier, the project gets `.prettierrc`, `.prettierignore`, a format script, and the Prettier dependency.
56
+ - If you disable Prettier, the project contains zero Prettier references.
57
+
43
58
  ## Beta Version Pinning
44
59
 
45
60
  Zenith beta currently pins `@zenithbuild/core` to `0.5.0-beta.2.20` and leaf packages (compiler, cli, runtime, router, bundler) to `0.5.0-beta.2.20`. This is intentional — core contains the CLI entry point and may bump independently for bin/CLI fixes without touching the engine.
@@ -50,6 +65,7 @@ If you see version mismatches after install, delete `node_modules` and `package-
50
65
 
51
66
  - Generated apps now depend on `@zenithbuild/core@latest` so new installs track the current stable framework release.
52
67
  - Template downloads now resolve from `zenithbuild/framework`, which is the active monorepo source of truth.
68
+ - ESLint and Prettier are now feature overlays, so opting out leaves no stray config or dependency references in the scaffolded app.
53
69
  - Verified scaffold → install → build coverage lives in `tests/template-regression.spec.mjs`.
54
70
 
55
71
  ## Development
package/dist/cli.js CHANGED
@@ -2819,6 +2819,72 @@ var log = {
2819
2819
  message: (message) => getUiMode(process).plain ? console.log(message) : M2.message(message)
2820
2820
  };
2821
2821
 
2822
+ // src/template-features.ts
2823
+ var FEATURE_DEFINITIONS = {
2824
+ eslint: {
2825
+ templatePath: "templates/features/eslint",
2826
+ packagePatch: {
2827
+ scripts: {
2828
+ lint: "eslint ."
2829
+ },
2830
+ devDependencies: {
2831
+ eslint: "^9.39.2",
2832
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
2833
+ "@typescript-eslint/parser": "^8.53.0"
2834
+ }
2835
+ }
2836
+ },
2837
+ prettier: {
2838
+ templatePath: "templates/features/prettier",
2839
+ packagePatch: {
2840
+ scripts: {
2841
+ format: "prettier --write ."
2842
+ },
2843
+ devDependencies: {
2844
+ prettier: "^3.7.4"
2845
+ }
2846
+ }
2847
+ }
2848
+ };
2849
+ function mergeRecord(target, patch) {
2850
+ if (!patch) {
2851
+ return target;
2852
+ }
2853
+ return { ...target || {}, ...patch };
2854
+ }
2855
+ function selectedTemplateFeaturePaths(options) {
2856
+ const paths = [];
2857
+ if (options.eslint) {
2858
+ paths.push(FEATURE_DEFINITIONS.eslint.templatePath);
2859
+ }
2860
+ if (options.prettier) {
2861
+ paths.push(FEATURE_DEFINITIONS.prettier.templatePath);
2862
+ }
2863
+ return paths;
2864
+ }
2865
+ function applyPackageFeatures(manifest, options) {
2866
+ const nextManifest = {
2867
+ ...manifest,
2868
+ scripts: { ...manifest.scripts || {} },
2869
+ devDependencies: { ...manifest.devDependencies || {} }
2870
+ };
2871
+ for (const featureName of Object.keys(FEATURE_DEFINITIONS)) {
2872
+ if (!options[featureName]) {
2873
+ continue;
2874
+ }
2875
+ const patch = FEATURE_DEFINITIONS[featureName].packagePatch;
2876
+ nextManifest.scripts = mergeRecord(nextManifest.scripts, patch.scripts);
2877
+ nextManifest.devDependencies = mergeRecord(nextManifest.devDependencies, patch.devDependencies);
2878
+ }
2879
+ if (nextManifest.scripts && Object.keys(nextManifest.scripts).length === 0) {
2880
+ delete nextManifest.scripts;
2881
+ }
2882
+ if (nextManifest.devDependencies && Object.keys(nextManifest.devDependencies).length === 0) {
2883
+ delete nextManifest.devDependencies;
2884
+ }
2885
+ return nextManifest;
2886
+ }
2887
+
2822
2888
  // src/index.ts
2823
2889
  var GITHUB_REPO = "zenithbuild/framework";
2824
2890
  var DEFAULT_TEMPLATE = "examples/starter";
@@ -2845,6 +2911,15 @@ function resolveLocalTemplatePath(templatePath) {
2845
2911
  const candidate = path.resolve(__dirname2, "..", templatePath);
2846
2912
  return fs.existsSync(candidate) ? candidate : null;
2847
2913
  }
2914
+ function copyDirectoryContents(sourceDir, targetDir) {
2915
+ fs.mkdirSync(targetDir, { recursive: true });
2916
+ for (const entry of fs.readdirSync(sourceDir)) {
2917
+ fs.cpSync(path.join(sourceDir, entry), path.join(targetDir, entry), {
2918
+ recursive: true,
2919
+ force: true
2920
+ });
2921
+ }
2922
+ }
2848
2923
  function detectPackageManager() {
2849
2924
  const userAgent = process.env.npm_config_user_agent || "";
2850
2925
  if (userAgent.includes("bun"))
@@ -2875,16 +2950,22 @@ function hasGit() {
2875
2950
  return false;
2876
2951
  }
2877
2952
  }
2878
- async function downloadTemplate(targetDir, templatePath) {
2879
- const localTemplatePath = resolveLocalTemplatePath(templatePath);
2953
+ async function downloadTemplate(targetDir, templatePaths) {
2954
+ const localTemplatePaths = templatePaths.map((templatePath) => ({
2955
+ templatePath,
2956
+ localPath: resolveLocalTemplatePath(templatePath)
2957
+ }));
2880
2958
  const forceLocal = process.env.CREATE_ZENITH_TEMPLATE_MODE === "local" || flagEnabled2(process.env.CREATE_ZENITH_OFFLINE);
2881
2959
  const preferLocal = process.env.CREATE_ZENITH_PREFER_LOCAL !== "0";
2882
- if (localTemplatePath && (forceLocal || preferLocal)) {
2883
- fs.cpSync(localTemplatePath, targetDir, { recursive: true });
2960
+ if (localTemplatePaths.every((entry) => entry.localPath) && (forceLocal || preferLocal)) {
2961
+ for (const entry of localTemplatePaths) {
2962
+ copyDirectoryContents(entry.localPath, targetDir);
2963
+ }
2884
2964
  return;
2885
2965
  }
2886
- if (forceLocal && !localTemplatePath) {
2887
- throw new Error(`Local template not found: ${templatePath}`);
2966
+ if (forceLocal) {
2967
+ const missingPath = localTemplatePaths.find((entry) => !entry.localPath)?.templatePath;
2968
+ throw new Error(`Local template not found: ${missingPath}`);
2888
2969
  }
2889
2970
  const tempDir = path.join(os2.tmpdir(), `zenith-template-${Date.now()}`);
2890
2971
  try {
@@ -2892,13 +2973,15 @@ async function downloadTemplate(targetDir, templatePath) {
2892
2973
  execSync(`git clone --depth 1 --filter=blob:none --sparse https://github.com/${GITHUB_REPO}.git "${tempDir}"`, {
2893
2974
  stdio: "pipe"
2894
2975
  });
2895
- const repoTemplatePath = `packages/create-zenith/${templatePath}`;
2896
- execSync(`git sparse-checkout set ${repoTemplatePath}`, {
2976
+ const repoTemplatePaths = templatePaths.map((templatePath) => `packages/create-zenith/${templatePath}`);
2977
+ execSync(`git sparse-checkout set ${repoTemplatePaths.join(" ")}`, {
2897
2978
  cwd: tempDir,
2898
2979
  stdio: "pipe"
2899
2980
  });
2900
- const templateSource = path.join(tempDir, repoTemplatePath);
2901
- fs.cpSync(templateSource, targetDir, { recursive: true });
2981
+ for (const repoTemplatePath of repoTemplatePaths) {
2982
+ const templateSource = path.join(tempDir, repoTemplatePath);
2983
+ copyDirectoryContents(templateSource, targetDir);
2984
+ }
2902
2985
  } else {
2903
2986
  const tarballUrl = `https://github.com/${GITHUB_REPO}/archive/refs/heads/main.tar.gz`;
2904
2987
  const tarballPath = path.join(os2.tmpdir(), `zenith-${Date.now()}.tar.gz`);
@@ -2909,8 +2992,10 @@ async function downloadTemplate(targetDir, templatePath) {
2909
2992
  if (!extractedDir) {
2910
2993
  throw new Error("Failed to extract template from GitHub");
2911
2994
  }
2912
- const templateSource = path.join(tempDir, extractedDir, "packages/create-zenith", templatePath);
2913
- fs.cpSync(templateSource, targetDir, { recursive: true });
2995
+ for (const templatePath of templatePaths) {
2996
+ const templateSource = path.join(tempDir, extractedDir, "packages/create-zenith", templatePath);
2997
+ copyDirectoryContents(templateSource, targetDir);
2998
+ }
2914
2999
  fs.unlinkSync(tarballPath);
2915
3000
  }
2916
3001
  } finally {
@@ -2919,7 +3004,17 @@ async function downloadTemplate(targetDir, templatePath) {
2919
3004
  }
2920
3005
  }
2921
3006
  }
3007
+ function readOptionOverride(name) {
3008
+ const value = process.env[name];
3009
+ if (value == null || value.trim() === "") {
3010
+ return;
3011
+ }
3012
+ return flagEnabled2(value);
3013
+ }
2922
3014
  async function gatherOptions(providedName, withTailwind) {
3015
+ const eslintOverride = readOptionOverride("CREATE_ZENITH_ESLINT");
3016
+ const prettierOverride = readOptionOverride("CREATE_ZENITH_PRETTIER");
3017
+ const pathAliasOverride = readOptionOverride("CREATE_ZENITH_PATH_ALIAS");
2923
3018
  let name = providedName;
2924
3019
  if (!name) {
2925
3020
  const nameResult = await text({
@@ -2957,9 +3052,9 @@ async function gatherOptions(providedName, withTailwind) {
2957
3052
  log.info("Non-interactive mode detected, using defaults...");
2958
3053
  return {
2959
3054
  name,
2960
- eslint: true,
2961
- prettier: true,
2962
- pathAlias: true,
3055
+ eslint: eslintOverride ?? true,
3056
+ prettier: prettierOverride ?? true,
3057
+ pathAlias: pathAliasOverride ?? true,
2963
3058
  tailwind: withTailwind ?? false
2964
3059
  };
2965
3060
  }
@@ -2969,23 +3064,23 @@ async function gatherOptions(providedName, withTailwind) {
2969
3064
  });
2970
3065
  if (isCancel(tailwindResult))
2971
3066
  handleCancel();
2972
- const eslintResult = await confirm({
3067
+ const eslintResult = eslintOverride ?? await confirm({
2973
3068
  message: "Add ESLint for code linting?",
2974
3069
  initialValue: true
2975
3070
  });
2976
- if (isCancel(eslintResult))
3071
+ if (eslintOverride === undefined && isCancel(eslintResult))
2977
3072
  handleCancel();
2978
- const prettierResult = await confirm({
3073
+ const prettierResult = prettierOverride ?? await confirm({
2979
3074
  message: "Add Prettier for code formatting?",
2980
3075
  initialValue: true
2981
3076
  });
2982
- if (isCancel(prettierResult))
3077
+ if (prettierOverride === undefined && isCancel(prettierResult))
2983
3078
  handleCancel();
2984
- const pathAliasResult = await confirm({
3079
+ const pathAliasResult = pathAliasOverride ?? await confirm({
2985
3080
  message: "Add TypeScript path alias (@/*)?",
2986
3081
  initialValue: true
2987
3082
  });
2988
- if (isCancel(pathAliasResult))
3083
+ if (pathAliasOverride === undefined && isCancel(pathAliasResult))
2989
3084
  handleCancel();
2990
3085
  return {
2991
3086
  name,
@@ -2998,31 +3093,13 @@ async function gatherOptions(providedName, withTailwind) {
2998
3093
  async function createProject(options) {
2999
3094
  const targetDir = path.resolve(process.cwd(), options.name);
3000
3095
  const templatePath = options.tailwind ? TAILWIND_TEMPLATE : DEFAULT_TEMPLATE;
3001
- await downloadTemplate(targetDir, templatePath);
3096
+ const templateFeaturePaths = selectedTemplateFeaturePaths(options);
3097
+ await downloadTemplate(targetDir, [templatePath, ...templateFeaturePaths]);
3002
3098
  const pkgPath = path.join(targetDir, "package.json");
3003
3099
  if (fs.existsSync(pkgPath)) {
3004
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
3100
+ const pkg = applyPackageFeatures(JSON.parse(fs.readFileSync(pkgPath, "utf8")), options);
3005
3101
  pkg.name = options.name;
3006
3102
  pkg.version = "0.1.0";
3007
- if (!options.eslint) {
3008
- delete pkg.devDependencies?.["eslint"];
3009
- delete pkg.devDependencies?.["@typescript-eslint/eslint-plugin"];
3010
- delete pkg.devDependencies?.["@typescript-eslint/parser"];
3011
- delete pkg.scripts?.lint;
3012
- const eslintPath = path.join(targetDir, ".eslintrc.json");
3013
- if (fs.existsSync(eslintPath))
3014
- fs.unlinkSync(eslintPath);
3015
- }
3016
- if (!options.prettier) {
3017
- delete pkg.devDependencies?.["prettier"];
3018
- delete pkg.scripts?.format;
3019
- const prettierRc = path.join(targetDir, ".prettierrc");
3020
- const prettierIgnore = path.join(targetDir, ".prettierignore");
3021
- if (fs.existsSync(prettierRc))
3022
- fs.unlinkSync(prettierRc);
3023
- if (fs.existsSync(prettierIgnore))
3024
- fs.unlinkSync(prettierIgnore);
3025
- }
3026
3103
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 4));
3027
3104
  }
3028
3105
  const tsconfigPath = path.join(targetDir, "tsconfig.json");
package/dist/index.js CHANGED
@@ -2818,6 +2818,72 @@ var log = {
2818
2818
  message: (message) => getUiMode(process).plain ? console.log(message) : M2.message(message)
2819
2819
  };
2820
2820
 
2821
+ // src/template-features.ts
2822
+ var FEATURE_DEFINITIONS = {
2823
+ eslint: {
2824
+ templatePath: "templates/features/eslint",
2825
+ packagePatch: {
2826
+ scripts: {
2827
+ lint: "eslint ."
2828
+ },
2829
+ devDependencies: {
2830
+ eslint: "^9.39.2",
2831
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
2832
+ "@typescript-eslint/parser": "^8.53.0"
2833
+ }
2834
+ }
2835
+ },
2836
+ prettier: {
2837
+ templatePath: "templates/features/prettier",
2838
+ packagePatch: {
2839
+ scripts: {
2840
+ format: "prettier --write ."
2841
+ },
2842
+ devDependencies: {
2843
+ prettier: "^3.7.4"
2844
+ }
2845
+ }
2846
+ }
2847
+ };
2848
+ function mergeRecord(target, patch) {
2849
+ if (!patch) {
2850
+ return target;
2851
+ }
2852
+ return { ...target || {}, ...patch };
2853
+ }
2854
+ function selectedTemplateFeaturePaths(options) {
2855
+ const paths = [];
2856
+ if (options.eslint) {
2857
+ paths.push(FEATURE_DEFINITIONS.eslint.templatePath);
2858
+ }
2859
+ if (options.prettier) {
2860
+ paths.push(FEATURE_DEFINITIONS.prettier.templatePath);
2861
+ }
2862
+ return paths;
2863
+ }
2864
+ function applyPackageFeatures(manifest, options) {
2865
+ const nextManifest = {
2866
+ ...manifest,
2867
+ scripts: { ...manifest.scripts || {} },
2868
+ devDependencies: { ...manifest.devDependencies || {} }
2869
+ };
2870
+ for (const featureName of Object.keys(FEATURE_DEFINITIONS)) {
2871
+ if (!options[featureName]) {
2872
+ continue;
2873
+ }
2874
+ const patch = FEATURE_DEFINITIONS[featureName].packagePatch;
2875
+ nextManifest.scripts = mergeRecord(nextManifest.scripts, patch.scripts);
2876
+ nextManifest.devDependencies = mergeRecord(nextManifest.devDependencies, patch.devDependencies);
2877
+ }
2878
+ if (nextManifest.scripts && Object.keys(nextManifest.scripts).length === 0) {
2879
+ delete nextManifest.scripts;
2880
+ }
2881
+ if (nextManifest.devDependencies && Object.keys(nextManifest.devDependencies).length === 0) {
2882
+ delete nextManifest.devDependencies;
2883
+ }
2884
+ return nextManifest;
2885
+ }
2886
+
2821
2887
  // src/index.ts
2822
2888
  var GITHUB_REPO = "zenithbuild/framework";
2823
2889
  var DEFAULT_TEMPLATE = "examples/starter";
@@ -2844,6 +2910,15 @@ function resolveLocalTemplatePath(templatePath) {
2844
2910
  const candidate = path.resolve(__dirname2, "..", templatePath);
2845
2911
  return fs.existsSync(candidate) ? candidate : null;
2846
2912
  }
2913
+ function copyDirectoryContents(sourceDir, targetDir) {
2914
+ fs.mkdirSync(targetDir, { recursive: true });
2915
+ for (const entry of fs.readdirSync(sourceDir)) {
2916
+ fs.cpSync(path.join(sourceDir, entry), path.join(targetDir, entry), {
2917
+ recursive: true,
2918
+ force: true
2919
+ });
2920
+ }
2921
+ }
2847
2922
  function detectPackageManager() {
2848
2923
  const userAgent = process.env.npm_config_user_agent || "";
2849
2924
  if (userAgent.includes("bun"))
@@ -2874,16 +2949,22 @@ function hasGit() {
2874
2949
  return false;
2875
2950
  }
2876
2951
  }
2877
- async function downloadTemplate(targetDir, templatePath) {
2878
- const localTemplatePath = resolveLocalTemplatePath(templatePath);
2952
+ async function downloadTemplate(targetDir, templatePaths) {
2953
+ const localTemplatePaths = templatePaths.map((templatePath) => ({
2954
+ templatePath,
2955
+ localPath: resolveLocalTemplatePath(templatePath)
2956
+ }));
2879
2957
  const forceLocal = process.env.CREATE_ZENITH_TEMPLATE_MODE === "local" || flagEnabled2(process.env.CREATE_ZENITH_OFFLINE);
2880
2958
  const preferLocal = process.env.CREATE_ZENITH_PREFER_LOCAL !== "0";
2881
- if (localTemplatePath && (forceLocal || preferLocal)) {
2882
- fs.cpSync(localTemplatePath, targetDir, { recursive: true });
2959
+ if (localTemplatePaths.every((entry) => entry.localPath) && (forceLocal || preferLocal)) {
2960
+ for (const entry of localTemplatePaths) {
2961
+ copyDirectoryContents(entry.localPath, targetDir);
2962
+ }
2883
2963
  return;
2884
2964
  }
2885
- if (forceLocal && !localTemplatePath) {
2886
- throw new Error(`Local template not found: ${templatePath}`);
2965
+ if (forceLocal) {
2966
+ const missingPath = localTemplatePaths.find((entry) => !entry.localPath)?.templatePath;
2967
+ throw new Error(`Local template not found: ${missingPath}`);
2887
2968
  }
2888
2969
  const tempDir = path.join(os2.tmpdir(), `zenith-template-${Date.now()}`);
2889
2970
  try {
@@ -2891,13 +2972,15 @@ async function downloadTemplate(targetDir, templatePath) {
2891
2972
  execSync(`git clone --depth 1 --filter=blob:none --sparse https://github.com/${GITHUB_REPO}.git "${tempDir}"`, {
2892
2973
  stdio: "pipe"
2893
2974
  });
2894
- const repoTemplatePath = `packages/create-zenith/${templatePath}`;
2895
- execSync(`git sparse-checkout set ${repoTemplatePath}`, {
2975
+ const repoTemplatePaths = templatePaths.map((templatePath) => `packages/create-zenith/${templatePath}`);
2976
+ execSync(`git sparse-checkout set ${repoTemplatePaths.join(" ")}`, {
2896
2977
  cwd: tempDir,
2897
2978
  stdio: "pipe"
2898
2979
  });
2899
- const templateSource = path.join(tempDir, repoTemplatePath);
2900
- fs.cpSync(templateSource, targetDir, { recursive: true });
2980
+ for (const repoTemplatePath of repoTemplatePaths) {
2981
+ const templateSource = path.join(tempDir, repoTemplatePath);
2982
+ copyDirectoryContents(templateSource, targetDir);
2983
+ }
2901
2984
  } else {
2902
2985
  const tarballUrl = `https://github.com/${GITHUB_REPO}/archive/refs/heads/main.tar.gz`;
2903
2986
  const tarballPath = path.join(os2.tmpdir(), `zenith-${Date.now()}.tar.gz`);
@@ -2908,8 +2991,10 @@ async function downloadTemplate(targetDir, templatePath) {
2908
2991
  if (!extractedDir) {
2909
2992
  throw new Error("Failed to extract template from GitHub");
2910
2993
  }
2911
- const templateSource = path.join(tempDir, extractedDir, "packages/create-zenith", templatePath);
2912
- fs.cpSync(templateSource, targetDir, { recursive: true });
2994
+ for (const templatePath of templatePaths) {
2995
+ const templateSource = path.join(tempDir, extractedDir, "packages/create-zenith", templatePath);
2996
+ copyDirectoryContents(templateSource, targetDir);
2997
+ }
2913
2998
  fs.unlinkSync(tarballPath);
2914
2999
  }
2915
3000
  } finally {
@@ -2918,7 +3003,17 @@ async function downloadTemplate(targetDir, templatePath) {
2918
3003
  }
2919
3004
  }
2920
3005
  }
3006
+ function readOptionOverride(name) {
3007
+ const value = process.env[name];
3008
+ if (value == null || value.trim() === "") {
3009
+ return;
3010
+ }
3011
+ return flagEnabled2(value);
3012
+ }
2921
3013
  async function gatherOptions(providedName, withTailwind) {
3014
+ const eslintOverride = readOptionOverride("CREATE_ZENITH_ESLINT");
3015
+ const prettierOverride = readOptionOverride("CREATE_ZENITH_PRETTIER");
3016
+ const pathAliasOverride = readOptionOverride("CREATE_ZENITH_PATH_ALIAS");
2922
3017
  let name = providedName;
2923
3018
  if (!name) {
2924
3019
  const nameResult = await text({
@@ -2956,9 +3051,9 @@ async function gatherOptions(providedName, withTailwind) {
2956
3051
  log.info("Non-interactive mode detected, using defaults...");
2957
3052
  return {
2958
3053
  name,
2959
- eslint: true,
2960
- prettier: true,
2961
- pathAlias: true,
3054
+ eslint: eslintOverride ?? true,
3055
+ prettier: prettierOverride ?? true,
3056
+ pathAlias: pathAliasOverride ?? true,
2962
3057
  tailwind: withTailwind ?? false
2963
3058
  };
2964
3059
  }
@@ -2968,23 +3063,23 @@ async function gatherOptions(providedName, withTailwind) {
2968
3063
  });
2969
3064
  if (isCancel(tailwindResult))
2970
3065
  handleCancel();
2971
- const eslintResult = await confirm({
3066
+ const eslintResult = eslintOverride ?? await confirm({
2972
3067
  message: "Add ESLint for code linting?",
2973
3068
  initialValue: true
2974
3069
  });
2975
- if (isCancel(eslintResult))
3070
+ if (eslintOverride === undefined && isCancel(eslintResult))
2976
3071
  handleCancel();
2977
- const prettierResult = await confirm({
3072
+ const prettierResult = prettierOverride ?? await confirm({
2978
3073
  message: "Add Prettier for code formatting?",
2979
3074
  initialValue: true
2980
3075
  });
2981
- if (isCancel(prettierResult))
3076
+ if (prettierOverride === undefined && isCancel(prettierResult))
2982
3077
  handleCancel();
2983
- const pathAliasResult = await confirm({
3078
+ const pathAliasResult = pathAliasOverride ?? await confirm({
2984
3079
  message: "Add TypeScript path alias (@/*)?",
2985
3080
  initialValue: true
2986
3081
  });
2987
- if (isCancel(pathAliasResult))
3082
+ if (pathAliasOverride === undefined && isCancel(pathAliasResult))
2988
3083
  handleCancel();
2989
3084
  return {
2990
3085
  name,
@@ -2997,31 +3092,13 @@ async function gatherOptions(providedName, withTailwind) {
2997
3092
  async function createProject(options) {
2998
3093
  const targetDir = path.resolve(process.cwd(), options.name);
2999
3094
  const templatePath = options.tailwind ? TAILWIND_TEMPLATE : DEFAULT_TEMPLATE;
3000
- await downloadTemplate(targetDir, templatePath);
3095
+ const templateFeaturePaths = selectedTemplateFeaturePaths(options);
3096
+ await downloadTemplate(targetDir, [templatePath, ...templateFeaturePaths]);
3001
3097
  const pkgPath = path.join(targetDir, "package.json");
3002
3098
  if (fs.existsSync(pkgPath)) {
3003
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
3099
+ const pkg = applyPackageFeatures(JSON.parse(fs.readFileSync(pkgPath, "utf8")), options);
3004
3100
  pkg.name = options.name;
3005
3101
  pkg.version = "0.1.0";
3006
- if (!options.eslint) {
3007
- delete pkg.devDependencies?.["eslint"];
3008
- delete pkg.devDependencies?.["@typescript-eslint/eslint-plugin"];
3009
- delete pkg.devDependencies?.["@typescript-eslint/parser"];
3010
- delete pkg.scripts?.lint;
3011
- const eslintPath = path.join(targetDir, ".eslintrc.json");
3012
- if (fs.existsSync(eslintPath))
3013
- fs.unlinkSync(eslintPath);
3014
- }
3015
- if (!options.prettier) {
3016
- delete pkg.devDependencies?.["prettier"];
3017
- delete pkg.scripts?.format;
3018
- const prettierRc = path.join(targetDir, ".prettierrc");
3019
- const prettierIgnore = path.join(targetDir, ".prettierignore");
3020
- if (fs.existsSync(prettierRc))
3021
- fs.unlinkSync(prettierRc);
3022
- if (fs.existsSync(prettierIgnore))
3023
- fs.unlinkSync(prettierIgnore);
3024
- }
3025
3102
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 4));
3026
3103
  }
3027
3104
  const tsconfigPath = path.join(targetDir, "tsconfig.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-zenith",
3
- "version": "1.3.18",
3
+ "version": "1.3.19",
4
4
  "description": "Create a new Zenith application - the modern reactive web framework",
5
5
  "type": "module",
6
6
  "bin": {