@stacksjs/stx 0.2.346 → 0.2.348

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 (77) hide show
  1. package/dist/binding-manifest.js +2 -0
  2. package/dist/{chunk-qp7sk0ex.js → chunk-05dbtcqr.js} +1 -1
  3. package/dist/chunk-08v51z39.js +2 -0
  4. package/dist/{chunk-t83m2pkm.js → chunk-1nhpc0hz.js} +1 -1
  5. package/dist/{chunk-zz2yxsf9.js → chunk-2dy1yerz.js} +1 -1
  6. package/dist/{chunk-akb6mgrb.js → chunk-39tzaza0.js} +1 -1
  7. package/dist/{chunk-21mmq3aj.js → chunk-42akykta.js} +1 -1
  8. package/dist/{chunk-fvvdq3ev.js → chunk-4956wxhq.js} +1 -1
  9. package/dist/{chunk-7hjjckat.js → chunk-5md1ycw2.js} +1 -1
  10. package/dist/{chunk-km92eab7.js → chunk-6nwrt02y.js} +1 -1
  11. package/dist/{chunk-dyy74sdv.js → chunk-72x80y39.js} +1 -1
  12. package/dist/{chunk-1xts7768.js → chunk-7j6vf641.js} +1 -1
  13. package/dist/{chunk-j8s9akdq.js → chunk-7pn9m07r.js} +1 -1
  14. package/dist/{chunk-wbp4vbm0.js → chunk-8fxbexvd.js} +1 -1
  15. package/dist/{chunk-9jbssgem.js → chunk-8m0g0h4x.js} +146 -10
  16. package/dist/{chunk-mph46gkj.js → chunk-9kmhwbwy.js} +12 -10
  17. package/dist/chunk-a8dyw9eg.js +32 -0
  18. package/dist/{chunk-3pggfwbf.js → chunk-bhjq5phg.js} +1 -1
  19. package/dist/{chunk-1bws4afs.js → chunk-c33jgh9n.js} +9 -9
  20. package/dist/chunk-cdt3dm8h.js +2 -0
  21. package/dist/{chunk-ddsgfmhv.js → chunk-cj5t2xsa.js} +1 -1
  22. package/dist/{chunk-rf2cejt3.js → chunk-d8gna0pj.js} +1 -1
  23. package/dist/{chunk-8tghv8cf.js → chunk-d9wq2e7a.js} +1 -1
  24. package/dist/{chunk-vw83y4we.js → chunk-djrrczet.js} +2 -2
  25. package/dist/{chunk-k5hv1qqy.js → chunk-e0qrfg4x.js} +1 -1
  26. package/dist/{chunk-vzbcdxd5.js → chunk-e1y8m2yp.js} +1 -1
  27. package/dist/{chunk-k80kr2t2.js → chunk-f32by983.js} +1 -1
  28. package/dist/{chunk-kfkf9v2d.js → chunk-f5veee11.js} +1 -1
  29. package/dist/{chunk-s3jyec9k.js → chunk-fb4gkrcw.js} +1 -1
  30. package/dist/{chunk-es275g3w.js → chunk-h0ntb2x4.js} +1 -1
  31. package/dist/{chunk-rwk5hwvk.js → chunk-hxta7f82.js} +1 -1
  32. package/dist/{chunk-1djdz98r.js → chunk-j6tdkr06.js} +1 -1
  33. package/dist/{chunk-1caep9rn.js → chunk-kzyd1gnx.js} +1 -1
  34. package/dist/{chunk-maq5jag2.js → chunk-mw33297e.js} +1 -1
  35. package/dist/chunk-mw3k7607.js +2 -0
  36. package/dist/{chunk-bxwanj4g.js → chunk-mz459926.js} +1 -1
  37. package/dist/{chunk-1xayahc6.js → chunk-na1wndvy.js} +1 -1
  38. package/dist/{chunk-v7aa7v85.js → chunk-p3p4d6g1.js} +1 -1
  39. package/dist/{chunk-xytgvfbf.js → chunk-pbt6f8gv.js} +2 -2
  40. package/dist/{chunk-5hhng72w.js → chunk-pg6esg0m.js} +1 -1
  41. package/dist/{chunk-tnm0nez5.js → chunk-pjg5v73e.js} +1 -1
  42. package/dist/{chunk-p04rck27.js → chunk-pw32a3x9.js} +1 -1
  43. package/dist/{chunk-1yh6pq6b.js → chunk-pwh8pbks.js} +1 -1
  44. package/dist/{chunk-s11e8aq9.js → chunk-r1x8wm83.js} +1 -1
  45. package/dist/{chunk-1vyz6kr8.js → chunk-rqfcafcy.js} +2 -2
  46. package/dist/{chunk-yg5r7bnm.js → chunk-swvm1wgn.js} +27 -3
  47. package/dist/{chunk-hfvknn03.js → chunk-t255mdy2.js} +2 -2
  48. package/dist/{chunk-7w66sc17.js → chunk-tbsvwy95.js} +1 -1
  49. package/dist/chunk-tg33an38.js +3745 -0
  50. package/dist/{chunk-jwe0cwff.js → chunk-vneewh3d.js} +6 -6
  51. package/dist/{chunk-q45fva8h.js → chunk-w1nnmcsr.js} +1 -1
  52. package/dist/{chunk-864m3xp2.js → chunk-xv6aydze.js} +1 -1
  53. package/dist/{chunk-b08taxsf.js → chunk-yj9kv14q.js} +1 -1
  54. package/dist/{chunk-byn0ptqt.js → chunk-zrjbge6f.js} +1 -1
  55. package/dist/{chunk-t2py7vc3.js → chunk-zwkkgham.js} +1 -1
  56. package/dist/cli.js +8 -8
  57. package/dist/config.js +16 -4
  58. package/dist/craft-entry.js +1 -1
  59. package/dist/craft.js +1 -1
  60. package/dist/dev-server/ts-css.js +16 -47
  61. package/dist/error-boundaries.d.ts +2 -13
  62. package/dist/error-boundaries.js +14 -6
  63. package/dist/process.js +13 -8
  64. package/dist/pwa.js +1 -1
  65. package/dist/signals.js +146 -10
  66. package/dist/ssg.js +2 -2
  67. package/dist/stx-virtual-ts.d.ts +16 -1
  68. package/dist/stx-virtual-ts.js +44 -3
  69. package/dist/typecheck.js +2 -0
  70. package/dist/types/config-types.d.ts +10 -0
  71. package/dist/utils.js +11 -2
  72. package/package.json +5 -5
  73. package/dist/chunk-fynb9e02.js +0 -2
  74. package/dist/chunk-pc8np1bb.js +0 -2
  75. package/dist/chunk-skd72bn4.js +0 -33
  76. package/dist/chunk-washyj03.js +0 -2
  77. package/dist/chunk-zdq7emrd.js +0 -3745
