create-avalon 0.1.15 → 0.1.16

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 +89 -1
  3. package/package.json +39 -39
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
@@ -1371,6 +1371,11 @@ function generateViteConfig(config) {
1371
1371
  ` nitro: {`,
1372
1372
  ` preset: process.env.NITRO_PRESET || 'node_server',`,
1373
1373
  ` streaming: true,`,
1374
+ ` prerender: {`,
1375
+ ` routes: ['/'],`,
1376
+ ` crawlLinks: true,`,
1377
+ ` ignore: [],`,
1378
+ ` },`,
1374
1379
  ` },`,
1375
1380
  ` });`,
1376
1381
  "",
@@ -1784,7 +1789,7 @@ function finish() {
1784
1789
  setTimeout(() => {
1785
1790
  console.log('[build] Running post-build...');
1786
1791
  try {
1787
- execSync('node post-build.mjs', { cwd: CWD, stdio: 'inherit', timeout: 60_000 });
1792
+ execSync('node post-build.mjs', { cwd: CWD, stdio: 'inherit', timeout: 120_000 });
1788
1793
  } catch (err) {
1789
1794
  console.error('[build] post-build warning:', err.message);
1790
1795
  }
@@ -1944,11 +1949,94 @@ function generatePostBuildMjs() {
1944
1949
  `}`,
1945
1950
  ``,
1946
1951
  `// ── Run ──────────────────────────────────────────────────────────`,
1952
+ `(async () => {`,
1953
+ ``,
1947
1954
  `generateIslandRedirects();`,
1948
1955
  `copyAdapters();`,
1949
1956
  `copyToNetlifyPaths();`,
1950
1957
  `ensureNetlifyRedirects();`,
1958
+ ``,
1959
+ `// ── Prerender (SSG) ──────────────────────────────────────────────`,
1960
+ `// Spawn the built server and fetch routes to generate static HTML.`,
1961
+ `const serverEntries = [`,
1962
+ ` join(CWD, '.output', 'server', 'index.mjs'),`,
1963
+ ` join(CWD, '.netlify', 'functions-internal', 'server', 'server.mjs'),`,
1964
+ ` join(CWD, '.netlify', 'v1', 'functions', 'server', 'server.mjs'),`,
1965
+ `];`,
1966
+ `const serverEntry = serverEntries.find(p => existsSync(p));`,
1967
+ `const outputDir = [join(CWD, '.output', 'public'), DIST_DIR].find(d => existsSync(d));`,
1968
+ ``,
1969
+ `if (serverEntry && outputDir) {`,
1970
+ ` const { spawn: spawnProcess } = await import('node:child_process');`,
1971
+ ` const PORT = 13172;`,
1972
+ ` const baseUrl = 'http://localhost:' + PORT;`,
1973
+ ` console.log('[prerender] Spawning server on port ' + PORT + '...');`,
1974
+ ` const srv = spawnProcess('node', [serverEntry], {`,
1975
+ ` env: { ...process.env, PORT: String(PORT), NITRO_PORT: String(PORT), HOST: '127.0.0.1', NITRO_HOST: '127.0.0.1', NODE_ENV: 'production' },`,
1976
+ ` stdio: ['ignore', 'pipe', 'pipe'],`,
1977
+ ` });`,
1978
+ ` srv.stdout?.on('data', d => { const m = d.toString().trim(); if (m) console.log('[prerender:server] ' + m); });`,
1979
+ ` srv.stderr?.on('data', d => { const m = d.toString().trim(); if (m) console.error('[prerender:server:err] ' + m); });`,
1980
+ ` let ready = false;`,
1981
+ ` const t0 = Date.now();`,
1982
+ ` while (Date.now() - t0 < 15000) {`,
1983
+ ` try { const r = await fetch(baseUrl + '/'); if (r.ok || r.status < 500) { ready = true; break; } } catch {}`,
1984
+ ` await new Promise(r => setTimeout(r, 200));`,
1985
+ ` }`,
1986
+ ` if (ready) {`,
1987
+ ` console.log('[prerender] Server ready');`,
1988
+ ` const visited = new Set();`,
1989
+ ` const queue = ['/'];`,
1990
+ ` const prerendered = [];`,
1991
+ ` while (queue.length > 0) {`,
1992
+ ` const batch = queue.splice(0, 4);`,
1993
+ ` await Promise.all(batch.map(async (route) => {`,
1994
+ ` const norm = route.endsWith('/') && route !== '/' ? route.slice(0, -1) : route;`,
1995
+ ` if (visited.has(norm)) return;`,
1996
+ ` visited.add(norm);`,
1997
+ ` try {`,
1998
+ ` const res = await fetch(baseUrl + norm);`,
1999
+ ` if (!res.ok) { console.error('[prerender] ' + norm + ' returned ' + res.status); return; }`,
2000
+ ` const html = await res.text();`,
2001
+ ` const fileName = join(norm, 'index.html');`,
2002
+ ` const out = join(outputDir, fileName);`,
2003
+ ` mkdirSync(dirname(out), { recursive: true });`,
2004
+ ` writeFileSync(out, html);`,
2005
+ ` prerendered.push(norm);`,
2006
+ ` console.log('[prerender] ' + norm);`,
2007
+ ` // Crawl links`,
2008
+ ` const re = /<a\\s[^>]*href=["']([^"'#?]+)/gi;`,
2009
+ ` let m;`,
2010
+ ` while ((m = re.exec(html)) !== null) {`,
2011
+ ` const href = m[1];`,
2012
+ ` if (href.startsWith('/') && !href.startsWith('//') && !href.startsWith('/assets/') && !href.startsWith('/islands/') && !href.match(/\\.\\w{2,5}$/)) {`,
2013
+ ` const n = href.endsWith('/') && href !== '/' ? href.slice(0, -1) : href;`,
2014
+ ` if (!visited.has(n)) queue.push(n);`,
2015
+ ` }`,
2016
+ ` }`,
2017
+ ` } catch (err) { console.error('[prerender] Error fetching ' + norm + ':', err.message); }`,
2018
+ ` }));`,
2019
+ ` }`,
2020
+ ` srv.kill('SIGKILL');`,
2021
+ ` console.log('[prerender] Done: ' + prerendered.length + ' page(s)');`,
2022
+ ` // Copy to alt output dirs`,
2023
+ ` for (const alt of [DIST_DIR, join(CWD, '.netlify', 'v1', 'functions', 'server', 'public')].filter(d => d !== outputDir && existsSync(dirname(d)))) {`,
2024
+ ` for (const route of prerendered) {`,
2025
+ ` const f = join(route, 'index.html');`,
2026
+ ` const src = join(outputDir, f);`,
2027
+ ` const dest = join(alt, f);`,
2028
+ ` if (existsSync(src)) { mkdirSync(dirname(dest), { recursive: true }); copyFileSync(src, dest); }`,
2029
+ ` }`,
2030
+ ` }`,
2031
+ ` } else {`,
2032
+ ` srv.kill('SIGKILL');`,
2033
+ ` console.error('[prerender] Server did not start, skipping prerender');`,
2034
+ ` }`,
2035
+ `}`,
2036
+ ``,
1951
2037
  `console.log('[post-build] Complete');`,
2038
+ ``,
2039
+ `})().catch(err => { console.error('[post-build] Fatal:', err); process.exit(1); });`,
1952
2040
  ``
1953
2041
  ];
1954
2042
  return lines.join(`
package/package.json CHANGED
@@ -1,39 +1,39 @@
1
- {
2
- "name": "create-avalon",
3
- "version": "0.1.15",
4
- "description": "Scaffold a new Avalon project with multi-framework islands architecture",
5
- "license": "MIT",
6
- "type": "module",
7
- "repository": {
8
- "type": "git",
9
- "url": "https://github.com/useAvalon/Avalon.git",
10
- "directory": "packages/create-avalon"
11
- },
12
- "homepage": "https://useavalon.dev",
13
- "keywords": [
14
- "avalon",
15
- "create",
16
- "scaffold",
17
- "cli",
18
- "islands",
19
- "vite"
20
- ],
21
- "bin": {
22
- "create-avalon": "dist/cli.js"
23
- },
24
- "files": [
25
- "dist",
26
- "README.md"
27
- ],
28
- "scripts": {
29
- "build": "bun build src/cli.ts --outdir dist --target node --format esm",
30
- "prepublishOnly": "bun run build"
31
- },
32
- "dependencies": {
33
- "@clack/prompts": "^1.1.0"
34
- },
35
- "devDependencies": {
36
- "fast-check": "^4.6.0",
37
- "vitest": "^4.1.0"
38
- }
39
- }
1
+ {
2
+ "name": "create-avalon",
3
+ "version": "0.1.16",
4
+ "description": "Scaffold a new Avalon project with multi-framework islands architecture",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/useAvalon/Avalon.git",
10
+ "directory": "packages/create-avalon"
11
+ },
12
+ "homepage": "https://useavalon.dev",
13
+ "keywords": [
14
+ "avalon",
15
+ "create",
16
+ "scaffold",
17
+ "cli",
18
+ "islands",
19
+ "vite"
20
+ ],
21
+ "bin": {
22
+ "create-avalon": "dist/cli.js"
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "README.md"
27
+ ],
28
+ "scripts": {
29
+ "build": "bun build src/cli.ts --outdir dist --target node --format esm",
30
+ "prepublishOnly": "bun run build"
31
+ },
32
+ "dependencies": {
33
+ "@clack/prompts": "^1.1.0"
34
+ },
35
+ "devDependencies": {
36
+ "fast-check": "^4.6.0",
37
+ "vitest": "^4.1.0"
38
+ }
39
+ }