@useavalon/avalon 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -54
- package/dist/mod.js +1 -0
- package/dist/src/build/integration-bundler-plugin.js +1 -0
- package/dist/src/build/integration-config.js +1 -0
- package/dist/src/build/integration-detection-plugin.js +1 -0
- package/dist/src/build/integration-resolver-plugin.js +1 -0
- package/dist/src/build/island-manifest.js +1 -0
- package/dist/src/build/island-types-generator.js +5 -0
- package/dist/src/build/mdx-island-transform.js +2 -0
- package/dist/src/build/mdx-plugin.js +1 -0
- package/dist/src/build/page-island-transform.js +3 -0
- package/dist/src/build/prop-extractors/index.js +1 -0
- package/dist/src/build/prop-extractors/lit.js +1 -0
- package/dist/src/build/prop-extractors/qwik.js +1 -0
- package/dist/src/build/prop-extractors/solid.js +1 -0
- package/dist/src/build/prop-extractors/svelte.js +1 -0
- package/dist/src/build/prop-extractors/vue.js +1 -0
- package/dist/src/build/sidecar-file-manager.js +1 -0
- package/dist/src/build/sidecar-renderer.js +6 -0
- package/dist/src/client/adapters/index.js +1 -0
- package/dist/src/client/components.js +1 -0
- package/dist/src/client/css-hmr-handler.js +1 -0
- package/dist/src/client/framework-adapter.js +13 -0
- package/dist/src/client/hmr-coordinator.js +1 -0
- package/dist/src/client/hmr-error-overlay.js +214 -0
- package/dist/src/client/main.js +39 -0
- package/{src → dist/src}/client/types/framework-runtime.d.ts +68 -68
- package/{src → dist/src}/client/types/vite-hmr.d.ts +46 -46
- package/dist/src/client/types/vite-virtual-modules.d.ts +70 -0
- package/dist/src/components/Image.js +1 -0
- package/dist/src/components/IslandErrorBoundary.js +1 -0
- package/dist/src/components/LayoutDataErrorBoundary.js +1 -0
- package/dist/src/components/LayoutErrorBoundary.js +1 -0
- package/dist/src/components/PersistentIsland.js +1 -0
- package/dist/src/components/StreamingErrorBoundary.js +1 -0
- package/dist/src/components/StreamingLayout.js +29 -0
- package/dist/src/core/components/component-analyzer.js +1 -0
- package/dist/src/core/components/component-detection.js +5 -0
- package/dist/src/core/components/enhanced-framework-detector.js +1 -0
- package/dist/src/core/components/framework-registry.js +1 -0
- package/dist/src/core/content/mdx-processor.js +1 -0
- package/dist/src/core/integrations/index.js +1 -0
- package/dist/src/core/integrations/loader.js +1 -0
- package/dist/src/core/integrations/registry.js +1 -0
- package/dist/src/core/islands/island-persistence.js +1 -0
- package/dist/src/core/islands/island-state-serializer.js +1 -0
- package/dist/src/core/islands/persistent-island-context.js +1 -0
- package/dist/src/core/islands/use-persistent-state.js +1 -0
- package/dist/src/core/layout/enhanced-layout-resolver.js +1 -0
- package/dist/src/core/layout/layout-cache-manager.js +1 -0
- package/dist/src/core/layout/layout-composer.js +1 -0
- package/dist/src/core/layout/layout-data-loader.js +1 -0
- package/dist/src/core/layout/layout-discovery.js +1 -0
- package/dist/src/core/layout/layout-matcher.js +1 -0
- package/dist/src/core/layout/layout-types.js +1 -0
- package/dist/src/core/modules/framework-module-resolver.js +1 -0
- package/dist/src/islands/component-analysis.js +1 -0
- package/dist/src/islands/css-utils.js +17 -0
- package/dist/src/islands/discovery/index.js +1 -0
- package/dist/src/islands/discovery/registry.js +1 -0
- package/dist/src/islands/discovery/resolver.js +2 -0
- package/dist/src/islands/discovery/scanner.js +1 -0
- package/dist/src/islands/discovery/types.js +1 -0
- package/dist/src/islands/discovery/validator.js +18 -0
- package/dist/src/islands/discovery/watcher.js +1 -0
- package/dist/src/islands/framework-detection.js +1 -0
- package/dist/src/islands/integration-loader.js +1 -0
- package/dist/src/islands/island.js +1 -0
- package/dist/src/islands/render-cache.js +1 -0
- package/dist/src/islands/types.js +1 -0
- package/dist/src/islands/universal-css-collector.js +5 -0
- package/dist/src/islands/universal-head-collector.js +2 -0
- package/{src → dist/src}/layout-system.d.ts +592 -592
- package/dist/src/layout-system.js +1 -0
- package/dist/src/middleware/discovery.js +1 -0
- package/dist/src/middleware/executor.js +1 -0
- package/dist/src/middleware/index.js +1 -0
- package/dist/src/middleware/types.js +1 -0
- package/dist/src/nitro/build-config.js +1 -0
- package/dist/src/nitro/config.js +1 -0
- package/dist/src/nitro/error-handler.js +198 -0
- package/dist/src/nitro/index.js +1 -0
- package/dist/src/nitro/island-manifest.js +2 -0
- package/dist/src/nitro/middleware-adapter.js +1 -0
- package/dist/src/nitro/renderer.js +183 -0
- package/dist/src/nitro/route-discovery.js +1 -0
- package/dist/src/nitro/types.js +1 -0
- package/dist/src/render/collect-css.js +3 -0
- package/{src/render/error-pages.ts → dist/src/render/error-pages.js} +7 -38
- package/dist/src/render/isolated-ssr-renderer.js +1 -0
- package/dist/src/render/ssr.js +90 -0
- package/dist/src/schemas/api.js +1 -0
- package/dist/src/schemas/core.js +1 -0
- package/dist/src/schemas/index.js +1 -0
- package/dist/src/schemas/layout.js +1 -0
- package/dist/src/schemas/routing/index.js +1 -0
- package/dist/src/schemas/routing.js +1 -0
- package/dist/src/types/as-island.js +1 -0
- package/{src → dist/src}/types/image.d.ts +106 -106
- package/{src → dist/src}/types/index.d.ts +22 -22
- package/{src → dist/src}/types/island-jsx.d.ts +33 -33
- package/{src → dist/src}/types/island-prop.d.ts +20 -20
- package/dist/src/types/layout.js +1 -0
- package/{src → dist/src}/types/mdx.d.ts +6 -6
- package/dist/src/types/routing.js +1 -0
- package/dist/src/types/types.js +1 -0
- package/{src → dist/src}/types/urlpattern.d.ts +49 -49
- package/{src → dist/src}/types/vite-env.d.ts +11 -11
- package/dist/src/utils/dev-logger.js +12 -0
- package/dist/src/utils/fs.js +1 -0
- package/dist/src/vite-plugin/auto-discover.js +1 -0
- package/dist/src/vite-plugin/config.js +1 -0
- package/dist/src/vite-plugin/errors.js +1 -0
- package/dist/src/vite-plugin/image-optimization.js +45 -0
- package/dist/src/vite-plugin/integration-activator.js +1 -0
- package/dist/src/vite-plugin/island-sidecar-plugin.js +1 -0
- package/dist/src/vite-plugin/module-discovery.js +1 -0
- package/dist/src/vite-plugin/nitro-integration.js +42 -0
- package/dist/src/vite-plugin/plugin.js +1 -0
- package/dist/src/vite-plugin/types.js +1 -0
- package/dist/src/vite-plugin/validation.js +2 -0
- package/package.json +57 -26
- package/mod.ts +0 -302
- package/src/build/integration-bundler-plugin.ts +0 -116
- package/src/build/integration-config.ts +0 -168
- package/src/build/integration-detection-plugin.ts +0 -117
- package/src/build/integration-resolver-plugin.ts +0 -90
- package/src/build/island-manifest.ts +0 -269
- package/src/build/island-types-generator.ts +0 -476
- package/src/build/mdx-island-transform.ts +0 -464
- package/src/build/mdx-plugin.ts +0 -98
- package/src/build/page-island-transform.ts +0 -598
- package/src/build/prop-extractors/index.ts +0 -21
- package/src/build/prop-extractors/lit.ts +0 -140
- package/src/build/prop-extractors/qwik.ts +0 -16
- package/src/build/prop-extractors/solid.ts +0 -125
- package/src/build/prop-extractors/svelte.ts +0 -194
- package/src/build/prop-extractors/vue.ts +0 -111
- package/src/build/sidecar-file-manager.ts +0 -104
- package/src/build/sidecar-renderer.ts +0 -30
- package/src/client/adapters/index.js +0 -12
- package/src/client/adapters/index.ts +0 -13
- package/src/client/adapters/lit-adapter.js +0 -467
- package/src/client/adapters/lit-adapter.ts +0 -654
- package/src/client/adapters/preact-adapter.js +0 -223
- package/src/client/adapters/preact-adapter.ts +0 -331
- package/src/client/adapters/qwik-adapter.js +0 -259
- package/src/client/adapters/qwik-adapter.ts +0 -345
- package/src/client/adapters/react-adapter.js +0 -220
- package/src/client/adapters/react-adapter.ts +0 -353
- package/src/client/adapters/solid-adapter.js +0 -295
- package/src/client/adapters/solid-adapter.ts +0 -451
- package/src/client/adapters/svelte-adapter.js +0 -368
- package/src/client/adapters/svelte-adapter.ts +0 -524
- package/src/client/adapters/vue-adapter.js +0 -278
- package/src/client/adapters/vue-adapter.ts +0 -467
- package/src/client/components.js +0 -23
- package/src/client/components.ts +0 -35
- package/src/client/css-hmr-handler.js +0 -263
- package/src/client/css-hmr-handler.ts +0 -344
- package/src/client/framework-adapter.js +0 -283
- package/src/client/framework-adapter.ts +0 -462
- package/src/client/hmr-coordinator.js +0 -274
- package/src/client/hmr-coordinator.ts +0 -396
- package/src/client/hmr-error-overlay.js +0 -533
- package/src/client/main.js +0 -816
- package/src/client/types/vite-virtual-modules.d.ts +0 -60
- package/src/components/Image.tsx +0 -123
- package/src/components/IslandErrorBoundary.tsx +0 -145
- package/src/components/LayoutDataErrorBoundary.tsx +0 -141
- package/src/components/LayoutErrorBoundary.tsx +0 -127
- package/src/components/PersistentIsland.tsx +0 -52
- package/src/components/StreamingErrorBoundary.tsx +0 -233
- package/src/components/StreamingLayout.tsx +0 -538
- package/src/core/components/component-analyzer.ts +0 -192
- package/src/core/components/component-detection.ts +0 -508
- package/src/core/components/enhanced-framework-detector.ts +0 -500
- package/src/core/components/framework-registry.ts +0 -563
- package/src/core/content/mdx-processor.ts +0 -46
- package/src/core/integrations/index.ts +0 -19
- package/src/core/integrations/loader.ts +0 -125
- package/src/core/integrations/registry.ts +0 -175
- package/src/core/islands/island-persistence.ts +0 -325
- package/src/core/islands/island-state-serializer.ts +0 -258
- package/src/core/islands/persistent-island-context.tsx +0 -80
- package/src/core/islands/use-persistent-state.ts +0 -68
- package/src/core/layout/enhanced-layout-resolver.ts +0 -322
- package/src/core/layout/layout-cache-manager.ts +0 -485
- package/src/core/layout/layout-composer.ts +0 -357
- package/src/core/layout/layout-data-loader.ts +0 -516
- package/src/core/layout/layout-discovery.ts +0 -243
- package/src/core/layout/layout-matcher.ts +0 -299
- package/src/core/layout/layout-types.ts +0 -110
- package/src/core/modules/framework-module-resolver.ts +0 -273
- package/src/islands/component-analysis.ts +0 -213
- package/src/islands/css-utils.ts +0 -565
- package/src/islands/discovery/index.ts +0 -80
- package/src/islands/discovery/registry.ts +0 -340
- package/src/islands/discovery/resolver.ts +0 -477
- package/src/islands/discovery/scanner.ts +0 -386
- package/src/islands/discovery/types.ts +0 -117
- package/src/islands/discovery/validator.ts +0 -544
- package/src/islands/discovery/watcher.ts +0 -368
- package/src/islands/framework-detection.ts +0 -428
- package/src/islands/integration-loader.ts +0 -490
- package/src/islands/island.tsx +0 -565
- package/src/islands/render-cache.ts +0 -550
- package/src/islands/types.ts +0 -80
- package/src/islands/universal-css-collector.ts +0 -157
- package/src/islands/universal-head-collector.ts +0 -137
- package/src/layout-system.ts +0 -218
- package/src/middleware/discovery.ts +0 -268
- package/src/middleware/executor.ts +0 -315
- package/src/middleware/index.ts +0 -76
- package/src/middleware/types.ts +0 -99
- package/src/nitro/build-config.ts +0 -576
- package/src/nitro/config.ts +0 -483
- package/src/nitro/error-handler.ts +0 -636
- package/src/nitro/index.ts +0 -173
- package/src/nitro/island-manifest.ts +0 -584
- package/src/nitro/middleware-adapter.ts +0 -260
- package/src/nitro/renderer.ts +0 -1471
- package/src/nitro/route-discovery.ts +0 -439
- package/src/nitro/types.ts +0 -321
- package/src/render/collect-css.ts +0 -198
- package/src/render/isolated-ssr-renderer.ts +0 -654
- package/src/render/ssr.ts +0 -1030
- package/src/schemas/api.ts +0 -30
- package/src/schemas/core.ts +0 -64
- package/src/schemas/index.ts +0 -212
- package/src/schemas/layout.ts +0 -279
- package/src/schemas/routing/index.ts +0 -38
- package/src/schemas/routing.ts +0 -376
- package/src/types/as-island.ts +0 -20
- package/src/types/layout.ts +0 -285
- package/src/types/routing.ts +0 -555
- package/src/types/types.ts +0 -5
- package/src/utils/dev-logger.ts +0 -299
- package/src/utils/fs.ts +0 -151
- package/src/vite-plugin/auto-discover.ts +0 -551
- package/src/vite-plugin/config.ts +0 -266
- package/src/vite-plugin/errors.ts +0 -127
- package/src/vite-plugin/image-optimization.ts +0 -156
- package/src/vite-plugin/integration-activator.ts +0 -126
- package/src/vite-plugin/island-sidecar-plugin.ts +0 -176
- package/src/vite-plugin/module-discovery.ts +0 -189
- package/src/vite-plugin/nitro-integration.ts +0 -1354
- package/src/vite-plugin/plugin.ts +0 -401
- package/src/vite-plugin/types.ts +0 -327
- package/src/vite-plugin/validation.ts +0 -228
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
typeof globalThis<`u`&&!globalThis.__svelteSSRCSS&&(globalThis.__svelteSSRCSS=new Map);export function addSvelteSSRCSS(e,t,n,r=!1){globalThis.__svelteSSRCSS||(globalThis.__svelteSSRCSS=new Map);let i={css:e.trim(),scopeId:t,src:n,isGlobal:r,timestamp:Date.now()};globalThis.__svelteSSRCSS.set(t,i)}export function getSvelteSSRCSS(e=!1){if(!globalThis.__svelteSSRCSS||globalThis.__svelteSSRCSS.size===0)return``;let t=Array.from(globalThis.__svelteSSRCSS.values());t.sort((e,t)=>e.isGlobal&&!t.isGlobal?-1:!e.isGlobal&&t.isGlobal?1:e.timestamp-t.timestamp);let n=t.filter(e=>e.isGlobal),r=t.filter(e=>!e.isGlobal),i=o([n.map(e=>`${`/* Global CSS from: ${e.src} */`}\n${e.css}`).join(`
|
|
2
|
+
|
|
3
|
+
`),r.map(e=>`${`/* Component CSS: ${e.src} (${e.scopeId}) */`}\n${e.css}`).join(`
|
|
4
|
+
|
|
5
|
+
`)].filter(e=>e.trim()).join(`
|
|
6
|
+
|
|
7
|
+
`));return e&&globalThis.__svelteSSRCSS.clear(),i}export function getSvelteSSRCSSForHead(e=!1){let n=getSvelteSSRCSS(e);return n.trim()?`<style data-svelte-ssr="true" data-generated="${new Date().toISOString()}">\n${n}\n</style>`:``}export function getSvelteSSRCSSStats(){if(!globalThis.__svelteSSRCSS||globalThis.__svelteSSRCSS.size===0)return{totalComponents:0,globalComponents:0,scopedComponents:0,totalCSSSize:0,averageCSSSize:0,oldestTimestamp:0,newestTimestamp:0};let e=Array.from(globalThis.__svelteSSRCSS.values()),t=e.filter(e=>e.isGlobal),n=e.filter(e=>!e.isGlobal),r=e.reduce((e,t)=>e+t.css.length,0),i=e.map(e=>e.timestamp);return{totalComponents:e.length,globalComponents:t.length,scopedComponents:n.length,totalCSSSize:r,averageCSSSize:e.length>0?Math.round(r/e.length):0,oldestTimestamp:Math.min(...i),newestTimestamp:Math.max(...i)}}export function getSvelteComponentCSS(e){if(!globalThis.__svelteSSRCSS)return null;let t=globalThis.__svelteSSRCSS.get(e);return t?t.css:null}export function clearSvelteComponentCSS(e){return globalThis.__svelteSSRCSS?globalThis.__svelteSSRCSS.delete(e):!1}function o(e){try{return s(optimizeComponentCSS(e))}catch(t){return console.warn(`⚠️ Failed to optimize Svelte SSR CSS:`,t),e}}function s(e){try{let t=l(c(e));return process.env.NODE_ENV===`production`?minifyCSS(t):u(t)}catch(t){return console.warn(`⚠️ Failed to apply SSR CSS collection optimizations:`,t),e}}function c(e){let t=new Set;return e.replace(/\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\//g,e=>e.includes(`!important`)||e.includes(`@preserve`)||e.includes(`license`)?e:t.has(e)?``:(t.add(e),e))}function l(e){return e.replace(/\n\s*\n\s*\n/g,`
|
|
8
|
+
|
|
9
|
+
`).replace(/^\s*\n/gm,``).trim()}function u(e){return e.replace(/\{/g,` {
|
|
10
|
+
`).replace(/;/g,`;
|
|
11
|
+
`).replace(/\}/g,`
|
|
12
|
+
}
|
|
13
|
+
`).replace(/\n {2}\n/g,`
|
|
14
|
+
`).replace(/\n\n+/g,`
|
|
15
|
+
|
|
16
|
+
`).trim()}export function applyCSSScoping(e,t){return e.replace(/([^{}]+){/g,(e,n)=>{let r=n.trim();return r.startsWith(`@`)||r.includes(`[data-${t}]`)?e:r.includes(`:global(`)?`${r.replace(/:global\(([^)]+)\)/g,`$1`)} {`:`${r.split(`,`).map(e=>applySelectorScoping(e.trim(),t)).join(`, `)} {`})}export function applySelectorScoping(e,t){if(!e||e.length===0||e.includes(`[data-${t}]`))return e;let n=e.split(/(\s*[>+~]\s*|\s+)/);if(n.length>1){let e=n[0].trim(),r=n.slice(1).join(``);return d(e,t)+r}return d(e,t)}function d(e,t){let n=e.match(/^([^:]+)(::.*)?$/);if(n){let[,e,r]=n;return`${e}[data-${t}]${r||``}`}let r=e.match(/^([^:]+)(:.*)?$/);if(r){let[,e,n]=r;return`${e}[data-${t}]${n||``}`}return`${e}[data-${t}]`}export function optimizeComponentCSS(e){try{let t=p(f(e)).join(`
|
|
17
|
+
`);return process.env.NODE_ENV===`production`?minifyCSS(t):t}catch(t){return console.warn(`⚠️ Failed to optimize component CSS:`,t),e}}function f(e){let t=[],n=``,r=0,i=!1,a=``;for(let o=0;o<e.length;o++){let s=e[o],c=o>0?e[o-1]:``;if((s===`"`||s===`'`)&&c!==`\\`&&(i?s===a&&(i=!1,a=``):(i=!0,a=s)),!i){if(s===`{`)r++;else if(s===`}`&&(r--,r===0)){n+=s;let e=n.trim();e&&!h(e)&&t.push(e),n=``;continue}}n+=s}return n.trim()&&t.push(n.trim()),t}function p(e){let t=new Map,n=[];for(let r=0;r<e.length;r++){let i=e[r],a=m(i);if(a){let e=t.get(a);if(e)n[e.index]=i,t.set(a,{rule:i,index:e.index});else{let e=n.length;n.push(i),t.set(a,{rule:i,index:e})}}else n.push(i)}return n.filter(e=>e!==null)}function m(e){let t=e.match(/^([^{]+)\{([^}]+)\}/);if(!t)return null;let n=t[1].trim();return t[2].trim(),n}function h(e){let t=e.match(/^[^{]+\{([^}]*)\}/);if(!t)return!0;let n=t[1].trim();return n.length===0||n===`;`}export function minifyCSS(e){return e.replace(/\/\*[\s\S]*?\*\//g,``).replace(/\s+/g,` `).replace(/\s*{\s*/g,`{`).replace(/\s*}\s*/g,`}`).replace(/\s*;\s*/g,`;`).replace(/;\s*}/g,`}`).replace(/;}/g,`}`).trim()}export function generateComponentScopeId(e,t=`component`){return`${t}-${e.replace(/^\/+/,``).replace(/\.(svelte|tsx|jsx|vue|ts|js)$/,``).replace(/[^a-zA-Z0-9\/]/g,`-`).replace(/\/+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``).toLowerCase()}-${simpleHash(e)}`}export function simpleHash(e){let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);t=(t<<5)-t+r,t&=t}return Math.abs(t).toString(36).substring(0,6)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{ISLAND_FILE_EXTENSIONS,DEFAULT_DISCOVERY_CONFIG,isSupportedIslandExtension}from"./types.js";export{discoverIslandDirectories,discoverIslandsInDirectory,discoverAllIslands,isIslandsDirectory,getDefaultIslandsPath,hasDefaultIslandsDirectory,getQualifiedIslandName,parseQualifiedIslandName}from"./scanner.js";export{IslandRegistry,createIslandRegistry}from"./registry.js";export{IslandResolver,createIslandResolver}from"./resolver.js";export{IslandValidator,createIslandValidator,validateAllIslands,formatValidationError,formatValidationWarning,formatCircularDependency,formatValidationResult}from"./validator.js";export{IslandWatcher,createIslandWatcher}from"./watcher.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{discoverIslandDirectories as e,discoverIslandsInDirectory as t,getQualifiedIslandName as n,parseQualifiedIslandName as r}from"./scanner.js";export class IslandRegistry{_islands=new Map;_directories=[];_byName=new Map;_collisions=[];_projectRoot;_config;constructor(e,t={}){this._projectRoot=e,this._config=t}get islands(){return new Map(this._islands)}get directories(){return[...this._directories]}get collisions(){return[...this._collisions]}get size(){return this._islands.size}register(e){let t=n(e);this._islands.set(t,e);let r=this._byName.get(e.name)||[];r.push(e),this._byName.set(e.name,r)}resolve(e,t){if(t!==void 0){let n=t===``?e:`${t}/${e}`,r=this._islands.get(n);if(r)return r}if(e.includes(`/`)){let t=this._islands.get(e);if(t)return t;let{namespace:n,name:i}=r(e),a=n===``?i:`${n}/${i}`;return this._islands.get(a)||null}let n=this._byName.get(e);return!n||n.length===0?null:n.length===1?n[0]:n.find(e=>e.directory.isDefault)||n[0]}findByName(e){return this._byName.get(e)||[]}getQualifiedName(e){return n(e)}has(e){return this._islands.has(e)?!0:this._byName.has(e)}detectCollisions(){let e=[];for(let[t,n]of this._byName)if(n.length>1){let r=n.some(e=>e.directory.isDefault)?`priority`:`namespace`;e.push({name:t,islands:[...n],resolution:r})}return this._collisions=e,e}async rebuild(){this._islands.clear(),this._byName.clear(),this._directories=[],this._collisions=[],this._directories=await e(this._projectRoot,this._config);for(let e of this._directories){let n=await t(e,this._projectRoot);for(let e of n)this.register(e)}this.detectCollisions()}getAllIslands(){return Array.from(this._islands.values())}getIslandsInDirectory(e){return this.getAllIslands().filter(t=>t.directory.path===e.path)}getIslandsByNamespace(e){return this.getAllIslands().filter(t=>t.namespace===e)}unregister(e){let t=this._islands.get(e);if(!t)return!1;this._islands.delete(e);let r=this._byName.get(t.name);if(r){let i=r.filter(t=>n(t)!==e);i.length===0?this._byName.delete(t.name):this._byName.set(t.name,i)}return!0}toJSON(){return{islands:Object.fromEntries(this._islands),directories:this._directories,collisions:this._collisions}}}export async function createIslandRegistry(e,t={}){let n=new IslandRegistry(e,t);return await n.rebuild(),n}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{relative as e}from"node:path";import{parseQualifiedIslandName as t,getQualifiedIslandName as n}from"./scanner.js";const r={isDevelopment:!0,basePath:`/`,projectRoot:``,absolute:!1};export class IslandResolver{_registry;_projectRoot;constructor(e,t){this._registry=e,this._projectRoot=t}get registry(){return this._registry}get projectRoot(){return this._projectRoot}resolve(e){let t=this.normalizeReference(e),n=this.resolveExplicitPath(t);if(n)return n;if(t.includes(`/`)){let e=this.resolveQualifiedName(t);if(e)return e}return this.resolveByName(t)}normalizeReference(e){let t=e.trim().replace(/^\/+|\/+$/g,``);t=t.replace(/\\/g,`/`);for(let e of[/\.solid\.(tsx|jsx)$/,/\.react\.(tsx|jsx)$/,/\.lit\.(ts|js)$/,/\.preact\.(tsx|jsx)$/,/\.(tsx|ts|jsx|js|vue|svelte)$/])if(e.test(t)){t=t.replace(e,``);break}return t}resolveExplicitPath(e){if(!e.includes(`islands/`))return null;let t=this._registry.getAllIslands();for(let n of t){let t=n.relativePath.replace(/\.[^.]+$/,``),r=[/\.solid$/,/\.react$/,/\.lit$/,/\.preact$/],i=t;for(let e of r)i=i.replace(e,``);if(i===e||i.endsWith(`/`+e)||t===e||t.endsWith(`/`+e))return{island:n,importPath:this.generateImportPath(n),ambiguous:!1}}return null}resolveQualifiedName(e){let{namespace:n,name:r}=t(e),i=this._registry.resolve(r,n);if(!i)return null;let a=this._registry.findByName(r),o=a.length>1;return{island:i,importPath:this.generateImportPath(i),ambiguous:o,alternatives:o?a.filter(e=>e!==i):void 0}}resolveByName(e){let t=this._registry.findByName(e);if(t.length===0)return null;let n=[...t].sort((e,t)=>e.directory.isDefault&&!t.directory.isDefault?-1:!e.directory.isDefault&&t.directory.isDefault?1:e.namespace.localeCompare(t.namespace)),r=n[0],i=t.length>1;return{island:r,importPath:this.generateImportPath(r),ambiguous:i,alternatives:i?n.slice(1):void 0}}generateImportPath(t,n={}){let i={...r,...n},a=i.projectRoot||this._projectRoot;if(i.absolute)return t.filePath;if(i.isDevelopment){let n=e(a,t.filePath).replace(/\\/g,`/`);return`${i.basePath}${n}`}return`${i.basePath}${t.relativePath}`}generateQualifiedImportPath(e){return n(e)}getResolutionOrder(){return[`Island Resolution Order:`,`1. Explicit path-based references (e.g., 'src/modules/auth/islands/Counter')`,`2. Qualified name matches (e.g., 'modules/auth/Counter')`,`3. Default /src/islands/ directory (highest priority for unqualified names)`,`4. Nested directories in alphabetical order by namespace`,``,`Discovered directories (in priority order):`,...this._registry.directories.map((e,t)=>` ${t+1}. ${e.relativePath}${e.isDefault?` (default)`:``}`)]}isAmbiguous(e){return this.resolve(e)?.ambiguous??!1}getAllMatches(e){let n=this.normalizeReference(e);if(n.includes(`/`)&&!n.includes(`islands/`)){let{namespace:e,name:r}=t(n),i=this._registry.resolve(r,e);return i?[i]:[]}return this._registry.findByName(n)}suggestQualifiedNames(e){return this._registry.findByName(e).map(e=>n(e))}resolveOrThrow(e){let t=this.resolve(e);if(!t){let t=this.findSimilarNames(e),n=`Island not found: "${e}"`;throw t.length>0&&(n+=`\n\nDid you mean one of these?\n${t.map(e=>` - ${e}`).join(`
|
|
2
|
+
`)}`),Error(n)}return t}findSimilarNames(e){let t=this._registry.getAllIslands(),r=e.toLowerCase();return t.filter(e=>{let t=e.name.toLowerCase(),i=n(e).toLowerCase();return t.includes(r)||r.includes(t)||i.includes(r)||this.levenshteinDistance(t,r)<=3}).map(e=>n(e)).slice(0,5)}levenshteinDistance(e,t){let n=[];for(let e=0;e<=t.length;e++)n[e]=[e];for(let t=0;t<=e.length;t++)n[0][t]=t;for(let r=1;r<=t.length;r++)for(let i=1;i<=e.length;i++)t.charAt(r-1)===e.charAt(i-1)?n[r][i]=n[r-1][i-1]:n[r][i]=Math.min(n[r-1][i-1]+1,n[r][i-1]+1,n[r-1][i]+1);return n[t.length][e.length]}}export function createIslandResolver(e,t){return new IslandResolver(e,t)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{resolve as e,relative as t,dirname as n,basename as r,extname as i}from"node:path";import{stat as a,readdir as o}from"node:fs/promises";import{DEFAULT_DISCOVERY_CONFIG as s,isSupportedIslandExtension as c}from"./types.js";export async function discoverIslandDirectories(t,n={}){let r={...s,...n},i=e(t,r.rootDir),o=[];try{if(!(await a(i)).isDirectory())return o}catch{return o}return await u(i,t,r,o),o.sort((e,t)=>e.isDefault&&!t.isDefault?-1:!e.isDefault&&t.isDefault?1:e.relativePath.localeCompare(t.relativePath)),o}async function u(n,r,i,a){try{let s=await o(n,{withFileTypes:!0});for(let o of s){if(!o.isDirectory())continue;let s=e(n,o.name);if(!d(t(r,s),i.exclude)){if(o.name===`islands`){let e=f(s,r,i);a.push(e);continue}await u(s,r,i,a)}}}catch(e){(!(e instanceof Error)||e.code!==`EACCES`)&&console.warn(`Warning: Could not scan directory ${n}:`,e)}}function d(e,t){let n=e.replace(/\\/g,`/`);for(let e of t)if(n===e||n.startsWith(e+`/`)||n.includes(`/`+e+`/`)||n.endsWith(`/`+e))return!0;return!1}function f(r,i,a){let o=t(e(i,a.rootDir),r),s=o===`islands`,c=``;return s||(c=n(o).replace(/\\/g,`/`),a.namespaces[c]&&(c=a.namespaces[c])),{path:r,relativePath:o.replace(/\\/g,`/`),namespace:c,isDefault:s}}export function isIslandsDirectory(e){return r(e)===`islands`}export function getDefaultIslandsPath(t,n=`src`){return e(t,n,`islands`)}export async function hasDefaultIslandsDirectory(e,t=`src`){let n=getDefaultIslandsPath(e,t);try{return(await a(n)).isDirectory()}catch{return!1}}export async function discoverIslandsInDirectory(e,t){let n=[];try{let r=await o(e.path,{withFileTypes:!0});for(let a of r){if(!a.isFile()||!c(i(a.name)))continue;let r=p(a.name,e,t);n.push(r)}}catch(t){console.warn(`Warning: Could not scan islands directory ${e.path}:`,t)}return n.sort((e,t)=>e.name.localeCompare(t.name)),n}export async function discoverAllIslands(e,t={}){let n=await discoverIslandDirectories(e,t),r=[];for(let t of n){let n=await discoverIslandsInDirectory(t,e);r.push(...n)}return r}function p(n,r,a){let o=i(n),s=m(n),c=e(r.path,n),l=t(a,c).replace(/\\/g,`/`),u=h(n);return{name:s,filePath:c,relativePath:l,namespace:r.namespace,framework:u,extension:o,directory:r}}function m(e){let t=e;for(let e of[`.solid.tsx`,`.solid.jsx`,`.react.tsx`,`.react.jsx`,`.lit.ts`,`.lit.js`,`.preact.tsx`,`.preact.jsx`])if(t.endsWith(e))return t.slice(0,-e.length);for(let e of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(t.endsWith(e))return t.slice(0,-e.length);return t}function h(e){let t=e.toLowerCase();if(t.includes(`.solid.`))return`solid`;if(t.includes(`.react.`))return`react`;if(t.includes(`.lit.`))return`lit`;if(t.includes(`.preact.`))return`preact`;if(t.includes(`.qwik.`))return`qwik`;if(e.endsWith(`.vue`))return`vue`;if(e.endsWith(`.svelte`))return`svelte`;if((e.endsWith(`.ts`)||e.endsWith(`.js`))&&!e.endsWith(`.d.ts`)){let t=m(e);if(/^[A-Z]/.test(t))return`lit`}return e.endsWith(`.tsx`)||e.endsWith(`.jsx`)?`preact`:`unknown`}export function getQualifiedIslandName(e){return e.namespace===``?e.name:`${e.namespace}/${e.name}`}export function parseQualifiedIslandName(e){let t=e.lastIndexOf(`/`);return t===-1?{namespace:``,name:e}:{namespace:e.slice(0,t),name:e.slice(t+1)}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const ISLAND_FILE_EXTENSIONS=[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`];export function isSupportedIslandExtension(e){return ISLAND_FILE_EXTENSIONS.includes(e)}export const DEFAULT_DISCOVERY_CONFIG={rootDir:`src`,include:[],exclude:[`node_modules`,`.git`,`dist`,`build`],namespaces:{},strictCollisions:!1};
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
|
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+=`
|
|
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(`
|
|
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
|
+
`):e.valid?n.push(`
|
|
14
|
+
✓ Validation passed with warnings
|
|
15
|
+
`):n.push(`
|
|
16
|
+
✗ Validation failed
|
|
17
|
+
`),n.join(`
|
|
18
|
+
`)}export function createIslandValidator(e){return new IslandValidator(e)}export async function validateAllIslands(e,t){let n=createIslandValidator(t),r=[],i=[];for(let t of e){let e=await n.validateComponent(t.filePath);r.push(...e.errors),i.push(...e.warnings)}let a=await n.detectCircularDependencies(e);for(let e of a)r.push({type:`circular-dependency`,message:e.description,filePath:e.cycle[0]});return{valid:r.length===0,errors:r,warnings:i}}
|
|
@@ -0,0 +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)}
|
|
@@ -0,0 +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`}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{registry as e}from"../core/integrations/registry.js";import{devWarn as t}from"../utils/dev-logger.js";const n=new Map;export async function loadIntegration(t){if(n.has(t))return n.get(t);if(e.has(t)){let r=e.get(t);return n.set(t,r),r}try{let r=await e.load(t);return n.set(t,r),r}catch(e){throw Error(`Integration '${t}' could not be loaded. Make sure @useavalon/${t} is installed.`,{cause:e})}}export async function detectAndLoadIntegration(e){return await loadIntegration(detectFrameworkFromPath(e))}export function detectFrameworkFromPath(e){let t=e.replaceAll(`\\`,`/`);return t.endsWith(`.vue`)?`vue`:t.endsWith(`.svelte`)?`svelte`:t.includes(`.solid.`)?`solid`:t.includes(`.qwik.`)?`qwik`:t.includes(`.react.`)?`react`:t.includes(`.lit.`)||(t.split(`/`).pop()||``).startsWith(`Lit`)&&(t.endsWith(`.ts`)||t.endsWith(`.js`))||isInIslandsDirectory(t)&&(t.endsWith(`.ts`)||t.endsWith(`.js`))?`lit`:(t.endsWith(`.tsx`)||t.endsWith(`.jsx`),`preact`)}export function isInIslandsDirectory(e){return e.replaceAll(`\\`,`/`).includes(`/islands/`)}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}export function extractNamespaceFromPath(e){let t=e.replaceAll(`\\`,`/`),n=new RegExp(/(?:\/src)?\/(.+?)\/islands\//).exec(t);return n?n[1]:``}export function detectFrameworkFromContent(e,t){let n=detectFrameworkFromPath(e);return n===`vue`||n===`svelte`||n===`react`||n===`lit`?n:t.includes(`from 'react'`)||t.includes(`from "react"`)||t.includes(`from 'react-dom'`)||t.includes(`from "react-dom"`)||t.includes(`"use client"`)||t.includes(`'use client'`)||t.includes(`"use server"`)||t.includes(`'use server'`)?`react`:t.includes(`from 'lit'`)||t.includes(`from "lit"`)||t.includes(`@lit-labs/ssr`)||t.includes(`LitElement`)||t.includes(`@customElement`)?`lit`:t.includes(`solid-js`)||t.includes(`from 'solid-js'`)||t.includes(`from "solid-js"`)?`solid`:t.includes(`from 'preact'`)||t.includes(`from "preact"`)||t.includes(`preact/hooks`)?`preact`:t.includes(`extends LitElement`)||t.includes(`@property`)||t.includes(`@state`)||t.includes("html`")||t.includes("css`")?`lit`:t.includes(`createSignal`)||t.includes(`createEffect`)||t.includes(`createMemo`)?`solid`:t.includes(`useState`)||t.includes(`useEffect`)||t.includes(`useRef`)?`preact`:n}export async function getIntegration(e){try{return await loadIntegration(e)}catch(t){return console.error(`Failed to load integration for ${e}:`,t),null}}export async function hasIntegration(e){try{return await loadIntegration(e),!0}catch{return!1}}export function getLoadedIntegrations(){return Array.from(n.values())}export function getLoadedFrameworks(){return Array.from(n.keys())}export function clearIntegrationCache(){n.clear()}export function isIntegrationLoaded(e){return n.has(e)}export const DEFAULT_PRELOAD_FRAMEWORKS=[`preact`,`react`,`vue`,`svelte`,`solid`,`lit`];export async function preloadIntegrations(e){let n,i=!1,a;if(e?(n=e.frameworks??DEFAULT_PRELOAD_FRAMEWORKS,i=e.lazy??!1,a=e.detectedFrameworks):n=DEFAULT_PRELOAD_FRAMEWORKS,i&&a&&a.length>0){let e=n.filter(e=>a.includes(e));if(e.length===0)return;n=e}else if(i&&(!a||a.length===0))return;let o=await Promise.allSettled(n.map(e=>loadIntegration(e))),s=0,c=0;o.forEach((e,r)=>{e.status===`rejected`?(c++,t(`⚠️ Failed to preload integration '${n[r]}':`,e.reason)):s++})}export function detectFrameworksFromPageContent(e){let t=new Set,n=e.matchAll(/framework\s*=\s*["'](\w+)["']/g);for(let e of n)t.add(e[1]);let r=e.matchAll(/src\s*=\s*["']([^"']+)["']/g);for(let e of r){let n=e[1],r=detectFrameworkFromPath(n);t.add(r)}return(e.includes(`from 'react'`)||e.includes(`from "react"`))&&t.add(`react`),(e.includes(`from 'preact'`)||e.includes(`from "preact"`))&&t.add(`preact`),(e.includes(`from 'vue'`)||e.includes(`from "vue"`))&&t.add(`vue`),(e.includes(`from 'svelte'`)||e.includes(`from "svelte"`))&&t.add(`svelte`),(e.includes(`from 'solid-js'`)||e.includes(`from "solid-js"`))&&t.add(`solid`),(e.includes(`from 'lit'`)||e.includes(`from "lit"`))&&t.add(`lit`),Array.from(t)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{h as e}from"preact";import{detectFramework as t}from"./framework-detection.js";import{analyzeComponentFile as n,renderComponentSSROnly as r}from"./component-analysis.js";import{loadIntegration as i,detectFrameworkFromPath as a}from"./integration-loader.js";import{addUniversalCSS as o}from"./universal-css-collector.js";import{addUniversalHead as s}from"./universal-head-collector.js";import{getIslandBundlePath as c}from"../build/island-manifest.js";import{isDev as l,devLog as u,devWarn as d,devError as f,logRenderTiming as p}from"../utils/dev-logger.js";function m(e){return`island-${e.replaceAll(/[^a-zA-Z0-9]/g,`-`)}`}function h(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 g(e,t,n,r){return{"data-condition":t,"data-src":c(e),"data-props":JSON.stringify(n),"data-render-strategy":`hydrate`,...h(r)}}function _(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 v(e){let t=e.match(/<style[^>]*>([\s\S]*?)<\/style>/i);return t?t[1].trim():null}function y(e,t,n,r){if(e.css&&o(e.css,t,n,e.scopeId),e.head){let i=e.head.trim(),a=_(i);if(a===`style`){let a=v(i);a&&(u(`${r} Extracting CSS from head <style> tag`),o(a,t,n,e.scopeId));return}s(e.head,t,n,a)}}function b(t){let{islandId:n,detectedFramework:r,shouldSkipHydration:i,src:a,condition:o,props:s,hydrationData:c,children:l}=t,d={id:n,"data-framework":r},f=i?{"data-render-strategy":`ssr-only`}:g(a,o,s,c);r===`lit`&&u(`🔍 [Island Component] ${a} - Lit hydration data:`,{hydrationDataKeys:Object.keys(c),metadata:c.metadata});let p={...d,...f};return typeof l==`string`?e(`avalon-island`,{...p,dangerouslySetInnerHTML:{__html:l}}):e(`avalon-island`,p,l)}function x(t,n,r,i,a,o,s){return r?e(`avalon-island`,{id:t,"data-render-strategy":`ssr-only`,"data-framework":n}):e(`avalon-island`,{id:t,"data-condition":a,"data-src":c(i),"data-props":JSON.stringify(o),"data-render-strategy":`hydrate`,"data-framework":n,...h(s)})}export default function S({src:e,condition:t=`on:client`,props:n={},children:r,ssr:i=t!==`on:client`,framework:o,ssrOnly:s=!1,renderOptions:c={},hydrationData:l={}}){let f=m(e),p=s||!!c.forceSSROnly,h=o||a(e),g=r!=null&&r!==``;return u(`🔍 [Island Component] ${e}`,{ssr:i,ssrOnly:s,hasChildren:g,framework:o,condition:t}),i&&g?b({islandId:f,detectedFramework:h,shouldSkipHydration:p,src:e,condition:t,props:n,hydrationData:l,children:r}):(i&&!g&&p&&d(`${e}: SSR-only component has no rendered content. This may indicate a rendering error.`),x(f,h,p,e,t,n,l))}function C(t,n){let r=n instanceof Error?n.message:String(n);return f(`🚨 Island SSR failed for ${t}:`,n),n instanceof Error&&n.stack&&f(`Stack trace:`,n.stack),e(`avalon-island`,{id:m(t),"data-src":c(t),"data-ssr-error":r,"data-render-strategy":`client-only`})}async function w({src:e,condition:t,props:n,children:r,ssr:a,framework:o,ssrOnly:s,renderOptions:c}){let u=`🏝️ [${e}]`;if(!a||r)return S({src:e,condition:t,props:n,children:r,ssr:a,framework:o,ssrOnly:s,renderOptions:c});let d;try{d=await i(o)}catch(r){return f(`${u} Failed to load ${o} integration:`,r),S({src:e,condition:t,props:n,ssr:!1,framework:o,ssrOnly:s,renderOptions:c})}try{let r=await d.render({component:null,props:n,src:e,condition:t,ssrOnly:s,viteServer:globalThis.__viteDevServer,isDev:l()});return y(r,e,o,u),S({src:e,condition:t,props:n,children:r.html,ssr:!0,framework:o,ssrOnly:s,renderOptions:c,hydrationData:s?void 0:r.hydrationData})}catch(r){return f(`${u} Fast path SSR failed:`,r),S({src:e,condition:t,props:n,ssr:!1,framework:o,ssrOnly:s,renderOptions:c})}}async function T(e,t,r,i){if(t||r.detectScripts===!1)return t;try{let t=await n(e,r);if(t.decision.warnings?.length)for(let e of t.decision.warnings)d(`${i} Analysis warning: ${e}`);return!t.decision.shouldHydrate}catch(e){return d(`${i} Component analysis failed:`,e),t}}async function E(e){return e.endsWith(`.vue`)?`vue`:e.endsWith(`.svelte`)?`svelte`:e.endsWith(`.tsx`)||e.endsWith(`.jsx`)||e.endsWith(`.ts`)||e.endsWith(`.js`)?t(e):`unknown`}async function D(e,t,n,r,i,a){let o=await E(e),s=o,c=await(await O(o,a)).render({component:null,props:n,src:e,condition:t,ssrOnly:r,viteServer:globalThis.__viteDevServer,isDev:l()});return y(c,e,o,a),S({src:e,condition:t,props:n,children:c.html,ssr:!0,framework:s,ssrOnly:r,renderOptions:i,hydrationData:r?void 0:c.hydrationData})}async function O(e,t){try{u(`${t} Loading integration for framework: ${e}`);let n=await i(e);return u(`${t} ✅ Integration loaded successfully`),n}catch(n){throw f(`${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`,props:n={},children:r,ssr:i=t!==`on:client`,framework:a,ssrOnly:o=!1,renderOptions:s={}}){let c=l()?performance.now():0,u=`🏝️ [${e}]`;try{return o&&!i&&(i=!0),a?await w({src:e,condition:t,props:n,children:r,ssr:i,framework:a,ssrOnly:o,renderOptions:s}):await k({src:e,condition:t,props:n,children:r,ssr:i,ssrOnly:o,renderOptions:s,logPrefix:u})}catch(t){return C(e,t)}finally{l()&&p(e,performance.now()-c)}}async function k(e){let{src:t,condition:n,props:r,children:i,ssr:a,ssrOnly:o,renderOptions:s,logPrefix:c}=e;if(u(`🔍 [renderIsland] ${t} - Starting render (slow path)`,{ssr:a,ssrOnly:o,hasChildren:!!i,condition:n}),await T(t,o,s,c))return A(t,n,r,i,a,s,c);if(!a||i)return S({src:t,condition:n,props:r,children:i,ssr:a,renderOptions:s});try{return await D(t,n,r,o,s,c)}catch(e){let i=await E(t);return f(`${c} Framework rendering failed:`,e),S({src:t,condition:n,props:r,ssr:!1,framework:i,renderOptions:s})}}function A(e,t,n,i,a,o,s){return a&&!i?r({src:e,condition:t,props:n,renderOptions:o}).catch(r=>(f(`${s} SSR failed for SSR-only component:`,r),S({src:e,condition:t,props:n,ssr:!1,ssrOnly:!0,renderOptions:o}))):S({src:e,condition:t,props:n,children:i,ssr:a,ssrOnly:!0,renderOptions:o})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={analysisTTL:6e4,pathTTL:6e4,frameworkTTL:6e4,maxEntries:1e3},t={analysisSize:0,pathsSize:0,frameworksSize:0,analysisHits:0,analysisMisses:0,pathHits:0,pathMisses:0,frameworkHits:0,frameworkMisses:0},n={analysis:new Map,paths:new Map,frameworks:new Map,config:{...e},stats:{...t}};function r(){try{return process.env.NODE_ENV!==`production`}catch{return!0}}function i(){try{return process.env.AVALON_VERBOSE===`1`}catch{return!1}}function a(e,t){return Date.now()-e>t}function o(e,t){if(e.size<=t)return;let n=Array.from(e.entries()).sort((e,t)=>e[1].timestamp-t[1].timestamp).slice(0,e.size-t);for(let[t]of n)e.delete(t)}export function getCachedAnalysis(e){let t=n.analysis.get(e);if(t){if(!a(t.timestamp,n.config.analysisTTL))return n.stats.analysisHits++,t.result;n.analysis.delete(e)}return n.stats.analysisMisses++,null}export function setCachedAnalysis(e,t){n.analysis.set(e,{result:t,timestamp:Date.now()}),n.stats.analysisSize=n.analysis.size,o(n.analysis,n.config.maxEntries)}export function getCachedPath(e){let t=n.paths.get(e);if(t){if(!a(t.timestamp,n.config.pathTTL))return n.stats.pathHits++,t.resolved;n.paths.delete(e)}return n.stats.pathMisses++,null}export function setCachedPath(e,t){n.paths.set(e,{resolved:t,timestamp:Date.now()}),n.stats.pathsSize=n.paths.size,o(n.paths,n.config.maxEntries)}export function getCachedFramework(e){let t=n.frameworks.get(e);if(t){if(!a(t.timestamp,n.config.frameworkTTL))return n.stats.frameworkHits++,t.framework;n.frameworks.delete(e)}return n.stats.frameworkMisses++,null}export function setCachedFramework(e,t){n.frameworks.set(e,{framework:t,timestamp:Date.now()}),n.stats.frameworksSize=n.frameworks.size,o(n.frameworks,n.config.maxEntries)}export function clearCache(){n.analysis.clear(),n.paths.clear(),n.frameworks.clear(),n.stats={...t}}export function invalidateCacheForPath(e){n.analysis.delete(e),n.paths.delete(e),n.frameworks.delete(e),n.stats.analysisSize=n.analysis.size,n.stats.pathsSize=n.paths.size,n.stats.frameworksSize=n.frameworks.size}export function configureCache(e){n.config={...n.config,...e}}export function getCacheConfig(){return{...n.config}}export function getCacheStats(){return{analysisSize:n.analysis.size,pathsSize:n.paths.size,frameworksSize:n.frameworks.size,analysisHits:n.stats.analysisHits,analysisMisses:n.stats.analysisMisses,pathHits:n.stats.pathHits,pathMisses:n.stats.pathMisses,frameworkHits:n.stats.frameworkHits,frameworkMisses:n.stats.frameworkMisses}}export function logCacheStats(){if(!r()||!i())return;let e=getCacheStats(),t=e.analysisHits+e.pathHits+e.frameworkHits,n=e.analysisMisses+e.pathMisses+e.frameworkMisses,a=t+n>0?(t/(t+n)*100).toFixed(1):`0.0`;console.log(`📊 Island Render Cache Stats:`),console.log(` Analysis: ${e.analysisSize} entries (${e.analysisHits} hits / ${e.analysisMisses} misses)`),console.log(` Paths: ${e.pathsSize} entries (${e.pathHits} hits / ${e.pathMisses} misses)`),console.log(` Frameworks: ${e.frameworksSize} entries (${e.frameworkHits} hits / ${e.frameworkMisses} misses)`),console.log(` Overall hit rate: ${a}%`)}export function _getCache(){return n}function s(e){return e.replace(/\\/g,`/`).replace(/^\//,``).replace(/\?.*$/,``).replace(/#.*$/,``)}function c(e,t){let n=s(e),r=s(t);if(n===r||n.endsWith(r)||r.endsWith(n))return!0;let i=n.split(`/`).pop(),a=r.split(`/`).pop();return!!(i&&a&&i===a)}export function invalidateCacheForFile(e){let t=0;for(let r of n.analysis.keys())c(e,r)&&(n.analysis.delete(r),t++,i()&&console.log(`🗑️ [Cache] Invalidated analysis cache for: ${r}`));for(let r of n.paths.keys())c(e,r)&&(n.paths.delete(r),t++,i()&&console.log(`🗑️ [Cache] Invalidated path cache for: ${r}`));for(let r of n.frameworks.keys())c(e,r)&&(n.frameworks.delete(r),t++,i()&&console.log(`🗑️ [Cache] Invalidated framework cache for: ${r}`));return n.stats.analysisSize=n.analysis.size,n.stats.pathsSize=n.paths.size,n.stats.frameworksSize=n.frameworks.size,t}export function isIslandComponentFile(e){let t=s(e);return t.includes(`/islands/`)||t.includes(`\\islands\\`)?!0:[`.tsx`,`.jsx`,`.vue`,`.svelte`,`.solid.tsx`,`.lit.ts`].some(e=>t.endsWith(e))}export function clearPathCacheOnStructureChange(){n.paths.clear(),n.stats.pathsSize=0,i()&&console.log(`🗑️ [Cache] Cleared path cache due to file structure change`)}export function clearIslandCache(){clearCache(),i()&&console.log(`🗑️ [Cache] Cleared all island render caches`)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
typeof globalThis<`u`&&!globalThis.__universalSSRCSS&&(globalThis.__universalSSRCSS=new Map);export function addUniversalCSS(e,t,n,r){if(!e||!e.trim())return;globalThis.__universalSSRCSS||(globalThis.__universalSSRCSS=new Map);let i=r||`${n}-${t}`,a={css:e.trim(),scopeId:i,src:t,framework:n,timestamp:Date.now()};globalThis.__universalSSRCSS.set(i,a)}export function getUniversalCSS(e=!1){if(!globalThis.__universalSSRCSS||globalThis.__universalSSRCSS.size===0)return``;let t=Array.from(globalThis.__universalSSRCSS.values());t.sort((e,t)=>e.timestamp-t.timestamp);let n=t.reduce((e,t)=>(e[t.framework]||(e[t.framework]=[]),e[t.framework].push(t),e),{}),r=[];for(let[e,t]of Object.entries(n)){let n=t.map(t=>`${`/* ${e}: ${t.src} (${t.scopeId}) */`}\n${t.css}`).join(`
|
|
2
|
+
|
|
3
|
+
`);r.push(n)}let i=r.join(`
|
|
4
|
+
|
|
5
|
+
`);return e&&globalThis.__universalSSRCSS.clear(),i}export function getUniversalCSSForHead(e=!1){let n=getUniversalCSS(e);return n.trim()?`<style data-universal-ssr="true" data-generated="${new Date().toISOString()}">\n${n}\n</style>`:``}export function clearUniversalCSS(){globalThis.__universalSSRCSS&&globalThis.__universalSSRCSS.clear()}export function getUniversalCSSStats(){if(!globalThis.__universalSSRCSS||globalThis.__universalSSRCSS.size===0)return{totalComponents:0,byFramework:{},totalCSSSize:0,averageCSSSize:0};let e=Array.from(globalThis.__universalSSRCSS.values()),t=e.reduce((e,t)=>(e[t.framework]=(e[t.framework]||0)+1,e),{}),n=e.reduce((e,t)=>e+t.css.length,0);return{totalComponents:e.length,byFramework:t,totalCSSSize:n,averageCSSSize:e.length>0?Math.round(n/e.length):0}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(){return globalThis.__universalSSRHead||(globalThis.__universalSSRHead=new Map),globalThis.__universalSSRHead}export function addUniversalHead(t,n,r,i=`other`){let a=e(),o=`${r}-${n}-${i}`;a.set(o,{content:t,src:n,framework:r,type:i})}export function getUniversalHeadForInjection(t=!1){let n=e();if(n.size===0)return``;let r=Array.from(n.values()),i=r.filter(e=>e.type===`script`),a=r.filter(e=>e.type===`meta`),o=r.filter(e=>e.type===`link`),s=r.filter(e=>e.type===`other`),c=[];a.length>0&&(c.push(`<!-- Framework Meta Tags -->`),c.push(...a.map(e=>e.content))),o.length>0&&(c.push(`<!-- Framework Links -->`),c.push(...o.map(e=>e.content))),i.length>0&&(c.push(`<!-- Framework Hydration Scripts -->`),c.push(...i.map(e=>{let t=e.content.trim();return t.startsWith(`<script`)?t:`<script>${t}<\/script>`}))),s.length>0&&(c.push(`<!-- Framework Head Content -->`),c.push(...s.map(e=>e.content)));let l=c.join(`
|
|
2
|
+
`);return t&&n.clear(),l}export function clearUniversalHead(){e().clear()}export function getHeadCollectorSize(){return e().size}
|