create-avalon 0.1.9 → 0.1.11

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.
Files changed (3) hide show
  1. package/README.md +59 -59
  2. package/dist/cli.js +117 -74
  3. package/package.json +13 -3
package/README.md CHANGED
@@ -1,59 +1,59 @@
1
- # create-avalon
2
-
3
- Scaffold a new [Avalon](https://useavalon.dev) project in seconds.
4
-
5
- ## Usage
6
-
7
- ```bash
8
- npm create avalon@latest
9
- ```
10
-
11
- Or with other package managers:
12
-
13
- ```bash
14
- pnpm create avalon@latest
15
- yarn create avalon
16
- bun create avalon
17
- ```
18
-
19
- The CLI walks you through:
20
-
21
- - Project name and directory
22
- - Framework selection (React, Preact, Vue, Svelte, Solid, Lit, Qwik — or multiple)
23
- - Styling approach (CSS Modules, Tailwind, vanilla CSS)
24
- - Optional features (API routes, middleware, layouts, MDX)
25
- - Package manager preference
26
-
27
- ## What you get
28
-
29
- A ready-to-run Avalon project with file-system routing, islands architecture, and zero JavaScript by default.
30
-
31
- ```
32
- my-project/
33
- ├── app/
34
- │ ├── modules/
35
- │ │ └── home/
36
- │ │ ├── pages/ # File-system routes
37
- │ │ ├── components/ # Interactive components
38
- │ │ └── layouts/ # Module layouts
39
- │ └── shared/
40
- │ ├── layouts/ # Root layout
41
- │ ├── components/ # Shared components
42
- │ └── styles/ # Global styles & tokens
43
- ├── middleware/ # Server middleware
44
- ├── routes/
45
- │ └── api/ # API routes
46
- ├── server/ # Server config & env
47
- ├── public/ # Static assets
48
- ├── vite.config.ts
49
- └── package.json
50
- ```
51
-
52
- ## Links
53
-
54
- - [Documentation](https://useavalon.dev/docs/introduction)
55
- - [GitHub](https://github.com/useAvalon/Avalon)
56
-
57
- ## License
58
-
59
- MIT
1
+ # create-avalon
2
+
3
+ Scaffold a new [Avalon](https://useavalon.dev) project in seconds.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ npm create avalon@latest
9
+ ```
10
+
11
+ Or with other package managers:
12
+
13
+ ```bash
14
+ pnpm create avalon@latest
15
+ yarn create avalon
16
+ bun create avalon
17
+ ```
18
+
19
+ The CLI walks you through:
20
+
21
+ - Project name and directory
22
+ - Framework selection (React, Preact, Vue, Svelte, Solid, Lit, Qwik — or multiple)
23
+ - Styling approach (CSS Modules, Tailwind, vanilla CSS)
24
+ - Optional features (API routes, middleware, layouts, MDX)
25
+ - Package manager preference
26
+
27
+ ## What you get
28
+
29
+ A ready-to-run Avalon project with file-system routing, islands architecture, and zero JavaScript by default.
30
+
31
+ ```
32
+ my-project/
33
+ ├── app/
34
+ │ ├── modules/
35
+ │ │ └── home/
36
+ │ │ ├── pages/ # File-system routes
37
+ │ │ ├── components/ # Interactive components
38
+ │ │ └── layouts/ # Module layouts
39
+ │ └── shared/
40
+ │ ├── layouts/ # Root layout
41
+ │ ├── components/ # Shared components
42
+ │ └── styles/ # Global styles & tokens
43
+ ├── middleware/ # Server middleware
44
+ ├── routes/
45
+ │ └── api/ # API routes
46
+ ├── server/ # Server config & env
47
+ ├── public/ # Static assets
48
+ ├── vite.config.ts
49
+ └── package.json
50
+ ```
51
+
52
+ ## Links
53
+
54
+ - [Documentation](https://useavalon.dev/docs/introduction)
55
+ - [GitHub](https://github.com/useAvalon/Avalon)
56
+
57
+ ## License
58
+
59
+ MIT
package/dist/cli.js CHANGED
@@ -1156,7 +1156,12 @@ async function collectProjectConfig(initialName) {
1156
1156
  const pluginsResult = await Lt2({
1157
1157
  message: "Which plugins would you like to include? (use space to toggle, enter to confirm)",
1158
1158
  options: [
1159
- { value: "agent-optimization", label: "agent-optimization", hint: "LLM/AI optimization" }
1159
+ { value: "agent-optimization", label: "agent-optimization", hint: "LLM/AI optimization" },
1160
+ {
1161
+ value: "syntax-highlighting",
1162
+ label: "syntax-highlighting",
1163
+ hint: "Code block highlighting for MDX (rehype-highlight)"
1164
+ }
1160
1165
  ],
1161
1166
  required: false
1162
1167
  });
@@ -1187,7 +1192,7 @@ async function collectProjectConfig(initialName) {
1187
1192
 
1188
1193
  // src/scaffold.ts
1189
1194
  import { mkdir, writeFile } from "node:fs/promises";
1190
- import { join } from "node:path";
1195
+ import { join, dirname } from "node:path";
1191
1196
 
1192
1197
  // src/types.ts
1193
1198
  var INTEGRATION_PACKAGES = {
@@ -1223,6 +1228,9 @@ function generatePackageJson(config) {
1223
1228
  if (config.plugins.includes("agent-optimization")) {
1224
1229
  dependencies["@useavalon/agent-optimization"] = "latest";
1225
1230
  }
1231
+ if (config.plugins.includes("syntax-highlighting")) {
1232
+ dependencies["rehype-highlight"] = "latest";
1233
+ }
1226
1234
  switch (config.middleware) {
1227
1235
  case "hono":
1228
1236
  dependencies["hono"] = "latest";
@@ -1246,6 +1254,8 @@ function generatePackageJson(config) {
1246
1254
  devDependencies["tailwindcss"] = "latest";
1247
1255
  devDependencies["@tailwindcss/vite"] = "latest";
1248
1256
  dependencies["@shadcn/ui"] = "latest";
1257
+ dependencies["tailwind-merge"] = "^3.5.0";
1258
+ dependencies["clsx"] = "^2.1.1";
1249
1259
  break;
1250
1260
  }
1251
1261
  const pkg = {
@@ -1274,7 +1284,10 @@ function generateTsConfig() {
1274
1284
  esModuleInterop: true,
1275
1285
  skipLibCheck: true,
1276
1286
  allowArbitraryExtensions: true,
1287
+ allowImportingTsExtensions: true,
1288
+ noEmit: true,
1277
1289
  jsx: "react-jsx",
1290
+ types: ["@useavalon/avalon/types"],
1278
1291
  paths: {
1279
1292
  "@shared/*": ["./app/shared/*"],
1280
1293
  "@modules/*": ["./app/modules/*"]
@@ -1288,6 +1301,7 @@ function generateTsConfig() {
1288
1301
  // src/templates/vite-config.ts
1289
1302
  function generateViteConfig(config) {
1290
1303
  const imports = [
1304
+ `import { resolve } from 'node:path';`,
1291
1305
  `import { defineConfig, type UserConfig } from 'vite';`,
1292
1306
  `import { avalon } from '@useavalon/avalon';`
1293
1307
  ];
@@ -1340,6 +1354,14 @@ function generateViteConfig(config) {
1340
1354
  `),
1341
1355
  ` ],`,
1342
1356
  ``,
1357
+ ` resolve: {`,
1358
+ ` alias: {`,
1359
+ ` '@shared': resolve(__dirname, 'app/shared'),`,
1360
+ ` '@modules': resolve(__dirname, 'app/modules'),`,
1361
+ ` '@': resolve(__dirname, 'app'),`,
1362
+ ` },`,
1363
+ ` },`,
1364
+ ``,
1343
1365
  ` server: {`,
1344
1366
  ` port: 3000,`,
1345
1367
  ` },`,
@@ -1445,91 +1467,32 @@ export default async function HomePage() {
1445
1467
  }
1446
1468
 
1447
1469
  // src/templates/middleware.ts
1448
- function generateSampleMiddleware(config) {
1449
- switch (config.middleware) {
1450
- case "h3":
1451
- return generateH3Middleware();
1452
- case "hono":
1453
- return generateHonoMiddleware();
1454
- case "elysia":
1455
- return generateElysiaMiddleware();
1456
- }
1457
- }
1458
- function generateH3Middleware() {
1459
- return `import { defineHandler } from 'nitro/h3';
1470
+ function generateSampleMiddleware(_config) {
1471
+ return `import { defineHandler } from 'nitro';
1460
1472
 
1461
1473
  export default defineHandler((event) => {
1462
1474
  console.log(\`[\${new Date().toISOString()}] \${event.method} \${event.path}\`);
1463
1475
  });
1464
1476
  `;
1465
1477
  }
1466
- function generateHonoMiddleware() {
1467
- return `import { Hono } from 'hono';
1468
-
1469
- const app = new Hono();
1470
-
1471
- app.use('*', async (c, next) => {
1472
- console.log(\`[\${new Date().toISOString()}] \${c.req.method} \${c.req.path}\`);
1473
- await next();
1474
- });
1475
-
1476
- export default app;
1477
- `;
1478
- }
1479
- function generateElysiaMiddleware() {
1480
- return `import { Elysia } from 'elysia';
1481
-
1482
- export default new Elysia()
1483
- .onBeforeHandle(({ request }) => {
1484
- console.log(\`[\${new Date().toISOString()}] \${request.method} \${new URL(request.url).pathname}\`);
1485
- });
1486
- `;
1487
- }
1488
1478
 
1489
1479
  // src/templates/api-routes.ts
1490
- function generateHelloRoute(config) {
1491
- switch (config.middleware) {
1492
- case "h3":
1493
- return generateH3Route();
1494
- case "hono":
1495
- return generateHonoRoute();
1496
- case "elysia":
1497
- return generateElysiaRoute();
1498
- }
1499
- }
1500
- function generateH3Route() {
1501
- return `import { defineHandler } from 'nitro/h3';
1480
+ function generateHelloRoute(_config) {
1481
+ return `import { defineHandler } from 'nitro';
1502
1482
 
1503
1483
  export default defineHandler(() => {
1504
- return { message: 'Hello from Avalon!' };
1484
+ return Response.json({ message: 'Hello from Avalon!' });
1505
1485
  });
1506
1486
  `;
1507
1487
  }
1508
- function generateHonoRoute() {
1509
- return `import { Hono } from 'hono';
1510
-
1511
- const app = new Hono();
1512
-
1513
- app.get('/', (c) => {
1514
- return c.json({ message: 'Hello from Avalon!' });
1515
- });
1516
-
1517
- export default app;
1518
- `;
1519
- }
1520
- function generateElysiaRoute() {
1521
- return `import { Elysia } from 'elysia';
1522
-
1523
- export default new Elysia()
1524
- .get('/', () => ({ message: 'Hello from Avalon!' }));
1525
- `;
1526
- }
1527
1488
 
1528
1489
  // src/templates/styling.ts
1529
1490
  function generateStylingFiles(config) {
1530
1491
  const files = new Map;
1531
1492
  files.set("app/shared/styles/main.css", generateMainCss(config));
1532
- files.set("app/shared/styles/reset.css", generateResetCss());
1493
+ if (config.styling === "css-modules") {
1494
+ files.set("app/shared/styles/reset.css", generateResetCss());
1495
+ }
1533
1496
  switch (config.styling) {
1534
1497
  case "css-modules":
1535
1498
  files.set("app/shared/styles/tokens.css", generateTokensCss());
@@ -1539,19 +1502,21 @@ function generateStylingFiles(config) {
1539
1502
  break;
1540
1503
  case "tailwind":
1541
1504
  files.set("tailwind.config.js", generateTailwindConfig());
1542
- files.set("app/shared/styles/global.css", generateTailwindGlobalCss());
1505
+ files.set("app/shared/styles/global.css", generateTailwindGlobalCss(config));
1543
1506
  break;
1544
1507
  case "shadcn":
1545
1508
  files.set("tailwind.config.js", generateTailwindConfig());
1546
- files.set("app/shared/styles/global.css", generateTailwindGlobalCss());
1509
+ files.set("app/shared/styles/global.css", generateTailwindGlobalCss(config));
1547
1510
  files.set("components.json", generateShadcnComponentsJson(config));
1511
+ files.set("app/shared/utils/cn.ts", generateCnUtil());
1548
1512
  break;
1549
1513
  }
1550
1514
  return files;
1551
1515
  }
1552
1516
  function generateMainCss(config) {
1553
- const imports = [`@import './reset.css';`];
1517
+ const imports = [];
1554
1518
  if (config.styling === "css-modules") {
1519
+ imports.push(`@import './reset.css';`);
1555
1520
  imports.push(`@import './tokens.css';`);
1556
1521
  } else {
1557
1522
  imports.push(`@import './global.css';`);
@@ -1659,8 +1624,47 @@ export default {
1659
1624
  };
1660
1625
  `;
1661
1626
  }
1662
- function generateTailwindGlobalCss() {
1663
- return `@import "tailwindcss";
1627
+ function generateTailwindGlobalCss(config) {
1628
+ const lines = [`@import "tailwindcss";`];
1629
+ if (config.styling === "shadcn") {
1630
+ lines.push("");
1631
+ lines.push(`@theme inline {
1632
+ --color-background: oklch(1 0 0);
1633
+ --color-foreground: oklch(0.145 0 0);
1634
+ --color-card: oklch(1 0 0);
1635
+ --color-card-foreground: oklch(0.145 0 0);
1636
+ --color-popover: oklch(1 0 0);
1637
+ --color-popover-foreground: oklch(0.145 0 0);
1638
+ --color-primary: oklch(0.205 0 0);
1639
+ --color-primary-foreground: oklch(0.985 0 0);
1640
+ --color-secondary: oklch(0.97 0 0);
1641
+ --color-secondary-foreground: oklch(0.205 0 0);
1642
+ --color-muted: oklch(0.97 0 0);
1643
+ --color-muted-foreground: oklch(0.556 0 0);
1644
+ --color-accent: oklch(0.97 0 0);
1645
+ --color-accent-foreground: oklch(0.205 0 0);
1646
+ --color-destructive: oklch(0.577 0.245 27.325);
1647
+ --color-destructive-foreground: oklch(0.577 0.245 27.325);
1648
+ --color-border: oklch(0.922 0 0);
1649
+ --color-input: oklch(0.922 0 0);
1650
+ --color-ring: oklch(0.708 0 0);
1651
+ --radius-sm: 0.25rem;
1652
+ --radius-md: 0.375rem;
1653
+ --radius-lg: 0.5rem;
1654
+ --radius-xl: 0.75rem;
1655
+ }`);
1656
+ }
1657
+ return lines.join(`
1658
+ `) + `
1659
+ `;
1660
+ }
1661
+ function generateCnUtil() {
1662
+ return `import { clsx, type ClassValue } from 'clsx';
1663
+ import { twMerge } from 'tailwind-merge';
1664
+
1665
+ export function cn(...inputs: ClassValue[]) {
1666
+ return twMerge(clsx(inputs));
1667
+ }
1664
1668
  `;
1665
1669
  }
1666
1670
  function generateShadcnComponentsJson(config) {
@@ -1687,6 +1691,39 @@ function getFaviconBuffer() {
1687
1691
  }
1688
1692
 
1689
1693
  // src/scaffold.ts
1694
+ function generateHonoServerEntry() {
1695
+ return `import { Hono } from 'hono';
1696
+
1697
+ const app = new Hono();
1698
+
1699
+ // Add your Hono middleware and routes here.
1700
+ // This file is the Nitro server entry using the web fetch interface.
1701
+ // Route files in routes/ still use defineHandler from 'nitro'.
1702
+
1703
+ app.use('*', async (c, next) => {
1704
+ console.log(\`[\${new Date().toISOString()}] \${c.req.method} \${c.req.path}\`);
1705
+ await next();
1706
+ });
1707
+
1708
+ export default app;
1709
+ `;
1710
+ }
1711
+ function generateElysiaServerEntry() {
1712
+ return `import { Elysia } from 'elysia';
1713
+
1714
+ const app = new Elysia();
1715
+
1716
+ // Add your Elysia middleware and routes here.
1717
+ // This file is the Nitro server entry using the web fetch interface.
1718
+ // Route files in routes/ still use defineHandler from 'nitro'.
1719
+
1720
+ app.onBeforeHandle(({ request }) => {
1721
+ console.log(\`[\${new Date().toISOString()}] \${request.method} \${new URL(request.url).pathname}\`);
1722
+ });
1723
+
1724
+ export default app;
1725
+ `;
1726
+ }
1690
1727
  async function scaffoldProject(config, targetDir) {
1691
1728
  await mkdir(targetDir, { recursive: true });
1692
1729
  for (const dir of BASE_DIRS) {
@@ -1700,8 +1737,14 @@ async function scaffoldProject(config, targetDir) {
1700
1737
  await writeFile(join(targetDir, "app/modules/home/pages/index.tsx"), generateHomePage(config));
1701
1738
  await writeFile(join(targetDir, "middleware/01.logger.ts"), generateSampleMiddleware(config));
1702
1739
  await writeFile(join(targetDir, "routes/api/hello.ts"), generateHelloRoute(config));
1740
+ if (config.middleware === "hono") {
1741
+ await writeFile(join(targetDir, "server.ts"), generateHonoServerEntry());
1742
+ } else if (config.middleware === "elysia") {
1743
+ await writeFile(join(targetDir, "server.ts"), generateElysiaServerEntry());
1744
+ }
1703
1745
  const stylingFiles = generateStylingFiles(config);
1704
1746
  for (const [filePath, content] of stylingFiles) {
1747
+ await mkdir(join(targetDir, dirname(filePath)), { recursive: true });
1705
1748
  await writeFile(join(targetDir, filePath), content);
1706
1749
  }
1707
1750
  await writeFile(join(targetDir, "public/favicon.ico"), getFaviconBuffer());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-avalon",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Scaffold a new Avalon project with multi-framework islands architecture",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -10,11 +10,21 @@
10
10
  "directory": "packages/create-avalon"
11
11
  },
12
12
  "homepage": "https://useavalon.dev",
13
- "keywords": ["avalon", "create", "scaffold", "cli", "islands", "vite"],
13
+ "keywords": [
14
+ "avalon",
15
+ "create",
16
+ "scaffold",
17
+ "cli",
18
+ "islands",
19
+ "vite"
20
+ ],
14
21
  "bin": {
15
22
  "create-avalon": "dist/cli.js"
16
23
  },
17
- "files": ["dist", "README.md"],
24
+ "files": [
25
+ "dist",
26
+ "README.md"
27
+ ],
18
28
  "scripts": {
19
29
  "build": "bun build src/cli.ts --outdir dist --target node --format esm",
20
30
  "prepublishOnly": "bun run build"