astro-config-cli 1.0.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 +73 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +372 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# astro-config-cli
|
|
2
|
+
|
|
3
|
+
CLI tool for generating and managing Astro framework configuration files
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g astro-config-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Initialize configuration
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
astro-config init
|
|
17
|
+
astro-config init --template advanced
|
|
18
|
+
astro-config init --output custom-config.json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Validate configuration
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
astro-config validate
|
|
25
|
+
astro-config validate path/to/config.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### View configuration
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
astro-config show
|
|
32
|
+
astro-config show --env production
|
|
33
|
+
astro-config show --json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Modify configuration
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
astro-config set settings.debug true
|
|
40
|
+
astro-config set settings.logLevel \"warn\"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Compare configurations
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
astro-config diff config-dev.json config-prod.json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### List templates
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
astro-config templates
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Templates
|
|
56
|
+
|
|
57
|
+
| Template | Description |
|
|
58
|
+
|----------|-------------|
|
|
59
|
+
| `minimal` | Bare minimum configuration |
|
|
60
|
+
| `standard` | Recommended defaults for most projects |
|
|
61
|
+
| `advanced` | Full-featured with security, caching, and multi-environment support |
|
|
62
|
+
|
|
63
|
+
## Why astro-config-cli?
|
|
64
|
+
|
|
65
|
+
- **Zero dependencies at runtime** — just `commander` and `chalk`
|
|
66
|
+
- **Template-based** — start with minimal, standard, or advanced presets
|
|
67
|
+
- **Validation built-in** — catch config errors before deployment
|
|
68
|
+
- **Environment-aware** — manage dev/staging/production configs in one file
|
|
69
|
+
- **Diff support** — compare configs across environments
|
|
70
|
+
|
|
71
|
+
## License
|
|
72
|
+
|
|
73
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
var CONFIG_FILE = "astro-cli.json";
|
|
8
|
+
function loadConfig() {
|
|
9
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
|
|
12
|
+
} catch {
|
|
13
|
+
console.error(chalk.red("Error: Could not parse " + CONFIG_FILE));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
function saveConfig(cfg) {
|
|
20
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
|
|
21
|
+
console.log(chalk.green("\u2714") + " Config saved to " + chalk.cyan(CONFIG_FILE));
|
|
22
|
+
}
|
|
23
|
+
function integrationImport(name) {
|
|
24
|
+
const map = {
|
|
25
|
+
react: "import react from '@astrojs/react';",
|
|
26
|
+
vue: "import vue from '@astrojs/vue';",
|
|
27
|
+
svelte: "import svelte from '@astrojs/svelte';",
|
|
28
|
+
tailwind: "import tailwind from '@astrojs/tailwind';",
|
|
29
|
+
mdx: "import mdx from '@astrojs/mdx';",
|
|
30
|
+
sitemap: "import sitemap from '@astrojs/sitemap';",
|
|
31
|
+
partytown: "import partytown from '@astrojs/partytown';"
|
|
32
|
+
};
|
|
33
|
+
return map[name];
|
|
34
|
+
}
|
|
35
|
+
function integrationCall(name) {
|
|
36
|
+
const map = {
|
|
37
|
+
react: "react()",
|
|
38
|
+
vue: "vue()",
|
|
39
|
+
svelte: "svelte()",
|
|
40
|
+
tailwind: "tailwind()",
|
|
41
|
+
mdx: "mdx()",
|
|
42
|
+
sitemap: "sitemap()",
|
|
43
|
+
partytown: 'partytown({ config: { forward: ["dataLayer.push"] } })'
|
|
44
|
+
};
|
|
45
|
+
return map[name];
|
|
46
|
+
}
|
|
47
|
+
function adapterImport(name) {
|
|
48
|
+
const map = {
|
|
49
|
+
node: "import node from '@astrojs/node';",
|
|
50
|
+
vercel: "import vercel from '@astrojs/vercel/serverless';",
|
|
51
|
+
netlify: "import netlify from '@astrojs/netlify';",
|
|
52
|
+
cloudflare: "import cloudflare from '@astrojs/cloudflare';",
|
|
53
|
+
deno: "import deno from '@astrojs/deno';"
|
|
54
|
+
};
|
|
55
|
+
return map[name];
|
|
56
|
+
}
|
|
57
|
+
function adapterCall(name, opts) {
|
|
58
|
+
if (Object.keys(opts).length === 0) return `${name}()`;
|
|
59
|
+
const args = JSON.stringify(opts, null, 2).replace(/^{/, "").replace(/}$/, "").trim();
|
|
60
|
+
return `${name}({ ${args.replace(/\n/g, " ")} })`;
|
|
61
|
+
}
|
|
62
|
+
function generateAstroConfig(cfg) {
|
|
63
|
+
const imports = ["import { defineConfig } from 'astro/config';"];
|
|
64
|
+
const parts = [];
|
|
65
|
+
if (cfg.output && cfg.output !== "static") {
|
|
66
|
+
parts.push(` output: '${cfg.output}',`);
|
|
67
|
+
}
|
|
68
|
+
if (cfg.site) parts.push(` site: '${cfg.site}',`);
|
|
69
|
+
if (cfg.base) parts.push(` base: '${cfg.base}',`);
|
|
70
|
+
if (cfg.srcDir) parts.push(` srcDir: '${cfg.srcDir}',`);
|
|
71
|
+
if (cfg.outDir) parts.push(` outDir: '${cfg.outDir}',`);
|
|
72
|
+
if (cfg.publicDir) parts.push(` publicDir: '${cfg.publicDir}',`);
|
|
73
|
+
if (cfg.adapter) {
|
|
74
|
+
imports.push(adapterImport(cfg.adapter));
|
|
75
|
+
parts.push(` adapter: ${adapterCall(cfg.adapter, cfg.adapterOptions ?? {})},`);
|
|
76
|
+
}
|
|
77
|
+
const integrations = cfg.integrations ?? [];
|
|
78
|
+
if (integrations.length > 0) {
|
|
79
|
+
integrations.forEach((i) => imports.push(integrationImport(i)));
|
|
80
|
+
const calls = integrations.map((i) => " " + integrationCall(i)).join(",\n");
|
|
81
|
+
parts.push(` integrations: [
|
|
82
|
+
${calls},
|
|
83
|
+
],`);
|
|
84
|
+
}
|
|
85
|
+
if (cfg.image && Object.keys(cfg.image).length > 0) {
|
|
86
|
+
const img = cfg.image;
|
|
87
|
+
const imgLines = [];
|
|
88
|
+
if (img.service) {
|
|
89
|
+
imgLines.push(` service: { entrypoint: 'astro/assets/services/${img.service}' },`);
|
|
90
|
+
}
|
|
91
|
+
if (img.domains?.length) {
|
|
92
|
+
imgLines.push(` domains: ${JSON.stringify(img.domains)},`);
|
|
93
|
+
}
|
|
94
|
+
if (img.remotePatterns?.length) {
|
|
95
|
+
const pats = img.remotePatterns.map((p) => ` { hostname: '${p}' }`).join(",\n");
|
|
96
|
+
imgLines.push(` remotePatterns: [
|
|
97
|
+
${pats},
|
|
98
|
+
],`);
|
|
99
|
+
}
|
|
100
|
+
if (img.format) imgLines.push(` format: '${img.format}',`);
|
|
101
|
+
if (img.quality !== void 0) imgLines.push(` quality: ${img.quality},`);
|
|
102
|
+
parts.push(` image: {
|
|
103
|
+
${imgLines.join("\n")}
|
|
104
|
+
},`);
|
|
105
|
+
}
|
|
106
|
+
if (cfg.i18n) {
|
|
107
|
+
const i = cfg.i18n;
|
|
108
|
+
const i18n = [
|
|
109
|
+
` defaultLocale: '${i.defaultLocale}',`,
|
|
110
|
+
` locales: ${JSON.stringify(i.locales)},`
|
|
111
|
+
];
|
|
112
|
+
if (i.routing) {
|
|
113
|
+
i18n.push(` routing: { prefixDefaultLocale: ${i.routing === "prefix-always"} },`);
|
|
114
|
+
}
|
|
115
|
+
if (i.fallback && Object.keys(i.fallback).length) {
|
|
116
|
+
i18n.push(` fallback: ${JSON.stringify(i.fallback)},`);
|
|
117
|
+
}
|
|
118
|
+
parts.push(` i18n: {
|
|
119
|
+
${i18n.join("\n")}
|
|
120
|
+
},`);
|
|
121
|
+
}
|
|
122
|
+
if (cfg.markdown && Object.keys(cfg.markdown).length > 0) {
|
|
123
|
+
const m = cfg.markdown;
|
|
124
|
+
const md = [];
|
|
125
|
+
if (m.syntaxHighlight !== void 0) {
|
|
126
|
+
md.push(` syntaxHighlight: ${m.syntaxHighlight === false ? "false" : `'${m.syntaxHighlight}'`},`);
|
|
127
|
+
}
|
|
128
|
+
if (m.shikiConfig) md.push(` shikiConfig: ${JSON.stringify(m.shikiConfig)},`);
|
|
129
|
+
if (m.gfm !== void 0) md.push(` gfm: ${m.gfm},`);
|
|
130
|
+
if (m.smartypants !== void 0) md.push(` smartypants: ${m.smartypants},`);
|
|
131
|
+
if (m.remarkPlugins?.length) md.push(` remarkPlugins: ${JSON.stringify(m.remarkPlugins)},`);
|
|
132
|
+
if (m.rehypePlugins?.length) md.push(` rehypePlugins: ${JSON.stringify(m.rehypePlugins)},`);
|
|
133
|
+
parts.push(` markdown: {
|
|
134
|
+
${md.join("\n")}
|
|
135
|
+
},`);
|
|
136
|
+
}
|
|
137
|
+
if (cfg.prefetch !== void 0) {
|
|
138
|
+
if (typeof cfg.prefetch === "boolean") {
|
|
139
|
+
parts.push(` prefetch: ${cfg.prefetch},`);
|
|
140
|
+
} else {
|
|
141
|
+
const pf = [];
|
|
142
|
+
if (cfg.prefetch.prefetchAll !== void 0) pf.push(` prefetchAll: ${cfg.prefetch.prefetchAll},`);
|
|
143
|
+
if (cfg.prefetch.defaultStrategy) pf.push(` defaultStrategy: '${cfg.prefetch.defaultStrategy}',`);
|
|
144
|
+
parts.push(` prefetch: {
|
|
145
|
+
${pf.join("\n")}
|
|
146
|
+
},`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (cfg.devToolbar) {
|
|
150
|
+
parts.push(` devToolbar: { enabled: ${cfg.devToolbar.enabled ?? true} },`);
|
|
151
|
+
}
|
|
152
|
+
if (cfg.vitePlugins?.length) {
|
|
153
|
+
cfg.vitePlugins.forEach((p) => imports.push(`import ${p.name} from '${p.package}';`));
|
|
154
|
+
const pluginCalls = cfg.vitePlugins.map((p) => {
|
|
155
|
+
const opts = p.options && Object.keys(p.options).length ? JSON.stringify(p.options) : "";
|
|
156
|
+
return ` ${p.name}(${opts})`;
|
|
157
|
+
}).join(",\n");
|
|
158
|
+
parts.push(` vite: {
|
|
159
|
+
plugins: [
|
|
160
|
+
${pluginCalls},
|
|
161
|
+
],
|
|
162
|
+
},`);
|
|
163
|
+
}
|
|
164
|
+
if (cfg.server) {
|
|
165
|
+
const srv = [];
|
|
166
|
+
if (cfg.server.port) srv.push(` port: ${cfg.server.port},`);
|
|
167
|
+
if (cfg.server.host) srv.push(` host: '${cfg.server.host}',`);
|
|
168
|
+
if (srv.length) parts.push(` server: {
|
|
169
|
+
${srv.join("\n")}
|
|
170
|
+
},`);
|
|
171
|
+
}
|
|
172
|
+
const body = parts.length > 0 ? "\n" + parts.join("\n") + "\n" : "";
|
|
173
|
+
return `${imports.join("\n")}
|
|
174
|
+
|
|
175
|
+
export default defineConfig({${body}});
|
|
176
|
+
`;
|
|
177
|
+
}
|
|
178
|
+
function validateConfig(cfg) {
|
|
179
|
+
const errors = [];
|
|
180
|
+
if ((cfg.output === "server" || cfg.output === "hybrid") && !cfg.adapter) {
|
|
181
|
+
errors.push(`output: "${cfg.output}" requires an adapter \u2014 run: astro-config set-adapter <name>`);
|
|
182
|
+
}
|
|
183
|
+
if (cfg.i18n) {
|
|
184
|
+
if (!cfg.i18n.defaultLocale) errors.push("i18n.defaultLocale is required");
|
|
185
|
+
if (!cfg.i18n.locales?.length) errors.push("i18n.locales must have at least one entry");
|
|
186
|
+
if (cfg.i18n.locales && cfg.i18n.defaultLocale && !cfg.i18n.locales.includes(cfg.i18n.defaultLocale)) {
|
|
187
|
+
errors.push("i18n.defaultLocale must appear in i18n.locales");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (cfg.image?.quality !== void 0 && (cfg.image.quality < 1 || cfg.image.quality > 100)) {
|
|
191
|
+
errors.push("image.quality must be between 1 and 100");
|
|
192
|
+
}
|
|
193
|
+
return errors;
|
|
194
|
+
}
|
|
195
|
+
var program = new Command();
|
|
196
|
+
program.name("astro-config").description(chalk.cyan("Astro Config CLI") + " \u2014 Generate and manage astro.config.mjs").version("1.0.0");
|
|
197
|
+
program.command("init").description("Initialize a new Astro config (creates astro-cli.json)").option("--output <mode>", "Output mode: static | server | hybrid", "static").option("--site <url>", "Canonical site URL, e.g. https://example.com").option("--base <path>", "Base path, e.g. /app").option("--src <dir>", "Source directory", "./src").option("--out <dir>", "Build output directory", "./dist").option("--port <port>", "Dev server port", "4321").option("--host <host>", "Dev server host (true = expose to LAN)").action((opts) => {
|
|
198
|
+
const cfg = {
|
|
199
|
+
output: opts.output,
|
|
200
|
+
srcDir: opts.src,
|
|
201
|
+
outDir: opts.out,
|
|
202
|
+
server: { port: parseInt(opts.port, 10) }
|
|
203
|
+
};
|
|
204
|
+
if (opts.host) cfg.server.host = opts.host;
|
|
205
|
+
if (opts.site) cfg.site = opts.site;
|
|
206
|
+
if (opts.base) cfg.base = opts.base;
|
|
207
|
+
saveConfig(cfg);
|
|
208
|
+
console.log(chalk.green("\u2714") + " Initialized \u2014 output mode: " + chalk.yellow(opts.output));
|
|
209
|
+
console.log(chalk.dim(" Run `astro-config export` to generate astro.config.mjs"));
|
|
210
|
+
});
|
|
211
|
+
program.command("set-output <mode>").description("Set output mode: static | server | hybrid").action((mode) => {
|
|
212
|
+
const valid = ["static", "server", "hybrid"];
|
|
213
|
+
if (!valid.includes(mode)) {
|
|
214
|
+
console.error(chalk.red("Error: mode must be one of: " + valid.join(", ")));
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
const cfg = loadConfig();
|
|
218
|
+
cfg.output = mode;
|
|
219
|
+
if (mode !== "static" && !cfg.adapter) {
|
|
220
|
+
console.log(chalk.yellow("\u26A0") + ' output="' + mode + '" needs an adapter \u2014 run: astro-config set-adapter <name>');
|
|
221
|
+
}
|
|
222
|
+
saveConfig(cfg);
|
|
223
|
+
console.log(chalk.green("\u2714") + " Output set to: " + chalk.yellow(mode));
|
|
224
|
+
});
|
|
225
|
+
var validIntegrations = ["react", "vue", "svelte", "tailwind", "mdx", "sitemap", "partytown"];
|
|
226
|
+
program.command("add-integration <name>").description("Add an integration: " + validIntegrations.join(" | ")).action((name) => {
|
|
227
|
+
if (!validIntegrations.includes(name)) {
|
|
228
|
+
console.error(chalk.red('Error: unknown integration "' + name + '"'));
|
|
229
|
+
console.log(" Available: " + validIntegrations.join(", "));
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
const cfg = loadConfig();
|
|
233
|
+
cfg.integrations = cfg.integrations ?? [];
|
|
234
|
+
if (cfg.integrations.includes(name)) {
|
|
235
|
+
console.log(chalk.yellow("\u26A0") + " " + name + " is already in integrations");
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
cfg.integrations.push(name);
|
|
239
|
+
saveConfig(cfg);
|
|
240
|
+
console.log(chalk.green("\u2714") + " Added: " + chalk.cyan(name));
|
|
241
|
+
console.log(chalk.dim(" npm install @astrojs/" + name));
|
|
242
|
+
});
|
|
243
|
+
var validAdapters = ["node", "vercel", "netlify", "cloudflare", "deno"];
|
|
244
|
+
program.command("set-adapter <name>").description("Set SSR adapter: " + validAdapters.join(" | ")).option("--mode <mode>", "node adapter mode: standalone | middleware", "standalone").option("--region <region>", "Deploy region (vercel / netlify / cloudflare)").option("--runtime <runtime>", "Cloudflare runtime: advanced | directory").action((name, opts) => {
|
|
245
|
+
if (!validAdapters.includes(name)) {
|
|
246
|
+
console.error(chalk.red('Error: unknown adapter "' + name + '"'));
|
|
247
|
+
console.log(" Available: " + validAdapters.join(", "));
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
const cfg = loadConfig();
|
|
251
|
+
cfg.adapter = name;
|
|
252
|
+
cfg.adapterOptions = {};
|
|
253
|
+
if (name === "node") cfg.adapterOptions["mode"] = opts.mode;
|
|
254
|
+
if (name === "cloudflare" && opts.runtime) cfg.adapterOptions["runtime"] = opts.runtime;
|
|
255
|
+
if ((name === "vercel" || name === "netlify") && opts.region) {
|
|
256
|
+
cfg.adapterOptions["region"] = opts.region;
|
|
257
|
+
}
|
|
258
|
+
if (!cfg.output || cfg.output === "static") {
|
|
259
|
+
cfg.output = "server";
|
|
260
|
+
console.log(chalk.yellow("\u26A0") + ' Auto-set output \u2192 "server"');
|
|
261
|
+
}
|
|
262
|
+
saveConfig(cfg);
|
|
263
|
+
console.log(chalk.green("\u2714") + " Adapter: " + chalk.cyan(name));
|
|
264
|
+
console.log(chalk.dim(" npm install @astrojs/" + name));
|
|
265
|
+
});
|
|
266
|
+
program.command("set-image").description("Configure image optimization").option("--service <svc>", "sharp | squoosh | noop", "sharp").option("--domains <list>", "Comma-separated allowed remote domains").option("--patterns <list>", "Comma-separated remote hostname patterns").option("--format <fmt>", "Default output format: webp | avif | png | jpg").option("--quality <n>", "Default quality 1\u2013100", "80").action((opts) => {
|
|
267
|
+
const cfg = loadConfig();
|
|
268
|
+
cfg.image = {
|
|
269
|
+
service: opts.service,
|
|
270
|
+
quality: parseInt(opts.quality, 10)
|
|
271
|
+
};
|
|
272
|
+
if (opts.domains) cfg.image.domains = opts.domains.split(",").map((d) => d.trim());
|
|
273
|
+
if (opts.patterns) cfg.image.remotePatterns = opts.patterns.split(",").map((p) => p.trim());
|
|
274
|
+
if (opts.format) cfg.image.format = opts.format;
|
|
275
|
+
saveConfig(cfg);
|
|
276
|
+
console.log(chalk.green("\u2714") + " Image: service=" + chalk.cyan(opts.service) + ", quality=" + opts.quality);
|
|
277
|
+
});
|
|
278
|
+
program.command("set-i18n").description("Configure internationalization routing").requiredOption("--default <locale>", "Default locale, e.g. en").requiredOption("--locales <list>", "Comma-separated locales, e.g. en,fr,de").option("--routing <mode>", "prefix-always | prefix-other-locales", "prefix-other-locales").option("--fallback <json>", `Fallback map JSON, e.g. '{"fr":"en"}'`).action((opts) => {
|
|
279
|
+
const locales = opts.locales.split(",").map((l) => l.trim());
|
|
280
|
+
if (!locales.includes(opts.default)) {
|
|
281
|
+
console.error(chalk.red("Error: --default locale must be listed in --locales"));
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
const cfg = loadConfig();
|
|
285
|
+
cfg.i18n = {
|
|
286
|
+
defaultLocale: opts.default,
|
|
287
|
+
locales,
|
|
288
|
+
routing: opts.routing
|
|
289
|
+
};
|
|
290
|
+
if (opts.fallback) {
|
|
291
|
+
try {
|
|
292
|
+
cfg.i18n.fallback = JSON.parse(opts.fallback);
|
|
293
|
+
} catch {
|
|
294
|
+
console.error(chalk.red("Error: --fallback must be valid JSON"));
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
saveConfig(cfg);
|
|
299
|
+
console.log(chalk.green("\u2714") + " i18n: " + chalk.cyan(opts.default) + " \u2192 [" + locales.join(", ") + "]");
|
|
300
|
+
});
|
|
301
|
+
program.command("set-markdown").description("Configure Markdown / MDX processing").option("--highlight <engine>", "shiki | prism | false", "shiki").option("--theme <theme>", "Shiki theme name", "github-dark").option("--wrap", "Enable shiki code-block word wrap").option("--no-gfm", "Disable GitHub Flavored Markdown").option("--no-smartypants", "Disable Smartypants typographic transforms").option("--remark <plugins>", "Comma-separated remark plugin package names").option("--rehype <plugins>", "Comma-separated rehype plugin package names").action((opts) => {
|
|
302
|
+
const cfg = loadConfig();
|
|
303
|
+
const hl = opts.highlight === "false" ? false : opts.highlight;
|
|
304
|
+
cfg.markdown = {
|
|
305
|
+
syntaxHighlight: hl,
|
|
306
|
+
gfm: opts.gfm !== false,
|
|
307
|
+
smartypants: opts.smartypants !== false
|
|
308
|
+
};
|
|
309
|
+
if (hl === "shiki") {
|
|
310
|
+
cfg.markdown.shikiConfig = { theme: opts.theme, wrap: !!opts.wrap };
|
|
311
|
+
}
|
|
312
|
+
if (opts.remark) cfg.markdown.remarkPlugins = opts.remark.split(",").map((r) => r.trim());
|
|
313
|
+
if (opts.rehype) cfg.markdown.rehypePlugins = opts.rehype.split(",").map((r) => r.trim());
|
|
314
|
+
saveConfig(cfg);
|
|
315
|
+
console.log(chalk.green("\u2714") + " Markdown: highlight=" + (hl === false ? "false" : chalk.cyan(String(hl))));
|
|
316
|
+
});
|
|
317
|
+
program.command("set-prefetch").description("Configure link prefetch behavior").option("--all", "Prefetch all links on the page").option("--strategy <s>", "hover | tap | viewport | load", "hover").action((opts) => {
|
|
318
|
+
const cfg = loadConfig();
|
|
319
|
+
cfg.prefetch = opts.all ? { prefetchAll: true, defaultStrategy: opts.strategy } : { defaultStrategy: opts.strategy };
|
|
320
|
+
saveConfig(cfg);
|
|
321
|
+
console.log(chalk.green("\u2714") + " Prefetch: " + (opts.all ? "all links, " : "") + "strategy=" + opts.strategy);
|
|
322
|
+
});
|
|
323
|
+
program.command("set-toolbar").description("Enable or disable the Astro dev toolbar").option("--disable", "Disable the toolbar (enabled by default)").action((opts) => {
|
|
324
|
+
const cfg = loadConfig();
|
|
325
|
+
cfg.devToolbar = { enabled: !opts.disable };
|
|
326
|
+
saveConfig(cfg);
|
|
327
|
+
console.log(chalk.green("\u2714") + " Dev toolbar: " + (cfg.devToolbar.enabled ? chalk.green("enabled") : chalk.red("disabled")));
|
|
328
|
+
});
|
|
329
|
+
program.command("validate").description("Validate the current config for errors and show a summary").action(() => {
|
|
330
|
+
const cfg = loadConfig();
|
|
331
|
+
const errors = validateConfig(cfg);
|
|
332
|
+
if (errors.length === 0) {
|
|
333
|
+
console.log(chalk.green("\u2714") + " Config is valid\n");
|
|
334
|
+
console.log(" Output: " + chalk.yellow(cfg.output ?? "static"));
|
|
335
|
+
if (cfg.adapter) console.log(" Adapter: " + chalk.cyan(cfg.adapter));
|
|
336
|
+
if (cfg.integrations?.length) console.log(" Integrations: " + cfg.integrations.join(", "));
|
|
337
|
+
if (cfg.i18n) console.log(" i18n: " + cfg.i18n.defaultLocale + " / [" + cfg.i18n.locales.join(", ") + "]");
|
|
338
|
+
if (cfg.image?.service) console.log(" Image: " + cfg.image.service);
|
|
339
|
+
if (cfg.markdown?.syntaxHighlight) console.log(" Markdown: " + cfg.markdown.syntaxHighlight);
|
|
340
|
+
} else {
|
|
341
|
+
console.log(chalk.red("\u2716") + " " + errors.length + " validation error(s):\n");
|
|
342
|
+
errors.forEach((e) => console.log(" " + chalk.red("\u2022") + " " + e));
|
|
343
|
+
process.exit(1);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
program.command("export").description("Generate astro.config.mjs from the current CLI config").option("--out <file>", "Output file path", "astro.config.mjs").option("--dry-run", "Print to stdout without writing").action((opts) => {
|
|
347
|
+
const cfg = loadConfig();
|
|
348
|
+
const errors = validateConfig(cfg);
|
|
349
|
+
if (errors.length > 0) {
|
|
350
|
+
console.log(chalk.red("\u2716") + " Export blocked \u2014 fix errors first:\n");
|
|
351
|
+
errors.forEach((e) => console.log(" " + chalk.red("\u2022") + " " + e));
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
354
|
+
const content = generateAstroConfig(cfg);
|
|
355
|
+
if (opts.dryRun) {
|
|
356
|
+
console.log(chalk.dim("\u2500\u2500\u2500 " + opts.out + " \u2500\u2500\u2500"));
|
|
357
|
+
console.log(content);
|
|
358
|
+
} else {
|
|
359
|
+
fs.writeFileSync(opts.out, content, "utf-8");
|
|
360
|
+
console.log(chalk.green("\u2714") + " Written \u2192 " + chalk.cyan(opts.out));
|
|
361
|
+
console.log(chalk.dim("\n" + content));
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
program.command("show").description("Show the raw astro-cli.json state").action(() => {
|
|
365
|
+
const cfg = loadConfig();
|
|
366
|
+
console.log(chalk.bold("\nCurrent config (" + CONFIG_FILE + "):"));
|
|
367
|
+
console.log(chalk.dim(JSON.stringify(cfg, null, 2)));
|
|
368
|
+
});
|
|
369
|
+
if (process.argv.length < 3) {
|
|
370
|
+
program.help();
|
|
371
|
+
}
|
|
372
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "astro-config-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool for generating and managing Astro framework configuration files",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"astro-config": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "node node_modules/tsup/dist/cli-default.js",
|
|
14
|
+
"dev": "node node_modules/tsup/dist/cli-default.js --watch",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"astro",
|
|
19
|
+
"cli",
|
|
20
|
+
"config",
|
|
21
|
+
"generator",
|
|
22
|
+
"framework"
|
|
23
|
+
],
|
|
24
|
+
"author": "",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"chalk": "^5.3.0",
|
|
28
|
+
"commander": "^12.1.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^20.14.0",
|
|
32
|
+
"tsup": "^8.1.0",
|
|
33
|
+
"typescript": "^5.4.5"
|
|
34
|
+
},
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/okirmio-create/cli-forge.git",
|
|
38
|
+
"directory": "astro-config-cli"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://github.com/okirmio-create/cli-forge/tree/main/astro-config-cli",
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/okirmio-create/cli-forge/issues"
|
|
43
|
+
}
|
|
44
|
+
}
|