vue-zero-ai 1.2.1 → 1.3.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
@@ -51,7 +51,7 @@ pages/
51
51
 
52
52
  **File-based routing** — Nuxt-style dynamic routes, catch-all routes, nested routes.
53
53
 
54
- **Auto components** — Put `.vue` files in `components/` and list them in `components/components.json`. They're globally available in all pages.
54
+ **Auto components** — Put `.vue` files in `components/` and list them in `components/components.json`. They're globally available in all pages and are loaded lazily — only the components a page (or layout) actually uses are fetched when that page opens.
55
55
 
56
56
  **Layouts** — `layouts/default.vue` wraps all pages. Use `layout: 'admin'` or `layout: false` per page.
57
57
 
package/dist/vue-zero.js CHANGED
@@ -1,4 +1,4 @@
1
- var VueZero=(()=>{var E=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var ee=(n,e,t)=>e in n?E(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var te=(n,e)=>{for(var t in e)E(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&&E(n,r,{get:()=>e[r],enumerable:!(s=Y(e,r))||s.enumerable});return n};var oe=n=>ne(E({},"__esModule",{value:!0}),n);var f=(n,e,t)=>ee(n,typeof e!="symbol"?e+"":e,t);var ue={};te(ue,{createApp:()=>pe});var j=class{constructor(e){f(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 C=class{constructor(){f(this,"injected",new Map);f(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,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,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,m=a.script,u=a.style,p=await se(m);return u&&B.inject(u,e,t),{template:c,componentOptions:p,style:u}}var D=class{constructor(e){f(this,"componentsDir");f(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}};function ae(n){let e=n.replace(/-/g,"+").replace(/_/g,"/"),t=e.padEnd(e.length+(4-e.length%4)%4,"="),s=atob(t),r=new Uint8Array(s.length);for(let a=0;a<s.length;a++)r[a]=s.charCodeAt(a);return new TextDecoder().decode(r)}var L=class{constructor(e={}){f(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(ae(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 ie(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 ce=`
1
+ var VueZero=(()=>{var C=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var ee=Object.prototype.hasOwnProperty;var te=(n,e,t)=>e in n?C(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var ne=(n,e)=>{for(var t in e)C(n,t,{get:e[t],enumerable:!0})},oe=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Q(e))!ee.call(n,s)&&s!==t&&C(n,s,{get:()=>e[s],enumerable:!(o=Z(e,s))||o.enumerable});return n};var re=n=>oe(C({},"__esModule",{value:!0}),n);var u=(n,e,t)=>te(n,typeof e!="symbol"?e+"":e,t);var ge={};ne(ge,{createApp:()=>ue});var E=class{constructor(e){u(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 o=await t.json();return o.forEach(s=>{s.endsWith(".vue")&&console.error(`[vue-zero] pages.json entry should not include ".vue" extension (got: "${s}"). Use "${s.replace(/\.vue$/,"")}"`)}),o.map(s=>this.fileToRoute(s))}catch{return console.warn(`[vue-zero] pages.json not found at ${e}. Create it: ["index", "about", ...]`),[]}}fileToRoute(e){let t=e.replace(/\.vue$/,""),s=t.split("/").map(g=>this.segmentToPath(g)),a=s[s.length-1],c;a===""?(s.pop(),c=s.length===0?"/":"/"+s.join("/")):c="/"+s.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(){u(this,"injected",new Map);u(this,"activePageId",null)}inject(e,t,o="component"){if(!e.trim()||this.injected.has(t))return;let s=document.createElement("style");s.setAttribute("data-vue-zero",t),s.setAttribute("data-scope",o),s.textContent=e,document.head.appendChild(s),this.injected.set(t,{el:s,scope:o})}remove(e){let t=this.injected.get(e);t&&(t.el.remove(),this.injected.delete(e))}switchPage(e){for(let[t,o]of this.injected)o.scope==="page"&&(o.el.disabled=t!==e);this.activePageId=e}clearPages(){}clear(){this.injected.forEach(e=>e.el.remove()),this.injected.clear()}};var K=new D;function H(){return K}function se(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,g=1,p=a;for(;p<n.length;){c.lastIndex=p,m.lastIndex=p;let y=c.exec(n),w=m.exec(n),b=y?y.index:1/0,v=w?w.index:1/0;if(v===1/0)break;if(b<v)g++,p=b+y[0].length;else{if(g--,g===0){e.template=n.slice(a,v).trim();break}p=v+11}}}let o=/<script(\s[^>]*)?>/.exec(n);if(o){let a=o.index+o[0].length,c=n.indexOf("<\/script>",a);c!==-1&&(e.script=n.slice(a,c).trim())}let s=/<style(\s[^>]*)?>/.exec(n);if(s){let a=s.index+s[0].length,c=n.indexOf("</style>",a);c!==-1&&(e.style=n.slice(a,c).trim())}return e}async function ae(n){if(!n.trim())return{};let e=new Blob([n],{type:"text/javascript"}),t=URL.createObjectURL(e);try{return(await import(t)).default??{}}catch(o){throw new Error(`[vue-zero] script eval failed: ${o.message}`)}finally{URL.revokeObjectURL(t)}}async function R(n,e,t="component"){let o=await fetch(n);if(!o.ok)throw new Error(`[vue-zero] failed to fetch ${n} (${o.status})`);let s=await o.text(),a=se(s),c=a.template,m=a.script,g=a.style,p=await ae(m);return g&&K.inject(g,e,t),{template:c,componentOptions:p,style:g}}var j=class{constructor(e){u(this,"componentsDir");u(this,"cache",new Map);u(this,"inflight",new Map);u(this,"lookup",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[]}}createAsyncComponents(e){let t={};for(let o of e)this.lookup.set(o.replace(/-/g,"").toLowerCase(),o),t[o]=Vue.defineAsyncComponent(async()=>(await this.preloadDeep(o,new Set),this.cache.get(o)));return t}async preload(e){let t=new Set;await Promise.allSettled(this.findUsed(e).map(o=>this.preloadDeep(o,t)))}findUsed(e){let t=new Set,o=/<([A-Za-z][\w-]*)/g,s;for(;(s=o.exec(e))!==null;){let a=this.lookup.get(s[1].replace(/-/g,"").toLowerCase());a&&t.add(a)}return[...t]}async preloadDeep(e,t){if(t.has(e))return;t.add(e);let o=await this.load(e),s=this.findUsed(String(o.template??""));await Promise.all(s.map(a=>this.preloadDeep(a,t)))}load(e){let t=this.cache.get(e);if(t)return Promise.resolve(t);let o=this.inflight.get(e);return o||(o=this.fetchOne(e).finally(()=>this.inflight.delete(e)),this.inflight.set(e,o)),o}async fetchOne(e){let t=`${this.componentsDir}/${e}.vue`;try{let{template:o,componentOptions:s}=await R(t,`component-${e}`),a={...s,name:e,template:o};return this.cache.set(e,a),a}catch(o){throw console.error(`[vue-zero] \uCEF4\uD3EC\uB10C\uD2B8 "${e}" \uB85C\uB4DC \uC2E4\uD328 (${t}):`,o),o}}};function ie(n){let e=n.replace(/-/g,"+").replace(/_/g,"/"),t=e.padEnd(e.length+(4-e.length%4)%4,"="),o=atob(t),s=new Uint8Array(o.length);for(let a=0;a<o.length;a++)s[a]=o.charCodeAt(a);return new TextDecoder().decode(s)}var L=class{constructor(e={}){u(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(ie(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 ce(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 le=`
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,8 +6,8 @@ var VueZero=(()=>{var E=Object.defineProperty;var Y=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 le(){let n=document.createElement("style");n.textContent=ce,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 pe(n={}){ie(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),m=new j(t),u=K(),p=le(),[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 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 d=i.componentOptions,g=d.layout;return _.set(o,g===!1?!1:g??"default"),T.set(o,d.title??null),V.set(o,d.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:d}=await P(i,`layout-${o}`,"layout"),g=l.replace(/<slot\s*\/>/,"<router-view />").replace(/<slot><\/slot>/,"<router-view />"),h=Vue.defineComponent({...d,name:`layout-${o}`,template:g,components:w});return R.set(o,h),h}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 h=await x(l.name,l.filePath);$(i,h)}else if(i==="404"&&N){let h=await x("404",O);$("404",h)}let d=_.get(i);if(d===!1)A.value=null,I.value="__none__";else{let h=d??"default",J=await G(h);A.value=J,I.value=h}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(d){if(console.error(`[vue-zero] \uD398\uC774\uC9C0 \uB85C\uB4DC \uC2E4\uD328: ${o.fullPath}`,d),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:`
9
+ `;function pe(){let n=document.createElement("style");n.textContent=le,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 ue(n={}){ce(n);let e=(n.baseDir??"/").replace(/\/$/,""),t=e+"/"+(n.pagesDir??"pages").replace(/^\//,"").replace(/\/$/,""),o=e+"/"+(n.componentsDir??"components").replace(/^\//,"").replace(/\/$/,""),s=e+"/"+(n.layoutsDir??"layouts").replace(/^\//,"").replace(/\/$/,""),a=new L(n.auth),c=new j(o),m=new E(t),g=H(),p=pe(),y=`${t}/404.vue`,w=`${t}/error.vue`,b=r=>fetch(r).then(i=>i.ok,()=>!1),[v,O,T,X]=await Promise.all([c.readManifest(),m.scan(),b(y),b(w)]),z=c.createAsyncComponents(v);O.length===0&&console.warn('[vue-zero] No pages found. Create pages/pages.json: ["index", "about", ...]');let A=new Map,M=new Map,k=new Map,U=new Map,N=new Map,W=new Map,G=new Map(O.map(r=>[r.name,r]));async function x(r,i){if(A.has(r))return A.get(r);let l=await R(i,`page-${r}`,"page");return await c.preload(l.template),A.set(r,l),l}let q=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 S(r,i){if(M.has(r))return M.get(r);q.has(r)&&console.error(`[vue-zero] \uD398\uC774\uC9C0 \uD30C\uC77C\uBA85 "${r}"\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:r,template:i.template,components:z});M.set(r,l);let f=i.componentOptions,d=f.layout;return U.set(r,d===!1?!1:d??"default"),N.set(r,f.title??null),W.set(r,f.auth!==!1),l}async function F(r){if(k.has(r))return k.get(r);let i=`${s}/${r}.vue`;try{let{template:l,componentOptions:f}=await R(i,`layout-${r}`,"layout");await c.preload(l);let d=l.replace(/<slot\s*\/>/,"<router-view />").replace(/<slot><\/slot>/,"<router-view />"),h=Vue.defineComponent({...f,name:`layout-${r}`,template:d,components:z});return k.set(r,h),h}catch{return console.warn(`[vue-zero] layout "${r}.vue" not found \u2014 rendering page without layout`),k.set(r,null),null}}let B=O.map(r=>({path:r.path,name:r.name,component:async()=>{let i=await x(r.name,r.filePath);return S(r.name,i)}}));T&&B.push({path:"/:pathMatch(.*)*",name:"404",component:async()=>{let r=await x("404",y);return S("404",r)}});let P=VueRouter.createRouter({history:VueRouter.createWebHistory(),routes:B,scrollBehavior(r,i,l){return l||{top:0}}}),I=Vue.shallowRef(null),V=Vue.ref("__pending__"),_=Vue.shallowRef(null);P.beforeEach(async r=>{p.start(),_.value=null;let i=String(r.name),l=G.get(i);try{if(l){let h=await x(l.name,l.filePath);S(i,h)}else if(i==="404"&&T){let h=await x("404",y);S("404",h)}let f=U.get(i);if(f===!1)I.value=null,V.value="__none__";else{let h=f??"default",Y=await F(h);I.value=Y,V.value=h}g.switchPage(`page-${i}`);let d=N.get(i);if(d&&(document.title=d),a.isEnabled()&&W.get(i)&&!a.isAuthenticated())return p.done(),a.getLoginPage()}catch(f){if(console.error(`[vue-zero] \uD398\uC774\uC9C0 \uB85C\uB4DC \uC2E4\uD328: ${r.fullPath}`,f),X)try{let d=await x("error",w);_.value=S("error",d)}catch(d){console.error("[vue-zero] error.vue \uB85C\uB4DC \uC2E4\uD328",d)}return p.done(),!1}}),P.afterEach(()=>{p.done()}),P.onError(r=>{console.error("[vue-zero] navigation error:",r)});let J=Vue.defineComponent({name:"LayoutWrapper",setup(){return{currentLayout:I,currentLayoutName:V,currentError:_}},template:`
10
10
  <component v-if="currentError" :is="currentError" />
11
11
  <component v-else-if="currentLayout" :is="currentLayout" :key="currentLayoutName" />
12
12
  <router-view v-else-if="currentLayoutName !== '__pending__'" />
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(ue);})();
13
+ `}),$=Vue.createApp({template:"<LayoutWrapper />",components:{LayoutWrapper:J}});$.use(P),$.config.errorHandler=(r,i,l)=>{console.error(`[vue-zero] runtime error (${l}):`,r)},Object.entries(z).forEach(([r,i])=>{$.component(r,i)}),await P.isReady().catch(()=>{}),$.mount("#app")}return re(ge);})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-zero-ai",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "Zero-build Vue 3 router for AI-driven development",
5
5
  "main": "dist/vue-zero.js",
6
6
  "files": [