create-avalon 0.1.16 → 0.1.17

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 +55 -14
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1735,6 +1735,14 @@ function generateNetlifyToml(config) {
1735
1735
 
1736
1736
  [functions]
1737
1737
  directory = "netlify/functions"
1738
+
1739
+ # SSR catch-all — Netlify checks for a matching static/prerendered file
1740
+ # first (force=false is the default in netlify.toml). Only requests with
1741
+ # no static file hit the server function.
1742
+ [[redirects]]
1743
+ from = "/*"
1744
+ to = "/.netlify/functions/server"
1745
+ status = 200
1738
1746
  `;
1739
1747
  }
1740
1748
  function generateBuildMjs() {
@@ -1842,7 +1850,6 @@ function generatePostBuildMjs() {
1842
1850
  ` * - Generates _redirects for island JS path mapping`,
1843
1851
  ` * - Copies island JS to clean paths for local preview`,
1844
1852
  ` * - Copies server function to all Netlify function paths`,
1845
- ` * - Ensures SSR catch-all redirect exists`,
1846
1853
  ` */`,
1847
1854
  ``,
1848
1855
  `import {`,
@@ -1937,27 +1944,47 @@ function generatePostBuildMjs() {
1937
1944
  ` console.log('[netlify-fn] Copied server function to all Netlify paths');`,
1938
1945
  `}`,
1939
1946
  ``,
1940
- `// ── Ensure SSR catch-all redirect ─────────────────────────────────`,
1941
- `function ensureNetlifyRedirects() {`,
1942
- ` const redirectsPath = join(DIST_DIR, '_redirects');`,
1943
- ` let content = existsSync(redirectsPath) ? readFileSync(redirectsPath, 'utf-8') : '';`,
1944
- ` if (content.includes('/.netlify/functions/server')) return;`,
1945
- ` const catchAll = '\\n# SSR catch-all (Nitro server function)\\n/* /.netlify/functions/server 200\\n';`,
1946
- ` content = content.trimEnd() + '\\n' + catchAll;`,
1947
- ` writeFileSync(redirectsPath, content);`,
1948
- ` console.log('[redirects] Added SSR catch-all to _redirects');`,
1949
- `}`,
1950
- ``,
1951
1947
  `// ── Run ──────────────────────────────────────────────────────────`,
1952
1948
  `(async () => {`,
1953
1949
  ``,
1954
1950
  `generateIslandRedirects();`,
1955
1951
  `copyAdapters();`,
1956
1952
  `copyToNetlifyPaths();`,
1957
- `ensureNetlifyRedirects();`,
1958
1953
  ``,
1959
1954
  `// ── Prerender (SSG) ──────────────────────────────────────────────`,
1960
1955
  `// Spawn the built server and fetch routes to generate static HTML.`,
1956
+ `// The Netlify preset produces a function handler (not a standalone`,
1957
+ `// server), so we detect it and wrap it in a minimal HTTP server.`,
1958
+ ``,
1959
+ `function isNetlifyHandler(entryPath) {`,
1960
+ ` const code = readFileSync(entryPath, 'utf-8');`,
1961
+ ` return code.includes('path: "/*"') || code.includes('path:\`/*\`');`,
1962
+ `}`,
1963
+ ``,
1964
+ `function writeNetlifyWrapper(serverDir, port) {`,
1965
+ ` const wrapperPath = join(serverDir, '_prerender-server.mjs');`,
1966
+ ` writeFileSync(wrapperPath, [`,
1967
+ ` 'import { createServer } from "node:http";',`,
1968
+ ` 'import handler from "./main.mjs";',`,
1969
+ ` 'const PORT = ' + port + ';',`,
1970
+ ` 'const server = createServer(async (req, res) => {',`,
1971
+ ` ' try {',`,
1972
+ ` ' const url = new URL(req.url, "http://localhost:" + PORT);',`,
1973
+ ` ' const headers = new Headers();',`,
1974
+ ` ' for (const [key, value] of Object.entries(req.headers)) {',`,
1975
+ ` ' if (value) headers.set(key, Array.isArray(value) ? value.join(", ") : value);',`,
1976
+ ` ' }',`,
1977
+ ` ' const request = new Request(url.toString(), { method: req.method, headers });',`,
1978
+ ` ' const response = await handler(request);',`,
1979
+ ` ' res.writeHead(response.status, Object.fromEntries(response.headers.entries()));',`,
1980
+ ` ' res.end(await response.text());',`,
1981
+ ` ' } catch (err) { console.error("[prerender-wrapper]", err); res.writeHead(500); res.end("Error"); }',`,
1982
+ ` '});',`,
1983
+ ` 'server.listen(PORT, "127.0.0.1", () => console.log("[prerender-wrapper] Listening on port " + PORT));',`,
1984
+ ` ].join('\\n'));`,
1985
+ ` return wrapperPath;`,
1986
+ `}`,
1987
+ ``,
1961
1988
  `const serverEntries = [`,
1962
1989
  ` join(CWD, '.output', 'server', 'index.mjs'),`,
1963
1990
  ` join(CWD, '.netlify', 'functions-internal', 'server', 'server.mjs'),`,
@@ -1970,8 +1997,17 @@ function generatePostBuildMjs() {
1970
1997
  ` const { spawn: spawnProcess } = await import('node:child_process');`,
1971
1998
  ` const PORT = 13172;`,
1972
1999
  ` const baseUrl = 'http://localhost:' + PORT;`,
2000
+ ` const netlifyMode = isNetlifyHandler(serverEntry);`,
2001
+ ` let actualEntry = serverEntry;`,
2002
+ ` if (netlifyMode) {`,
2003
+ ` const mainMjs = join(dirname(serverEntry), 'main.mjs');`,
2004
+ ` if (existsSync(mainMjs)) {`,
2005
+ ` actualEntry = writeNetlifyWrapper(dirname(serverEntry), PORT);`,
2006
+ ` console.log('[prerender] Netlify handler detected, using wrapper');`,
2007
+ ` }`,
2008
+ ` }`,
1973
2009
  ` console.log('[prerender] Spawning server on port ' + PORT + '...');`,
1974
- ` const srv = spawnProcess('node', [serverEntry], {`,
2010
+ ` const srv = spawnProcess('node', [actualEntry], {`,
1975
2011
  ` 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
2012
  ` stdio: ['ignore', 'pipe', 'pipe'],`,
1977
2013
  ` });`,
@@ -2019,6 +2055,11 @@ function generatePostBuildMjs() {
2019
2055
  ` }`,
2020
2056
  ` srv.kill('SIGKILL');`,
2021
2057
  ` console.log('[prerender] Done: ' + prerendered.length + ' page(s)');`,
2058
+ ` // Clean up wrapper`,
2059
+ ` if (netlifyMode) {`,
2060
+ ` const wp = join(dirname(serverEntry), '_prerender-server.mjs');`,
2061
+ ` if (existsSync(wp)) unlinkSync(wp);`,
2062
+ ` }`,
2022
2063
  ` // Copy to alt output dirs`,
2023
2064
  ` for (const alt of [DIST_DIR, join(CWD, '.netlify', 'v1', 'functions', 'server', 'public')].filter(d => d !== outputDir && existsSync(dirname(d)))) {`,
2024
2065
  ` for (const route of prerendered) {`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-avalon",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "Scaffold a new Avalon project with multi-framework islands architecture",
5
5
  "license": "MIT",
6
6
  "type": "module",