package/dist/pwa.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  import{Fk as wq,Gk as dq,Hk as Cq,Ik as mq,Jk as gq}from"./chunk-wvc7t11n.js";import{Kk as S,Lk as Tq,Mk as _q,Nk as z,Ok as D,Pk as P,Qk as kq,Rk as vq,Sk as w,Tk as Iq,Uk as d,Vk as Hq,Wk as Oq,Xk as Mq}from"./chunk-c30qnb6z.js";import{Ew as Aq,Fw as bq,Gw as Sq,Hw as zq,Iw as Dq,Jw as Pq}from"./chunk-9nrgjtah.js";import{Nw as N}from"./chunk-ejqpq0wc.js";import p from"fs";import E from"path";import C from"fs";import L from"path";var k=[72,96,128,144,152,192,384,512],v=[120,152,167,180],I=[16,32];async function H(G,B){let q={success:!0,generatedFiles:[],errors:[],warnings:[]},K=G.pwa?.icons;if(!K?.src)return q.errors.push("No source icon specified in pwa.icons.src"),q.success=!1,q;let Y=L.isAbsolute(K.src)?K.src:L.resolve(process.cwd(),K.src);if(!await Bun.file(Y).exists())return q.errors.push(`Source icon not found: ${Y}`),q.success=!1,q;let Q=L.resolve(B,K.outputDir||"pwa-icons");try{C.mkdirSync(Q,{recursive:!0})}catch{return q.errors.push(`Failed to create output directory: ${Q}`),q.success=!1,q}let X=K.sizes||k,j=K.generateWebP??!0,J=K.generateAppleIcons??!0;try{let y;try{y=await import("sharp")}catch{return q.errors.push(`sharp is not installed. Install it with: bun add sharp
3
- Icon generation requires the sharp package for image processing.`),q.success=!1,q}let R=await y.default(Y).metadata();if(R.width&&R.width<512)q.warnings.push(`Source icon is ${R.width}x${R.height}. Recommend using at least 512x512 for best quality.`);for(let $ of X){let x=L.join(Q,`icon-${$}x${$}.png`);if(await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toFile(x),q.generatedFiles.push(x),j){let F=L.join(Q,`icon-${$}x${$}.webp`);await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).webp({quality:90}).toFile(F),q.generatedFiles.push(F)}}if(J){for(let x of v){let F=L.join(Q,`apple-touch-icon-${x}x${x}.png`);await y.default(Y).resize(x,x,{fit:"contain",background:{r:255,g:255,b:255,alpha:1}}).png().toFile(F),q.generatedFiles.push(F)}let $=L.join(Q,"apple-touch-icon.png");await y.default(Y).resize(180,180,{fit:"contain",background:{r:255,g:255,b:255,alpha:1}}).png().toFile($),q.generatedFiles.push($)}for(let $ of I){let x=L.join(Q,`favicon-${$}x${$}.png`);await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toFile(x),q.generatedFiles.push(x)}let U=512,T=L.join(Q,`icon-maskable-${U}x${U}.png`),Z=Math.floor(U*0.1),_=U-Z*2;await y.default(Y).resize(_,_,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).extend({top:Z,bottom:Z,left:Z,right:Z,background:{r:255,g:255,b:255,alpha:1}}).png().toFile(T),q.generatedFiles.push(T)}catch(y){let V=y instanceof Error?y.message:String(y);q.errors.push(`Icon generation failed: ${V}`),q.success=!1}return q}function n(G){let B=G.sizes||k,q=G.outputDir?`/${G.outputDir}`:"/pwa-icons",K=G.generateWebP??!0,Y=G.generateAppleIcons??!0,Q=[];for(let X of B)if(Q.push(`${q}/icon-${X}x${X}.png`),K)Q.push(`${q}/icon-${X}x${X}.webp`);if(Y){Q.push(`${q}/apple-touch-icon.png`);for(let X of v)Q.push(`${q}/apple-touch-icon-${X}x${X}.png`)}for(let X of I)Q.push(`${q}/favicon-${X}x${X}.png`);return Q.push(`${q}/icon-maskable-512x512.png`),Q}async function O(){try{return await import("sharp"),!0}catch{return!1}}function m(G,B,q,K){let Y=[],Q=K.join(" ");for(let X of G)if(Y.push({src:`${B}/icon-${X}x${X}.png`,sizes:`${X}x${X}`,type:"image/png",purpose:Q}),q)Y.push({src:`${B}/icon-${X}x${X}.webp`,sizes:`${X}x${X}`,type:"image/webp",purpose:Q});return Y}function g(G){return G.map((B)=>({name:B.name,short_name:B.shortName,description:B.description,url:B.url,icons:B.icons?.map((q)=>({src:q.src,sizes:q.sizes,type:q.type}))}))}function h(G){let B=G.pwa?.shareTarget;if(!B?.enabled)return;let q={action:B.action||"/share",method:B.method||"POST",enctype:B.enctype||"multipart/form-data",params:{title:B.params?.title||"title",text:B.params?.text||"text",url:B.params?.url||"url"}};if(B.acceptFiles&&B.acceptFiles.length>0)q.params.files=B.acceptFiles.map((K)=>({name:K.name,accept:K.accept}));return q}function c(G){let B=G.pwa?.fileHandlers;if(!B?.enabled||!B.accept)return;let q=[{action:B.action||"/",accept:B.accept,launch_type:B.launchType||"single-client"}];if(B.icons)q[0].icons=B.icons.map((K)=>({src:K.src,sizes:K.sizes,type:K.type}));return q}function l(G){let B=G.pwa?.protocolHandlers;if(!B||B.length===0)return;return B.map((q)=>({protocol:q.protocol,url:q.url}))}function u(G){let B=G.pwa;if(!B?.enabled||!B.manifest)return null;let{manifest:q,icons:K}=B,Y=K?.sizes||[72,96,128,144,152,192,384,512],Q=K?.outputDir?`/${K.outputDir}`:"/pwa-icons",X=K?.generateWebP??!0,j=K?.purpose||["any","maskable"],J={name:q.name,short_name:q.shortName||q.name,description:q.description,start_url:q.startUrl||"/",display:q.display||"standalone",display_override:q.displayOverride,orientation:q.orientation,theme_color:q.themeColor,background_color:q.backgroundColor,scope:q.scope||"/",lang:q.lang,dir:q.dir,id:q.id,categories:q.categories,icons:m(Y,Q,X,j)};if(q.shortcuts&&q.shortcuts.length>0)J.shortcuts=g(q.shortcuts);if(q.screenshots&&q.screenshots.length>0)J.screenshots=q.screenshots.map((U)=>({src:U.src,sizes:U.sizes,type:U.type,label:U.label,form_factor:U.platform}));let y=h(G);if(y)J.share_target=y;let V=c(G);if(V)J.file_handlers=V;let R=l(G);if(R)J.protocol_handlers=R;if(q.launchHandler)J.launch_handler={client_mode:q.launchHandler};if(q.handleLinks)J.handle_links=q.handleLinks;if(q.edgeSidePanel?.enabled)J.edge_side_panel={preferred_width:q.edgeSidePanel.preferredWidth};return J}function M(G){let B=u(G);if(!B)return"";let q=JSON.parse(JSON.stringify(B));return JSON.stringify(q,null,2)}function i(G,B){return{...B,...G,shortcuts:G.shortcuts||B.shortcuts,screenshots:G.screenshots||B.screenshots,categories:G.categories||B.categories}}function s(G){let B=[],q=G.pwa;if(!q?.enabled)return B;let K=q.manifest;if(!K)return B.push("PWA manifest configuration is missing"),B;if(!K.name)B.push("Manifest name is required");let Y=["fullscreen","standalone","minimal-ui","browser"];if(K.display&&!Y.includes(K.display))B.push(`Invalid display mode: ${K.display}. Must be one of: ${Y.join(", ")}`);let Q=["any","natural","landscape","landscape-primary","landscape-secondary","portrait","portrait-primary","portrait-secondary"];if(K.orientation&&!Q.includes(K.orientation))B.push(`Invalid orientation: ${K.orientation}`);let X=/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;if(K.themeColor&&!X.test(K.themeColor))B.push(`Invalid theme color: ${K.themeColor}. Must be a valid hex color.`);if(K.backgroundColor&&!X.test(K.backgroundColor))B.push(`Invalid background color: ${K.backgroundColor}. Must be a valid hex color.`);if(q.shareTarget?.enabled){if(!q.shareTarget.action)B.push("Share target action URL is required")}if(q.fileHandlers?.enabled){if(!q.fileHandlers.accept||Object.keys(q.fileHandlers.accept).length===0)B.push("File handlers must specify accepted MIME types")}if(q.protocolHandlers)for(let j of q.protocolHandlers){if(!j.protocol)B.push("Protocol handler missing protocol");if(!j.url||!j.url.includes("%s"))B.push(`Protocol handler URL must contain %s placeholder: ${j.protocol}`)}return B}import A from"path";async function b(G){let B=G.pwa?.offline;if(!B?.enabled)return"";if(B.page){let q=A.isAbsolute(B.page)?B.page:A.resolve(process.cwd(),B.page);if(await Bun.file(q).exists())try{let{processDirectives:K}=await import("./chunk-t83m2pkm.js"),Y=await Bun.file(q).text();return await K(Y,{},q,G,new Set)}catch(K){console.warn(`[PWA] Failed to process custom offline page: ${K}`)}else console.warn(`[PWA] Custom offline page not found: ${q}`)}return f(G)}function f(G){let B=G.pwa?.offline,q=G.pwa?.manifest,K=B?.fallbackTitle||"You are offline",Y=B?.fallbackMessage||"Please check your internet connection and try again.",Q=q?.themeColor||"#4f46e5",X=q?.shortName||q?.name||"App";return`<!DOCTYPE html>
3
+ Icon generation requires the sharp package for image processing.`),q.success=!1,q}let R=await y.default(Y).metadata();if(R.width&&R.width<512)q.warnings.push(`Source icon is ${R.width}x${R.height}. Recommend using at least 512x512 for best quality.`);for(let $ of X){let x=L.join(Q,`icon-${$}x${$}.png`);if(await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toFile(x),q.generatedFiles.push(x),j){let F=L.join(Q,`icon-${$}x${$}.webp`);await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).webp({quality:90}).toFile(F),q.generatedFiles.push(F)}}if(J){for(let x of v){let F=L.join(Q,`apple-touch-icon-${x}x${x}.png`);await y.default(Y).resize(x,x,{fit:"contain",background:{r:255,g:255,b:255,alpha:1}}).png().toFile(F),q.generatedFiles.push(F)}let $=L.join(Q,"apple-touch-icon.png");await y.default(Y).resize(180,180,{fit:"contain",background:{r:255,g:255,b:255,alpha:1}}).png().toFile($),q.generatedFiles.push($)}for(let $ of I){let x=L.join(Q,`favicon-${$}x${$}.png`);await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toFile(x),q.generatedFiles.push(x)}let U=512,T=L.join(Q,`icon-maskable-${U}x${U}.png`),Z=Math.floor(U*0.1),_=U-Z*2;await y.default(Y).resize(_,_,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).extend({top:Z,bottom:Z,left:Z,right:Z,background:{r:255,g:255,b:255,alpha:1}}).png().toFile(T),q.generatedFiles.push(T)}catch(y){let V=y instanceof Error?y.message:String(y);q.errors.push(`Icon generation failed: ${V}`),q.success=!1}return q}function n(G){let B=G.sizes||k,q=G.outputDir?`/${G.outputDir}`:"/pwa-icons",K=G.generateWebP??!0,Y=G.generateAppleIcons??!0,Q=[];for(let X of B)if(Q.push(`${q}/icon-${X}x${X}.png`),K)Q.push(`${q}/icon-${X}x${X}.webp`);if(Y){Q.push(`${q}/apple-touch-icon.png`);for(let X of v)Q.push(`${q}/apple-touch-icon-${X}x${X}.png`)}for(let X of I)Q.push(`${q}/favicon-${X}x${X}.png`);return Q.push(`${q}/icon-maskable-512x512.png`),Q}async function O(){try{return await import("sharp"),!0}catch{return!1}}function m(G,B,q,K){let Y=[],Q=K.join(" ");for(let X of G)if(Y.push({src:`${B}/icon-${X}x${X}.png`,sizes:`${X}x${X}`,type:"image/png",purpose:Q}),q)Y.push({src:`${B}/icon-${X}x${X}.webp`,sizes:`${X}x${X}`,type:"image/webp",purpose:Q});return Y}function g(G){return G.map((B)=>({name:B.name,short_name:B.shortName,description:B.description,url:B.url,icons:B.icons?.map((q)=>({src:q.src,sizes:q.sizes,type:q.type}))}))}function h(G){let B=G.pwa?.shareTarget;if(!B?.enabled)return;let q={action:B.action||"/share",method:B.method||"POST",enctype:B.enctype||"multipart/form-data",params:{title:B.params?.title||"title",text:B.params?.text||"text",url:B.params?.url||"url"}};if(B.acceptFiles&&B.acceptFiles.length>0)q.params.files=B.acceptFiles.map((K)=>({name:K.name,accept:K.accept}));return q}function c(G){let B=G.pwa?.fileHandlers;if(!B?.enabled||!B.accept)return;let q=[{action:B.action||"/",accept:B.accept,launch_type:B.launchType||"single-client"}];if(B.icons)q[0].icons=B.icons.map((K)=>({src:K.src,sizes:K.sizes,type:K.type}));return q}function l(G){let B=G.pwa?.protocolHandlers;if(!B||B.length===0)return;return B.map((q)=>({protocol:q.protocol,url:q.url}))}function u(G){let B=G.pwa;if(!B?.enabled||!B.manifest)return null;let{manifest:q,icons:K}=B,Y=K?.sizes||[72,96,128,144,152,192,384,512],Q=K?.outputDir?`/${K.outputDir}`:"/pwa-icons",X=K?.generateWebP??!0,j=K?.purpose||["any","maskable"],J={name:q.name,short_name:q.shortName||q.name,description:q.description,start_url:q.startUrl||"/",display:q.display||"standalone",display_override:q.displayOverride,orientation:q.orientation,theme_color:q.themeColor,background_color:q.backgroundColor,scope:q.scope||"/",lang:q.lang,dir:q.dir,id:q.id,categories:q.categories,icons:m(Y,Q,X,j)};if(q.shortcuts&&q.shortcuts.length>0)J.shortcuts=g(q.shortcuts);if(q.screenshots&&q.screenshots.length>0)J.screenshots=q.screenshots.map((U)=>({src:U.src,sizes:U.sizes,type:U.type,label:U.label,form_factor:U.platform}));let y=h(G);if(y)J.share_target=y;let V=c(G);if(V)J.file_handlers=V;let R=l(G);if(R)J.protocol_handlers=R;if(q.launchHandler)J.launch_handler={client_mode:q.launchHandler};if(q.handleLinks)J.handle_links=q.handleLinks;if(q.edgeSidePanel?.enabled)J.edge_side_panel={preferred_width:q.edgeSidePanel.preferredWidth};return J}function M(G){let B=u(G);if(!B)return"";let q=JSON.parse(JSON.stringify(B));return JSON.stringify(q,null,2)}function i(G,B){return{...B,...G,shortcuts:G.shortcuts||B.shortcuts,screenshots:G.screenshots||B.screenshots,categories:G.categories||B.categories}}function s(G){let B=[],q=G.pwa;if(!q?.enabled)return B;let K=q.manifest;if(!K)return B.push("PWA manifest configuration is missing"),B;if(!K.name)B.push("Manifest name is required");let Y=["fullscreen","standalone","minimal-ui","browser"];if(K.display&&!Y.includes(K.display))B.push(`Invalid display mode: ${K.display}. Must be one of: ${Y.join(", ")}`);let Q=["any","natural","landscape","landscape-primary","landscape-secondary","portrait","portrait-primary","portrait-secondary"];if(K.orientation&&!Q.includes(K.orientation))B.push(`Invalid orientation: ${K.orientation}`);let X=/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;if(K.themeColor&&!X.test(K.themeColor))B.push(`Invalid theme color: ${K.themeColor}. Must be a valid hex color.`);if(K.backgroundColor&&!X.test(K.backgroundColor))B.push(`Invalid background color: ${K.backgroundColor}. Must be a valid hex color.`);if(q.shareTarget?.enabled){if(!q.shareTarget.action)B.push("Share target action URL is required")}if(q.fileHandlers?.enabled){if(!q.fileHandlers.accept||Object.keys(q.fileHandlers.accept).length===0)B.push("File handlers must specify accepted MIME types")}if(q.protocolHandlers)for(let j of q.protocolHandlers){if(!j.protocol)B.push("Protocol handler missing protocol");if(!j.url||!j.url.includes("%s"))B.push(`Protocol handler URL must contain %s placeholder: ${j.protocol}`)}return B}import A from"path";async function b(G){let B=G.pwa?.offline;if(!B?.enabled)return"";if(B.page){let q=A.isAbsolute(B.page)?B.page:A.resolve(process.cwd(),B.page);if(await Bun.file(q).exists())try{let{processDirectives:K}=await import("./chunk-1nhpc0hz.js"),Y=await Bun.file(q).text();return await K(Y,{},q,G,new Set)}catch(K){console.warn(`[PWA] Failed to process custom offline page: ${K}`)}else console.warn(`[PWA] Custom offline page not found: ${q}`)}return f(G)}function f(G){let B=G.pwa?.offline,q=G.pwa?.manifest,K=B?.fallbackTitle||"You are offline",Y=B?.fallbackMessage||"Please check your internet connection and try again.",Q=q?.themeColor||"#4f46e5",X=q?.shortName||q?.name||"App";return`<!DOCTYPE html>
4
4
  <html lang="en">
5
5
  <head>
6
6
  <meta charset="UTF-8">
package/dist/signals.js CHANGED
@@ -6487,6 +6487,89 @@ catch (e) {} }
6487
6487
  // Both return Promises and render into a temporary modal overlay.
6488
6488
 
6489
6489
  var _dialogId = 0;
6490
+
6491
+ // Shared across every open dialog, because four of the defects in #1998 were
6492
+ // each dialog acting as if it were the only one.
6493
+ var _dialogStack = [];
6494
+ // What WE set inert, so restoring never clears an app's own inert.
6495
+ var _dialogInerted = [];
6496
+ // Saved once, when the first dialog opens.
6497
+ var _dialogScrollLock = null;
6498
+
6499
+ /*
6500
+ * The page behind an aria-modal dialog does not scroll and is not reachable
6501
+ * by a virtual cursor (stacksjs/stx#1998, items 1 and 2).
6502
+ *
6503
+ * The backdrop is position:fixed;inset:0, so it stayed put while the content
6504
+ * behind it scrolled away underneath - the dialog claimed to be modal and the
6505
+ * page moved anyway. And the Tab trap, which #1875 added, only covers the
6506
+ * keyboard: aria-modal support for the virtual cursor is uneven, so a screen
6507
+ * reader could still browse the page behind the dialog.
6508
+ *
6509
+ * inert rather than aria-hidden on the siblings: aria-hidden on an element
6510
+ * that contains focus is itself a violation, and inert removes the subtree
6511
+ * from the tab order and the accessibility tree together. Everything except
6512
+ * the TOPMOST dialog goes inert, which also settles the two traps competing
6513
+ * for Tab while both were open - a backgrounded dialog's buttons stop being
6514
+ * focusable at all.
6515
+ */
6516
+ function _dialogSyncModality() {
6517
+ var top = _dialogStack.length ? _dialogStack[_dialogStack.length - 1] : null;
6518
+
6519
+ for (var i = 0; i < _dialogInerted.length; i++) {
6520
+ try { _dialogInerted[i].inert = false; }
6521
+ catch (_e) { /* element may be gone */ }
6522
+ }
6523
+ _dialogInerted = [];
6524
+
6525
+ if (!top) {
6526
+ if (_dialogScrollLock) {
6527
+ document.body.style.overflow = _dialogScrollLock.body;
6528
+ document.documentElement.style.overflow = _dialogScrollLock.html;
6529
+ document.body.style.paddingRight = _dialogScrollLock.pad;
6530
+ _dialogScrollLock = null;
6531
+ }
6532
+ return;
6533
+ }
6534
+
6535
+ if (!_dialogScrollLock) {
6536
+ _dialogScrollLock = {
6537
+ body: document.body.style.overflow,
6538
+ html: document.documentElement.style.overflow,
6539
+ pad: document.body.style.paddingRight
6540
+ };
6541
+ // Compensate for the scrollbar the lock removes, or the whole page shifts
6542
+ // sideways the moment a dialog opens.
6543
+ var gap = window.innerWidth - document.documentElement.clientWidth;
6544
+ if (gap > 0) {
6545
+ var existing = Number.parseFloat(window.getComputedStyle(document.body).paddingRight) || 0;
6546
+ document.body.style.paddingRight = (existing + gap) + 'px';
6547
+ }
6548
+ document.body.style.overflow = 'hidden';
6549
+ document.documentElement.style.overflow = 'hidden';
6550
+ }
6551
+
6552
+ var kids = document.body.children;
6553
+ for (var k = 0; k < kids.length; k++) {
6554
+ var kid = kids[k];
6555
+ if (kid === top || kid.inert) continue;
6556
+ try {
6557
+ kid.inert = true;
6558
+ _dialogInerted.push(kid);
6559
+ }
6560
+ catch (_e) { /* inert unsupported; the Tab trap still holds */ }
6561
+ }
6562
+ }
6563
+
6564
+ /** Dialogs animate unless the reader asked them not to (#1998 item 5). */
6565
+ function _dialogReducedMotion() {
6566
+ try {
6567
+ return !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches);
6568
+ }
6569
+ catch (_e) {
6570
+ return false;
6571
+ }
6572
+ }
6490
6573
  var _dialogIcons = {
6491
6574
  info: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>',
6492
6575
  warning: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#d97706" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',
@@ -6514,14 +6597,23 @@ catch (e) {} }
6514
6597
  var icon = _dialogIcons[type] || _dialogIcons.info;
6515
6598
 
6516
6599
  return new Promise(function(resolve) {
6600
+ // Inline transitions cannot be reached by a stylesheet media query, so the
6601
+ // preference is read here instead (#1998 item 5). One matchMedia probe
6602
+ // rather than usePreferredReducedMotion(): that returns a signal with a
6603
+ // change listener, and an imperative dialog that reads the value once at
6604
+ // open time would leak one listener per call.
6605
+ var still = _dialogReducedMotion();
6606
+ var fade = still ? '' : 'transition:opacity 0.2s ease;';
6607
+ var scale = still ? '' : 'transition:transform 0.2s ease;';
6608
+
6517
6609
  var backdrop = document.createElement('div');
6518
6610
  backdrop.id = id;
6519
- backdrop.style.cssText = 'position:fixed;inset:0;z-index:999999;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0.5);backdrop-filter:blur(2px);opacity:0;transition:opacity 0.2s ease;font-family:system-ui,-apple-system,sans-serif';
6611
+ backdrop.style.cssText = 'position:fixed;inset:0;z-index:999999;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0.5);backdrop-filter:blur(2px);opacity:' + (still ? '1' : '0') + ';' + fade + 'font-family:system-ui,-apple-system,sans-serif';
6520
6612
  backdrop.setAttribute('role', 'alertdialog');
6521
6613
  backdrop.setAttribute('aria-modal', 'true');
6522
6614
 
6523
6615
  var panel = document.createElement('div');
6524
- panel.style.cssText = 'max-width:24rem;width:calc(100% - 2rem);border-radius:0.75rem;padding:1.5rem;background:' + bg + ';color:' + textColor + ';box-shadow:0 20px 60px rgba(0,0,0,0.3);transform:scale(0.95);transition:transform 0.2s ease;text-align:center';
6616
+ panel.style.cssText = 'max-width:24rem;width:calc(100% - 2rem);border-radius:0.75rem;padding:1.5rem;background:' + bg + ';color:' + textColor + ';box-shadow:0 20px 60px rgba(0,0,0,0.3);transform:scale(' + (still ? '1' : '0.95') + ');' + scale + 'text-align:center';
6525
6617
 
6526
6618
  var iconDiv = document.createElement('div');
6527
6619
  iconDiv.style.cssText = 'display:flex;justify-content:center;margin-bottom:1rem';
@@ -6562,9 +6654,25 @@ catch (e) {} }
6562
6654
  if (closed) return;
6563
6655
  closed = true;
6564
6656
  document.removeEventListener('keydown', keyHandler, true);
6657
+
6658
+ // Out of the stack BEFORE resolving, so a caller that opens another
6659
+ // dialog the moment this one answers does not land under a backdrop
6660
+ // that is still fading.
6661
+ var at = _dialogStack.indexOf(backdrop);
6662
+ if (at !== -1) _dialogStack.splice(at, 1);
6663
+
6664
+ // The fade is 200ms and resolve() is immediate, so for those 200ms a
6665
+ // full-viewport element at z-index 999999 was still hit-testing at the
6666
+ // centre of the screen - after the caller's await had already returned
6667
+ // (#1998 item 6). Fading out is right; swallowing clicks is not.
6668
+ backdrop.style.pointerEvents = 'none';
6565
6669
  backdrop.style.opacity = '0';
6566
- panel.style.transform = 'scale(0.95)';
6567
- setTimeout(function() { backdrop.remove(); }, 200);
6670
+ if (!still) panel.style.transform = 'scale(0.95)';
6671
+ setTimeout(function() { backdrop.remove(); }, still ? 0 : 200);
6672
+
6673
+ // Unlocks the page and clears inert when this was the last dialog, or
6674
+ // hands modality back to the one underneath when it was not.
6675
+ _dialogSyncModality();
6568
6676
  if (previouslyFocused && typeof previouslyFocused.focus === 'function') {
6569
6677
  try { previouslyFocused.focus(); }
6570
6678
  catch (_e) { /* element may be gone; not worth failing the dialog over */ }
@@ -6572,8 +6680,11 @@ catch (e) {} }
6572
6680
  resolve(result);
6573
6681
  }
6574
6682
 
6683
+ // Declared out here rather than inside the branch: the focus decision
6684
+ // below needs to know whether a Cancel button exists at all.
6685
+ var cancelBtn = null;
6575
6686
  if (isConfirm) {
6576
- var cancelBtn = document.createElement('button');
6687
+ cancelBtn = document.createElement('button');
6577
6688
  cancelBtn.textContent = cancelText;
6578
6689
  cancelBtn.style.cssText = 'padding:0.5rem 1.25rem;border-radius:0.5rem;font-size:0.875rem;font-weight:500;cursor:pointer;border:1px solid ' + (isDark ? '#374151' : '#d1d5db') + ';background:transparent;color:' + textColor + ';transition:background 0.15s';
6579
6690
  cancelBtn.onmouseover = function() { this.style.background = isDark ? '#374151' : '#f3f4f6'; };
@@ -6594,11 +6705,15 @@ catch (e) {} }
6594
6705
  panel.appendChild(btnRow);
6595
6706
  backdrop.appendChild(panel);
6596
6707
  document.body.appendChild(backdrop);
6708
+ _dialogStack.push(backdrop);
6709
+ _dialogSyncModality();
6597
6710
 
6598
6711
  // Animate in
6599
- void backdrop.offsetHeight;
6600
- backdrop.style.opacity = '1';
6601
- panel.style.transform = 'scale(1)';
6712
+ if (!still) {
6713
+ void backdrop.offsetHeight;
6714
+ backdrop.style.opacity = '1';
6715
+ panel.style.transform = 'scale(1)';
6716
+ }
6602
6717
 
6603
6718
  // Escape, plus a real focus trap.
6604
6719
  //
@@ -6611,6 +6726,11 @@ catch (e) {} }
6611
6726
  // walked straight out into the page behind it. Capture phase so the trap
6612
6727
  // wins over anything the page has bound.
6613
6728
  var keyHandler = function(e) {
6729
+ // Every dialog binds its own capture-phase handler on document and none
6730
+ // of them checked whether they were on top, so ONE Escape resolved every
6731
+ // open dialog at once (#1998 item 4). The backgrounded dialogs are inert
6732
+ // too, which is what stops their traps competing for Tab.
6733
+ if (_dialogStack.length && _dialogStack[_dialogStack.length - 1] !== backdrop) return;
6614
6734
  if (e.key === 'Escape') {
6615
6735
  e.preventDefault();
6616
6736
  cleanup(isConfirm ? false : undefined);
@@ -6640,8 +6760,24 @@ catch (e) {} }
6640
6760
  };
6641
6761
  document.addEventListener('keydown', keyHandler, true);
6642
6762
 
6643
- // Focus the primary button
6644
- okBtn.focus();
6763
+ /*
6764
+ * Initial focus, which was an unconditional okBtn.focus() (#1998 item 3).
6765
+ *
6766
+ * type: 'error' already paints that button red, so the API knows the
6767
+ * action is destructive - and still handed it the keyboard, where a stray
6768
+ * Enter or Space confirmed the delete. An error-type confirm now defaults
6769
+ * to Cancel, and defaultFocus overrides either way.
6770
+ *
6771
+ * An alert has only one button, so it keeps it: there is nothing
6772
+ * destructive to land on and focus has to go somewhere inside the trap.
6773
+ */
6774
+ var focusTarget = okBtn;
6775
+ if (isConfirm && cancelBtn) {
6776
+ var want = opts.defaultFocus;
6777
+ if (want === 'cancel' || (!want && type === 'error')) focusTarget = cancelBtn;
6778
+ else if (want === 'confirm') focusTarget = okBtn;
6779
+ }
6780
+ focusTarget.focus();
6645
6781
  });
6646
6782
  }
6647
6783
 
package/dist/ssg.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{Bk as Fq,wk as Uq,xk as Iq}from"./chunk-v7aa7v85.js";import{Ck as Eq,Dk as Tq,Ek as Dq}from"./chunk-c0n802j1.js";import{Zk as _q,al as zq,bl as Aq}from"./chunk-tnm0nez5.js";import"./chunk-hfvknn03.js";import"./chunk-fvsefztj.js";import{Jp as P,Sm as Oq,io as l,lo as Hq,sr as n}from"./chunk-zdq7emrd.js";import"./chunk-8y1ve8tc.js";import"./chunk-njx93b4z.js";import"./chunk-bqdfbwdf.js";import"./chunk-89mqnh67.js";import"./chunk-xvh1k1a4.js";import{it as Xq}from"./chunk-skd72bn4.js";import{nt as d}from"./chunk-y2f41kaq.js";import"./chunk-xj6bcwqa.js";import"./chunk-21mmq3aj.js";import"./chunk-vhta1be7.js";import{Ut as Bq}from"./chunk-tc4pj651.js";import"./chunk-san1eq0r.js";import"./chunk-avwywzsj.js";import"./chunk-wj21f1e0.js";import"./chunk-d86q27j8.js";import"./chunk-72x62kch.js";import{rw as Yq,sw as Vq,tw as jq,uw as Gq,vw as Lq,ww as Nq}from"./chunk-yg5r7bnm.js";import"./chunk-9nrgjtah.js";import{Nw as y}from"./chunk-ejqpq0wc.js";import O from"fs";import j from"path";import{createHash as xq}from"crypto";function yq(q){try{return new Bun.Transpiler({loader:"js",minifyWhitespace:!0}).transformSync(q).replace(/\}(var |let |const |function )/g,"};$1").trim()}catch{return q}}var Pq=/<script\s+type="stx\/island"\s+data-stx-island="([^"]+)"([^>]*)>([\s\S]*?)<\/script>/g;function Cq(q){return Bun.hash(q).toString(16)}function Qq(q,Z={}){if(!q.includes('type="stx/island"'))return{html:q,chunks:[]};let $=new Map,Q=q.replace(Pq,(J,W,z,A)=>{let G=A.trim();if(!G)return J;if(/\bdata-stx-src=/.test(z))return J;if(Z.minify)G=yq(G);let X=Cq(G);if(!$.has(X))$.set(X,G);let B=Z.integrity?` data-stx-integrity="sha384-${xq("sha384").update(G).digest("base64")}"`:"";return`<script type="stx/island" data-stx-island="${W}" data-stx-src="/_stx/islands/${X}.js"${B}${z}></script>`}),K=Array.from($,([J,W])=>({hash:J,code:W}));return{html:Q,chunks:K}}var gq=new Set(["visible","idle"]);function Zq(q){if(!q.includes("data-stx-src="))return q;let Z=new Map,$=/data-stx-scope="([^"]+)"[^>]*?stx-hydrate="([^"]+)"/g,Q;while((Q=$.exec(q))!==null)Z.set(Q[1],Q[2]);let K=new Set,J=/data-stx-island="([^"]+)"[^>]*?data-stx-src="([^"]+)"/g,W;while((W=J.exec(q))!==null)if(gq.has(Z.get(W[1])||""))K.add(W[2]);let z=q.lastIndexOf("</head>");if(K.size===0||z===-1)return q;let A=Array.from(K).filter((G)=>!q.includes(`rel="prefetch" href="${G}"`)).map((G)=>`<link rel="prefetch" href="${G}" as="script">`).join("");if(!A)return q;return q.slice(0,z)+A+q.slice(z)}var fq=["STX_SITE_URL","SITE_URL","URL","VERCEL_URL","CF_PAGES_URL"];function h(q){let Z=q.trim();if(!Z)return null;let $=/^https?:\/\//i.test(Z)?Z:`https://${Z}`;try{return new URL($).origin+new URL($).pathname.replace(/\/$/,"")}catch{return null}}function mq(q){for(let Z of fq){let $=q[Z];if(!$)continue;let Q=h($);if(Q)return{url:Q,source:"env",via:Z}}return null}function $q(q){if(!q||typeof q!=="object")return null;let Z=q,$=Z.site?.url??Z.url??Z.app?.url;return typeof $==="string"?h($):null}async function dq(q){let{existsSync:Z}=await import("fs"),$=await import("path");for(let Q of["site.config.ts","site.config.js",".config/site.config.ts"]){let K=$.resolve(q,Q);if(!Z(K))continue;try{let J=await import(K),W=$q(J.default??J);if(W)return W}catch{}}return null}async function Kq(q={}){let Z=q.cwd??process.cwd(),$=q.env??process.env;if(q.explicit){let W=h(q.explicit);if(W)return{url:W,source:"option"}}let Q=$q(q.stxConfig);if(Q)return{url:Q,source:"stx.config",via:"site.url"};let K=await dq(Z);if(K)return{url:K,source:"site.config",via:"url"};let J=mq($);if(J)return J;return{url:"http://localhost",source:"fallback"}}function Wq(){return["No site URL configured \u2014 sitemap.xml and robots.txt will point at http://localhost."," Set one in stx.config.ts (site: { url: 'https://example.com' }), in site.config.ts,"," via --domain, or with SITE_URL in the build environment."].join(`
2
+ import{Bk as Fq,wk as Uq,xk as Iq}from"./chunk-p3p4d6g1.js";import{Ck as Eq,Dk as Tq,Ek as Dq}from"./chunk-c0n802j1.js";import{Zk as _q,al as zq,bl as Aq}from"./chunk-pjg5v73e.js";import"./chunk-t255mdy2.js";import"./chunk-fvsefztj.js";import{Jp as P,Sm as Oq,io as l,lo as Hq,sr as n}from"./chunk-tg33an38.js";import"./chunk-8y1ve8tc.js";import"./chunk-njx93b4z.js";import"./chunk-bqdfbwdf.js";import"./chunk-89mqnh67.js";import"./chunk-xvh1k1a4.js";import{it as Xq}from"./chunk-a8dyw9eg.js";import{nt as d}from"./chunk-y2f41kaq.js";import"./chunk-xj6bcwqa.js";import"./chunk-42akykta.js";import"./chunk-vhta1be7.js";import{Ut as Bq}from"./chunk-tc4pj651.js";import"./chunk-san1eq0r.js";import"./chunk-avwywzsj.js";import"./chunk-wj21f1e0.js";import"./chunk-d86q27j8.js";import"./chunk-72x62kch.js";import{rw as Yq,sw as Vq,tw as jq,uw as Gq,vw as Lq,ww as Nq}from"./chunk-swvm1wgn.js";import"./chunk-9nrgjtah.js";import{Nw as y}from"./chunk-ejqpq0wc.js";import O from"fs";import j from"path";import{createHash as xq}from"crypto";function yq(q){try{return new Bun.Transpiler({loader:"js",minifyWhitespace:!0}).transformSync(q).replace(/\}(var |let |const |function )/g,"};$1").trim()}catch{return q}}var Pq=/<script\s+type="stx\/island"\s+data-stx-island="([^"]+)"([^>]*)>([\s\S]*?)<\/script>/g;function Cq(q){return Bun.hash(q).toString(16)}function Qq(q,Z={}){if(!q.includes('type="stx/island"'))return{html:q,chunks:[]};let $=new Map,Q=q.replace(Pq,(J,W,z,A)=>{let G=A.trim();if(!G)return J;if(/\bdata-stx-src=/.test(z))return J;if(Z.minify)G=yq(G);let X=Cq(G);if(!$.has(X))$.set(X,G);let B=Z.integrity?` data-stx-integrity="sha384-${xq("sha384").update(G).digest("base64")}"`:"";return`<script type="stx/island" data-stx-island="${W}" data-stx-src="/_stx/islands/${X}.js"${B}${z}></script>`}),K=Array.from($,([J,W])=>({hash:J,code:W}));return{html:Q,chunks:K}}var gq=new Set(["visible","idle"]);function Zq(q){if(!q.includes("data-stx-src="))return q;let Z=new Map,$=/data-stx-scope="([^"]+)"[^>]*?stx-hydrate="([^"]+)"/g,Q;while((Q=$.exec(q))!==null)Z.set(Q[1],Q[2]);let K=new Set,J=/data-stx-island="([^"]+)"[^>]*?data-stx-src="([^"]+)"/g,W;while((W=J.exec(q))!==null)if(gq.has(Z.get(W[1])||""))K.add(W[2]);let z=q.lastIndexOf("</head>");if(K.size===0||z===-1)return q;let A=Array.from(K).filter((G)=>!q.includes(`rel="prefetch" href="${G}"`)).map((G)=>`<link rel="prefetch" href="${G}" as="script">`).join("");if(!A)return q;return q.slice(0,z)+A+q.slice(z)}var fq=["STX_SITE_URL","SITE_URL","URL","VERCEL_URL","CF_PAGES_URL"];function h(q){let Z=q.trim();if(!Z)return null;let $=/^https?:\/\//i.test(Z)?Z:`https://${Z}`;try{return new URL($).origin+new URL($).pathname.replace(/\/$/,"")}catch{return null}}function mq(q){for(let Z of fq){let $=q[Z];if(!$)continue;let Q=h($);if(Q)return{url:Q,source:"env",via:Z}}return null}function $q(q){if(!q||typeof q!=="object")return null;let Z=q,$=Z.site?.url??Z.url??Z.app?.url;return typeof $==="string"?h($):null}async function dq(q){let{existsSync:Z}=await import("fs"),$=await import("path");for(let Q of["site.config.ts","site.config.js",".config/site.config.ts"]){let K=$.resolve(q,Q);if(!Z(K))continue;try{let J=await import(K),W=$q(J.default??J);if(W)return W}catch{}}return null}async function Kq(q={}){let Z=q.cwd??process.cwd(),$=q.env??process.env;if(q.explicit){let W=h(q.explicit);if(W)return{url:W,source:"option"}}let Q=$q(q.stxConfig);if(Q)return{url:Q,source:"stx.config",via:"site.url"};let K=await dq(Z);if(K)return{url:K,source:"site.config",via:"url"};let J=mq($);if(J)return J;return{url:"http://localhost",source:"fallback"}}function Wq(){return["No site URL configured \u2014 sitemap.xml and robots.txt will point at http://localhost."," Set one in stx.config.ts (site: { url: 'https://example.com' }), in site.config.ts,"," via --domain, or with SITE_URL in the build environment."].join(`
3
3
  `)}class wq{cacheDir;cache=new Map;loaded=!1;salt;constructor(q,Z=""){this.cacheDir=q,this.salt=Z}async load(){if(this.loaded)return;let q=j.join(this.cacheDir,"build-cache.json");if(await Bun.file(q).exists())try{let Z=JSON.parse(await Bun.file(q).text());for(let[$,Q]of Object.entries(Z))this.cache.set($,Q)}catch{}this.loaded=!0}async save(){await O.promises.mkdir(this.cacheDir,{recursive:!0});let q=j.join(this.cacheDir,"build-cache.json"),Z={};for(let[$,Q]of this.cache)Z[$]=Q;await Bun.write(q,JSON.stringify(Z))}getHash(q,Z){let $=O.statSync(q),Q=`${this.salt}|${q}:${$.mtimeMs}`;for(let J of Z)if(O.existsSync(J)){let W=O.statSync(J);Q+=`:${J}:${W.mtimeMs}`}let K=0;for(let J=0;J<Q.length;J++){let W=Q.charCodeAt(J);K=(K<<5)-K+W,K=K&K}return Math.abs(K).toString(36)}get(q,Z){let $=this.cache.get(q);if(!$)return null;let Q=this.getHash(Z,$.dependencies??[]);if($.hash!==Q)return this.cache.delete(q),null;return $.html}set(q,Z,$,Q){let K=this.getHash(Z,$);this.cache.set(q,{hash:K,html:Q,generatedAt:Date.now(),dependencies:$})}}class Rq{cacheDir;constructor(q){this.cacheDir=q}getFilePath(q){let Z=q.replace(/[^a-zA-Z0-9]/g,"_")+".json";return j.join(this.cacheDir,"isr",Z)}async get(q){let Z=this.getFilePath(q);if(!await Bun.file(Z).exists())return null;try{return JSON.parse(await Bun.file(Z).text())}catch{return null}}async set(q,Z){let $=this.getFilePath(q);await O.promises.mkdir(j.dirname($),{recursive:!0}),await Bun.write($,JSON.stringify(Z))}async invalidate(q){let Z=this.getFilePath(q);if(await Bun.file(Z).exists())await O.promises.unlink(Z)}async invalidatePattern(q){let Z=j.join(this.cacheDir,"isr");if(!O.existsSync(Z))return;let $=await O.promises.readdir(Z);for(let Q of $){let K=Q.replace(/_/g,"/").replace(".json","");if(q.test(K))await O.promises.unlink(j.join(Z,Q))}}async needsRevalidation(q){let Z=await this.get(q);if(!Z)return!0;return Date.now()>Z.revalidateAfter}}async function pq(q){try{let $=(await Bun.file(q).text()).match(/<script\s+server\b[^>]*>([\s\S]*?)<\/script>/i);if(!$)return null;let Q=$[1];if(!Q.includes("getStaticPaths"))return null;let K=Q.match(/(?:export\s+)?(?:async\s+)?function\s+getStaticPaths\s*\([^)]*\)\s*\{([\s\S]*?)\n[\t ]*\}/);if(!K)return null;return await Function(`
