create-avalon 0.1.10 → 0.1.12

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 (2) hide show
  1. package/dist/cli.js +120 -75
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1192,7 +1192,7 @@ async function collectProjectConfig(initialName) {
1192
1192
 
1193
1193
  // src/scaffold.ts
1194
1194
  import { mkdir, writeFile } from "node:fs/promises";
1195
- import { join } from "node:path";
1195
+ import { join, dirname } from "node:path";
1196
1196
 
1197
1197
  // src/types.ts
1198
1198
  var INTEGRATION_PACKAGES = {
@@ -1254,6 +1254,8 @@ function generatePackageJson(config) {
1254
1254
  devDependencies["tailwindcss"] = "latest";
1255
1255
  devDependencies["@tailwindcss/vite"] = "latest";
1256
1256
  dependencies["@shadcn/ui"] = "latest";
1257
+ dependencies["tailwind-merge"] = "^3.5.0";
1258
+ dependencies["clsx"] = "^2.1.1";
1257
1259
  break;
1258
1260
  }
1259
1261
  const pkg = {
@@ -1282,20 +1284,33 @@ function generateTsConfig() {
1282
1284
  esModuleInterop: true,
1283
1285
  skipLibCheck: true,
1284
1286
  allowArbitraryExtensions: true,
1287
+ allowImportingTsExtensions: true,
1288
+ noEmit: true,
1285
1289
  jsx: "react-jsx",
1286
1290
  paths: {
1287
1291
  "@shared/*": ["./app/shared/*"],
1288
1292
  "@modules/*": ["./app/modules/*"]
1289
1293
  }
1290
1294
  },
1291
- include: ["app/**/*.ts", "app/**/*.tsx", "server/**/*.ts", "routes/**/*.ts", "middleware/**/*.ts"]
1295
+ include: ["app/**/*.ts", "app/**/*.tsx", "app/**/*.d.ts", "server/**/*.ts", "routes/**/*.ts", "middleware/**/*.ts"]
1292
1296
  };
1293
1297
  return JSON.stringify(tsconfig, null, 2);
1294
1298
  }
1299
+ function generateEnvDts() {
1300
+ return `/// <reference types="@useavalon/avalon/types" />
1301
+
1302
+ // Virtual module declarations
1303
+ declare module 'virtual:avalon/config' {
1304
+ const config: Record<string, unknown>;
1305
+ export default config;
1306
+ }
1307
+ `;
1308
+ }
1295
1309
 
1296
1310
  // src/templates/vite-config.ts
1297
1311
  function generateViteConfig(config) {
1298
1312
  const imports = [
1313
+ `import { resolve } from 'node:path';`,
1299
1314
  `import { defineConfig, type UserConfig } from 'vite';`,
1300
1315
  `import { avalon } from '@useavalon/avalon';`
1301
1316
  ];
@@ -1348,6 +1363,14 @@ function generateViteConfig(config) {
1348
1363
  `),
1349
1364
  ` ],`,
1350
1365
  ``,
1366
+ ` resolve: {`,
1367
+ ` alias: {`,
1368
+ ` '@shared': resolve(__dirname, 'app/shared'),`,
1369
+ ` '@modules': resolve(__dirname, 'app/modules'),`,
1370
+ ` '@': resolve(__dirname, 'app'),`,
1371
+ ` },`,
1372
+ ` },`,
1373
+ ``,
1351
1374
  ` server: {`,
1352
1375
  ` port: 3000,`,
1353
1376
  ` },`,
@@ -1453,91 +1476,32 @@ export default async function HomePage() {
1453
1476
  }
1454
1477
 
1455
1478
  // src/templates/middleware.ts
1456
- function generateSampleMiddleware(config) {
1457
- switch (config.middleware) {
1458
- case "h3":
1459
- return generateH3Middleware();
1460
- case "hono":
1461
- return generateHonoMiddleware();
1462
- case "elysia":
1463
- return generateElysiaMiddleware();
1464
- }
1465
- }
1466
- function generateH3Middleware() {
1467
- return `import { defineHandler } from 'nitro/h3';
1479
+ function generateSampleMiddleware(_config) {
1480
+ return `import { defineHandler } from 'nitro';
1468
1481
 
1469
1482
  export default defineHandler((event) => {
1470
- console.log(\`[\${new Date().toISOString()}] \${event.method} \${event.path}\`);
1471
- });
1472
- `;
1473
- }
1474
- function generateHonoMiddleware() {
1475
- return `import { Hono } from 'hono';
1476
-
1477
- const app = new Hono();
1478
-
1479
- app.use('*', async (c, next) => {
1480
- console.log(\`[\${new Date().toISOString()}] \${c.req.method} \${c.req.path}\`);
1481
- await next();
1483
+ console.log(\`[\${new Date().toISOString()}] \${event.req.method} \${event.url.pathname}\`);
1482
1484
  });
1483
-
1484
- export default app;
1485
- `;
1486
- }
1487
- function generateElysiaMiddleware() {
1488
- return `import { Elysia } from 'elysia';
1489
-
1490
- export default new Elysia()
1491
- .onBeforeHandle(({ request }) => {
1492
- console.log(\`[\${new Date().toISOString()}] \${request.method} \${new URL(request.url).pathname}\`);
1493
- });
1494
1485
  `;
1495
1486
  }
1496
1487
 
1497
1488
  // src/templates/api-routes.ts
1498
- function generateHelloRoute(config) {
1499
- switch (config.middleware) {
1500
- case "h3":
1501
- return generateH3Route();
1502
- case "hono":
1503
- return generateHonoRoute();
1504
- case "elysia":
1505
- return generateElysiaRoute();
1506
- }
1507
- }
1508
- function generateH3Route() {
1509
- return `import { defineHandler } from 'nitro/h3';
1489
+ function generateHelloRoute(_config) {
1490
+ return `import { defineHandler } from 'nitro';
1510
1491
 
1511
1492
  export default defineHandler(() => {
1512
- return { message: 'Hello from Avalon!' };
1493
+ return Response.json({ message: 'Hello from Avalon!' });
1513
1494
  });
1514
1495
  `;
1515
1496
  }
1516
- function generateHonoRoute() {
1517
- return `import { Hono } from 'hono';
1518
-
1519
- const app = new Hono();
1520
-
1521
- app.get('/', (c) => {
1522
- return c.json({ message: 'Hello from Avalon!' });
1523
- });
1524
-
1525
- export default app;
1526
- `;
1527
- }
1528
- function generateElysiaRoute() {
1529
- return `import { Elysia } from 'elysia';
1530
-
1531
- export default new Elysia()
1532
- .get('/', () => ({ message: 'Hello from Avalon!' }));
1533
- `;
1534
- }
1535
1497
 
1536
1498
  // src/templates/styling.ts
1537
1499
  function generateStylingFiles(config) {
1538
1500
  const files = new Map;
1539
1501
  files.set("app/shared/styles/main.css", generateMainCss(config));
1540
- files.set("app/shared/styles/reset.css", generateResetCss());
1502
+ if (config.styling === "css-modules") {
1503
+ files.set("app/shared/styles/reset.css", generateResetCss());
1504
+ }
1541
1505
  switch (config.styling) {
1542
1506
  case "css-modules":
1543
1507
  files.set("app/shared/styles/tokens.css", generateTokensCss());
@@ -1547,19 +1511,21 @@ function generateStylingFiles(config) {
1547
1511
  break;
1548
1512
  case "tailwind":
1549
1513
  files.set("tailwind.config.js", generateTailwindConfig());
1550
- files.set("app/shared/styles/global.css", generateTailwindGlobalCss());
1514
+ files.set("app/shared/styles/global.css", generateTailwindGlobalCss(config));
1551
1515
  break;
1552
1516
  case "shadcn":
1553
1517
  files.set("tailwind.config.js", generateTailwindConfig());
1554
- files.set("app/shared/styles/global.css", generateTailwindGlobalCss());
1518
+ files.set("app/shared/styles/global.css", generateTailwindGlobalCss(config));
1555
1519
  files.set("components.json", generateShadcnComponentsJson(config));
1520
+ files.set("app/shared/utils/cn.ts", generateCnUtil());
1556
1521
  break;
1557
1522
  }
1558
1523
  return files;
1559
1524
  }
1560
1525
  function generateMainCss(config) {
1561
- const imports = [`@import './reset.css';`];
1526
+ const imports = [];
1562
1527
  if (config.styling === "css-modules") {
1528
+ imports.push(`@import './reset.css';`);
1563
1529
  imports.push(`@import './tokens.css';`);
1564
1530
  } else {
1565
1531
  imports.push(`@import './global.css';`);
@@ -1667,8 +1633,47 @@ export default {
1667
1633
  };
1668
1634
  `;
1669
1635
  }
1670
- function generateTailwindGlobalCss() {
1671
- return `@import "tailwindcss";
1636
+ function generateTailwindGlobalCss(config) {
1637
+ const lines = [`@import "tailwindcss";`];
1638
+ if (config.styling === "shadcn") {
1639
+ lines.push("");
1640
+ lines.push(`@theme inline {
1641
+ --color-background: oklch(1 0 0);
1642
+ --color-foreground: oklch(0.145 0 0);
1643
+ --color-card: oklch(1 0 0);
1644
+ --color-card-foreground: oklch(0.145 0 0);
1645
+ --color-popover: oklch(1 0 0);
1646
+ --color-popover-foreground: oklch(0.145 0 0);
1647
+ --color-primary: oklch(0.205 0 0);
1648
+ --color-primary-foreground: oklch(0.985 0 0);
1649
+ --color-secondary: oklch(0.97 0 0);
1650
+ --color-secondary-foreground: oklch(0.205 0 0);
1651
+ --color-muted: oklch(0.97 0 0);
1652
+ --color-muted-foreground: oklch(0.556 0 0);
1653
+ --color-accent: oklch(0.97 0 0);
1654
+ --color-accent-foreground: oklch(0.205 0 0);
1655
+ --color-destructive: oklch(0.577 0.245 27.325);
1656
+ --color-destructive-foreground: oklch(0.577 0.245 27.325);
1657
+ --color-border: oklch(0.922 0 0);
1658
+ --color-input: oklch(0.922 0 0);
1659
+ --color-ring: oklch(0.708 0 0);
1660
+ --radius-sm: 0.25rem;
1661
+ --radius-md: 0.375rem;
1662
+ --radius-lg: 0.5rem;
1663
+ --radius-xl: 0.75rem;
1664
+ }`);
1665
+ }
1666
+ return lines.join(`
1667
+ `) + `
1668
+ `;
1669
+ }
1670
+ function generateCnUtil() {
1671
+ return `import { clsx, type ClassValue } from 'clsx';
1672
+ import { twMerge } from 'tailwind-merge';
1673
+
1674
+ export function cn(...inputs: ClassValue[]) {
1675
+ return twMerge(clsx(inputs));
1676
+ }
1672
1677
  `;
1673
1678
  }
1674
1679
  function generateShadcnComponentsJson(config) {
@@ -1695,6 +1700,39 @@ function getFaviconBuffer() {
1695
1700
  }
1696
1701
 
1697
1702
  // src/scaffold.ts
1703
+ function generateHonoServerEntry() {
1704
+ return `import { Hono } from 'hono';
1705
+
1706
+ const app = new Hono();
1707
+
1708
+ // Add your Hono middleware and routes here.
1709
+ // This file is the Nitro server entry using the web fetch interface.
1710
+ // Route files in routes/ still use defineHandler from 'nitro'.
1711
+
1712
+ app.use('*', async (c, next) => {
1713
+ console.log(\`[\${new Date().toISOString()}] \${c.req.method} \${c.req.path}\`);
1714
+ await next();
1715
+ });
1716
+
1717
+ export default app;
1718
+ `;
1719
+ }
1720
+ function generateElysiaServerEntry() {
1721
+ return `import { Elysia } from 'elysia';
1722
+
1723
+ const app = new Elysia();
1724
+
1725
+ // Add your Elysia middleware and routes here.
1726
+ // This file is the Nitro server entry using the web fetch interface.
1727
+ // Route files in routes/ still use defineHandler from 'nitro'.
1728
+
1729
+ app.onBeforeHandle(({ request }) => {
1730
+ console.log(\`[\${new Date().toISOString()}] \${request.method} \${new URL(request.url).pathname}\`);
1731
+ });
1732
+
1733
+ export default app;
1734
+ `;
1735
+ }
1698
1736
  async function scaffoldProject(config, targetDir) {
1699
1737
  await mkdir(targetDir, { recursive: true });
1700
1738
  for (const dir of BASE_DIRS) {
@@ -1708,13 +1746,20 @@ async function scaffoldProject(config, targetDir) {
1708
1746
  await writeFile(join(targetDir, "app/modules/home/pages/index.tsx"), generateHomePage(config));
1709
1747
  await writeFile(join(targetDir, "middleware/01.logger.ts"), generateSampleMiddleware(config));
1710
1748
  await writeFile(join(targetDir, "routes/api/hello.ts"), generateHelloRoute(config));
1749
+ if (config.middleware === "hono") {
1750
+ await writeFile(join(targetDir, "server.ts"), generateHonoServerEntry());
1751
+ } else if (config.middleware === "elysia") {
1752
+ await writeFile(join(targetDir, "server.ts"), generateElysiaServerEntry());
1753
+ }
1711
1754
  const stylingFiles = generateStylingFiles(config);
1712
1755
  for (const [filePath, content] of stylingFiles) {
1756
+ await mkdir(join(targetDir, dirname(filePath)), { recursive: true });
1713
1757
  await writeFile(join(targetDir, filePath), content);
1714
1758
  }
1715
1759
  await writeFile(join(targetDir, "public/favicon.ico"), getFaviconBuffer());
1716
1760
  await writeFile(join(targetDir, "server/env.d.ts"), `/// <reference types="nitro" />
1717
1761
  `);
1762
+ await writeFile(join(targetDir, "app/env.d.ts"), generateEnvDts());
1718
1763
  await writeFile(join(targetDir, "server/renderer.ts"), [
1719
1764
  `import { createNitroRenderer } from '@useavalon/avalon/nitro/renderer';`,
1720
1765
  `import avalonConfig from 'virtual:avalon/config';`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-avalon",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Scaffold a new Avalon project with multi-framework islands architecture",
5
5
  "license": "MIT",
6
6
  "type": "module",