rari 0.15.3 → 0.15.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/vite.mjs +2 -2
  2. package/package.json +8 -8
package/dist/vite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import{t as e}from"./api-routes-ChRr3O5-.mjs";import{i as t,n,o as r,r as i,t as a}from"./constants-De7aSsCq.mjs";import{a as o,c as s,d as c,g as l,h as u,i as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y}from"./regex-constants-Wm7xRA3u.mjs";import{a as b,i as ee,n as te,o as ne,r as x,t as S}from"./alias-resolver-CHTPYtdq.mjs";import{t as re}from"./http-C5Y9ZrK9.mjs";import{t as C}from"./timer-Duul5JHq.mjs";import{t as ie}from"./names-N6JRDeT1.mjs";import{builtinModules as ae,createRequire as w}from"node:module";import{Buffer as oe}from"node:buffer";import{spawn as se,spawnSync as T}from"node:child_process";import E,{promises as D}from"node:fs";import O from"node:path";import k from"node:process";import{fileURLToPath as A,pathToFileURL as j}from"node:url";import M from"node:crypto";import{build as N}from"rolldown";function ce(e){return e}function P(e){return e}function le(e={}){let{root:t=k.cwd(),srcDir:n=`src`,proxyFileName:r=`proxy`,extensions:i=[`.ts`,`.tsx`,`.js`,`.jsx`,`.mts`,`.mjs`],verbose:a=!1}=e,o=null,s=e=>{a&&console.warn(`[rari] Proxy: ${e}`)};async function c(){for(let e of i){let n=`${r}${e}`,i=O.join(t,n);try{return await D.access(i),s(`Found proxy file: ${n}`),{filePath:i,exists:!0,relativePath:n}}catch{}}let e=O.join(t,n);try{await D.access(e);for(let t of i){let i=`${r}${t}`,a=O.join(e,i);try{return await D.access(a),s(`Found proxy file: ${O.join(n,i)}`),{filePath:a,exists:!0,relativePath:O.join(n,i)}}catch{}}}catch{}return null}return P({name:`rari:proxy`,async buildStart(){o=await c(),s(o?`Proxy enabled: ${o.relativePath}`:`No proxy file found`)},configureServer(e){o&&(e.watcher.add(o.filePath),e.watcher.on(`change`,t=>{t===o?.filePath&&(s(`Proxy file changed, reloading...`),e.ws.send({type:`custom`,event:`rari:proxy-reload`}))}))},async handleHotUpdate({file:e,server:t}){if(o&&e===o.filePath)return s(`Hot reloading proxy...`),t.ws.send({type:`custom`,event:`rari:proxy-reload`,data:{file:o.relativePath}}),[]}})}const F={PAGE:`page`,LAYOUT:`layout`,LOADING:`loading`,ERROR:`error`,NOT_FOUND:`not-found`,TEMPLATE:`template`,DEFAULT:`default`,ROUTE:`route`,OG_IMAGE:`opengraph-image`,TWITTER_IMAGE:`twitter-image`,ICON:`icon`,APPLE_ICON:`apple-icon`},ue={DYNAMIC:/^\[([^\]]+)\]$/,CATCH_ALL:/^\[\.\.\.([^\]]+)\]$/,OPTIONAL_CATCH_ALL:/^\[\[\.\.\.([^\]]+)\]\]$/},de=[{pattern:ue.OPTIONAL_CATCH_ALL,type:`optional-catch-all`,format:e=>`[[...${e}]]`},{pattern:ue.CATCH_ALL,type:`catch-all`,format:e=>`[...${e}]`},{pattern:ue.DYNAMIC,type:`dynamic`,format:e=>`[${e}]`}],fe=/^\([^/]+\)$/;function pe(e){return fe.test(e)}function me(e){return e?e.replace(v,`/`).split(`/`).filter(Boolean).some(pe):!1}function he(e){for(let t of de){let n=e.match(t.pattern);if(n)return{type:t.type,param:n[1],format:t.format}}}function ge(e){let t=he(e);return t?t.format(t.param):e}function _e(e){let t=he(e);return t?{type:t.type,value:e,param:t.param}:{type:`static`,value:e}}const ve=/export\s+const\s+size\s*=\s*\{\s*width\s*:\s*(\d+)\s*,\s*height\s*:\s*(\d+)\s*[,}]/,ye=/export\s+const\s+contentType\s*=\s*['"]([^'"]+)['"]/,be=[`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`];var xe=class{appDir;extensions;verbose;constructor(e){this.appDir=O.resolve(e.appDir),this.extensions=e.extensions||[`.tsx`,`.jsx`,`.ts`,`.js`],this.verbose=e.verbose||!1}async generateManifest(){this.verbose&&console.warn(`[rari] Router: Scanning app directory: ${this.appDir}`);let e=[],t=[],n=[],r=[],i=[],a=[],o=[],s=[];await this.scanDirectory(``,e,t,n,r,i,a,o,s);for(let o of[t,n,r,i,a,s])this.finalizeGroupEntries(e,o);return this.assertNoDuplicateRoutes(e),this.assertNoDuplicateRoutes(o),this.verbose&&(console.warn(`[rari] Router: Found ${e.length} routes`),console.warn(`[rari] Router: Found ${t.length} layouts`),console.warn(`[rari] Router: Found ${n.length} loading components`),console.warn(`[rari] Router: Found ${r.length} error boundaries`),console.warn(`[rari] Router: Found ${a.length} templates`),console.warn(`[rari] Router: Found ${o.length} API routes`),console.warn(`[rari] Router: Found ${s.length} OG images`)),{routes:this.sortRoutes(e),layouts:this.sortLayouts(t),loading:n,errors:r,notFound:i,templates:this.sortTemplates(a),apiRoutes:this.sortApiRoutes(o),ogImages:s,generated:new Date().toISOString()}}finalizeGroupEntries(e,t){for(let n=t.length-1;n>=0;n--){let r=t[n],i=O.dirname(r.filePath).replace(v,`/`);if(!me(i))continue;let a=e.filter(e=>{let t=O.dirname(e.filePath).replace(v,`/`);return t===i||t.startsWith(`${i}/`)}).map(e=>e.path);if(a.length===0){t.splice(n,1);continue}let o=Array.from(new Set(a)).sort();r.path=o[0],o.length>1&&(r.additionalPaths=o.slice(1))}}assertNoDuplicateRoutes(e){let t=new Map;for(let n of e){let e=t.get(n.path);if(e)throw Error(`[rari] Route conflict: path '${n.path}' is defined by both '${e}' and '${n.filePath}'.`);t.set(n.path,n.filePath)}}async scanDirectory(e,t,n,r,i,a,o,s,c){let l=O.join(this.appDir,e),u;try{u=await D.readdir(l)}catch{return}let d=[],f=[];for(let e of u){let t=O.join(l,e),n=await D.stat(t);n.isDirectory()?this.shouldScanDirectory(e)&&f.push(e):n.isFile()&&d.push(e)}await this.processSpecialFiles(e,d,t,n,r,i,a,o,s,c);for(let l of f){let u=e?O.join(e,l):l;await this.scanDirectory(u,t,n,r,i,a,o,s,c)}}async processSpecialFiles(e,t,n,r,i,a,o,s,c,l){let u=this.pathToRoute(e),d=this.findFile(t,F.PAGE);if(d){let t=this.parseRouteSegments(e),r=this.extractParams(t);n.push({path:u,filePath:O.join(e,d).replace(v,`/`),segments:t,params:r,isDynamic:r.length>0})}let f=this.findFile(t,F.LAYOUT);if(f){let t=this.getParentPath(e);r.push({path:u,filePath:O.join(e,f).replace(v,`/`),parentPath:t===null?void 0:this.pathToRoute(t)})}let p=this.findFile(t,F.LOADING);if(p){let t=this.generateComponentId(u,`loading`);i.push({path:u,filePath:O.join(e,p).replace(v,`/`),componentId:t})}let m=this.findFile(t,F.ERROR);m&&a.push({path:u,filePath:O.join(e,m).replace(v,`/`)});let h=this.findFile(t,F.NOT_FOUND);h&&o.push({path:u,filePath:O.join(e,h).replace(v,`/`)});let g=this.findFile(t,F.TEMPLATE);if(g){let t=this.getParentPath(e);s.push({path:u,filePath:O.join(e,g).replace(v,`/`),parentPath:t===null?void 0:this.pathToRoute(t)})}let _=this.findFile(t,F.OG_IMAGE);if(_){let t=O.join(e,_).replace(v,`/`),n=O.join(this.appDir,t),r,i,a;try{let e=await D.readFile(n,`utf-8`),t=e.match(ve);t&&(r=Number.parseInt(t[1],10),i=Number.parseInt(t[2],10));let o=e.match(ye);o&&(a=o[1])}catch{}l.push({path:u,filePath:t,width:r,height:i,contentType:a})}let y=this.findFile(t,F.ROUTE);if(y){let t=await this.processApiRouteFile(e,y);c.push(t)}}findFile(e,t){for(let n of this.extensions){let r=`${t}${n}`;if(e.includes(r))return r}}pathToRoute(e){return e?`/${e.replace(v,`/`).split(`/`).filter(Boolean).filter(e=>!pe(e)).map(ge).join(`/`)}`:`/`}parseRouteSegments(e){return e?e.split(c).filter(Boolean).filter(e=>!pe(e)).map(_e):[]}extractParams(e){return e.filter(e=>e.param!==void 0).map(e=>e.param)}getParentPath(e){if(!e)return null;let t=e.split(c).filter(Boolean);return t.length===0?null:t.slice(0,-1).join(`/`)}generateComponentId(e,t){return`${t}:${e}`}shouldScanDirectory(e){return![`node_modules`,`.git`,`dist`,`build`,`__tests__`,`test`,`tests`,`coverage`].includes(e)&&!e.startsWith(`_`)&&!e.startsWith(`.`)}sortRoutes(e){return e.sort((e,t)=>{let n=e=>{if(!e.isDynamic)return 0;let t=e.segments.some(e=>e.type===`catch-all`);return e.segments.some(e=>e.type===`optional-catch-all`)?3:t?2:1},r=n(e),i=n(t);if(r!==i)return r-i;let a=e.path.split(`/`).length,o=t.path.split(`/`).length;return a===o?e.path.localeCompare(t.path):o-a})}sortApiRoutes(e){return e.sort((e,t)=>{if(!e.isDynamic&&t.isDynamic)return-1;if(e.isDynamic&&!t.isDynamic)return 1;let n=e.path.split(`/`).length,r=t.path.split(`/`).length;return n===r?e.path.localeCompare(t.path):n-r})}sortLayouts(e){return e.sort((e,t)=>e.path===`/`&&t.path!==`/`?-1:t.path===`/`&&e.path!==`/`?1:e.path.split(`/`).length-t.path.split(`/`).length)}sortTemplates(e){return e.sort((e,t)=>e.path===`/`&&t.path!==`/`?-1:t.path===`/`&&e.path!==`/`?1:e.path.split(`/`).length-t.path.split(`/`).length)}async detectHttpMethods(e){let t=O.join(this.appDir,e),n=await D.readFile(t,`utf-8`),r=[];for(let e of be){let t=RegExp(`export\\s+(?:async\\s+)?function\\s+${e}\\s*\\(`),i=RegExp(`export\\s+(?:async\\s+)?(?:const|let|var)\\s+${e}\\s*=`);(t.test(n)||i.test(n))&&r.push(e)}return r}async processApiRouteFile(e,t){let n=O.join(e,t).replace(v,`/`),r=this.pathToRoute(e),i=this.parseRouteSegments(e),a=this.extractParams(i),o=await this.detectHttpMethods(n);return{path:r,filePath:n,segments:i,params:a,isDynamic:a.length>0,methods:o}}};async function Se(e,t={}){return new xe({appDir:e,...t}).generateManifest()}const Ce=/export\s+const\s+metadata\s*(?::\s*\w+\s*)?=\s*(\{[\s\S]*?\n\})/,we=/title\s*:\s*['"]([^'"]+)['"]/,Te=/description\s*:\s*['"]([^'"]+)['"]/,Ee=/keywords\s*:\s*\[([\s\S]*?)\]/,De={appDir:`src/app`,extensions:[`.tsx`,`.jsx`,`.ts`,`.js`],outDir:`dist`};function Oe(e){switch(O.basename(e).replace(u,``)){case`page`:return`page`;case`layout`:return`layout`;case`template`:return`template`;case`loading`:return`loading`;case`error`:return`error`;case`not-found`:return`not-found`;case`route`:return`route`;default:return null}}function ke(e){return/^\([^/]+\)$/.test(e)}function Ae(e){if(!e||e===`/`)return`/`;let t=e.replace(v,`/`).split(`/`).filter(e=>!!e&&!ke(e));return t.length>0?`/${t.join(`/`)}`:`/`}function je(e,t){let n=O.relative(t,O.dirname(e));return!n||n===`.`?`/`:Ae(`/${n.replace(v,`/`).split(`/`).filter(Boolean).join(`/`)}`)}function Me(e,t,n){if(t===`page`)return[e];let r=`${e}${e===`/`?``:`/`}`,i=n.filter(t=>t===e||t.startsWith(r));return i.length>0?i:[e]}function Ne(e){try{let t=e.match(Ce);if(!t)return null;let n=t[1],r={},i=n.match(we);i&&(r.title=i[1]);let a=n.match(Te);a&&(r.description=a[1]);let o=n.match(Ee);o&&(r.keywords=o[1].split(`,`).map(e=>e.trim().replace(h,``)).filter(Boolean));for(let e of[`author`,`viewport`,`themeColor`,`robots`,`openGraph`,`twitter`]){let t=RegExp(`${e}\\s*:\\s*['"]([^'"]+)['"]`,`m`),i=n.match(t);i&&(r[e]=i[1])}return Object.keys(r).length>0?r:null}catch(e){return console.error(`[rari] Router: Failed to extract metadata:`,e),null}}function Pe(e){let t=[];for(let n of[`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`]){let r=RegExp(`export\\s+(?:async\\s+)?function\\s+${n}\\s*\\(`),i=RegExp(`export\\s+(?:async\\s+)?(?:const|let|var)\\s+${n}\\s*=`);(r.test(e)||i.test(e))&&t.push(n)}return t}async function Fe(e){try{let t=await fetch(`http://localhost:3000/_rari/hmr`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`invalidate-api-route`,filePath:e})});if(!t.ok){console.error(`[rari] Router: Failed to invalidate API route cache: ${t.statusText}`);return}let n=await t.json();n.success||console.error(`[rari] HMR: Failed to invalidate API route cache: ${n.error||`Unknown error`}`)}catch(e){console.error(`[rari] Router: Failed to notify API route invalidation:`,e)}}function Ie(e={}){let t={...De,...e},n=null,r=new Map,i=null,a=new Set,o=e=>[...e].toSorted().join(`|`),s=async e=>{let n=new Set,r=async e=>{try{let i=await D.readdir(e,{withFileTypes:!0});for(let a of i){let i=O.join(e,a.name);a.isDirectory()?await r(i):a.isFile()&&t.extensions.some(e=>a.name.endsWith(e))&&Oe(i)&&n.add(i)}}catch{}};return await r(e),n},c=async(e,r=!1)=>{let c=O.resolve(e,t.appDir);try{await D.access(c)}catch{return null}try{let l=await s(c),u=o(l);if(!r&&i===u&&n)return n;let d=await Se(c,{extensions:t.extensions}),f=JSON.stringify(d),p=O.resolve(e,t.outDir);await D.mkdir(p,{recursive:!0});let m=O.join(p,`server`);return await D.mkdir(m,{recursive:!0}),await D.writeFile(O.join(m,`routes.json`),f,`utf-8`),i=u,a.clear(),l.forEach(e=>a.add(e)),f}catch(e){return console.error(`[rari] Router: Failed to generate app routes:`,e),null}},l=e=>{let n=O.resolve(e.config.root,t.appDir);e.watcher.on(`all`,async(r,i)=>{if(i.startsWith(n)&&t.extensions.some(e=>i.endsWith(e)))try{let n=Oe(i)!==null,o=r===`add`||r===`unlink`,s=n&&!a.has(i);(o||s)&&(await c(e.config.root,!0),i.includes(t.appDir)&&e.ws.send({type:`full-reload`,path:`*`}))}catch(e){console.error(`[rari] Router: Failed to regenerate app routes:`,e)}})},u;return P({name:`rari-router`,configResolved(e){u=e.root;let t=e.logger.warn;e.logger.warn=(e,n)=>{typeof e==`string`&&e.includes(`The above dynamic import cannot be analyzed`)&&e.includes(`packages/rari/dist/`)||t(e,n)}},async writeBundle(){let e=u||k.cwd();n=await c(e,!0)},configureServer(e){l(e)},async handleHotUpdate(e){let{file:i,server:o}=e,s=O.resolve(o.config.root,t.appDir);if(i.startsWith(s)&&t.extensions.some(e=>i.endsWith(e))){let e=Oe(i);if(e){let t=r.get(i);t&&clearTimeout(t);let l=setTimeout(async()=>{r.delete(i);let t=!a.has(i),l=n;n=await c(o.config.root,t);let u=l!==n,d=je(i,s),f=[d];if(n)try{f=JSON.parse(n).routes.map(e=>e.path)}catch(e){console.error(`[rari] Router: Failed to parse manifest for affected routes:`,e)}let p=Me(d,e,f),m,h=!1,g;if(e===`page`||e===`layout`)try{let e=Ne(await D.readFile(i,`utf-8`));e&&(m=e,h=!0)}catch(e){console.error(`[rari] Router: Failed to extract metadata:`,e)}if(e===`route`)try{g=Pe(await D.readFile(i,`utf-8`)),await Fe(O.relative(s,i))}catch(e){console.error(`[rari] Router: Failed to detect HTTP methods:`,e)}let _={fileType:e,filePath:O.relative(o.config.root,i),routePath:d,affectedRoutes:p,manifestUpdated:u,timestamp:Date.now(),metadata:m,metadataChanged:h,methods:g};o.ws.send({type:`custom`,event:`rari:app-router-updated`,data:_})},200);return r.set(i,l),[]}return n=await c(o.config.root),[]}},async closeBundle(){for(let e of r.values())clearTimeout(e);r.clear();let e=u||k.cwd(),n=O.resolve(e,t.outDir,`server`),i=O.join(n,`routes.json`);try{let e=await D.readFile(i,`utf-8`),t=JSON.parse(e),r=!1;for(let e of t.routes){if(!e.isDynamic)continue;let t=e.componentId;if(!t)continue;let i=t.startsWith(`app/`)?t.slice(4):t,a=O.resolve(n,`app`,`${i}.js`);try{let t=await import(a);if(typeof t.generateStaticParams==`function`){let n=await t.generateStaticParams();Array.isArray(n)&&n.length>0&&(e.staticParams=n,r=!0)}}catch{}}r&&await D.writeFile(i,JSON.stringify(t),`utf-8`)}catch{}}})}function Le(e,t){let n=t.indexOf(`var boundCache = new WeakMap();`),r=t.indexOf(`function createBoundServerReference`,n);if(n===-1||r===-1)throw Error(`Failed to locate edge client form-action helpers for browser patch`);let i=t.slice(n,r).replace(`return {
1
+ import{t as e}from"./api-routes-ChRr3O5-.mjs";import{i as t,n,o as r,r as i,t as a}from"./constants-De7aSsCq.mjs";import{a as o,c as s,d as c,g as l,h as u,i as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y}from"./regex-constants-Wm7xRA3u.mjs";import{a as b,i as ee,n as te,o as ne,r as x,t as S}from"./alias-resolver-CHTPYtdq.mjs";import{t as re}from"./http-C5Y9ZrK9.mjs";import{t as C}from"./timer-Duul5JHq.mjs";import{t as ie}from"./names-N6JRDeT1.mjs";import{builtinModules as ae,createRequire as w}from"node:module";import{Buffer as oe}from"node:buffer";import{spawn as se,spawnSync as T}from"node:child_process";import E,{promises as D}from"node:fs";import O from"node:path";import k from"node:process";import{fileURLToPath as A,pathToFileURL as j}from"node:url";import M from"node:crypto";import{build as N}from"rolldown";function ce(e){return e}function P(e){return e}function le(e={}){let{root:t=k.cwd(),srcDir:n=`src`,proxyFileName:r=`proxy`,extensions:i=[`.ts`,`.tsx`,`.js`,`.jsx`,`.mts`,`.mjs`],verbose:a=!1}=e,o=null,s=e=>{a&&console.warn(`[rari] Proxy: ${e}`)};async function c(){for(let e of i){let n=`${r}${e}`,i=O.join(t,n);try{return await D.access(i),s(`Found proxy file: ${n}`),{filePath:i,exists:!0,relativePath:n}}catch{}}let e=O.join(t,n);try{await D.access(e);for(let t of i){let i=`${r}${t}`,a=O.join(e,i);try{return await D.access(a),s(`Found proxy file: ${O.join(n,i)}`),{filePath:a,exists:!0,relativePath:O.join(n,i)}}catch{}}}catch{}return null}return P({name:`rari:proxy`,async buildStart(){o=await c(),s(o?`Proxy enabled: ${o.relativePath}`:`No proxy file found`)},configureServer(e){o&&(e.watcher.add(o.filePath),e.watcher.on(`change`,t=>{t===o?.filePath&&(s(`Proxy file changed, reloading...`),e.ws.send({type:`custom`,event:`rari:proxy-reload`}))}))},async handleHotUpdate({file:e,server:t}){if(o&&e===o.filePath)return s(`Hot reloading proxy...`),t.ws.send({type:`custom`,event:`rari:proxy-reload`,data:{file:o.relativePath}}),[]}})}const F={PAGE:`page`,LAYOUT:`layout`,LOADING:`loading`,ERROR:`error`,NOT_FOUND:`not-found`,TEMPLATE:`template`,DEFAULT:`default`,ROUTE:`route`,OG_IMAGE:`opengraph-image`,TWITTER_IMAGE:`twitter-image`,ICON:`icon`,APPLE_ICON:`apple-icon`},ue={DYNAMIC:/^\[([^\]]+)\]$/,CATCH_ALL:/^\[\.\.\.([^\]]+)\]$/,OPTIONAL_CATCH_ALL:/^\[\[\.\.\.([^\]]+)\]\]$/},de=[{pattern:ue.OPTIONAL_CATCH_ALL,type:`optional-catch-all`,format:e=>`[[...${e}]]`},{pattern:ue.CATCH_ALL,type:`catch-all`,format:e=>`[...${e}]`},{pattern:ue.DYNAMIC,type:`dynamic`,format:e=>`[${e}]`}],fe=/^\([^/]+\)$/;function pe(e){return fe.test(e)}function me(e){return e?e.replace(v,`/`).split(`/`).filter(Boolean).some(pe):!1}function he(e){for(let t of de){let n=e.match(t.pattern);if(n)return{type:t.type,param:n[1],format:t.format}}}function ge(e){let t=he(e);return t?t.format(t.param):e}function _e(e){let t=he(e);return t?{type:t.type,value:e,param:t.param}:{type:`static`,value:e}}const ve=/export\s+const\s+size\s*=\s*\{\s*width\s*:\s*(\d+)\s*,\s*height\s*:\s*(\d+)\s*[,}]/,ye=/export\s+const\s+contentType\s*=\s*['"]([^'"]+)['"]/,be=[`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`];var xe=class{appDir;extensions;verbose;constructor(e){this.appDir=O.resolve(e.appDir),this.extensions=e.extensions||[`.tsx`,`.jsx`,`.ts`,`.js`],this.verbose=e.verbose||!1}async generateManifest(){this.verbose&&console.warn(`[rari] Router: Scanning app directory: ${this.appDir}`);let e=[],t=[],n=[],r=[],i=[],a=[],o=[],s=[];await this.scanDirectory(``,e,t,n,r,i,a,o,s);for(let o of[t,n,r,i,a,s])this.finalizeGroupEntries(e,o);return this.assertNoDuplicateRoutes(e),this.assertNoDuplicateRoutes(o),this.verbose&&(console.warn(`[rari] Router: Found ${e.length} routes`),console.warn(`[rari] Router: Found ${t.length} layouts`),console.warn(`[rari] Router: Found ${n.length} loading components`),console.warn(`[rari] Router: Found ${r.length} error boundaries`),console.warn(`[rari] Router: Found ${a.length} templates`),console.warn(`[rari] Router: Found ${o.length} API routes`),console.warn(`[rari] Router: Found ${s.length} OG images`)),{routes:this.sortRoutes(e),layouts:this.sortLayouts(t),loading:n,errors:r,notFound:i,templates:this.sortTemplates(a),apiRoutes:this.sortApiRoutes(o),ogImages:s,generated:new Date().toISOString()}}finalizeGroupEntries(e,t){for(let n=t.length-1;n>=0;n--){let r=t[n],i=O.dirname(r.filePath).replace(v,`/`);if(!me(i))continue;let a=e.filter(e=>{let t=O.dirname(e.filePath).replace(v,`/`);return t===i||t.startsWith(`${i}/`)}).map(e=>e.path);if(a.length===0){t.splice(n,1);continue}let o=Array.from(new Set(a)).sort();r.path=o[0],o.length>1&&(r.additionalPaths=o.slice(1))}}assertNoDuplicateRoutes(e){let t=new Map;for(let n of e){let e=t.get(n.path);if(e)throw Error(`[rari] Route conflict: path '${n.path}' is defined by both '${e}' and '${n.filePath}'.`);t.set(n.path,n.filePath)}}async scanDirectory(e,t,n,r,i,a,o,s,c){let l=O.join(this.appDir,e),u;try{u=await D.readdir(l)}catch{return}let d=[],f=[];for(let e of u){let t=O.join(l,e),n=await D.stat(t);n.isDirectory()?this.shouldScanDirectory(e)&&f.push(e):n.isFile()&&d.push(e)}await this.processSpecialFiles(e,d,t,n,r,i,a,o,s,c);for(let l of f){let u=e?O.join(e,l):l;await this.scanDirectory(u,t,n,r,i,a,o,s,c)}}async processSpecialFiles(e,t,n,r,i,a,o,s,c,l){let u=this.pathToRoute(e),d=this.findFile(t,F.PAGE);if(d){let t=this.parseRouteSegments(e),r=this.extractParams(t);n.push({path:u,filePath:O.join(e,d).replace(v,`/`),segments:t,params:r,isDynamic:r.length>0})}let f=this.findFile(t,F.LAYOUT);if(f){let t=this.getParentPath(e);r.push({path:u,filePath:O.join(e,f).replace(v,`/`),parentPath:t===null?void 0:this.pathToRoute(t)})}let p=this.findFile(t,F.LOADING);p&&i.push({path:u,filePath:O.join(e,p).replace(v,`/`)});let m=this.findFile(t,F.ERROR);m&&a.push({path:u,filePath:O.join(e,m).replace(v,`/`)});let h=this.findFile(t,F.NOT_FOUND);h&&o.push({path:u,filePath:O.join(e,h).replace(v,`/`)});let g=this.findFile(t,F.TEMPLATE);if(g){let t=this.getParentPath(e);s.push({path:u,filePath:O.join(e,g).replace(v,`/`),parentPath:t===null?void 0:this.pathToRoute(t)})}let _=this.findFile(t,F.OG_IMAGE);if(_){let t=O.join(e,_).replace(v,`/`),n=O.join(this.appDir,t),r,i,a;try{let e=await D.readFile(n,`utf-8`),t=e.match(ve);t&&(r=Number.parseInt(t[1],10),i=Number.parseInt(t[2],10));let o=e.match(ye);o&&(a=o[1])}catch{}l.push({path:u,filePath:t,width:r,height:i,contentType:a})}let y=this.findFile(t,F.ROUTE);if(y){let t=await this.processApiRouteFile(e,y);c.push(t)}}findFile(e,t){for(let n of this.extensions){let r=`${t}${n}`;if(e.includes(r))return r}}pathToRoute(e){return e?`/${e.replace(v,`/`).split(`/`).filter(Boolean).filter(e=>!pe(e)).map(ge).join(`/`)}`:`/`}parseRouteSegments(e){return e?e.split(c).filter(Boolean).filter(e=>!pe(e)).map(_e):[]}extractParams(e){return e.filter(e=>e.param!==void 0).map(e=>e.param)}getParentPath(e){if(!e)return null;let t=e.split(c).filter(Boolean);return t.length===0?null:t.slice(0,-1).join(`/`)}shouldScanDirectory(e){return![`node_modules`,`.git`,`dist`,`build`,`__tests__`,`test`,`tests`,`coverage`].includes(e)&&!e.startsWith(`_`)&&!e.startsWith(`.`)}sortRoutes(e){return e.sort((e,t)=>{let n=e=>{if(!e.isDynamic)return 0;let t=e.segments.some(e=>e.type===`catch-all`);return e.segments.some(e=>e.type===`optional-catch-all`)?3:t?2:1},r=n(e),i=n(t);if(r!==i)return r-i;let a=e.path.split(`/`).length,o=t.path.split(`/`).length;return a===o?e.path.localeCompare(t.path):o-a})}sortApiRoutes(e){return e.sort((e,t)=>{if(!e.isDynamic&&t.isDynamic)return-1;if(e.isDynamic&&!t.isDynamic)return 1;let n=e.path.split(`/`).length,r=t.path.split(`/`).length;return n===r?e.path.localeCompare(t.path):n-r})}sortLayouts(e){return e.sort((e,t)=>e.path===`/`&&t.path!==`/`?-1:t.path===`/`&&e.path!==`/`?1:e.path.split(`/`).length-t.path.split(`/`).length)}sortTemplates(e){return e.sort((e,t)=>e.path===`/`&&t.path!==`/`?-1:t.path===`/`&&e.path!==`/`?1:e.path.split(`/`).length-t.path.split(`/`).length)}async detectHttpMethods(e){let t=O.join(this.appDir,e),n=await D.readFile(t,`utf-8`),r=[];for(let e of be){let t=RegExp(`export\\s+(?:async\\s+)?function\\s+${e}\\s*\\(`),i=RegExp(`export\\s+(?:async\\s+)?(?:const|let|var)\\s+${e}\\s*=`);(t.test(n)||i.test(n))&&r.push(e)}return r}async processApiRouteFile(e,t){let n=O.join(e,t).replace(v,`/`),r=this.pathToRoute(e),i=this.parseRouteSegments(e),a=this.extractParams(i),o=await this.detectHttpMethods(n);return{path:r,filePath:n,segments:i,params:a,isDynamic:a.length>0,methods:o}}};async function Se(e,t={}){return new xe({appDir:e,...t}).generateManifest()}const Ce=/export\s+const\s+metadata\s*(?::\s*\w+\s*)?=\s*(\{[\s\S]*?\n\})/,we=/title\s*:\s*['"]([^'"]+)['"]/,Te=/description\s*:\s*['"]([^'"]+)['"]/,Ee=/keywords\s*:\s*\[([\s\S]*?)\]/,De={appDir:`src/app`,extensions:[`.tsx`,`.jsx`,`.ts`,`.js`],outDir:`dist`};function Oe(e){switch(O.basename(e).replace(u,``)){case`page`:return`page`;case`layout`:return`layout`;case`template`:return`template`;case`loading`:return`loading`;case`error`:return`error`;case`not-found`:return`not-found`;case`route`:return`route`;default:return null}}function ke(e){return/^\([^/]+\)$/.test(e)}function Ae(e){if(!e||e===`/`)return`/`;let t=e.replace(v,`/`).split(`/`).filter(e=>!!e&&!ke(e));return t.length>0?`/${t.join(`/`)}`:`/`}function je(e,t){let n=O.relative(t,O.dirname(e));return!n||n===`.`?`/`:Ae(`/${n.replace(v,`/`).split(`/`).filter(Boolean).join(`/`)}`)}function Me(e,t,n){if(t===`page`)return[e];let r=`${e}${e===`/`?``:`/`}`,i=n.filter(t=>t===e||t.startsWith(r));return i.length>0?i:[e]}function Ne(e){try{let t=e.match(Ce);if(!t)return null;let n=t[1],r={},i=n.match(we);i&&(r.title=i[1]);let a=n.match(Te);a&&(r.description=a[1]);let o=n.match(Ee);o&&(r.keywords=o[1].split(`,`).map(e=>e.trim().replace(h,``)).filter(Boolean));for(let e of[`author`,`viewport`,`themeColor`,`robots`,`openGraph`,`twitter`]){let t=RegExp(`${e}\\s*:\\s*['"]([^'"]+)['"]`,`m`),i=n.match(t);i&&(r[e]=i[1])}return Object.keys(r).length>0?r:null}catch(e){return console.error(`[rari] Router: Failed to extract metadata:`,e),null}}function Pe(e){let t=[];for(let n of[`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`]){let r=RegExp(`export\\s+(?:async\\s+)?function\\s+${n}\\s*\\(`),i=RegExp(`export\\s+(?:async\\s+)?(?:const|let|var)\\s+${n}\\s*=`);(r.test(e)||i.test(e))&&t.push(n)}return t}async function Fe(e){try{let t=await fetch(`http://localhost:3000/_rari/hmr`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`invalidate-api-route`,filePath:e})});if(!t.ok){console.error(`[rari] Router: Failed to invalidate API route cache: ${t.statusText}`);return}let n=await t.json();n.success||console.error(`[rari] HMR: Failed to invalidate API route cache: ${n.error||`Unknown error`}`)}catch(e){console.error(`[rari] Router: Failed to notify API route invalidation:`,e)}}function Ie(e={}){let t={...De,...e},n=null,r=new Map,i=null,a=new Set,o=e=>[...e].toSorted().join(`|`),s=async e=>{let n=new Set,r=async e=>{try{let i=await D.readdir(e,{withFileTypes:!0});for(let a of i){let i=O.join(e,a.name);a.isDirectory()?await r(i):a.isFile()&&t.extensions.some(e=>a.name.endsWith(e))&&Oe(i)&&n.add(i)}}catch{}};return await r(e),n},c=async(e,r=!1)=>{let c=O.resolve(e,t.appDir);try{await D.access(c)}catch{return null}try{let l=await s(c),u=o(l);if(!r&&i===u&&n)return n;let d=await Se(c,{extensions:t.extensions}),f=JSON.stringify(d),p=O.resolve(e,t.outDir);await D.mkdir(p,{recursive:!0});let m=O.join(p,`server`);return await D.mkdir(m,{recursive:!0}),await D.writeFile(O.join(m,`routes.json`),f,`utf-8`),i=u,a.clear(),l.forEach(e=>a.add(e)),f}catch(e){return console.error(`[rari] Router: Failed to generate app routes:`,e),null}},l=e=>{let n=O.resolve(e.config.root,t.appDir);e.watcher.on(`all`,async(r,i)=>{if(i.startsWith(n)&&t.extensions.some(e=>i.endsWith(e)))try{let n=Oe(i)!==null,o=r===`add`||r===`unlink`,s=n&&!a.has(i);(o||s)&&(await c(e.config.root,!0),i.includes(t.appDir)&&e.ws.send({type:`full-reload`,path:`*`}))}catch(e){console.error(`[rari] Router: Failed to regenerate app routes:`,e)}})},u;return P({name:`rari-router`,configResolved(e){u=e.root;let t=e.logger.warn;e.logger.warn=(e,n)=>{typeof e==`string`&&e.includes(`The above dynamic import cannot be analyzed`)&&e.includes(`packages/rari/dist/`)||t(e,n)}},async writeBundle(){let e=u||k.cwd();n=await c(e,!0)},configureServer(e){l(e)},async handleHotUpdate(e){let{file:i,server:o}=e,s=O.resolve(o.config.root,t.appDir);if(i.startsWith(s)&&t.extensions.some(e=>i.endsWith(e))){let e=Oe(i);if(e){let t=r.get(i);t&&clearTimeout(t);let l=setTimeout(async()=>{r.delete(i);let t=!a.has(i),l=n;n=await c(o.config.root,t);let u=l!==n,d=je(i,s),f=[d];if(n)try{f=JSON.parse(n).routes.map(e=>e.path)}catch(e){console.error(`[rari] Router: Failed to parse manifest for affected routes:`,e)}let p=Me(d,e,f),m,h=!1,g;if(e===`page`||e===`layout`)try{let e=Ne(await D.readFile(i,`utf-8`));e&&(m=e,h=!0)}catch(e){console.error(`[rari] Router: Failed to extract metadata:`,e)}if(e===`route`)try{g=Pe(await D.readFile(i,`utf-8`)),await Fe(O.relative(s,i))}catch(e){console.error(`[rari] Router: Failed to detect HTTP methods:`,e)}let _={fileType:e,filePath:O.relative(o.config.root,i),routePath:d,affectedRoutes:p,manifestUpdated:u,timestamp:Date.now(),metadata:m,metadataChanged:h,methods:g};o.ws.send({type:`custom`,event:`rari:app-router-updated`,data:_})},200);return r.set(i,l),[]}return n=await c(o.config.root),[]}},async closeBundle(){for(let e of r.values())clearTimeout(e);r.clear();let e=u||k.cwd(),n=O.resolve(e,t.outDir,`server`),i=O.join(n,`routes.json`);try{let e=await D.readFile(i,`utf-8`),t=JSON.parse(e),r=!1;for(let e of t.routes){if(!e.isDynamic)continue;let t=e.componentId;if(!t)continue;let i=O.join(n,`${t}.js`);try{let t=await import(i);if(typeof t.generateStaticParams==`function`){let n=await t.generateStaticParams();Array.isArray(n)&&n.length>0&&(e.staticParams=n,r=!0)}}catch{}}r&&await D.writeFile(i,JSON.stringify(t),`utf-8`)}catch{}}})}function Le(e,t){let n=t.indexOf(`var boundCache = new WeakMap();`),r=t.indexOf(`function createBoundServerReference`,n);if(n===-1||r===-1)throw Error(`Failed to locate edge client form-action helpers for browser patch`);let i=t.slice(n,r).replace(`return {
2
2
  name: referenceClosure,
3
3
  method: "POST",
4
4
  encType: "multipart/form-data",
@@ -44,7 +44,7 @@ ${e.map(e=>` { name: ${JSON.stringify(e.name)}, component: ${e.binding}, id: ${
44
44
  `)},
45
45
  ])
46
46
  `}function Tt(e,t){return{componentsDir:t?.componentsDir??`src/components`,contentDirs:t?.contentDirs??[`public/content`,`content`]}}function Et(e,t,n){let r=O.join(e,t),i=new Set(n);return E.existsSync(r)&&i.add(r),[...i]}const Dt=/import\s*\(\s*["']([^"']+)["']\s*\)|import\s+["']([^"']+)["']/g,Ot=/<script\b[^>]*>/gi;function kt(e,t,n){n?.startsWith(`/src/`)&&e.add(J(O.join(t,n.slice(1))))}function At(e){return/\btype\s*=\s*["']module["']/i.test(e)?e.match(/\bsrc\s*=\s*["']([^"']+)["']/i)?.[1]??null:null}function jt(e){let t=new Set,n=O.join(e,`index.html`);if(!E.existsSync(n))return t;try{let r=E.readFileSync(n,`utf-8`);for(let n of r.matchAll(Dt))kt(t,e,n[1]||n[2]);for(let n of r.matchAll(Ot))kt(t,e,At(n[0]))}catch{}return t}let Y;async function Mt(){if(Y!==void 0)return Y;try{return Y=(await import(`@rari/use-cache`)).transformUseCacheModule??null,Y}catch{return Y=null,null}}const Nt=/import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g,Pt=/import\s+(?:(\w+)|\{([^}]+)\})\s+from\s+['"]([^'"]+)['"];?\s*$/gm,Ft=/^proxy\.(?:tsx?|jsx?|mts|mjs)$/,It=/\/components\/(\w+)(?:\.tsx?|\.jsx?)?$/,Lt=/[/\\]components[/\\](\w+)(?:\.tsx?|\.jsx?)?$/,Rt=/^(?:robots|sitemap|feed)\.(?:tsx?|jsx?)$/,zt=`react-server-dom-rari/server`,Bt=/^node:/,Vt=`[hash]_[local]`;function Ht(e){if(e.startsWith(`@`)){let t=e.split(`/`);return t.length>=2?`${t[0]}/${t[1]}`:e}return e.split(`/`)[0]??e}function Ut(e,t){let n=Ht(t),r=e;for(;;){let e=O.join(r,`node_modules`,...n.split(`/`));if(E.existsSync(O.join(e,`package.json`)))return!0;let t=O.dirname(r);if(t===r)return!1;r=t}}const Wt=[{componentId:`rari/image`,devSourceSegments:[`src`,`image`,`image.tsx`],publishedExport:`rari/image`,exports:[`Image`]}],Gt=O.dirname(A(import.meta.url)),X=O.dirname(Gt);function Kt(e){return e.startsWith(X)}function qt(e,t){return Kt(e)?O.join(X,`src`):O.join(t,`src`)}function Jt(){let e=O.join(X,`src`,`runtime`,`boundaries`,`error-boundary-wrapper.tsx`);if(E.existsSync(e))return e;try{let e=A(import.meta.resolve(`rari/runtime/ErrorBoundaryWrapper`));if(E.existsSync(e))return e}catch{}return null}function Yt(e){let t=e.replace(v,`/`);return t.includes(`ErrorBoundaryWrapper`)||t.includes(`/boundaries/error-boundary-wrapper`)||t.endsWith(`/error-boundary-wrapper.tsx`)}function Xt(e,t){if(Yt(e))return`virtual:error-boundary-wrapper.tsx`;let n=O.relative(t,e).replace(v,`/`);return n.startsWith(`..`)||O.isAbsolute(n)?e.replace(v,`/`):n}function Zt(e,t){if(Yt(e))return`error_boundary_wrapper_${I(`virtual:error-boundary-wrapper.tsx`)}`;if(Kt(e)){let t=O.relative(X,e).replace(v,`/`);return`${ze(t)}_${I(t)}`}return R(e,t)}let Qt=null;async function $t(){return Qt||=(await import(`lightningcss`)).transform,Qt}function Z(e,t,n,r){return e.includes(`node_modules`)||n.has(r??J(e))?!1:!t.directives.hasUseClient&&!t.directives.hasUseServer}var en=class{serverComponents=new Map;serverActions=new Map;options;projectRoot;buildCache=new Map;useCacheBuildId=null;htmlOnlyImports=new Set;fileImporters=new Map;moduleAnalysisCache;discoveredExternalClientComponents=new Set;clientComponentFiles=new Map;recordClientComponent(e,t){this.clientComponentFiles.set(e,t)}getClientComponentFiles(){return[...this.clientComponentFiles.entries()].map(([e,t])=>({filePath:e,code:t}))}getClientComponentPaths(){return[...this.clientComponentFiles.keys()]}getModuleAnalysisCache(){return this.moduleAnalysisCache}clearClientComponentFiles(){this.clientComponentFiles.clear()}getComponentCount(){return this.serverComponents.size+this.serverActions.size}hasComponent(e){return this.serverComponents.has(e)||this.serverActions.has(e)}removeComponent(e){this.serverComponents.delete(e),this.serverActions.delete(e),this.moduleAnalysisCache.invalidate(e)}getImportGraph(){let e=new Map;for(let[t,n]of this.fileImporters)e.set(t,new Set(n));return e}getHtmlOnlyImports(){return new Set(this.htmlOnlyImports)}async writeComponentCssAsset(e,t){if(t.length===0)return[];let n=O.join(this.options.outDir,`assets`,`server`);await E.promises.mkdir(n,{recursive:!0});let r=`${t.join(`
47
- `)}\n`,i=`${I(e+r,12)}.css`,a=O.join(n,i);return await E.promises.writeFile(a,r,`utf-8`),[`/assets/server/${i}`]}getComponentIdFromRouteManifestPath(e){return this.getComponentId(O.join(this.projectRoot,`src`,`app`,e))}getComponentReferenceId(e){return this.getReadableComponentId(this.getProjectRelativePath(e))}async writeRouteCssEntries(e){let t=O.join(this.options.outDir,this.options.rscDir,`routes.json`);if(!E.existsSync(t))return;let n=await E.promises.readFile(t,`utf-8`),r=JSON.parse(n),i=t=>{if(t)for(let n of t){if(!n.filePath)continue;let t=this.getComponentIdFromRouteManifestPath(n.filePath);n.componentId=t;let r=e.components[t]?.css??[];r.length?n.css=r:delete n.css}};if(i(r.routes),i(r.layouts),i(r.loading),i(r.errors),i(r.notFound),r.apiRoutes)for(let e of r.apiRoutes)e.filePath&&(e.componentId=this.getComponentIdFromRouteManifestPath(e.filePath));await E.promises.writeFile(t,JSON.stringify(r),`utf-8`)}constructor(e,t={}){this.projectRoot=e,this.moduleAnalysisCache=t.moduleAnalysisCache??new mt;let n=t.rscDir||`server`;this.options={outDir:t.outDir||O.join(e,`dist`),rscDir:n,manifestPath:t.manifestPath||O.join(n,`manifest.json`),serverConfigPath:t.serverConfigPath||O.join(n,`config.json`),minify:t.minify??k.env.NODE_ENV===`production`,alias:t.alias||{},define:t.define,csp:t.csp,cacheControl:t.cacheControl,experimental:t.experimental,mdx:t.mdx},this.parseHtmlImports()}parseHtmlImports(){for(let e of jt(this.projectRoot))this.htmlOnlyImports.add(e)}getModuleAnalysis(e,t){return this.moduleAnalysisCache.get(e,t)}isServerComponent(e,t){try{return Z(e,this.moduleAnalysisCache.get(e,t),this.htmlOnlyImports)}catch{return!1}}isClientComponent(e,t){try{return this.moduleAnalysisCache.get(e,t).directives.hasUseClient}catch{return!1}}resolveImportedFilePath(e,t){let n=null;if(t.startsWith(`./`)||t.startsWith(`../`)){let r=O.dirname(e);n=O.resolve(r,t)}else if(n=S(t,this.options.alias,this.projectRoot),!n&&t.startsWith(`@/`)){let e=t.slice(2);n=O.join(this.projectRoot,`src`,e)}return n?ne(n,[``,`.ts`,`.tsx`,`.js`,`.jsx`]):null}populateImportGraphFromFiles(e){this.fileImporters.clear();for(let{filePath:t,analysis:n}of e)for(let e of dt(n.importSources)){let n=this.resolveImportedFilePath(t,e);n&&(this.fileImporters.has(n)||this.fileImporters.set(n,new Set),this.fileImporters.get(n).add(t))}}buildImportGraph(e){let t=tn(this,[e]);this.populateImportGraphFromFiles(t)}isOnlyImportedByClientComponents(e){let t=this.fileImporters.get(e);if(!t||t.size===0)return!1;for(let e of t)if(!this.isClientComponent(e)&&!this.isOnlyImportedByClientComponents(e))return!1;return!0}addServerComponent(e,t,n){let r=t??E.readFileSync(e,`utf-8`),i=n??this.moduleAnalysisCache.get(e,r),a=ut(i.importSources),o=lt(i);if(i.directives.hasUseServer){this.serverActions.set(e,{filePath:e,originalCode:r,dependencies:a,hasNodeImports:o});return}Z(e,i,this.htmlOnlyImports)&&this.serverComponents.set(e,{filePath:e,originalCode:r,dependencies:a,hasNodeImports:o})}isServerAction(e,t){return t?this.moduleAnalysisCache.get(t,e).directives.hasUseServer:K(e).directives.hasUseServer}extractDependencies(e,t){return ut((t?this.moduleAnalysisCache.get(t,e):K(e)).importSources)}hasNodeImports(e,t){return lt(t?this.moduleAnalysisCache.get(t,e):K(e))}async getTransformedComponentsForDevelopment(){let e=[];for(let[t]of this.serverComponents){let n=O.relative(this.projectRoot,t),r=this.getComponentId(n),i=await this.buildComponentCodeOnly(t);e.push({id:r,code:i,isAction:!1})}for(let[t]of this.serverActions){let n=O.relative(this.projectRoot,t),r=this.getComponentId(n),i=await this.buildComponentCodeOnly(t);e.push({id:r,code:i,isAction:!0})}return e}transformComponentImportsToGlobal(e){let t=[];for(let n of e.matchAll(Nt)){let[e,r,i]=n;if(!i.startsWith(`.`)&&!i.startsWith(`@`)&&!i.startsWith(`~`)&&!i.startsWith(`#`))continue;let a=null;if(i.startsWith(`.`)){if(i.includes(`/components/`)){let n=i.match(It);if(n){let i=n[1],a=[O.resolve(this.projectRoot,`src`,`components`,`${i}.tsx`),O.resolve(this.projectRoot,`src`,`components`,`${i}.ts`),O.resolve(this.projectRoot,`src`,`components`,`${i}.jsx`),O.resolve(this.projectRoot,`src`,`components`,`${i}.js`)],o=!1;for(let e of a)if(E.existsSync(e)&&this.isClientComponent(e)){o=!0;break}if(!o)continue;let s=`// Component reference: ${i}
47
+ `)}\n`,i=`${I(e+r,12)}.css`,a=O.join(n,i);return await E.promises.writeFile(a,r,`utf-8`),[`/assets/server/${i}`]}getComponentIdFromRouteManifestPath(e){return this.getComponentId(O.join(this.projectRoot,`src`,`app`,e))}getComponentReferenceId(e){return this.getReadableComponentId(this.getProjectRelativePath(e))}async writeRouteCssEntries(e){let t=O.join(this.options.outDir,this.options.rscDir,`routes.json`);if(!E.existsSync(t))return;let n=await E.promises.readFile(t,`utf-8`),r=JSON.parse(n),i=t=>{if(t)for(let n of t){if(!n.filePath)continue;let t=this.getComponentIdFromRouteManifestPath(n.filePath);n.componentId=t;let r=e.components[t]?.css??[];r.length?n.css=r:delete n.css}};if(i(r.routes),i(r.layouts),i(r.loading),i(r.errors),i(r.notFound),i(r.templates),r.apiRoutes)for(let e of r.apiRoutes)e.filePath&&(e.componentId=this.getComponentIdFromRouteManifestPath(e.filePath));await E.promises.writeFile(t,JSON.stringify(r),`utf-8`)}constructor(e,t={}){this.projectRoot=e,this.moduleAnalysisCache=t.moduleAnalysisCache??new mt;let n=t.rscDir||`server`;this.options={outDir:t.outDir||O.join(e,`dist`),rscDir:n,manifestPath:t.manifestPath||O.join(n,`manifest.json`),serverConfigPath:t.serverConfigPath||O.join(n,`config.json`),minify:t.minify??k.env.NODE_ENV===`production`,alias:t.alias||{},define:t.define,csp:t.csp,cacheControl:t.cacheControl,experimental:t.experimental,mdx:t.mdx},this.parseHtmlImports()}parseHtmlImports(){for(let e of jt(this.projectRoot))this.htmlOnlyImports.add(e)}getModuleAnalysis(e,t){return this.moduleAnalysisCache.get(e,t)}isServerComponent(e,t){try{return Z(e,this.moduleAnalysisCache.get(e,t),this.htmlOnlyImports)}catch{return!1}}isClientComponent(e,t){try{return this.moduleAnalysisCache.get(e,t).directives.hasUseClient}catch{return!1}}resolveImportedFilePath(e,t){let n=null;if(t.startsWith(`./`)||t.startsWith(`../`)){let r=O.dirname(e);n=O.resolve(r,t)}else if(n=S(t,this.options.alias,this.projectRoot),!n&&t.startsWith(`@/`)){let e=t.slice(2);n=O.join(this.projectRoot,`src`,e)}return n?ne(n,[``,`.ts`,`.tsx`,`.js`,`.jsx`]):null}populateImportGraphFromFiles(e){this.fileImporters.clear();for(let{filePath:t,analysis:n}of e)for(let e of dt(n.importSources)){let n=this.resolveImportedFilePath(t,e);n&&(this.fileImporters.has(n)||this.fileImporters.set(n,new Set),this.fileImporters.get(n).add(t))}}buildImportGraph(e){let t=tn(this,[e]);this.populateImportGraphFromFiles(t)}isOnlyImportedByClientComponents(e){let t=this.fileImporters.get(e);if(!t||t.size===0)return!1;for(let e of t)if(!this.isClientComponent(e)&&!this.isOnlyImportedByClientComponents(e))return!1;return!0}addServerComponent(e,t,n){let r=t??E.readFileSync(e,`utf-8`),i=n??this.moduleAnalysisCache.get(e,r),a=ut(i.importSources),o=lt(i);if(i.directives.hasUseServer){this.serverActions.set(e,{filePath:e,originalCode:r,dependencies:a,hasNodeImports:o});return}Z(e,i,this.htmlOnlyImports)&&this.serverComponents.set(e,{filePath:e,originalCode:r,dependencies:a,hasNodeImports:o})}isServerAction(e,t){return t?this.moduleAnalysisCache.get(t,e).directives.hasUseServer:K(e).directives.hasUseServer}extractDependencies(e,t){return ut((t?this.moduleAnalysisCache.get(t,e):K(e)).importSources)}hasNodeImports(e,t){return lt(t?this.moduleAnalysisCache.get(t,e):K(e))}async getTransformedComponentsForDevelopment(){let e=[];for(let[t]of this.serverComponents){let n=O.relative(this.projectRoot,t),r=this.getComponentId(n),i=await this.buildComponentCodeOnly(t);e.push({id:r,code:i,isAction:!1})}for(let[t]of this.serverActions){let n=O.relative(this.projectRoot,t),r=this.getComponentId(n),i=await this.buildComponentCodeOnly(t);e.push({id:r,code:i,isAction:!0})}return e}transformComponentImportsToGlobal(e){let t=[];for(let n of e.matchAll(Nt)){let[e,r,i]=n;if(!i.startsWith(`.`)&&!i.startsWith(`@`)&&!i.startsWith(`~`)&&!i.startsWith(`#`))continue;let a=null;if(i.startsWith(`.`)){if(i.includes(`/components/`)){let n=i.match(It);if(n){let i=n[1],a=[O.resolve(this.projectRoot,`src`,`components`,`${i}.tsx`),O.resolve(this.projectRoot,`src`,`components`,`${i}.ts`),O.resolve(this.projectRoot,`src`,`components`,`${i}.jsx`),O.resolve(this.projectRoot,`src`,`components`,`${i}.js`)],o=!1;for(let e of a)if(E.existsSync(e)&&this.isClientComponent(e)){o=!0;break}if(!o)continue;let s=`// Component reference: ${i}
48
48
  const ${r} = (props) => {
49
49
  let Component = globalThis['~clientComponents']?.['components/${i}']?.component
50
50
  || globalThis['components/${i}'];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rari",
3
3
  "type": "module",
4
- "version": "0.15.3",
4
+ "version": "0.15.4",
5
5
  "description": "Runtime Accelerated Rendering Infrastructure (rari)",
6
6
  "author": "Ryan Skinner",
7
7
  "license": "MIT",
@@ -145,13 +145,13 @@
145
145
  "rolldown": "^1.1.5"
146
146
  },
147
147
  "optionalDependencies": {
148
- "@rari/use-cache": "0.15.3",
149
- "rari-darwin-arm64": "0.15.3",
150
- "rari-darwin-x64": "0.15.3",
151
- "rari-linux-arm64": "0.15.3",
152
- "rari-linux-x64": "0.15.3",
153
- "rari-win32-arm64": "0.15.3",
154
- "rari-win32-x64": "0.15.3"
148
+ "@rari/use-cache": "0.15.4",
149
+ "rari-darwin-arm64": "0.15.4",
150
+ "rari-darwin-x64": "0.15.4",
151
+ "rari-linux-arm64": "0.15.4",
152
+ "rari-linux-x64": "0.15.4",
153
+ "rari-win32-arm64": "0.15.4",
154
+ "rari-win32-x64": "0.15.4"
155
155
  },
156
156
  "devDependencies": {
157
157
  "@mdx-js/mdx": "^3.1.1",