4
4
  return (async function getStaticPaths() {
5
5
  ${K[1]}
@@ -41,7 +41,7 @@ ${q.map((Q)=>{let K=new URL(Q.loc,Z).href,J=` <url>
41
41
  ${$.join(`
42
42
  `)}
43
43
  </channel>
44
- </rss>`}async function aq(q={}){let Z=Date.now();Aq();let $=await n(process.cwd()),Q=$.build||{},K=await Kq({explicit:q.domain||Q.domain,stxConfig:$});if(K.source==="fallback"&&(q.sitemap??Q.sitemap??!0))console.warn(Wq());let J={router:q.router??$?.router??{},pagesDir:q.pagesDir||Q.pagesDir||"pages",outputDir:q.outputDir||Q.outputDir||"dist",baseUrl:q.baseUrl||Q.baseUrl||"/",domain:K.url,revalidate:q.revalidate??Q.revalidate??!1,sitemap:q.sitemap??Q.sitemap??!0,sitemapExclude:q.sitemapExclude||Q.sitemapExclude||[],robots:q.robots??Q.robots??!0,rss:q.rss??Q.rss??!1,concurrency:q.concurrency||Q.concurrency||10,cache:q.cache??Q.cache??!0,cacheDir:q.cacheDir||Q.cacheDir||d(process.cwd(),"ssg-cache"),contentLoaders:q.contentLoaders||[],hooks:q.hooks||{},minify:q.minify??Q.minify??!0,generate404:q.generate404??Q.generate404??!0,publicDir:q.publicDir||Q.publicDir||"public",trailingSlash:q.trailingSlash??Q.trailingSlash??!1,cleanOutput:q.cleanOutput??Q.cleanOutput??!0,cacheSalt:q.cacheSalt??"",partialsDir:q.partialsDir||$?.partialsDir||"",componentsDir:q.componentsDir||$?.componentsDir||"",failOnIncludeError:q.failOnIncludeError??!0,chunkIslands:q.chunkIslands===!0,prefetchIslands:q.prefetchIslands===!0,integrityIslands:q.integrityIslands===!0},W={totalPages:0,successCount:0,failedCount:0,cachedCount:0,buildTime:0,pages:[],errors:[]},z=new Set,A=0,G={},X={};await J.hooks.onBuildStart?.();try{if(J.cleanOutput&&O.existsSync(J.outputDir))await O.promises.rm(J.outputDir,{recursive:!0});await O.promises.mkdir(J.outputDir,{recursive:!0});let L=J.cacheSalt;if(!L){let{resolveUserCssConfig:Y,fingerprintConfig:N}=await import("./chunk-864m3xp2.js");try{L=N(await Y(process.cwd()))}catch{}}let{prepareImageDelivery:_}=await import("./chunk-e631svvs.js"),F=await _(J.publicDir,J.outputDir);if(F.count>0)console.log(`Optimized ${F.count} image(s) for responsive delivery`),L=[L,F.fingerprint].filter(Boolean).join(":");let C=new wq(J.cacheDir,L);if(J.cache)await C.load();try{let{generateCss:Y}=await import("./chunk-864m3xp2.js");await Y('<div class="bg-black"></div>')}catch{}Yq();let kq=$?.routeMiddleware?.dir||"middleware";await jq(process.cwd(),kq);let p=Vq();if(p.length>0)console.log(`Loaded ${p.length} middleware: ${p.join(", ")}`);let bq=$?.routeMiddleware?.global||[];Fq($?.layoutsDir,d(process.cwd()));let i=l(".",{pagesDir:J.pagesDir,pagesDirs:$?._layerPageDirs});console.log(`Found ${i.length} routes`);let g=[];for(let Y of i){let N=await uq(Y);for(let H of N)g.push({route:Y,url:H.url,params:H.params,props:H.props,revalidate:H.revalidate??J.revalidate})}W.totalPages=g.length,console.log(`Generating ${W.totalPages} pages...`);let b=[],s=[];for(let Y=0;Y<g.length;Y+=J.concurrency)s.push(g.slice(Y,Y+J.concurrency));for(let Y of s)await Promise.all(Y.map(async(N)=>{let{route:H,url:V,params:S,props:Sq,revalidate:a}=N;try{await J.hooks.onPageStart?.(V);let w=await Bun.file(H.filePath).text(),R=JJ(w),vq=R?.middleware?Array.isArray(R.middleware)?R.middleware:[R.middleware]:[],t=[...bq,...vq];if(t.length>0){let D=Gq(V,S,R||{}),M=Lq(D,null,void 0,{isServer:!0}),E=await Nq(t,M);if(E.redirect){let U=typeof E.redirect==="string"?E.redirect:E.redirect.path||E.redirect,x=QJ(String(U),V),k=ZJ(V,J);await O.promises.mkdir(j.dirname(k),{recursive:!0}),await Bun.write(k,x),W.successCount++,W.pages.push({route:V,outputPath:k,size:Buffer.byteLength(x),cached:!1}),b.push({loc:V,lastmod:new Date().toISOString()}),console.log(` \u21B3 ${V} \u2192 redirect to ${U}`);return}if(E.abort){let U=typeof E.abort==="string"?E.abort:E.abort?.error?.message||"aborted";console.warn(` \u21B3 ${V} \u2014 middleware aborted: ${U}`);return}}let e=w.match(/definePageMeta\s*\(\s*\{[\s\S]*?validate\s*:\s*((?:\([^)]*\)|[^,}])*(?:\{[\s\S]*?\})?)/m);if(e)try{if(!await Function("route",`
44
+ </rss>`}async function aq(q={}){let Z=Date.now();Aq();let $=await n(process.cwd()),Q=$.build||{},K=await Kq({explicit:q.domain||Q.domain,stxConfig:$});if(K.source==="fallback"&&(q.sitemap??Q.sitemap??!0))console.warn(Wq());let J={router:q.router??$?.router??{},pagesDir:q.pagesDir||Q.pagesDir||"pages",outputDir:q.outputDir||Q.outputDir||"dist",baseUrl:q.baseUrl||Q.baseUrl||"/",domain:K.url,revalidate:q.revalidate??Q.revalidate??!1,sitemap:q.sitemap??Q.sitemap??!0,sitemapExclude:q.sitemapExclude||Q.sitemapExclude||[],robots:q.robots??Q.robots??!0,rss:q.rss??Q.rss??!1,concurrency:q.concurrency||Q.concurrency||10,cache:q.cache??Q.cache??!0,cacheDir:q.cacheDir||Q.cacheDir||d(process.cwd(),"ssg-cache"),contentLoaders:q.contentLoaders||[],hooks:q.hooks||{},minify:q.minify??Q.minify??!0,generate404:q.generate404??Q.generate404??!0,publicDir:q.publicDir||Q.publicDir||"public",trailingSlash:q.trailingSlash??Q.trailingSlash??!1,cleanOutput:q.cleanOutput??Q.cleanOutput??!0,cacheSalt:q.cacheSalt??"",partialsDir:q.partialsDir||$?.partialsDir||"",componentsDir:q.componentsDir||$?.componentsDir||"",failOnIncludeError:q.failOnIncludeError??!0,chunkIslands:q.chunkIslands===!0,prefetchIslands:q.prefetchIslands===!0,integrityIslands:q.integrityIslands===!0},W={totalPages:0,successCount:0,failedCount:0,cachedCount:0,buildTime:0,pages:[],errors:[]},z=new Set,A=0,G={},X={};await J.hooks.onBuildStart?.();try{if(J.cleanOutput&&O.existsSync(J.outputDir))await O.promises.rm(J.outputDir,{recursive:!0});await O.promises.mkdir(J.outputDir,{recursive:!0});let L=J.cacheSalt;if(!L){let{resolveUserCssConfig:Y,fingerprintConfig:N}=await import("./chunk-xv6aydze.js");try{L=N(await Y(process.cwd()))}catch{}}let{prepareImageDelivery:_}=await import("./chunk-e631svvs.js"),F=await _(J.publicDir,J.outputDir);if(F.count>0)console.log(`Optimized ${F.count} image(s) for responsive delivery`),L=[L,F.fingerprint].filter(Boolean).join(":");let C=new wq(J.cacheDir,L);if(J.cache)await C.load();try{let{generateCss:Y}=await import("./chunk-xv6aydze.js");await Y('<div class="bg-black"></div>')}catch{}Yq();let kq=$?.routeMiddleware?.dir||"middleware";await jq(process.cwd(),kq);let p=Vq();if(p.length>0)console.log(`Loaded ${p.length} middleware: ${p.join(", ")}`);let bq=$?.routeMiddleware?.global||[];Fq($?.layoutsDir,d(process.cwd()));let i=l(".",{pagesDir:J.pagesDir,pagesDirs:$?._layerPageDirs});console.log(`Found ${i.length} routes`);let g=[];for(let Y of i){let N=await uq(Y);for(let H of N)g.push({route:Y,url:H.url,params:H.params,props:H.props,revalidate:H.revalidate??J.revalidate})}W.totalPages=g.length,console.log(`Generating ${W.totalPages} pages...`);let b=[],s=[];for(let Y=0;Y<g.length;Y+=J.concurrency)s.push(g.slice(Y,Y+J.concurrency));for(let Y of s)await Promise.all(Y.map(async(N)=>{let{route:H,url:V,params:S,props:Sq,revalidate:a}=N;try{await J.hooks.onPageStart?.(V);let w=await Bun.file(H.filePath).text(),R=JJ(w),vq=R?.middleware?Array.isArray(R.middleware)?R.middleware:[R.middleware]:[],t=[...bq,...vq];if(t.length>0){let D=Gq(V,S,R||{}),M=Lq(D,null,void 0,{isServer:!0}),E=await Nq(t,M);if(E.redirect){let U=typeof E.redirect==="string"?E.redirect:E.redirect.path||E.redirect,x=QJ(String(U),V),k=ZJ(V,J);await O.promises.mkdir(j.dirname(k),{recursive:!0}),await Bun.write(k,x),W.successCount++,W.pages.push({route:V,outputPath:k,size:Buffer.byteLength(x),cached:!1}),b.push({loc:V,lastmod:new Date().toISOString()}),console.log(` \u21B3 ${V} \u2192 redirect to ${U}`);return}if(E.abort){let U=typeof E.abort==="string"?E.abort:E.abort?.error?.message||"aborted";console.warn(` \u21B3 ${V} \u2014 middleware aborted: ${U}`);return}}let e=w.match(/definePageMeta\s*\(\s*\{[\s\S]*?validate\s*:\s*((?:\([^)]*\)|[^,}])*(?:\{[\s\S]*?\})?)/m);if(e)try{if(!await Function("route",`
45
45
  const validate = ${e[1]};
46
46
  return validate(route);
47
47
  `)({params:S})){console.warn(`Validation failed for ${V}, skipping...`);return}}catch{}let I=null,qq=!1;if(J.cache){if(I=C.get(V,H.filePath),I)qq=!0,W.cachedCount++}if(!I){let D=await Mq(H,S,Sq,J,$);if(I=D.html,J.failOnIncludeError&&D.includeFailures.length>0)throw Error(`${D.includeFailures.length} include(s) failed to resolve, so this page would have shipped with an error banner where the markup should be:
@@ -62,7 +62,7 @@ export interface TemplateExpression {
62
62
  line: number;
63
63
  /** 1-based column of the expression's first character. */
64
64
  column: number;
65
- kind: 'interpolation' | 'directive';
65
+ kind: 'interpolation' | 'directive' | 'condition';
66
66
  /** For directives, the attribute name (`:if`, `@click`, `x-text`). */
67
67
  attribute?: string;
68
68
  /**
@@ -86,6 +86,15 @@ export interface MappedLine {
86
86
  * the start of the attribute.
87
87
  */
88
88
  prefixLength?: number;
89
+ /**
90
+ * Characters of `if (…) {` wrapper before the expression's own statement.
91
+ *
92
+ * A diagnostic inside this span is about the enclosing CONDITION, not about
93
+ * the expression this line carries - and the condition is checked on a line
94
+ * of its own, so reporting it here too would name innocent markup twice
95
+ * (stacksjs/stx#2013).
96
+ */
97
+ guardPrefixLength?: number;
89
98
  }
90
99
  export interface VirtualFile {
91
100
  text: string;
@@ -463,6 +472,12 @@ export interface ResolvedPosition {
463
472
  column: number;
464
473
  /** Set when the diagnostic came from a template expression. */
465
474
  expression?: TemplateExpression;
475
+ /**
476
+ * The hit landed in the `if (…) {` wrapper that markup guards put around an
477
+ * expression, so it is about the CONDITION rather than this expression. The
478
+ * condition has a line of its own (stacksjs/stx#2013).
479
+ */
480
+ inGuard?: boolean;
466
481
  }
467
482
  /**
468
483
  * Translate a position in a virtual buffer back to the `.stx` file.
@@ -173,6 +173,35 @@ export function extractTemplateExpressions(source) {
173
173
  kind: "interpolation"
174
174
  });
175
175
  }
176
+ const condition = /@(if|elseif|else\s+if|unless)\b\s*\(/g;
177
+ while ((m = condition.exec(masked)) !== null) {
178
+ const open = m.index + m[0].length - 1;
179
+ let depth = 0, index = open;
180
+ for (;index < masked.length; index++) {
181
+ const char = masked[index];
182
+ if (char === "(")
183
+ depth++;
184
+ else if (char === ")") {
185
+ depth--;
186
+ if (depth === 0)
187
+ break;
188
+ }
189
+ }
190
+ if (depth !== 0)
191
+ continue;
192
+ const raw = masked.slice(open + 1, index), code = raw.trim();
193
+ condition.lastIndex = index + 1;
194
+ if (!code)
195
+ continue;
196
+ const start = open + 1 + (raw.length - raw.trimStart().length);
197
+ found.push({
198
+ code,
199
+ line: lineAt(masked, start),
200
+ column: columnAt(masked, start),
201
+ offset: m.index,
202
+ kind: "condition"
203
+ });
204
+ }
176
205
  DIRECTIVE_ATTR_RE.lastIndex = 0;
177
206
  while ((m = DIRECTIVE_ATTR_RE.exec(masked)) !== null) {
178
207
  const name = m[1], value = m[3] ?? "", base = name.replace(/\..*$/, "").replace(/^([^:].*?):.*$/, "$1");
@@ -505,9 +534,19 @@ export function guardChainAt(source, offset) {
505
534
  const directive = /@(if|unless|elseif|else|endif|endunless)\b\s*(\()?/g, stack = [];
506
535
  let match;
507
536
  while ((match = directive.exec(source)) !== null) {
508
- if (match.index >= offset)
537
+ if (match.index > offset)
509
538
  break;
510
539
  const name = match[1];
540
+ if (match.index === offset) {
541
+ if (name === "elseif") {
542
+ const open = stack[stack.length - 1];
543
+ if (open?.current)
544
+ open.seen.push(open.current);
545
+ if (open)
546
+ open.current = null;
547
+ }
548
+ break;
549
+ }
511
550
  if (name === "endif" || name === "endunless") {
512
551
  stack.pop();
513
552
  continue;
@@ -648,7 +687,8 @@ export function buildVirtualTypeScript(source, options = {}) {
648
687
  line: expression.line,
649
688
  column: expression.column,
650
689
  expression,
651
- prefixLength: statement.prefixLength + pad.length + guardPrefix.length
690
+ prefixLength: statement.prefixLength + pad.length + guardPrefix.length,
691
+ guardPrefixLength: pad.length + guardPrefix.length
652
692
  });
653
693
  }
654
694
  if (indent > 0)
@@ -689,6 +729,7 @@ export function resolvePosition(virtual, line, column) {
689
729
  return {
690
730
  line: mapped.line,
691
731
  column: mapped.column + within,
692
- expression: mapped.expression
732
+ expression: mapped.expression,
733
+ inGuard: column <= (mapped.guardPrefixLength ?? 0)
693
734
  };
694
735
  }
package/dist/typecheck.js CHANGED
@@ -305,6 +305,8 @@ export async function typecheckStxFiles(files, options = {}) {
305
305
  const at = resolvePosition(entry.virtual, line, column);
306
306
  if (!at?.expression)
307
307
  continue;
308
+ if (at.inGuard)
309
+ continue;
308
310
  if (Number(code) === 2774)
309
311
  continue;
310
312
  line = at.line;
@@ -708,6 +708,16 @@ export interface StxConfig {
708
708
  defaultLayout?: string;
709
709
  /** Plugins to load — npm packages, local paths, or [path, options] tuples */
710
710
  plugins?: Array<string | [string, Record<string, any>]>;
711
+ /**
712
+ * Installed packages whose components resolve by bare tag, with no plugin
713
+ * entry and no import.
714
+ *
715
+ * Each is loaded through its own `<pkg>/stx-plugin` export if the project has
716
+ * it installed, and is searched AFTER every project directory - so a
717
+ * component the app wrote still wins. Defaults to `['@stacksjs/components']`;
718
+ * set it to `[]` to opt out entirely (stacksjs/stx#2011).
719
+ */
720
+ componentPackages?: string[];
711
721
  /** Path to public/static assets directory, defaults to 'public' */
712
722
  publicDir?: string;
713
723
  /** Path to .env file, defaults to '.env' in project root (Bun loads this automatically) */
package/dist/utils.js CHANGED
@@ -740,7 +740,9 @@ export async function renderComponentWithSlot(componentPath, props, slotContent,
740
740
  const templateBlock = findSfcTemplateBlock(workingContent);
741
741
  if (templateBlock)
742
742
  workingContent = templateBlock.content.trim();
743
- const scriptRegex = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi, scriptMatches = [...componentContent.matchAll(scriptRegex)], clientScripts = [], cacheableServerComponent = scriptMatches.some((match) => /\bserver\b/.test(match[1] || "") && /\bcache\b/.test(match[1] || ""));
743
+ const scriptRegex = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi, scriptMatches = [...componentContent.matchAll(scriptRegex)], clientScripts = [];
744
+ let serverScriptFailure = null;
745
+ const cacheableServerComponent = scriptMatches.some((match) => /\bserver\b/.test(match[1] || "") && /\bcache\b/.test(match[1] || ""));
744
746
  let componentRenderCacheKey = null, dependencyBaseline = null, clientFactoryBaseline = null, uidBaseline = 0, preservedExpressionBaseline = null;
745
747
  applyComponentRenderCacheBudget(options);
746
748
  if (cacheableServerComponent && appliedComponentRenderCacheBytes > 0) {
@@ -785,7 +787,12 @@ export async function renderComponentWithSlot(componentPath, props, slotContent,
785
787
  for (const name of collectBlockDeclarations(content))
786
788
  ownServerNames.add(name);
787
789
  try {
788
- await extractVariables(content, componentContext, componentFilePath);
790
+ await extractVariables(content, componentContext, componentFilePath, {
791
+ onFailure: (failure) => {
792
+ if (failure.kind !== "unknown")
793
+ serverScriptFailure = failure.kind;
794
+ }
795
+ });
789
796
  } catch (e) {}
790
797
  }
791
798
  if (!isServerScript) {
@@ -902,6 +909,8 @@ export async function renderComponentWithSlot(componentPath, props, slotContent,
902
909
  preservedClientExpressions: preservedExpressionBaseline ? preservedNow.filter((expression) => !preservedExpressionBaseline.has(expression)) : []
903
910
  });
904
911
  }
912
+ if (serverScriptFailure)
913
+ output = `<!--stx-render-failed:${serverScriptFailure}-->${output}`;
905
914
  return callerClientScripts.length > 0 ? `${output}
906
915
  ${callerClientScripts.join(`
907
916
  `)}` : output;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/stx",
3
3
  "type": "module",
4
- "version": "0.2.346",
4
+ "version": "0.2.348",
5
5
  "description": "A performant UI Framework. Powered by Bun.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",
@@ -117,12 +117,12 @@
117
117
  "dependencies": {
118
118
  "@stacksjs/ts-css": "^0.3.2",
119
119
  "@stacksjs/clapp": "^0.2.16",
120
- "@stacksjs/desktop": "0.2.346",
121
- "@stacksjs/sanitizer": "0.2.346",
120
+ "@stacksjs/desktop": "0.2.348",
121
+ "@stacksjs/sanitizer": "0.2.348",
122
122
  "@stacksjs/ts-i18n": "^0.1.11",
123
- "bun-plugin-stx": "0.2.346",
123
+ "bun-plugin-stx": "0.2.348",
124
124
  "bunfig": "^0.15.19",
125
- "stx-router": "0.2.346",
125
+ "stx-router": "0.2.348",
126
126
  "ts-broadcasting": "^0.0.10",
127
127
  "ts-images": "^0.2.22",
128
128
  "ts-syntax-highlighter": "^0.2.1"
@@ -1,2 +0,0 @@
1
- // @bun
2
- import{Wf as a}from"./chunk-ddsgfmhv.js";import"./chunk-xytgvfbf.js";import"./chunk-57atgbyq.js";import"./chunk-9jbssgem.js";import"./chunk-e4g8wz6t.js";import"./chunk-c0n802j1.js";import"./chunk-hfvknn03.js";import"./chunk-zdq7emrd.js";import"./chunk-8y1ve8tc.js";import"./chunk-njx93b4z.js";import"./chunk-bqdfbwdf.js";import"./chunk-89mqnh67.js";import"./chunk-xvh1k1a4.js";import"./chunk-skd72bn4.js";import"./chunk-y2f41kaq.js";import"./chunk-xj6bcwqa.js";import"./chunk-21mmq3aj.js";import"./chunk-vhta1be7.js";import"./chunk-tc4pj651.js";import"./chunk-san1eq0r.js";import"./chunk-avwywzsj.js";import"./chunk-wj21f1e0.js";import"./chunk-d86q27j8.js";import"./chunk-72x62kch.js";import"./chunk-yg5r7bnm.js";import"./chunk-9nrgjtah.js";import"./chunk-ejqpq0wc.js";export{a as buildForProduction};
@@ -1,2 +0,0 @@
1
- // @bun
2
- import{Ue as a}from"./chunk-rwk5hwvk.js";import"./chunk-57atgbyq.js";import"./chunk-zdq7emrd.js";import"./chunk-8y1ve8tc.js";import"./chunk-njx93b4z.js";import"./chunk-bqdfbwdf.js";import"./chunk-89mqnh67.js";import"./chunk-xvh1k1a4.js";import"./chunk-skd72bn4.js";import"./chunk-y2f41kaq.js";import"./chunk-xj6bcwqa.js";import"./chunk-21mmq3aj.js";import"./chunk-vhta1be7.js";import"./chunk-tc4pj651.js";import"./chunk-san1eq0r.js";import"./chunk-avwywzsj.js";import"./chunk-wj21f1e0.js";import"./chunk-d86q27j8.js";import"./chunk-72x62kch.js";import"./chunk-yg5r7bnm.js";import"./chunk-9nrgjtah.js";import"./chunk-ejqpq0wc.js";export{a as buildApp};