@deneb-ui/cli 2.0.18 → 2.0.20

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/bin/index.js CHANGED
@@ -935,7 +935,7 @@ Options:
935
935
 
936
936
  console.log(`[Step 1/2] Running Fivora preflight validation in ${targetDir}...\n`);
937
937
 
938
- const validatorScript = path.join(toolsDir, 'fivora-template-validator.cjs');
938
+ const validatorScript = path.join(toolsDir, 'deneb-template-validator.cjs');
939
939
  const valRes = spawnSync(process.execPath, [validatorScript, 'validate', targetDir, ...extraArgs], {
940
940
  stdio: 'inherit',
941
941
  });
@@ -1177,7 +1177,7 @@ if (command === 'init') {
1177
1177
  const cleanArgs = commandArgs.filter((a) => a !== '--zip' && a !== '-z');
1178
1178
  runValidateAndZip(cleanArgs[0] || '.', cleanArgs.slice(1));
1179
1179
  } else {
1180
- const script = path.join(toolsDir, 'fivora-template-validator.cjs');
1180
+ const script = path.join(toolsDir, 'deneb-template-validator.cjs');
1181
1181
  const res = spawnSync(process.execPath, [script, 'validate', ...commandArgs], { stdio: 'inherit' });
1182
1182
  process.exit(res.status ?? 0);
1183
1183
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deneb-ui/cli",
3
- "version": "2.0.18",
3
+ "version": "2.0.20",
4
4
  "description": "Official developer CLI for DENEB UI — Validating, scaffolding, testing, and packaging storefront templates. Created by Chamika Gayashan & Induranga Kawishwara.",
5
5
  "bin": {
6
6
  "deneb": "bin/index.js",
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  var oi=Object.create;var ge=Object.defineProperty;var si=Object.getOwnPropertyDescriptor;var ai=Object.getOwnPropertyNames;var li=Object.getPrototypeOf,ci=Object.prototype.hasOwnProperty;var $=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(n){throw t=0,n}},di=(e,t)=>{for(var n in t)ge(e,n,{get:t[n],enumerable:!0})},St=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ai(t))!ci.call(e,r)&&r!==n&&ge(e,r,{get:()=>t[r],enumerable:!(i=si(t,r))||i.enumerable});return e};var wt=(e,t,n)=>(n=e!=null?oi(li(e)):{},St(t||!e||!e.__esModule?ge(n,"default",{value:e,enumerable:!0}):n,e)),ui=e=>St(ge({},"__esModule",{value:!0}),e);var Ue=$((Wr,Tt)=>{Tt.exports={LOCHDR:30,LOCSIG:67324752,LOCVER:4,LOCFLG:6,LOCHOW:8,LOCTIM:10,LOCCRC:14,LOCSIZ:18,LOCLEN:22,LOCNAM:26,LOCEXT:28,EXTSIG:134695760,EXTHDR:16,EXTCRC:4,EXTSIZ:8,EXTLEN:12,CENHDR:46,CENSIG:33639248,CENVEM:4,CENVER:6,CENFLG:8,CENHOW:10,CENTIM:12,CENCRC:16,CENSIZ:20,CENLEN:24,CENNAM:28,CENEXT:30,CENCOM:32,CENDSK:34,CENATT:36,CENATX:38,CENOFF:42,ENDHDR:22,ENDSIG:101010256,ENDSUB:8,ENDTOT:10,ENDSIZ:12,ENDOFF:16,ENDCOM:20,END64HDR:20,END64SIG:117853008,END64START:4,END64OFF:8,END64NUMDISKS:16,ZIP64SIG:101075792,ZIP64HDR:56,ZIP64LEAD:12,ZIP64SIZE:4,ZIP64VEM:12,ZIP64VER:14,ZIP64DSK:16,ZIP64DSKDIR:20,ZIP64SUB:24,ZIP64TOT:32,ZIP64SIZB:40,ZIP64OFF:48,ZIP64EXTRA:56,STORED:0,SHRUNK:1,REDUCED1:2,REDUCED2:3,REDUCED3:4,REDUCED4:5,IMPLODED:6,DEFLATED:8,ENHANCED_DEFLATED:9,PKWARE:10,BZIP2:12,LZMA:14,IBM_TERSE:18,IBM_LZ77:19,AES_ENCRYPT:99,FLG_ENC:1,FLG_COMP1:2,FLG_COMP2:4,FLG_DESC:8,FLG_ENH:16,FLG_PATCH:32,FLG_STR:64,FLG_EFS:2048,FLG_MSK:4096,FILE:2,BUFFER:1,NONE:0,EF_ID:0,EF_SIZE:2,ID_ZIP64:1,ID_AVINFO:7,ID_PFS:8,ID_OS2:9,ID_NTFS:10,ID_OPENVMS:12,ID_UNIX:13,ID_FORK:14,ID_PATCH:15,ID_X509_PKCS7:20,ID_X509_CERTID_F:21,ID_X509_CERTID_C:22,ID_STRONGENC:23,ID_RECORD_MGT:24,ID_X509_PKCS7_RL:25,ID_IBM1:101,ID_IBM2:102,ID_POSZIP:18064,EF_ZIP64_OR_32:4294967295,EF_ZIP64_OR_16:65535,EF_ZIP64_SUNCOMP:0,EF_ZIP64_SCOMP:8,EF_ZIP64_RHO:16,EF_ZIP64_DSN:24}});var he=$(It=>{var bt={INVALID_LOC:"Invalid LOC header (bad signature)",INVALID_CEN:"Invalid CEN header (bad signature)",INVALID_END:"Invalid END header (bad signature)",DESCRIPTOR_NOT_EXIST:"No descriptor present",DESCRIPTOR_UNKNOWN:"Unknown descriptor format",DESCRIPTOR_FAULTY:"Descriptor data is malformed",NO_DATA:"Nothing to decompress",BAD_CRC:"CRC32 checksum failed {0}",FILE_IN_THE_WAY:"There is a file in the way: {0}",UNKNOWN_METHOD:"Invalid/unsupported compression method",AVAIL_DATA:"inflate::Available inflate data did not terminate",INVALID_DISTANCE:"inflate::Invalid literal/length or distance code in fixed or dynamic block",TO_MANY_CODES:"inflate::Dynamic block code description: too many length or distance codes",INVALID_REPEAT_LEN:"inflate::Dynamic block code description: repeat more than specified lengths",INVALID_REPEAT_FIRST:"inflate::Dynamic block code description: repeat lengths with no first length",INCOMPLETE_CODES:"inflate::Dynamic block code description: code lengths codes incomplete",INVALID_DYN_DISTANCE:"inflate::Dynamic block code description: invalid distance code lengths",INVALID_CODES_LEN:"inflate::Dynamic block code description: invalid literal/length code lengths",INVALID_STORE_BLOCK:"inflate::Stored block length did not match one's complement",INVALID_BLOCK_TYPE:"inflate::Invalid block type (type == 3)",CANT_EXTRACT_FILE:"Could not extract the file",CANT_OVERRIDE:"Target file already exists",DISK_ENTRY_TOO_LARGE:"Number of disk entries is too large",NO_ZIP:"No zip file was loaded",NO_ENTRY:"Entry doesn't exist",DIRECTORY_CONTENT_ERROR:"A directory cannot have content",FILE_NOT_FOUND:'File not found: "{0}"',NOT_IMPLEMENTED:"Not implemented",INVALID_FILENAME:"Invalid filename",INVALID_FORMAT:"Invalid or unsupported zip format. No END header found",INVALID_PASS_PARAM:"Incompatible password parameter",WRONG_PASSWORD:"Wrong Password",COMMENT_TOO_LONG:"Comment is too long",EXTRA_FIELD_PARSE_ERROR:"Extra field parsing error"};function fi(e){return function(...t){return t.length&&(e=e.replace(/\{(\d)\}/g,(n,i)=>t[i]||"")),new Error("ADM-ZIP: "+e)}}for(let e of Object.keys(bt))It[e]=fi(bt[e])});var Ft=$((Xr,xt)=>{var mi=require("fs"),O=require("path"),Pt=Ue(),pi=he(),gi=typeof process=="object"&&process.platform==="win32",Ct=e=>typeof e=="object"&&e!==null,At=new Uint32Array(256).map((e,t)=>{for(let n=0;n<8;n++)(t&1)!==0?t=3988292384^t>>>1:t>>>=1;return t>>>0});function R(e){this.sep=O.sep,this.fs=mi,Ct(e)&&Ct(e.fs)&&typeof e.fs.statSync=="function"&&(this.fs=e.fs)}xt.exports=R;R.prototype.makeDir=function(e){let t=this;function n(i){let r=i.split(t.sep)[0];i.split(t.sep).forEach(function(o){if(!(!o||o.substr(-1,1)===":")){r+=t.sep+o;var s;try{s=t.fs.statSync(r)}catch(l){if(l.message&&l.message.startsWith("ENOENT"))t.fs.mkdirSync(r);else throw l}if(s&&s.isFile())throw pi.FILE_IN_THE_WAY(`"${r}"`)}})}n(e)};R.prototype.writeFileTo=function(e,t,n,i){let r=this;if(r.fs.existsSync(e)){if(!n)return!1;var o=r.fs.statSync(e);if(o.isDirectory())return!1}var s=O.dirname(e);r.fs.existsSync(s)||r.makeDir(s);var l;try{l=r.fs.openSync(e,"w",438)}catch{r.fs.chmodSync(e,438),l=r.fs.openSync(e,"w",438)}if(l)try{r.fs.writeSync(l,t,0,t.length,0)}finally{r.fs.closeSync(l)}return r.fs.chmodSync(e,i||438),!0};R.prototype.writeFileToAsync=function(e,t,n,i,r){typeof i=="function"&&(r=i,i=void 0);let o=this;o.fs.exists(e,function(s){if(s&&!n)return r(!1);o.fs.stat(e,function(l,f){if(s&&f.isDirectory())return r(!1);var u=O.dirname(e);o.fs.exists(u,function(d){d||o.makeDir(u),o.fs.open(e,"w",438,function(g,b){g?o.fs.chmod(e,438,function(){o.fs.open(e,"w",438,function(c,p){o.fs.write(p,t,0,t.length,0,function(){o.fs.close(p,function(){o.fs.chmod(e,i||438,function(){r(!0)})})})})}):b?o.fs.write(b,t,0,t.length,0,function(){o.fs.close(b,function(){o.fs.chmod(e,i||438,function(){r(!0)})})}):o.fs.chmod(e,i||438,function(){r(!0)})})})})})};R.prototype.findFiles=function(e){let t=this;function n(i,r,o){typeof r=="boolean"&&(o=r,r=void 0);let s=[];return t.fs.readdirSync(i).forEach(function(l){let f=O.join(i,l),u=t.fs.statSync(f);(!r||r.test(f))&&s.push(O.normalize(f)+(u.isDirectory()?t.sep:"")),u.isDirectory()&&o&&(s=s.concat(n(f,r,o)))}),s}return n(e,void 0,!0)};R.prototype.findFilesAsync=function(e,t){let n=this,i=[];n.fs.readdir(e,function(r,o){if(r)return t(r);let s=o.length;if(!s)return t(null,i);o.forEach(function(l){l=O.join(e,l),n.fs.stat(l,function(f,u){if(f)return t(f);u&&(i.push(O.normalize(l)+(u.isDirectory()?n.sep:"")),u.isDirectory()?n.findFilesAsync(l,function(d,g){if(d)return t(d);i=i.concat(g),--s||t(null,i)}):--s||t(null,i))})})})};R.prototype.getAttributes=function(){};R.prototype.setAttributes=function(){};R.crc32update=function(e,t){return At[(e^t)&255]^e>>>8};R.crc32=function(e){typeof e=="string"&&(e=Buffer.from(e,"utf8"));let t=e.length,n=-1;for(let i=0;i<t;)n=R.crc32update(n,e[i++]);return~n>>>0};R.methodToString=function(e){switch(e){case Pt.STORED:return"STORED ("+e+")";case Pt.DEFLATED:return"DEFLATED ("+e+")";default:return"UNSUPPORTED ("+e+")"}};R.canonical=function(e){if(!e)return"";let t=O.posix.normalize("/"+e.split("\\").join("/"));return O.join(".",t)};R.zipnamefix=function(e){if(!e)return"";let t=O.posix.normalize("/"+e.split("\\").join("/"));return O.posix.join(".",t)};R.findLast=function(e,t){if(!Array.isArray(e))throw new TypeError("arr is not array");let n=e.length>>>0;for(let i=n-1;i>=0;i--)if(t(e[i],i,e))return e[i]};R.sanitize=function(e,t){e=O.resolve(O.normalize(e));for(var n=t.split("/"),i=0,r=n.length;i<r;i++){var o=O.normalize(O.join(e,n.slice(i,r).join(O.sep)));if(o===e||o.startsWith(e+O.sep))return o}return O.normalize(O.join(e,O.basename(t)))};R.toBuffer=function(t,n){return Buffer.isBuffer(t)?t:t instanceof Uint8Array?Buffer.from(t):typeof t=="string"?n(t):Buffer.alloc(0)};R.readBigUInt64LE=function(e,t){let n=e.readUInt32LE(t);return e.readUInt32LE(t+4)*4294967296+n};R.writeBigUInt64LE=function(e,t,n){let i=t>>>0,r=Math.floor(t/4294967296)>>>0;e.writeUInt32LE(i,n),e.writeUInt32LE(r,n+4)};R.fromDOS2Date=function(e){return new Date((e>>25&127)+1980,Math.max((e>>21&15)-1,0),Math.max(e>>16&31,1),e>>11&31,e>>5&63,(e&31)<<1)};R.fromDate2DOS=function(e){let t=0,n=0;return e.getFullYear()>1979&&(t=(e.getFullYear()-1980&127)<<9|e.getMonth()+1<<5|e.getDate(),n=e.getHours()<<11|e.getMinutes()<<5|e.getSeconds()>>1),t<<16|n};R.isWin=gi;R.crcTable=At});var kt=$((Yr,vt)=>{var hi=require("path");vt.exports=function(e,{fs:t}){var n=e||"",i=o(),r=null;function o(){return{directory:!1,readonly:!1,hidden:!1,executable:!1,mtime:0,atime:0}}return n&&t.existsSync(n)?(r=t.statSync(n),i.directory=r.isDirectory(),i.mtime=r.mtime,i.atime=r.atime,i.executable=(73&r.mode)!==0,i.readonly=(128&r.mode)===0,i.hidden=hi.basename(n)[0]==="."):console.warn("Invalid path: "+n),{get directory(){return i.directory},get readOnly(){return i.readonly},get hidden(){return i.hidden},get mtime(){return i.mtime},get atime(){return i.atime},get executable(){return i.executable},decodeAttributes:function(){},encodeAttributes:function(){},toJSON:function(){return{path:n,isDirectory:i.directory,isReadOnly:i.readonly,isHidden:i.hidden,isExecutable:i.executable,mTime:i.mtime,aTime:i.atime}},toString:function(){return JSON.stringify(this.toJSON(),null," ")}}}});var Rt=$((Jr,Lt)=>{Lt.exports={efs:!0,encode:e=>Buffer.from(e,"utf8"),decode:e=>e.toString("utf8")}});var se=$((Qr,oe)=>{oe.exports=Ft();oe.exports.Constants=Ue();oe.exports.Errors=he();oe.exports.FileAttr=kt();oe.exports.decoder=Rt()});var Dt=$((eo,_t)=>{var Y=se(),I=Y.Constants;_t.exports=function(){var e=20,t=10,n=0,i=0,r=0,o=0,s=0,l=0,f=0,u=0,d=0,g=0,b=0,c=0,p=0;e|=Y.isWin?2560:768,n|=I.FLG_EFS;let y={extraLen:0},m=a=>Math.max(0,a)>>>0,E=a=>Math.max(0,a)&65535,w=a=>Math.max(0,a)&255;return r=Y.fromDate2DOS(new Date),{get made(){return e},set made(a){e=a},get version(){return t},set version(a){t=a},get flags(){return n},set flags(a){n=a},get flags_efs(){return(n&I.FLG_EFS)>0},set flags_efs(a){a?n|=I.FLG_EFS:n&=~I.FLG_EFS},get flags_desc(){return(n&I.FLG_DESC)>0},set flags_desc(a){a?n|=I.FLG_DESC:n&=~I.FLG_DESC},get method(){return i},set method(a){switch(a){case I.STORED:this.version=10;break;case I.DEFLATED:default:this.version=20}i=a},get time(){return Y.fromDOS2Date(this.timeval)},set time(a){a=new Date(a),this.timeval=Y.fromDate2DOS(a)},get timeval(){return r},set timeval(a){r=m(a)},get timeHighByte(){return w(r>>>8)},get crc(){return o},set crc(a){o=m(a)},get compressedSize(){return s},set compressedSize(a){s=m(a)},get size(){return l},set size(a){l=m(a)},get fileNameLength(){return f},set fileNameLength(a){f=a},get extraLength(){return u},set extraLength(a){u=a},get extraLocalLength(){return y.extraLen},set extraLocalLength(a){y.extraLen=a},get commentLength(){return d},set commentLength(a){d=a},get diskNumStart(){return g},set diskNumStart(a){g=m(a)},get inAttr(){return b},set inAttr(a){b=m(a)},get attr(){return c},set attr(a){c=m(a)},get fileAttr(){return(c||0)>>16&4095},get offset(){return p},set offset(a){p=m(a)},get encrypted(){return(n&I.FLG_ENC)===I.FLG_ENC},get centralHeaderSize(){return I.CENHDR+f+u+d},get realDataOffset(){return p+I.LOCHDR+y.fnameLen+y.extraLen},get localHeader(){return y},loadLocalHeaderFromBinary:function(a){var h=a.slice(p,p+I.LOCHDR);if(h.readUInt32LE(0)!==I.LOCSIG)throw Y.Errors.INVALID_LOC();y.version=h.readUInt16LE(I.LOCVER),y.flags=h.readUInt16LE(I.LOCFLG),y.flags_desc=(y.flags&I.FLG_DESC)>0,y.method=h.readUInt16LE(I.LOCHOW),y.time=h.readUInt32LE(I.LOCTIM),y.crc=h.readUInt32LE(I.LOCCRC),y.compressedSize=h.readUInt32LE(I.LOCSIZ),y.size=h.readUInt32LE(I.LOCLEN),y.fnameLen=h.readUInt16LE(I.LOCNAM),y.extraLen=h.readUInt16LE(I.LOCEXT);let S=p+I.LOCHDR+y.fnameLen,T=S+y.extraLen;return a.slice(S,T)},loadFromBinary:function(a){if(a.length!==I.CENHDR||a.readUInt32LE(0)!==I.CENSIG)throw Y.Errors.INVALID_CEN();e=a.readUInt16LE(I.CENVEM),t=a.readUInt16LE(I.CENVER),n=a.readUInt16LE(I.CENFLG),i=a.readUInt16LE(I.CENHOW),r=a.readUInt32LE(I.CENTIM),o=a.readUInt32LE(I.CENCRC),s=a.readUInt32LE(I.CENSIZ),l=a.readUInt32LE(I.CENLEN),f=a.readUInt16LE(I.CENNAM),u=a.readUInt16LE(I.CENEXT),d=a.readUInt16LE(I.CENCOM),g=a.readUInt16LE(I.CENDSK),b=a.readUInt16LE(I.CENATT),c=a.readUInt32LE(I.CENATX),p=a.readUInt32LE(I.CENOFF)},localHeaderToBinary:function(){var a=Buffer.alloc(I.LOCHDR);return a.writeUInt32LE(I.LOCSIG,0),a.writeUInt16LE(t,I.LOCVER),a.writeUInt16LE(n&~I.FLG_DESC,I.LOCFLG),a.writeUInt16LE(i,I.LOCHOW),a.writeUInt32LE(r,I.LOCTIM),a.writeUInt32LE(o,I.LOCCRC),a.writeUInt32LE(s,I.LOCSIZ),a.writeUInt32LE(l,I.LOCLEN),a.writeUInt16LE(f,I.LOCNAM),a.writeUInt16LE(y.extraLen,I.LOCEXT),a},centralHeaderToBinary:function(){var a=Buffer.alloc(I.CENHDR+f+u+d);return a.writeUInt32LE(I.CENSIG,0),a.writeUInt16LE(e,I.CENVEM),a.writeUInt16LE(t,I.CENVER),a.writeUInt16LE(n&~I.FLG_DESC,I.CENFLG),a.writeUInt16LE(i,I.CENHOW),a.writeUInt32LE(r,I.CENTIM),a.writeUInt32LE(o,I.CENCRC),a.writeUInt32LE(s,I.CENSIZ),a.writeUInt32LE(l,I.CENLEN),a.writeUInt16LE(f,I.CENNAM),a.writeUInt16LE(u,I.CENEXT),a.writeUInt16LE(d,I.CENCOM),a.writeUInt16LE(g,I.CENDSK),a.writeUInt16LE(b,I.CENATT),a.writeUInt32LE(c,I.CENATX),a.writeUInt32LE(p,I.CENOFF),a},toJSON:function(){let a=function(h){return h+" bytes"};return{made:e,version:t,flags:n,method:Y.methodToString(i),time:this.time,crc:"0x"+o.toString(16).toUpperCase(),compressedSize:a(s),size:a(l),fileNameLength:a(f),extraLength:a(u),commentLength:a(d),diskNumStart:g,inAttr:b,attr:c,offset:p,centralHeaderSize:a(I.CENHDR+f+u+d)}},toString:function(){return JSON.stringify(this.toJSON(),null," ")}}}});var Ot=$((to,Nt)=>{var Z=se(),C=Z.Constants;Nt.exports=function(){var e=0,t=0,n=0,i=0,r=0;let o=()=>e>C.EF_ZIP64_OR_16||t>C.EF_ZIP64_OR_16||n>C.EF_ZIP64_OR_32||i>C.EF_ZIP64_OR_32;return{get diskEntries(){return e},set diskEntries(s){e=t=s},get totalEntries(){return t},set totalEntries(s){t=e=s},get size(){return n},set size(s){n=s},get offset(){return i},set offset(s){i=s},get commentLength(){return r},set commentLength(s){r=s},get mainHeaderSize(){return(o()?C.ZIP64HDR+C.END64HDR:0)+C.ENDHDR+r},loadFromBinary:function(s){if((s.length!==C.ENDHDR||s.readUInt32LE(0)!==C.ENDSIG)&&(s.length<C.ZIP64HDR||s.readUInt32LE(0)!==C.ZIP64SIG))throw Z.Errors.INVALID_END();s.readUInt32LE(0)===C.ENDSIG?(e=s.readUInt16LE(C.ENDSUB),t=s.readUInt16LE(C.ENDTOT),n=s.readUInt32LE(C.ENDSIZ),i=s.readUInt32LE(C.ENDOFF),r=s.readUInt16LE(C.ENDCOM)):(e=Z.readBigUInt64LE(s,C.ZIP64SUB),t=Z.readBigUInt64LE(s,C.ZIP64TOT),n=Z.readBigUInt64LE(s,C.ZIP64SIZB),i=Z.readBigUInt64LE(s,C.ZIP64OFF),r=0)},toBinary:function(){if(!o()){var s=Buffer.alloc(C.ENDHDR+r);return s.writeUInt32LE(C.ENDSIG,0),s.writeUInt32LE(0,4),s.writeUInt16LE(e,C.ENDSUB),s.writeUInt16LE(t,C.ENDTOT),s.writeUInt32LE(n,C.ENDSIZ),s.writeUInt32LE(i,C.ENDOFF),s.writeUInt16LE(r,C.ENDCOM),s.fill(" ",C.ENDHDR),s}var s=Buffer.alloc(this.mainHeaderSize);let l=0;s.writeUInt32LE(C.ZIP64SIG,l),Z.writeBigUInt64LE(s,C.ZIP64HDR-C.ZIP64LEAD,l+C.ZIP64SIZE),s.writeUInt16LE(45,l+C.ZIP64VEM),s.writeUInt16LE(45,l+C.ZIP64VER),s.writeUInt32LE(0,l+C.ZIP64DSK),s.writeUInt32LE(0,l+C.ZIP64DSKDIR),Z.writeBigUInt64LE(s,e,l+C.ZIP64SUB),Z.writeBigUInt64LE(s,t,l+C.ZIP64TOT),Z.writeBigUInt64LE(s,n,l+C.ZIP64SIZB),Z.writeBigUInt64LE(s,i,l+C.ZIP64OFF);let f=i+n;return l+=C.ZIP64HDR,s.writeUInt32LE(C.END64SIG,l),s.writeUInt32LE(0,l+C.END64START),Z.writeBigUInt64LE(s,f,l+C.END64OFF),s.writeUInt32LE(1,l+C.END64NUMDISKS),l+=C.END64HDR,s.writeUInt32LE(C.ENDSIG,l),s.writeUInt32LE(0,l+4),s.writeUInt16LE(Math.min(e,C.EF_ZIP64_OR_16),l+C.ENDSUB),s.writeUInt16LE(Math.min(t,C.EF_ZIP64_OR_16),l+C.ENDTOT),s.writeUInt32LE(Math.min(n,C.EF_ZIP64_OR_32),l+C.ENDSIZ),s.writeUInt32LE(Math.min(i,C.EF_ZIP64_OR_32),l+C.ENDOFF),s.writeUInt16LE(r,l+C.ENDCOM),s.fill(" ",l+C.ENDHDR),s},toJSON:function(){let s=function(l,f){let u=l.toString(16).toUpperCase();for(;u.length<f;)u="0"+u;return"0x"+u};return{diskEntries:e,totalEntries:t,size:n+" bytes",offset:s(i,4),commentLength:r}},toString:function(){return JSON.stringify(this.toJSON(),null," ")}}}});var je=$(ze=>{ze.EntryHeader=Dt();ze.MainHeader=Ot()});var $t=$((io,Mt)=>{Mt.exports=function(e){var t=require("zlib"),n={chunkSize:(parseInt(e.length/1024)+1)*1024};return{deflate:function(){return t.deflateRawSync(e,n)},deflateAsync:function(i){var r=t.createDeflateRaw(n),o=[],s=0;r.on("data",function(l){o.push(l),s+=l.length}),r.on("end",function(){var l=Buffer.alloc(s),f=0;l.fill(0);for(var u=0;u<o.length;u++){var d=o[u];d.copy(l,f),f+=d.length}i&&i(l)}),r.end(e)}}}});var Vt=$((ro,Bt)=>{var yi=+(process?.versions?.node??"").split(".")[0]||0;Bt.exports=function(e,t){var n=require("zlib");let i=yi>=15&&t>0?{maxOutputLength:t}:{};return{inflate:function(){return n.inflateRawSync(e,i)},inflateAsync:function(r){var o=n.createInflateRaw(i),s=[],l=0;o.on("data",function(f){s.push(f),l+=f.length}),o.on("end",function(){var f=Buffer.alloc(l),u=0;f.fill(0);for(var d=0;d<s.length;d++){var g=s[d];g.copy(f,u),u+=g.length}r&&r(f)}),o.end(e)}}}});var Kt=$((oo,Ht)=>{"use strict";var{randomFillSync:Ut}=require("crypto"),Ei=he(),Si=new Uint32Array(256).map((e,t)=>{for(let n=0;n<8;n++)(t&1)!==0?t=t>>>1^3988292384:t>>>=1;return t>>>0}),jt=(e,t)=>Math.imul(e,t)>>>0,zt=(e,t)=>Si[(e^t)&255]^e>>>8,de=()=>typeof Ut=="function"?Ut(Buffer.alloc(12)):de.node();de.node=()=>{let e=Buffer.alloc(12),t=e.length;for(let n=0;n<t;n++)e[n]=Math.random()*256&255;return e};var ye={genSalt:de};function Ee(e){let t=Buffer.isBuffer(e)?e:Buffer.from(e);this.keys=new Uint32Array([305419896,591751049,878082192]);for(let n=0;n<t.length;n++)this.updateKeys(t[n])}Ee.prototype.updateKeys=function(e){let t=this.keys;return t[0]=zt(t[0],e),t[1]+=t[0]&255,t[1]=jt(t[1],134775813)+1,t[2]=zt(t[2],t[1]>>>24),e};Ee.prototype.next=function(){let e=(this.keys[2]|2)>>>0;return jt(e,e^1)>>8&255};function wi(e){let t=new Ee(e);return function(n){let i=Buffer.alloc(n.length),r=0;for(let o of n)i[r++]=t.updateKeys(o^t.next());return i}}function Ti(e){let t=new Ee(e);return function(n,i,r=0){i||(i=Buffer.alloc(n.length));for(let o of n){let s=t.next();i[r++]=o^s,t.updateKeys(o)}return i}}function bi(e,t,n){if(!e||!Buffer.isBuffer(e)||e.length<12)return Buffer.alloc(0);let i=wi(n),r=i(e.slice(0,12)),o=(t.flags&8)===8?t.timeHighByte:t.crc>>>24;if(r[11]!==o)throw Ei.WRONG_PASSWORD();return i(e.slice(12))}function Ii(e){Buffer.isBuffer(e)&&e.length>=12?ye.genSalt=function(){return e.slice(0,12)}:e==="node"?ye.genSalt=de.node:ye.genSalt=de}function Pi(e,t,n,i=!1){e==null&&(e=Buffer.alloc(0)),Buffer.isBuffer(e)||(e=Buffer.from(e.toString()));let r=Ti(n),o=ye.genSalt();o[11]=t.crc>>>24&255,i&&(o[10]=t.crc>>>16&255);let s=Buffer.alloc(e.length+12);return r(o,s),r(e,s,12)}Ht.exports={decrypt:bi,encrypt:Pi,_salter:Ii}});var Zt=$(Se=>{Se.Deflater=$t();Se.Inflater=Vt();Se.ZipCrypto=Kt()});var Ke=$((ao,qt)=>{var v=se(),Ci=je(),N=v.Constants,He=Zt();qt.exports=function(e,t){var n=new Ci.EntryHeader,i=Buffer.alloc(0),r=Buffer.alloc(0),o=!1,s=null,l=Buffer.alloc(0),f=Buffer.alloc(0),u=!0;let d=e,g=typeof d.decoder=="object"?d.decoder:v.decoder;u=g.hasOwnProperty("efs")?g.efs:!1;function b(){return!t||!(t instanceof Uint8Array)?Buffer.alloc(0):(f=n.loadLocalHeaderFromBinary(t),t.slice(n.realDataOffset,n.realDataOffset+n.compressedSize))}function c(a){if(!n.flags_desc&&!n.localHeader.flags_desc){if(v.crc32(a)!==n.localHeader.crc)return!1}else{let h={},S=n.realDataOffset+n.compressedSize;if(t.readUInt32LE(S)==N.LOCSIG||t.readUInt32LE(S)==N.CENSIG)throw v.Errors.DESCRIPTOR_NOT_EXIST();if(t.readUInt32LE(S)==N.EXTSIG)h.crc=t.readUInt32LE(S+N.EXTCRC),h.compressedSize=t.readUInt32LE(S+N.EXTSIZ),h.size=t.readUInt32LE(S+N.EXTLEN);else if(t.readUInt16LE(S+12)===19280)h.crc=t.readUInt32LE(S+N.EXTCRC-4),h.compressedSize=t.readUInt32LE(S+N.EXTSIZ-4),h.size=t.readUInt32LE(S+N.EXTLEN-4);else throw v.Errors.DESCRIPTOR_UNKNOWN();if(h.compressedSize!==n.compressedSize||h.size!==n.size||h.crc!==n.crc)throw v.Errors.DESCRIPTOR_FAULTY();if(v.crc32(a)!==h.crc)return!1}return!0}function p(a,h,S){if(typeof h>"u"&&typeof a=="string"&&(S=a,a=void 0),o)return a&&h&&h(Buffer.alloc(0),v.Errors.DIRECTORY_CONTENT_ERROR()),Buffer.alloc(0);var T=b();if(T.length===0)return a&&h&&h(T),T;if(n.encrypted){if(typeof S!="string"&&!Buffer.isBuffer(S))throw v.Errors.INVALID_PASS_PARAM();T=He.ZipCrypto.decrypt(T,n,S)}var P=Buffer.alloc(n.size);switch(n.method){case v.Constants.STORED:if(T.copy(P),c(P))return a&&h&&h(P),P;throw a&&h&&h(P,v.Errors.BAD_CRC()),v.Errors.BAD_CRC();case v.Constants.DEFLATED:var k=new He.Inflater(T,n.size);if(a)k.inflateAsync(function(F){F.copy(F,0),h&&(c(F)?h(F):h(F,v.Errors.BAD_CRC()))});else{if(k.inflate(P).copy(P,0),!c(P))throw v.Errors.BAD_CRC(`"${g.decode(i)}"`);return P}break;default:throw a&&h&&h(Buffer.alloc(0),v.Errors.UNKNOWN_METHOD()),v.Errors.UNKNOWN_METHOD()}}function y(a,h){if((!s||!s.length)&&Buffer.isBuffer(t))return a&&h&&h(b()),b();if(s.length&&!o){var S;switch(n.method){case v.Constants.STORED:return n.compressedSize=n.size,S=Buffer.alloc(s.length),s.copy(S),a&&h&&h(S),S;default:case v.Constants.DEFLATED:var T=new He.Deflater(s);if(a)T.deflateAsync(function(k){S=Buffer.alloc(k.length),n.compressedSize=k.length,k.copy(S),h&&h(S)});else{var P=T.deflate();return n.compressedSize=P.length,P}T=null;break}}else if(a&&h)h(Buffer.alloc(0));else return Buffer.alloc(0)}function m(a,h){return v.readBigUInt64LE(a,h)}function E(a){try{for(var h=0,S,T,P;h+4<a.length;)S=a.readUInt16LE(h),h+=2,T=a.readUInt16LE(h),h+=2,P=a.slice(h,h+T),h+=T,N.ID_ZIP64===S&&w(P)}catch{throw v.Errors.EXTRA_FIELD_PARSE_ERROR()}}function w(a){var h,S,T,P;a.length>=N.EF_ZIP64_SCOMP&&(h=m(a,N.EF_ZIP64_SUNCOMP),n.size===N.EF_ZIP64_OR_32&&(n.size=h)),a.length>=N.EF_ZIP64_RHO&&(S=m(a,N.EF_ZIP64_SCOMP),n.compressedSize===N.EF_ZIP64_OR_32&&(n.compressedSize=S)),a.length>=N.EF_ZIP64_DSN&&(T=m(a,N.EF_ZIP64_RHO),n.offset===N.EF_ZIP64_OR_32&&(n.offset=T)),a.length>=N.EF_ZIP64_DSN+4&&(P=a.readUInt32LE(N.EF_ZIP64_DSN),n.diskNumStart===N.EF_ZIP64_OR_16&&(n.diskNumStart=P))}return{get entryName(){return g.decode(i)},get rawEntryName(){return i},set entryName(a){i=v.toBuffer(a,g.encode);var h=i[i.length-1];o=h===47||h===92,n.fileNameLength=i.length},get efs(){return typeof u=="function"?u(this.entryName):u},get extra(){return l},set extra(a){l=a,n.extraLength=a.length,E(a)},get comment(){return g.decode(r)},set comment(a){if(r=v.toBuffer(a,g.encode),n.commentLength=r.length,r.length>65535)throw v.Errors.COMMENT_TOO_LONG()},get name(){var a=g.decode(i);return o?a.substr(a.length-1).split("/").pop():a.split("/").pop()},get isDirectory(){return o},getCompressedData:function(){return y(!1,null)},getCompressedDataAsync:function(a){y(!0,a)},setData:function(a){s=v.toBuffer(a,v.decoder.encode),!o&&s.length?(n.size=s.length,n.method=v.Constants.DEFLATED,n.crc=v.crc32(a),n.changed=!0):n.method=v.Constants.STORED},getData:function(a){return n.changed?s:p(!1,null,a)},getDataAsync:function(a,h){n.changed?a(s):p(!0,a,h)},set attr(a){n.attr=a},get attr(){return n.attr},set header(a){n.loadFromBinary(a)},get header(){return n},packCentralHeader:function(){n.flags_efs=this.efs,n.extraLength=l.length;var a=n.centralHeaderToBinary(),h=v.Constants.CENHDR;return i.copy(a,h),h+=i.length,l.copy(a,h),h+=n.extraLength,r.copy(a,h),a},packLocalHeader:function(){let a=0;n.flags_efs=this.efs,n.extraLocalLength=f.length;let h=n.localHeaderToBinary(),S=Buffer.alloc(h.length+i.length+n.extraLocalLength);return h.copy(S,a),a+=h.length,i.copy(S,a),a+=i.length,f.copy(S,a),a+=f.length,S},toJSON:function(){let a=function(h){return"<"+(h&&h.length+" bytes buffer"||"null")+">"};return{entryName:this.entryName,name:this.name,comment:this.comment,isDirectory:this.isDirectory,header:n.toJSON(),compressedData:a(t),data:a(s)}},toString:function(){return JSON.stringify(this.toJSON(),null," ")}}}});var Xt=$((lo,Gt)=>{var Wt=Ke(),Ai=je(),U=se();Gt.exports=function(e,t){var n=[],i={},r=Buffer.alloc(0),o=new Ai.MainHeader,s=!1,l=null;let f=new Set,u=t,{noSort:d,decoder:g}=u;e?p(u.readEntries):s=!0;function b(){let m=new Set;for(let E of Object.keys(i)){let w=E.split("/");if(w.pop(),!!w.length)for(let a=0;a<w.length;a++){let h=w.slice(0,a+1).join("/")+"/";m.add(h)}}for(let E of m)if(!(E in i)){let w=new Wt(u);w.entryName=E,w.attr=16,w.temporary=!0,n.push(w),i[w.entryName]=w,f.add(w)}}function c(){if(s=!0,i={},o.diskEntries>(e.length-o.offset)/U.Constants.CENHDR)throw U.Errors.DISK_ENTRY_TOO_LARGE();n=new Array(o.diskEntries);for(var m=o.offset,E=0;E<n.length;E++){var w=m,a=new Wt(u,e);a.header=e.slice(w,w+=U.Constants.CENHDR),a.entryName=e.slice(w,w+=a.header.fileNameLength),a.header.extraLength&&(a.extra=e.slice(w,w+=a.header.extraLength)),a.header.commentLength&&(a.comment=e.slice(w,w+a.header.commentLength)),m+=a.header.centralHeaderSize,n[E]=a,i[a.entryName]=a}f.clear(),b()}function p(m){var E=e.length-U.Constants.ENDHDR,w=Math.max(0,E-65535),a=w,h=e.length,S=-1,T=0;for(typeof u.trailingSpace=="boolean"&&u.trailingSpace&&(w=0),E;E>=a;E--)if(e[E]===80){if(e.readUInt32LE(E)===U.Constants.ENDSIG){S=E,T=E,h=E+U.Constants.ENDHDR,a=E-U.Constants.END64HDR;continue}if(e.readUInt32LE(E)===U.Constants.END64SIG){a=w;continue}if(e.readUInt32LE(E)===U.Constants.ZIP64SIG){S=E,h=E+U.readBigUInt64LE(e,E+U.Constants.ZIP64SIZE)+U.Constants.ZIP64LEAD;break}}if(S==-1)throw U.Errors.INVALID_FORMAT();o.loadFromBinary(e.slice(S,h)),o.commentLength&&(r=e.slice(T+U.Constants.ENDHDR)),m&&c()}function y(){n.length>1&&!d&&n.sort((m,E)=>m.entryName.toLowerCase().localeCompare(E.entryName.toLowerCase()))}return{get entries(){return s||c(),n.filter(m=>!f.has(m))},get comment(){return g.decode(r)},set comment(m){r=U.toBuffer(m,g.encode),o.commentLength=r.length},getEntryCount:function(){return s?n.length:o.diskEntries},forEach:function(m){this.entries.forEach(m)},getEntry:function(m){return s||c(),i[m]||null},setEntry:function(m){s||c(),n.push(m),i[m.entryName]=m,o.totalEntries=n.length},deleteFile:function(m,E=!0){s||c();let w=i[m];this.getEntryChildren(w,E).map(h=>h.entryName).forEach(this.deleteEntry)},deleteEntry:function(m){s||c();let E=i[m],w=n.indexOf(E);w>=0&&(n.splice(w,1),delete i[m],o.totalEntries=n.length)},getEntryChildren:function(m,E=!0){if(s||c(),typeof m=="object")if(m.isDirectory&&E){let w=[],a=m.entryName;for(let h of n)h.entryName.startsWith(a)&&w.push(h);return w}else return[m];return[]},getChildCount:function(m){if(m&&m.isDirectory){let E=this.getEntryChildren(m);return E.includes(m)?E.length-1:E.length}return 0},compressToBuffer:function(){s||c(),y();let m=[],E=[],w=0,a=0;o.size=0,o.offset=0;let h=0;for(let P of this.entries){let k=P.getCompressedData();P.header.offset=a;let F=P.packLocalHeader(),M=F.length+k.length;a+=M,m.push(F),m.push(k);let L=P.packCentralHeader();E.push(L),o.size+=L.length,w+=M+L.length,h++}w+=o.mainHeaderSize,o.offset=a,o.totalEntries=h,a=0;let S=Buffer.alloc(w);for(let P of m)P.copy(S,a),a+=P.length;for(let P of E)P.copy(S,a),a+=P.length;let T=o.toBinary();return r&&r.copy(T,T.length-r.length),T.copy(S,a),e=S,s=!1,S},toAsyncBuffer:function(m,E,w,a){try{s||c(),y();let h=[],S=[],T=0,P=0,k=0;o.size=0,o.offset=0;let F=function(M){if(M.length>0){let L=M.shift(),H=L.entryName+L.extra.toString();w&&w(H),L.getCompressedDataAsync(function(K){a&&a(H),L.header.offset=P;let pe=L.packLocalHeader(),Et=pe.length+K.length;P+=Et,h.push(pe),h.push(K);let Ve=L.packCentralHeader();S.push(Ve),o.size+=Ve.length,T+=Et+Ve.length,k++,F(M)})}else{T+=o.mainHeaderSize,o.offset=P,o.totalEntries=k,P=0;let L=Buffer.alloc(T);h.forEach(function(K){K.copy(L,P),P+=K.length}),S.forEach(function(K){K.copy(L,P),P+=K.length});let H=o.toBinary();r&&r.copy(H,H.length-r.length),H.copy(L,P),e=L,s=!1,m(L)}};F(Array.from(this.entries))}catch(h){E(h)}}}}});var Ze=$((co,Jt)=>{var D=se(),_=require("path"),xi=Ke(),Fi=Xt(),ee=(...e)=>D.findLast(e,t=>typeof t=="boolean"),Yt=(...e)=>D.findLast(e,t=>typeof t=="string"),vi=(...e)=>D.findLast(e,t=>typeof t=="function"),ki={noSort:!1,readEntries:!1,method:D.Constants.NONE,fs:null};Jt.exports=function(e,t){let n=null,i=Object.assign(Object.create(null),ki);e&&typeof e=="object"&&(e instanceof Uint8Array||(Object.assign(i,e),e=i.input?i.input:void 0,i.input&&delete i.input),Buffer.isBuffer(e)&&(n=e,i.method=D.Constants.BUFFER,e=void 0)),Object.assign(i,t);let r=new D(i);if((typeof i.decoder!="object"||typeof i.decoder.encode!="function"||typeof i.decoder.decode!="function")&&(i.decoder=D.decoder),e&&typeof e=="string")if(r.fs.existsSync(e))i.method=D.Constants.FILE,i.filename=e,n=r.fs.readFileSync(e);else throw D.Errors.INVALID_FILENAME();let o=new Fi(n,i),{canonical:s,sanitize:l,zipnamefix:f}=D;function u(c){if(c&&o){var p;if(typeof c=="string"&&(p=o.getEntry(_.posix.normalize(c))),typeof c=="object"&&typeof c.entryName<"u"&&typeof c.header<"u"&&(p=o.getEntry(c.entryName)),p)return p}return null}function d(c){let{join:p,normalize:y,sep:m}=_.posix;return p(_.isAbsolute(c)?"/":".",y(m+c.split("\\").join(m)+m))}function g(c){return c instanceof RegExp?(function(p){return function(y){return p.test(y)}})(c):typeof c!="function"?()=>!0:c}let b=(c,p)=>{let y=p.slice(-1);return y=y===r.sep?r.sep:"",_.relative(c,p)+y};return{readFile:function(c,p){var y=u(c);return y&&y.getData(p)||null},childCount:function(c){let p=u(c);if(p)return o.getChildCount(p)},readFileAsync:function(c,p){var y=u(c);y?y.getDataAsync(p):p(null,"getEntry failed for:"+c)},readAsText:function(c,p){var y=u(c);if(y){var m=y.getData();if(m&&m.length)return m.toString(p||"utf8")}return""},readAsTextAsync:function(c,p,y){var m=u(c);m?m.getDataAsync(function(E,w){if(w){p(E,w);return}E&&E.length?p(E.toString(y||"utf8")):p("")}):p("")},deleteFile:function(c,p=!0){var y=u(c);y&&o.deleteFile(y.entryName,p)},deleteEntry:function(c){var p=u(c);p&&o.deleteEntry(p.entryName)},addZipComment:function(c){o.comment=c},getZipComment:function(){return o.comment||""},addZipEntryComment:function(c,p){var y=u(c);y&&(y.comment=p)},getZipEntryComment:function(c){var p=u(c);return p&&p.comment||""},updateFile:function(c,p){var y=u(c);y&&y.setData(p)},addLocalFile:function(c,p,y,m){if(r.fs.existsSync(c)){p=p?d(p):"";let E=_.win32.basename(_.win32.normalize(c));p+=y||E;let w=r.fs.statSync(c),a=w.isFile()?r.fs.readFileSync(c):Buffer.alloc(0);w.isDirectory()&&(p+=r.sep),this.addFile(p,a,m,w)}else throw D.Errors.FILE_NOT_FOUND(c)},addLocalFileAsync:function(c,p){c=typeof c=="object"?c:{localPath:c};let y=_.resolve(c.localPath),{comment:m}=c,{zipPath:E,zipName:w}=c,a=this;r.fs.stat(y,function(h,S){if(h)return p(h,!1);E=E?d(E):"";let T=_.win32.basename(_.win32.normalize(y));if(E+=w||T,S.isFile())r.fs.readFile(y,function(P,k){return P?p(P,!1):(a.addFile(E,k,m,S),setImmediate(p,void 0,!0))});else if(S.isDirectory())return E+=r.sep,a.addFile(E,Buffer.alloc(0),m,S),setImmediate(p,void 0,!0)})},addLocalFolder:function(c,p,y){if(y=g(y),p=p?d(p):"",c=_.normalize(c),r.fs.existsSync(c)){let m=r.findFiles(c),E=this;if(m.length)for(let w of m){let a=_.join(p,b(c,w));y(a)&&E.addLocalFile(w,_.dirname(a))}}else throw D.Errors.FILE_NOT_FOUND(c)},addLocalFolderAsync:function(c,p,y,m){m=g(m),y=y?d(y):"",c=_.normalize(c);var E=this;r.fs.open(c,"r",function(w){if(w&&w.code==="ENOENT")p(void 0,D.Errors.FILE_NOT_FOUND(c));else if(w)p(void 0,w);else{var a=r.findFiles(c),h=-1,S=function(){if(h+=1,h<a.length){var T=a[h],P=b(c,T).split("\\").join("/");P=P.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^\x20-\x7E]/g,""),m(P)?r.fs.stat(T,function(k,F){k&&p(void 0,k),F.isFile()?r.fs.readFile(T,function(M,L){M?p(void 0,M):(E.addFile(y+P,L,"",F),S())}):(E.addFile(y+P+"/",Buffer.alloc(0),"",F),S())}):process.nextTick(()=>{S()})}else p(!0,void 0)};S()}})},addLocalFolderAsync2:function(c,p){let y=this;c=typeof c=="object"?c:{localPath:c};let m=_.resolve(d(c.localPath)),{zipPath:E,filter:w,namefix:a}=c;w instanceof RegExp?w=(function(T){return function(P){return T.test(P)}})(w):typeof w!="function"&&(w=function(){return!0}),E=E?d(E):"",a==="latin1"&&(a=T=>T.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^\x20-\x7E]/g,"")),typeof a!="function"&&(a=T=>T);let h=T=>_.join(E,a(b(m,T))),S=T=>_.win32.basename(_.win32.normalize(a(T)));r.fs.open(m,"r",function(T){T&&T.code==="ENOENT"?p(void 0,D.Errors.FILE_NOT_FOUND(m)):T?p(void 0,T):r.findFilesAsync(m,function(P,k){if(P)return p(P);k=k.filter(F=>w(h(F))),k.length||p(void 0,!1),setImmediate(k.reverse().reduce(function(F,M){return function(L,H){if(L||H===!1)return setImmediate(F,L,!1);y.addLocalFileAsync({localPath:M,zipPath:_.dirname(h(M)),zipName:S(M)},F)}},p))})})},addLocalFolderPromise:function(c,p){return new Promise((y,m)=>{this.addLocalFolderAsync2(Object.assign({localPath:c},p),(E,w)=>{E&&m(E),w&&y(this)})})},addFile:function(c,p,y,m){c=f(c);let E=u(c),w=E!=null;w||(E=new xi(i),E.entryName=c),E.comment=y||"";let a=typeof m=="object"&&m instanceof r.fs.Stats;a&&(E.header.time=m.mtime);var h=E.isDirectory?16:0;let S=E.isDirectory?16384:32768;return a?S|=4095&m.mode:typeof m=="number"?S|=4095&m:S|=E.isDirectory?493:420,h=(h|S<<16)>>>0,E.attr=h,E.setData(p),w||o.setEntry(E),E},getEntries:function(c){return o.password=c,o?o.entries:[]},getEntry:function(c){return u(c)},getEntryCount:function(){return o.getEntryCount()},forEach:function(c){return o.forEach(c)},extractEntryTo:function(c,p,y,m,E,w){m=ee(!1,m),E=ee(!1,E),y=ee(!0,y),w=Yt(E,w);var a=u(c);if(!a)throw D.Errors.NO_ENTRY();var h=s(a.entryName),S=l(p,w&&!a.isDirectory?s(w):y?h:_.basename(h));if(a.isDirectory){var T=o.getEntryChildren(a);return T.forEach(function(F){if(F.isDirectory)return;var M=F.getData();if(!M)throw D.Errors.CANT_EXTRACT_FILE();var L=s(F.entryName),H=l(p,y?L:_.basename(L));let K=E?F.header.fileAttr:void 0;r.writeFileTo(H,M,m,K)}),!0}var P=a.getData(o.password);if(!P)throw D.Errors.CANT_EXTRACT_FILE();if(r.fs.existsSync(S)&&!m)throw D.Errors.CANT_OVERRIDE();let k=E?c.header.fileAttr:void 0;return r.writeFileTo(S,P,m,k),!0},test:function(c){if(!o)return!1;for(var p of o.entries)try{if(p.isDirectory)continue;var y=o.entries[p].getData(c);if(!y)return!1}catch{return!1}return!0},extractAllTo:function(c,p,y,m){if(y=ee(!1,y),m=Yt(y,m),p=ee(!1,p),!o)throw D.Errors.NO_ZIP();o.entries.forEach(function(E){var w=l(c,s(E.entryName));if(E.isDirectory){r.makeDir(w);return}var a=E.getData(m);if(!a)throw D.Errors.CANT_EXTRACT_FILE();let h=y?E.header.fileAttr:void 0;r.writeFileTo(w,a,p,h);try{r.fs.utimesSync(w,E.header.time,E.header.time)}catch{throw D.Errors.CANT_EXTRACT_FILE()}})},extractAllToAsync:function(c,p,y,m){if(m=vi(p,y,m),y=ee(!1,y),p=ee(!1,p),!m)return new Promise((S,T)=>{this.extractAllToAsync(c,p,y,function(P){P?T(P):S(this)})});if(!o){m(D.Errors.NO_ZIP());return}c=_.resolve(c);let E=S=>l(c,_.normalize(s(S.entryName))),w=(S,T)=>new Error(S+': "'+T+'"'),a=[],h=[];o.entries.forEach(S=>{S.isDirectory?a.push(S):h.push(S)});for(let S of a){let T=E(S),P=y?S.header.fileAttr:void 0;try{r.makeDir(T),P&&r.fs.chmodSync(T,P),r.fs.utimesSync(T,S.header.time,S.header.time)}catch{m(w("Unable to create folder",T))}}h.reverse().reduce(function(S,T){return function(P){if(P)S(P);else{let k=_.normalize(s(T.entryName)),F=l(c,k);T.getDataAsync(function(M,L){if(L)S(L);else if(!M)S(D.Errors.CANT_EXTRACT_FILE());else{let H=y?T.header.fileAttr:void 0;r.writeFileToAsync(F,M,p,H,function(K){K||S(w("Unable to write file",F)),r.fs.utimes(F,T.header.time,T.header.time,function(pe){pe?S(w("Unable to set times",F)):S()})})}})}}},m)()},writeZip:function(c,p){if(arguments.length===1&&typeof c=="function"&&(p=c,c=""),!c&&i.filename&&(c=i.filename),!!c){var y=o.compressToBuffer();if(y){var m=r.writeFileTo(c,y,!0);typeof p=="function"&&p(m?null:new Error("failed"),"")}}},writeZipPromise:function(c,p){let{overwrite:y,perm:m}=Object.assign({overwrite:!0},p);return new Promise((E,w)=>{!c&&i.filename&&(c=i.filename),c||w("ADM-ZIP: ZIP File Name Missing"),this.toBufferPromise().then(a=>{let h=S=>S?E(S):w("ADM-ZIP: Wasn't able to write zip file");r.writeFileToAsync(c,a,y,m,h)},w)})},toBufferPromise:function(){return new Promise((c,p)=>{o.toAsyncBuffer(c,p)})},toBuffer:function(c,p,y,m){return typeof c=="function"?(o.toAsyncBuffer(c,p,y,m),null):o.compressToBuffer()}}}});var Zr={};di(Zr,{runTemplatePreflight:()=>ti});module.exports=ui(Zr);var Jn=require("node:child_process"),x=require("node:fs/promises"),Qn=require("node:os"),A=require("node:path"),yt=wt(Ze());var Qt=[{key:"content_image",label:"Content images",accept:["image/jpeg","image/png","image/webp"],maxSizeBytes:5242880,maxFiles:200},{key:"business_logo",label:"Business logo",accept:["image/jpeg","image/png","image/webp"],maxSizeBytes:5242880,maxFiles:1},{key:"website_banner",label:"Website banner images",accept:["image/jpeg","image/png","image/webp"],maxSizeBytes:5242880,maxFiles:10},{key:"gallery",label:"Gallery images",accept:["image/jpeg","image/png","image/webp"],maxSizeBytes:5242880,maxFiles:30},{key:"product",label:"Product images",accept:["image/jpeg","image/png","image/webp"],maxSizeBytes:5242880,maxFiles:50},{key:"service",label:"Service images",accept:["image/jpeg","image/png","image/webp"],maxSizeBytes:5242880,maxFiles:50},{key:"shop_front",label:"Shop front images",accept:["image/jpeg","image/png","image/webp"],maxSizeBytes:5242880,maxFiles:10},{key:"company_document",label:"Company documents",accept:["application/pdf","image/jpeg","image/png","image/webp"],maxSizeBytes:10485760,maxFiles:10},{key:"brochure_pdf",label:"Brochure PDF",accept:["application/pdf"],maxSizeBytes:10485760,maxFiles:5},{key:"restaurant_menu_pdf",label:"Restaurant menu PDF",accept:["application/pdf"],maxSizeBytes:10485760,maxFiles:5}];var Li={business_logo:["logo"],website_banner:["hero","banners"],gallery:["gallery"],product:["products"],service:["services"],shop_front:["shopFront"],content_image:["contentImages"],company_document:["documents"],brochure_pdf:["brochures"],restaurant_menu_pdf:["menus"]};function en(e,t=[]){return{project:{id:"template-validation",title:"Template Validation",status:"APPROVED"},shop:{businessName:"Template Validation Shop",description:"Validation build payload that mirrors fivora-generated site data.",contact:{phone:"",email:"",whatsapp:""},address:{line1:"",city:"",district:"",province:"",postalCode:""},social:{facebook:"",instagram:"",tiktok:"",youtube:"",linkedin:"",website:""},logoUrl:""},template:{id:"template-validation",name:"Template Validation",engine:"NEXT_STATIC_EXPORT",structure:null},requirements:{websiteType:"",mainPurpose:"",targetCustomers:"",preferredLanguage:"",preferredColorTheme:"",preferredStyle:"",requiredPages:t,requiredFeatures:[],customerSpecialRequirements:""},content:e??{},media:Ri(),seo:null}}function Ri(){let e={};for(let t of Qt){e[t.key]=[];for(let n of Li[t.key]??[])e[n]||(e[n]=[])}return e}var tn=wt(Ze()),_i=new Set([".cache",".git",".next",".npm",".pnpm-store",".turbo","__macosx","node_modules"]),Di=new Set(["build","coverage","dist","out"]);function nn(e){let t;try{t=new tn.default(e).getEntries()}catch{throw new Error("Template package is not a valid ZIP archive.")}let n=new Set,i=[];for(let r of t){let o=on(r.entryName);if(i.push(o),Ni(o))throw new Error(`Template ZIP contains an unsafe entry: ${r.entryName||"(empty path)"}.`);(!r.isDirectory&&we(o)||r.isDirectory&&we(o))&&n.add(o)}return{entries:i,forbiddenEntries:[...n]}}function rn(e){let t=e.slice(0,8),n=e.length-t.length;return["Template ZIP contains generated, cached, secret, log, or nested archive files that must be removed.",`Remove: ${t.join(", ")}${n>0?`, and ${n} more`:""}.`,"Create a clean source-only ZIP and upload it again."].join(" ")}function on(e){return e.replace(/\\/g,"/").replace(/^\.\//,"")}function Ni(e){let t=sn(e);return!e||e.includes("\0")||e.startsWith("/")||/^[a-z]:\//i.test(e)||t.includes("..")}function we(e){let t=on(e),n=sn(t),i=n.at(-1)??"",r=n.some(b=>_i.has(b)),o=n[0]===".yarn"&&n[1]==="cache",s=n.some(b=>Di.has(b)),l=i===".env"||i.startsWith(".env."),f=i.endsWith(".zip"),u=i.endsWith(".log"),d=i.endsWith(".tsbuildinfo");return r||o||s||l||f||u||d||(i===".ds_store"||i==="thumbs.db")}function sn(e){return e.split("/").map(t=>t.trim().toLowerCase()).filter(Boolean)}var Oi={common:{label:"Common Content"},home:{label:"Home Page",pageKey:"home"},about:{label:"About Page",pageKey:"about_us"},services:{label:"Services",pageKey:"services"},products:{label:"Products",pageKey:"products"},gallery:{label:"Gallery",pageKey:"gallery"},contact:{label:"Contact Page",pageKey:"contact"},additionalPages:{label:"Additional Pages"}},Mi=new Set(["text","textarea","email","tel","url","image","number","boolean","select"]),$i={version:1,sections:[{id:"common",path:"common",label:"Common Content",type:"object",fields:[{key:"logoUrl",type:"image",label:"Website logo",description:"Used by templates that read content.common.logoUrl or merchant.logoUrl."}]}]};function ln(e){if(!e||typeof e!="object")return null;let t=e,i=(Array.isArray(t.sections)?t.sections:[]).map(r=>Bi(r)).filter(r=>!!r);return i.length===0?null:{version:typeof t.version=="number"&&Number.isFinite(t.version)?t.version:1,sections:i}}function cn(e,t=[]){let n=new Map(t.map(r=>[r.id,r.label]));return{version:1,sections:Object.entries(e).map(([r,o])=>Ui(r,o,n)).filter(r=>!!r)}}function ue(e){if(!e)return null;let t=new Map;for(let o of e.sections){let s=t.get(o.path);t.set(o.path,s?We(s,o):o)}let n=[...t.values()],i=n.map(o=>o.path),r=n.map(o=>{let l=n.filter(u=>Ce(o.path,u.path)).sort((u,d)=>an(d.path)-an(u.path)).map(u=>gn({...e,sections:[u]},o.path)).filter(u=>!!u).reduce((u,d)=>We(u,d),o),f=new Set(i.filter(u=>u!==o.path&&Ce(u,o.path)));return qe(l,f)}).filter(o=>!!o);return{...e,sections:r}}function Ae(e){if(!e)return[];let t=new Map,n=[],i=new Set,r=(s,l,f)=>{let u=X(s),d=t.get(u);if(!d){t.set(u,{kind:l,sectionId:f});return}i.has(u)||(i.add(u),n.push({path:u,firstKind:d.kind,duplicateKind:l,firstSectionId:d.sectionId,duplicateSectionId:f}))},o=(s,l,f)=>{if(l.type==="object"){for(let u of l.fields??[])o(te(s,u.key),u,f);return}if(l.type==="list"){let u=X(s);r(u,"list",f);let d=`${u}[*]`;l.itemField&&r(d,"field",f);for(let g of l.fields??[])o(te(d,g.key),g,f);return}r(s,"field",f)};for(let s of e.sections)o(s.path,s,s.id);return n}function Ge(e,t){if(!e)return ue(t);if(!t)return ue(e);let n=ue(e)??e,i=ue(t)??t,r=n.sections.map(f=>f.path),o=n.sections.map(f=>{let u=gn(i,f.path);if(!u)return f;let d=new Set(r.filter(b=>b!==f.path&&Ce(b,f.path))),g=qe(u,d);return g?We(f,g):f}),s=new Set(n.sections.map(({path:f})=>f)),l=i.sections.filter(f=>!s.has(f.path)).map(f=>qe(f,new Set(r.filter(u=>Ce(u,f.path))))).filter(f=>!!f);return ue({...t,...e,sections:[...o,...l]})}function dn(e){return e?Ge(e,$i):null}function Bi(e){if(!e||typeof e!="object")return null;let t=e,n=B(t.id),i=B(t.path),r=B(t.label),o=fn(t.type);if(!n||!i||!r||!o)return null;let s={id:n,path:i,label:r,description:B(t.description)||void 0,required:typeof t.required=="boolean"?t.required:void 0,placeholder:B(t.placeholder)||void 0,maxLength:Je(t.maxLength),recommendedWidth:J(t.recommendedWidth),recommendedHeight:J(t.recommendedHeight),pageKey:B(t.pageKey)||void 0,...Xe(t.sharedFieldKey)};if(o==="object"){let l=be(t.fields);return{...s,type:o,fields:l}}if(o==="list"){let l=be(t.fields),f=un(t.itemField);return l.length===0&&!f?null:{...s,type:o,fields:l.length>0?l:void 0,itemField:f??void 0,itemLabel:B(t.itemLabel)||void 0,minItems:Ie(t.minItems),maxItems:Ie(t.maxItems)}}return{...s,type:o,options:o==="select"?Ye(t.options):void 0}}function qe(e,t){if(t.has(e.path))return null;if(e.type==="object"){let n=(e.fields??[]).map(i=>Te(i,e.path,t)).filter(i=>!!i);return n.length===0?null:{...e,fields:n}}if(e.type==="list"){let n=(e.fields??[]).map(i=>Te(i,e.path,t)).filter(i=>!!i);return(e.fields?.length??0)>0&&n.length===0&&!e.itemField?null:{...e,fields:n.length>0?n:void 0}}return e}function Te(e,t,n){let i=te(t,e.key);if(n.has(i))return null;if(e.type==="object"){let r=e.fields.map(o=>Te(o,i,n)).filter(o=>!!o);return r.length===0?null:{...e,fields:r}}if(e.type==="list"){let r=(e.fields??[]).map(o=>Te(o,i,n)).filter(o=>!!o);return(e.fields?.length??0)>0&&r.length===0&&!e.itemField?null:{...e,fields:r.length>0?r:void 0}}return e}function be(e){return Array.isArray(e)?e.map(t=>Vi(t)).filter(t=>!!t):[]}function Vi(e){if(!e||typeof e!="object")return null;let t=e,n=B(t.key),i=B(t.label),r=fn(t.type);if(!n||!i||!r)return null;let o={key:n,label:i,description:B(t.description)||void 0,required:typeof t.required=="boolean"?t.required:void 0,placeholder:B(t.placeholder)||void 0,maxLength:Je(t.maxLength),recommendedWidth:J(t.recommendedWidth),recommendedHeight:J(t.recommendedHeight),...Xe(t.sharedFieldKey)};if(r==="object")return{...o,type:r,fields:be(t.fields)};if(r==="list"){let s=be(t.fields),l=un(t.itemField);return s.length===0&&!l?null:{...o,type:r,fields:s.length>0?s:void 0,itemField:l??void 0,itemLabel:B(t.itemLabel)||void 0,minItems:Ie(t.minItems),maxItems:Ie(t.maxItems)}}return{...o,type:r,options:r==="select"?Ye(t.options):void 0}}function un(e){if(!e||typeof e!="object")return null;let t=e,n=B(t.label),i=mn(t.type);return!n||!i?null:{label:n,type:i,description:B(t.description)||void 0,required:typeof t.required=="boolean"?t.required:void 0,placeholder:B(t.placeholder)||void 0,maxLength:Je(t.maxLength),recommendedWidth:J(t.recommendedWidth),recommendedHeight:J(t.recommendedHeight),...Xe(t.sharedFieldKey),options:i==="select"?Ye(t.options):void 0}}function Xe(e){return typeof e=="string"&&e.trim()?{sharedFieldKey:e.trim()}:{}}function Ye(e){if(!Array.isArray(e))return;let t=e.map(n=>B(n)).filter(n=>!!n);return t.length>0?t:void 0}function Je(e){return typeof e=="number"&&Number.isInteger(e)&&e>0&&e<=1e4?e:void 0}function J(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>0?e:void 0}function Ie(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?e:void 0}function fn(e){return e==="object"?e:e==="list"||e==="array"?"list":mn(e)}function mn(e){return typeof e=="string"&&Mi.has(e)?e:null}function Ui(e,t,n){let i=Oi[e],r=n.has(e)?e:void 0,o=!r&&e==="about"&&n.has("about_us")?"about_us":void 0,s=r||o||i?.pageKey,l=(s?n.get(s):void 0)||i?.label||En(e);return Array.isArray(t)?zi(e,l,s,t):ne(t)?{id:e,path:e,label:l,pageKey:s,type:"object",fields:Object.entries(t).map(([f,u])=>xe(f,u))}:{id:e,path:e,label:l,pageKey:s,...Fe(e,t)}}function xe(e,t){let n=En(e);return Array.isArray(t)?ji(e,n,t):ne(t)?{key:e,label:n,type:"object",fields:Object.entries(t).map(([i,r])=>xe(i,r))}:{key:e,label:n,...Fe(e,t)}}function zi(e,t,n,i){let r=hn(i),o=Sn(t);return ne(r)?{id:e,path:e,label:t,pageKey:n,type:"list",itemLabel:o,fields:Object.entries(r).map(([s,l])=>xe(s,l))}:{id:e,path:e,label:t,pageKey:n,type:"list",itemLabel:o,itemField:{label:o,...Fe(e,r)}}}function ji(e,t,n){let i=hn(n),r=Sn(t);return ne(i)?{key:e,label:t,type:"list",itemLabel:r,fields:Object.entries(i).map(([o,s])=>xe(o,s))}:{key:e,label:t,type:"list",itemLabel:r,itemField:{label:r,...Fe(e,i)}}}function We(e,t){let n={...t,...e,pageKey:e.pageKey??t.pageKey,description:e.description??t.description,placeholder:e.placeholder??t.placeholder};if(e.type==="object"&&t.type==="object")return{...n,type:"object",fields:Pe(e.fields??[],t.fields??[])};if(e.type==="list"&&t.type==="list"){let i=Pe(e.fields??[],t.fields??[]);return{...n,type:"list",fields:i.length>0?i:void 0,itemField:pn(e.itemField,t.itemField),itemLabel:e.itemLabel??t.itemLabel,minItems:e.minItems??t.minItems,maxItems:e.maxItems??t.maxItems}}return{...e,recommendedWidth:e.recommendedWidth??t.recommendedWidth,recommendedHeight:e.recommendedHeight??t.recommendedHeight}}function Pe(e,t){let n=new Map(t.map(r=>[r.key,r]));return[...e.map(r=>{let o=n.get(r.key);return n.delete(r.key),o?Hi(r,o):r}),...n.values()]}function Hi(e,t){let n={...t,...e,description:e.description??t.description,placeholder:e.placeholder??t.placeholder};if(e.type==="object"&&t.type==="object")return{...n,type:"object",fields:Pe(e.fields,t.fields)};if(e.type==="list"&&t.type==="list"){let i=Pe(e.fields??[],t.fields??[]);return{...n,type:"list",fields:i.length>0?i:void 0,itemField:pn(e.itemField,t.itemField),itemLabel:e.itemLabel??t.itemLabel,minItems:e.minItems??t.minItems,maxItems:e.maxItems??t.maxItems}}return{...e,recommendedWidth:e.recommendedWidth??t.recommendedWidth,recommendedHeight:e.recommendedHeight??t.recommendedHeight}}function pn(e,t){return e?!t||e.type!==t.type?e:{...t,...e,recommendedWidth:e.recommendedWidth??t.recommendedWidth,recommendedHeight:e.recommendedHeight??t.recommendedHeight}:t}function gn(e,t){let n=(r,o,s)=>{let{key:l,...f}=r;return{...f,id:s.id,path:o,pageKey:s.pageKey}},i=(r,o,s)=>{if(X(o)===X(t))return n(r,o,s);if(r.type==="object")for(let l of r.fields){let f=i(l,te(o,l.key),s);if(f)return f}if(r.type==="list"){let l=`${X(o)}[*]`;for(let f of r.fields??[]){let u=i(f,te(l,f.key),s);if(u)return u}}return null};for(let r of e.sections){if(X(r.path)===X(t))return r;if(r.type==="object")for(let o of r.fields??[]){let s=i(o,te(r.path,o.key),r);if(s)return s}if(r.type==="list"){let o=`${X(r.path)}[*]`;for(let s of r.fields??[]){let l=i(s,te(o,s.key),r);if(l)return l}}}return null}function Ce(e,t){let n=X(e),i=X(t);return n.startsWith(`${i}.`)||n.startsWith(`${i}[`)}function X(e){return e.replace(/\[\d+\]/g,"[*]").trim()}function an(e){return X(e).split(/\.|\[/).filter(Boolean).length}function hn(e){let t=e.filter(ne);return t.length===0?e.find(n=>n!=null):t.reduce((n,i)=>yn(n,i),{})}function yn(e,t){let n={...e};for(let[i,r]of Object.entries(t)){let o=n[i];if(ne(o)&&ne(r)){n[i]=yn(o,r);continue}if(Array.isArray(o)&&Array.isArray(r)){n[i]=[...o,...r];continue}(o==null||Array.isArray(o)&&o.length===0)&&(n[i]=r)}return n}function Fe(e,t){let n=Ki(e,t);if(n!=="image"||typeof t!="string"||!t.trim())return{type:n};try{let i=new URL(t,"https://fivora-template.invalid"),r=J(Number(i.searchParams.get("w")??i.searchParams.get("width"))),o=J(Number(i.searchParams.get("h")??i.searchParams.get("height")));return{type:n,...r?{recommendedWidth:r}:{},...o?{recommendedHeight:o}:{}}}catch{return{type:n}}}function Ki(e,t){if(typeof t=="boolean")return"boolean";if(typeof t=="number")return"number";let n=e.toLowerCase();return n.includes("email")?"email":n.includes("phone")||n.includes("mobile")||n.includes("whatsapp")||n.includes("contactnumber")?"tel":n.includes("image")||n.includes("logo")||n.includes("banner")||n.includes("thumbnail")||n.includes("photo")?"image":n.includes("url")||n.includes("link")||typeof t=="string"&&/^https?:\/\//i.test(t.trim())?"url":n.includes("description")||n.includes("about")||n.includes("mission")||n.includes("vision")||n.includes("history")||n.includes("hours")||n.includes("address")||n.includes("body")||typeof t=="string"&&t.length>120?"textarea":"text"}function te(e,t){return e?`${e}.${t}`:t}function B(e){return typeof e=="string"?e.trim():""}function ne(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function En(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[_-]+/g," ").replace(/\b\w/g,t=>t.toUpperCase())}function Sn(e){return/ies$/i.test(e)?e.replace(/ies$/i,"y"):/s$/i.test(e)&&!/ss$/i.test(e)?e.replace(/s$/i,""):e}var Zi=["primary","secondary","accent","background","text","surface","surfaceAlt","heading","mutedText","border","headerBackground","footerBackground","cardBackground","buttonBackground","buttonText"],qi=["headingFont","bodyFont","baseSize","headingScale","bodyLineHeight","headingLineHeight","headingWeight","bodyWeight","letterSpacing"],Wi=["heroMinHeight","sectionPadding","contentMaxWidth","containerPadding","sectionGap","elementGap","gridGap"],Gi=["textAlign","contentAlign","heroTextAlign","cardTextAlign","gridColumns"],Xi=["cardWidth","cardMinHeight","cardPadding","cardRadius","cardBorderWidth","cardShadow","buttonPadding","buttonRadius","buttonShadow","imageRadius","headerHeight"],Yi=["backgroundColor","textColor","headingColor","minHeight","padding","contentMaxWidth","gap","textAlign","contentAlign","cardBackgroundColor","cardWidth","cardMinHeight","cardRadius","gridColumns"];function Q(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Ji(e){let t=e.trim();if(!t)return"";if(!(t.length>160)&&!/[;{}<>\r\n]/.test(t)&&!/(?:url\s*\(|expression\s*\(|@import|javascript:)/i.test(t))return t}function wn(e){let t=e.trim().toLowerCase(),n=t.match(/^#([0-9a-f]{3})$/);return n?`#${[...n[1]].map(i=>i.repeat(2)).join("")}`:/^#[0-9a-f]{6}$/.test(t)?t:null}function Qi(e){if(!Q(e))return;let t={};for(let[n,i]of Object.entries(e).slice(0,64)){if(typeof i!="string")continue;let r=wn(n),o=wn(i);!r||!o||(t[r]=o)}return Object.keys(t).length>0?t:void 0}function ae(e,t){if(!Q(e))return;let n={};for(let i of t){if(typeof e[i]!="string")continue;let r=Ji(e[i]);r!==void 0&&(n[i]=r)}return Object.keys(n).length>0?n:void 0}function er(e){return/^[a-zA-Z0-9_-]{1,64}$/.test(e)}function tr(){return{version:1}}function nr(e){if(!Q(e))return tr();let t=ae(e.colors,Zi),n=Qi(e.colorReplacements),i=ae(e.typography,qi),r=ae(e.spacing,Wi),o=ae(e.layout,Gi),s=ae(e.components,Xi),l={};if(Q(e.sections))for(let[f,u]of Object.entries(e.sections)){if(!er(f)||!Q(u))continue;let g={...ae(u,Yi)??{}};typeof u.visible=="boolean"&&(g.visible=u.visible),Object.keys(g).length>0&&(l[f]=g)}return{version:1,...t?{colors:t}:{},...n?{colorReplacements:n}:{},...i?{typography:i}:{},...r?{spacing:r}:{},...o?{layout:o}:{},...s?{components:s}:{},...Object.keys(l).length>0?{sections:l}:{}}}function Tn(e){if(!Q(e))return null;let t=e.themeSchema;if(!Q(t))return null;let n=nr(Q(t.defaults)?{version:1,...t.defaults}:null),i={...n.colors?{colors:n.colors}:{},...n.typography?{typography:n.typography}:{},...n.spacing?{spacing:n.spacing}:{},...n.layout?{layout:n.layout}:{},...n.components?{components:n.components}:{},...n.sections?{sections:n.sections}:{}};return{version:typeof t.version=="number"?t.version:1,tokens:Array.isArray(t.tokens)?t.tokens.filter(r=>typeof r=="string"):void 0,...Object.keys(i).length>0?{defaults:i}:{}}}var ir=e=>new Error(e);function bn(e,t=ir){let n=d=>{throw t(d)};(!e||typeof e!="object")&&n("Template manifest is missing or invalid.");let i=e;i.framework!=="nextjs-static-export"&&n('Template manifest framework must be "nextjs-static-export".'),(typeof i.siteDataFile!="string"||!i.siteDataFile.trim())&&n("Template manifest siteDataFile is required.");let r=typeof i.version=="number"&&Number.isFinite(i.version)?i.version:1,o=rr(i.visualEditing,r,t),s=ln(i.editorSchema),l=Tn(i),f=Array.isArray(i.colorPalette)?i.colorPalette.filter(d=>!!d&&typeof d=="object").flatMap(d=>{let g=typeof d.color=="string"?d.color.trim().toLowerCase():"";if(!/^#[0-9a-f]{6}$/.test(g))return[];let b=typeof d.usageCount=="number"&&Number.isFinite(d.usageCount)?Math.max(1,Math.floor(d.usageCount)):1;return[{color:g,usageCount:b}]}).slice(0,40):[],u=Ae(s);if(u.length>0){let d=u.slice(0,5).map(g=>`"${g.path}"`).join(", ");n(`Template editorSchema declares the same editable path in more than one place: ${d}. Keep each primitive field and list in exactly one section; a dedicated nested section must not also be repeated inside its ancestor section.`)}return{framework:"nextjs-static-export",version:r,siteDataFile:i.siteDataFile.trim(),editorSchema:s,pages:Array.isArray(i.pages)?i.pages.filter(d=>!!d&&typeof d=="object").map(d=>{let g=typeof d.id=="string"&&d.id.trim()?d.id.trim():null,b=typeof d.label=="string"&&d.label.trim()?d.label.trim():null;return!g||!b?n("Each template manifest page must include id and label."):{id:g,label:b,route:typeof d.route=="string"&&d.route.trim()?d.route.trim():void 0,required:typeof d.required=="boolean"?d.required:!1,description:typeof d.description=="string"?d.description.trim():void 0}}):void 0,visualEditing:o,...l?{themeSchema:l}:{},...f.length>0?{colorPalette:f}:{},outputDirectory:typeof i.outputDirectory=="string"?i.outputDirectory.trim():void 0,installCommand:typeof i.installCommand=="string"?i.installCommand.trim():void 0,buildCommand:typeof i.buildCommand=="string"?i.buildCommand.trim():void 0,basePathEnvVar:typeof i.basePathEnvVar=="string"?i.basePathEnvVar.trim():"NEXT_PUBLIC_SITE_BASE_PATH",publicSiteUrlEnvVar:typeof i.publicSiteUrlEnvVar=="string"?i.publicSiteUrlEnvVar.trim():void 0}}function rr(e,t,n){let i=l=>{throw n(l)};if(!e||typeof e!="object"||Array.isArray(e))return t>=2&&i('Template manifest version 2 requires visualEditing.contractVersion 1 and visualEditing.mode "strict".'),{contractVersion:1,mode:"legacy"};let r=e;r.contractVersion!==1&&i("Template visualEditing.contractVersion must be 1.");let o=r.mode==="strict"||r.mode==="legacy"?r.mode:null;if(!o)return i('Template visualEditing.mode must be "strict" or "legacy".');t>=2&&o!=="strict"&&i('Template manifest version 2 requires visualEditing.mode "strict".');let s=Array.isArray(r.controlOnlyPaths)?r.controlOnlyPaths.filter(l=>typeof l=="string").map(l=>l.trim()).filter(Boolean):[];return{contractVersion:1,mode:o,controlOnlyPaths:s.length>0?s:void 0}}var or={"data-preview-field-path":"field","data-preview-list-path":"list","data-preview-item-path":"item","data-preview-page-key":"page"},In=/\b(data-preview-(?:field-path|list-path|item-path|page-key))\s*=\s*(?:"([^"]*)"|'([^']*)'|\{\s*`([\s\S]*?)`\s*\}|\{\s*"([^"]*)"\s*\}|\{\s*'([^']*)'\s*\})/g,Pn=/\b(data-preview-(?:field-path|list-path|item-path|page-key))\s*=/g,Cn=String.raw`[^.[\]\s]+`,sr=new RegExp(String.raw`^${Cn}(?:\[(?:\d+|\*)\])*(?:\.${Cn}(?:\[(?:\d+|\*)\])*)*$`),ar=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),lr=new Set(["head","script","style","noscript","svg","template"]),An=new Set(["html","body","main","header","footer","nav","section","article","aside","form","div","ul","ol","table","thead","tbody","tfoot","tr"]),ve="FIVORA_PREVIEW_SITE_DATA",kn=`${["MARKET","PLACE"].join("")}_PREVIEW_`,ke=`${kn}SITE_DATA`;var Le="FIVORA_PREVIEW_READY",Qe=`${kn}READY`,cr=Le;function rt(e,t){let n={fieldPatterns:new Set,concreteFields:new Set,listPatterns:new Set,concreteLists:new Set,itemPatterns:new Set,concreteItems:new Set};if(e)for(let[i,r]of Object.entries(e))at(r,i,n);for(let i of t?.sections??[])lt(i.path,i,n);return{fieldPatterns:[...n.fieldPatterns].sort(),concreteFields:[...n.concreteFields].sort(),listPatterns:[...n.listPatterns].sort(),concreteLists:[...n.concreteLists].sort(),itemPatterns:[...n.itemPatterns].sort(),concreteItems:[...n.concreteItems].sort()}}function dt(e,t){let n=Nn(e??{});for(let i of t?.sections??[])fr(n,i.path,i);return n}function Ln(e,t){let n=structuredClone(e??{});for(let i of t?.sections??[])dr(n,i.path,i);return st(n,"")}function Rn(e){let t=[],n=[];for(let i of e){let r=new Set;In.lastIndex=0;for(let o of i.content.matchAll(In)){let s=o[1],l=o[2]??o[3]??o[4]??o[5]??o[6]??"",f=o.index??0;r.add(f),t.push({kind:or[s],value:re(l).trim(),filePath:i.filePath,artifactKind:i.kind,offset:f,line:V(i.content,f)})}Pn.lastIndex=0;for(let o of i.content.matchAll(Pn)){let s=o.index??0;r.has(s)||n.push(`${i.filePath}:${V(i.content,s)} ${o[1]} must use a literal string or a JSX template literal.`)}}return{markers:t,unparseableAttributes:n}}function _n(e){let t=e.manifestVersion>=2||e.visualEditing?.mode==="strict"?"strict":"legacy",n=[],i=[],r=rt(e.contentDefaults,e.editorSchema),o=Rn(e.artifacts),s=o.markers;e.contentDefaults||n.push('site-data.json must contain a JSON object at "content".'),e.editorSchema||n.push("An editor schema could not be derived from site-data.json content."),vr(e.editorSchema,n),kr(e.editorSchema,n),hr(e.editorSchema,n,e.pages),yr(e.editorSchema,e.contentDefaults,n),Sr(e.artifacts,n),wr(e.artifacts,n),i.push(...o.unparseableAttributes.map(T=>`${T} Exported exact markers may still satisfy strict coverage.`));let l=q(s,"field",n),f=q(s,"list",n),u=q(s,"item",n),d=s.filter(T=>T.artifactKind==="html"),g=q(d,"field",n),b=q(d,"list",n),c=q(d,"item",n),p=s.filter(T=>T.artifactKind==="source"),y=q(p,"field",n),m=q(p,"list",n),E=q(p,"item",n),w=On(e.visualEditing?.controlOnlyPaths??[],r,n);tt({label:"editable field",expectedPatterns:r.fieldPatterns,concretePaths:r.concreteFields,htmlMarkerPaths:g,sourceMarkerPaths:y,controlOnlyPaths:w,findings:n}),tt({label:"editable list",expectedPatterns:r.listPatterns,concretePaths:r.concreteLists,htmlMarkerPaths:b,sourceMarkerPaths:m,controlOnlyPaths:[],findings:n}),tt({label:"editable list item",expectedPatterns:r.itemPatterns,concretePaths:r.concreteItems,htmlMarkerPaths:c,sourceMarkerPaths:E,controlOnlyPaths:[],findings:n}),nt("field",l,r.fieldPatterns,r.concreteFields,n),nt("list",f,r.listPatterns,r.concreteLists,n),nt("item",u,r.itemPatterns,r.concreteItems,n),Mn(e.manifestVersion,e.pages??[],s,e.artifacts,n),$n({manifestVersion:e.manifestVersion,pages:e.pages??[],schema:e.editorSchema,markers:s,fieldPaths:z([...r.fieldPatterns.filter(T=>!T.includes("[*]")),...r.concreteFields]),listPaths:z([...r.listPatterns.filter(T=>!T.includes("[*]")),...r.concreteLists]),itemPaths:r.concreteItems,controlOnlyPaths:w,findings:n});let a=Tr(e.artifacts,e.pages??[]);t==="strict"?n.push(...a):i.push(...a);let h=z(n),S=z(i);return t==="legacy"?{mode:t,errors:[],warnings:z([...h.map(T=>`[legacy] ${T}`),...S]),inventory:r,markers:s}:{mode:t,errors:h,warnings:S,inventory:r,markers:s}}function Dn(e){let t=[],n=[],i=rt(e.contentDefaults,e.editorSchema),r=dt(e.contentDefaults,e.editorSchema),o=rt(r,e.editorSchema),s=z([...i.fieldPatterns.filter(y=>!y.includes("[*]")),...o.concreteFields]),l=z([...i.listPatterns.filter(y=>!y.includes("[*]")),...o.concreteLists]),f=o.concreteItems,u=e.artifacts.filter(y=>y.kind==="html"),d=Rn(u),g=q(d.markers,"field",t),b=q(d.markers,"list",t),c=q(d.markers,"item",t),p=On(e.visualEditing?.controlOnlyPaths??[],i,t);et({markerPaths:g,expectedPaths:o.concreteFields,knownPatterns:i.fieldPatterns,attribute:"field",findings:t}),et({markerPaths:b,expectedPaths:o.concreteLists,knownPatterns:i.listPatterns,attribute:"list",findings:t}),et({markerPaths:c,expectedPaths:o.concreteItems,knownPatterns:i.itemPatterns,attribute:"item",findings:t});for(let y of s)Ne(y,p)||g.includes(y)||t.push(`Empty-state export removed data-preview-field-path="${y}". Keep the editable target mounted when its value is empty, false, or zero.`);for(let y of l)b.includes(y)||t.push(`Empty-state export removed data-preview-list-path="${y}". Keep the list container mounted when the list has no items.`);for(let y of f)c.includes(y)||t.push(`Empty-state export removed data-preview-item-path="${y}" required by minItems/required list validation.`);return Mn(e.manifestVersion,e.pages??[],d.markers,u,t),$n({manifestVersion:e.manifestVersion,pages:e.pages??[],schema:e.editorSchema,markers:d.markers,fieldPaths:s,listPaths:l,itemPaths:f,controlOnlyPaths:p,findings:t}),n.push(...d.unparseableAttributes),{errors:z(t),warnings:z(n),requiredFieldPaths:s,requiredListPaths:l,requiredItemPaths:f}}function et(e){let t=new Set(e.expectedPaths),n=new Set(e.knownPatterns);for(let i of e.markerPaths)i.includes("[*]")||t.has(i)||!n.has(j(i))||e.findings.push(`Empty-state export rendered out-of-range data-preview-${e.attribute}-path="${i}" for a list item that does not exist. Render list items from the actual site-data array instead of fixed indexes or placeholder cards.`)}function dr(e,t,n){let i=t.split(".").map(s=>s.trim()).filter(Boolean);if(i.length===0||i.some(s=>s.includes("[")))return;let r=e;for(let s of i.slice(0,-1)){let l=r[s];G(l)||(r[s]={}),r=r[s]}let o=i.at(-1);ot(r,o,n,t)}function ot(e,t,n,i){if(n.type==="list"){let r=Array.isArray(e[t])?[...e[t]]:[],o=ie(n.maxItems),s=Math.min(o??Number.MAX_SAFE_INTEGER,o===0?0:Math.max(1,ie(n.minItems)??(n.required?1:0)));for(;r.length<s;)r.push(void 0);e[t]=r.map((l,f)=>{let u=`${i}[${f}]`;if(n.itemField)return xn(l,n.itemField.type,u,n.itemField.options);let d=G(l)?l:{};for(let g of n.fields??[])ot(d,g.key,g,W(u,g.key));return d});return}if(n.type==="object"){let r=G(e[t])?e[t]:{};e[t]=r;for(let o of n.fields??[])ot(r,o.key,o,W(i,o.key));return}e[t]=xn(e[t],n.type,i,n.options)}function xn(e,t,n,i){return t==="number"?typeof e=="number"&&Number.isFinite(e)&&e!==0?e:1:t==="boolean"?e===!0?e:!0:typeof e=="string"&&e.trim()&&(t!=="select"||!i?.length||i.includes(e))?e:t==="select"?i?.[0]??Re(n):t==="url"?`https://template-validation.example.invalid/${_e(n)}`:t==="image"?`/template-validation-${_e(n)}.svg`:t==="email"?"validation@example.invalid":t==="tel"?"+12025550142":Re(n)}function st(e,t){return Array.isArray(e)?e.map((n,i)=>st(n,`${t}[${i}]`)):G(e)?Object.fromEntries(Object.entries(e).map(([n,i])=>{let r=W(t,n);return[n,st(i,r)]})):typeof e=="string"?e.trim()?e:ur(t):typeof e=="number"?Number.isFinite(e)&&e!==0?e:1:typeof e=="boolean"?!0:e??Re(t)}function ur(e){let t=e.toLowerCase();return t.includes("email")?"validation@example.invalid":t.includes("phone")||t.includes("mobile")||t.includes("whatsapp")||t.includes("contactnumber")?"+12025550142":t.includes("image")||t.includes("logo")||t.includes("banner")||t.includes("thumbnail")||t.includes("photo")?`/template-validation-${_e(e)}.svg`:t.includes("url")||t.includes("link")?`https://template-validation.example.invalid/${_e(e)}`:Re(e)}function Re(e){return`Validation ${e||"content"}`}function _e(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"content"}function Nn(e){return Array.isArray(e)?[]:G(e)?Object.fromEntries(Object.entries(e).map(([t,n])=>[t,Nn(n)])):typeof e=="string"?"":typeof e=="number"?0:typeof e=="boolean"?!1:e}function fr(e,t,n){let i=t.split(".").map(s=>s.trim()).filter(Boolean);if(i.length===0||i.some(s=>s.includes("[")))return;let r=e;for(let s of i.slice(0,-1)){let l=r[s];G(l)||(r[s]={}),r=r[s]}let o=i.at(-1);ut(r,o,n)}function ut(e,t,n){if(n.type==="list"){let i=Math.min(ie(n.maxItems)??Number.MAX_SAFE_INTEGER,ie(n.minItems)??(n.required?1:0));e[t]=Array.from({length:i},()=>mr(n));return}if(n.type==="object"){let i=G(e[t])?e[t]:{};e[t]=i;for(let r of n.fields??[])ut(i,r.key,r);return}e[t]=n.type==="number"?0:n.type==="boolean"?!1:""}function mr(e){if(e.itemField)return e.itemField.type==="number"?0:e.itemField.type==="boolean"?!1:"";let t={};for(let n of e.fields??[])ut(t,n.key,n);return t}function at(e,t,n){if(Array.isArray(e)){let i=j(t);n.listPatterns.add(i),n.concreteLists.add(t),n.itemPatterns.add(`${i}[*]`),e.forEach((r,o)=>{let s=`${t}[${o}]`;n.concreteItems.add(s),Array.isArray(r)||G(r)?at(r,s,n):(n.fieldPatterns.add(j(s)),n.concreteFields.add(s))});return}if(G(e)){for(let[i,r]of Object.entries(e))at(r,W(t,i),n);return}n.fieldPatterns.add(j(t)),n.concreteFields.add(t)}function lt(e,t,n){if(t.type==="object"){for(let i of t.fields??[])lt(W(e,i.key),i,n);return}if(t.type==="list"){let i=j(e),r=`${i}[*]`;n.listPatterns.add(i),n.itemPatterns.add(r),t.itemField&&n.fieldPatterns.add(r);for(let o of t.fields??[])lt(W(r,o.key),o,n);return}n.fieldPatterns.add(j(e))}function q(e,t,n){let i=[];for(let r of e.filter(o=>o.kind===t)){let o=fe(r.value);if(!o){n.push(`${r.filePath}:${Un(r)} has invalid data-preview-${t}-path "${r.value}".`);continue}i.push(o)}return z(i)}function On(e,t,n){let i=[];for(let r of e){let o=fe(r);if(!o){n.push(`controlOnlyPaths contains invalid path "${r}".`);continue}if(![...t.fieldPatterns,...t.concreteFields].some(l=>ct(o,l))){n.push(`controlOnlyPaths contains unknown editable field path "${o}".`);continue}i.push(o)}return z(i)}function tt(e){for(let t of e.expectedPatterns){if(Ne(t,e.controlOnlyPaths))continue;let n=e.concretePaths.filter(i=>j(i)===t);if(!t.includes("[*]")){e.htmlMarkerPaths.includes(t)||e.findings.push(`Exported HTML is missing exact data-preview-${it(e.label)}="${t}" for ${e.label}.`);continue}e.sourceMarkerPaths.some(i=>Lr(i,t))||e.findings.push(`Source is missing dynamic data-preview-${it(e.label)} mapping for ${e.label} "${t}". Use an exact JSX template path such as [\${index}] so newly added and reordered items remain editable.`),n.length>0}for(let t of e.concretePaths)e.expectedPatterns.includes(t)||Ne(t,e.controlOnlyPaths)||e.htmlMarkerPaths.includes(t)||e.findings.push(`Exported HTML is missing exact data-preview-${it(e.label)}="${t}" for concrete ${e.label}.`)}function nt(e,t,n,i,r){for(let o of t)n.some(l=>ct(o,l))||i.some(l=>ct(o,l))||r.push(`data-preview-${e}-path references unknown path "${o}".`)}function Mn(e,t,n,i,r){let o=i.filter(d=>d.kind==="html"),s=n.filter(d=>d.kind==="page"&&d.artifactKind==="html"),l=new Set(t.map(d=>d.id)),f=new Set,u=new Map;t.length===0&&r.push("Strict visual editing requires at least one manifest pages[] entry.");for(let d of t){f.has(d.id)&&r.push(`Manifest pages[] contains duplicate id "${d.id}".`),f.add(d.id);let g=mt(d.route)??(e<2?Vn(d.id):null);if(!g){r.push(`Manifest page "${d.id}" must declare a canonical route for strict visual editing.`);continue}let b=u.get(g);b?r.push(`Manifest pages "${b}" and "${d.id}" use duplicate route "${g}".`):u.set(g,d.id);let c=o.filter(m=>pt(m.filePath,g));if(c.length===0){r.push(`Manifest page "${d.id}" route "${g}" has no exported HTML file.`);continue}let p=new Set(c.map(m=>m.filePath));s.some(m=>m.value===d.id&&p.has(m.filePath))||r.push(`Exported route "${g}" is missing data-preview-page-key="${d.id}".`)}for(let d of n.filter(g=>g.kind==="page"))l.has(d.value)||r.push(`${d.filePath}:${Un(d)} data-preview-page-key references unknown manifest page "${d.value}".`)}function $n(e){let t=(e.schema?.sections??[]).map(r=>({section:r,canonicalPath:fe(r.path)})).filter(r=>!!r.canonicalPath),n=new Map(e.pages.map(r=>[r.id,r])),i=(r,o)=>{for(let s of o){if(r==="field"&&Ne(s,e.controlOnlyPaths))continue;let l=t.filter(b=>pr(s,b.canonicalPath)).sort((b,c)=>c.canonicalPath.length-b.canonicalPath.length)[0];if(!l?.section.pageKey)continue;let f=n.get(l.section.pageKey);if(!f){e.findings.push(`editorSchema section "${l.section.path}" assigns ${Fn(r)} "${s}" to unknown manifest page "${l.section.pageKey}".`);continue}let u=mt(f.route)??(e.manifestVersion<2?Vn(f.id):null);!u||!e.markers.some(b=>b.kind===r&&b.artifactKind==="html"&&fe(b.value)===s)||e.markers.some(b=>b.kind===r&&b.artifactKind==="html"&&fe(b.value)===s&&pt(b.filePath,u))||e.findings.push(`Page-owned ${Fn(r)} "${s}" from editorSchema section "${l.section.path}" must render data-preview-${gr(r)}="${s}" on manifest page "${f.id}" route "${u}". Shared sections without pageKey may render globally.`)}};i("field",z(e.fieldPaths)),i("list",z(e.listPaths)),i("item",z(e.itemPaths))}function pr(e,t){let n=j(e),i=j(t);return n===i||n.startsWith(`${i}.`)||n.startsWith(`${i}[`)}function Fn(e){return e==="field"?"editable field":e==="list"?"editable list":"editable list item"}function gr(e){return e==="field"?"field-path":e==="list"?"list-path":"item-path"}function hr(e,t,n=[]){let i=new Set(n.map(s=>s.id?.trim()).filter(s=>!!s)),r=(s,l)=>{if(!l?.some(f=>typeof f=="string"&&f.trim().length>0)){t.push(`editorSchema select field "${s}" must declare at least one non-empty option for strict visual editing. Add options: ["First option", ...] or change the field type.`);return}if(i.size>0&&/(?:destination|action|targetpage|buttonaction|pagekey)/i.test(s))for(let u of l){let d=typeof u=="string"?u.trim():"";d&&d!=="none"&&d!=="external"&&!i.has(d)&&t.push(`editorSchema select field "${s}" declares destination option "${d}" which is not in fivora-template.json pages[]. Declared pages: ${[...i].join(", ")}.`)}},o=(s,l)=>{if(l.type==="select"){r(s,l.options);return}if(l.type==="object"){for(let u of l.fields??[])o(W(s,u.key),u);return}if(l.type!=="list")return;let f=`${j(s)}[*]`;l.itemField?.type==="select"&&r(f,l.itemField.options);for(let u of l.fields??[])o(W(f,u.key),u)};for(let s of e?.sections??[])o(s.path,s)}function yr(e,t,n){let i=(o,s)=>{if(s.type==="object"){for(let g of s.fields??[])i(W(o,g.key),g);return}if(s.type!=="list")return;let l=ie(s.minItems),f=ie(s.maxItems);s.minItems!==void 0&&l===null&&n.push(`editorSchema list "${o}" minItems must be a non-negative safe integer.`),s.maxItems!==void 0&&f===null&&n.push(`editorSchema list "${o}" maxItems must be a non-negative safe integer.`);let u=l??(s.required?1:0);f!==null&&u>f&&n.push(`editorSchema list "${o}" requires at least ${u} item${u===1?"":"s"} but maxItems is ${f}. Increase maxItems or lower minItems/required.`);let d=`${j(o)}[*]`;for(let g of s.fields??[])i(W(d,g.key),g)},r=(o,s,l)=>{if(s.type==="object"){let d=G(l)?l:{};for(let g of s.fields??[])r(W(o,g.key),g,d[g.key]);return}if(s.type!=="list")return;let f=Array.isArray(l)?l:[],u=ie(s.maxItems);u!==null&&f.length>u&&n.push(`site-data.json content list "${o}" contains ${f.length} items, exceeding editorSchema maxItems ${u}.`);for(let[d,g]of f.entries()){let b=G(g)?g:{};for(let c of s.fields??[])r(W(`${o}[${d}]`,c.key),c,b[c.key])}};for(let o of e?.sections??[])i(o.path,o),r(o.path,o,Er(t??{},o.path))}function ie(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?e:null}function Er(e,t){let n=e;for(let i of t.split(".").map(r=>r.trim())){if(!i||!G(n))return;n=n[i]}return n}function Sr(e,t){let n=[/\b(?:setAttribute|setAttributeNS|toggleAttribute)\s*\(\s*['"`]data-preview-static['"`]/m,/\.(?:attr|prop)\s*\(\s*['"`]data-preview-static['"`]/m,/\bdataset\s*(?:\.\s*previewStatic|\[\s*['"`]previewStatic['"`]\s*\])\s*=/m,/\b(?:innerHTML|outerHTML)\s*\+?=[^;]{0,500}data-preview-static/m,/\.(?:replace|replaceAll)\s*\([\s\S]{0,500}?data-preview-static/m];for(let i of e.filter(r=>r.kind==="source")){let r=n.map(d=>d.exec(i.content)).find(d=>!!d),o=i.content.search(/data-preview-static/),s=/\b(?:writeFile|writeFileSync|appendFile|appendFileSync)\s*\(/m.exec(i.content),l=/\.[cm]?[jt]s$/i.test(i.filePath),f=o>=0&&l&&s;if(!r&&!f)continue;let u=r?.index??o;t.push(`${i.filePath}:${V(i.content,u)} programmatically injects data-preview-static. Author each intentional static annotation directly on the smallest source element; blanket or post-build annotation bypasses strict editable-content validation.`)}}function wr(e,t){let n=e.filter(b=>b.kind==="source"),i=n.map(b=>b.content).join(`
3
- `),m=(i.includes("@fivora/editable-components")||i.includes("@deneb-ui/ui")||i.includes("@deneb/ui"))&&(i.includes("SiteDataProvider")||i.includes("BaseSiteDataProvider")||i.includes("DenebDataProvider")),r=m||i.includes(ve)||i.includes(ke),o=m||i.includes(Le)||i.includes(Qe),s=/(?:window|globalThis|self)\s*\.\s*addEventListener\s*\(\s*['"]message['"]/m.test(i)||/(?:window|globalThis|self)\s*\.\s*onmessage\s*=/m.test(i),l=/\bset[A-Z_$][\w$]*\s*\(/m.test(i)||/\bdispatch\s*\(/m.test(i)||/\b(?:store|siteDataStore)\s*\.\s*(?:setState|set|update)\s*\(/m.test(i),f=n.some(b=>{let c=b.content,p=/(?:window|globalThis|self)\s*\.\s*addEventListener\s*\(\s*['"]message['"]/m.test(c)||/(?:window|globalThis|self)\s*\.\s*onmessage\s*=/m.test(c),y=/\bset[A-Z_$][\w$]*\s*\(/m.test(c)||/\bdispatch\s*\(/m.test(c)||/\b(?:store|siteDataStore)\s*\.\s*(?:setState|set|update)\s*\(/m.test(c);return(c.includes(ve)||c.includes(ke))&&p&&y}),d=/\bcreateContext\s*[<(]/m.test(i)&&/(?:\.Provider\b|<[A-Za-z_$][\w$]*Provider\b)/m.test(i)&&/\buseContext\s*[<(]/m.test(i)||/\buseSyncExternalStore\s*[<(]/m.test(i)||/\bcreate(?:Store|Signal)\s*[<(]/m.test(i)&&/\buse[A-Z_$][\w$]*(?:Store|Data)\s*[<(]/m.test(i),g=n.some(b=>(b.content.includes(Le)||b.content.includes(Qe))&&/\bpostMessage\s*\(/m.test(b.content));r||t.push(`Preview runtime source must implement the "${ve}" (or legacy "${ke}") protocol so editor changes replace the rendered site data instead of remaining in a static JSON import.`),o||t.push(`Preview runtime source must implement the "${Le}" (or legacy "${Qe}") protocol so the editor can wait for a live preview before sending data.`),(!m&&(!s||!l||!f))&&t.push(`Preview runtime source must handle "${ve}" (or legacy "${ke}") and apply its payload through a reactive state setter, reducer, or store update in the same live-data module.`),(m||d)||t.push("Preview runtime source must expose live site data through a recognizable reactive provider/hook (for example createContext + Provider + useContext, useSyncExternalStore, or a reactive store hook). Static site-data.json imports alone cannot be certified."),(m||g)||t.push(`Preview runtime source must call postMessage with "${cr}" after its live-data listener is ready.`)}function Tr(e,t){let n=[];for(let i of e.filter(r=>r.kind==="html"&&!br(r.filePath,t)))n.push(...Ir(i));return n}function br(e,t){let n=e.replace(/\\/g,"/").replace(/^\/+/,"");return/^(?:404|500|_error|_not-found)(?:\/index)?\.html$/i.test(n)?!t.some(r=>{let o=mt(r.route);return o?pt(n,o):!1}):!1}function Ir(e){let t=[],n=[],i=e.content.matchAll(/<!--[\s\S]*?-->|<![^>]*>|<\/?[^>]+>|[^<]+/g);for(let r of i){let o=r[0],s=r.index??0,l=n.at(-1);if(o.startsWith("<!--")||o.startsWith("<!"))continue;if(o.startsWith("</")){let u=o.slice(2,-1).trim().split(/\s+/)[0]?.toLowerCase(),d=n.map(g=>g.tag).lastIndexOf(u);d>=0&&(t.push(...Pr(e,n[d])),n.splice(d));continue}if(o.startsWith("<")){let u=o.match(/^<\s*([a-zA-Z0-9:-]+)/);if(!u)continue;let d=u[1].toLowerCase(),g=/\bdata-preview-field-path\s*=/.test(o),b=/\bdata-preview-list-path\s*=/.test(o),c=/\bdata-preview-item-path\s*=/.test(o),p=g||b||c;if(g)for(let T of n)T.ownsFieldMarker&&(T.hasNestedFieldMarker=!0);let y=o.match(/\bdata-preview-static\s*=\s*(?:"([^"]*)"|'([^']*)')/),m=!!y;m&&!(y?.[1]??y?.[2]??"").trim()&&t.push(`${e.filePath}:${V(e.content,s)} data-preview-static requires a reason.`),p&&(m||l?.staticCovered)&&t.push(`${e.filePath}:${V(e.content,s)} data-preview field/list/item markers cannot be on or inside data-preview-static. The visual editor intentionally ignores targets beneath a static ancestor.`),g&&An.has(d)&&t.push(`${e.filePath}:${V(e.content,s)} data-preview-field-path cannot be placed on broad <${d}> content containers. Put the marker on the exact visible text, media, link, or control that the field edits.`),m&&An.has(d)&&t.push(`${e.filePath}:${V(e.content,s)} data-preview-static cannot cover a broad <${d}> content container. Mark only the smallest genuinely non-editable element.`);let E=!!l?.hidden||Fr(o,d);p&&E&&t.push(`${e.filePath}:${V(e.content,s)} data-preview field/list/item marker is hidden. Strict visual-edit targets must remain visible and clickable in the exported page.`);let w=o.match(/\bdata-preview-field-path\s*=\s*(?:"([^"]*)"|'([^']*)')/)?.slice(1).find(Boolean)??null,a=o.match(/\bdata-preview-item-path\s*=\s*(?:"([^"]*)"|'([^']*)')/)?.slice(1).find(Boolean)??null;a&&l?.itemPath&&!vn(a,l.itemPath)&&t.push(`${e.filePath}:${V(e.content,s)} repeated item "${a}" is nested inside unrelated item "${l.itemPath}". One visual card must be one object-list item; do not couple parallel arrays by index.`);let h=a??l?.itemPath??null;w&&h&&/\[\d+\]/.test(w)&&!vn(w,h)&&t.push(`${e.filePath}:${V(e.content,s)} repeated field "${w}" is rendered inside item "${h}" but belongs to a different list. Model one visual card as one object-list item instead of coupling parallel arrays by index.`);let S={tag:d,ignored:!!l?.ignored||lr.has(d),hidden:E,fieldCovered:!!l?.fieldCovered||g,staticCovered:!!l?.staticCovered||m,ownsFieldMarker:g,hasNestedFieldMarker:!1,fieldPath:w,itemPath:h,shopAttributeValues:Cr(o,d),visibleTextParts:[],offset:s};if(!S.ignored&&!S.fieldCovered&&!S.staticCovered){let T=xr(e,o,d,s);t.push(...T),d==="img"&&!S.hidden&&T.length===0&&t.push(`${e.filePath}:${V(e.content,s)} rendered <img> is not covered by data-preview-field-path or data-preview-static. Bind business media to an exact image field, or mark an intentional fixed/decorative image static with a reason.`)}!ar.has(d)&&!/\/\s*>$/.test(o)&&n.push(S);continue}let f=ft(o);if(De(f))for(let u of n)u.ownsFieldMarker&&u.visibleTextParts.push(f);l?.ignored||l?.fieldCovered||l?.staticCovered||De(f)&&t.push(`${e.filePath}:${V(e.content,s)} visible text "${Oe(f,72)}" is not covered by data-preview-field-path or data-preview-static.`)}return t}function vn(e,t){let n=re(e).trim(),i=re(t).trim();return n===i||n.startsWith(`${i}.`)||n.startsWith(`${i}[`)}function Pr(e,t){if(!t.ownsFieldMarker||t.hasNestedFieldMarker||t.shopAttributeValues.length===0)return[];let n=ft(t.visibleTextParts.join(" "));return!De(n)||t.shopAttributeValues.some(i=>Ar(i,n))?[]:[`${e.filePath}:${V(e.content,t.offset)} data-preview-field-path="${t.fieldPath??""}" cannot cover both <${t.tag}> action/media attributes and different visible text "${Oe(n,72)}". Put the action/media marker on the element and the label marker on an exact nested text element.`]}function Cr(e,t){return[...e.matchAll(/\b(href|src|poster)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi)].map(n=>({name:n[1].toLowerCase(),value:re(n[2]??n[3]??"").trim()})).filter(({name:n,value:i})=>Bn(t,n,i)).map(({value:n})=>n)}function Ar(e,t){let n=i=>re(i).replace(/^(?:mailto:|tel:|sms:|https?:\/\/)/i,"").replace(/^www\./i,"").replace(/\/+$/g,"").replace(/\s+/g,"").toLowerCase();return n(e)===n(t)}function xr(e,t,n,i){let r=[],o=[...t.matchAll(/\b(href|src|poster)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi)];for(let d of o){let g=d[1].toLowerCase(),b=re(d[2]??d[3]??"").trim();Bn(n,g,b)&&r.push(`${e.filePath}:${V(e.content,i)} ${n}[${g}="${Oe(b,72)}"] is not covered by data-preview-field-path or data-preview-static.`)}let s=[...t.matchAll(/\b(placeholder|alt|title|aria-label|value)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi)],l=t.match(/\btype\s*=\s*(?:"([^"]*)"|'([^']*)')/i),f=(l?.[1]??l?.[2]??"").toLowerCase();for(let d of s){let g=d[1].toLowerCase(),b=ft(d[2]??d[3]??"");!(g==="aria-label"||g==="title"||g==="alt"&&n==="img"||g==="placeholder"&&["input","textarea"].includes(n)||g==="value"&&["input","button"].includes(n)&&!["hidden","checkbox","radio"].includes(f))||!De(b)||r.push(`${e.filePath}:${V(e.content,i)} ${n}[${g}="${Oe(b,72)}"] is not covered by data-preview-field-path or data-preview-static.`)}let u=t.match(/\bstyle\s*=\s*(?:"([^"]*)"|'([^']*)')/i);return u&&/(?:background|background-image)\s*:[^;]*url\(/i.test(u[1]??u[2]??"")&&r.push(`${e.filePath}:${V(e.content,i)} background image is not covered by data-preview-field-path or data-preview-static.`),r}function Fr(e,t){if(/\bhidden(?:\s|=|\/?>)/i.test(e)||/\baria-hidden\s*=\s*(?:"true"|'true')/i.test(e))return!0;if(t==="input"){let r=e.match(/\btype\s*=\s*(?:"([^"]*)"|'([^']*)')/i);if((r?.[1]??r?.[2]??"").trim().toLowerCase()==="hidden")return!0}let n=e.match(/\bstyle\s*=\s*(?:"([^"]*)"|'([^']*)')/i),i=n?.[1]??n?.[2]??"";return/\bdisplay\s*:\s*none\b/i.test(i)||/\bvisibility\s*:\s*hidden\b/i.test(i)}function vr(e,t){let n=new Set,i=new Set;for(let r of e?.sections??[])n.has(r.id)&&t.push(`editorSchema.sections contains duplicate id "${r.id}".`),i.has(r.path)&&t.push(`editorSchema.sections contains duplicate path "${r.path}".`),n.add(r.id),i.add(r.path)}function kr(e,t){for(let n of Ae(e)){let i=n.firstKind===n.duplicateKind?n.firstKind:"field/list";t.push(`editorSchema declares duplicate editable ${i} path "${n.path}" in sections "${n.firstSectionId}" and "${n.duplicateSectionId}". Each editable path must be owned by exactly one section.`)}}function Bn(e,t,n){return!n||n.startsWith("data:")||n.startsWith("blob:")||n.includes("/_next/")||n.includes("${")?!1:t==="href"?e==="a"&&!/^(?:javascript:|data:|blob:)/i.test(n):t==="src"&&["img","video","source"].includes(e)||t==="poster"&&e==="video"}function ft(e){return re(e).replace(/\s+/g," ").trim()}function De(e){return e.length<=2||!new RegExp("\\p{L}","u").test(e)?!1:!/^(?:true|false|null|undefined)$/i.test(e)}function it(e){return e==="editable field"?"field-path":e==="editable list"?"list-path":"item-path"}function Lr(e,t){return t.includes("[*]")?e.includes("[*]")&&e===t:e===t}function ct(e,t){return j(e)===j(t)}function Ne(e,t){return t.some(n=>n.includes("[*]")?j(e)===n:e===n)}function fe(e){let t=e.trim().replace(/\[\s*\$\{[^}]+\}\s*\]/g,"[*]").replace(/\[\s+/g,"[").replace(/\s+\]/g,"]");return sr.test(t)?t:null}function j(e){return e.replace(/\[\d+\]/g,"[*]")}function W(e,t){return e?`${e}.${t}`:t}function mt(e){if(!e)return null;let t=e.trim();return!t.startsWith("/")||t.includes("?")||t.includes("#")||t.includes("\\")||t.includes("..")?null:t==="/"?t:t.replace(/\/+$/,"")}function Vn(e){return e==="home"?"/":`/${e}`}function pt(e,t){let n=e.replace(/\\/g,"/").replace(/^\/+/,"");if(t==="/")return n==="index.html";let i=t.replace(/^\/+/,"");return n===`${i}.html`||n===`${i}/index.html`}function G(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function re(e){return e.replace(/&quot;/gi,'"').replace(/&#39;|&#x27;/gi,"'").replace(/&lt;/gi,"<").replace(/&gt;/gi,">").replace(/&amp;/gi,"&").replace(/&nbsp;/gi," ")}function Un(e){return e.line}function V(e,t){let n=1;for(let i=0;i<t;i+=1)e.charCodeAt(i)===10&&(n+=1);return n}function z(e){return[...new Set(e)].sort()}function Oe(e,t){return e.length<=t?e:`${e.slice(0,Math.max(0,t-1))}\u2026`}function jn(e){let t=e.filter((n,i)=>n.required===!0||i===0).map(n=>n.id);return t.length>0?t:e.slice(0,1).map(n=>n.id)}function zn(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Rr(e,t,n){let i=e.trim().split(/[?#]/,1)[0];return i==="/"||i===""?n?"/":`/${t}`:/^[a-z][a-z0-9+.-]*:/i.test(i)||i.startsWith("//")?n?"/":`/${t}`:`/${i.replace(/^\/+|\/+$/g,"")}`}function Hn(e,t=[]){let i=(zn(e)&&Array.isArray(e.pages)?e.pages:[]).flatMap((o,s)=>{if(!zn(o)||typeof o.id!="string"||!o.id.trim())return[];let l=o.id.trim(),f=typeof o.label=="string"&&o.label.trim()?o.label.trim():l.replace(/_/g," ");return[{id:l,label:f,route:Rr(typeof o.route=="string"?o.route:"",l,s===0)}]});return i.length>0?i:t.map(o=>o.trim()).filter(Boolean).map((o,s)=>({id:o,label:o.replace(/_/g," "),route:s===0?"/":`/${o}`}))}function Kn(e){let t=new Set(e.selectedPages),n=e.pageDefinitions.filter(r=>!t.has(r.id)),i=[];for(let r of e.html.matchAll(/<[a-z][^>]*\b(?:href|formaction|data-href|data-route|data-url)\s*=\s*(?:"([^"]*)"|'([^']*)')[^>]*>/gi)){let o=r[1]??r[2]??"";if(!o.trim()||o.trim().startsWith("#")||/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(o.trim()))continue;let s=o.split(/[?#]/,1)[0],l=e.basePath?.replace(/\/+$/g,"")||"",u=`/${(l&&(s===l||s.startsWith(`${l}/`))?s.slice(l.length)||"/":s).replace(/\/index\.html$/i,"/").replace(/\.html$/i,"").replace(/^\.\//,"").replace(/^\/+|\/+$/g,"")}`,d=u==="/"?"/":u,g=n.find(b=>{let c=b.route==="/"?"/":`/${b.route.replace(/^\/+|\/+$/g,"")}`;return c==="/"?d==="/":d===c||d.startsWith(`${c}/`)});g&&i.push({pageId:g.id,route:g.route,href:s})}return i}var le="fivora-template-validator",Be="1.0.0",Me="fivora-template.json",_r=2500,Dr=12*1024*1024,ei="/template-validation",gt=class{constructor(t,n){this.options=t;this.report={validator:le,version:Be,command:t.command,input:(0,A.resolve)(t.inputPath),status:"passed",startedAt:n.toISOString(),durationMs:0,steps:[],warnings:[]}}options;report;async step(t,n,i){let r=Date.now();this.options.json||process.stdout.write(`\u2192 ${t}
3
+ `),m=(i.includes("@fivora/editable-components")||i.includes("@deneb-ui/ui")||i.includes("@deneb/ui"))&&(i.includes("SiteDataProvider")||i.includes("BaseSiteDataProvider")||i.includes("DenebDataProvider")),r=m||i.includes(ve)||i.includes(ke),o=m||i.includes(Le)||i.includes(Qe),s=/(?:window|globalThis|self)\s*\.\s*addEventListener\s*\(\s*['"]message['"]/m.test(i)||/(?:window|globalThis|self)\s*\.\s*onmessage\s*=/m.test(i),l=/\bset[A-Z_$][\w$]*\s*\(/m.test(i)||/\bdispatch\s*\(/m.test(i)||/\b(?:store|siteDataStore)\s*\.\s*(?:setState|set|update)\s*\(/m.test(i),f=n.some(b=>{let c=b.content,p=/(?:window|globalThis|self)\s*\.\s*addEventListener\s*\(\s*['"]message['"]/m.test(c)||/(?:window|globalThis|self)\s*\.\s*onmessage\s*=/m.test(c),y=/\bset[A-Z_$][\w$]*\s*\(/m.test(c)||/\bdispatch\s*\(/m.test(c)||/\b(?:store|siteDataStore)\s*\.\s*(?:setState|set|update)\s*\(/m.test(c);return(c.includes(ve)||c.includes(ke))&&p&&y}),d=/\bcreateContext\s*[<(]/m.test(i)&&/(?:\.Provider\b|<[A-Za-z_$][\w$]*Provider\b)/m.test(i)&&/\buseContext\s*[<(]/m.test(i)||/\buseSyncExternalStore\s*[<(]/m.test(i)||/\bcreate(?:Store|Signal)\s*[<(]/m.test(i)&&/\buse[A-Z_$][\w$]*(?:Store|Data)\s*[<(]/m.test(i),g=n.some(b=>(b.content.includes(Le)||b.content.includes(Qe))&&/\bpostMessage\s*\(/m.test(b.content));r||t.push(`Preview runtime source must implement the "${ve}" (or legacy "${ke}") protocol so editor changes replace the rendered site data instead of remaining in a static JSON import.`),o||t.push(`Preview runtime source must implement the "${Le}" (or legacy "${Qe}") protocol so the editor can wait for a live preview before sending data.`),(!m&&(!s||!l||!f))&&t.push(`Preview runtime source must handle "${ve}" (or legacy "${ke}") and apply its payload through a reactive state setter, reducer, or store update in the same live-data module.`),(m||d)||t.push("Preview runtime source must expose live site data through a recognizable reactive provider/hook (for example createContext + Provider + useContext, useSyncExternalStore, or a reactive store hook). Static site-data.json imports alone cannot be certified."),(m||g)||t.push(`Preview runtime source must call postMessage with "${cr}" after its live-data listener is ready.`)}function Tr(e,t){let n=[];for(let i of e.filter(r=>r.kind==="html"&&!br(r.filePath,t)))n.push(...Ir(i));return n}function br(e,t){let n=e.replace(/\\/g,"/").replace(/^\/+/,"");return/^(?:404|500|_error|_not-found)(?:\/index)?\.html$/i.test(n)?!t.some(r=>{let o=mt(r.route);return o?pt(n,o):!1}):!1}function Ir(e){let t=[],n=[],i=e.content.matchAll(/<!--[\s\S]*?-->|<![^>]*>|<\/?[^>]+>|[^<]+/g);for(let r of i){let o=r[0],s=r.index??0,l=n.at(-1);if(o.startsWith("<!--")||o.startsWith("<!"))continue;if(o.startsWith("</")){let u=o.slice(2,-1).trim().split(/\s+/)[0]?.toLowerCase(),d=n.map(g=>g.tag).lastIndexOf(u);d>=0&&(t.push(...Pr(e,n[d])),n.splice(d));continue}if(o.startsWith("<")){let u=o.match(/^<\s*([a-zA-Z0-9:-]+)/);if(!u)continue;let d=u[1].toLowerCase(),g=/\bdata-preview-field-path\s*=/.test(o),b=/\bdata-preview-list-path\s*=/.test(o),c=/\bdata-preview-item-path\s*=/.test(o),p=g||b||c;if(g)for(let T of n)T.ownsFieldMarker&&(T.hasNestedFieldMarker=!0);let y=o.match(/\bdata-preview-static\s*=\s*(?:"([^"]*)"|'([^']*)')/),m=!!y;m&&!(y?.[1]??y?.[2]??"").trim()&&t.push(`${e.filePath}:${V(e.content,s)} data-preview-static requires a reason.`),p&&(m||l?.staticCovered)&&t.push(`${e.filePath}:${V(e.content,s)} data-preview field/list/item markers cannot be on or inside data-preview-static. The visual editor intentionally ignores targets beneath a static ancestor.`),g&&An.has(d)&&t.push(`${e.filePath}:${V(e.content,s)} data-preview-field-path cannot be placed on broad <${d}> content containers. Put the marker on the exact visible text, media, link, or control that the field edits.`),m&&An.has(d)&&t.push(`${e.filePath}:${V(e.content,s)} data-preview-static cannot cover a broad <${d}> content container. Mark only the smallest genuinely non-editable element.`);let E=!!l?.hidden||Fr(o,d);p&&E&&t.push(`${e.filePath}:${V(e.content,s)} data-preview field/list/item marker is hidden. Strict visual-edit targets must remain visible and clickable in the exported page.`);let w=o.match(/\bdata-preview-field-path\s*=\s*(?:"([^"]*)"|'([^']*)')/)?.slice(1).find(Boolean)??null,a=o.match(/\bdata-preview-item-path\s*=\s*(?:"([^"]*)"|'([^']*)')/)?.slice(1).find(Boolean)??null;a&&l?.itemPath&&!vn(a,l.itemPath)&&t.push(`${e.filePath}:${V(e.content,s)} repeated item "${a}" is nested inside unrelated item "${l.itemPath}". One visual card must be one object-list item; do not couple parallel arrays by index.`);let h=a??l?.itemPath??null;w&&h&&/\[\d+\]/.test(w)&&!vn(w,h)&&t.push(`${e.filePath}:${V(e.content,s)} repeated field "${w}" is rendered inside item "${h}" but belongs to a different list. Model one visual card as one object-list item instead of coupling parallel arrays by index.`);let S={tag:d,ignored:!!l?.ignored||lr.has(d),hidden:E,fieldCovered:!!l?.fieldCovered||g,staticCovered:!!l?.staticCovered||m,ownsFieldMarker:g,hasNestedFieldMarker:!1,fieldPath:w,itemPath:h,shopAttributeValues:Cr(o,d),visibleTextParts:[],offset:s};if(!S.ignored&&!S.fieldCovered&&!S.staticCovered){let T=xr(e,o,d,s);t.push(...T),d==="img"&&!S.hidden&&T.length===0&&t.push(`${e.filePath}:${V(e.content,s)} rendered <img> is not covered by data-preview-field-path or data-preview-static. Bind business media to an exact image field, or mark an intentional fixed/decorative image static with a reason.`)}!ar.has(d)&&!/\/\s*>$/.test(o)&&n.push(S);continue}let f=ft(o);if(De(f))for(let u of n)u.ownsFieldMarker&&u.visibleTextParts.push(f);l?.ignored||l?.fieldCovered||l?.staticCovered||De(f)&&t.push(`${e.filePath}:${V(e.content,s)} visible text "${Oe(f,72)}" is not covered by data-preview-field-path or data-preview-static.`)}return t}function vn(e,t){let n=re(e).trim(),i=re(t).trim();return n===i||n.startsWith(`${i}.`)||n.startsWith(`${i}[`)}function Pr(e,t){if(!t.ownsFieldMarker||t.hasNestedFieldMarker||t.shopAttributeValues.length===0)return[];let n=ft(t.visibleTextParts.join(" "));return!De(n)||t.shopAttributeValues.some(i=>Ar(i,n))?[]:[`${e.filePath}:${V(e.content,t.offset)} data-preview-field-path="${t.fieldPath??""}" cannot cover both <${t.tag}> action/media attributes and different visible text "${Oe(n,72)}". Put the action/media marker on the element and the label marker on an exact nested text element.`]}function Cr(e,t){return[...e.matchAll(/\b(href|src|poster)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi)].map(n=>({name:n[1].toLowerCase(),value:re(n[2]??n[3]??"").trim()})).filter(({name:n,value:i})=>Bn(t,n,i)).map(({value:n})=>n)}function Ar(e,t){let n=i=>re(i).replace(/^(?:mailto:|tel:|sms:|https?:\/\/)/i,"").replace(/^www\./i,"").replace(/\/+$/g,"").replace(/\s+/g,"").toLowerCase();return n(e)===n(t)}function xr(e,t,n,i){let r=[],o=[...t.matchAll(/\b(href|src|poster)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi)];for(let d of o){let g=d[1].toLowerCase(),b=re(d[2]??d[3]??"").trim();Bn(n,g,b)&&r.push(`${e.filePath}:${V(e.content,i)} ${n}[${g}="${Oe(b,72)}"] is not covered by data-preview-field-path or data-preview-static.`)}let s=[...t.matchAll(/\b(placeholder|alt|title|aria-label|value)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi)],l=t.match(/\btype\s*=\s*(?:"([^"]*)"|'([^']*)')/i),f=(l?.[1]??l?.[2]??"").toLowerCase();for(let d of s){let g=d[1].toLowerCase(),b=ft(d[2]??d[3]??"");!(g==="aria-label"||g==="title"||g==="alt"&&n==="img"||g==="placeholder"&&["input","textarea"].includes(n)||g==="value"&&["input","button"].includes(n)&&!["hidden","checkbox","radio"].includes(f))||!De(b)||r.push(`${e.filePath}:${V(e.content,i)} ${n}[${g}="${Oe(b,72)}"] is not covered by data-preview-field-path or data-preview-static.`)}let u=t.match(/\bstyle\s*=\s*(?:"([^"]*)"|'([^']*)')/i);return u&&/(?:background|background-image)\s*:[^;]*url\(/i.test(u[1]??u[2]??"")&&r.push(`${e.filePath}:${V(e.content,i)} background image is not covered by data-preview-field-path or data-preview-static.`),r}function Fr(e,t){if(/\bhidden(?:\s|=|\/?>)/i.test(e)||/\baria-hidden\s*=\s*(?:"true"|'true')/i.test(e))return!0;if(t==="input"){let r=e.match(/\btype\s*=\s*(?:"([^"]*)"|'([^']*)')/i);if((r?.[1]??r?.[2]??"").trim().toLowerCase()==="hidden")return!0}let n=e.match(/\bstyle\s*=\s*(?:"([^"]*)"|'([^']*)')/i),i=n?.[1]??n?.[2]??"";return/\bdisplay\s*:\s*none\b/i.test(i)||/\bvisibility\s*:\s*hidden\b/i.test(i)}function vr(e,t){let n=new Set,i=new Set;for(let r of e?.sections??[])n.has(r.id)&&t.push(`editorSchema.sections contains duplicate id "${r.id}".`),i.has(r.path)&&t.push(`editorSchema.sections contains duplicate path "${r.path}".`),n.add(r.id),i.add(r.path)}function kr(e,t){for(let n of Ae(e)){let i=n.firstKind===n.duplicateKind?n.firstKind:"field/list";t.push(`editorSchema declares duplicate editable ${i} path "${n.path}" in sections "${n.firstSectionId}" and "${n.duplicateSectionId}". Each editable path must be owned by exactly one section.`)}}function Bn(e,t,n){return!n||n.startsWith("data:")||n.startsWith("blob:")||n.includes("/_next/")||n.includes("${")?!1:t==="href"?e==="a"&&!/^(?:javascript:|data:|blob:)/i.test(n):t==="src"&&["img","video","source"].includes(e)||t==="poster"&&e==="video"}function ft(e){return re(e).replace(/\s+/g," ").trim()}function De(e){return e.length<=2||!new RegExp("\\p{L}","u").test(e)?!1:!/^(?:true|false|null|undefined)$/i.test(e)}function it(e){return e==="editable field"?"field-path":e==="editable list"?"list-path":"item-path"}function Lr(e,t){return t.includes("[*]")?e.includes("[*]")&&e===t:e===t}function ct(e,t){return j(e)===j(t)}function Ne(e,t){return t.some(n=>n.includes("[*]")?j(e)===n:e===n)}function fe(e){let t=e.trim().replace(/\[\s*\$\{[^}]+\}\s*\]/g,"[*]").replace(/\[\s+/g,"[").replace(/\s+\]/g,"]");return sr.test(t)?t:null}function j(e){return e.replace(/\[\d+\]/g,"[*]")}function W(e,t){return e?`${e}.${t}`:t}function mt(e){if(!e)return null;let t=e.trim();return!t.startsWith("/")||t.includes("?")||t.includes("#")||t.includes("\\")||t.includes("..")?null:t==="/"?t:t.replace(/\/+$/,"")}function Vn(e){return e==="home"?"/":`/${e}`}function pt(e,t){let n=e.replace(/\\/g,"/").replace(/^\/+/,"");if(t==="/")return n==="index.html";let i=t.replace(/^\/+/,"");return n===`${i}.html`||n===`${i}/index.html`}function G(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function re(e){return e.replace(/&quot;/gi,'"').replace(/&#39;|&#x27;/gi,"'").replace(/&lt;/gi,"<").replace(/&gt;/gi,">").replace(/&amp;/gi,"&").replace(/&nbsp;/gi," ")}function Un(e){return e.line}function V(e,t){let n=1;for(let i=0;i<t;i+=1)e.charCodeAt(i)===10&&(n+=1);return n}function z(e){return[...new Set(e)].sort()}function Oe(e,t){return e.length<=t?e:`${e.slice(0,Math.max(0,t-1))}\u2026`}function jn(e){let t=e.filter((n,i)=>n.required===!0||i===0).map(n=>n.id);return t.length>0?t:e.slice(0,1).map(n=>n.id)}function zn(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Rr(e,t,n){let i=e.trim().split(/[?#]/,1)[0];return i==="/"||i===""?n?"/":`/${t}`:/^[a-z][a-z0-9+.-]*:/i.test(i)||i.startsWith("//")?n?"/":`/${t}`:`/${i.replace(/^\/+|\/+$/g,"")}`}function Hn(e,t=[]){let i=(zn(e)&&Array.isArray(e.pages)?e.pages:[]).flatMap((o,s)=>{if(!zn(o)||typeof o.id!="string"||!o.id.trim())return[];let l=o.id.trim(),f=typeof o.label=="string"&&o.label.trim()?o.label.trim():l.replace(/_/g," ");return[{id:l,label:f,route:Rr(typeof o.route=="string"?o.route:"",l,s===0)}]});return i.length>0?i:t.map(o=>o.trim()).filter(Boolean).map((o,s)=>({id:o,label:o.replace(/_/g," "),route:s===0?"/":`/${o}`}))}function Kn(e){let t=new Set(e.selectedPages),n=e.pageDefinitions.filter(r=>!t.has(r.id)),i=[];for(let r of e.html.matchAll(/<[a-z][^>]*\b(?:href|formaction|data-href|data-route|data-url)\s*=\s*(?:"([^"]*)"|'([^']*)')[^>]*>/gi)){let o=r[1]??r[2]??"";if(!o.trim()||o.trim().startsWith("#")||/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(o.trim()))continue;let s=o.split(/[?#]/,1)[0],l=e.basePath?.replace(/\/+$/g,"")||"",u=`/${(l&&(s===l||s.startsWith(`${l}/`))?s.slice(l.length)||"/":s).replace(/\/index\.html$/i,"/").replace(/\.html$/i,"").replace(/^\.\//,"").replace(/^\/+|\/+$/g,"")}`,d=u==="/"?"/":u,g=n.find(b=>{let c=b.route==="/"?"/":`/${b.route.replace(/^\/+|\/+$/g,"")}`;return c==="/"?d==="/":d===c||d.startsWith(`${c}/`)});g&&i.push({pageId:g.id,route:g.route,href:s})}return i}var le="deneb-template-validator",Be="1.0.0",Me="fivora-template.json",_r=2500,Dr=12*1024*1024,ei="/template-validation",gt=class{constructor(t,n){this.options=t;this.report={validator:le,version:Be,command:t.command,input:(0,A.resolve)(t.inputPath),status:"passed",startedAt:n.toISOString(),durationMs:0,steps:[],warnings:[]}}options;report;async step(t,n,i){let r=Date.now();this.options.json||process.stdout.write(`\u2192 ${t}
4
4
  `);try{let o=await n();return this.report.steps.push({name:t,status:"passed",durationMs:Date.now()-r,...i?{detail:i}:{}}),this.options.json||process.stdout.write(` \u2713 ${t}
5
5
  `),o}catch(o){throw this.report.steps.push({name:t,status:"failed",durationMs:Date.now()-r,detail:me(o)}),o}}skip(t,n){this.report.steps.push({name:t,status:"skipped",durationMs:0,detail:n}),this.warn(n)}warn(t){this.report.warnings.includes(t)||this.report.warnings.push(t),this.options.json||process.stdout.write(` ! ${t}
6
6
  `)}finish(t,n){this.report.durationMs=Date.now()-t.getTime(),n&&(this.report.status="failed",this.report.error=me(n))}print(){if(this.options.json){process.stdout.write(`${JSON.stringify(this.report,null,2)}
@@ -1,16 +1,687 @@
1
1
  #!/usr/bin/env node
2
- const Q=require("node:crypto"),E=require("node:fs"),A=require("node:http"),f=require("node:path"),{spawn:O}=require("node:child_process"),Z=4174,q=4173,M=96*1024,v="127.0.0.1",U="/__fivora_local_preview",ee=`(()=>{const p=["market","place"].join(""),R="__"+p.toUpperCase()+"_LOCAL_VISUAL_BRIDGE__",y=p.toUpperCase()+"_PREVIEW_",h=t=>y+t;if(window.__FIVORA_LOCAL_VISUAL_BRIDGE__||window[R])return;window.__FIVORA_LOCAL_VISUAL_BRIDGE__=!0,window[R]=!0;const O="FIVORA_PREVIEW_EDIT_MODE",V=h("EDIT_MODE"),x="FIVORA_PREVIEW_ELEMENT_CLICKED",P=h("ELEMENT_CLICKED"),G="FIVORA_PREVIEW_READY",U=h("READY"),T="data-preview-field-path",L="data-preview-list-path",v="data-preview-item-path",w="data-fivora-local-edit-target",A="data-fivora-local-selected-target",C="data-"+p+"-local-edit-target",_="data-"+p+"-local-selected-target",B="[data-preview-field-path], [data-preview-list-path], [data-preview-item-path]";let r=window.parent!==window,E=new Map,l=null,i=null,m="*";const g=document.createElement("style");g.setAttribute("data-fivora-local-visual-bridge",""),g.setAttribute("data-"+p+"-local-visual-bridge",""),g.textContent=["["+w+"], ["+C+"] {"," outline: 2px solid #06b6d4 !important;"," outline-offset: 3px !important;"," cursor: pointer !important;"," box-shadow: 0 0 0 5px rgba(6, 182, 212, 0.16) !important;","}","["+A+"], ["+_+"] {"," outline: 2px dashed #06b6d4 !important;"," outline-offset: 3px !important;"," box-shadow: 0 0 0 5px rgba(6, 182, 212, 0.18) !important;","}",'html[data-fivora-local-edit-mode="true"] [data-preview-field-path],','html[data-fivora-local-edit-mode="true"] [data-preview-list-path],','html[data-fivora-local-edit-mode="true"] [data-preview-item-path],','html[data-fivora-local-edit-mode="true"] [data-preview-field-path],','html[data-fivora-local-edit-mode="true"] [data-preview-list-path],','html[data-fivora-local-edit-mode="true"] [data-preview-item-path] {'," cursor: pointer !important;","}"].join(\`
3
- \`),document.head.appendChild(g),document.documentElement.setAttribute("data-fivora-local-edit-mode",String(r)),document.documentElement.setAttribute("data-fivora-local-edit-mode",String(r));function Y(t){return t.source!==window.parent?!1:(m==="*"&&t.origin&&t.origin!=="null"&&(m=t.origin),m==="*"||t.origin===m)}function I(t){window.parent.postMessage(t,m)}function b(){l&&(l.removeAttribute(w),l.removeAttribute(C)),l=null}function F(t){i&&i!==t&&(i.removeAttribute(A),i.removeAttribute(_)),i=t,i.setAttribute(A,"true"),i.setAttribute(_,"true")}function W(){i&&(i.removeAttribute(A),i.removeAttribute(_)),i=null}function S(t){return t instanceof Element?t.closest(B):null}function k(t,e){const c=E.get(e);return c&&["string","number","boolean"].includes(typeof c.value)?c.value:t instanceof HTMLImageElement?t.currentSrc||t.src||"":(t.textContent||"").trim()}function K(t){if(!r)return;const e=S(t.target);!e||e===l||(b(),l=e,l.setAttribute(w,"true"))}function N(t){if(!r||!l)return;const e=t.relatedTarget;e instanceof Node&&l.contains(e)||b()}function j(t,e,c){const f=[],s=new Set(e?[e]:[]),n=c||e&&e.replace(/(\\[\\d+\\])?\\.\\w+$/,"").replace(/\\[\\d+\\]$/,"");if(n)for(const[a,o]of E)a!==e&&!s.has(a)&&(a.startsWith(n+".")||a.startsWith(n+"["))&&o?.kind!=="collection"&&(s.add(a),f.push({path:a,label:o.label||a.split(".").pop()||"Content",type:o.type||"text"}));let d=t instanceof Element?t:null,u=0;for(;d&&d!==document.body&&u<3;){const a=d.getAttribute(T);if(a&&a!==e&&!s.has(a)){const o=E.get(a);o?.kind!=="collection"&&(s.add(a),f.push({path:a,label:o?.label||a.split(".").pop()||"Content",type:o?.type||"text"}))}d=d.parentElement,u+=1}return f}function H(t){if(!r)return;const e=S(t.target);if(!e)return;t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),F(e);const c=e.closest("["+T+"]"),f=e.closest("["+L+"]"),s=e.closest("["+v+"]"),n=c?.getAttribute(T)||null,d=f?.getAttribute(L)||null,u=s?.getAttribute(v)||null,a=n?E.get(n):null,o=e.getBoundingClientRect(),D=u?.match(/\\[(\\d+)\\](?!.*\\[\\d+\\])/),M={type:x,fieldPath:n,fieldValue:n?k(c||e,n):"",elementTag:e.tagName.toLowerCase(),isImage:e instanceof HTMLImageElement||a?.type==="image",boundingRect:{top:o.top,left:o.left,width:o.width,height:o.height},collectionPath:d,listPath:d,itemPath:u,itemIndex:D?Number(D[1]):null,descriptorKind:n?"field":d?"collection":null,relatedFields:j(e,n,u)};I(M),I({...M,type:P})}window.addEventListener("message",t=>{!Y(t)||!t.data||typeof t.data!="object"||t.data.type!==O&&t.data.type!==V||(r=t.data.editMode===!0,E=new Map(Array.isArray(t.data.fields)?t.data.fields.filter(e=>e&&typeof e.path=="string").map(e=>[e.path,e]):[]),document.documentElement.setAttribute("data-fivora-local-edit-mode",String(r)),document.documentElement.setAttribute("data-fivora-local-edit-mode",String(r)),r||(b(),W()))}),document.addEventListener("mouseover",K,!0),document.addEventListener("mouseout",N,!0),document.addEventListener("click",H,!0),I({type:G,pathname:window.location.pathname}),I({type:U,pathname:window.location.pathname})})();`;let D=ee;try{const e=require("./template-preview-focus-bridge.cjs");typeof e=="string"&&e.trim()&&(D=e)}catch{}function p(e){process.stderr.write(`Local Template Lab: ${e}
4
- `),process.exit(1)}try{new Function(D)}catch(e){p(`Visual editor bridge is invalid: ${e.message}`)}function W(e,t,a){if(e===void 0)return a;const r=Number(e);return(!Number.isInteger(r)||r<1024||r>65535)&&p(`${t} must be a port between 1024 and 65535.`),r}function te(e){const t=[...e];let a="",r,n,s=!1;for(let m=0;m<t.length;m+=1){const d=t[m];d==="--api-port"?(r=t[m+1],m+=1):d.startsWith("--api-port=")?r=d.slice(11):d==="--preview-port"?(n=t[m+1],m+=1):d.startsWith("--preview-port=")?n=d.slice(15):d==="--skip-install"?s=!0:d==="--help"||d==="-h"?(process.stdout.write(["Fivora Local Template Lab","","Usage:"," npm run lab -- <template-directory> [options]","","Options:"," --api-port <port> Loopback controller port (default: 4174)"," --preview-port <port> Template dev-server port (default: 4173)"," --skip-install Do not install missing local dependencies",""].join(`
5
- `)),process.exit(0)):d.startsWith("-")?p(`Unknown option: ${d}`):a?p(`Unexpected argument: ${d}`):a=d}return a||p("A template directory is required. Run with --help for usage."),{templatePath:f.resolve(a),apiPort:W(r,"--api-port",Z),previewPort:W(n,"--preview-port",q),skipInstall:s}}function B(e,t){try{return JSON.parse(E.readFileSync(e,"utf8"))}catch(a){p(`${t} is missing or invalid at ${e}: ${a instanceof Error?a.message:"unknown error"}`)}}const i=te(process.argv.slice(2));E.existsSync(i.templatePath)||p(`Template directory does not exist: ${i.templatePath}`),E.statSync(i.templatePath).isDirectory()||p(`Template path must be a directory: ${i.templatePath}`);const ae=["fivora-template.json","fivora-template.json"].find(e=>E.existsSync(f.join(i.templatePath,e)))||"fivora-template.json",re=f.join(i.templatePath,ae),ne=f.join(i.templatePath,"package.json"),c=B(re,"Template manifest"),T=B(ne,"package.json");c.framework!=="nextjs-static-export"&&p('Template manifest framework must be "nextjs-static-export".'),(!T.scripts||typeof T.scripts.dev!="string")&&p("Template package.json must define a dev script for live preview."),(typeof c.siteDataFile!="string"||!c.siteDataFile.trim())&&p("Template manifest siteDataFile is required.");const j=f.resolve(i.templatePath,c.siteDataFile.trim()),N=f.relative(i.templatePath,j);(N.startsWith("..")||f.isAbsolute(N))&&p("Template manifest siteDataFile must stay inside the template directory.");const H=Q.randomBytes(24).toString("base64url"),y=`http://${v}:${i.apiPort}`,G=`http://${v}:${i.previewPort}`,$=`${y}${U}`,ie=f.join(__dirname,"fivora-template-validator.cjs");let P=!1,u=null,h=null,I=null,_=null,b=0;const k=5;let x="",R="";const o={protocolVersion:2,connected:!0,templateName:typeof c.name=="string"&&c.name.trim()?c.name.trim():typeof T.name=="string"?T.name:f.basename(i.templatePath),templatePath:i.templatePath,previewUrl:$,apiUrl:y,devStatus:"starting",devError:null,startedAt:new Date().toISOString(),validation:{status:"idle",startedAt:null,completedAt:null,exitCode:null}};function l(e,t){const a=t.toString();e==="dev"?x=`${x}${a}`.slice(-M):R=`${R}${a}`.slice(-M),process.stdout.write(a)}function K(){return{...o,devLog:x,validationLog:R}}function oe(e,t){const a=e.headers.origin;a&&/^(https?:\/\/|null$)/.test(a)&&(t.setHeader("Access-Control-Allow-Origin",a),t.setHeader("Vary","Origin")),t.setHeader("Access-Control-Allow-Headers","Authorization, Content-Type"),t.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.setHeader("Access-Control-Allow-Private-Network","true"),t.setHeader("Cache-Control","no-store"),t.setHeader("X-Content-Type-Options","nosniff")}function g(e,t,a){const r=JSON.stringify(a);e.statusCode=t,e.setHeader("Content-Type","application/json; charset=utf-8"),e.setHeader("Content-Length",Buffer.byteLength(r)),e.end(r)}function se(e){return e.headers.authorization===`Bearer ${H}`}function le(){try{return JSON.parse(E.readFileSync(j,"utf8"))}catch(e){throw new Error(`Unable to read ${c.siteDataFile}: ${e instanceof Error?e.message:"unknown error"}`)}}function de(){return h?!1:(R="",o.validation={status:"running",startedAt:new Date().toISOString(),completedAt:null,exitCode:null},h=O(process.execPath,[ie,"validate",i.templatePath],{cwd:__dirname,env:process.env,stdio:["ignore","pipe","pipe"]}),h.stdout.on("data",e=>l("validation",e)),h.stderr.on("data",e=>l("validation",e)),h.on("error",e=>{l("validation",`
6
- Unable to start validation: ${e.message}
7
- `)}),h.on("close",e=>{o.validation={...o.validation,status:e===0?"passed":"failed",completedAt:new Date().toISOString(),exitCode:e},h=null}),!0)}function V(){if(P||o.devStatus==="ready")return;const e=A.get(G,t=>{if(t.resume(),t.statusCode&&t.statusCode<500){o.devStatus="ready",o.devError=null,b=0,process.stdout.write(`
8
- Live preview ready: ${$}
9
- `);return}I=setTimeout(V,600)});e.setTimeout(900,()=>e.destroy()),e.on("error",()=>{I=setTimeout(V,600)})}function pe(e){if(!(P||_)){if(b>=k){o.devStatus="failed",o.devError=e;return}b+=1,o.devStatus="starting",o.devError=null,l("dev",`
10
- Preview server stopped during navigation (${e}). Restarting (${b}/${k})...
11
- `),_=setTimeout(()=>{_=null,F()},900)}}function ce(){const e=f.join(i.templatePath,"node_modules");if(!i.skipInstall&&!E.existsSync(e)){o.devStatus="installing";const t=typeof c.installCommand=="string"&&c.installCommand.trim()?c.installCommand.trim():"npm install";l("dev",`Installing local dependencies with: ${t}
12
- `);const a=O(t,{cwd:i.templatePath,env:process.env,shell:!0,stdio:["ignore","pipe","pipe"]});u=a,a.stdout.on("data",r=>l("dev",r)),a.stderr.on("data",r=>l("dev",r)),a.on("error",r=>{o.devStatus="failed",o.devError=r.message,u=null}),a.on("close",r=>{if(u=null,r!==0){o.devStatus="failed",o.devError=`Dependency installation exited with code ${r}.`;return}F()});return}F()}function F(){o.devStatus="starting",o.devError=null,l("dev",`Starting template source server on ${G}. Source edits will hot reload.
13
- `),u=O(process.platform==="win32"?"npm.cmd":"npm",["run","dev","--","--hostname",v,"--port",String(i.previewPort)],{cwd:i.templatePath,env:{...process.env,NEXT_PUBLIC_SITE_BASE_PATH:""},shell:process.platform==="win32",stdio:["ignore","pipe","pipe"]}),u.stdout.on("data",e=>l("dev",e)),u.stderr.on("data",e=>l("dev",e)),u.on("error",e=>{o.devStatus="failed",o.devError=e.message,u=null}),u.on("close",(e,t)=>{if(u=null,!P){const a=t?`signal ${t}`:`exit code ${e}`;pe(a)}}),V()}function ue(){return`<!doctype html>
2
+
3
+ const crypto = require('node:crypto');
4
+ const fs = require('node:fs');
5
+ const http = require('node:http');
6
+ const path = require('node:path');
7
+ const { spawn } = require('node:child_process');
8
+
9
+ const DEFAULT_API_PORT = 4174;
10
+ const DEFAULT_PREVIEW_PORT = 4173;
11
+ const MAX_LOG_LENGTH = 96 * 1024;
12
+ const LOOPBACK_HOST = '127.0.0.1';
13
+ const LOCAL_PREVIEW_ROUTE = '/__fivora_local_preview';
14
+ const FALLBACK_LOCAL_VISUAL_BRIDGE_SCRIPT = String.raw`
15
+ (() => {
16
+ const PREVIOUS_BRAND = ['market', 'place'].join('');
17
+ const PREVIOUS_BRIDGE_KEY = '__' + PREVIOUS_BRAND.toUpperCase() + '_LOCAL_VISUAL_BRIDGE__';
18
+ const PREVIOUS_PREVIEW_PREFIX = PREVIOUS_BRAND.toUpperCase() + '_PREVIEW_';
19
+ const previousPreviewMessage = (suffix) => PREVIOUS_PREVIEW_PREFIX + suffix;
20
+ if (window.__FIVORA_LOCAL_VISUAL_BRIDGE__ || window[PREVIOUS_BRIDGE_KEY]) return;
21
+ window.__FIVORA_LOCAL_VISUAL_BRIDGE__ = true;
22
+ window[PREVIOUS_BRIDGE_KEY] = true;
23
+
24
+ const EDIT_MODE_MESSAGE = 'FIVORA_PREVIEW_EDIT_MODE';
25
+ const LEGACY_EDIT_MODE_MESSAGE = previousPreviewMessage('EDIT_MODE');
26
+ const CLICK_MESSAGE = 'FIVORA_PREVIEW_ELEMENT_CLICKED';
27
+ const LEGACY_CLICK_MESSAGE = previousPreviewMessage('ELEMENT_CLICKED');
28
+ const READY_MESSAGE = 'FIVORA_PREVIEW_READY';
29
+ const LEGACY_READY_MESSAGE = previousPreviewMessage('READY');
30
+ const FIELD_ATTRIBUTE = 'data-preview-field-path';
31
+ const LIST_ATTRIBUTE = 'data-preview-list-path';
32
+ const ITEM_ATTRIBUTE = 'data-preview-item-path';
33
+ const ACTIVE_ATTRIBUTE = 'data-fivora-local-edit-target';
34
+ const SELECTED_ATTRIBUTE = 'data-fivora-local-selected-target';
35
+ const LEGACY_ACTIVE_ATTRIBUTE = 'data-' + PREVIOUS_BRAND + '-local-edit-target';
36
+ const LEGACY_SELECTED_ATTRIBUTE = 'data-' + PREVIOUS_BRAND + '-local-selected-target';
37
+ const EDITABLE_SELECTOR =
38
+ '[data-preview-field-path], [data-preview-list-path], [data-preview-item-path]';
39
+ // The local lab is edit-first when embedded. The portal can still switch the
40
+ // preview back to normal navigation mode with EDIT_MODE_MESSAGE.
41
+ let editMode = window.parent !== window;
42
+ let descriptors = new Map();
43
+ let activeTarget = null;
44
+ let selectedTarget = null;
45
+ let parentOrigin = '*';
46
+
47
+ const style = document.createElement('style');
48
+ style.setAttribute('data-fivora-local-visual-bridge', '');
49
+ style.setAttribute('data-' + PREVIOUS_BRAND + '-local-visual-bridge', '');
50
+ style.textContent = [
51
+ '[' + ACTIVE_ATTRIBUTE + '], [' + LEGACY_ACTIVE_ATTRIBUTE + '] {',
52
+ ' outline: 2px solid #06b6d4 !important;',
53
+ ' outline-offset: 3px !important;',
54
+ ' cursor: pointer !important;',
55
+ ' box-shadow: 0 0 0 5px rgba(6, 182, 212, 0.16) !important;',
56
+ '}',
57
+ '[' + SELECTED_ATTRIBUTE + '], [' + LEGACY_SELECTED_ATTRIBUTE + '] {',
58
+ ' outline: 2px dashed #06b6d4 !important;',
59
+ ' outline-offset: 3px !important;',
60
+ ' box-shadow: 0 0 0 5px rgba(6, 182, 212, 0.18) !important;',
61
+ '}',
62
+ 'html[data-fivora-local-edit-mode="true"] [data-preview-field-path],',
63
+ 'html[data-fivora-local-edit-mode="true"] [data-preview-list-path],',
64
+ 'html[data-fivora-local-edit-mode="true"] [data-preview-item-path],',
65
+ 'html[data-fivora-local-edit-mode="true"] [data-preview-field-path],',
66
+ 'html[data-fivora-local-edit-mode="true"] [data-preview-list-path],',
67
+ 'html[data-fivora-local-edit-mode="true"] [data-preview-item-path] {',
68
+ ' cursor: pointer !important;',
69
+ '}',
70
+ ].join('\n');
71
+ document.head.appendChild(style);
72
+ document.documentElement.setAttribute(
73
+ 'data-fivora-local-edit-mode',
74
+ String(editMode),
75
+ );
76
+ document.documentElement.setAttribute(
77
+ 'data-fivora-local-edit-mode',
78
+ String(editMode),
79
+ );
80
+
81
+ function rememberParentOrigin(event) {
82
+ if (event.source !== window.parent) return false;
83
+ if (parentOrigin === '*' && event.origin && event.origin !== 'null') {
84
+ parentOrigin = event.origin;
85
+ }
86
+ return parentOrigin === '*' || event.origin === parentOrigin;
87
+ }
88
+
89
+ function post(payload) {
90
+ window.parent.postMessage(payload, parentOrigin);
91
+ }
92
+
93
+ function clearActiveTarget() {
94
+ if (activeTarget) {
95
+ activeTarget.removeAttribute(ACTIVE_ATTRIBUTE);
96
+ activeTarget.removeAttribute(LEGACY_ACTIVE_ATTRIBUTE);
97
+ }
98
+ activeTarget = null;
99
+ }
100
+
101
+ function selectTarget(target) {
102
+ if (selectedTarget && selectedTarget !== target) {
103
+ selectedTarget.removeAttribute(SELECTED_ATTRIBUTE);
104
+ selectedTarget.removeAttribute(LEGACY_SELECTED_ATTRIBUTE);
105
+ }
106
+ selectedTarget = target;
107
+ selectedTarget.setAttribute(SELECTED_ATTRIBUTE, 'true');
108
+ selectedTarget.setAttribute(LEGACY_SELECTED_ATTRIBUTE, 'true');
109
+ }
110
+
111
+ function clearSelectedTarget() {
112
+ if (selectedTarget) {
113
+ selectedTarget.removeAttribute(SELECTED_ATTRIBUTE);
114
+ selectedTarget.removeAttribute(LEGACY_SELECTED_ATTRIBUTE);
115
+ }
116
+ selectedTarget = null;
117
+ }
118
+
119
+ function findEditableTarget(rawTarget) {
120
+ if (!(rawTarget instanceof Element)) return null;
121
+ return rawTarget.closest(EDITABLE_SELECTOR);
122
+ }
123
+
124
+ function fieldValue(target, fieldPath) {
125
+ const descriptor = descriptors.get(fieldPath);
126
+ if (descriptor && ['string', 'number', 'boolean'].includes(typeof descriptor.value)) {
127
+ return descriptor.value;
128
+ }
129
+ if (target instanceof HTMLImageElement) return target.currentSrc || target.src || '';
130
+ return (target.textContent || '').trim();
131
+ }
132
+
133
+ function onPointerOver(event) {
134
+ if (!editMode) return;
135
+ const target = findEditableTarget(event.target);
136
+ if (!target || target === activeTarget) return;
137
+ clearActiveTarget();
138
+ activeTarget = target;
139
+ activeTarget.setAttribute(ACTIVE_ATTRIBUTE, 'true');
140
+ }
141
+
142
+ function onPointerOut(event) {
143
+ if (!editMode || !activeTarget) return;
144
+ const next = event.relatedTarget;
145
+ if (next instanceof Node && activeTarget.contains(next)) return;
146
+ clearActiveTarget();
147
+ }
148
+
149
+ function findRelatedFields(target, fieldPath, itemPath) {
150
+ const related = [];
151
+ const seen = new Set(fieldPath ? [fieldPath] : []);
152
+ const prefix =
153
+ itemPath ||
154
+ (fieldPath && fieldPath.replace(/(\[\d+\])?\.\w+$/, '').replace(/\[\d+\]$/, ''));
155
+ if (prefix) {
156
+ for (const [path, descriptor] of descriptors) {
157
+ if (
158
+ path !== fieldPath &&
159
+ !seen.has(path) &&
160
+ (path.startsWith(prefix + '.') || path.startsWith(prefix + '[')) &&
161
+ descriptor?.kind !== 'collection'
162
+ ) {
163
+ seen.add(path);
164
+ related.push({
165
+ path,
166
+ label: descriptor.label || path.split('.').pop() || 'Content',
167
+ type: descriptor.type || 'text',
168
+ });
169
+ }
170
+ }
171
+ }
172
+ let current = target instanceof Element ? target : null;
173
+ let depth = 0;
174
+ while (current && current !== document.body && depth < 3) {
175
+ const candidatePath = current.getAttribute(FIELD_ATTRIBUTE);
176
+ if (
177
+ candidatePath &&
178
+ candidatePath !== fieldPath &&
179
+ !seen.has(candidatePath)
180
+ ) {
181
+ const descriptor = descriptors.get(candidatePath);
182
+ if (descriptor?.kind !== 'collection') {
183
+ seen.add(candidatePath);
184
+ related.push({
185
+ path: candidatePath,
186
+ label: descriptor?.label || candidatePath.split('.').pop() || 'Content',
187
+ type: descriptor?.type || 'text',
188
+ });
189
+ }
190
+ }
191
+ current = current.parentElement;
192
+ depth += 1;
193
+ }
194
+ return related;
195
+ }
196
+
197
+ function onClick(event) {
198
+ if (!editMode) return;
199
+ const target = findEditableTarget(event.target);
200
+ if (!target) return;
201
+ event.preventDefault();
202
+ event.stopPropagation();
203
+ event.stopImmediatePropagation();
204
+ selectTarget(target);
205
+
206
+ const fieldTarget = target.closest('[' + FIELD_ATTRIBUTE + ']');
207
+ const listTarget = target.closest('[' + LIST_ATTRIBUTE + ']');
208
+ const itemTarget = target.closest('[' + ITEM_ATTRIBUTE + ']');
209
+ const fieldPath = fieldTarget?.getAttribute(FIELD_ATTRIBUTE) || null;
210
+ const listPath = listTarget?.getAttribute(LIST_ATTRIBUTE) || null;
211
+ const itemPath = itemTarget?.getAttribute(ITEM_ATTRIBUTE) || null;
212
+ const descriptor = fieldPath ? descriptors.get(fieldPath) : null;
213
+ const rect = target.getBoundingClientRect();
214
+ const itemIndexMatch = itemPath?.match(/\[(\d+)\](?!.*\[\d+\])/);
215
+
216
+ const clickPayload = {
217
+ type: CLICK_MESSAGE,
218
+ fieldPath,
219
+ fieldValue: fieldPath ? fieldValue(fieldTarget || target, fieldPath) : '',
220
+ elementTag: target.tagName.toLowerCase(),
221
+ isImage:
222
+ target instanceof HTMLImageElement || descriptor?.type === 'image',
223
+ boundingRect: {
224
+ top: rect.top,
225
+ left: rect.left,
226
+ width: rect.width,
227
+ height: rect.height,
228
+ },
229
+ collectionPath: listPath,
230
+ listPath,
231
+ itemPath,
232
+ itemIndex: itemIndexMatch ? Number(itemIndexMatch[1]) : null,
233
+ descriptorKind: fieldPath ? 'field' : listPath ? 'collection' : null,
234
+ relatedFields: findRelatedFields(target, fieldPath, itemPath),
235
+ };
236
+ post(clickPayload);
237
+ post({ ...clickPayload, type: LEGACY_CLICK_MESSAGE });
238
+ }
239
+
240
+ window.addEventListener('message', (event) => {
241
+ if (!rememberParentOrigin(event) || !event.data || typeof event.data !== 'object') {
242
+ return;
243
+ }
244
+ if (event.data.type !== EDIT_MODE_MESSAGE && event.data.type !== LEGACY_EDIT_MODE_MESSAGE) return;
245
+ editMode = event.data.editMode === true;
246
+ descriptors = new Map(
247
+ Array.isArray(event.data.fields)
248
+ ? event.data.fields
249
+ .filter((field) => field && typeof field.path === 'string')
250
+ .map((field) => [field.path, field])
251
+ : [],
252
+ );
253
+ document.documentElement.setAttribute(
254
+ 'data-fivora-local-edit-mode',
255
+ String(editMode),
256
+ );
257
+ document.documentElement.setAttribute(
258
+ 'data-fivora-local-edit-mode',
259
+ String(editMode),
260
+ );
261
+ if (!editMode) {
262
+ clearActiveTarget();
263
+ clearSelectedTarget();
264
+ }
265
+ });
266
+
267
+ document.addEventListener('mouseover', onPointerOver, true);
268
+ document.addEventListener('mouseout', onPointerOut, true);
269
+ document.addEventListener('click', onClick, true);
270
+ post({ type: READY_MESSAGE, pathname: window.location.pathname });
271
+ post({ type: LEGACY_READY_MESSAGE, pathname: window.location.pathname });
272
+ })();
273
+ `;
274
+
275
+ let LOCAL_VISUAL_BRIDGE_SCRIPT = FALLBACK_LOCAL_VISUAL_BRIDGE_SCRIPT;
276
+ try {
277
+ const productionBridge = require('./template-preview-focus-bridge.cjs');
278
+ if (typeof productionBridge === 'string' && productionBridge.trim()) {
279
+ LOCAL_VISUAL_BRIDGE_SCRIPT = productionBridge;
280
+ }
281
+ } catch {
282
+ // Source checkouts can run before the generated production bridge exists.
283
+ // The package build always creates it; retain a compact fallback for safety.
284
+ }
285
+
286
+ function fail(message) {
287
+ process.stderr.write(`Local Template Lab: ${message}\n`);
288
+ process.exit(1);
289
+ }
290
+
291
+ try {
292
+ // Validate the generated iframe program as well as this outer runner file.
293
+ new Function(LOCAL_VISUAL_BRIDGE_SCRIPT);
294
+ } catch (error) {
295
+ fail(`Visual editor bridge is invalid: ${error.message}`);
296
+ }
297
+
298
+ function parsePort(value, flag, fallback) {
299
+ if (value === undefined) return fallback;
300
+ const port = Number(value);
301
+ if (!Number.isInteger(port) || port < 1024 || port > 65535) {
302
+ fail(`${flag} must be a port between 1024 and 65535.`);
303
+ }
304
+ return port;
305
+ }
306
+
307
+ function parseArguments(argv) {
308
+ const args = [...argv];
309
+ let templatePath = '';
310
+ let apiPort;
311
+ let previewPort;
312
+ let skipInstall = false;
313
+
314
+ for (let index = 0; index < args.length; index += 1) {
315
+ const arg = args[index];
316
+ if (arg === '--api-port') {
317
+ apiPort = args[index + 1];
318
+ index += 1;
319
+ } else if (arg.startsWith('--api-port=')) {
320
+ apiPort = arg.slice('--api-port='.length);
321
+ } else if (arg === '--preview-port') {
322
+ previewPort = args[index + 1];
323
+ index += 1;
324
+ } else if (arg.startsWith('--preview-port=')) {
325
+ previewPort = arg.slice('--preview-port='.length);
326
+ } else if (arg === '--skip-install') {
327
+ skipInstall = true;
328
+ } else if (arg === '--help' || arg === '-h') {
329
+ process.stdout.write(
330
+ [
331
+ 'Fivora Local Template Lab',
332
+ '',
333
+ 'Usage:',
334
+ ' npm run lab -- <template-directory> [options]',
335
+ '',
336
+ 'Options:',
337
+ ' --api-port <port> Loopback controller port (default: 4174)',
338
+ ' --preview-port <port> Template dev-server port (default: 4173)',
339
+ ' --skip-install Do not install missing local dependencies',
340
+ '',
341
+ ].join('\n'),
342
+ );
343
+ process.exit(0);
344
+ } else if (arg.startsWith('-')) {
345
+ fail(`Unknown option: ${arg}`);
346
+ } else if (!templatePath) {
347
+ templatePath = arg;
348
+ } else {
349
+ fail(`Unexpected argument: ${arg}`);
350
+ }
351
+ }
352
+
353
+ if (!templatePath) {
354
+ fail('A template directory is required. Run with --help for usage.');
355
+ }
356
+
357
+ return {
358
+ templatePath: path.resolve(templatePath),
359
+ apiPort: parsePort(apiPort, '--api-port', DEFAULT_API_PORT),
360
+ previewPort: parsePort(
361
+ previewPort,
362
+ '--preview-port',
363
+ DEFAULT_PREVIEW_PORT,
364
+ ),
365
+ skipInstall,
366
+ };
367
+ }
368
+
369
+ function readJson(filePath, label) {
370
+ try {
371
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
372
+ } catch (error) {
373
+ fail(
374
+ `${label} is missing or invalid at ${filePath}: ${
375
+ error instanceof Error ? error.message : 'unknown error'
376
+ }`,
377
+ );
378
+ }
379
+ }
380
+
381
+ const options = parseArguments(process.argv.slice(2));
382
+ if (!fs.existsSync(options.templatePath)) {
383
+ fail(`Template directory does not exist: ${options.templatePath}`);
384
+ }
385
+ if (!fs.statSync(options.templatePath).isDirectory()) {
386
+ fail(`Template path must be a directory: ${options.templatePath}`);
387
+ }
388
+
389
+ const manifestFile = [
390
+ 'fivora-template.json',
391
+ 'fivora-template.json',
392
+ ].find((name) => fs.existsSync(path.join(options.templatePath, name))) || 'fivora-template.json';
393
+
394
+ const manifestPath = path.join(options.templatePath, manifestFile);
395
+ const packagePath = path.join(options.templatePath, 'package.json');
396
+ const manifest = readJson(manifestPath, 'Template manifest');
397
+ const packageJson = readJson(packagePath, 'package.json');
398
+
399
+ if (manifest.framework !== 'nextjs-static-export') {
400
+ fail('Template manifest framework must be "nextjs-static-export".');
401
+ }
402
+ if (!packageJson.scripts || typeof packageJson.scripts.dev !== 'string') {
403
+ fail('Template package.json must define a dev script for live preview.');
404
+ }
405
+ if (typeof manifest.siteDataFile !== 'string' || !manifest.siteDataFile.trim()) {
406
+ fail('Template manifest siteDataFile is required.');
407
+ }
408
+
409
+ const siteDataPath = path.resolve(
410
+ options.templatePath,
411
+ manifest.siteDataFile.trim(),
412
+ );
413
+ const relativeSiteDataPath = path.relative(options.templatePath, siteDataPath);
414
+ if (
415
+ relativeSiteDataPath.startsWith('..') ||
416
+ path.isAbsolute(relativeSiteDataPath)
417
+ ) {
418
+ fail('Template manifest siteDataFile must stay inside the template directory.');
419
+ }
420
+
421
+ const controllerToken = crypto.randomBytes(24).toString('base64url');
422
+ const apiUrl = `http://${LOOPBACK_HOST}:${options.apiPort}`;
423
+ const sourcePreviewUrl = `http://${LOOPBACK_HOST}:${options.previewPort}`;
424
+ const previewUrl = `${apiUrl}${LOCAL_PREVIEW_ROUTE}`;
425
+ const validatorPath = path.join(
426
+ __dirname,
427
+ 'deneb-template-validator.cjs',
428
+ );
429
+
430
+ let shuttingDown = false;
431
+ let devProcess = null;
432
+ let validationProcess = null;
433
+ let readinessTimer = null;
434
+ let devRestartTimer = null;
435
+ let devRestartAttempts = 0;
436
+ const MAX_DEV_RESTART_ATTEMPTS = 5;
437
+ let devLog = '';
438
+ let validationLog = '';
439
+
440
+ const state = {
441
+ protocolVersion: 2,
442
+ connected: true,
443
+ templateName:
444
+ typeof manifest.name === 'string' && manifest.name.trim()
445
+ ? manifest.name.trim()
446
+ : typeof packageJson.name === 'string'
447
+ ? packageJson.name
448
+ : path.basename(options.templatePath),
449
+ templatePath: options.templatePath,
450
+ previewUrl,
451
+ apiUrl,
452
+ devStatus: 'starting',
453
+ devError: null,
454
+ startedAt: new Date().toISOString(),
455
+ validation: {
456
+ status: 'idle',
457
+ startedAt: null,
458
+ completedAt: null,
459
+ exitCode: null,
460
+ },
461
+ };
462
+
463
+ function appendLog(target, chunk) {
464
+ const text = chunk.toString();
465
+ if (target === 'dev') {
466
+ devLog = `${devLog}${text}`.slice(-MAX_LOG_LENGTH);
467
+ } else {
468
+ validationLog = `${validationLog}${text}`.slice(-MAX_LOG_LENGTH);
469
+ }
470
+ process.stdout.write(text);
471
+ }
472
+
473
+ function statusPayload() {
474
+ return {
475
+ ...state,
476
+ devLog,
477
+ validationLog,
478
+ };
479
+ }
480
+
481
+ function setCorsHeaders(request, response) {
482
+ const origin = request.headers.origin;
483
+ if (origin && /^(https?:\/\/|null$)/.test(origin)) {
484
+ response.setHeader('Access-Control-Allow-Origin', origin);
485
+ response.setHeader('Vary', 'Origin');
486
+ }
487
+ response.setHeader(
488
+ 'Access-Control-Allow-Headers',
489
+ 'Authorization, Content-Type',
490
+ );
491
+ response.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
492
+ response.setHeader('Access-Control-Allow-Private-Network', 'true');
493
+ response.setHeader('Cache-Control', 'no-store');
494
+ response.setHeader('X-Content-Type-Options', 'nosniff');
495
+ }
496
+
497
+ function sendJson(response, statusCode, payload) {
498
+ const body = JSON.stringify(payload);
499
+ response.statusCode = statusCode;
500
+ response.setHeader('Content-Type', 'application/json; charset=utf-8');
501
+ response.setHeader('Content-Length', Buffer.byteLength(body));
502
+ response.end(body);
503
+ }
504
+
505
+ function isAuthorized(request) {
506
+ return request.headers.authorization === `Bearer ${controllerToken}`;
507
+ }
508
+
509
+ function readSiteData() {
510
+ try {
511
+ return JSON.parse(fs.readFileSync(siteDataPath, 'utf8'));
512
+ } catch (error) {
513
+ throw new Error(
514
+ `Unable to read ${manifest.siteDataFile}: ${
515
+ error instanceof Error ? error.message : 'unknown error'
516
+ }`,
517
+ );
518
+ }
519
+ }
520
+
521
+ function startValidation() {
522
+ if (validationProcess) return false;
523
+
524
+ validationLog = '';
525
+ state.validation = {
526
+ status: 'running',
527
+ startedAt: new Date().toISOString(),
528
+ completedAt: null,
529
+ exitCode: null,
530
+ };
531
+
532
+ validationProcess = spawn(
533
+ process.execPath,
534
+ [validatorPath, 'validate', options.templatePath],
535
+ {
536
+ cwd: __dirname,
537
+ env: process.env,
538
+ stdio: ['ignore', 'pipe', 'pipe'],
539
+ },
540
+ );
541
+ validationProcess.stdout.on('data', (chunk) => appendLog('validation', chunk));
542
+ validationProcess.stderr.on('data', (chunk) => appendLog('validation', chunk));
543
+ validationProcess.on('error', (error) => {
544
+ appendLog('validation', `\nUnable to start validation: ${error.message}\n`);
545
+ });
546
+ validationProcess.on('close', (code) => {
547
+ state.validation = {
548
+ ...state.validation,
549
+ status: code === 0 ? 'passed' : 'failed',
550
+ completedAt: new Date().toISOString(),
551
+ exitCode: code,
552
+ };
553
+ validationProcess = null;
554
+ });
555
+ return true;
556
+ }
557
+
558
+ function probePreview() {
559
+ if (shuttingDown || state.devStatus === 'ready') return;
560
+ const request = http.get(sourcePreviewUrl, (response) => {
561
+ response.resume();
562
+ if (response.statusCode && response.statusCode < 500) {
563
+ state.devStatus = 'ready';
564
+ state.devError = null;
565
+ devRestartAttempts = 0;
566
+ process.stdout.write(`\nLive preview ready: ${previewUrl}\n`);
567
+ return;
568
+ }
569
+ readinessTimer = setTimeout(probePreview, 600);
570
+ });
571
+ request.setTimeout(900, () => request.destroy());
572
+ request.on('error', () => {
573
+ readinessTimer = setTimeout(probePreview, 600);
574
+ });
575
+ }
576
+
577
+ function scheduleDevRestart(reason) {
578
+ if (shuttingDown || devRestartTimer) return;
579
+ if (devRestartAttempts >= MAX_DEV_RESTART_ATTEMPTS) {
580
+ state.devStatus = 'failed';
581
+ state.devError = reason;
582
+ return;
583
+ }
584
+ devRestartAttempts += 1;
585
+ state.devStatus = 'starting';
586
+ state.devError = null;
587
+ appendLog(
588
+ 'dev',
589
+ `\nPreview server stopped during navigation (${reason}). Restarting (${devRestartAttempts}/${MAX_DEV_RESTART_ATTEMPTS})...\n`,
590
+ );
591
+ devRestartTimer = setTimeout(() => {
592
+ devRestartTimer = null;
593
+ startPreview();
594
+ }, 900);
595
+ }
596
+
597
+ function runInstallThenPreview() {
598
+ const nodeModulesPath = path.join(options.templatePath, 'node_modules');
599
+ if (!options.skipInstall && !fs.existsSync(nodeModulesPath)) {
600
+ state.devStatus = 'installing';
601
+ const installCommand =
602
+ typeof manifest.installCommand === 'string' && manifest.installCommand.trim()
603
+ ? manifest.installCommand.trim()
604
+ : 'npm install';
605
+ appendLog('dev', `Installing local dependencies with: ${installCommand}\n`);
606
+ const install = spawn(installCommand, {
607
+ cwd: options.templatePath,
608
+ env: process.env,
609
+ shell: true,
610
+ stdio: ['ignore', 'pipe', 'pipe'],
611
+ });
612
+ devProcess = install;
613
+ install.stdout.on('data', (chunk) => appendLog('dev', chunk));
614
+ install.stderr.on('data', (chunk) => appendLog('dev', chunk));
615
+ install.on('error', (error) => {
616
+ state.devStatus = 'failed';
617
+ state.devError = error.message;
618
+ devProcess = null;
619
+ });
620
+ install.on('close', (code) => {
621
+ devProcess = null;
622
+ if (code !== 0) {
623
+ state.devStatus = 'failed';
624
+ state.devError = `Dependency installation exited with code ${code}.`;
625
+ return;
626
+ }
627
+ startPreview();
628
+ });
629
+ return;
630
+ }
631
+
632
+ startPreview();
633
+ }
634
+
635
+ function startPreview() {
636
+ state.devStatus = 'starting';
637
+ state.devError = null;
638
+ appendLog(
639
+ 'dev',
640
+ `Starting template source server on ${sourcePreviewUrl}. Source edits will hot reload.\n`,
641
+ );
642
+ const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
643
+ devProcess = spawn(
644
+ npmCmd,
645
+ [
646
+ 'run',
647
+ 'dev',
648
+ '--',
649
+ '--hostname',
650
+ LOOPBACK_HOST,
651
+ '--port',
652
+ String(options.previewPort),
653
+ ],
654
+ {
655
+ cwd: options.templatePath,
656
+ env: {
657
+ ...process.env,
658
+ NEXT_PUBLIC_SITE_BASE_PATH: '',
659
+ },
660
+ shell: process.platform === 'win32',
661
+ stdio: ['ignore', 'pipe', 'pipe'],
662
+ },
663
+ );
664
+ devProcess.stdout.on('data', (chunk) => appendLog('dev', chunk));
665
+ devProcess.stderr.on('data', (chunk) => appendLog('dev', chunk));
666
+ devProcess.on('error', (error) => {
667
+ state.devStatus = 'failed';
668
+ state.devError = error.message;
669
+ devProcess = null;
670
+ });
671
+ devProcess.on('close', (code, signal) => {
672
+ devProcess = null;
673
+ if (!shuttingDown) {
674
+ const reason = signal
675
+ ? `signal ${signal}`
676
+ : `exit code ${code}`;
677
+ scheduleDevRestart(reason);
678
+ }
679
+ });
680
+ probePreview();
681
+ }
682
+
683
+ function previewShellHtml() {
684
+ return `<!doctype html>
14
685
  <html lang="en">
15
686
  <head>
16
687
  <meta charset="utf-8">
@@ -28,7 +699,7 @@ Preview server stopped during navigation (${e}). Restarting (${b}/${k})...
28
699
  <iframe id="template-preview" title="Local template preview"></iframe>
29
700
  <script>
30
701
  (() => {
31
- const BRIDGE_SOURCE = ${JSON.stringify((()=>{try{delete require.cache[require.resolve("./template-preview-focus-bridge.cjs")];const e=require("./template-preview-focus-bridge.cjs");if(typeof e=="string"&&e.trim())return e;}catch{}return ee;})())};
702
+ const BRIDGE_SOURCE = ${JSON.stringify(LOCAL_VISUAL_BRIDGE_SCRIPT)};
32
703
  const preview = document.getElementById('template-preview');
33
704
  const errorBox = document.getElementById('bridge-error');
34
705
  const PREVIOUS_PREVIEW_PREFIX = ['MARKET', 'PLACE'].join('') + '_PREVIEW_';
@@ -112,25 +783,247 @@ Preview server stopped during navigation (${e}). Restarting (${b}/${k})...
112
783
 
113
784
  preview.src = '/';
114
785
  })();
115
- <\/script>
786
+ </script>
116
787
  </body>
117
- </html>`}function w(e){if(!e||typeof e!="object")return!1;const t="code"in e?String(e.code):"";return t==="ECONNRESET"||t==="ECONNABORTED"||t==="EPIPE"||t==="ERR_STREAM_DESTROYED"}function me(e,t){const a={...e.headers};a.host=`${v}:${i.previewPort}`,delete a["accept-encoding"],delete a.authorization;const r=A.request({hostname:v,port:i.previewPort,method:e.method,path:e.url,headers:a},n=>{t.writeHead(n.statusCode||502,n.statusMessage,n.headers),n.on("error",s=>{w(s)||l("dev",`
118
- Preview proxy upstream error: ${s.message}
119
- `),t.writableEnded||t.destroy()}),t.on("error",s=>{w(s)||l("dev",`
120
- Preview proxy response error: ${s.message}
121
- `),n.destroy()}),n.pipe(t)});r.on("error",n=>{w(n)||l("dev",`
122
- Preview proxy request error: ${n.message}
123
- `),t.headersSent?t.writableEnded||t.destroy():g(t,502,{message:`Local preview is not ready: ${n.message}`})}),e.on("error",n=>{w(n)||l("dev",`
124
- Preview proxy client error: ${n.message}
125
- `),r.destroy()}),e.pipe(r)}const C=A.createServer((e,t)=>{const a=new URL(e.url||"/",y);if(e.method==="GET"&&a.pathname===U){const r=ue();t.writeHead(200,{"Cache-Control":"no-store","Content-Length":Buffer.byteLength(r),"Content-Type":"text/html; charset=utf-8"}),t.end(r);return}if(!a.pathname.startsWith("/api/")){me(e,t);return}if(oe(e,t),e.method==="OPTIONS"){t.statusCode=204,t.end();return}if(!se(e)){g(t,401,{message:"Invalid Local Template Lab token."});return}if(e.method==="GET"&&a.pathname==="/api/status"){g(t,200,K());return}if(e.method==="GET"&&a.pathname==="/api/site-data"){try{g(t,200,{manifest:c,siteData:le(),siteDataFile:c.siteDataFile})}catch(r){g(t,500,{message:r instanceof Error?r.message:"Unable to read site data."})}return}if(e.method==="POST"&&a.pathname==="/api/validate"){if(!de()){g(t,409,{message:"Validation is already running."});return}g(t,202,K());return}g(t,404,{message:"Local Template Lab endpoint not found."})});function fe(e,t){const a=()=>{e.destroyed||e.destroy(),t.destroyed||t.destroy()},r=n=>{w(n)||l("dev",`
126
- Preview proxy socket error: ${n.message}
127
- `),a()};e.on("error",r),t.on("error",r),e.on("close",()=>{t.destroyed||t.end()}),t.on("close",()=>{e.destroyed||e.end()}),t.pipe(e),e.pipe(t)}C.on("upgrade",(e,t,a)=>{if(e.url?.startsWith("/api/")){t.destroy();return}t.on("error",s=>{w(s)||l("dev",`
128
- Preview proxy upgrade client error: ${s.message}
129
- `)});const r={...e.headers};r.host=`${v}:${i.previewPort}`;const n=A.request({hostname:v,port:i.previewPort,method:e.method,path:e.url,headers:r});n.on("upgrade",(s,m,d)=>{const Y=Object.entries(s.headers).flatMap(([z,L])=>(Array.isArray(L)?L:[L]).filter(S=>S!==void 0).map(S=>`${z}: ${S}`)).join(`\r
130
- `);t.write(`HTTP/1.1 ${s.statusCode||101} ${s.statusMessage||"Switching Protocols"}\r
131
- ${Y}\r
132
- \r
133
- `),a.length&&m.write(a),d.length&&t.write(d),fe(t,m)}),n.on("error",s=>{w(s)||l("dev",`
134
- Preview proxy upgrade upstream error: ${s.message}
135
- `),t.destroyed||t.destroy()}),n.end()});function X(e){!e||e.killed||e.kill("SIGTERM")}function J(){P||(P=!0,I&&clearTimeout(I),_&&clearTimeout(_),X(h),X(u),C.close(()=>process.exit(0)),setTimeout(()=>process.exit(0),1500).unref())}C.on("error",e=>{p(`Unable to start loopback controller at ${y}: ${e instanceof Error?e.message:"unknown error"}`)}),C.listen(i.apiPort,v,()=>{process.stdout.write(["","Fivora Local Template Lab is running.",`Template: ${o.templateName}`,`Controller URL: ${y}`,`Connection token: ${H}`,`Preview URL: ${$}`,"","Paste the controller URL and connection token into Developer Portal > Local Test Lab.","Press Ctrl+C to stop. No template files are uploaded by this process.",""].join(`
136
- `)),ce()}),process.on("SIGINT",J),process.on("SIGTERM",J);
788
+ </html>`;
789
+ }
790
+
791
+ function ignoreAbortedStreamError(error) {
792
+ if (!error || typeof error !== 'object') return false;
793
+ const code = 'code' in error ? String(error.code) : '';
794
+ return (
795
+ code === 'ECONNRESET' ||
796
+ code === 'ECONNABORTED' ||
797
+ code === 'EPIPE' ||
798
+ code === 'ERR_STREAM_DESTROYED'
799
+ );
800
+ }
801
+
802
+ function proxyPreviewRequest(request, response) {
803
+ const headers = { ...request.headers };
804
+ headers.host = `${LOOPBACK_HOST}:${options.previewPort}`;
805
+ delete headers['accept-encoding'];
806
+ delete headers.authorization;
807
+
808
+ const upstream = http.request(
809
+ {
810
+ hostname: LOOPBACK_HOST,
811
+ port: options.previewPort,
812
+ method: request.method,
813
+ path: request.url,
814
+ headers,
815
+ },
816
+ (upstreamResponse) => {
817
+ response.writeHead(
818
+ upstreamResponse.statusCode || 502,
819
+ upstreamResponse.statusMessage,
820
+ upstreamResponse.headers,
821
+ );
822
+ upstreamResponse.on('error', (error) => {
823
+ if (!ignoreAbortedStreamError(error)) {
824
+ appendLog('dev', `\nPreview proxy upstream error: ${error.message}\n`);
825
+ }
826
+ if (!response.writableEnded) response.destroy();
827
+ });
828
+ response.on('error', (error) => {
829
+ if (!ignoreAbortedStreamError(error)) {
830
+ appendLog('dev', `\nPreview proxy response error: ${error.message}\n`);
831
+ }
832
+ upstreamResponse.destroy();
833
+ });
834
+ upstreamResponse.pipe(response);
835
+ },
836
+ );
837
+ upstream.on('error', (error) => {
838
+ if (!ignoreAbortedStreamError(error)) {
839
+ appendLog('dev', `\nPreview proxy request error: ${error.message}\n`);
840
+ }
841
+ if (!response.headersSent) {
842
+ sendJson(response, 502, {
843
+ message: `Local preview is not ready: ${error.message}`,
844
+ });
845
+ } else if (!response.writableEnded) {
846
+ response.destroy();
847
+ }
848
+ });
849
+ request.on('error', (error) => {
850
+ if (!ignoreAbortedStreamError(error)) {
851
+ appendLog('dev', `\nPreview proxy client error: ${error.message}\n`);
852
+ }
853
+ upstream.destroy();
854
+ });
855
+ request.pipe(upstream);
856
+ }
857
+
858
+ const server = http.createServer((request, response) => {
859
+ const url = new URL(request.url || '/', apiUrl);
860
+ if (request.method === 'GET' && url.pathname === LOCAL_PREVIEW_ROUTE) {
861
+ const html = previewShellHtml();
862
+ response.writeHead(200, {
863
+ 'Cache-Control': 'no-store',
864
+ 'Content-Length': Buffer.byteLength(html),
865
+ 'Content-Type': 'text/html; charset=utf-8',
866
+ });
867
+ response.end(html);
868
+ return;
869
+ }
870
+ if (!url.pathname.startsWith('/api/')) {
871
+ proxyPreviewRequest(request, response);
872
+ return;
873
+ }
874
+
875
+ setCorsHeaders(request, response);
876
+ if (request.method === 'OPTIONS') {
877
+ response.statusCode = 204;
878
+ response.end();
879
+ return;
880
+ }
881
+
882
+ if (!isAuthorized(request)) {
883
+ sendJson(response, 401, { message: 'Invalid Local Template Lab token.' });
884
+ return;
885
+ }
886
+
887
+ if (request.method === 'GET' && url.pathname === '/api/status') {
888
+ sendJson(response, 200, statusPayload());
889
+ return;
890
+ }
891
+
892
+ if (request.method === 'GET' && url.pathname === '/api/site-data') {
893
+ try {
894
+ sendJson(response, 200, {
895
+ manifest,
896
+ siteData: readSiteData(),
897
+ siteDataFile: manifest.siteDataFile,
898
+ });
899
+ } catch (error) {
900
+ sendJson(response, 500, {
901
+ message: error instanceof Error ? error.message : 'Unable to read site data.',
902
+ });
903
+ }
904
+ return;
905
+ }
906
+
907
+ if (request.method === 'POST' && url.pathname === '/api/validate') {
908
+ if (!startValidation()) {
909
+ sendJson(response, 409, { message: 'Validation is already running.' });
910
+ return;
911
+ }
912
+ sendJson(response, 202, statusPayload());
913
+ return;
914
+ }
915
+
916
+ sendJson(response, 404, { message: 'Local Template Lab endpoint not found.' });
917
+ });
918
+
919
+ function pipeProxySockets(clientSocket, upstreamSocket) {
920
+ const closeBoth = () => {
921
+ if (!clientSocket.destroyed) clientSocket.destroy();
922
+ if (!upstreamSocket.destroyed) upstreamSocket.destroy();
923
+ };
924
+ const onSocketError = (error) => {
925
+ if (!ignoreAbortedStreamError(error)) {
926
+ appendLog('dev', `\nPreview proxy socket error: ${error.message}\n`);
927
+ }
928
+ closeBoth();
929
+ };
930
+ clientSocket.on('error', onSocketError);
931
+ upstreamSocket.on('error', onSocketError);
932
+ clientSocket.on('close', () => {
933
+ if (!upstreamSocket.destroyed) upstreamSocket.end();
934
+ });
935
+ upstreamSocket.on('close', () => {
936
+ if (!clientSocket.destroyed) clientSocket.end();
937
+ });
938
+ upstreamSocket.pipe(clientSocket);
939
+ clientSocket.pipe(upstreamSocket);
940
+ }
941
+
942
+ server.on('upgrade', (request, socket, head) => {
943
+ if (request.url?.startsWith('/api/')) {
944
+ socket.destroy();
945
+ return;
946
+ }
947
+ socket.on('error', (error) => {
948
+ if (!ignoreAbortedStreamError(error)) {
949
+ appendLog('dev', `\nPreview proxy upgrade client error: ${error.message}\n`);
950
+ }
951
+ });
952
+ const headers = { ...request.headers };
953
+ headers.host = `${LOOPBACK_HOST}:${options.previewPort}`;
954
+ const upstreamRequest = http.request({
955
+ hostname: LOOPBACK_HOST,
956
+ port: options.previewPort,
957
+ method: request.method,
958
+ path: request.url,
959
+ headers,
960
+ });
961
+ upstreamRequest.on('upgrade', (upstreamResponse, upstreamSocket, upstreamHead) => {
962
+ const responseHeaders = Object.entries(upstreamResponse.headers)
963
+ .flatMap(([name, value]) => {
964
+ const values = Array.isArray(value) ? value : [value];
965
+ return values
966
+ .filter((entry) => entry !== undefined)
967
+ .map((entry) => `${name}: ${entry}`);
968
+ })
969
+ .join('\r\n');
970
+ socket.write(
971
+ `HTTP/1.1 ${upstreamResponse.statusCode || 101} ${upstreamResponse.statusMessage || 'Switching Protocols'}\r\n${responseHeaders}\r\n\r\n`,
972
+ );
973
+ if (head.length) upstreamSocket.write(head);
974
+ if (upstreamHead.length) socket.write(upstreamHead);
975
+ pipeProxySockets(socket, upstreamSocket);
976
+ });
977
+ upstreamRequest.on('error', (error) => {
978
+ if (!ignoreAbortedStreamError(error)) {
979
+ appendLog('dev', `\nPreview proxy upgrade upstream error: ${error.message}\n`);
980
+ }
981
+ if (!socket.destroyed) socket.destroy();
982
+ });
983
+ upstreamRequest.end();
984
+ });
985
+
986
+ function stopChild(child) {
987
+ if (!child || child.killed) return;
988
+ child.kill('SIGTERM');
989
+ }
990
+
991
+ function shutdown() {
992
+ if (shuttingDown) return;
993
+ shuttingDown = true;
994
+ if (readinessTimer) clearTimeout(readinessTimer);
995
+ if (devRestartTimer) clearTimeout(devRestartTimer);
996
+ stopChild(validationProcess);
997
+ stopChild(devProcess);
998
+ server.close(() => process.exit(0));
999
+ setTimeout(() => process.exit(0), 1500).unref();
1000
+ }
1001
+
1002
+ server.on('error', (error) => {
1003
+ fail(
1004
+ `Unable to start loopback controller at ${apiUrl}: ${
1005
+ error instanceof Error ? error.message : 'unknown error'
1006
+ }`,
1007
+ );
1008
+ });
1009
+
1010
+ server.listen(options.apiPort, LOOPBACK_HOST, () => {
1011
+ process.stdout.write(
1012
+ [
1013
+ '',
1014
+ 'Fivora Local Template Lab is running.',
1015
+ `Template: ${state.templateName}`,
1016
+ `Controller URL: ${apiUrl}`,
1017
+ `Connection token: ${controllerToken}`,
1018
+ `Preview URL: ${previewUrl}`,
1019
+ '',
1020
+ 'Paste the controller URL and connection token into Developer Portal > Local Test Lab.',
1021
+ 'Press Ctrl+C to stop. No template files are uploaded by this process.',
1022
+ '',
1023
+ ].join('\n'),
1024
+ );
1025
+ runInstallThenPreview();
1026
+ });
1027
+
1028
+ process.on('SIGINT', shutdown);
1029
+ process.on('SIGTERM', shutdown);