@stacksjs/stx 0.2.355 → 0.2.357
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/dist/chunk-0c49cy69.js +2 -0
- package/dist/chunk-0chkqvs1.js +2 -0
- package/dist/chunk-0d6qgbks.js +2 -0
- package/dist/{chunk-84bhnp6p.js → chunk-0dj2gne3.js} +2 -2
- package/dist/{chunk-57atgbyq.js → chunk-0knxnyq6.js} +1 -1
- package/dist/{chunk-m6dstr44.js → chunk-0smr2xjs.js} +2 -2
- package/dist/{chunk-e4g8wz6t.js → chunk-0t1yyn1d.js} +1 -1
- package/dist/{chunk-xvh1k1a4.js → chunk-19m7hed6.js} +1 -1
- package/dist/{chunk-vhta1be7.js → chunk-1nnza3m6.js} +1 -1
- package/dist/chunk-284kattb.js +2 -0
- package/dist/{chunk-n5657hm3.js → chunk-2gtwha4k.js} +1 -1
- package/dist/{chunk-f5veee11.js → chunk-2s3wvns6.js} +1 -1
- package/dist/chunk-2x3zy811.js +2 -0
- package/dist/chunk-38mpg3kn.js +2 -0
- package/dist/chunk-3f782ywp.js +2 -0
- package/dist/{chunk-mmnf2pac.js → chunk-3kd0zn9c.js} +2 -2
- package/dist/{chunk-avye7h5s.js → chunk-3kyydhzt.js} +1 -1
- package/dist/{chunk-msq8xvhp.js → chunk-3ssjb8cx.js} +309 -312
- package/dist/{chunk-6r3aavbv.js → chunk-3y8vvkar.js} +2 -2
- package/dist/{chunk-8cc4vdkh.js → chunk-4gtsf1xw.js} +1 -1
- package/dist/chunk-4mkqzhfh.js +2 -0
- package/dist/{chunk-xj6bcwqa.js → chunk-5270fyk7.js} +1 -1
- package/dist/chunk-54w1tgzq.js +2 -0
- package/dist/chunk-5x0zjm34.js +2 -0
- package/dist/{chunk-8bxtvsgm.js → chunk-634gaa9d.js} +1 -1
- package/dist/{chunk-pwh8pbks.js → chunk-6gsgayq3.js} +1 -1
- package/dist/{chunk-a8ghkfh6.js → chunk-6qhatdte.js} +2 -2
- package/dist/{chunk-6zrg2mmc.js → chunk-6yfccnr7.js} +2 -2
- package/dist/{chunk-z23sc9p4.js → chunk-79fj9zem.js} +2 -2
- package/dist/{chunk-2ver2s2y.js → chunk-7hb89n3z.js} +1 -1
- package/dist/{chunk-05zfez2g.js → chunk-7jcntsp4.js} +1 -1
- package/dist/{chunk-nf7k53ap.js → chunk-7kw3grq5.js} +1 -1
- package/dist/chunk-7nf8azjh.js +2 -0
- package/dist/{chunk-62nz9v8t.js → chunk-7v1g7prf.js} +2 -2
- package/dist/chunk-8wgsjh65.js +2 -0
- package/dist/{chunk-34f8c48f.js → chunk-8xjasa91.js} +1 -1
- package/dist/{chunk-w5j9tbsk.js → chunk-94dz7hrj.js} +1 -1
- package/dist/{chunk-6h3r8v55.js → chunk-9qdn9y72.js} +1 -1
- package/dist/{chunk-g7msqva8.js → chunk-a4jhcbsh.js} +3 -3
- package/dist/chunk-a6x0czvr.js +2 -0
- package/dist/{chunk-72x62kch.js → chunk-aa8015mk.js} +1 -1
- package/dist/{chunk-64n10kpa.js → chunk-aacfyyya.js} +1 -1
- package/dist/chunk-abtxpqna.js +2 -0
- package/dist/{chunk-c30qnb6z.js → chunk-apbr1kb1.js} +2 -2
- package/dist/{chunk-nm60wh6r.js → chunk-awyyskad.js} +1 -1
- package/dist/{chunk-ppzz953j.js → chunk-b8ywrx2w.js} +1 -1
- package/dist/{chunk-18018jkn.js → chunk-bcpjhcpn.js} +1 -1
- package/dist/{chunk-kw9cgyfc.js → chunk-c17ybabd.js} +1 -1
- package/dist/chunk-c4rpdtvw.js +2 -0
- package/dist/{chunk-zk6ghjnj.js → chunk-c79nfdyj.js} +1 -1
- package/dist/{chunk-a1knndrh.js → chunk-cf9gt3h9.js} +10 -10
- package/dist/chunk-cgs5xpsn.js +2 -0
- package/dist/{chunk-avwywzsj.js → chunk-czj6nq0b.js} +2 -2
- package/dist/{chunk-9kmhwbwy.js → chunk-czypgdc1.js} +1 -1
- package/dist/{chunk-epqd3eah.js → chunk-degz74nv.js} +2 -2
- package/dist/chunk-dpyc7pht.js +2 -0
- package/dist/{chunk-hay8nwv3.js → chunk-dtdwjpvf.js} +2 -2
- package/dist/chunk-e0f3qs59.js +2 -0
- package/dist/{chunk-dsztk2kp.js → chunk-e48050x3.js} +1 -1
- package/dist/{chunk-3nx7z086.js → chunk-ec8jsqgm.js} +3 -3
- package/dist/{chunk-86c461ca.js → chunk-eg8k598q.js} +1 -1
- package/dist/{chunk-bgrkxzr7.js → chunk-ej8mv2k6.js} +1 -1
- package/dist/{chunk-y2f41kaq.js → chunk-ejwfnttb.js} +1 -1
- package/dist/{chunk-ejqpq0wc.js → chunk-emjmshj8.js} +1 -1
- package/dist/{chunk-59906baj.js → chunk-ep034wt0.js} +1 -1
- package/dist/{chunk-njx93b4z.js → chunk-ez003q74.js} +1 -1
- package/dist/{chunk-ws0282jr.js → chunk-f11z7q5g.js} +1 -1
- package/dist/{chunk-g5mhck0r.js → chunk-f2jypsax.js} +2 -2
- package/dist/chunk-f3eb1f6z.js +2 -0
- package/dist/{chunk-6k5a03pw.js → chunk-f72c62s7.js} +2 -2
- package/dist/{chunk-1z1efvtw.js → chunk-fqq5k9ve.js} +1 -1
- package/dist/{chunk-c0n802j1.js → chunk-frp9fc7j.js} +1 -1
- package/dist/chunk-fzq2n865.js +2 -0
- package/dist/{chunk-g6czgcg4.js → chunk-g1vxsvqv.js} +1 -1
- package/dist/chunk-g3cmkyk2.js +2 -0
- package/dist/{chunk-7r9vgzg4.js → chunk-g7bpkpd4.js} +1 -1
- package/dist/{chunk-at622hg0.js → chunk-gn2qc03b.js} +1 -1
- package/dist/chunk-gxgrzeeh.js +2 -0
- package/dist/{chunk-a9w1ds4w.js → chunk-h99qxgbr.js} +1 -1
- package/dist/{chunk-dgv43ccd.js → chunk-hcf8399w.js} +1 -1
- package/dist/{chunk-hbkjzx1h.js → chunk-hh0aaxxy.js} +1 -1
- package/dist/{chunk-tc4pj651.js → chunk-hkrzv980.js} +2 -2
- package/dist/{chunk-7qp3zphs.js → chunk-hy79zwyy.js} +2 -2
- package/dist/chunk-j6kec9kp.js +2 -0
- package/dist/{chunk-e631svvs.js → chunk-j8wycqve.js} +1 -1
- package/dist/chunk-jmdxn2mq.js +2 -0
- package/dist/{chunk-a959m68j.js → chunk-k33778kc.js} +1 -1
- package/dist/{chunk-wvc7t11n.js → chunk-kaet6r9w.js} +1 -1
- package/dist/{chunk-9e20mgwc.js → chunk-kjd9hbg4.js} +3 -3
- package/dist/{chunk-8m0g0h4x.js → chunk-krt45cqy.js} +2 -2
- package/dist/{chunk-2wb3pgp4.js → chunk-kyyt9xhs.js} +1 -1
- package/dist/chunk-m0eg86q3.js +20 -0
- package/dist/{chunk-0k1mtwby.js → chunk-mdbj7sq8.js} +1 -1
- package/dist/{chunk-d86q27j8.js → chunk-mere396d.js} +1 -1
- package/dist/{chunk-1c9453w0.js → chunk-ms25gb16.js} +1 -1
- package/dist/{chunk-ym3r8ktq.js → chunk-n0d7nwhd.js} +1 -1
- package/dist/{chunk-7h9fajgs.js → chunk-n1y0hjk1.js} +2 -2
- package/dist/{chunk-bk1zb1xp.js → chunk-n5tpqzcb.js} +1 -1
- package/dist/{chunk-b5hank5e.js → chunk-nybn003d.js} +2 -2
- package/dist/chunk-p78b80dp.js +2 -0
- package/dist/chunk-pr3hz3ec.js +2 -0
- package/dist/{chunk-gtqbvt3a.js → chunk-q4kgqqed.js} +2 -2
- package/dist/{chunk-san1eq0r.js → chunk-qbz6yn8c.js} +2 -2
- package/dist/{chunk-fvsefztj.js → chunk-qjvny3wf.js} +1 -1
- package/dist/{chunk-v0e259x2.js → chunk-qnptmtqh.js} +1 -1
- package/dist/{chunk-msywnv5n.js → chunk-qrvey4wk.js} +2 -2
- package/dist/{chunk-7we3xfde.js → chunk-ra1s4s6b.js} +1 -1
- package/dist/{chunk-99b5tfxc.js → chunk-rcbt11p8.js} +1 -1
- package/dist/{chunk-9nrgjtah.js → chunk-rtfwn4cm.js} +1 -1
- package/dist/chunk-rydb5n5b.js +2 -0
- package/dist/chunk-sa6cgj9h.js +2 -0
- package/dist/chunk-skdfq4hq.js +2 -0
- package/dist/{chunk-ngjkzaj7.js → chunk-t23kccpz.js} +3 -3
- package/dist/{chunk-89mqnh67.js → chunk-tf16jtj4.js} +1 -1
- package/dist/{chunk-swvm1wgn.js → chunk-trva71am.js} +2 -2
- package/dist/{chunk-rwwfzkz4.js → chunk-tv04k7gq.js} +1 -1
- package/dist/{chunk-5wbdbcvf.js → chunk-v1qm7p7t.js} +2 -2
- package/dist/chunk-w1a8dwgx.js +2 -0
- package/dist/chunk-w9gserf7.js +2 -0
- package/dist/{chunk-y6xzr30x.js → chunk-wkyt4j9e.js} +1 -1
- package/dist/{chunk-p3p4d6g1.js → chunk-wz4fnsat.js} +2 -2
- package/dist/chunk-x131a0jq.js +2 -0
- package/dist/{chunk-f5cw54q3.js → chunk-x21hdhjw.js} +1 -1
- package/dist/chunk-x5b8az2h.js +2 -0
- package/dist/chunk-xk782v5z.js +2 -0
- package/dist/chunk-xxrv2p42.js +2 -0
- package/dist/{chunk-qsbjtp60.js → chunk-y4nzmkea.js} +1 -1
- package/dist/{chunk-sqvqwd0p.js → chunk-y4zddt5r.js} +1 -1
- package/dist/{chunk-vgfd9582.js → chunk-ya5m5vbn.js} +1 -1
- package/dist/{chunk-1vb2rj09.js → chunk-yg0qm73a.js} +2 -2
- package/dist/{chunk-8y1ve8tc.js → chunk-ykevda74.js} +2 -2
- package/dist/chunk-ynj1y0qm.js +2 -0
- package/dist/{chunk-v6e35j4g.js → chunk-z50ex86m.js} +1 -1
- package/dist/chunk-z8gccz1q.js +2 -0
- package/dist/{chunk-wj21f1e0.js → chunk-zxfejz72.js} +1 -1
- package/dist/chunk-zxnf0c9x.js +2 -0
- package/dist/cli.js +14 -14
- package/dist/craft-entry.js +1 -1
- package/dist/craft.js +1 -1
- package/dist/database.js +1 -1
- package/dist/engine-bindings.d.ts +35 -0
- package/dist/engine-bindings.js +55 -0
- package/dist/pwa.js +2 -2
- package/dist/ssg.js +2 -2
- package/dist/stx-module-imports.d.ts +24 -0
- package/dist/stx-module-imports.js +57 -0
- package/dist/stx-module.d.ts +154 -0
- package/dist/stx-plugin-config.d.ts +17 -0
- package/dist/stx-plugin-config.js +42 -0
- package/dist/stx-virtual-ts.d.ts +74 -1
- package/dist/stx-virtual-ts.js +81 -21
- package/dist/typecheck.d.ts +13 -0
- package/dist/typecheck.js +82 -64
- package/dist/variable-extractor.d.ts +2 -22
- package/dist/variable-extractor.js +3 -55
- package/dist/visual-testing.js +1 -1
- package/package.json +7 -6
- package/stx-module.d.ts +154 -0
- package/dist/chunk-04x3vny9.js +0 -19
- package/dist/chunk-1apnswz7.js +0 -2
- package/dist/chunk-1qvf8ase.js +0 -2
- package/dist/chunk-1vt1h19d.js +0 -2
- package/dist/chunk-32x78na8.js +0 -2
- package/dist/chunk-3z4d7kmp.js +0 -2
- package/dist/chunk-4b2vsawv.js +0 -2
- package/dist/chunk-616fn77w.js +0 -2
- package/dist/chunk-70zk8tj2.js +0 -2
- package/dist/chunk-86q2h34b.js +0 -2
- package/dist/chunk-88e14er7.js +0 -2
- package/dist/chunk-8yydz0hk.js +0 -2
- package/dist/chunk-a7yxvxke.js +0 -2
- package/dist/chunk-aanwshk6.js +0 -2
- package/dist/chunk-ahfj7dc7.js +0 -2
- package/dist/chunk-bed5f4bp.js +0 -2
- package/dist/chunk-dxkjvajv.js +0 -2
- package/dist/chunk-e7np0h2q.js +0 -2
- package/dist/chunk-erb294sv.js +0 -2
- package/dist/chunk-evfr2zgg.js +0 -2
- package/dist/chunk-f85f75jh.js +0 -2
- package/dist/chunk-gsc2vds7.js +0 -2
- package/dist/chunk-h5jt4mxx.js +0 -2
- package/dist/chunk-hke0k33t.js +0 -2
- package/dist/chunk-hysq9e9t.js +0 -2
- package/dist/chunk-kq30wqp6.js +0 -2
- package/dist/chunk-m2j5skez.js +0 -2
- package/dist/chunk-ntzzhw3w.js +0 -2
- package/dist/chunk-px0bs815.js +0 -2
- package/dist/chunk-qw92p9za.js +0 -2
- package/dist/chunk-rjwnw5hj.js +0 -2
- package/dist/chunk-tmr3xq5d.js +0 -2
- package/dist/chunk-tpk6wm38.js +0 -2
- package/dist/chunk-vw4b7g24.js +0 -2
- package/dist/chunk-x054qzma.js +0 -2
- package/dist/chunk-x2n1x19t.js +0 -2
- package/dist/chunk-zks9ft7n.js +0 -2
- package/dist/chunk-zkxnarrh.js +0 -2
- package/dist/chunk-zp14ksx1.js +0 -2
package/dist/ssg.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{Ck as Fq,xk as Uq,yk as Iq}from"./chunk-wz4fnsat.js";import{Dk as Eq,Ek as Tq,Fk as Dq}from"./chunk-frp9fc7j.js";import{_k as _q,bl as zq,cl as Aq}from"./chunk-degz74nv.js";import"./chunk-t23kccpz.js";import"./chunk-qjvny3wf.js";import{Kp as P,Tm as Oq,jo as l,mo as Hq,wr as n}from"./chunk-3ssjb8cx.js";import"./chunk-ykevda74.js";import"./chunk-ez003q74.js";import"./chunk-kyyt9xhs.js";import"./chunk-tf16jtj4.js";import"./chunk-19m7hed6.js";import{mt as Xq}from"./chunk-kjd9hbg4.js";import{rt as d}from"./chunk-ejwfnttb.js";import"./chunk-5270fyk7.js";import"./chunk-q4kgqqed.js";import"./chunk-1nnza3m6.js";import{Yt as Bq}from"./chunk-hkrzv980.js";import"./chunk-qbz6yn8c.js";import"./chunk-czj6nq0b.js";import"./chunk-zxfejz72.js";import"./chunk-mere396d.js";import"./chunk-aa8015mk.js";import{Aw as Nq,vw as Yq,ww as Vq,xw as jq,yw as Gq,zw as Lq}from"./chunk-trva71am.js";import"./chunk-rtfwn4cm.js";import{Rw as y}from"./chunk-emjmshj8.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-
|
|
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-3kyydhzt.js");try{L=N(await Y(process.cwd()))}catch{}}let{prepareImageDelivery:_}=await import("./chunk-j8wycqve.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-3kyydhzt.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:
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ScriptBlock, ScriptKind } from './stx-virtual-ts';
|
|
2
|
+
/**
|
|
3
|
+
* Names imported from `stx` into a block kind that does not receive them.
|
|
4
|
+
*
|
|
5
|
+
* A name the module does not export at all is left alone: TypeScript already
|
|
6
|
+
* reports it (TS2305), and saying it twice helps nobody.
|
|
7
|
+
*/
|
|
8
|
+
export declare function stxImportDiagnostics(source: string, blocks: readonly ScriptBlock[]): StxImportDiagnostic[];
|
|
9
|
+
/** Names `import { … } from 'stx'` binds in a `<script server>` block. */
|
|
10
|
+
export declare const STX_SERVER_MODULE_EXPORTS: readonly string[];
|
|
11
|
+
/** Names `import { … } from 'stx'` binds in a client block. */
|
|
12
|
+
export declare const STX_CLIENT_MODULE_EXPORTS: readonly string[];
|
|
13
|
+
/** Every value `stx-module.d.ts` exports: what at least one block kind gets. */
|
|
14
|
+
export declare const STX_MODULE_EXPORTS: readonly string[];
|
|
15
|
+
/** A name imported from `stx` into a block that does not receive it. */
|
|
16
|
+
export declare interface StxImportDiagnostic {
|
|
17
|
+
line: number
|
|
18
|
+
column: number
|
|
19
|
+
offset: number
|
|
20
|
+
length: number
|
|
21
|
+
name: string
|
|
22
|
+
kind: ScriptKind
|
|
23
|
+
message: string
|
|
24
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { STX_ENGINE_BINDING_NAMES } from "./engine-bindings.js";
|
|
2
|
+
import { STX_RUNTIME_GLOBALS } from "./runtime-globals.js";
|
|
3
|
+
const ENVIRONMENT_BINDINGS = new Set([
|
|
4
|
+
"module",
|
|
5
|
+
"exports",
|
|
6
|
+
"require",
|
|
7
|
+
"$bool",
|
|
8
|
+
"window",
|
|
9
|
+
"document",
|
|
10
|
+
"console",
|
|
11
|
+
"confirm",
|
|
12
|
+
"alert",
|
|
13
|
+
"fetch"
|
|
14
|
+
]);
|
|
15
|
+
export const STX_SERVER_MODULE_EXPORTS = STX_ENGINE_BINDING_NAMES.filter((name) => !ENVIRONMENT_BINDINGS.has(name)).sort(), STX_CLIENT_MODULE_EXPORTS = [...STX_RUNTIME_GLOBALS].sort(), STX_MODULE_EXPORTS = [...new Set([...STX_SERVER_MODULE_EXPORTS, ...STX_CLIENT_MODULE_EXPORTS])].sort();
|
|
16
|
+
const SERVER = new Set(STX_SERVER_MODULE_EXPORTS), CLIENT = new Set(STX_CLIENT_MODULE_EXPORTS), EXPORTED = new Set(STX_MODULE_EXPORTS), STX_IMPORT_RE = /\bimport\s+(?!type[\s{])\{([^}]*)\}\s*from\s*(['"])stx\2/g;
|
|
17
|
+
function messageFor(name, kind) {
|
|
18
|
+
if (kind === "server")
|
|
19
|
+
return `'${name}' is not provided by 'stx' in a <script server> block. The engine binds only its own names there (defineProps, state, useHead, ...); any other name becomes \`await import('stx')\`, which does not resolve, so the whole script fails when the page renders. Import it from '@stacksjs/stx' instead.`;
|
|
20
|
+
return `'${name}' is not provided by 'stx' in a client <script> block. The import is replaced by the window.stx runtime, which has no '${name}', so it is undefined in the browser.`;
|
|
21
|
+
}
|
|
22
|
+
export function stxImportDiagnostics(source, blocks) {
|
|
23
|
+
const diagnostics = [];
|
|
24
|
+
for (const block of blocks) {
|
|
25
|
+
if (block.offset === void 0)
|
|
26
|
+
continue;
|
|
27
|
+
const provided = block.kind === "server" ? SERVER : CLIENT;
|
|
28
|
+
STX_IMPORT_RE.lastIndex = 0;
|
|
29
|
+
for (const match of block.code.matchAll(STX_IMPORT_RE)) {
|
|
30
|
+
const listStart = match.index + match[0].indexOf("{") + 1;
|
|
31
|
+
for (const specifier of match[1].matchAll(/[^,]+/g)) {
|
|
32
|
+
const text = specifier[0];
|
|
33
|
+
if (/^\s*type\s/.test(text))
|
|
34
|
+
continue;
|
|
35
|
+
const imported = /^\s*([A-Za-z_$][\w$]*)/.exec(text);
|
|
36
|
+
if (!imported)
|
|
37
|
+
continue;
|
|
38
|
+
const name = imported[1];
|
|
39
|
+
if (!EXPORTED.has(name) || provided.has(name))
|
|
40
|
+
continue;
|
|
41
|
+
const offset = block.offset + listStart + specifier.index + imported[0].length - name.length, before = source.slice(0, offset), line = before.split(`
|
|
42
|
+
`).length;
|
|
43
|
+
diagnostics.push({
|
|
44
|
+
line,
|
|
45
|
+
column: offset - (before.lastIndexOf(`
|
|
46
|
+
`) + 1) + 1,
|
|
47
|
+
offset,
|
|
48
|
+
length: name.length,
|
|
49
|
+
name,
|
|
50
|
+
kind: block.kind,
|
|
51
|
+
message: messageFor(name, block.kind)
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return diagnostics;
|
|
57
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/// <reference path="./stx.d.ts" />
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `stx` module, as a `.stx` script block sees it.
|
|
5
|
+
*
|
|
6
|
+
* `stx` is a VIRTUAL specifier. No package by that name is installed in an app,
|
|
7
|
+
* and `import { … } from 'stx'` works only because both script paths intercept
|
|
8
|
+
* it: a client block's import is stripped and its names destructured off
|
|
9
|
+
* `window.stx`, and a server block's names are handed in by the engine as
|
|
10
|
+
* parameters. So what this module exports is exactly what those two paths bind,
|
|
11
|
+
* and nothing else from `@stacksjs/stx` (see src/stx-module-imports.ts):
|
|
12
|
+
*
|
|
13
|
+
* - every name destructured off `window.stx` (STX_RUNTIME_GLOBALS), which a
|
|
14
|
+
* server block also receives where the engine binds it, and
|
|
15
|
+
* - the stx API names only the server engine binds, marked below.
|
|
16
|
+
*
|
|
17
|
+
* Each value is typed by the ambient global of the same name in `stx.d.ts`, so
|
|
18
|
+
* an imported `state` is exactly the auto-imported one; the module adds no
|
|
19
|
+
* second copy of any signature to drift.
|
|
20
|
+
*
|
|
21
|
+
* This file is NOT referenced from the package's types entry, on purpose. The
|
|
22
|
+
* specifier is virtual only inside a `.stx` block; a `.ts` file importing from
|
|
23
|
+
* `stx` has a real import that does not resolve. `stx typecheck` and the editor
|
|
24
|
+
* plugin add it to the programs they build for `.stx` files.
|
|
25
|
+
*
|
|
26
|
+
* Which block kind gets which name is checked separately, because one
|
|
27
|
+
* declaration cannot say it: `stxImportDiagnostics` reports a server-only name
|
|
28
|
+
* imported into a client block and the reverse.
|
|
29
|
+
*
|
|
30
|
+
* test/stx-module-declaration.test.ts keeps this list equal to the runtime's.
|
|
31
|
+
*/
|
|
32
|
+
declare module 'stx' {
|
|
33
|
+
export const $props: Record<string, any> // <script server> only
|
|
34
|
+
export const batch: typeof globalThis.batch
|
|
35
|
+
export const clearServerData: typeof globalThis.clearServerData
|
|
36
|
+
export const computed: typeof globalThis.computed
|
|
37
|
+
export const configureFetch: typeof globalThis.configureFetch
|
|
38
|
+
export const defineClientPayload: (payload: Record<string, unknown>) => void // <script server> only
|
|
39
|
+
export const defineEmits: typeof globalThis.defineEmits
|
|
40
|
+
export const defineExpose: typeof globalThis.defineExpose
|
|
41
|
+
export const definePageMeta: typeof globalThis.definePageMeta
|
|
42
|
+
export const defineProps: typeof globalThis.defineProps
|
|
43
|
+
export const defineSlots: typeof globalThis.defineSlots
|
|
44
|
+
export const defineStore: typeof globalThis.defineStore
|
|
45
|
+
export const derived: typeof globalThis.derived
|
|
46
|
+
export const effect: typeof globalThis.effect
|
|
47
|
+
export const goBack: typeof globalThis.goBack
|
|
48
|
+
export const goForward: typeof globalThis.goForward
|
|
49
|
+
export const inject: typeof globalThis.inject
|
|
50
|
+
export const invalidateRoute: typeof globalThis.invalidateRoute
|
|
51
|
+
export const isDerived: typeof globalThis.isDerived
|
|
52
|
+
export const isSignal: typeof globalThis.isSignal
|
|
53
|
+
export const navigate: typeof globalThis.navigate
|
|
54
|
+
export const nextTick: typeof globalThis.nextTick
|
|
55
|
+
export const notFound: (status?: number) => void // <script server> only
|
|
56
|
+
export const onBeforeMount: typeof globalThis.onBeforeMount
|
|
57
|
+
export const onBeforeUnmount: typeof globalThis.onBeforeUnmount
|
|
58
|
+
export const onDestroy: typeof globalThis.onDestroy
|
|
59
|
+
export const onMount: typeof globalThis.onMount
|
|
60
|
+
export const onMounted: typeof globalThis.onMounted
|
|
61
|
+
export const onUnmounted: typeof globalThis.onUnmounted
|
|
62
|
+
export const params: Record<string, string> // <script server> only
|
|
63
|
+
export const peek: typeof globalThis.peek
|
|
64
|
+
export const props: Record<string, any> // <script server> only
|
|
65
|
+
export const provide: typeof globalThis.provide
|
|
66
|
+
export const reactive: typeof globalThis.reactive
|
|
67
|
+
export const ref: typeof globalThis.ref
|
|
68
|
+
export const refresh: typeof globalThis.refresh
|
|
69
|
+
export const registerStoresClient: typeof globalThis.registerStoresClient
|
|
70
|
+
export const setResponseHeader: (name: string, value: string) => void // <script server> only
|
|
71
|
+
export const setResponseStatus: (status: number) => void // <script server> only
|
|
72
|
+
export const setRouteParams: typeof globalThis.setRouteParams
|
|
73
|
+
export const state: typeof globalThis.state
|
|
74
|
+
export const untrack: typeof globalThis.untrack
|
|
75
|
+
export const useAsync: typeof globalThis.useAsync
|
|
76
|
+
export const useClickOutside: typeof globalThis.useClickOutside
|
|
77
|
+
export const useColorMode: typeof globalThis.useColorMode
|
|
78
|
+
export const useCookie: typeof globalThis.useCookie
|
|
79
|
+
export const useCounter: typeof globalThis.useCounter
|
|
80
|
+
export const useDark: typeof globalThis.useDark
|
|
81
|
+
export const useDebounce: typeof globalThis.useDebounce
|
|
82
|
+
export const useDebouncedValue: typeof globalThis.useDebouncedValue
|
|
83
|
+
export const useDocumentVisibility: typeof globalThis.useDocumentVisibility
|
|
84
|
+
export const useEventListener: typeof globalThis.useEventListener
|
|
85
|
+
export const useFetch: typeof globalThis.useFetch
|
|
86
|
+
export const useFocus: typeof globalThis.useFocus
|
|
87
|
+
export const useHead: typeof globalThis.useHead
|
|
88
|
+
export const useId: typeof globalThis.useId
|
|
89
|
+
export const useInterval: typeof globalThis.useInterval
|
|
90
|
+
export const useLocalStorage: typeof globalThis.useLocalStorage
|
|
91
|
+
export const useMediaQuery: typeof globalThis.useMediaQuery
|
|
92
|
+
export const useModel: typeof globalThis.useModel
|
|
93
|
+
export const useMutation: typeof globalThis.useMutation
|
|
94
|
+
export const useOptimistic: typeof globalThis.useOptimistic
|
|
95
|
+
export const usePreferredContrast: typeof globalThis.usePreferredContrast
|
|
96
|
+
export const usePreferredDark: typeof globalThis.usePreferredDark
|
|
97
|
+
export const usePreferredLight: typeof globalThis.usePreferredLight
|
|
98
|
+
export const usePreferredReducedMotion: typeof globalThis.usePreferredReducedMotion
|
|
99
|
+
export const useQuery: typeof globalThis.useQuery
|
|
100
|
+
export const useReactiveProp: typeof globalThis.useReactiveProp
|
|
101
|
+
export const useRef: typeof globalThis.useRef
|
|
102
|
+
export const useRoute: typeof globalThis.useRoute
|
|
103
|
+
export const useRouteParam: typeof globalThis.useRouteParam
|
|
104
|
+
export const useRouteParams: typeof globalThis.useRouteParams
|
|
105
|
+
export const useRouter: () => { push: (to: unknown) => void, replace: (to: unknown) => void, back: () => void, forward: () => void, go: (n: number) => void } // <script server> only
|
|
106
|
+
export const useRuntimeConfig: () => Readonly<Record<string, any>> // <script server> only
|
|
107
|
+
export const useScrollLock: typeof globalThis.useScrollLock
|
|
108
|
+
export const useSearchParams: typeof globalThis.useSearchParams
|
|
109
|
+
export const useSeoMeta: typeof globalThis.useSeoMeta
|
|
110
|
+
export const useServerData: typeof globalThis.useServerData // <script server> only
|
|
111
|
+
export const useServerRuntimeConfig: () => Readonly<{ public: Record<string, any>, private: Record<string, any> }> // <script server> only
|
|
112
|
+
export const useSessionStorage: typeof globalThis.useSessionStorage
|
|
113
|
+
export const useSlots: typeof globalThis.useSlots
|
|
114
|
+
export const useStore: typeof globalThis.useStore
|
|
115
|
+
export const useThrottle: typeof globalThis.useThrottle
|
|
116
|
+
export const useTimeout: typeof globalThis.useTimeout
|
|
117
|
+
export const useToggle: typeof globalThis.useToggle
|
|
118
|
+
export const useWebSocket: typeof globalThis.useWebSocket
|
|
119
|
+
export const watch: typeof globalThis.watch
|
|
120
|
+
export const watchEffect: typeof globalThis.watchEffect
|
|
121
|
+
export const watchMultiple: typeof globalThis.watchMultiple
|
|
122
|
+
export const withDefaults: typeof globalThis.withDefaults
|
|
123
|
+
|
|
124
|
+
export type StxSignal<T> = globalThis.StxSignal<T>
|
|
125
|
+
export type StxDerivedSignal<T> = globalThis.StxDerivedSignal<T>
|
|
126
|
+
export type StxRef<T> = globalThis.StxRef<T>
|
|
127
|
+
export type StxCleanup = globalThis.StxCleanup
|
|
128
|
+
export type StxModelOptions<T> = globalThis.StxModelOptions<T>
|
|
129
|
+
export type StxModelSignal<T> = globalThis.StxModelSignal<T>
|
|
130
|
+
export type StxTemplateRef<T> = globalThis.StxTemplateRef<T>
|
|
131
|
+
export type StxNavigateOptions = globalThis.StxNavigateOptions
|
|
132
|
+
export type StxSearchParamsCommitOptions = globalThis.StxSearchParamsCommitOptions
|
|
133
|
+
export type StxRefetchOptions = globalThis.StxRefetchOptions
|
|
134
|
+
export type StxFetchResult<T> = globalThis.StxFetchResult<T>
|
|
135
|
+
export type StxQueryResult<T> = globalThis.StxQueryResult<T>
|
|
136
|
+
export type StxMutationResult<T> = globalThis.StxMutationResult<T>
|
|
137
|
+
export type StxFetchRequestContext = globalThis.StxFetchRequestContext
|
|
138
|
+
export type StxFetchResponseContext = globalThis.StxFetchResponseContext
|
|
139
|
+
export type StxFetchErrorContext = globalThis.StxFetchErrorContext
|
|
140
|
+
export type StxEventListenerOptions = globalThis.StxEventListenerOptions
|
|
141
|
+
export type StxIntervalOptions = globalThis.StxIntervalOptions
|
|
142
|
+
export type StxIntervalControls = globalThis.StxIntervalControls
|
|
143
|
+
export type StxCookieOptions = globalThis.StxCookieOptions
|
|
144
|
+
export type StxColorModeOptions = globalThis.StxColorModeOptions
|
|
145
|
+
export type StxHeadConfig = globalThis.StxHeadConfig
|
|
146
|
+
export type StxSeoMetaConfig = globalThis.StxSeoMetaConfig
|
|
147
|
+
export type StxToastOptions = globalThis.StxToastOptions
|
|
148
|
+
export type StxToast = globalThis.StxToast
|
|
149
|
+
export type StxModal = globalThis.StxModal
|
|
150
|
+
export type StxDrawer = globalThis.StxDrawer
|
|
151
|
+
export type StxDialogOptions = globalThis.StxDialogOptions
|
|
152
|
+
export type StxStorePersistOptions = globalThis.StxStorePersistOptions
|
|
153
|
+
export type StxStoreOptions = globalThis.StxStoreOptions
|
|
154
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** The nearest `tsconfig.json` at or above `startDir`. */
|
|
2
|
+
export declare function findNearestTsconfig(startDir: string, exists: (file: string) => boolean): string | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* The stx plugin entry governing files under `startDir`, following `extends`.
|
|
5
|
+
*
|
|
6
|
+
* Only relative `extends` are followed; a package base (`@tsconfig/…`) does not
|
|
7
|
+
* carry an app's stx configuration.
|
|
8
|
+
*/
|
|
9
|
+
export declare function findStxPluginEntry(startDir: string, read: ReadConfig, exists: (file: string) => boolean): StxPluginEntry | undefined;
|
|
10
|
+
/** The name the stx TypeScript plugin is contributed and configured under. */
|
|
11
|
+
export declare const STX_TS_PLUGIN_NAME: '@stacksjs/stx-typescript-plugin';
|
|
12
|
+
export declare interface StxPluginEntry {
|
|
13
|
+
configPath: string
|
|
14
|
+
libs: string[]
|
|
15
|
+
}
|
|
16
|
+
/** Read a tsconfig file as an object, or undefined when it cannot be read. */
|
|
17
|
+
export type ReadConfig = (file: string) => Record<string, any> | undefined;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export const STX_TS_PLUGIN_NAME = "@stacksjs/stx-typescript-plugin";
|
|
3
|
+
export function findNearestTsconfig(startDir, exists) {
|
|
4
|
+
let dir = path.resolve(startDir);
|
|
5
|
+
for (;; ) {
|
|
6
|
+
const candidate = path.join(dir, "tsconfig.json");
|
|
7
|
+
if (exists(candidate))
|
|
8
|
+
return candidate;
|
|
9
|
+
const parent = path.dirname(dir);
|
|
10
|
+
if (parent === dir)
|
|
11
|
+
return;
|
|
12
|
+
dir = parent;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function findStxPluginEntry(startDir, read, exists) {
|
|
16
|
+
const leaf = findNearestTsconfig(startDir, exists);
|
|
17
|
+
if (!leaf)
|
|
18
|
+
return;
|
|
19
|
+
const seen = new Set, visit = (configPath) => {
|
|
20
|
+
if (seen.has(configPath))
|
|
21
|
+
return;
|
|
22
|
+
seen.add(configPath);
|
|
23
|
+
const config = read(configPath);
|
|
24
|
+
if (!config)
|
|
25
|
+
return;
|
|
26
|
+
const plugins = config.compilerOptions?.plugins;
|
|
27
|
+
if (Array.isArray(plugins)) {
|
|
28
|
+
const entry = plugins.find((plugin) => plugin?.name === STX_TS_PLUGIN_NAME), libs = Array.isArray(entry?.libs) ? entry.libs.filter((lib) => typeof lib === "string") : [];
|
|
29
|
+
return entry ? { configPath, libs: libs.map((lib) => path.resolve(path.dirname(configPath), lib)) } : null;
|
|
30
|
+
}
|
|
31
|
+
const bases = typeof config.extends === "string" ? [config.extends] : Array.isArray(config.extends) ? config.extends : [];
|
|
32
|
+
for (const base of [...bases].reverse()) {
|
|
33
|
+
if (typeof base !== "string" || !base.startsWith("."))
|
|
34
|
+
continue;
|
|
35
|
+
const resolved = path.resolve(path.dirname(configPath), base.endsWith(".json") ? base : `${base}.json`), found = visit(resolved);
|
|
36
|
+
if (found !== void 0)
|
|
37
|
+
return found;
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
};
|
|
41
|
+
return visit(leaf) ?? void 0;
|
|
42
|
+
}
|
package/dist/stx-virtual-ts.d.ts
CHANGED
|
@@ -49,6 +49,15 @@ export interface ScriptBlock {
|
|
|
49
49
|
code: string;
|
|
50
50
|
/** 1-based line in the source file where the body's first character sits. */
|
|
51
51
|
startLine: number;
|
|
52
|
+
/**
|
|
53
|
+
* 1-based column of the body's first character. Greater than 1 when the
|
|
54
|
+
* code starts on the line the opening tag is on (`<script client>const a`),
|
|
55
|
+
* which a buffer has to pad for or every diagnostic on that line lands
|
|
56
|
+
* left of the code it is about.
|
|
57
|
+
*/
|
|
58
|
+
startColumn?: number;
|
|
59
|
+
/** Offset of the body's first character in the source. */
|
|
60
|
+
offset?: number;
|
|
52
61
|
/** The opening tag's attributes, trimmed. */
|
|
53
62
|
attrs: string;
|
|
54
63
|
}
|
|
@@ -99,6 +108,8 @@ export interface MappedLine {
|
|
|
99
108
|
export interface VirtualFile {
|
|
100
109
|
text: string;
|
|
101
110
|
componentDependencies?: Map<string, string>;
|
|
111
|
+
/** Whether the `reference` option's directive was written (line 1 was free). */
|
|
112
|
+
referenced?: boolean;
|
|
102
113
|
/**
|
|
103
114
|
* Virtual 1-based line → where it came from.
|
|
104
115
|
*
|
|
@@ -239,7 +250,17 @@ export declare function runtimeGlobalDeclarations(): string;
|
|
|
239
250
|
* checker report a genuine typo instead of suppressing every unresolved name.
|
|
240
251
|
*/
|
|
241
252
|
export declare const STX_SERVER_CONTEXT: readonly ['params', 'query', 'cookies', 'host', 'ip', 'setResponseStatus', 'setResponseHeader', 'notFound', 'request', 'url', 'definePageMeta', 'defineClientPayload', 'defineStore', 'props', '$props'];
|
|
242
|
-
export declare function serverContextDeclarations(): string;
|
|
253
|
+
export declare function serverContextDeclarations(typed?: ReadonlySet<string>): string;
|
|
254
|
+
/**
|
|
255
|
+
* Names a global declaration file declares as values: `declare function`,
|
|
256
|
+
* `declare const` / `let` / `var`, at the start of a line.
|
|
257
|
+
*
|
|
258
|
+
* Used to keep the `any` fallbacks below from colliding with a TYPED global of
|
|
259
|
+
* the same name in `stx.d.ts` — `definePageMeta` and `defineStore` are both
|
|
260
|
+
* server context and typed runtime globals, and `declare var x: any` beside
|
|
261
|
+
* `declare function x()` is a conflict that leaves the name typed by neither.
|
|
262
|
+
*/
|
|
263
|
+
export declare function declaredGlobalNames(declarations: string): Set<string>;
|
|
243
264
|
/**
|
|
244
265
|
* The names a `defineClientPayload({ … })` call publishes, or `null` when the
|
|
245
266
|
* page does not declare one.
|
|
@@ -421,6 +442,19 @@ export declare function expressionStatement(expression: TemplateExpression): {
|
|
|
421
442
|
* change a line count, so every diagnostic still lands on the author's line.
|
|
422
443
|
*/
|
|
423
444
|
export declare function absolutizeRelativeSpecifiers(code: string, originDir: string): string;
|
|
445
|
+
/**
|
|
446
|
+
* Spaces that put a block's first line at the column it occupies in the file.
|
|
447
|
+
*
|
|
448
|
+
* A body that starts on the opening tag's line (`<script client>const a = 1`)
|
|
449
|
+
* was written from column 1, so every diagnostic on that line pointed left of
|
|
450
|
+
* the code it was about by the width of the tag.
|
|
451
|
+
*/
|
|
452
|
+
export declare function firstLinePadding(block: ScriptBlock): string;
|
|
453
|
+
/**
|
|
454
|
+
* Local names a block's `import` declarations bind, type-only ones included:
|
|
455
|
+
* `import a, { b as c, type D } from 'x'` and `import * as ns from 'x'`.
|
|
456
|
+
*/
|
|
457
|
+
export declare function collectImportedNames(code: string): string[];
|
|
424
458
|
export interface BuildVirtualOptions {
|
|
425
459
|
/** Enables component call-site checks using the renderer's file lookup. */
|
|
426
460
|
filePath?: string;
|
|
@@ -438,6 +472,28 @@ export interface BuildVirtualOptions {
|
|
|
438
472
|
originDir?: string;
|
|
439
473
|
/** Append ambient declarations at all. Default true. */
|
|
440
474
|
globals?: boolean;
|
|
475
|
+
/**
|
|
476
|
+
* Where the server context, the `@stacksjs/browser` auto-imports and the
|
|
477
|
+
* template globals are declared. Default `'module'`.
|
|
478
|
+
*
|
|
479
|
+
* `'global'` wraps them in `declare global { … }`. Declared in the module
|
|
480
|
+
* they share a scope with the author's own bindings, so a block's
|
|
481
|
+
* `const { query } = defineProps()` is a redeclaration of the context's
|
|
482
|
+
* `query`; declared globally, the block's binding shadows it instead, as it
|
|
483
|
+
* does in `stx typecheck`, whose context is a global file. The editor, which
|
|
484
|
+
* has one buffer per file, needs the global form.
|
|
485
|
+
*/
|
|
486
|
+
contextScope?: 'module' | 'global';
|
|
487
|
+
/**
|
|
488
|
+
* A declaration file to pull into the program with a triple-slash
|
|
489
|
+
* reference, written on the buffer's first line.
|
|
490
|
+
*
|
|
491
|
+
* That line is always blank when the file opens with markup or with a
|
|
492
|
+
* `<script>` tag on a line of its own, which is how every real file starts,
|
|
493
|
+
* so nothing moves. When code sits on line 1 the reference is left out and
|
|
494
|
+
* {@link VirtualFile.referenced} says so, so the caller can fall back.
|
|
495
|
+
*/
|
|
496
|
+
reference?: string;
|
|
441
497
|
/**
|
|
442
498
|
* Declare the stx runtime globals as `any`. Default true.
|
|
443
499
|
*
|
|
@@ -479,6 +535,23 @@ export interface ResolvedPosition {
|
|
|
479
535
|
*/
|
|
480
536
|
inGuard?: boolean;
|
|
481
537
|
}
|
|
538
|
+
/**
|
|
539
|
+
* Whether a diagnostic on a template-expression line is an artefact of how the
|
|
540
|
+
* expression was wrapped rather than a fault in it. Both checkers drop these,
|
|
541
|
+
* so the editor and `stx typecheck` agree:
|
|
542
|
+
*
|
|
543
|
+
* - A hit inside the `if (…) {` wrapper that markup guards put around an
|
|
544
|
+
* expression is about the enclosing CONDITION, which is checked on a line
|
|
545
|
+
* of its own. This copy would report the same fault again against innocent
|
|
546
|
+
* markup (stacksjs/stx#2013).
|
|
547
|
+
* - TS2774 ("this condition will always return true since this function is
|
|
548
|
+
* always defined") is wrong about a template, and only about a template.
|
|
549
|
+
* {@link UNWRAP_HELPER} types a signal as the intersection of the signal and
|
|
550
|
+
* its value, which stays callable, and the runtime unwraps a name the
|
|
551
|
+
* expression only reads — so `x-class="ready ? '' : 'hidden'"` does not
|
|
552
|
+
* always return true. In a script block it is a true positive and is kept.
|
|
553
|
+
*/
|
|
554
|
+
export declare function isTemplateArtefact(position: ResolvedPosition, code: number): boolean;
|
|
482
555
|
/**
|
|
483
556
|
* Translate a position in a virtual buffer back to the `.stx` file.
|
|
484
557
|
*
|
package/dist/stx-virtual-ts.js
CHANGED
|
@@ -20,7 +20,7 @@ export function extractScriptBlocks(source) {
|
|
|
20
20
|
if (typeMatch && !/^(?:module|text\/(?:javascript|typescript))$/i.test(typeMatch[1]))
|
|
21
21
|
continue;
|
|
22
22
|
const kind = /\bserver\b/.test(attrs) ? "server" : /\bclient\b/.test(attrs) ? "client" : "plain", startLine = lineAt(source, bodyStart);
|
|
23
|
-
blocks.push({ kind, code: body, startLine, attrs });
|
|
23
|
+
blocks.push({ kind, code: body, startLine, startColumn: columnAt(source, bodyStart), offset: bodyStart, attrs });
|
|
24
24
|
}
|
|
25
25
|
return blocks;
|
|
26
26
|
}
|
|
@@ -340,10 +340,13 @@ export const STX_SERVER_CONTEXT = [
|
|
|
340
340
|
"props",
|
|
341
341
|
"$props"
|
|
342
342
|
];
|
|
343
|
-
export function serverContextDeclarations() {
|
|
344
|
-
return STX_SERVER_CONTEXT.map((name) => `declare var ${name}: any`).join(`
|
|
343
|
+
export function serverContextDeclarations(typed = new Set) {
|
|
344
|
+
return STX_SERVER_CONTEXT.filter((name) => !typed.has(name)).map((name) => `declare var ${name}: any`).join(`
|
|
345
345
|
`);
|
|
346
346
|
}
|
|
347
|
+
export function declaredGlobalNames(declarations) {
|
|
348
|
+
return new Set([...declarations.matchAll(/^declare (?:function|const|let|var)\s+([A-Za-z_$][\w$]*)/gm)].map((match) => match[1]));
|
|
349
|
+
}
|
|
347
350
|
export function extractClientPayloadNames(serverCode) {
|
|
348
351
|
const call = /\bdefineClientPayload\s*\(\s*\{([\s\S]*?)\}\s*\)/g;
|
|
349
352
|
let match, found = !1;
|
|
@@ -608,6 +611,27 @@ export function absolutizeRelativeSpecifiers(code, originDir) {
|
|
|
608
611
|
return `${prefix}${quote}${absolute}${quote}`;
|
|
609
612
|
});
|
|
610
613
|
}
|
|
614
|
+
export function firstLinePadding(block) {
|
|
615
|
+
return " ".repeat(Math.max(0, (block.startColumn ?? 1) - 1));
|
|
616
|
+
}
|
|
617
|
+
export function collectImportedNames(code) {
|
|
618
|
+
const names = new Set, stripped = stripCommentsAndLiterals(code);
|
|
619
|
+
for (const match of stripped.matchAll(/\bimport\s+(?:type\s+)?([\w$*{}\s,]+?)\s+from\b/g)) {
|
|
620
|
+
const clause = match[1], named = /\{([^}]*)\}/.exec(clause);
|
|
621
|
+
for (const part of named?.[1].split(",") ?? []) {
|
|
622
|
+
const local = part.trim().replace(/^type\s+/, "").split(/\s+as\s+/).pop()?.trim();
|
|
623
|
+
if (local && /^[A-Z_$][\w$]*$/i.test(local))
|
|
624
|
+
names.add(local);
|
|
625
|
+
}
|
|
626
|
+
const outside = clause.replace(/\{[^}]*\}/, ""), namespace = /\*\s*as\s+([A-Z_$][\w$]*)/i.exec(outside);
|
|
627
|
+
if (namespace)
|
|
628
|
+
names.add(namespace[1]);
|
|
629
|
+
const defaultName = /^\s*([A-Z_$][\w$]*)/i.exec(outside);
|
|
630
|
+
if (defaultName && defaultName[1] !== "type")
|
|
631
|
+
names.add(defaultName[1]);
|
|
632
|
+
}
|
|
633
|
+
return [...names].sort();
|
|
634
|
+
}
|
|
611
635
|
export function buildVirtualTypeScript(source, options = {}) {
|
|
612
636
|
const blocks = extractScriptBlocks(source), sourceLines = source.split(`
|
|
613
637
|
`), lines = Array.from({ length: sourceLines.length }, () => ""), lineMap = new Map, components = options.filePath && options.templateExpressions !== !1 ? componentContractChecks(source, maskNonTemplateRegions(source), {
|
|
@@ -617,14 +641,24 @@ export function buildVirtualTypeScript(source, options = {}) {
|
|
|
617
641
|
readComponent: options.readComponent,
|
|
618
642
|
scriptCode: (text, file) => extractScriptBlocks(text).map((block) => absolutizeRelativeSpecifiers(block.code, path.dirname(file))).join(`
|
|
619
643
|
`)
|
|
620
|
-
}) : void 0;
|
|
621
|
-
for (const block of blocks)
|
|
622
|
-
|
|
623
|
-
`)
|
|
644
|
+
}) : void 0, occupied = new Set, blockEnds = [];
|
|
645
|
+
for (const block of blocks) {
|
|
646
|
+
const code = blankScriptDirectives(substituteInterpolationsInPlace(block.code)), bodyLines = absolutizeRelativeSpecifiers(code, options.originDir ?? "").split(`
|
|
647
|
+
`);
|
|
648
|
+
bodyLines.forEach((text, i) => {
|
|
624
649
|
const index = block.startLine - 1 + i;
|
|
625
|
-
if (index < lines.length)
|
|
626
|
-
lines[index] = text;
|
|
650
|
+
if (index < lines.length) {
|
|
651
|
+
lines[index] = i === 0 ? firstLinePadding(block) + text : text;
|
|
652
|
+
occupied.add(index);
|
|
653
|
+
}
|
|
627
654
|
});
|
|
655
|
+
blockEnds.push(block.startLine - 1 + bodyLines.length - 1);
|
|
656
|
+
}
|
|
657
|
+
for (const end of blockEnds) {
|
|
658
|
+
const at = lines[end]?.trim() === "" ? end : end + 1;
|
|
659
|
+
if (at < lines.length && lines[at].trim() === "" && (at === end || !occupied.has(at)))
|
|
660
|
+
lines[at] = ";";
|
|
661
|
+
}
|
|
628
662
|
const append = (text, origin) => {
|
|
629
663
|
for (const [index, line] of text.split(`
|
|
630
664
|
`).entries()) {
|
|
@@ -635,17 +669,33 @@ export function buildVirtualTypeScript(source, options = {}) {
|
|
|
635
669
|
};
|
|
636
670
|
if (options.globals !== !1) {
|
|
637
671
|
append("");
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
`)
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
672
|
+
const bound = new Set([
|
|
673
|
+
...blocks.flatMap((block) => collectBlockDeclarations(block.code)),
|
|
674
|
+
...blocks.flatMap((block) => collectImportedNames(block.code))
|
|
675
|
+
]), declareAny = (name) => {
|
|
676
|
+
if (!bound.has(name))
|
|
677
|
+
append(`declare var ${name}: any`);
|
|
678
|
+
};
|
|
679
|
+
if (options.runtimeGlobals !== !1) {
|
|
680
|
+
if (!bound.has("window"))
|
|
681
|
+
append("declare var window: any");
|
|
682
|
+
for (const name of STX_RUNTIME_GLOBALS)
|
|
683
|
+
declareAny(name);
|
|
684
|
+
}
|
|
685
|
+
const contextNames = [...new Set([...STX_SERVER_CONTEXT, ...BROWSER_CORE_IMPORTS, ...STX_TEMPLATE_GLOBALS])].filter((name) => options.runtimeGlobals !== !1 || !STX_RUNTIME_GLOBALS.includes(name));
|
|
686
|
+
if (options.contextScope === "global") {
|
|
687
|
+
append("declare global {");
|
|
688
|
+
for (const name of contextNames)
|
|
689
|
+
append(` var ${name}: any`);
|
|
690
|
+
append("}");
|
|
691
|
+
} else {
|
|
692
|
+
for (const name of STX_SERVER_CONTEXT)
|
|
693
|
+
declareAny(name);
|
|
694
|
+
for (const name of BROWSER_CORE_IMPORTS)
|
|
695
|
+
declareAny(name);
|
|
696
|
+
for (const name of STX_TEMPLATE_GLOBALS)
|
|
697
|
+
declareAny(name);
|
|
698
|
+
}
|
|
649
699
|
append(`declare var ${INTERPOLATION_PLACEHOLDER}: any`);
|
|
650
700
|
const declared = new Set(blocks.flatMap((block) => collectBlockDeclarations(block.code)));
|
|
651
701
|
append(`type ${ELEMENT_HELPER}<T> = T extends readonly (infer E)[] ? E : T extends Iterable<infer E2> ? E2 : any`);
|
|
@@ -695,9 +745,14 @@ export function buildVirtualTypeScript(source, options = {}) {
|
|
|
695
745
|
append("});");
|
|
696
746
|
}
|
|
697
747
|
}
|
|
748
|
+
let referenced = !1;
|
|
749
|
+
if (options.reference && lines[0] !== void 0 && lines[0].trim() === "") {
|
|
750
|
+
lines[0] = `/// <reference path=${JSON.stringify(options.reference.replace(/\\/g, "/"))} />`;
|
|
751
|
+
referenced = !0;
|
|
752
|
+
}
|
|
698
753
|
append("export {}");
|
|
699
754
|
return { text: lines.join(`
|
|
700
|
-
`), lineMap, sourceLineCount: sourceLines.length, componentDependencies: components?.dependencies };
|
|
755
|
+
`), lineMap, sourceLineCount: sourceLines.length, componentDependencies: components?.dependencies, referenced };
|
|
701
756
|
}
|
|
702
757
|
export function lineStarts(text) {
|
|
703
758
|
const starts = [0];
|
|
@@ -721,6 +776,11 @@ export function positionToOffset(starts, line, column) {
|
|
|
721
776
|
const index = Math.min(Math.max(line, 1), starts.length) - 1, next = index + 1 < starts.length ? starts[index + 1] - 1 : Number.MAX_SAFE_INTEGER;
|
|
722
777
|
return Math.min(starts[index] + Math.max(column, 1) - 1, next);
|
|
723
778
|
}
|
|
779
|
+
export function isTemplateArtefact(position, code) {
|
|
780
|
+
if (!position.expression)
|
|
781
|
+
return !1;
|
|
782
|
+
return position.inGuard === !0 || code === 2774;
|
|
783
|
+
}
|
|
724
784
|
export function resolvePosition(virtual, line, column) {
|
|
725
785
|
const mapped = virtual.lineMap.get(line);
|
|
726
786
|
if (!mapped)
|
package/dist/typecheck.d.ts
CHANGED
|
@@ -34,6 +34,19 @@ export declare function sourcePathFor(virtualPath: string): string;
|
|
|
34
34
|
* than hand tsc a path to nothing.
|
|
35
35
|
*/
|
|
36
36
|
export declare function findRuntimeTypeDeclarations(): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Locate the package's own `stx-module.d.ts`, which declares the virtual `stx`
|
|
39
|
+
* module a `.stx` block imports from.
|
|
40
|
+
*
|
|
41
|
+
* It used to be generated here as `declare module 'stx' { export * from
|
|
42
|
+
* '@stacksjs/stx' }`, which typed `from 'stx'` as the whole package. That is
|
|
43
|
+
* not what the specifier binds: a client block gets only what is destructured
|
|
44
|
+
* off `window.stx`, a server block only what the engine passes in, and every
|
|
45
|
+
* other name fails at runtime (stacksjs/stx#2028). The declaration file says
|
|
46
|
+
* exactly that, and the editor plugin loads the same one, so the two checkers
|
|
47
|
+
* cannot disagree about it.
|
|
48
|
+
*/
|
|
49
|
+
export declare function findStxModuleDeclarations(): string | null;
|
|
37
50
|
export declare function typecheckStxFiles(files: string[], options?: TypecheckOptions): Promise<TypecheckResult>;
|
|
38
51
|
/** Render diagnostics the way a CLI should: file:line:col, then the message. */
|
|
39
52
|
export declare function formatTypecheckDiagnostics(diagnostics: TypecheckDiagnostic[]): string;
|