vue-zero-ai 1.1.3 → 1.2.0

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 CHANGED
@@ -59,6 +59,8 @@ pages/
59
59
 
60
60
  **Page titles** — Set `title: 'My Page'` and `document.title` updates on navigation.
61
61
 
62
+ **Error page** — `pages/error.vue` is auto-detected and rendered when a page fails to load (fetch or script errors).
63
+
62
64
  **Design system** — Bootstrap 5 base with Notion-inspired `base.css` tokens (colors, typography, spacing, shadows). All rem-based for consistent scaling.
63
65
 
64
66
  **CSP friendly** — Script evaluation uses Blob URL + dynamic import instead of `eval`/`new Function`. No `unsafe-eval` required.
@@ -148,6 +150,7 @@ VueZero.createApp({
148
150
  2. **Options API only** — No `<script setup>`, no Composition API, no TypeScript
149
151
  3. **No `<style scoped>`** — Use Bootstrap classes + `base.css` tokens. Use class names for isolation when needed.
150
152
  4. **404 page** — `pages/404.vue` is auto-detected. Do NOT add it to `pages.json`
153
+ 5. **Error page** — `pages/error.vue` is auto-detected. Do NOT add it to `pages.json`
151
154
 
152
155
  ## License
153
156
 
package/dist/vue-zero.js CHANGED
@@ -1,4 +1,4 @@
1
- var VueZero=(()=>{var j=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var Y=(n,e,t)=>e in n?j(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var Q=(n,e)=>{for(var t in e)j(n,t,{get:e[t],enumerable:!0})},Z=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of F(e))!J.call(n,r)&&r!==t&&j(n,r,{get:()=>e[r],enumerable:!(s=q(e,r))||s.enumerable});return n};var ee=n=>Z(j({},"__esModule",{value:!0}),n);var d=(n,e,t)=>Y(n,typeof e!="symbol"?e+"":e,t);var ie={};Q(ie,{createApp:()=>ae});var C=class{constructor(e){d(this,"pagesDir");this.pagesDir=e.replace(/\/$/,"")}async scan(){let e=`${this.pagesDir}/pages.json`;try{let t=await fetch(e);if(!t.ok)throw new Error(`${t.status}`);let s=await t.json();return s.forEach(r=>{r.endsWith(".vue")&&console.error(`[vue-zero] pages.json entry should not include ".vue" extension (got: "${r}"). Use "${r.replace(/\.vue$/,"")}"`)}),s.map(r=>this.fileToRoute(r))}catch{return console.warn(`[vue-zero] pages.json not found at ${e}. Create it: ["index", "about", ...]`),[]}}fileToRoute(e){let t=e.replace(/\.vue$/,""),r=t.split("/").map(u=>this.segmentToPath(u)),a=r[r.length-1],c;a===""?(r.pop(),c=r.length===0?"/":"/"+r.join("/")):c="/"+r.join("/");let m=t.replace(/\//g,"-").replace(/[\[\]\.]/g,"").replace(/\.\.\./g,"");return{path:c,filePath:`${this.pagesDir}/${e.endsWith(".vue")?e:e+".vue"}`,name:m}}segmentToPath(e){return e.startsWith("[...")&&e.endsWith("]")?":"+e.slice(4,-1)+"*":e.startsWith("[")&&e.endsWith("]")?":"+e.slice(1,-1):e==="index"?"":e}};var D=class{constructor(){d(this,"injected",new Map);d(this,"activePageId",null)}inject(e,t,s="component"){if(!e.trim()||this.injected.has(t))return;let r=document.createElement("style");r.setAttribute("data-vue-zero",t),r.setAttribute("data-scope",s),r.textContent=e,document.head.appendChild(r),this.injected.set(t,{el:r,scope:s})}remove(e){let t=this.injected.get(e);t&&(t.el.remove(),this.injected.delete(e))}switchPage(e){for(let[t,s]of this.injected)s.scope==="page"&&(s.el.disabled=t!==e);this.activePageId=e}clearPages(){}clear(){this.injected.forEach(e=>e.el.remove()),this.injected.clear()}};var W=new D;function B(){return W}function te(n){let e={template:"",script:"",style:""},t=/<template(\s[^>]*)?>/.exec(n);if(t){let a=t.index+t[0].length,c=/<template(\s[^>]*)?>/gi,m=/<\/template>/gi,u=1,p=a;for(;p<n.length;){c.lastIndex=p,m.lastIndex=p;let b=c.exec(n),v=m.exec(n),w=b?b.index:1/0,h=v?v.index:1/0;if(h===1/0)break;if(w<h)u++,p=w+b[0].length;else{if(u--,u===0){e.template=n.slice(a,h).trim();break}p=h+11}}}let s=/<script(\s[^>]*)?>/.exec(n);if(s){let a=s.index+s[0].length,c=n.indexOf("<\/script>",a);c!==-1&&(e.script=n.slice(a,c).trim())}let r=/<style(\s[^>]*)?>/.exec(n);if(r){let a=r.index+r[0].length,c=n.indexOf("</style>",a);c!==-1&&(e.style=n.slice(a,c).trim())}return e}async function ne(n){if(!n.trim())return{};let e=new Blob([n],{type:"text/javascript"}),t=URL.createObjectURL(e);try{return(await import(t)).default??{}}catch(s){return console.error("[vue-zero] SfcParser: script eval failed",s),{}}finally{URL.revokeObjectURL(t)}}async function S(n,e,t="component"){let s=await fetch(n);if(!s.ok)throw new Error(`[vue-zero] failed to fetch ${n} (${s.status})`);let r=await s.text(),a=te(r),c=a.template,m=a.script,u=a.style,p=await ne(m);return u&&W.inject(u,e,t),{template:c,componentOptions:p,style:u}}var L=class{constructor(e){d(this,"componentsDir");d(this,"cache",new Map);this.componentsDir=e.replace(/\/$/,"")}async readManifest(){let e=`${this.componentsDir}/components.json`;try{let t=await fetch(e);if(!t.ok)throw new Error(`${t.status}`);return await t.json()}catch{return[]}}async loadAll(e){let t={};return await Promise.all(e.map(async s=>{try{t[s]=await this.load(s)}catch{console.error(`[vue-zero] components.json\uC5D0 "${s}"\uC774 \uB4F1\uB85D\uB418\uC5B4 \uC788\uC9C0\uB9CC \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${this.componentsDir}/${s}.vue`)}})),t}async load(e){if(this.cache.has(e))return this.cache.get(e);let t=`${this.componentsDir}/${e}.vue`,{template:s,componentOptions:r}=await S(t,`component-${e}`),a={...r,name:e,template:s};return this.cache.set(e,a),a}};var E=class{constructor(e={}){d(this,"config");this.config={enabled:e.enabled??!1,loginPage:e.loginPage??"/login",tokenKey:e.tokenKey??"token"}}isEnabled(){return this.config.enabled}isAuthenticated(){try{let e=localStorage.getItem(this.config.tokenKey);if(!e)return!1;let t=JSON.parse(atob(e.split(".")[1]));return t.exp&&t.exp*1e3<Date.now()?(localStorage.removeItem(this.config.tokenKey),!1):!0}catch{return!1}}getLoginPage(){return this.config.loginPage}};function oe(n){for(let e of["pagesDir","componentsDir","layoutsDir"]){let t=n[e];t!==void 0&&t.includes("\\")&&console.error(`[vue-zero] "${e}" must use "/" as separator (got: "${t}")`)}n.auth&&!n.auth.enabled&&(n.auth.loginPage||n.auth.tokenKey)&&console.warn('[vue-zero] auth options are set but "enabled" is false \u2014 auth guard will not run')}var re=`
1
+ var VueZero=(()=>{var j=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var ee=(n,e,t)=>e in n?j(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var te=(n,e)=>{for(var t in e)j(n,t,{get:e[t],enumerable:!0})},ne=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Q(e))!Z.call(n,r)&&r!==t&&j(n,r,{get:()=>e[r],enumerable:!(s=Y(e,r))||s.enumerable});return n};var oe=n=>ne(j({},"__esModule",{value:!0}),n);var d=(n,e,t)=>ee(n,typeof e!="symbol"?e+"":e,t);var pe={};te(pe,{createApp:()=>le});var E=class{constructor(e){d(this,"pagesDir");this.pagesDir=e.replace(/\/$/,"")}async scan(){let e=`${this.pagesDir}/pages.json`;try{let t=await fetch(e);if(!t.ok)throw new Error(`${t.status}`);let s=await t.json();return s.forEach(r=>{r.endsWith(".vue")&&console.error(`[vue-zero] pages.json entry should not include ".vue" extension (got: "${r}"). Use "${r.replace(/\.vue$/,"")}"`)}),s.map(r=>this.fileToRoute(r))}catch{return console.warn(`[vue-zero] pages.json not found at ${e}. Create it: ["index", "about", ...]`),[]}}fileToRoute(e){let t=e.replace(/\.vue$/,""),r=t.split("/").map(u=>this.segmentToPath(u)),a=r[r.length-1],c;a===""?(r.pop(),c=r.length===0?"/":"/"+r.join("/")):c="/"+r.join("/");let h=t.replace(/\//g,"-").replace(/[\[\]\.]/g,"").replace(/\.\.\./g,"");return{path:c,filePath:`${this.pagesDir}/${e.endsWith(".vue")?e:e+".vue"}`,name:h}}segmentToPath(e){return e.startsWith("[...")&&e.endsWith("]")?":"+e.slice(4,-1)+"*":e.startsWith("[")&&e.endsWith("]")?":"+e.slice(1,-1):e==="index"?"":e}};var C=class{constructor(){d(this,"injected",new Map);d(this,"activePageId",null)}inject(e,t,s="component"){if(!e.trim()||this.injected.has(t))return;let r=document.createElement("style");r.setAttribute("data-vue-zero",t),r.setAttribute("data-scope",s),r.textContent=e,document.head.appendChild(r),this.injected.set(t,{el:r,scope:s})}remove(e){let t=this.injected.get(e);t&&(t.el.remove(),this.injected.delete(e))}switchPage(e){for(let[t,s]of this.injected)s.scope==="page"&&(s.el.disabled=t!==e);this.activePageId=e}clearPages(){}clear(){this.injected.forEach(e=>e.el.remove()),this.injected.clear()}};var B=new C;function K(){return B}function re(n){let e={template:"",script:"",style:""},t=/<template(\s[^>]*)?>/.exec(n);if(t){let a=t.index+t[0].length,c=/<template(\s[^>]*)?>/gi,h=/<\/template>/gi,u=1,p=a;for(;p<n.length;){c.lastIndex=p,h.lastIndex=p;let b=c.exec(n),v=h.exec(n),w=b?b.index:1/0,y=v?v.index:1/0;if(y===1/0)break;if(w<y)u++,p=w+b[0].length;else{if(u--,u===0){e.template=n.slice(a,y).trim();break}p=y+11}}}let s=/<script(\s[^>]*)?>/.exec(n);if(s){let a=s.index+s[0].length,c=n.indexOf("<\/script>",a);c!==-1&&(e.script=n.slice(a,c).trim())}let r=/<style(\s[^>]*)?>/.exec(n);if(r){let a=r.index+r[0].length,c=n.indexOf("</style>",a);c!==-1&&(e.style=n.slice(a,c).trim())}return e}async function se(n){if(!n.trim())return{};let e=new Blob([n],{type:"text/javascript"}),t=URL.createObjectURL(e);try{return(await import(t)).default??{}}catch(s){throw new Error(`[vue-zero] script eval failed: ${s.message}`)}finally{URL.revokeObjectURL(t)}}async function P(n,e,t="component"){let s=await fetch(n);if(!s.ok)throw new Error(`[vue-zero] failed to fetch ${n} (${s.status})`);let r=await s.text(),a=re(r),c=a.template,h=a.script,u=a.style,p=await se(h);return u&&B.inject(u,e,t),{template:c,componentOptions:p,style:u}}var D=class{constructor(e){d(this,"componentsDir");d(this,"cache",new Map);this.componentsDir=e.replace(/\/$/,"")}async readManifest(){let e=`${this.componentsDir}/components.json`;try{let t=await fetch(e);if(!t.ok)throw new Error(`${t.status}`);return await t.json()}catch{return[]}}async loadAll(e){let t={};return await Promise.all(e.map(async s=>{try{t[s]=await this.load(s)}catch{console.error(`[vue-zero] components.json\uC5D0 "${s}"\uC774 \uB4F1\uB85D\uB418\uC5B4 \uC788\uC9C0\uB9CC \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${this.componentsDir}/${s}.vue`)}})),t}async load(e){if(this.cache.has(e))return this.cache.get(e);let t=`${this.componentsDir}/${e}.vue`,{template:s,componentOptions:r}=await P(t,`component-${e}`),a={...r,name:e,template:s};return this.cache.set(e,a),a}};var L=class{constructor(e={}){d(this,"config");this.config={enabled:e.enabled??!1,loginPage:e.loginPage??"/login",tokenKey:e.tokenKey??"token"}}isEnabled(){return this.config.enabled}isAuthenticated(){try{let e=localStorage.getItem(this.config.tokenKey);if(!e)return!1;let t=JSON.parse(atob(e.split(".")[1]));return t.exp&&t.exp*1e3<Date.now()?(localStorage.removeItem(this.config.tokenKey),!1):!0}catch{return!1}}getLoginPage(){return this.config.loginPage}};function ae(n){for(let e of["pagesDir","componentsDir","layoutsDir"]){let t=n[e];t!==void 0&&t.includes("\\")&&console.error(`[vue-zero] "${e}" must use "/" as separator (got: "${t}")`)}n.auth&&!n.auth.enabled&&(n.auth.loginPage||n.auth.tokenKey)&&console.warn('[vue-zero] auth options are set but "enabled" is false \u2014 auth guard will not run')}var ie=`
2
2
  .vue-zero-progress {
3
3
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 99999;
4
4
  background: #42b883; transform-origin: left; transform: scaleX(0);
@@ -6,7 +6,8 @@ var VueZero=(()=>{var j=Object.defineProperty;var q=Object.getOwnPropertyDescrip
6
6
  }
7
7
  .vue-zero-progress.loading { transform: scaleX(0.8); transition: transform 8s cubic-bezier(0.1, 0.05, 0, 1); }
8
8
  .vue-zero-progress.done { transform: scaleX(1); opacity: 0; transition: transform 0.1s ease, opacity 0.4s ease 0.1s; }
9
- `;function se(){let n=document.createElement("style");n.textContent=re,document.head.appendChild(n);let e=document.createElement("div");return e.className="vue-zero-progress",document.body.appendChild(e),{start(){e.className="vue-zero-progress",e.offsetWidth,e.classList.add("loading")},done(){e.classList.remove("loading"),e.classList.add("done")}}}async function ae(n={}){oe(n);let e=(n.baseDir??"/").replace(/\/$/,""),t=e+"/"+(n.pagesDir??"pages").replace(/^\//,"").replace(/\/$/,""),s=e+"/"+(n.componentsDir??"components").replace(/^\//,"").replace(/\/$/,""),r=e+"/"+(n.layoutsDir??"layouts").replace(/^\//,"").replace(/\/$/,""),a=new E(n.auth),c=new L(s),m=new C(t),u=B(),p=se(),[b,v]=await Promise.all([c.readManifest(),m.scan()]),w=await c.loadAll(b);v.length===0&&console.warn('[vue-zero] No pages found. Create pages/pages.json: ["index", "about", ...]');let h=new Map,O=new Map,$=new Map,M=new Map,_=new Map,T=new Map,K=new Map(v.map(o=>[o.name,o]));async function P(o,i){if(h.has(o))return h.get(o);let l=await S(i,`page-${o}`,"page");return h.set(o,l),l}let U=new Set(["html","body","head","base","meta","link","style","script","noscript","template","slot","component","div","span","p","a","br","hr","img","input","button","select","option","textarea","form","label","fieldset","legend","table","thead","tbody","tfoot","tr","th","td","caption","colgroup","col","ul","ol","li","dl","dt","dd","h1","h2","h3","h4","h5","h6","header","footer","main","nav","section","article","aside","details","summary","dialog","figure","figcaption","video","audio","source","canvas","svg","iframe","embed","object","pre","code","blockquote","strong","em","small","sub","sup","mark"]);function R(o,i){if(O.has(o))return O.get(o);U.has(o)&&console.error(`[vue-zero] \uD398\uC774\uC9C0 \uD30C\uC77C\uBA85 "${o}"\uC740 HTML \uC608\uC57D \uD0DC\uADF8\uC640 \uCDA9\uB3CC\uD569\uB2C8\uB2E4. \uD30C\uC77C\uBA85\uC744 \uBCC0\uACBD\uD558\uC138\uC694.`);let l=Vue.defineComponent({...i.componentOptions,name:o,template:i.template,components:w});O.set(o,l);let g=i.componentOptions,y=g.layout;return M.set(o,y===!1?!1:y??"default"),_.set(o,g.title??null),T.set(o,g.auth!==!1),l}async function H(o){if($.has(o))return $.get(o);let i=`${r}/${o}.vue`;try{let{template:l,componentOptions:g}=await S(i,`layout-${o}`,"layout"),y=l.replace(/<slot\s*\/>/,"<router-view />").replace(/<slot><\/slot>/,"<router-view />"),f=Vue.defineComponent({...g,name:`layout-${o}`,template:y,components:w});return $.set(o,f),f}catch{return console.warn(`[vue-zero] layout "${o}.vue" not found \u2014 rendering page without layout`),$.set(o,null),null}}let z=`${t}/404.vue`,V=(await fetch(z)).ok,N=v.map(o=>({path:o.path,name:o.name,component:async()=>{let i=await P(o.name,o.filePath);return R(o.name,i)}}));V&&N.push({path:"/:pathMatch(.*)*",name:"404",component:async()=>{let o=await P("404",z);return R("404",o)}});let x=VueRouter.createRouter({history:VueRouter.createWebHistory(),routes:N,scrollBehavior(o,i,l){return l||{top:0}}}),A=Vue.shallowRef(null),I=Vue.ref("__pending__");x.beforeEach(async o=>{p.start();let i=String(o.name),l=K.get(i);try{if(l){let f=await P(l.name,l.filePath);R(i,f)}else if(i==="404"&&V){let f=await P("404",z);R("404",f)}let g=M.get(i);if(g===!1)A.value=null,I.value="__none__";else{let f=g??"default",G=await H(f);A.value=G,I.value=f}u.switchPage(`page-${i}`);let y=_.get(i);if(y&&(document.title=y),a.isEnabled()&&T.get(i)&&!a.isAuthenticated())return p.done(),a.getLoginPage()}catch(g){return console.error(`[vue-zero] \uD398\uC774\uC9C0 \uB85C\uB4DC \uC2E4\uD328: ${o.fullPath}`,g),p.done(),!1}}),x.afterEach(()=>{p.done()}),x.onError(o=>{console.error("[vue-zero] navigation error:",o)});let X=Vue.defineComponent({name:"LayoutWrapper",setup(){return{currentLayout:A,currentLayoutName:I}},template:`
10
- <component v-if="currentLayout" :is="currentLayout" :key="currentLayoutName" />
9
+ `;function ce(){let n=document.createElement("style");n.textContent=ie,document.head.appendChild(n);let e=document.createElement("div");return e.className="vue-zero-progress",document.body.appendChild(e),{start(){e.className="vue-zero-progress",e.offsetWidth,e.classList.add("loading")},done(){e.classList.remove("loading"),e.classList.add("done")}}}async function le(n={}){ae(n);let e=(n.baseDir??"/").replace(/\/$/,""),t=e+"/"+(n.pagesDir??"pages").replace(/^\//,"").replace(/\/$/,""),s=e+"/"+(n.componentsDir??"components").replace(/^\//,"").replace(/\/$/,""),r=e+"/"+(n.layoutsDir??"layouts").replace(/^\//,"").replace(/\/$/,""),a=new L(n.auth),c=new D(s),h=new E(t),u=K(),p=ce(),[b,v]=await Promise.all([c.readManifest(),h.scan()]),w=await c.loadAll(b);v.length===0&&console.warn('[vue-zero] No pages found. Create pages/pages.json: ["index", "about", ...]');let y=new Map,z=new Map,R=new Map,_=new Map,T=new Map,V=new Map,H=new Map(v.map(o=>[o.name,o]));async function x(o,i){if(y.has(o))return y.get(o);let l=await P(i,`page-${o}`,"page");return y.set(o,l),l}let X=new Set(["html","body","head","base","meta","link","style","script","noscript","template","slot","component","div","span","p","a","br","hr","img","input","button","select","option","textarea","form","label","fieldset","legend","table","thead","tbody","tfoot","tr","th","td","caption","colgroup","col","ul","ol","li","dl","dt","dd","h1","h2","h3","h4","h5","h6","header","footer","main","nav","section","article","aside","details","summary","dialog","figure","figcaption","video","audio","source","canvas","svg","iframe","embed","object","pre","code","blockquote","strong","em","small","sub","sup","mark"]);function $(o,i){if(z.has(o))return z.get(o);X.has(o)&&console.error(`[vue-zero] \uD398\uC774\uC9C0 \uD30C\uC77C\uBA85 "${o}"\uC740 HTML \uC608\uC57D \uD0DC\uADF8\uC640 \uCDA9\uB3CC\uD569\uB2C8\uB2E4. \uD30C\uC77C\uBA85\uC744 \uBCC0\uACBD\uD558\uC138\uC694.`);let l=Vue.defineComponent({...i.componentOptions,name:o,template:i.template,components:w});z.set(o,l);let f=i.componentOptions,g=f.layout;return _.set(o,g===!1?!1:g??"default"),T.set(o,f.title??null),V.set(o,f.auth!==!1),l}async function G(o){if(R.has(o))return R.get(o);let i=`${r}/${o}.vue`;try{let{template:l,componentOptions:f}=await P(i,`layout-${o}`,"layout"),g=l.replace(/<slot\s*\/>/,"<router-view />").replace(/<slot><\/slot>/,"<router-view />"),m=Vue.defineComponent({...f,name:`layout-${o}`,template:g,components:w});return R.set(o,m),m}catch{return console.warn(`[vue-zero] layout "${o}.vue" not found \u2014 rendering page without layout`),R.set(o,null),null}}let O=`${t}/404.vue`,N=(await fetch(O)).ok,W=`${t}/error.vue`,q=(await fetch(W)).ok,U=v.map(o=>({path:o.path,name:o.name,component:async()=>{let i=await x(o.name,o.filePath);return $(o.name,i)}}));N&&U.push({path:"/:pathMatch(.*)*",name:"404",component:async()=>{let o=await x("404",O);return $("404",o)}});let S=VueRouter.createRouter({history:VueRouter.createWebHistory(),routes:U,scrollBehavior(o,i,l){return l||{top:0}}}),A=Vue.shallowRef(null),I=Vue.ref("__pending__"),M=Vue.shallowRef(null);S.beforeEach(async o=>{p.start(),M.value=null;let i=String(o.name),l=H.get(i);try{if(l){let m=await x(l.name,l.filePath);$(i,m)}else if(i==="404"&&N){let m=await x("404",O);$("404",m)}let f=_.get(i);if(f===!1)A.value=null,I.value="__none__";else{let m=f??"default",J=await G(m);A.value=J,I.value=m}u.switchPage(`page-${i}`);let g=T.get(i);if(g&&(document.title=g),a.isEnabled()&&V.get(i)&&!a.isAuthenticated())return p.done(),a.getLoginPage()}catch(f){if(console.error(`[vue-zero] \uD398\uC774\uC9C0 \uB85C\uB4DC \uC2E4\uD328: ${o.fullPath}`,f),q)try{let g=await x("error",W);M.value=$("error",g)}catch(g){console.error("[vue-zero] error.vue \uB85C\uB4DC \uC2E4\uD328",g)}return p.done(),!1}}),S.afterEach(()=>{p.done()}),S.onError(o=>{console.error("[vue-zero] navigation error:",o)});let F=Vue.defineComponent({name:"LayoutWrapper",setup(){return{currentLayout:A,currentLayoutName:I,currentError:M}},template:`
10
+ <component v-if="currentError" :is="currentError" />
11
+ <component v-else-if="currentLayout" :is="currentLayout" :key="currentLayoutName" />
11
12
  <router-view v-else-if="currentLayoutName !== '__pending__'" />
12
- `}),k=Vue.createApp({template:"<LayoutWrapper />",components:{LayoutWrapper:X}});k.use(x),k.config.errorHandler=(o,i,l)=>{console.error(`[vue-zero] runtime error (${l}):`,o)},Object.entries(w).forEach(([o,i])=>{k.component(o,i)}),await x.isReady(),k.mount("#app")}return ee(ie);})();
13
+ `}),k=Vue.createApp({template:"<LayoutWrapper />",components:{LayoutWrapper:F}});k.use(S),k.config.errorHandler=(o,i,l)=>{console.error(`[vue-zero] runtime error (${l}):`,o)},Object.entries(w).forEach(([o,i])=>{k.component(o,i)}),await S.isReady().catch(()=>{}),k.mount("#app")}return oe(pe);})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-zero-ai",
3
- "version": "1.1.3",
3
+ "version": "1.2.0",
4
4
  "description": "Zero-build Vue 3 router for AI-driven development",
5
5
  "main": "dist/vue-zero.js",
6
6
  "files": [