@useavalon/avalon 0.1.89 → 0.1.90

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 (107) hide show
  1. package/dist/src/build/integration-bundler-plugin.d.ts +1 -1
  2. package/dist/src/build/integration-detection-plugin.d.ts +1 -1
  3. package/dist/src/build/integration-detection-plugin.js +1 -1
  4. package/dist/src/build/integration-resolver-plugin.d.ts +1 -1
  5. package/dist/src/build/island-code-splitting.d.ts +1 -1
  6. package/dist/src/build/island-manifest.d.ts +2 -2
  7. package/dist/src/build/island-manifest.js +1 -1
  8. package/dist/src/build/island-types-generator.js +4 -4
  9. package/dist/src/build/mdx-island-transform.js +1 -1
  10. package/dist/src/build/mdx-plugin.d.ts +2 -2
  11. package/dist/src/build/prop-extractors/index.d.ts +3 -3
  12. package/dist/src/build/prop-extractors/index.js +1 -1
  13. package/dist/src/build/prop-extractors/lit.js +1 -1
  14. package/dist/src/build/prop-extractors/svelte.js +1 -1
  15. package/dist/src/build/sidecar-file-manager.js +1 -1
  16. package/dist/src/client/adapters/index.d.ts +1 -1
  17. package/dist/src/client/adapters/index.js +1 -1
  18. package/dist/src/client/css-hmr-handler.d.ts +2 -2
  19. package/dist/src/client/framework-adapter.d.ts +2 -2
  20. package/dist/src/client/hmr-coordinator.d.ts +6 -6
  21. package/dist/src/client/types/framework-runtime.d.ts +54 -55
  22. package/dist/src/client/types/vite-hmr.d.ts +35 -35
  23. package/dist/src/client/types/vite-virtual-modules.d.ts +56 -28
  24. package/dist/src/core/components/component-analyzer.d.ts +3 -3
  25. package/dist/src/core/components/component-analyzer.js +1 -1
  26. package/dist/src/core/components/component-detection.d.ts +8 -8
  27. package/dist/src/core/components/component-detection.js +1 -1
  28. package/dist/src/core/components/enhanced-framework-detector.d.ts +2 -2
  29. package/dist/src/core/components/enhanced-framework-detector.js +1 -1
  30. package/dist/src/core/components/framework-registry.d.ts +1 -1
  31. package/dist/src/core/integrations/index.d.ts +1 -1
  32. package/dist/src/core/integrations/index.js +1 -1
  33. package/dist/src/core/integrations/registry.js +1 -1
  34. package/dist/src/core/layout/enhanced-layout-resolver.d.ts +8 -8
  35. package/dist/src/core/layout/enhanced-layout-resolver.js +1 -1
  36. package/dist/src/core/layout/layout-cache-manager.d.ts +1 -1
  37. package/dist/src/core/layout/layout-composer.d.ts +2 -2
  38. package/dist/src/core/layout/layout-composer.js +1 -1
  39. package/dist/src/core/layout/layout-data-loader.d.ts +2 -2
  40. package/dist/src/core/layout/layout-discovery.d.ts +2 -2
  41. package/dist/src/core/layout/layout-discovery.js +1 -1
  42. package/dist/src/core/layout/layout-matcher.d.ts +1 -1
  43. package/dist/src/core/layout/layout-matcher.js +1 -1
  44. package/dist/src/core/layout/layout-types.d.ts +3 -3
  45. package/dist/src/islands/component-analysis.d.ts +4 -4
  46. package/dist/src/islands/component-analysis.js +1 -1
  47. package/dist/src/islands/css-utils.js +1 -1
  48. package/dist/src/islands/discovery/index.d.ts +9 -9
  49. package/dist/src/islands/discovery/index.js +1 -1
  50. package/dist/src/islands/discovery/registry.d.ts +1 -1
  51. package/dist/src/islands/discovery/resolver.d.ts +1 -1
  52. package/dist/src/islands/discovery/resolver.js +2 -2
  53. package/dist/src/islands/discovery/scanner.d.ts +1 -1
  54. package/dist/src/islands/discovery/scanner.js +1 -1
  55. package/dist/src/islands/discovery/validator.d.ts +1 -1
  56. package/dist/src/islands/discovery/validator.js +9 -9
  57. package/dist/src/islands/discovery/watcher.d.ts +1 -1
  58. package/dist/src/islands/discovery/watcher.js +1 -1
  59. package/dist/src/islands/framework-detection.d.ts +3 -3
  60. package/dist/src/islands/framework-detection.js +1 -1
  61. package/dist/src/islands/island.js +1 -1
  62. package/dist/src/islands/universal-head-collector.d.ts +2 -2
  63. package/dist/src/middleware/discovery.d.ts +1 -1
  64. package/dist/src/middleware/discovery.js +1 -1
  65. package/dist/src/middleware/executor.d.ts +2 -2
  66. package/dist/src/middleware/index.d.ts +3 -3
  67. package/dist/src/middleware/index.js +1 -1
  68. package/dist/src/middleware/types.d.ts +2 -2
  69. package/dist/src/nitro/error-handler.d.ts +2 -2
  70. package/dist/src/nitro/error-handler.js +2 -2
  71. package/dist/src/nitro/index.d.ts +8 -8
  72. package/dist/src/nitro/index.js +1 -1
  73. package/dist/src/nitro/island-manifest.d.ts +1 -1
  74. package/dist/src/nitro/island-manifest.js +1 -1
  75. package/dist/src/nitro/middleware-adapter.d.ts +2 -2
  76. package/dist/src/nitro/types.d.ts +4 -4
  77. package/dist/src/render/isolated-ssr-renderer.d.ts +2 -2
  78. package/dist/src/render/isolated-ssr-renderer.js +1 -1
  79. package/dist/src/render/ssr.d.ts +5 -5
  80. package/dist/src/render/ssr.js +4 -4
  81. package/dist/src/schemas/api.d.ts +1 -1
  82. package/dist/src/schemas/core.d.ts +1 -1
  83. package/dist/src/schemas/index.d.ts +8 -8
  84. package/dist/src/schemas/index.js +1 -1
  85. package/dist/src/schemas/routing/index.d.ts +1 -1
  86. package/dist/src/schemas/routing/index.js +1 -1
  87. package/dist/src/schemas/routing.d.ts +4 -4
  88. package/dist/src/schemas/routing.js +1 -1
  89. package/dist/src/types/image.d.ts +38 -38
  90. package/dist/src/types/island-jsx.d.ts +16 -16
  91. package/dist/src/types/mdx.d.ts +2 -2
  92. package/dist/src/types/routing.d.ts +7 -7
  93. package/dist/src/types/routing.js +1 -1
  94. package/dist/src/types/virtual-modules.d.ts +1 -1
  95. package/dist/src/types/vite-env.d.ts +1 -1
  96. package/dist/src/vite-plugin/auto-discover.js +1 -1
  97. package/dist/src/vite-plugin/config.d.ts +1 -1
  98. package/dist/src/vite-plugin/image-optimization.d.ts +2 -2
  99. package/dist/src/vite-plugin/image-optimization.js +1 -1
  100. package/dist/src/vite-plugin/island-sidecar-plugin.js +1 -1
  101. package/dist/src/vite-plugin/module-discovery.js +1 -1
  102. package/dist/src/vite-plugin/plugin.d.ts +2 -2
  103. package/dist/src/vite-plugin/plugin.js +1 -1
  104. package/dist/src/vite-plugin/types.d.ts +1 -2
  105. package/package.json +3 -2
  106. package/dist/src/client/main-slim.js +0 -1
  107. package/dist/src/client/strategies.js +0 -1
@@ -1,14 +1,14 @@
1
- import{resolve as e,relative as t,basename as n,extname as r}from"node:path";import{readFile as i,stat as a,readdir as o}from"node:fs/promises";import{isSupportedIslandExtension as s}from"./types.js";const c={pascalCase:/^[A-Z][a-zA-Z0-9]*$/,validFileName:/^[a-zA-Z][a-zA-Z0-9._-]*$/,frameworkSuffixes:[`.solid`,`.react`,`.lit`,`.preact`]},l=`https://avalon.dev/docs/islands`;export class IslandValidator{_projectRoot;constructor(e){this._projectRoot=e}get projectRoot(){return this._projectRoot}extractComponentName(e){let t=n(e);for(let e of c.frameworkSuffixes)if(t.includes(e)){let n=t.indexOf(e);return t.slice(0,n)}let i=r(t);return t.slice(0,-i.length)}toPascalCase(e){return e.split(/[-_\s]+/).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``)}hasValidJsExport(e){let t=/export\s+default\s+/.test(e)||/export\s*\{\s*[^}]*\s+as\s+default\s*[,}]/.test(e),n=/export\s+(function|class|const)\s+[A-Z]/.test(e),r=/@customElement\s*\(/.test(e)||/customElements\.define\s*\(/.test(e);return t||n||r}isValidVueComponent(e){return/<template[\s>]/.test(e)||/<script[\s>]/.test(e)}isValidSvelteComponent(e){return e.trim().length>0}createExportError(e,t){let n=this.extractComponentName(e),r;switch(t){case`vue`:r=`Add a <template> or <script> section to your Vue component`;break;case`svelte`:r=`Add component markup to your Svelte file`;break;default:r=`Add a default export: export default function ${n}() { return <div>...</div>; }`}return{type:`invalid-export`,message:`Island component "${n}" does not export a valid component`,filePath:e,line:1,column:1,suggestion:`${r}\n\nSee: ${l}#component-exports`}}async validateExports(e){let t=[],n=[];try{let n=await i(e,`utf-8`),a=r(e).toLowerCase();a===`.vue`?this.isValidVueComponent(n)||t.push(this.createExportError(e,`vue`)):a===`.svelte`?this.isValidSvelteComponent(n)||t.push(this.createExportError(e,`svelte`)):this.hasValidJsExport(n)||t.push(this.createExportError(e,`js`))}catch{t.push({type:`invalid-export`,message:`Cannot read file: ${e}`,filePath:e,suggestion:`Check file permissions and encoding`})}return{valid:t.length===0,errors:t,warnings:n}}extractJsImports(e){let t=[],n=/import\s+(?:[\w\s{},*]+\s+from\s+)?['"]([^'"]+)['"]/g,r;for(;(r=n.exec(e))!==null;)t.push(r[1]);let i=/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;for(;(r=i.exec(e))!==null;)t.push(r[1]);let a=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;for(;(r=a.exec(e))!==null;)t.push(r[1]);return t}extractImports(e,t){let n=[],i=r(t).toLowerCase();if(i===`.vue`||i===`.svelte`){let t=e.match(/<script[^>]*>([\s\S]*?)<\/script>/gi);if(t)for(let e of t)n.push(...this.extractJsImports(e))}else n.push(...this.extractJsImports(e));return n}resolveImportToIsland(t,i,a,o){if(!t.startsWith(`.`)&&!t.startsWith(`/`))return null;if(t.startsWith(`.`)){let n=e(e(i.filePath,`..`),t);if(!r(n)){for(let e of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(o.has(n+e)){for(let t of a.values())if(t.filePath===n+e)return t}}if(o.has(n)){for(let e of a.values())if(e.filePath===n)return e}}let s=n(t).replace(/\.[^.]+$/,``);return a.get(s)||null}async buildImportGraph(e){let t=new Map,n=new Set(e.map(e=>e.filePath)),r=new Map;for(let t of e){r.set(t.name,t);let e=t.relativePath.replace(/\.[^.]+$/,``);r.set(e,t)}for(let a of e){let e=[];try{let t=await i(a.filePath,`utf-8`),o=this.extractImports(t,a.filePath);for(let t of o){let i=this.resolveImportToIsland(t,a,r,n);i&&e.push(i.filePath)}}catch{}t.set(a.filePath,e)}return t}cycleExists(e,t){let n=new Set(t);for(let r of e){if(r.length!==t.length-1)continue;let e=new Set(r),i=!0;for(let t of n)if(!e.has(t)){i=!1;break}if(i)return!0}return!1}findCycles(e){let t=[],n=new Set,r=new Set,i=[],a=o=>{n.add(o),r.add(o),i.push(o);let s=e.get(o)||[];for(let e of s)if(!n.has(e))a(e);else if(r.has(e)){let n=i.indexOf(e);if(n!==-1){let r=[...i.slice(n),e];this.cycleExists(t,r)||t.push(r)}}i.pop(),r.delete(o)};for(let t of e.keys())n.has(t)||a(t);return t}formatCycleDescription(e){return`Circular dependency detected:\n ${e.map(e=>t(this._projectRoot,e)).join(`
2
- → `)}`}async validateComponent(e){let t=[],n=[];try{if(!(await a(e)).isFile())return t.push({type:`invalid-export`,message:`Path is not a file: ${e}`,filePath:e}),{valid:!1,errors:t,warnings:n}}catch{return t.push({type:`invalid-export`,message:`File not found: ${e}`,filePath:e}),{valid:!1,errors:t,warnings:n}}let i=r(e);if(!s(i))return t.push({type:`invalid-export`,message:`Unsupported file extension: ${i}`,filePath:e,suggestion:`Use one of: .tsx, .ts, .jsx, .js, .vue, .svelte`}),{valid:!1,errors:t,warnings:n};let o=this.validateNamingConvention(this.extractComponentName(e),e);t.push(...o.errors),n.push(...o.warnings);let c=await this.validateExports(e);return t.push(...c.errors),n.push(...c.warnings),{valid:t.length===0,errors:t,warnings:n}}async validateDirectory(t){let n=[],i=[],a=!1;try{let c=await o(t.path,{withFileTypes:!0});for(let o of c){if(!o.isFile()||!s(r(o.name)))continue;a=!0;let c=e(t.path,o.name),l=await this.validateComponent(c);n.push(...l.errors),i.push(...l.warnings)}}catch{return n.push({type:`invalid-export`,message:`Cannot read directory: ${t.path}`,filePath:t.path,suggestion:`Check directory permissions`}),{valid:!1,errors:n,warnings:i}}return a||i.push({type:`empty-directory`,message:`Islands directory is empty: ${t.relativePath}`,filePath:t.path,suggestion:`Add island components or remove the empty directory`}),{valid:n.length===0,errors:n,warnings:i}}validateNamingConvention(e,t){let n=[],r=[];return c.pascalCase.test(e)||(e.length===0?n.push({type:`naming-convention`,message:`Invalid component name: empty name`,filePath:t,suggestion:`Use PascalCase naming (e.g., "Counter", "UserProfile")`}):/^[a-z]/.test(e)?r.push({type:`deprecated-pattern`,message:`Component name "${e}" should use PascalCase`,filePath:t,suggestion:`Rename to "${this.toPascalCase(e)}"`}):/[^a-zA-Z0-9]/.test(e)&&r.push({type:`deprecated-pattern`,message:`Component name "${e}" contains special characters`,filePath:t,suggestion:`Use only letters and numbers in component names`})),{valid:n.length===0,errors:n,warnings:r}}async detectCircularDependencies(e){let t=await this.buildImportGraph(e);return this.findCycles(t).map(e=>({cycle:e,description:this.formatCycleDescription(e)}))}}export function formatValidationError(e,n){let r=t(n,e.filePath),i=e.line?`${r}:${e.line}${e.column?`:${e.column}`:``}`:r,a=`Error: ${e.message}\n\n`;return a+=` File: ${i}\n`,e.suggestion&&(a+=`\n ${e.suggestion}\n`),a}export function formatValidationWarning(e,n){let r=`Warning: ${e.message}\n`;if(e.filePath){let i=t(n,e.filePath);r+=` File: ${i}\n`}return e.suggestion&&(r+=` Suggestion: ${e.suggestion}\n`),r}export function formatCircularDependency(e,n){let r=e.cycle.map(e=>t(n,e)),i=`Error: Circular dependency detected
1
+ import{stat as e,readdir as t,readFile as n}from"node:fs/promises";import{basename as r,extname as i,relative as a,resolve as o}from"node:path";import{isSupportedIslandExtension as s}from"./types.js";const c={pascalCase:/^[A-Z][a-zA-Z0-9]*$/,validFileName:/^[a-zA-Z][a-zA-Z0-9._-]*$/,frameworkSuffixes:[`.solid`,`.react`,`.lit`,`.preact`]},l=`https://avalon.dev/docs/islands`;export class IslandValidator{_projectRoot;constructor(e){this._projectRoot=e}get projectRoot(){return this._projectRoot}extractComponentName(e){let t=r(e);for(let e of c.frameworkSuffixes)if(t.includes(e)){let n=t.indexOf(e);return t.slice(0,n)}let n=i(t);return t.slice(0,-n.length)}toPascalCase(e){return e.split(/[-_\s]+/).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``)}hasValidJsExport(e){let t=/export\s+default\s+/.test(e)||/export\s*\{\s*[^}]*\s+as\s+default\s*[,}]/.test(e),n=/export\s+(function|class|const)\s+[A-Z]/.test(e),r=/@customElement\s*\(/.test(e)||/customElements\.define\s*\(/.test(e);return t||n||r}isValidVueComponent(e){return/<template[\s>]/.test(e)||/<script[\s>]/.test(e)}isValidSvelteComponent(e){return e.trim().length>0}createExportError(e,t){let n=this.extractComponentName(e),r;switch(t){case`vue`:r=`Add a <template> or <script> section to your Vue component`;break;case`svelte`:r=`Add component markup to your Svelte file`;break;default:r=`Add a default export: export default function ${n}() { return <div>...</div>; }`}return{type:`invalid-export`,message:`Island component "${n}" does not export a valid component`,filePath:e,line:1,column:1,suggestion:`${r}\n\nSee: ${l}#component-exports`}}async validateExports(e){let t=[],r=[];try{let r=await n(e,`utf-8`),a=i(e).toLowerCase();a===`.vue`?this.isValidVueComponent(r)||t.push(this.createExportError(e,`vue`)):a===`.svelte`?this.isValidSvelteComponent(r)||t.push(this.createExportError(e,`svelte`)):this.hasValidJsExport(r)||t.push(this.createExportError(e,`js`))}catch{t.push({type:`invalid-export`,message:`Cannot read file: ${e}`,filePath:e,suggestion:`Check file permissions and encoding`})}return{valid:t.length===0,errors:t,warnings:r}}extractJsImports(e){let t=[],n=/import\s+(?:[\w\s{},*]+\s+from\s+)?['"]([^'"]+)['"]/g,r;for(r=n.exec(e);r!==null;r=n.exec(e))t.push(r[1]);let i=/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;for(r=i.exec(e);r!==null;r=i.exec(e))t.push(r[1]);let a=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;for(r=a.exec(e);r!==null;r=a.exec(e))t.push(r[1]);return t}extractImports(e,t){let n=[],r=i(t).toLowerCase();if(r===`.vue`||r===`.svelte`){let t=e.match(/<script[^>]*>([\s\S]*?)<\/script>/gi);if(t)for(let e of t)n.push(...this.extractJsImports(e))}else n.push(...this.extractJsImports(e));return n}resolveImportToIsland(e,t,n,a){if(!e.startsWith(`.`)&&!e.startsWith(`/`))return null;if(e.startsWith(`.`)){let r=o(o(t.filePath,`..`),e);if(!i(r)){for(let e of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(a.has(r+e)){for(let t of n.values())if(t.filePath===r+e)return t}}if(a.has(r)){for(let e of n.values())if(e.filePath===r)return e}}let s=r(e).replace(/\.[^.]+$/,``);return n.get(s)||null}async buildImportGraph(e){let t=new Map,r=new Set(e.map(e=>e.filePath)),i=new Map;for(let t of e){i.set(t.name,t);let e=t.relativePath.replace(/\.[^.]+$/,``);i.set(e,t)}for(let a of e){let e=[];try{let t=await n(a.filePath,`utf-8`),o=this.extractImports(t,a.filePath);for(let t of o){let n=this.resolveImportToIsland(t,a,i,r);n&&e.push(n.filePath)}}catch{}t.set(a.filePath,e)}return t}cycleExists(e,t){let n=new Set(t);for(let r of e){if(r.length!==t.length-1)continue;let e=new Set(r),i=!0;for(let t of n)if(!e.has(t)){i=!1;break}if(i)return!0}return!1}findCycles(e){let t=[],n=new Set,r=new Set,i=[],a=o=>{n.add(o),r.add(o),i.push(o);let s=e.get(o)||[];for(let e of s)if(!n.has(e))a(e);else if(r.has(e)){let n=i.indexOf(e);if(n!==-1){let r=[...i.slice(n),e];this.cycleExists(t,r)||t.push(r)}}i.pop(),r.delete(o)};for(let t of e.keys())n.has(t)||a(t);return t}formatCycleDescription(e){return`Circular dependency detected:\n ${e.map(e=>a(this._projectRoot,e)).join(`
2
+ → `)}`}async validateComponent(t){let n=[],r=[];try{if(!(await e(t)).isFile())return n.push({type:`invalid-export`,message:`Path is not a file: ${t}`,filePath:t}),{valid:!1,errors:n,warnings:r}}catch{return n.push({type:`invalid-export`,message:`File not found: ${t}`,filePath:t}),{valid:!1,errors:n,warnings:r}}let a=i(t);if(!s(a))return n.push({type:`invalid-export`,message:`Unsupported file extension: ${a}`,filePath:t,suggestion:`Use one of: .tsx, .ts, .jsx, .js, .vue, .svelte`}),{valid:!1,errors:n,warnings:r};let o=this.validateNamingConvention(this.extractComponentName(t),t);n.push(...o.errors),r.push(...o.warnings);let c=await this.validateExports(t);return n.push(...c.errors),r.push(...c.warnings),{valid:n.length===0,errors:n,warnings:r}}async validateDirectory(e){let n=[],r=[],a=!1;try{let c=await t(e.path,{withFileTypes:!0});for(let t of c){if(!t.isFile()||!s(i(t.name)))continue;a=!0;let c=o(e.path,t.name),l=await this.validateComponent(c);n.push(...l.errors),r.push(...l.warnings)}}catch{return n.push({type:`invalid-export`,message:`Cannot read directory: ${e.path}`,filePath:e.path,suggestion:`Check directory permissions`}),{valid:!1,errors:n,warnings:r}}return a||r.push({type:`empty-directory`,message:`Islands directory is empty: ${e.relativePath}`,filePath:e.path,suggestion:`Add island components or remove the empty directory`}),{valid:n.length===0,errors:n,warnings:r}}validateNamingConvention(e,t){let n=[],r=[];return c.pascalCase.test(e)||(e.length===0?n.push({type:`naming-convention`,message:`Invalid component name: empty name`,filePath:t,suggestion:`Use PascalCase naming (e.g., "Counter", "UserProfile")`}):/^[a-z]/.test(e)?r.push({type:`deprecated-pattern`,message:`Component name "${e}" should use PascalCase`,filePath:t,suggestion:`Rename to "${this.toPascalCase(e)}"`}):/[^a-zA-Z0-9]/.test(e)&&r.push({type:`deprecated-pattern`,message:`Component name "${e}" contains special characters`,filePath:t,suggestion:`Use only letters and numbers in component names`})),{valid:n.length===0,errors:n,warnings:r}}async detectCircularDependencies(e){let t=await this.buildImportGraph(e);return this.findCycles(t).map(e=>({cycle:e,description:this.formatCycleDescription(e)}))}}export function formatValidationError(e,t){let n=a(t,e.filePath),r=e.line?`${n}:${e.line}${e.column?`:${e.column}`:``}`:n,i=`Error: ${e.message}\n\n`;return i+=` File: ${r}\n`,e.suggestion&&(i+=`\n ${e.suggestion}\n`),i}export function formatValidationWarning(e,t){let n=`Warning: ${e.message}\n`;if(e.filePath){let r=a(t,e.filePath);n+=` File: ${r}\n`}return e.suggestion&&(n+=` Suggestion: ${e.suggestion}\n`),n}export function formatCircularDependency(e,t){let n=e.cycle.map(e=>a(t,e)),r=`Error: Circular dependency detected
3
3
 
4
- `;i+=` Dependency chain:
5
- `;for(let e=0;e<r.length;e++){let t=e===r.length-1;i+=`${t?` └─`:` ├─`} ${r[e]}\n`,t||(i+=` │ ↓
6
- `)}return i+=`
4
+ `;r+=` Dependency chain:
5
+ `;for(let e=0;e<n.length;e++){let t=e===n.length-1;r+=`${t?` └─`:` ├─`} ${n[e]}\n`,t||(r+=` │ ↓
6
+ `)}return r+=`
7
7
  Suggestion: Break the cycle by:
8
- `,i+=` - Moving shared code to a separate module
9
- `,i+=` - Using dynamic imports for one of the dependencies
10
- `,i+=` - Restructuring the component hierarchy
11
- `,i+=`\n See: ${l}#circular-dependencies\n`,i}export function formatValidationResult(e,t){let n=[];if(e.errors.length>0){n.push(`Found ${e.errors.length} error(s):\n`);for(let r of e.errors)n.push(formatValidationError(r,t))}if(e.warnings.length>0){n.length>0&&n.push(`
8
+ `,r+=` - Moving shared code to a separate module
9
+ `,r+=` - Using dynamic imports for one of the dependencies
10
+ `,r+=` - Restructuring the component hierarchy
11
+ `,r+=`\n See: ${l}#circular-dependencies\n`,r}export function formatValidationResult(e,t){let n=[];if(e.errors.length>0){n.push(`Found ${e.errors.length} error(s):\n`);for(let r of e.errors)n.push(formatValidationError(r,t))}if(e.warnings.length>0){n.length>0&&n.push(`
12
12
  `),n.push(`Found ${e.warnings.length} warning(s):\n`);for(let r of e.warnings)n.push(formatValidationWarning(r,t))}return e.valid&&e.warnings.length===0?n.push(`✓ Validation passed
13
13
  `):e.valid?n.push(`
14
14
  ✓ Validation passed with warnings
@@ -5,8 +5,8 @@
5
5
  * change events with affected island information. Supports HMR for
6
6
  * nested island directories.
7
7
  */
8
+ import type { IslandRegistry } from "./registry.ts";
8
9
  import type { IslandChangeEvent, IslandDiscoveryConfig } from "./types.ts";
9
- import { IslandRegistry } from "./registry.ts";
10
10
  /**
11
11
  * Callback type for island change events
12
12
  */
@@ -1 +1 @@
1
- import{resolve as e,relative as t,extname as n,basename as r}from"node:path";import{watch as i}from"node:fs";import{isSupportedIslandExtension as a}from"./types.js";import{discoverIslandsInDirectory as o}from"./scanner.js";const s={debounceMs:100,emitInitial:!1};export class IslandWatcher{_projectRoot;_config;_options;_registry;_watchers=[];_callbacks=new Set;_isWatching=!1;_debounceTimers=new Map;constructor(e,t,n={},r={}){this._projectRoot=e,this._registry=t,this._config=n,this._options={...s,...r}}get isWatching(){return this._isWatching}get callbackCount(){return this._callbacks.size}async watch(e){return this._callbacks.add(e),this._isWatching||await this._startWatching(),()=>{this._callbacks.delete(e),this._callbacks.size===0&&this.stop()}}stop(){this._isWatching=!1;for(let e of this._watchers)try{e.close()}catch{}this._watchers=[];for(let e of this._debounceTimers.values())clearTimeout(e);this._debounceTimers.clear()}async _startWatching(){if(this._isWatching)return;this._isWatching=!0;let e=this._registry.directories;for(let t of e)try{this._watchDirectory(t)}catch(e){console.warn(`⚠️ Failed to watch island directory ${t.relativePath}:`,e)}}_watchDirectory(t){try{let r=i(t.path,{recursive:!1},(r,i)=>{if(!this._isWatching||!i)return;let o=e(t.path,i);if(!a(n(i)))return;let s=r;this._debounceEvent(o,s,t)});this._watchers.push(r)}catch(e){if(e instanceof Error&&e.code===`ENOENT`)console.warn(`⚠️ Island directory not found: ${t.relativePath}`);else throw e}}_debounceEvent(e,t,n){let r=this._debounceTimers.get(e);r&&clearTimeout(r);let i=setTimeout(()=>{this._debounceTimers.delete(e),this._handleFileChange(e,t,n)},this._options.debounceMs);this._debounceTimers.set(e,i)}async _handleFileChange(e,n,r){let i=t(this._projectRoot,e).replace(/\\/g,`/`),a;if(n===`change`)a=`change`;else try{let{stat:t}=await import(`node:fs/promises`);await t(e),a=`add`}catch{a=`remove`}let s=null;if(a===`remove`){let t=this._getQualifiedNameFromPath(e,r);s=this._registry.resolve(t)||null,s&&this._registry.unregister(t)}else try{s=(await o(r,this._projectRoot)).find(t=>t.filePath===e)||null,a===`add`&&s&&this._registry.register(s)}catch{s=null}let c={type:a,island:s,filePath:i,timestamp:Date.now()};this._emitEvent(c)}_getQualifiedNameFromPath(e,t){let n=r(e),i=this._extractComponentName(n);return t.namespace===``?i:`${t.namespace}/${i}`}_extractComponentName(e){for(let t of[`.solid.tsx`,`.solid.jsx`,`.react.tsx`,`.react.jsx`,`.lit.ts`,`.lit.js`,`.preact.tsx`,`.preact.jsx`])if(e.endsWith(t))return e.slice(0,-t.length);for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e.endsWith(t))return e.slice(0,-t.length);return e}_emitEvent(e){for(let t of this._callbacks)try{t(e)}catch(e){console.error(`Error in island change callback:`,e)}}async refresh(){if(!this._isWatching)return;for(let e of this._watchers)try{e.close()}catch{}this._watchers=[];let e=this._registry.directories;for(let t of e)try{this._watchDirectory(t)}catch(e){console.warn(`⚠️ Failed to watch island directory ${t.relativePath}:`,e)}}}export function createIslandWatcher(e,t,n={},r={}){return new IslandWatcher(e,t,n,r)}
1
+ import{watch as e}from"node:fs";import{basename as t,extname as n,relative as r,resolve as i}from"node:path";import{discoverIslandsInDirectory as a}from"./scanner.js";import{isSupportedIslandExtension as o}from"./types.js";const s={debounceMs:100,emitInitial:!1};export class IslandWatcher{_projectRoot;_config;_options;_registry;_watchers=[];_callbacks=new Set;_isWatching=!1;_debounceTimers=new Map;constructor(e,t,n={},r={}){this._projectRoot=e,this._registry=t,this._config=n,this._options={...s,...r}}get isWatching(){return this._isWatching}get callbackCount(){return this._callbacks.size}async watch(e){return this._callbacks.add(e),this._isWatching||await this._startWatching(),()=>{this._callbacks.delete(e),this._callbacks.size===0&&this.stop()}}stop(){this._isWatching=!1;for(let e of this._watchers)try{e.close()}catch{}this._watchers=[];for(let e of this._debounceTimers.values())clearTimeout(e);this._debounceTimers.clear()}async _startWatching(){if(this._isWatching)return;this._isWatching=!0;let e=this._registry.directories;for(let t of e)try{this._watchDirectory(t)}catch(e){console.warn(`⚠️ Failed to watch island directory ${t.relativePath}:`,e)}}_watchDirectory(t){try{let r=e(t.path,{recursive:!1},(e,r)=>{if(!this._isWatching||!r)return;let a=i(t.path,r);if(!o(n(r)))return;let s=e;this._debounceEvent(a,s,t)});this._watchers.push(r)}catch(e){if(e instanceof Error&&e.code===`ENOENT`)console.warn(`⚠️ Island directory not found: ${t.relativePath}`);else throw e}}_debounceEvent(e,t,n){let r=this._debounceTimers.get(e);r&&clearTimeout(r);let i=setTimeout(()=>{this._debounceTimers.delete(e),this._handleFileChange(e,t,n)},this._options.debounceMs);this._debounceTimers.set(e,i)}async _handleFileChange(e,t,n){let i=r(this._projectRoot,e).replace(/\\/g,`/`),o;if(t===`change`)o=`change`;else try{let{stat:t}=await import(`node:fs/promises`);await t(e),o=`add`}catch{o=`remove`}let s=null;if(o===`remove`){let t=this._getQualifiedNameFromPath(e,n);s=this._registry.resolve(t)||null,s&&this._registry.unregister(t)}else try{s=(await a(n,this._projectRoot)).find(t=>t.filePath===e)||null,o===`add`&&s&&this._registry.register(s)}catch{s=null}let c={type:o,island:s,filePath:i,timestamp:Date.now()};this._emitEvent(c)}_getQualifiedNameFromPath(e,n){let r=t(e),i=this._extractComponentName(r);return n.namespace===``?i:`${n.namespace}/${i}`}_extractComponentName(e){for(let t of[`.solid.tsx`,`.solid.jsx`,`.react.tsx`,`.react.jsx`,`.lit.ts`,`.lit.js`,`.preact.tsx`,`.preact.jsx`])if(e.endsWith(t))return e.slice(0,-t.length);for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e.endsWith(t))return e.slice(0,-t.length);return e}_emitEvent(e){for(let t of this._callbacks)try{t(e)}catch(e){console.error(`Error in island change callback:`,e)}}async refresh(){if(!this._isWatching)return;for(let e of this._watchers)try{e.close()}catch{}this._watchers=[];let e=this._registry.directories;for(let t of e)try{this._watchDirectory(t)}catch(e){console.warn(`⚠️ Failed to watch island directory ${t.relativePath}:`,e)}}}export function createIslandWatcher(e,t,n={},r={}){return new IslandWatcher(e,t,n,r)}
@@ -1,7 +1,7 @@
1
- import type { Framework } from './types.ts';
2
- import { IslandRegistry } from './discovery/index.ts';
1
+ import { type IslandRegistry } from "./discovery/index.ts";
2
+ import type { Framework } from "./types.ts";
3
3
  /** Known synchronous framework types (excludes 'unknown') */
4
- type SyncFramework = 'solid' | 'vue' | 'svelte' | 'preact' | 'react' | 'lit' | 'qwik';
4
+ type SyncFramework = "solid" | "vue" | "svelte" | "preact" | "react" | "lit" | "qwik";
5
5
  /**
6
6
  * Resolve Island component path for Vite SSR loading
7
7
  * Converts /islands/* paths to /src/islands/* for proper resolution
@@ -1 +1 @@
1
- import{registry as e}from"../core/integrations/registry.js";import{createIslandRegistry as t}from"./discovery/index.js";import{getCachedPath as n,setCachedPath as r}from"./render-cache.js";import{stat as i,readFile as a}from"node:fs/promises";function o(e,t){let n=s(e);if(!n)return null;let r=t.resolve(n);if(r)return`/`+r.relativePath;if(e.includes(`/`)){let r=c(e);if(r){let e=t.resolve(n,r);if(e)return`/`+e.relativePath}}return null}function s(e){let t=e.split(`/`).filter(Boolean);if(t.length===0)return null;let n=t.at(-1);for(let e of[/\.solid\.(tsx|jsx)$/,/\.react\.(tsx|jsx)$/,/\.lit\.(ts|js)$/,/\.preact\.(tsx|jsx)$/])if(e.test(n)){n=n.replace(e,``);break}return n=n.replace(/\.(tsx|ts|jsx|js|vue|svelte)$/,``),n||null}function c(e){let t=new RegExp(/(?:\/src)?\/(.+?)\/islands\//).exec(e);return t?t[1]:``}async function l(e){try{return await i(e),!0}catch{return!1}}function u(e){if(e.includes(`/islands/`)&&!e.startsWith(`/src/`)){if(/^\/(?:modules\/)?[^/]+\/islands\//.test(e))return`/src`+e;if(e.startsWith(`/islands/`))return e.replace(`/islands/`,`/src/islands/`)}return e}async function d(t){let n=e.getAll(),r=[],i=t.replace(`.tsx`,``);for(let e of n){let t=e.config();for(let e of t.fileExtensions)e===`.tsx`||e===`.jsx`?r.push(`${i}.${t.name}${e}`):r.push(`${i}${e}`)}r.push(t);for(let e of r)if(await l(e.startsWith(`/`)?e.substring(1):e))return e;return null}export async function resolveIslandPath(e){let t=n(e);if(t!==null)return t;let i=u(e.replaceAll(`\\`,`/`)),a=f.__islandRegistry;if(a){let t=o(i,a);if(t)return r(e,t),t}if(i.endsWith(`.tsx`)&&!i.includes(`.solid.`)&&!i.includes(`.preact.`)){let t=await d(i);if(t)return r(e,t),t}return r(e,i),i}export function isNestedIslandPath(e){let t=e.replaceAll(`\\`,`/`);if(!t.includes(`/islands/`))return!1;for(let e of[/^\/islands\//,/^\/src\/islands\//,/^src\/islands\//,/^islands\//])if(e.test(t))return!1;return!0}const f=globalThis;export async function getOrCreateIslandRegistry(e=process.cwd()){return f.__islandRegistry??=await t(e),f.__islandRegistry}export function setIslandRegistry(e){f.__islandRegistry=e}export function clearIslandRegistry(){f.__islandRegistry=void 0}export function detectFrameworkFromSrc(t){let n=t.replaceAll(`\\`,`/`),r=e.getAll();for(let e of r){let t=e.config();if(n.includes(`.${t.name}.`))return t.name}for(let e of r){let t=e.config();for(let e of t.fileExtensions)if(n.endsWith(e))return t.name}return p(n)}function p(e){return e.endsWith(`.vue`)?`vue`:e.endsWith(`.svelte`)?`svelte`:e.includes(`.solid.`)||e.toLowerCase().includes(`solid`)?`solid`:e.includes(`.qwik.`)||e.toLowerCase().includes(`qwik`)?`qwik`:e.includes(`react`)||e.toLowerCase().includes(`react`)?`react`:`preact`}function m(e,t){for(let n of t){let t=n.config();for(let n of t.detectionPatterns.imports)if(n.test(e))return t.name;for(let n of t.detectionPatterns.content)if(n.test(e))return t.name}return null}function h(e){for(let t of[{pattern:/solid-js|@jsxImportSource solid-js/,framework:`solid`},{pattern:/@builder\.io\/qwik|@jsxImportSource @builder\.io\/qwik/,framework:`qwik`},{pattern:/vue|Vue/,framework:`vue`},{pattern:/svelte/,framework:`svelte`},{pattern:/react/,framework:`react`},{pattern:/preact/,framework:`preact`}])if(t.pattern.test(e))return t.framework;return`preact`}async function g(e){try{return await a((await resolveIslandPath(e)).replace(/^\//,``),`utf-8`)}catch{let t=f.__viteDevServer;if(t){let n=await resolveIslandPath(e),r=await t.ssrLoadModule(n);return JSON.stringify(r)}return null}}export async function detectFramework(t){let n=e.getAll();for(let e of n){let n=e.config();for(let e of n.fileExtensions)if(t.endsWith(e))return n.name;if(t.includes(`.${n.name}.`))return n.name}try{let e=await g(t);return e?m(e,n)||(n.length===0?h(e):`preact`):`unknown`}catch{return`unknown`}}
1
+ import{stat as e,readFile as t}from"node:fs/promises";import{registry as n}from"../core/integrations/registry.js";import{createIslandRegistry as r}from"./discovery/index.js";import{getCachedPath as i,setCachedPath as a}from"./render-cache.js";function o(e,t){let n=s(e);if(!n)return null;let r=t.resolve(n);if(r)return`/`+r.relativePath;if(e.includes(`/`)){let r=c(e);if(r){let e=t.resolve(n,r);if(e)return`/`+e.relativePath}}return null}function s(e){let t=e.split(`/`).filter(Boolean);if(t.length===0)return null;let n=t.at(-1);for(let e of[/\.solid\.(tsx|jsx)$/,/\.react\.(tsx|jsx)$/,/\.lit\.(ts|js)$/,/\.preact\.(tsx|jsx)$/])if(e.test(n)){n=n.replace(e,``);break}return n=n.replace(/\.(tsx|ts|jsx|js|vue|svelte)$/,``),n||null}function c(e){let t=new RegExp(/(?:\/src)?\/(.+?)\/islands\//).exec(e);return t?t[1]:``}async function l(t){try{return await e(t),!0}catch{return!1}}function u(e){if(e.includes(`/islands/`)&&!e.startsWith(`/src/`)){if(/^\/(?:modules\/)?[^/]+\/islands\//.test(e))return`/src`+e;if(e.startsWith(`/islands/`))return e.replace(`/islands/`,`/src/islands/`)}return e}async function d(e){let t=n.getAll(),r=[],i=e.replace(`.tsx`,``);for(let e of t){let t=e.config();for(let e of t.fileExtensions)e===`.tsx`||e===`.jsx`?r.push(`${i}.${t.name}${e}`):r.push(`${i}${e}`)}r.push(e);for(let e of r)if(await l(e.startsWith(`/`)?e.substring(1):e))return e;return null}export async function resolveIslandPath(e){let t=i(e);if(t!==null)return t;let n=u(e.replaceAll(`\\`,`/`)),r=f.__islandRegistry;if(r){let t=o(n,r);if(t)return a(e,t),t}if(n.endsWith(`.tsx`)&&!n.includes(`.solid.`)&&!n.includes(`.preact.`)){let t=await d(n);if(t)return a(e,t),t}return a(e,n),n}export function isNestedIslandPath(e){let t=e.replaceAll(`\\`,`/`);if(!t.includes(`/islands/`))return!1;for(let e of[/^\/islands\//,/^\/src\/islands\//,/^src\/islands\//,/^islands\//])if(e.test(t))return!1;return!0}const f=globalThis;export async function getOrCreateIslandRegistry(e=process.cwd()){return f.__islandRegistry??=await r(e),f.__islandRegistry}export function setIslandRegistry(e){f.__islandRegistry=e}export function clearIslandRegistry(){f.__islandRegistry=void 0}export function detectFrameworkFromSrc(e){let t=e.replaceAll(`\\`,`/`),r=n.getAll();for(let e of r){let n=e.config();if(t.includes(`.${n.name}.`))return n.name}for(let e of r){let n=e.config();for(let e of n.fileExtensions)if(t.endsWith(e))return n.name}return p(t)}function p(e){return e.endsWith(`.vue`)?`vue`:e.endsWith(`.svelte`)?`svelte`:e.includes(`.solid.`)||e.toLowerCase().includes(`solid`)?`solid`:e.includes(`.qwik.`)||e.toLowerCase().includes(`qwik`)?`qwik`:e.includes(`react`)||e.toLowerCase().includes(`react`)?`react`:`preact`}function m(e,t){for(let n of t){let t=n.config();for(let n of t.detectionPatterns.imports)if(n.test(e))return t.name;for(let n of t.detectionPatterns.content)if(n.test(e))return t.name}return null}function h(e){for(let t of[{pattern:/solid-js|@jsxImportSource solid-js/,framework:`solid`},{pattern:/@builder\.io\/qwik|@jsxImportSource @builder\.io\/qwik/,framework:`qwik`},{pattern:/vue|Vue/,framework:`vue`},{pattern:/svelte/,framework:`svelte`},{pattern:/react/,framework:`react`},{pattern:/preact/,framework:`preact`}])if(t.pattern.test(e))return t.framework;return`preact`}async function g(e){try{return await t((await resolveIslandPath(e)).replace(/^\//,``),`utf-8`)}catch{let t=f.__viteDevServer;if(t){let n=await resolveIslandPath(e),r=await t.ssrLoadModule(n);return JSON.stringify(r)}return null}}export async function detectFramework(e){let t=n.getAll();for(let n of t){let t=n.config();for(let n of t.fileExtensions)if(e.endsWith(n))return t.name;if(e.includes(`.${t.name}.`))return t.name}try{let n=await g(e);return n?m(n,t)||(t.length===0?h(n):`preact`):`unknown`}catch{return`unknown`}}
@@ -1 +1 @@
1
- import{Fragment as e,h as t}from"preact";import{getIslandBundlePath as n}from"../build/island-manifest.js";import{devError as r,devLog as i,devWarn as a,isDev as o,logRenderTiming as s}from"../utils/dev-logger.js";import{analyzeComponentFile as c,renderComponentSSROnly as l}from"./component-analysis.js";import{detectFramework as u}from"./framework-detection.js";import{isCustomDirective as d,serializeDirectiveScript as f}from"./hydration-directives.js";import{detectFrameworkFromPath as p,loadIntegration as m}from"./integration-loader.js";import{generatePerIslandScript as h}from"./per-island-script.js";import{addModulepreload as g}from"./modulepreload-collector.js";import{addUniversalCSS as _}from"./universal-css-collector.js";import{addUniversalHead as v}from"./universal-head-collector.js";function y(e){return`island-${e.replaceAll(/[^a-zA-Z0-9]/g,`-`)}`}function b(){return globalThis.__avalonHydrationMode===void 0?globalThis.__viteDevServer?!1:typeof __AVALON_PER_ISLAND__<`u`?__AVALON_PER_ISLAND__:!o():globalThis.__avalonHydrationMode===`per-island`}function x(r,i){if(!b()||i.shouldSkipHydration)return r;let a=n(i.src);i.condition===`on:client`&&g(a);let o=d(i.condition),s=o?f(i.condition):void 0;return t(e,null,r,t(`div`,{dangerouslySetInnerHTML:{__html:h({islandId:i.islandId,componentSrc:a,framework:i.framework,condition:i.condition,conditionArg:i.conditionArg,propsJson:JSON.stringify(i.props),isCustomDirective:o,directiveScript:s??void 0})},"data-island-script":``}))}function S(e){let t={};e.renderId&&(t[`data-solid-render-id`]=e.renderId);let n=e.metadata;return n?.tagName&&(t[`data-tag-name`]=n.tagName),t}function C(e,t,r,i,a){let o={"data-condition":t,"data-src":n(e),"data-props":JSON.stringify(r),"data-render-strategy":`hydrate`,...S(i)};if(d(t)){o[`data-custom-directive`]=t;let e=f(t);e&&(o[`data-directive-script`]=e)}return a&&(o[`data-condition-arg`]=a),o}function w(e){return e.startsWith(`<script`)?`script`:e.startsWith(`<style`)?`style`:e.startsWith(`<meta`)?`meta`:e.startsWith(`<link`)?`link`:e.includes(`window._$HY`)||e.includes(`_$HY=`)?`script`:`other`}function T(e){let t=e.match(/<style[^>]*>([\s\S]*?)<\/style>/i);return t?t[1].trim():null}function E(e,t,n,r){if(e.css&&_(e.css,t,n,e.scopeId),e.head){let a=e.head.trim(),o=w(a);if(o===`style`){let o=T(a);o&&(i(`${r} Extracting CSS from head <style> tag`),_(o,t,n,e.scopeId));return}v(e.head,t,n,o)}}function D(e){let{islandId:n,detectedFramework:r,shouldSkipHydration:a,src:o,condition:s,conditionArg:c,props:l,hydrationData:u,children:d}=e,f={id:n,"data-framework":r},p=a?{"data-render-strategy":`ssr-only`}:C(o,s,l,u,c);r===`lit`&&i(`🔍 [Island Component] ${o} - Lit hydration data:`,{hydrationDataKeys:Object.keys(u),metadata:u.metadata});let m={...f,...p},h;return h=typeof d==`string`?t(`avalon-island`,{...m,dangerouslySetInnerHTML:{__html:d}}):t(`avalon-island`,m,d),x(h,{islandId:n,src:o,condition:s,conditionArg:c,props:l,framework:r,shouldSkipHydration:a})}function O(e){let{islandId:r,detectedFramework:i,shouldSkipHydration:a,src:o,condition:s,props:c,hydrationData:l,conditionArg:u}=e;if(a)return t(`avalon-island`,{id:r,"data-render-strategy":`ssr-only`,"data-framework":i});let p={id:r,"data-condition":s,"data-src":n(o),"data-props":JSON.stringify(c),"data-render-strategy":`hydrate`,"data-framework":i,...S(l)};if(d(s)){p[`data-custom-directive`]=s;let e=f(s);e&&(p[`data-directive-script`]=e)}return u&&(p[`data-condition-arg`]=u),x(t(`avalon-island`,p),{islandId:r,src:o,condition:s,conditionArg:u,props:c,framework:i,shouldSkipHydration:a})}export default function k({src:e,condition:t=`on:client`,conditionArg:n,props:r={},children:o,ssr:s=t!==`on:client`,framework:c,ssrOnly:l=!1,renderOptions:u={},hydrationData:d={}}){let f=y(e),m=l||!!u.forceSSROnly,h=c||p(e),g=o!=null&&o!==``;return i(`🔍 [Island Component] ${e}`,{ssr:s,ssrOnly:l,hasChildren:g,framework:c,condition:t}),s&&g?D({islandId:f,detectedFramework:h,shouldSkipHydration:m,src:e,condition:t,conditionArg:n,props:r,hydrationData:d,children:o}):(s&&!g&&m&&a(`${e}: SSR-only component has no rendered content. This may indicate a rendering error.`),O({islandId:f,detectedFramework:h,shouldSkipHydration:m,src:e,condition:t,props:r,hydrationData:d,conditionArg:n}))}function A(e,i){let a=i instanceof Error?i.message:String(i);return r(`🚨 Island SSR failed for ${e}:`,i),i instanceof Error&&i.stack&&r(`Stack trace:`,i.stack),t(`avalon-island`,{id:y(e),"data-src":n(e),"data-ssr-error":a,"data-render-strategy":`client-only`})}async function j({src:e,condition:t,conditionArg:n,props:i,children:a,ssr:s,framework:c,ssrOnly:l,renderOptions:u,component:d}){let f=`🏝️ [${e}]`;if(!s||a)return k({src:e,condition:t,conditionArg:n,props:i,children:a,ssr:s,framework:c,ssrOnly:l,renderOptions:u});let p;try{p=await m(c)}catch(a){return r(`${f} Failed to load ${c} integration:`,a),k({src:e,condition:t,conditionArg:n,props:i,ssr:!1,framework:c,ssrOnly:l,renderOptions:u})}try{let r=await p.render({component:d??null,props:i,src:e,condition:t,ssrOnly:l,viteServer:globalThis.__viteDevServer,isDev:o()});return E(r,e,c,f),k({src:e,condition:t,conditionArg:n,props:i,children:r.html,ssr:!0,framework:c,ssrOnly:l,renderOptions:u,hydrationData:l?void 0:r.hydrationData})}catch(a){return r(`${f} Fast path SSR failed:`,a),k({src:e,condition:t,conditionArg:n,props:i,ssr:!1,framework:c,ssrOnly:l,renderOptions:u})}}async function M(e,t,n,r){if(t||n.detectScripts===!1)return t;try{let t=await c(e,n);if(t.decision.warnings?.length)for(let e of t.decision.warnings)a(`${r} Analysis warning: ${e}`);return!t.decision.shouldHydrate}catch(e){return a(`${r} Component analysis failed:`,e),t}}async function N(e){return e.endsWith(`.vue`)?`vue`:e.endsWith(`.svelte`)?`svelte`:e.endsWith(`.tsx`)||e.endsWith(`.jsx`)||e.endsWith(`.ts`)||e.endsWith(`.js`)?u(e):`unknown`}async function P(e,t,n,r,i,a,s){let c=await N(e),l=c,u=await(await F(c,a)).render({component:s??null,props:n,src:e,condition:t,ssrOnly:r,viteServer:globalThis.__viteDevServer,isDev:o()});return E(u,e,c,a),k({src:e,condition:t,props:n,children:u.html,ssr:!0,framework:l,ssrOnly:r,renderOptions:i,hydrationData:r?void 0:u.hydrationData})}async function F(e,t){try{i(`${t} Loading integration for framework: ${e}`);let n=await m(e);return i(`${t} ✅ Integration loaded successfully`),n}catch(n){throw r(`${t} Failed to load ${e} integration:`,n),Error(`Failed to load integration for framework '${e}'. Make sure @useavalon/${e} is installed.\nInstall it with: deno add @useavalon/${e}`,{cause:n})}}export async function renderIsland({src:e,condition:t=`on:client`,conditionArg:n,props:r={},children:i,ssr:a=t!==`on:client`,framework:c,ssrOnly:l=!1,renderOptions:u={},component:d}){let f=o()?performance.now():0,p=`🏝️ [${e}]`;try{return l&&!a&&(a=!0),c?await j({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:a,framework:c,ssrOnly:l,renderOptions:u,component:d}):await I({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:a,ssrOnly:l,renderOptions:u,logPrefix:p,component:d})}catch(t){return A(e,t)}finally{o()&&s(e,performance.now()-f)}}async function I(e){let{src:t,condition:n,conditionArg:a,props:o,children:s,ssr:c,ssrOnly:l,renderOptions:u,logPrefix:d,component:f}=e;if(i(`🔍 [renderIsland] ${t} - Starting render (slow path)`,{ssr:c,ssrOnly:l,hasChildren:!!s,condition:n}),await M(t,l,u,d))return L(t,n,o,s,c,u,d);if(!c||s)return k({src:t,condition:n,conditionArg:a,props:o,children:s,ssr:c,renderOptions:u});try{return await P(t,n,o,l,u,d,f)}catch(e){let i=await N(t);return r(`${d} Framework rendering failed:`,e),k({src:t,condition:n,conditionArg:a,props:o,ssr:!1,framework:i,renderOptions:u})}}function L(e,t,n,i,a,o,s){return a&&!i?l({src:e,condition:t,props:n,renderOptions:o}).catch(i=>(r(`${s} SSR failed for SSR-only component:`,i),k({src:e,condition:t,props:n,ssr:!1,ssrOnly:!0,renderOptions:o}))):k({src:e,condition:t,props:n,children:i,ssr:a,ssrOnly:!0,renderOptions:o})}
1
+ import{Fragment as e,h as t}from"preact";import{getIslandBundlePath as n}from"../build/island-manifest.js";import{devError as r,devLog as i,devWarn as a,isDev as o,logRenderTiming as s}from"../utils/dev-logger.js";import{analyzeComponentFile as c,renderComponentSSROnly as l}from"./component-analysis.js";import{detectFramework as u}from"./framework-detection.js";import{isCustomDirective as d,serializeDirectiveScript as f}from"./hydration-directives.js";import{detectFrameworkFromPath as p,loadIntegration as m}from"./integration-loader.js";import{addModulepreload as h}from"./modulepreload-collector.js";import{generatePerIslandScript as g}from"./per-island-script.js";import{addUniversalCSS as _}from"./universal-css-collector.js";import{addUniversalHead as v}from"./universal-head-collector.js";function y(e){return`island-${e.replaceAll(/[^a-zA-Z0-9]/g,`-`)}`}function b(){return globalThis.__avalonHydrationMode===void 0?globalThis.__viteDevServer?!1:typeof __AVALON_PER_ISLAND__<`u`?__AVALON_PER_ISLAND__:!o():globalThis.__avalonHydrationMode===`per-island`}function x(r,i){if(!b()||i.shouldSkipHydration)return r;let a=n(i.src);i.condition===`on:client`&&h(a);let o=d(i.condition),s=o?f(i.condition):void 0;return t(e,null,r,t(`div`,{dangerouslySetInnerHTML:{__html:g({islandId:i.islandId,componentSrc:a,framework:i.framework,condition:i.condition,conditionArg:i.conditionArg,propsJson:JSON.stringify(i.props),isCustomDirective:o,directiveScript:s??void 0})},"data-island-script":``}))}function S(e){let t={};e.renderId&&(t[`data-solid-render-id`]=e.renderId);let n=e.metadata;return n?.tagName&&(t[`data-tag-name`]=n.tagName),t}function C(e,t,r,i,a){let o={"data-condition":t,"data-src":n(e),"data-props":JSON.stringify(r),"data-render-strategy":`hydrate`,...S(i)};if(d(t)){o[`data-custom-directive`]=t;let e=f(t);e&&(o[`data-directive-script`]=e)}return a&&(o[`data-condition-arg`]=a),o}function w(e){return e.startsWith(`<script`)?`script`:e.startsWith(`<style`)?`style`:e.startsWith(`<meta`)?`meta`:e.startsWith(`<link`)?`link`:e.includes(`window._$HY`)||e.includes(`_$HY=`)?`script`:`other`}function T(e){let t=e.match(/<style[^>]*>([\s\S]*?)<\/style>/i);return t?t[1].trim():null}function E(e,t,n,r){if(e.css&&_(e.css,t,n,e.scopeId),e.head){let a=e.head.trim(),o=w(a);if(o===`style`){let o=T(a);o&&(i(`${r} Extracting CSS from head <style> tag`),_(o,t,n,e.scopeId));return}v(e.head,t,n,o)}}function D(e){let{islandId:n,detectedFramework:r,shouldSkipHydration:a,src:o,condition:s,conditionArg:c,props:l,hydrationData:u,children:d}=e,f={id:n,"data-framework":r},p=a?{"data-render-strategy":`ssr-only`}:C(o,s,l,u,c);r===`lit`&&i(`🔍 [Island Component] ${o} - Lit hydration data:`,{hydrationDataKeys:Object.keys(u),metadata:u.metadata});let m={...f,...p},h;return h=typeof d==`string`?t(`avalon-island`,{...m,dangerouslySetInnerHTML:{__html:d}}):t(`avalon-island`,m,d),x(h,{islandId:n,src:o,condition:s,conditionArg:c,props:l,framework:r,shouldSkipHydration:a})}function O(e){let{islandId:r,detectedFramework:i,shouldSkipHydration:a,src:o,condition:s,props:c,hydrationData:l,conditionArg:u}=e;if(a)return t(`avalon-island`,{id:r,"data-render-strategy":`ssr-only`,"data-framework":i});let p={id:r,"data-condition":s,"data-src":n(o),"data-props":JSON.stringify(c),"data-render-strategy":`hydrate`,"data-framework":i,...S(l)};if(d(s)){p[`data-custom-directive`]=s;let e=f(s);e&&(p[`data-directive-script`]=e)}return u&&(p[`data-condition-arg`]=u),x(t(`avalon-island`,p),{islandId:r,src:o,condition:s,conditionArg:u,props:c,framework:i,shouldSkipHydration:a})}export default function k({src:e,condition:t=`on:client`,conditionArg:n,props:r={},children:o,ssr:s=t!==`on:client`,framework:c,ssrOnly:l=!1,renderOptions:u={},hydrationData:d={}}){let f=y(e),m=l||!!u.forceSSROnly,h=c||p(e),g=o!=null&&o!==``;return i(`🔍 [Island Component] ${e}`,{ssr:s,ssrOnly:l,hasChildren:g,framework:c,condition:t}),s&&g?D({islandId:f,detectedFramework:h,shouldSkipHydration:m,src:e,condition:t,conditionArg:n,props:r,hydrationData:d,children:o}):(s&&!g&&m&&a(`${e}: SSR-only component has no rendered content. This may indicate a rendering error.`),O({islandId:f,detectedFramework:h,shouldSkipHydration:m,src:e,condition:t,props:r,hydrationData:d,conditionArg:n}))}function A(e,i){let a=i instanceof Error?i.message:String(i);return r(`🚨 Island SSR failed for ${e}:`,i),i instanceof Error&&i.stack&&r(`Stack trace:`,i.stack),t(`avalon-island`,{id:y(e),"data-src":n(e),"data-ssr-error":a,"data-render-strategy":`client-only`})}async function j({src:e,condition:t,conditionArg:n,props:i,children:a,ssr:s,framework:c,ssrOnly:l,renderOptions:u,component:d}){let f=`🏝️ [${e}]`;if(!s||a)return k({src:e,condition:t,conditionArg:n,props:i,children:a,ssr:s,framework:c,ssrOnly:l,renderOptions:u});let p;try{p=await m(c)}catch(a){return r(`${f} Failed to load ${c} integration:`,a),k({src:e,condition:t,conditionArg:n,props:i,ssr:!1,framework:c,ssrOnly:l,renderOptions:u})}try{let r=await p.render({component:d??null,props:i,src:e,condition:t,ssrOnly:l,viteServer:globalThis.__viteDevServer,isDev:o()});return E(r,e,c,f),k({src:e,condition:t,conditionArg:n,props:i,children:r.html,ssr:!0,framework:c,ssrOnly:l,renderOptions:u,hydrationData:l?void 0:r.hydrationData})}catch(a){return r(`${f} Fast path SSR failed:`,a),k({src:e,condition:t,conditionArg:n,props:i,ssr:!1,framework:c,ssrOnly:l,renderOptions:u})}}async function M(e,t,n,r){if(t||n.detectScripts===!1)return t;try{let t=await c(e,n);if(t.decision.warnings?.length)for(let e of t.decision.warnings)a(`${r} Analysis warning: ${e}`);return!t.decision.shouldHydrate}catch(e){return a(`${r} Component analysis failed:`,e),t}}async function N(e){return e.endsWith(`.vue`)?`vue`:e.endsWith(`.svelte`)?`svelte`:e.endsWith(`.tsx`)||e.endsWith(`.jsx`)||e.endsWith(`.ts`)||e.endsWith(`.js`)?u(e):`unknown`}async function P(e,t,n,r,i,a,s){let c=await N(e),l=c,u=await(await F(c,a)).render({component:s??null,props:n,src:e,condition:t,ssrOnly:r,viteServer:globalThis.__viteDevServer,isDev:o()});return E(u,e,c,a),k({src:e,condition:t,props:n,children:u.html,ssr:!0,framework:l,ssrOnly:r,renderOptions:i,hydrationData:r?void 0:u.hydrationData})}async function F(e,t){try{i(`${t} Loading integration for framework: ${e}`);let n=await m(e);return i(`${t} ✅ Integration loaded successfully`),n}catch(n){throw r(`${t} Failed to load ${e} integration:`,n),Error(`Failed to load integration for framework '${e}'. Make sure @useavalon/${e} is installed.\nInstall it with: deno add @useavalon/${e}`,{cause:n})}}export async function renderIsland({src:e,condition:t=`on:client`,conditionArg:n,props:r={},children:i,ssr:a=t!==`on:client`,framework:c,ssrOnly:l=!1,renderOptions:u={},component:d}){let f=o()?performance.now():0,p=`🏝️ [${e}]`;try{return l&&!a&&(a=!0),c?await j({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:a,framework:c,ssrOnly:l,renderOptions:u,component:d}):await I({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:a,ssrOnly:l,renderOptions:u,logPrefix:p,component:d})}catch(t){return A(e,t)}finally{o()&&s(e,performance.now()-f)}}async function I(e){let{src:t,condition:n,conditionArg:a,props:o,children:s,ssr:c,ssrOnly:l,renderOptions:u,logPrefix:d,component:f}=e;if(i(`🔍 [renderIsland] ${t} - Starting render (slow path)`,{ssr:c,ssrOnly:l,hasChildren:!!s,condition:n}),await M(t,l,u,d))return L(t,n,o,s,c,u,d);if(!c||s)return k({src:t,condition:n,conditionArg:a,props:o,children:s,ssr:c,renderOptions:u});try{return await P(t,n,o,l,u,d,f)}catch(e){let i=await N(t);return r(`${d} Framework rendering failed:`,e),k({src:t,condition:n,conditionArg:a,props:o,ssr:!1,framework:i,renderOptions:u})}}function L(e,t,n,i,a,o,s){return a&&!i?l({src:e,condition:t,props:n,renderOptions:o}).catch(i=>(r(`${s} SSR failed for SSR-only component:`,i),k({src:e,condition:t,props:n,ssr:!1,ssrOnly:!0,renderOptions:o}))):k({src:e,condition:t,props:n,children:i,ssr:a,ssrOnly:!0,renderOptions:o})}
@@ -10,7 +10,7 @@ interface HeadEntry {
10
10
  content: string;
11
11
  src: string;
12
12
  framework: string;
13
- type: 'script' | 'meta' | 'link' | 'other';
13
+ type: "script" | "meta" | "link" | "other";
14
14
  }
15
15
  declare global {
16
16
  var __universalSSRHead: Map<string, HeadEntry>;
@@ -23,7 +23,7 @@ declare global {
23
23
  * @param framework - Framework name
24
24
  * @param type - Type of head content
25
25
  */
26
- export declare function addUniversalHead(content: string, src: string, framework: string, type?: 'script' | 'meta' | 'link' | 'other'): void;
26
+ export declare function addUniversalHead(content: string, src: string, framework: string, type?: "script" | "meta" | "link" | "other"): void;
27
27
  /**
28
28
  * Get all collected head content formatted for injection into HTML head
29
29
  *
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * Requirements: 3.1, 3.2, 3.3, 3.4
15
15
  */
16
- import type { MiddlewareRoute, MiddlewareDiscoveryOptions } from './types.ts';
16
+ import type { MiddlewareDiscoveryOptions, MiddlewareRoute } from "./types.ts";
17
17
  /**
18
18
  * Discovers route-scoped middleware files in the project
19
19
  *
@@ -1 +1 @@
1
- import{join as e,relative as t,resolve as n}from"node:path";import{stat as r,readdir as i}from"node:fs/promises";const a={filePattern:`_middleware.ts`,excludeDirs:[`node_modules`,`.git`,`dist`,`.output`,`.vite`],devMode:!1},o={pages:50};export async function discoverScopedMiddleware(t){let{baseDir:r,filePattern:i=a.filePattern,excludeDirs:o=a.excludeDirs,devMode:s=a.devMode}=t,l=n(r),u=[];if(await c(e(l,`pages`),`pages`,i,o,u,s),u.sort((e,t)=>e.priority-t.priority),s&&u.length>0){console.log(`[middleware] Discovered ${u.length} route-scoped middleware:`);for(let e of u)console.log(` - ${e.type}: ${e.filePath} (priority: ${e.priority})`)}return u}async function c(e,t,n,i,a,o){try{if(!(await r(e).catch(()=>null))?.isDirectory())return;await l(e,e,t,n,i,a,o)}catch(t){o&&(!(t instanceof Error)||t.code!==`ENOENT`)&&console.warn(`[middleware] Error scanning ${e}: ${t instanceof Error?t.message:String(t)}`)}}async function l(n,r,a,o,s,c,d){try{let f=await i(r,{withFileTypes:!0});for(let i of f){let f=e(r,i.name);if(!(i.isDirectory()&&s.includes(i.name))){if(i.isDirectory())await l(n,f,a,o,s,c,d);else if(i.name===o){let e=u(f,t(n,r),a);c.push(e)}}}}catch(e){d&&(!(e instanceof Error)||e.code!==`ENOENT`)&&console.warn(`[middleware] Error reading ${r}: ${e instanceof Error?e.message:String(e)}`)}}function u(e,t,n){let r=t?`/${t}{/*}?`:`/*`,i=t?t.split(`/`).filter(Boolean).length:0,a=o[n]+i;return{pattern:new URLPattern({pathname:r}),filePath:e,priority:a,type:n}}export function getMatchingMiddleware(e,t){let n=t.pathname.startsWith(`/api`);return e.filter(e=>!(!e.pattern.test(t)||e.type===`pages`&&n))}export function clearDiscoveryCache(){}
1
+ import{stat as e,readdir as t}from"node:fs/promises";import{join as n,relative as r,resolve as i}from"node:path";const a={filePattern:`_middleware.ts`,excludeDirs:[`node_modules`,`.git`,`dist`,`.output`,`.vite`],devMode:!1},o={pages:50};export async function discoverScopedMiddleware(e){let{baseDir:t,filePattern:r=a.filePattern,excludeDirs:o=a.excludeDirs,devMode:s=a.devMode}=e,l=i(t),u=[];if(await c(n(l,`pages`),`pages`,r,o,u,s),u.sort((e,t)=>e.priority-t.priority),s&&u.length>0){console.log(`[middleware] Discovered ${u.length} route-scoped middleware:`);for(let e of u)console.log(` - ${e.type}: ${e.filePath} (priority: ${e.priority})`)}return u}async function c(t,n,r,i,a,o){try{if(!(await e(t).catch(()=>null))?.isDirectory())return;await l(t,t,n,r,i,a,o)}catch(e){o&&(!(e instanceof Error)||e.code!==`ENOENT`)&&console.warn(`[middleware] Error scanning ${t}: ${e instanceof Error?e.message:String(e)}`)}}async function l(e,i,a,o,s,c,d){try{let f=await t(i,{withFileTypes:!0});for(let t of f){let f=n(i,t.name);if(!(t.isDirectory()&&s.includes(t.name))){if(t.isDirectory())await l(e,f,a,o,s,c,d);else if(t.name===o){let t=u(f,r(e,i),a);c.push(t)}}}}catch(e){d&&(!(e instanceof Error)||e.code!==`ENOENT`)&&console.warn(`[middleware] Error reading ${i}: ${e instanceof Error?e.message:String(e)}`)}}function u(e,t,n){let r=t?`/${t}{/*}?`:`/*`,i=t?t.split(`/`).filter(Boolean).length:0,a=o[n]+i;return{pattern:new URLPattern({pathname:r}),filePath:e,priority:a,type:n}}export function getMatchingMiddleware(e,t){let n=t.pathname.startsWith(`/api`);return e.filter(e=>!(!e.pattern.test(t)||e.type===`pages`&&n))}export function clearDiscoveryCache(){}
@@ -14,8 +14,8 @@
14
14
  *
15
15
  * Requirements: 1.2, 1.3, 1.4, 2.1, 2.2
16
16
  */
17
- import type { H3Event } from 'h3';
18
- import type { MiddlewareRoute, MiddlewareExecutorOptions } from './types.ts';
17
+ import type { H3Event } from "h3";
18
+ import type { MiddlewareExecutorOptions, MiddlewareRoute } from "./types.ts";
19
19
  /**
20
20
  * Executes route-scoped middleware chain for a request
21
21
  *
@@ -38,6 +38,6 @@
38
38
  *
39
39
  * Requirements: 4.3
40
40
  */
41
- export type { MiddlewareHandler, MiddlewareFileExport, MiddlewareRoute, MiddlewareDiscoveryOptions, MiddlewareExecutorOptions, } from './types.ts';
42
- export { discoverScopedMiddleware, getMatchingMiddleware, clearDiscoveryCache } from './discovery.ts';
43
- export { executeScopedMiddleware, clearMiddlewareCache, invalidateMiddleware, getMiddlewareCacheSize, hasContextValue, getContextValue, setContextValue, } from './executor.ts';
41
+ export type { MiddlewareDiscoveryOptions, MiddlewareExecutorOptions, MiddlewareFileExport, MiddlewareHandler, MiddlewareRoute, } from "./types.ts";
42
+ export { clearDiscoveryCache, discoverScopedMiddleware, getMatchingMiddleware, } from "./discovery.ts";
43
+ export { clearMiddlewareCache, executeScopedMiddleware, getContextValue, getMiddlewareCacheSize, hasContextValue, invalidateMiddleware, setContextValue, } from "./executor.ts";
@@ -1 +1 @@
1
- export{discoverScopedMiddleware,getMatchingMiddleware,clearDiscoveryCache}from"./discovery.js";export{executeScopedMiddleware,clearMiddlewareCache,invalidateMiddleware,getMiddlewareCacheSize,hasContextValue,getContextValue,setContextValue}from"./executor.js";
1
+ export{clearDiscoveryCache,discoverScopedMiddleware,getMatchingMiddleware}from"./discovery.js";export{clearMiddlewareCache,executeScopedMiddleware,getContextValue,getMiddlewareCacheSize,hasContextValue,invalidateMiddleware,setContextValue}from"./executor.js";
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Requirements: 1.1
13
13
  */
14
- import type { H3Event } from 'h3';
14
+ import type { H3Event } from "h3";
15
15
  /**
16
16
  * Nitro-aligned middleware handler signature
17
17
  *
@@ -63,7 +63,7 @@ export interface MiddlewareRoute {
63
63
  /** Execution priority (lower numbers execute first) */
64
64
  priority: number;
65
65
  /** Middleware type - determines which routes it applies to */
66
- type: 'global' | 'pages';
66
+ type: "global" | "pages";
67
67
  }
68
68
  /**
69
69
  * Middleware discovery options
@@ -11,9 +11,9 @@
11
11
  *
12
12
  * Requirements: 10.1, 10.2, 10.3, 10.4, 10.5
13
13
  */
14
- import type { PageModule, NitroRenderContext, AvalonRuntimeConfig } from "./types.ts";
15
14
  import type { H3Event } from "h3";
16
- import { HttpError } from "./types.ts";
15
+ import type { AvalonRuntimeConfig, NitroRenderContext, PageModule } from "./types.ts";
16
+ import { type HttpError } from "./types.ts";
17
17
  /**
18
18
  * Error page props passed to custom error page components
19
19
  */
@@ -1,4 +1,4 @@
1
- import{isHttpError as e,createNotFoundError as t,createInternalError as n}from"./types.js";import{createRenderContext as r,getRequestURL as i}from"./renderer.js";let a={initialized:!1};export function clearErrorPageCache(){a={initialized:!1}}export async function discoverErrorPages(e){if(a.initialized&&!e.isDev)return a;let{loadPageModule:t,pagesDir:n=`src/pages`}=e;if(!t)return a.initialized=!0,a;try{a.notFound=await t(`${n}/404.tsx`)}catch{try{a.notFound=await t(`${n}/404.jsx`)}catch{a.notFound=null}}try{a.serverError=await t(`${n}/500.tsx`)}catch{try{a.serverError=await t(`${n}/500.jsx`)}catch{a.serverError=null}}try{a.genericError=await t(`${n}/_error.tsx`)}catch{try{a.genericError=await t(`${n}/_error.jsx`)}catch{a.genericError=null}}return a.initialized=!0,a}export function getErrorPageModule(e,t){return e===404&&t.notFound?t.notFound:e===500&&t.serverError?t.serverError:t.genericError?t.genericError:null}export function createErrorPageProps(t,n,r){let i={statusCode:e(t)?t.statusCode:500,message:t.message,url:n};return r&&(i.error=t,i.stack=t.stack),i}export async function renderErrorPage(e,t,n,r){if(typeof e.default!=`function`)return generateDefaultErrorPage(t.statusCode,t.message,r,t.stack);try{let n=e.metadata||{};return`<!DOCTYPE html>
1
+ import{createRenderContext as e,getRequestURL as t}from"./renderer.js";import{createInternalError as n,createNotFoundError as r,isHttpError as i}from"./types.js";let a={initialized:!1};export function clearErrorPageCache(){a={initialized:!1}}export async function discoverErrorPages(e){if(a.initialized&&!e.isDev)return a;let{loadPageModule:t,pagesDir:n=`src/pages`}=e;if(!t)return a.initialized=!0,a;try{a.notFound=await t(`${n}/404.tsx`)}catch{try{a.notFound=await t(`${n}/404.jsx`)}catch{a.notFound=null}}try{a.serverError=await t(`${n}/500.tsx`)}catch{try{a.serverError=await t(`${n}/500.jsx`)}catch{a.serverError=null}}try{a.genericError=await t(`${n}/_error.tsx`)}catch{try{a.genericError=await t(`${n}/_error.jsx`)}catch{a.genericError=null}}return a.initialized=!0,a}export function getErrorPageModule(e,t){return e===404&&t.notFound?t.notFound:e===500&&t.serverError?t.serverError:t.genericError?t.genericError:null}export function createErrorPageProps(e,t,n){let r={statusCode:i(e)?e.statusCode:500,message:e.message,url:t};return n&&(r.error=e,r.stack=e.stack),r}export async function renderErrorPage(e,t,n,r){if(typeof e.default!=`function`)return generateDefaultErrorPage(t.statusCode,t.message,r,t.stack);try{let n=e.metadata||{};return`<!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8">
@@ -195,4 +195,4 @@ import{isHttpError as e,createNotFoundError as t,createInternalError as n}from".
195
195
  <p><a href="/">Return to home</a></p>
196
196
  </div>
197
197
  </body>
198
- </html>`}function l(e){return{400:`Bad Request`,401:`Unauthorized`,403:`Forbidden`,404:`Page Not Found`,405:`Method Not Allowed`,408:`Request Timeout`,410:`Gone`,429:`Too Many Requests`,500:`Internal Server Error`,502:`Bad Gateway`,503:`Service Unavailable`,504:`Gateway Timeout`}[e]||`Error`}function u(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`).replaceAll(`"`,`&quot;`).replaceAll(`'`,`&#039;`)}export async function handleRenderError(t,n,a){let{isDev:o=!1}=a,s=e(t)?t.statusCode:500,c=i(n);console.error(`[Render Error] ${s} - ${t.message}`,{url:c.pathname,stack:o?t.stack:void 0});let l=getErrorPageModule(s,await discoverErrorPages(a)),u;return u=l?await renderErrorPage(l,createErrorPageProps(t,c.pathname,o),r(n,{}),o):generateDefaultErrorPage(s,t.message,o,o?t.stack:void 0),new Response(u,{status:s,headers:{"Content-Type":`text/html; charset=utf-8`}})}export function handleApiError(t,n){let{isDev:r=!1}=n,i=e(t)?t.statusCode:500;console.error(`[API Error] ${i} - ${t.message}`,{stack:r?t.stack:void 0});let a=r?{error:t.message,statusCode:i,stack:t.stack}:{error:i>=500?`Internal Server Error`:t.message,statusCode:i};return new Response(JSON.stringify(a),{status:i,headers:{"Content-Type":`application/json`}})}export async function handleNotFound(e,n,r){return handleRenderError(t(`Page not found: ${e}`),n,r)}export async function handleInternalError(e,t,r){let i=n(e.message);return i.stack=e.stack,handleRenderError(i,t,r)}
198
+ </html>`}function l(e){return{400:`Bad Request`,401:`Unauthorized`,403:`Forbidden`,404:`Page Not Found`,405:`Method Not Allowed`,408:`Request Timeout`,410:`Gone`,429:`Too Many Requests`,500:`Internal Server Error`,502:`Bad Gateway`,503:`Service Unavailable`,504:`Gateway Timeout`}[e]||`Error`}function u(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`).replaceAll(`"`,`&quot;`).replaceAll(`'`,`&#039;`)}export async function handleRenderError(n,r,a){let{isDev:o=!1}=a,s=i(n)?n.statusCode:500,c=t(r);console.error(`[Render Error] ${s} - ${n.message}`,{url:c.pathname,stack:o?n.stack:void 0});let l=getErrorPageModule(s,await discoverErrorPages(a)),u;return u=l?await renderErrorPage(l,createErrorPageProps(n,c.pathname,o),e(r,{}),o):generateDefaultErrorPage(s,n.message,o,o?n.stack:void 0),new Response(u,{status:s,headers:{"Content-Type":`text/html; charset=utf-8`}})}export function handleApiError(e,t){let{isDev:n=!1}=t,r=i(e)?e.statusCode:500;console.error(`[API Error] ${r} - ${e.message}`,{stack:n?e.stack:void 0});let a=n?{error:e.message,statusCode:r,stack:e.stack}:{error:r>=500?`Internal Server Error`:e.message,statusCode:r};return new Response(JSON.stringify(a),{status:r,headers:{"Content-Type":`application/json`}})}export async function handleNotFound(e,t,n){return handleRenderError(r(`Page not found: ${e}`),t,n)}export async function handleInternalError(e,t,r){let i=n(e.message);return i.stack=e.stack,handleRenderError(i,t,r)}
@@ -5,11 +5,11 @@
5
5
  * enabling universal deployment through Nitro presets while maintaining
6
6
  * Avalon's multi-framework SSR and islands architecture.
7
7
  */
8
- export { createNitroConfig, isValidPreset, mergeRouteRules, createDefaultStaticAssetRouteRules, DEFAULT_NITRO_CONFIG, DEFAULT_STATIC_ASSETS_CONFIG, type AvalonNitroConfig, type CacheOptions, type RouteRule, type NitroConfigOutput, type AvalonRuntimeConfig, type StaticAssetsConfig, } from "./config.ts";
9
- export { type H3Event, type NitroRenderContext, type LayoutContext, type DiscoveredRoute, type NitroRouteConfig, type SSRRenderOptions, type SSRRenderResult, type AvalonEventContext, type IslandEntry, type IslandManifest, type PageModule, type PageMetadata, type ErrorResponse, HttpError, isHttpError, createNotFoundError, createMethodNotAllowedError, createInternalError, type DevServerOptions, type BuildOptions, } from "./types.ts";
10
- export { createNitroRenderer, createNitroCatchAllRenderer, createRenderContext, renderPage, renderPageStream, createStreamingResponse, injectHydrationScript, validateHydrationMarkers, extractIslandMarkers, ensureHydrationMarkers, processHydrationRequirements, createErrorResponse, getRequestURL as getRendererRequestURL, toRequest as rendererToRequest, setResponseHeader, type RenderHandlerOptions, type ResolvedPageRoute, type StreamingSSROptions, type IslandMarker, type NitroCatchAllOptions, } from "./renderer.ts";
11
- export { createMiddlewareContext, storeMiddlewareContext, getMiddlewareContext, getOrCreateMiddlewareContext, setMiddlewareState, getMiddlewareState, setMiddlewareLocal, getMiddlewareLocal, hasAvalonContext, ensureAvalonContext, getRequestURL as getMiddlewareRequestURL, getRequestHeaders as getMiddlewareRequestHeaders, toRequest as middlewareToRequest, getRouterParams as getMiddlewareRouterParams, type MiddlewareContextOptions, } from "./middleware-adapter.ts";
12
- export { discoverPageRoutes, filePathToPattern, isPrivateFile, calculateRouteSpecificity, sortRoutesBySpecificity, validateRoutePattern, extractParamsFromPattern, matchRoutePattern, PAGE_EXTENSIONS, type PageDiscoveryOptions, type FilePathPatternResult, } from "./route-discovery.ts";
13
- export { createClientBuildConfig, createServerBuildConfig, createCombinedBuildConfig, createNitroBuildPlugin, getPresetOutputConfig, presetSupportsStreaming, validateBuildConfig, createSourceMapConfig, createSourceMapPlugin, getViteSourceMapOption, DEFAULT_BUILD_CONFIG, DEFAULT_SOURCEMAP_CONFIG, PRESET_OUTPUT_CONFIGS, type BuildMode, type PresetOutputConfig, type AvalonBuildConfig, type SourceMapConfig, } from "./build-config.ts";
14
- export { createIslandManifestPlugin, createIslandEntry, detectIslandFramework, generateContentHash, extractIslandDependencies, generatePreloadHints, generatePreloadTags, loadIslandManifest, getIslandAssetPath, getPageCssAssets, DEFAULT_MANIFEST_OPTIONS, type BuildIslandEntry, type BuildIslandManifest, type PreloadHint, type IslandManifestOptions, type AssetMetadata, } from "./island-manifest.ts";
15
- export { discoverErrorPages, getErrorPageModule, renderErrorPage, generateDefaultErrorPage, createErrorPageProps, clearErrorPageCache, handleRenderError, handleApiError, handleNotFound, handleInternalError, type ErrorPageProps, type ErrorHandlerOptions, } from "./error-handler.ts";
8
+ export { type AvalonBuildConfig, type BuildMode, createClientBuildConfig, createCombinedBuildConfig, createNitroBuildPlugin, createServerBuildConfig, createSourceMapConfig, createSourceMapPlugin, DEFAULT_BUILD_CONFIG, DEFAULT_SOURCEMAP_CONFIG, getPresetOutputConfig, getViteSourceMapOption, PRESET_OUTPUT_CONFIGS, type PresetOutputConfig, presetSupportsStreaming, type SourceMapConfig, validateBuildConfig, } from "./build-config.ts";
9
+ export { type AvalonNitroConfig, type AvalonRuntimeConfig, type CacheOptions, createDefaultStaticAssetRouteRules, createNitroConfig, DEFAULT_NITRO_CONFIG, DEFAULT_STATIC_ASSETS_CONFIG, isValidPreset, mergeRouteRules, type NitroConfigOutput, type RouteRule, type StaticAssetsConfig, } from "./config.ts";
10
+ export { clearErrorPageCache, createErrorPageProps, discoverErrorPages, type ErrorHandlerOptions, type ErrorPageProps, generateDefaultErrorPage, getErrorPageModule, handleApiError, handleInternalError, handleNotFound, handleRenderError, renderErrorPage, } from "./error-handler.ts";
11
+ export { type AssetMetadata, type BuildIslandEntry, type BuildIslandManifest, createIslandEntry, createIslandManifestPlugin, DEFAULT_MANIFEST_OPTIONS, detectIslandFramework, extractIslandDependencies, generateContentHash, generatePreloadHints, generatePreloadTags, getIslandAssetPath, getPageCssAssets, type IslandManifestOptions, loadIslandManifest, type PreloadHint, } from "./island-manifest.ts";
12
+ export { createMiddlewareContext, ensureAvalonContext, getMiddlewareContext, getMiddlewareLocal, getMiddlewareState, getOrCreateMiddlewareContext, getRequestHeaders as getMiddlewareRequestHeaders, getRequestURL as getMiddlewareRequestURL, getRouterParams as getMiddlewareRouterParams, hasAvalonContext, type MiddlewareContextOptions, setMiddlewareLocal, setMiddlewareState, storeMiddlewareContext, toRequest as middlewareToRequest, } from "./middleware-adapter.ts";
13
+ export { createErrorResponse, createNitroCatchAllRenderer, createNitroRenderer, createRenderContext, createStreamingResponse, ensureHydrationMarkers, extractIslandMarkers, getRequestURL as getRendererRequestURL, type IslandMarker, injectHydrationScript, type NitroCatchAllOptions, processHydrationRequirements, type RenderHandlerOptions, type ResolvedPageRoute, renderPage, renderPageStream, type StreamingSSROptions, setResponseHeader, toRequest as rendererToRequest, validateHydrationMarkers, } from "./renderer.ts";
14
+ export { calculateRouteSpecificity, discoverPageRoutes, extractParamsFromPattern, type FilePathPatternResult, filePathToPattern, isPrivateFile, matchRoutePattern, PAGE_EXTENSIONS, type PageDiscoveryOptions, sortRoutesBySpecificity, validateRoutePattern, } from "./route-discovery.ts";
15
+ export { type AvalonEventContext, type BuildOptions, createInternalError, createMethodNotAllowedError, createNotFoundError, type DevServerOptions, type DiscoveredRoute, type ErrorResponse, type H3Event, HttpError, type IslandEntry, type IslandManifest, isHttpError, type LayoutContext, type NitroRenderContext, type NitroRouteConfig, type PageMetadata, type PageModule, type SSRRenderOptions, type SSRRenderResult, } from "./types.ts";
@@ -1 +1 @@
1
- export{createNitroConfig,isValidPreset,mergeRouteRules,createDefaultStaticAssetRouteRules,DEFAULT_NITRO_CONFIG,DEFAULT_STATIC_ASSETS_CONFIG}from"./config.js";export{HttpError,isHttpError,createNotFoundError,createMethodNotAllowedError,createInternalError}from"./types.js";export{createNitroRenderer,createNitroCatchAllRenderer,createRenderContext,renderPage,renderPageStream,createStreamingResponse,injectHydrationScript,validateHydrationMarkers,extractIslandMarkers,ensureHydrationMarkers,processHydrationRequirements,createErrorResponse,getRequestURL as getRendererRequestURL,toRequest as rendererToRequest,setResponseHeader}from"./renderer.js";export{createMiddlewareContext,storeMiddlewareContext,getMiddlewareContext,getOrCreateMiddlewareContext,setMiddlewareState,getMiddlewareState,setMiddlewareLocal,getMiddlewareLocal,hasAvalonContext,ensureAvalonContext,getRequestURL as getMiddlewareRequestURL,getRequestHeaders as getMiddlewareRequestHeaders,toRequest as middlewareToRequest,getRouterParams as getMiddlewareRouterParams}from"./middleware-adapter.js";export{discoverPageRoutes,filePathToPattern,isPrivateFile,calculateRouteSpecificity,sortRoutesBySpecificity,validateRoutePattern,extractParamsFromPattern,matchRoutePattern,PAGE_EXTENSIONS}from"./route-discovery.js";export{createClientBuildConfig,createServerBuildConfig,createCombinedBuildConfig,createNitroBuildPlugin,getPresetOutputConfig,presetSupportsStreaming,validateBuildConfig,createSourceMapConfig,createSourceMapPlugin,getViteSourceMapOption,DEFAULT_BUILD_CONFIG,DEFAULT_SOURCEMAP_CONFIG,PRESET_OUTPUT_CONFIGS}from"./build-config.js";export{createIslandManifestPlugin,createIslandEntry,detectIslandFramework,generateContentHash,extractIslandDependencies,generatePreloadHints,generatePreloadTags,loadIslandManifest,getIslandAssetPath,getPageCssAssets,DEFAULT_MANIFEST_OPTIONS}from"./island-manifest.js";export{discoverErrorPages,getErrorPageModule,renderErrorPage,generateDefaultErrorPage,createErrorPageProps,clearErrorPageCache,handleRenderError,handleApiError,handleNotFound,handleInternalError}from"./error-handler.js";
1
+ export{createClientBuildConfig,createCombinedBuildConfig,createNitroBuildPlugin,createServerBuildConfig,createSourceMapConfig,createSourceMapPlugin,DEFAULT_BUILD_CONFIG,DEFAULT_SOURCEMAP_CONFIG,getPresetOutputConfig,getViteSourceMapOption,PRESET_OUTPUT_CONFIGS,presetSupportsStreaming,validateBuildConfig}from"./build-config.js";export{createDefaultStaticAssetRouteRules,createNitroConfig,DEFAULT_NITRO_CONFIG,DEFAULT_STATIC_ASSETS_CONFIG,isValidPreset,mergeRouteRules}from"./config.js";export{clearErrorPageCache,createErrorPageProps,discoverErrorPages,generateDefaultErrorPage,getErrorPageModule,handleApiError,handleInternalError,handleNotFound,handleRenderError,renderErrorPage}from"./error-handler.js";export{createIslandEntry,createIslandManifestPlugin,DEFAULT_MANIFEST_OPTIONS,detectIslandFramework,extractIslandDependencies,generateContentHash,generatePreloadHints,generatePreloadTags,getIslandAssetPath,getPageCssAssets,loadIslandManifest}from"./island-manifest.js";export{createMiddlewareContext,ensureAvalonContext,getMiddlewareContext,getMiddlewareLocal,getMiddlewareState,getOrCreateMiddlewareContext,getRequestHeaders as getMiddlewareRequestHeaders,getRequestURL as getMiddlewareRequestURL,getRouterParams as getMiddlewareRouterParams,hasAvalonContext,setMiddlewareLocal,setMiddlewareState,storeMiddlewareContext,toRequest as middlewareToRequest}from"./middleware-adapter.js";export{createErrorResponse,createNitroCatchAllRenderer,createNitroRenderer,createRenderContext,createStreamingResponse,ensureHydrationMarkers,extractIslandMarkers,getRequestURL as getRendererRequestURL,injectHydrationScript,processHydrationRequirements,renderPage,renderPageStream,setResponseHeader,toRequest as rendererToRequest,validateHydrationMarkers}from"./renderer.js";export{calculateRouteSpecificity,discoverPageRoutes,extractParamsFromPattern,filePathToPattern,isPrivateFile,matchRoutePattern,PAGE_EXTENSIONS,sortRoutesBySpecificity,validateRoutePattern}from"./route-discovery.js";export{createInternalError,createMethodNotAllowedError,createNotFoundError,HttpError,isHttpError}from"./types.js";
@@ -33,7 +33,7 @@
33
33
  */
34
34
  import type { Plugin } from "vite";
35
35
  import type { ResolvedAvalonConfig } from "../vite-plugin/types.ts";
36
- import type { IslandManifest, IslandEntry } from "./types.ts";
36
+ import type { IslandEntry, IslandManifest } from "./types.ts";
37
37
  /**
38
38
  * Extended island entry with build-time metadata
39
39
  */
@@ -1,2 +1,2 @@
1
- import{readFile as e}from"node:fs/promises";export const DEFAULT_MANIFEST_OPTIONS={outputPath:`dist/island-manifest.json`,includeSourceMaps:!1,generatePreloadHints:!0,verbose:!1};const n={react:[/from\s+['"]react['"]/,/from\s+['"]react-dom['"]/,/@jsxImportSource\s+react/],preact:[/from\s+['"]preact['"]/,/from\s+['"]preact\/hooks['"]/,/@jsxImportSource\s+preact/],vue:[/from\s+['"]vue['"]/,/\.vue$/],svelte:[/from\s+['"]svelte['"]/,/\.svelte$/],solid:[/from\s+['"]solid-js['"]/,/\.solid\.(tsx|jsx)$/],lit:[/from\s+['"]lit['"]/,/from\s+['"]@lit['"]/,/\.lit\.(ts|js)$/]};export function detectIslandFramework(e,t){if(e.endsWith(`.vue`))return`vue`;if(e.endsWith(`.svelte`))return`svelte`;if(e.includes(`.solid.`))return`solid`;if(e.includes(`.lit.`))return`lit`;for(let[r,i]of Object.entries(n))for(let n of i)if(n.test(t)||n.test(e))return r;return e.endsWith(`.tsx`)||e.endsWith(`.jsx`)?`preact`:`unknown`}export async function generateContentHash(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,8)}export function extractIslandDependencies(e){let t=[],n=/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g,r=/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,i;for(;(i=n.exec(e))!==null;){let e=i[1];!e.startsWith(`.`)&&!e.startsWith(`/`)&&t.push(e)}for(;(i=r.exec(e))!==null;){let e=i[1];!e.startsWith(`.`)&&!e.startsWith(`/`)&&t.push(e)}return[...new Set(t)]}export async function createIslandEntry(e,t,n,o){let s=detectIslandFramework(t,n),c=await generateContentHash(n);return{src:o,framework:s,css:[],preload:extractIslandDependencies(n).filter(e=>!e.includes(`/`)),sourcePath:t,chunkName:e,contentHash:c,preloadDeps:[],usesStreaming:!1}}export function generatePreloadHints(e){let t=[];e.clientEntry&&t.push({href:e.clientEntry,as:`script`,type:`text/javascript`});for(let n of e.css??[])t.push({href:n,as:`style`,type:`text/css`});for(let n of Object.values(e.frameworkBundles??{}))t.push({href:n,as:`script`,type:`text/javascript`});return t}export function createIslandManifestPlugin(e,n={}){let r={...DEFAULT_MANIFEST_OPTIONS,...n},a=new Map,o=new Set,c=``;return{name:`avalon:island-manifest`,enforce:`post`,generateBundle(e,t){for(let[e,n]of Object.entries(t))if(e.endsWith(`.css`)&&o.add(`/${e}`),n.type===`chunk`&&(n.name===`client`||n.name===`main`)&&(c=`/${e}`),n.type===`chunk`&&(n.facadeModuleId?.includes(`/islands/`)||n.name?.startsWith(`islands/`))){let t=n.name?.replace(`islands/`,``)??e,r=a.get(t);r?r.src=`/${e}`:a.set(t,{src:`/${e}`,framework:u(n),css:[],preload:[],sourcePath:n.facadeModuleId??``,chunkName:t,contentHash:/\.([a-f0-9]+)\.js$/.exec(e)?.[1]??``,preloadDeps:n.imports??[],usesStreaming:!1})}},async writeBundle(e,t){let n={},u=new Date().toISOString();for(let[e,r]of Object.entries(t)){let t=await l(e,r,u);t&&(n[`/${e}`]=t)}let d={islands:Object.fromEntries(a),clientEntry:c,css:Array.from(o),buildTime:Date.now(),buildHash:await generateContentHash(JSON.stringify(Object.fromEntries(a))),avalonVersion:`1.0.0`,cssAssets:Array.from(o),preloadHints:r.generatePreloadHints?generatePreloadHints({clientEntry:c,css:Array.from(o),islands:Object.fromEntries(a)}):[],frameworkBundles:{},assetMetadata:n},f=JSON.stringify(d,null,2);r.verbose&&(console.log(`📋 Island manifest generated:`),console.log(` Islands: ${a.size}`),console.log(` CSS assets: ${o.size}`),console.log(` Client entry: ${c}`),console.log(` Asset metadata entries: ${Object.keys(n).length}`)),this.emitFile({type:`asset`,fileName:`island-manifest.json`,source:f})}}}async function l(e,t,n){let r;if(t.type===`asset`&&t.source?r=t.source:t.type===`chunk`&&t.code&&(r=t.code),!r)return null;let a=typeof r==`string`?new TextEncoder().encode(r).length:r.length,o=await generateContentHash(typeof r==`string`?r:new TextDecoder().decode(r)),s=e.substring(e.lastIndexOf(`.`));return{type:{".js":`application/javascript`,".mjs":`application/javascript`,".css":`text/css`,".json":`application/json`,".html":`text/html`,".map":`application/json`}[s]??`application/octet-stream`,etag:`"${o}"`,mtime:n,size:a}}function u(e){return detectIslandFramework(e.facadeModuleId??``,e.code??``)}export async function loadIslandManifest(t=`dist/island-manifest.json`){try{let n=await e(t,`utf-8`);return JSON.parse(n)}catch{return null}}export function getIslandAssetPath(e,t){return t?t.islands[e]?.src??null:null}export function getPageCssAssets(e,t){if(!t)return[];let n=new Set;for(let e of t.css)n.add(e);for(let r of e){let e=t.islands[r];if(e?.css)for(let t of e.css)n.add(t)}return Array.from(n)}export function generatePreloadTags(e){let t=[];for(let n of e.preloadHints){let e=[`rel="preload"`,`href="${n.href}"`,`as="${n.as}"`];n.type&&e.push(`type="${n.type}"`),n.crossorigin&&e.push(`crossorigin="${n.crossorigin}"`),t.push(`<link ${e.join(` `)}>`)}return t.join(`
1
+ import{readFile as e}from"node:fs/promises";export const DEFAULT_MANIFEST_OPTIONS={outputPath:`dist/island-manifest.json`,includeSourceMaps:!1,generatePreloadHints:!0,verbose:!1};const n={react:[/from\s+['"]react['"]/,/from\s+['"]react-dom['"]/,/@jsxImportSource\s+react/],preact:[/from\s+['"]preact['"]/,/from\s+['"]preact\/hooks['"]/,/@jsxImportSource\s+preact/],vue:[/from\s+['"]vue['"]/,/\.vue$/],svelte:[/from\s+['"]svelte['"]/,/\.svelte$/],solid:[/from\s+['"]solid-js['"]/,/\.solid\.(tsx|jsx)$/],lit:[/from\s+['"]lit['"]/,/from\s+['"]@lit['"]/,/\.lit\.(ts|js)$/]};export function detectIslandFramework(e,t){if(e.endsWith(`.vue`))return`vue`;if(e.endsWith(`.svelte`))return`svelte`;if(e.includes(`.solid.`))return`solid`;if(e.includes(`.lit.`))return`lit`;for(let[r,i]of Object.entries(n))for(let n of i)if(n.test(t)||n.test(e))return r;return e.endsWith(`.tsx`)||e.endsWith(`.jsx`)?`preact`:`unknown`}export async function generateContentHash(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,8)}export function extractIslandDependencies(e){let t=[],n=/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g,r=/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,i;for(i=n.exec(e);i!==null;i=n.exec(e)){let e=i[1];!e.startsWith(`.`)&&!e.startsWith(`/`)&&t.push(e)}for(i=r.exec(e);i!==null;i=r.exec(e)){let e=i[1];!e.startsWith(`.`)&&!e.startsWith(`/`)&&t.push(e)}return[...new Set(t)]}export async function createIslandEntry(e,t,n,o){let s=detectIslandFramework(t,n),c=await generateContentHash(n);return{src:o,framework:s,css:[],preload:extractIslandDependencies(n).filter(e=>!e.includes(`/`)),sourcePath:t,chunkName:e,contentHash:c,preloadDeps:[],usesStreaming:!1}}export function generatePreloadHints(e){let t=[];e.clientEntry&&t.push({href:e.clientEntry,as:`script`,type:`text/javascript`});for(let n of e.css??[])t.push({href:n,as:`style`,type:`text/css`});for(let n of Object.values(e.frameworkBundles??{}))t.push({href:n,as:`script`,type:`text/javascript`});return t}export function createIslandManifestPlugin(e,n={}){let r={...DEFAULT_MANIFEST_OPTIONS,...n},a=new Map,o=new Set,c=``;return{name:`avalon:island-manifest`,enforce:`post`,generateBundle(e,t){for(let[e,n]of Object.entries(t))if(e.endsWith(`.css`)&&o.add(`/${e}`),n.type===`chunk`&&(n.name===`client`||n.name===`main`)&&(c=`/${e}`),n.type===`chunk`&&(n.facadeModuleId?.includes(`/islands/`)||n.name?.startsWith(`islands/`))){let t=n.name?.replace(`islands/`,``)??e,r=a.get(t);r?r.src=`/${e}`:a.set(t,{src:`/${e}`,framework:u(n),css:[],preload:[],sourcePath:n.facadeModuleId??``,chunkName:t,contentHash:/\.([a-f0-9]+)\.js$/.exec(e)?.[1]??``,preloadDeps:n.imports??[],usesStreaming:!1})}},async writeBundle(e,t){let n={},u=new Date().toISOString();for(let[e,r]of Object.entries(t)){let t=await l(e,r,u);t&&(n[`/${e}`]=t)}let d={islands:Object.fromEntries(a),clientEntry:c,css:Array.from(o),buildTime:Date.now(),buildHash:await generateContentHash(JSON.stringify(Object.fromEntries(a))),avalonVersion:`1.0.0`,cssAssets:Array.from(o),preloadHints:r.generatePreloadHints?generatePreloadHints({clientEntry:c,css:Array.from(o),islands:Object.fromEntries(a)}):[],frameworkBundles:{},assetMetadata:n},f=JSON.stringify(d,null,2);r.verbose&&(console.log(`📋 Island manifest generated:`),console.log(` Islands: ${a.size}`),console.log(` CSS assets: ${o.size}`),console.log(` Client entry: ${c}`),console.log(` Asset metadata entries: ${Object.keys(n).length}`)),this.emitFile({type:`asset`,fileName:`island-manifest.json`,source:f})}}}async function l(e,t,n){let r;if(t.type===`asset`&&t.source?r=t.source:t.type===`chunk`&&t.code&&(r=t.code),!r)return null;let a=typeof r==`string`?new TextEncoder().encode(r).length:r.length,o=await generateContentHash(typeof r==`string`?r:new TextDecoder().decode(r)),s=e.substring(e.lastIndexOf(`.`));return{type:{".js":`application/javascript`,".mjs":`application/javascript`,".css":`text/css`,".json":`application/json`,".html":`text/html`,".map":`application/json`}[s]??`application/octet-stream`,etag:`"${o}"`,mtime:n,size:a}}function u(e){return detectIslandFramework(e.facadeModuleId??``,e.code??``)}export async function loadIslandManifest(t=`dist/island-manifest.json`){try{let n=await e(t,`utf-8`);return JSON.parse(n)}catch{return null}}export function getIslandAssetPath(e,t){return t?t.islands[e]?.src??null:null}export function getPageCssAssets(e,t){if(!t)return[];let n=new Set;for(let e of t.css)n.add(e);for(let r of e){let e=t.islands[r];if(e?.css)for(let t of e.css)n.add(t)}return Array.from(n)}export function generatePreloadTags(e){let t=[];for(let n of e.preloadHints){let e=[`rel="preload"`,`href="${n.href}"`,`as="${n.as}"`];n.type&&e.push(`type="${n.type}"`),n.crossorigin&&e.push(`crossorigin="${n.crossorigin}"`),t.push(`<link ${e.join(` `)}>`)}return t.join(`
2
2
  `)}
@@ -12,8 +12,8 @@
12
12
  *
13
13
  * Requirements: 6.1, 6.2, 6.3, 6.4
14
14
  */
15
- import type { AvalonEventContext } from './types.ts';
16
- import type { H3Event } from 'h3';
15
+ import type { H3Event } from "h3";
16
+ import type { AvalonEventContext } from "./types.ts";
17
17
  /**
18
18
  * Context object passed through the middleware chain
19
19
  */
@@ -7,8 +7,8 @@
7
7
  * In Nitro v3, canonical types should be imported from `nitro/types`.
8
8
  * Avalon-specific types that extend or complement Nitro's types are defined here.
9
9
  */
10
- import type { MiddlewareContext } from '../nitro/middleware-adapter.ts';
11
- import type { ApiMethod } from '../schemas/api.ts';
10
+ import type { MiddlewareContext } from "../nitro/middleware-adapter.ts";
11
+ import type { ApiMethod } from "../schemas/api.ts";
12
12
  /**
13
13
  * ServerRequest type reference from Nitro v3 (`nitro/types`).
14
14
  * Re-exported here for convenience within Avalon's Nitro integration.
@@ -91,7 +91,7 @@ export interface LayoutContext {
91
91
  */
92
92
  export interface DiscoveredRoute {
93
93
  /** Route type: page or API */
94
- type: 'page' | 'api';
94
+ type: "page" | "api";
95
95
  /** Absolute file path to the route handler */
96
96
  filePath: string;
97
97
  /** Route pattern for matching (e.g., /users/:id) */
@@ -108,7 +108,7 @@ export interface NitroRouteConfig {
108
108
  /** Route pattern (e.g., /users/:id) */
109
109
  pattern: string;
110
110
  /** Route handler type */
111
- type: 'page' | 'api' | 'middleware';
111
+ type: "page" | "api" | "middleware";
112
112
  /** File path to the handler */
113
113
  filePath: string;
114
114
  /** Extracted parameter names */
@@ -5,7 +5,7 @@
5
5
  * between different frameworks during server-side rendering. Each framework gets its
6
6
  * own isolated import context and rendering pipeline.
7
7
  */
8
- import type { JSX } from 'preact';
8
+ import type { JSX } from "preact";
9
9
  export interface FrameworkSSRContext {
10
10
  framework: string;
11
11
  imports: Map<string, unknown>;
@@ -16,7 +16,7 @@ export interface FrameworkSSRContext {
16
16
  export interface SSRIsolationConfig {
17
17
  enableStrictIsolation: boolean;
18
18
  allowedCrossFrameworkImports: string[];
19
- errorHandling: 'strict' | 'fallback' | 'ignore';
19
+ errorHandling: "strict" | "fallback" | "ignore";
20
20
  debugLogging: boolean;
21
21
  }
22
22
  export interface IsolatedRenderRequest {
@@ -1 +1 @@
1
- import{render as e}from"preact-render-to-string";import{readFile as t}from"node:fs/promises";import{EnhancedFrameworkDetector as n}from"../core/components/enhanced-framework-detector.js";import{toImportSpecifier as r}from"../middleware/executor.js";export class IsolatedSSRRenderer{contexts;detector;config;activeContext=null;constructor(e={}){this.contexts=new Map,this.detector=new n,this.config={enableStrictIsolation:!0,allowedCrossFrameworkImports:[`preact`,`preact-render-to-string`],errorHandling:`fallback`,debugLogging:!1,...e},this.initializeFrameworkContexts()}async renderWithIsolation(e){let t=[],n=[];try{let r=await this.resolveFramework(e,n);return await this.renderInContext(e,r,t,n)}catch(r){return t.push(`SSR rendering failed: ${r instanceof Error?r.message:String(r)}`),await this.tryFallbackRender(e,t,n)}}async resolveFramework(e,t){if(e.framework)return e.framework;try{let n=await this.getComponentContent(e.componentPath),r=this.detector.detectFramework(e.componentPath,n);return r.confidence===`low`&&t.push(`Low confidence framework detection for ${e.componentPath}: ${r.framework}`),this.config.debugLogging&&(console.log(`[SSR Isolation] Detected framework: ${r.framework} for ${e.componentPath}`),console.log(`[SSR Isolation] Evidence: ${r.evidence.join(`, `)}`)),r.framework}catch{return t.push(`Could not read component file for framework detection: ${e.componentPath}, defaulting to preact`),`preact`}}async renderInContext(e,t,n,r){let i=this.getFrameworkContext(t);if(!i)throw Error(`No SSR context available for framework: ${t}`);await this.switchToContext(t);try{let a=e.component(),o=a instanceof Promise?await a:a;return{html:await i.renderFunction(o,e.props||{}),framework:t,success:!0,errors:n,warnings:r}}finally{this.cleanupContext(t)}}async tryFallbackRender(t,n,r){if(this.config.errorHandling!==`fallback`)return{html:``,framework:t.framework||`unknown`,success:!1,errors:n,warnings:r};try{let i=e(await t.component());return r.push(`Fell back to Preact rendering due to framework-specific error`),{html:i,framework:`preact`,success:!0,errors:n,warnings:r}}catch(e){return n.push(`Fallback rendering also failed: ${e instanceof Error?e.message:String(e)}`),{html:``,framework:t.framework||`unknown`,success:!1,errors:n,warnings:r}}}initializeFrameworkContexts(){this.contexts.set(`preact`,{framework:`preact`,imports:new Map,renderFunction:t=>Promise.resolve(e(t)),cleanup:()=>{this.clearFrameworkGlobals(`preact`)},isActive:!1}),this.contexts.set(`solid`,{framework:`solid`,imports:new Map,renderFunction:async e=>{try{let t=await this.importFrameworkModule(`solid-js/web`,`solid`);if(t&&typeof t.renderToString==`function`)return t.renderToString(()=>e);throw Error(`Solid renderToString not available`)}catch(e){throw Error(`Solid SSR failed: ${e instanceof Error?e.message:String(e)}`)}},cleanup:()=>{this.clearFrameworkGlobals(`solid`)},isActive:!1}),this.contexts.set(`vue`,{framework:`vue`,imports:new Map,renderFunction:async e=>{try{let t=await this.importFrameworkModule(`vue/server-renderer`,`vue`);if(t&&typeof t.renderToString==`function`)return await t.renderToString(e);throw Error(`Vue renderToString not available`)}catch(e){throw Error(`Vue SSR failed: ${e instanceof Error?e.message:String(e)}`)}},cleanup:()=>{this.clearFrameworkGlobals(`vue`)},isActive:!1}),this.contexts.set(`svelte`,{framework:`svelte`,imports:new Map,renderFunction:e=>{try{if(e&&typeof e==`object`&&`render`in e){let t=e.render();return Promise.resolve(t.html||``)}throw Error(`Svelte component does not have render method`)}catch(e){throw Error(`Svelte SSR failed: ${e instanceof Error?e.message:String(e)}`)}},cleanup:()=>{this.clearFrameworkGlobals(`svelte`)},isActive:!1}),this.contexts.set(`unknown`,{framework:`unknown`,imports:new Map,renderFunction:t=>Promise.resolve(e(t)),cleanup:()=>{},isActive:!1})}getFrameworkContext(e){return this.contexts.get(e)||this.contexts.get(`unknown`)||null}async switchToContext(e){this.activeContext&&this.activeContext!==e&&this.cleanupContext(this.activeContext);let t=this.contexts.get(e);if(!t)throw Error(`Framework context not found: ${e}`);t.isActive=!0,this.activeContext=e,await this.setupFrameworkEnvironment(e)}cleanupContext(e){let t=this.contexts.get(e);t&&(t.cleanup(),t.isActive=!1,t.imports.clear(),this.activeContext===e&&(this.activeContext=null))}async setupFrameworkEnvironment(e){switch(e){case`solid`:await this.ensureSolidEnvironment();break;case`vue`:await this.ensureVueEnvironment();break;case`svelte`:this.ensureSvelteEnvironment();break;default:break}}async importFrameworkModule(e,t){let n=this.contexts.get(t);if(!n)throw Error(`No context for framework: ${t}`);if(n.imports.has(e))return n.imports.get(e);if(this.config.enableStrictIsolation&&!this.isImportAllowed(e,t))throw Error(`Import not allowed in ${t} context: ${e}`);try{let i=await import(r(e));return n.imports.set(e,i),this.config.debugLogging&&console.log(`[SSR Isolation] Imported ${e} in ${t} context`),i}catch(n){throw Error(`Failed to import ${e} in ${t} context: ${n instanceof Error?n.message:String(n)}`)}}isImportAllowed(e,t){let n=this.detector.getFrameworkConfigs().get(t);return n&&[...n.ssrModules,...n.hydrationModules].some(t=>e.startsWith(t))?!0:this.config.allowedCrossFrameworkImports.some(t=>e.startsWith(t))}clearFrameworkGlobals(e){let t=globalThis;switch(e){case`solid`:typeof globalThis<`u`&&(delete t._$HY,delete t.Solid);break;case`vue`:typeof globalThis<`u`&&(delete t.__VUE__,delete t.Vue);break;case`svelte`:typeof globalThis<`u`&&delete t.__SVELTE__;break}}async ensureSolidEnvironment(){try{await this.importFrameworkModule(`solid-js/web`,`solid`)}catch(e){this.config.debugLogging&&console.warn(`[SSR Isolation] Failed to set up Solid environment:`,e)}}async ensureVueEnvironment(){try{await this.importFrameworkModule(`vue/server-renderer`,`vue`)}catch(e){this.config.debugLogging&&console.warn(`[SSR Isolation] Failed to set up Vue environment:`,e)}}ensureSvelteEnvironment(){try{this.config.debugLogging&&console.log(`[SSR Isolation] Svelte environment ready`)}catch(e){this.config.debugLogging&&console.warn(`[SSR Isolation] Failed to set up Svelte environment:`,e)}}async getComponentContent(e){try{let n=e;e.startsWith(`/`)&&(n=e.substring(1));let r=[n,`src/islands/${n.split(`/`).pop()}`,`islands/${n.split(`/`).pop()}`,`examples/${n.split(`/`).pop()}`];for(let e of r)try{return await t(e,`utf-8`)}catch{continue}throw Error(`Component file not found: ${e}`)}catch(e){throw Error(`Failed to read component content: ${e instanceof Error?e.message:String(e)}`)}}getActiveContext(){return this.activeContext}getContexts(){return new Map(this.contexts)}updateConfig(e){this.config={...this.config,...e}}resetAllContexts(){for(let[e]of this.contexts)this.cleanupContext(e);this.activeContext=null}async renderWithFallback(e,t){let n=[],r=[];try{let i={componentPath:`fallback-component`,component:e,framework:t},a=await this.renderWithIsolation(i);if(a.success)return a;n.push(...a.errors),r.push(...a.warnings)}catch(e){n.push(`Preferred framework (${t}) failed: ${e instanceof Error?e.message:String(e)}`)}for(let i of[`preact`,`unknown`])if(i!==t)try{let a={componentPath:`fallback-component`,component:e,framework:i},o=await this.renderWithIsolation(a);if(o.success)return r.push(`Fell back to ${i} rendering from ${t}`),{...o,warnings:[...r,...o.warnings]};n.push(...o.errors)}catch(e){n.push(`Fallback framework (${i}) failed: ${e instanceof Error?e.message:String(e)}`)}return{html:``,framework:t,success:!1,errors:n,warnings:r}}async validateFrameworkContext(e){if(!this.contexts.get(e))return!1;try{return await this.setupFrameworkEnvironment(e),!0}catch(t){return this.config.debugLogging&&console.warn(`[SSR Isolation] Framework context validation failed for ${e}:`,t),!1}}getErrorRecoveryStrategies(e){return{solid:[`Ensure solid-js and solid-js/web are installed`,`Check that Solid components use proper JSX import source: /** @jsxImportSource solid-js */`,`Verify Solid components export default function`],vue:[`Ensure vue and vue/server-renderer are installed`,`Check that Vue components have proper <template>, <script>, and <style> sections`,`Verify Vue components are properly compiled for SSR`],svelte:[`Ensure svelte is installed and components are compiled`,`Check that Svelte components export default class or function`,`Verify Svelte components have proper script and style sections`],preact:[`Ensure preact and preact-render-to-string are installed`,`Check that Preact components use proper JSX import source: /** @jsxImportSource preact */`,`Verify Preact components export default function`]}[e]||[`Check that the framework is properly installed`,`Verify component syntax is correct for the detected framework`,`Consider adding explicit framework detection hints`]}}
1
+ import{readFile as e}from"node:fs/promises";import{render as t}from"preact-render-to-string";import{EnhancedFrameworkDetector as n}from"../core/components/enhanced-framework-detector.js";import{toImportSpecifier as r}from"../middleware/executor.js";export class IsolatedSSRRenderer{contexts;detector;config;activeContext=null;constructor(e={}){this.contexts=new Map,this.detector=new n,this.config={enableStrictIsolation:!0,allowedCrossFrameworkImports:[`preact`,`preact-render-to-string`],errorHandling:`fallback`,debugLogging:!1,...e},this.initializeFrameworkContexts()}async renderWithIsolation(e){let t=[],n=[];try{let r=await this.resolveFramework(e,n);return await this.renderInContext(e,r,t,n)}catch(r){return t.push(`SSR rendering failed: ${r instanceof Error?r.message:String(r)}`),await this.tryFallbackRender(e,t,n)}}async resolveFramework(e,t){if(e.framework)return e.framework;try{let n=await this.getComponentContent(e.componentPath),r=this.detector.detectFramework(e.componentPath,n);return r.confidence===`low`&&t.push(`Low confidence framework detection for ${e.componentPath}: ${r.framework}`),this.config.debugLogging&&(console.log(`[SSR Isolation] Detected framework: ${r.framework} for ${e.componentPath}`),console.log(`[SSR Isolation] Evidence: ${r.evidence.join(`, `)}`)),r.framework}catch{return t.push(`Could not read component file for framework detection: ${e.componentPath}, defaulting to preact`),`preact`}}async renderInContext(e,t,n,r){let i=this.getFrameworkContext(t);if(!i)throw Error(`No SSR context available for framework: ${t}`);await this.switchToContext(t);try{let a=e.component(),o=a instanceof Promise?await a:a;return{html:await i.renderFunction(o,e.props||{}),framework:t,success:!0,errors:n,warnings:r}}finally{this.cleanupContext(t)}}async tryFallbackRender(e,n,r){if(this.config.errorHandling!==`fallback`)return{html:``,framework:e.framework||`unknown`,success:!1,errors:n,warnings:r};try{let i=t(await e.component());return r.push(`Fell back to Preact rendering due to framework-specific error`),{html:i,framework:`preact`,success:!0,errors:n,warnings:r}}catch(t){return n.push(`Fallback rendering also failed: ${t instanceof Error?t.message:String(t)}`),{html:``,framework:e.framework||`unknown`,success:!1,errors:n,warnings:r}}}initializeFrameworkContexts(){this.contexts.set(`preact`,{framework:`preact`,imports:new Map,renderFunction:e=>Promise.resolve(t(e)),cleanup:()=>{this.clearFrameworkGlobals(`preact`)},isActive:!1}),this.contexts.set(`solid`,{framework:`solid`,imports:new Map,renderFunction:async e=>{try{let t=await this.importFrameworkModule(`solid-js/web`,`solid`);if(t&&typeof t.renderToString==`function`)return t.renderToString(()=>e);throw Error(`Solid renderToString not available`)}catch(e){throw Error(`Solid SSR failed: ${e instanceof Error?e.message:String(e)}`)}},cleanup:()=>{this.clearFrameworkGlobals(`solid`)},isActive:!1}),this.contexts.set(`vue`,{framework:`vue`,imports:new Map,renderFunction:async e=>{try{let t=await this.importFrameworkModule(`vue/server-renderer`,`vue`);if(t&&typeof t.renderToString==`function`)return await t.renderToString(e);throw Error(`Vue renderToString not available`)}catch(e){throw Error(`Vue SSR failed: ${e instanceof Error?e.message:String(e)}`)}},cleanup:()=>{this.clearFrameworkGlobals(`vue`)},isActive:!1}),this.contexts.set(`svelte`,{framework:`svelte`,imports:new Map,renderFunction:e=>{try{if(e&&typeof e==`object`&&`render`in e){let t=e.render();return Promise.resolve(t.html||``)}throw Error(`Svelte component does not have render method`)}catch(e){throw Error(`Svelte SSR failed: ${e instanceof Error?e.message:String(e)}`)}},cleanup:()=>{this.clearFrameworkGlobals(`svelte`)},isActive:!1}),this.contexts.set(`unknown`,{framework:`unknown`,imports:new Map,renderFunction:e=>Promise.resolve(t(e)),cleanup:()=>{},isActive:!1})}getFrameworkContext(e){return this.contexts.get(e)||this.contexts.get(`unknown`)||null}async switchToContext(e){this.activeContext&&this.activeContext!==e&&this.cleanupContext(this.activeContext);let t=this.contexts.get(e);if(!t)throw Error(`Framework context not found: ${e}`);t.isActive=!0,this.activeContext=e,await this.setupFrameworkEnvironment(e)}cleanupContext(e){let t=this.contexts.get(e);t&&(t.cleanup(),t.isActive=!1,t.imports.clear(),this.activeContext===e&&(this.activeContext=null))}async setupFrameworkEnvironment(e){switch(e){case`solid`:await this.ensureSolidEnvironment();break;case`vue`:await this.ensureVueEnvironment();break;case`svelte`:this.ensureSvelteEnvironment();break;default:break}}async importFrameworkModule(e,t){let n=this.contexts.get(t);if(!n)throw Error(`No context for framework: ${t}`);if(n.imports.has(e))return n.imports.get(e);if(this.config.enableStrictIsolation&&!this.isImportAllowed(e,t))throw Error(`Import not allowed in ${t} context: ${e}`);try{let i=await import(r(e));return n.imports.set(e,i),this.config.debugLogging&&console.log(`[SSR Isolation] Imported ${e} in ${t} context`),i}catch(n){throw Error(`Failed to import ${e} in ${t} context: ${n instanceof Error?n.message:String(n)}`)}}isImportAllowed(e,t){let n=this.detector.getFrameworkConfigs().get(t);return n&&[...n.ssrModules,...n.hydrationModules].some(t=>e.startsWith(t))?!0:this.config.allowedCrossFrameworkImports.some(t=>e.startsWith(t))}clearFrameworkGlobals(e){let t=globalThis;switch(e){case`solid`:typeof globalThis<`u`&&(delete t._$HY,delete t.Solid);break;case`vue`:typeof globalThis<`u`&&(delete t.__VUE__,delete t.Vue);break;case`svelte`:typeof globalThis<`u`&&delete t.__SVELTE__;break}}async ensureSolidEnvironment(){try{await this.importFrameworkModule(`solid-js/web`,`solid`)}catch(e){this.config.debugLogging&&console.warn(`[SSR Isolation] Failed to set up Solid environment:`,e)}}async ensureVueEnvironment(){try{await this.importFrameworkModule(`vue/server-renderer`,`vue`)}catch(e){this.config.debugLogging&&console.warn(`[SSR Isolation] Failed to set up Vue environment:`,e)}}ensureSvelteEnvironment(){try{this.config.debugLogging&&console.log(`[SSR Isolation] Svelte environment ready`)}catch(e){this.config.debugLogging&&console.warn(`[SSR Isolation] Failed to set up Svelte environment:`,e)}}async getComponentContent(t){try{let n=t;t.startsWith(`/`)&&(n=t.substring(1));let r=[n,`src/islands/${n.split(`/`).pop()}`,`islands/${n.split(`/`).pop()}`,`examples/${n.split(`/`).pop()}`];for(let t of r)try{return await e(t,`utf-8`)}catch{}throw Error(`Component file not found: ${t}`)}catch(e){throw Error(`Failed to read component content: ${e instanceof Error?e.message:String(e)}`)}}getActiveContext(){return this.activeContext}getContexts(){return new Map(this.contexts)}updateConfig(e){this.config={...this.config,...e}}resetAllContexts(){for(let[e]of this.contexts)this.cleanupContext(e);this.activeContext=null}async renderWithFallback(e,t){let n=[],r=[];try{let i={componentPath:`fallback-component`,component:e,framework:t},a=await this.renderWithIsolation(i);if(a.success)return a;n.push(...a.errors),r.push(...a.warnings)}catch(e){n.push(`Preferred framework (${t}) failed: ${e instanceof Error?e.message:String(e)}`)}for(let i of[`preact`,`unknown`])if(i!==t)try{let a={componentPath:`fallback-component`,component:e,framework:i},o=await this.renderWithIsolation(a);if(o.success)return r.push(`Fell back to ${i} rendering from ${t}`),{...o,warnings:[...r,...o.warnings]};n.push(...o.errors)}catch(e){n.push(`Fallback framework (${i}) failed: ${e instanceof Error?e.message:String(e)}`)}return{html:``,framework:t,success:!1,errors:n,warnings:r}}async validateFrameworkContext(e){if(!this.contexts.get(e))return!1;try{return await this.setupFrameworkEnvironment(e),!0}catch(t){return this.config.debugLogging&&console.warn(`[SSR Isolation] Framework context validation failed for ${e}:`,t),!1}}getErrorRecoveryStrategies(e){return{solid:[`Ensure solid-js and solid-js/web are installed`,`Check that Solid components use proper JSX import source: /** @jsxImportSource solid-js */`,`Verify Solid components export default function`],vue:[`Ensure vue and vue/server-renderer are installed`,`Check that Vue components have proper <template>, <script>, and <style> sections`,`Verify Vue components are properly compiled for SSR`],svelte:[`Ensure svelte is installed and components are compiled`,`Check that Svelte components export default class or function`,`Verify Svelte components have proper script and style sections`],preact:[`Ensure preact and preact-render-to-string are installed`,`Check that Preact components use proper JSX import source: /** @jsxImportSource preact */`,`Verify Preact components export default function`]}[e]||[`Check that the framework is properly installed`,`Verify component syntax is correct for the detected framework`,`Consider adding explicit framework detection hints`]}}
@@ -1,14 +1,14 @@
1
- import { type JSX } from 'preact';
2
- import type { RenderOptions } from '../schemas/core.ts';
3
- import type { EnhancedLayoutResolver } from '../core/layout/enhanced-layout-resolver.ts';
4
- import type { LayoutContext } from '../types/layout.ts';
1
+ import { type JSX } from "preact";
2
+ import type { EnhancedLayoutResolver } from "../core/layout/enhanced-layout-resolver.ts";
3
+ import type { RenderOptions } from "../schemas/core.ts";
4
+ import type { LayoutContext } from "../types/layout.ts";
5
5
  export interface RouteConfig {
6
6
  component: () => JSX.Element | Promise<JSX.Element>;
7
7
  options?: Partial<RenderOptions>;
8
8
  frontmatter?: Record<string, unknown>;
9
9
  }
10
10
  export interface RenderStrategy {
11
- type: 'hydrate' | 'ssr-only';
11
+ type: "hydrate" | "ssr-only";
12
12
  reason: string;
13
13
  warnings?: string[];
14
14
  }