@smart-cloud/publisher-exporter 1.1.72 → 1.1.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/content-sync.js +15 -15
- package/dist/crawl.js +13 -13
- package/dist/deploy.js +4 -4
- package/dist/invalidate.js +1 -1
- package/dist/queue-runner.js +1 -1
- package/package.json +3 -2
- package/publisher.config.example.json +3 -0
package/dist/content-sync.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import F,{readFile}from'fs/promises';import Vo from'http';import jn from'https';import v from'path';import rs,{createHash}from'crypto';import {request,chromium}from'playwright';import {gunzipSync}from'zlib';import fi from'fast-glob';import ks from'mime-types';import {availableParallelism}from'os';import {Worker}from'worker_threads';import {LambdaClient,InvokeCommand}from'@aws-sdk/client-lambda';import {DynamoDBClient,GetItemCommand}from'@aws-sdk/client-dynamodb';import {S3Client,GetObjectCommand,PutObjectCommand,CopyObjectCommand,ListObjectsV2Command,HeadObjectCommand,DeleteObjectsCommand}from'@aws-sdk/client-s3';import {fromTemporaryCredentials}from'@aws-sdk/credential-providers';import {Upload}from'@aws-sdk/lib-storage';import {CloudFrontClient,waitUntilInvalidationCompleted,CreateInvalidationCommand}from'@aws-sdk/client-cloudfront';var Lo=new Set(["post-type","taxonomy","author","date","posts-page","listing"]);function ze(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))].sort()}function qo(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))]}function Wo(e){return new URL(e).pathname.split("/").filter(Boolean).some(r=>{try{return decodeURIComponent(r).endsWith("__trashed")}catch{return r.endsWith("__trashed")}})}function xr(e){return Array.isArray(e)?e.map(xr):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>[t,xr(r)])):e}function No(e){return JSON.stringify(xr(e))}function De(e){return createHash("sha256").update(No(e)).digest("hex")}function Tn(e){return De({schemaVersion:1,wordpressFingerprint:e.wordpressFingerprint,targetFingerprint:e.targetFingerprint,sourceOrigin:e.sourceOrigin,sitemapPaths:[...e.sitemapPaths].sort(),blockedPathPrefixes:[...e.blockedPathPrefixes].sort(),assetPathPrefixes:[...e.assetPathPrefixes].sort(),noJavaScriptRenderPathPrefixes:[...e.noJavaScriptRenderPathPrefixes].sort(),urlRewriteMode:e.urlRewriteMode})}function Ir(e){let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error(`Unsupported source origin protocol: ${t.protocol}`);return t.hash="",t.search="",t.pathname=t.pathname.replace(/\/+$/,""),t.toString().replace(/\/$/,"")}function ke(e,t){_o(t);let r=new URL(Ir(e)),n=new URL(t,`${r.toString().replace(/\/$/,"")}/`);if(n.origin!==r.origin)throw new Error(`Content-sync URL is outside the source origin: ${t}`);let s=r.pathname.replace(/\/+$/,"");if(s&&n.pathname!==s&&!n.pathname.startsWith(`${s}/`))throw new Error(`Content-sync URL is outside the source site path: ${t}`);return n.hash="",n.toString()}function _o(e){let r=String(e).split(/[?#]/,1)[0];for(let s=0;s<3;s+=1)try{let o=decodeURIComponent(r);if(o===r)break;r=o;}catch{throw new Error(`Content-sync URL has malformed encoding: ${e}`)}if(r.includes("\0")||r.includes("\\"))throw new Error(`Content-sync URL has an unsafe path: ${e}`);if(r.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]*/i,"").split("/").some(s=>s==="."||s===".."))throw new Error(`Content-sync URL has an unsafe path: ${e}`)}function Pt(e){let t=ze((e.postTypes??[]).map(n=>String(n).toLowerCase().replace(/[^a-z0-9_-]/g,"")));if(t.length===0)throw new Error("Content-sync requires at least one public post type.");let r=ze((e.listingPaths??[]).map(n=>{let s=String(n).trim();if(!s)return "";let o=new URL(s,"https://content-sync.invalid/");if(o.origin!=="https://content-sync.invalid"&&/^https?:\/\//i.test(s))throw new Error("Content-sync listing routes must be same-site paths.");let a=`/${o.pathname.replace(/^\/+|\/+$/g,"")}`;return a==="/"?"/":`${a}/`}));return {postTypes:t,listingPaths:r,includeSubsites:e.includeSubsites===true,includePostTypeArchives:e.includePostTypeArchives!==false,includeTaxonomyArchives:e.includeTaxonomyArchives!==false,includeAuthorArchives:e.includeAuthorArchives===true,includeDateArchives:e.includeDateArchives===true,includePostsPage:e.includePostsPage!==false,includeSitemapChain:e.includeSitemapChain!==false}}function An(e,t,r){return De({schemaVersion:1,sourceOrigin:Ir(e),ruleId:t.trim(),scope:Pt(r)})}function En(e){return De({schemaVersion:1,...e})}function $n(e){let t=String(e.siteId??"").trim()||String(e.accountId??"").trim()||Ir(e.sourceOrigin);return `content-sync:${De({siteIdentity:t,ruleId:e.ruleId.trim(),targetFingerprint:e.targetFingerprint}).slice(0,48)}`}function On(e){let t=[...e].sort((s,o)=>s.sequence-o.sequence),r=new Map,n=-1;for(let s of t){if(!Number.isSafeInteger(s.sequence)||s.sequence<=n)throw new Error("Content-sync journal events are not strictly ordered.");if(n=s.sequence,!Number.isSafeInteger(s.blogId)||s.blogId<1)throw new Error("Content-sync journal event has an invalid multisite identity.");let o=`${s.blogId}:${s.postType}:${s.postId}`,a=r.get(o);if(!a){r.set(o,{postId:s.postId,blogId:s.blogId,postType:s.postType,fromSequence:s.sequence,toSequence:s.sequence,before:s.before,after:s.after,operations:[s.operation],correlationIds:s.correlationId?[s.correlationId]:[]});continue}a.toSequence=s.sequence,a.after=s.after,a.operations.push(s.operation),s.correlationId&&!a.correlationIds.includes(s.correlationId)&&a.correlationIds.push(s.correlationId);}return [...r.values()].sort((s,o)=>s.fromSequence-o.fromSequence)}function In(e){return e?.status==="publish"&&!!e.url}function Bo(e,t){return e==="post-type"?t.includePostTypeArchives:e==="taxonomy"?t.includeTaxonomyArchives:e==="author"?t.includeAuthorArchives:e==="date"?t.includeDateArchives:e==="posts-page"?t.includePostsPage:e==="listing"}function Tr(e){let t=Pt(e.scope),r=new Map;On(e.events);for(let n of e.events)for(let s of [n.before,n.after])for(let o of s?.archiveFamilies??[]){if(!Lo.has(o.kind)||!Bo(o.kind,t))continue;let a={...o,url:ke(e.sourceOrigin,o.url)};r.set(`${a.kind}|${a.url}`,a);}for(let n of t.listingPaths){let s=ke(e.sourceOrigin,n);r.set(`listing|${s}`,{kind:"listing",url:s});}return [...r.values()].sort((n,s)=>n.url.localeCompare(s.url))}function Mn(e){let t=Pt(e.scope),r=On(e.events),n=new Set,s=new Set,o=new Map,a=new Map(Tr({events:e.events,scope:t,sourceOrigin:e.sourceOrigin}).map(m=>[`${m.kind}|${m.url}`,m]));for(let m of r){let w=m.before,p=m.after,h=In(w),y=In(p);y&&p.url&&n.add(ke(e.sourceOrigin,p.url)),h&&w.url&&(!y||w.url!==p.url)&&s.add(ke(e.sourceOrigin,w.url));}for(let m of [...e.events].sort((w,p)=>w.sequence-p.sequence)){for(let w of [m.before,m.after])for(let p of w?.resourceDeleteUrls??[])o.set(ke(e.sourceOrigin,p),"delete");for(let w of m.after?.resourceRenderUrls??[])o.set(ke(e.sourceOrigin,w),"render");}let c=[...o].filter(([,m])=>m==="render").map(([m])=>m),i=[...o].filter(([,m])=>m==="delete").map(([m])=>m),d=new Map(e.resolvedArchiveFamilies.map(m=>[`${m.kind}|${ke(e.sourceOrigin,m.url)}`,{...m,url:ke(e.sourceOrigin,m.url),pageUrls:ze(m.pageUrls.map(w=>ke(e.sourceOrigin,w)))}])),l=[...a.entries()].map(([m,w])=>{let p=d.get(m);if(!p)throw new Error(`WordPress did not resolve archive family ${m}.`);return {...w,...p}}).sort((m,w)=>m.url.localeCompare(w.url)),u=ze(l.flatMap(m=>m.pageUrls)),g=t.includeSitemapChain?qo(e.sitemapUrls.map(m=>ke(e.sourceOrigin,m))):[],f={schemaVersion:1,generatedAt:new Date().toISOString(),jobId:e.jobId,ruleId:e.ruleId,consumerId:e.consumerId,coalesceKey:e.coalesceKey,scopeFingerprint:e.scopeFingerprint,targetFingerprint:e.targetFingerprint,baselineId:e.baselineId,fromSequence:e.fromSequence,toSequence:e.toSequence,eventCount:e.events.length,foldedCount:r.length,directRenderUrls:ze([...n]),archiveFamilyUrls:u,sitemapUrls:g,deleteUrls:ze([...s]),resourceRenderUrls:ze(c),resourceDeleteUrls:ze(i),archiveFamilies:l};return {...f,impactHash:De(f)}}function Rt(e){let{impactHash:t,...r}=e;if(e.schemaVersion!==1||!t)throw new Error("Invalid content-sync impact plan schema.");if(!Array.isArray(e.resourceRenderUrls)||!Array.isArray(e.resourceDeleteUrls))throw new Error("Invalid content-sync resource impact contract.");if(De(r)!==t)throw new Error("Content-sync impact plan hash mismatch.");for(let n of [...e.directRenderUrls,...e.deleteUrls,...e.resourceRenderUrls,...e.resourceDeleteUrls])if(Wo(n))throw new Error(`Content-sync impact contains a WordPress trash alias instead of the last public URL: ${n}`)}var Ko="wp-json/smartcloud-static-publisher/v1/content-sync/",zo=25*1024*1024,Lt=class extends Error{status;code;constructor(t,r,n){super(n),this.name="ContentSyncApiError",this.status=t,this.code=r;}},qt=class{options;constructor(t){if(!t.runtimeToken.trim())throw new Error("Content-sync requires a WordPress runtime token.");this.options={...t,timeoutMs:t.timeoutMs??6e4};}endpoint(t,r="content-sync"){let n=this.options.sourceOrigin.replace(/\/+$/,"")+"/",s=r==="content-sync"?Ko:`wp-json/smartcloud-static-publisher/v1/${r}/`;return new URL(`${s}${t}`,n)}async post(t,r,n="content-sync"){let s=this.endpoint(t,n),o=Buffer.from(JSON.stringify(r),"utf8"),a=s.protocol==="https:"?jn:Vo,c=s.protocol==="https:"?new jn.Agent({rejectUnauthorized:!this.options.ignoreHttpsErrors}):void 0;return new Promise((i,d)=>{let l=a.request(s,{method:"POST",agent:c,headers:{"content-type":"application/json","content-length":String(o.byteLength),"x-static-publisher-token":this.options.runtimeToken},timeout:this.options.timeoutMs},u=>{let g=[],f=0;u.on("data",m=>{if(f+=m.byteLength,f>zo){u.destroy(new Error("Content-sync API response exceeded the size limit."));return}g.push(m);}),u.on("error",d),u.on("end",()=>{let m=Buffer.concat(g).toString("utf8"),w;try{w=m?JSON.parse(m):{};}catch{d(new Lt(u.statusCode??500,"invalid-json","Content-sync API returned invalid JSON."));return}let p=u.statusCode??500;if(p<200||p>=300){d(new Lt(p,String(w.code??"request-failed"),String(w.message??`Content-sync API request failed (${p}).`)));return}i(w);});});l.on("timeout",()=>l.destroy(new Error(`Content-sync API request timed out: ${t}`))),l.on("error",d),l.end(o);})}async head(t){return this.post("head",t)}async unboundHead(t,r){return this.post("head",{postTypes:t,includeSubsites:r})}async events(t){let r=[],n=t.afterSequence,s=new Set(t.postTypes);for(;n<t.throughSequence;){let o=await this.post("events",{...t,afterSequence:n,limit:250});if(o.fromSequence!==n||o.throughSequence!==t.throughSequence||o.nextSequence<n||o.nextSequence>t.throughSequence)throw new Error("Content-sync API returned an inconsistent event page.");if(!Array.isArray(o.items))throw new Error("Content-sync API returned a malformed event page.");let a=n;for(let c of o.items){if(!Number.isSafeInteger(c.sequence)||c.sequence<=a||c.sequence>t.throughSequence||!Number.isSafeInteger(c.postId)||c.postId<=0||!Number.isSafeInteger(c.blogId)||c.blogId<=0||!s.has(c.postType)||typeof c.operation!="string"||!c.operation)throw new Error("Content-sync API returned an invalid or out-of-scope journal event.");a=c.sequence;}if(o.items.length>0&&o.nextSequence!==a)throw new Error("Content-sync API event cursor does not match the final returned event.");if(r.push(...o.items),!o.hasMore)break;if(o.nextSequence===n)throw new Error("Content-sync API event pagination did not advance.");n=o.nextSequence;}if(t.throughSequence>t.afterSequence&&r.at(-1)?.sequence!==t.throughSequence)throw new Error("Content-sync API omitted the claimed journal high-water event.");return r}async resolveImpactFamilies(t,r){let n=await this.post("impact",{families:t,includeSubsites:r});return Array.isArray(n.families)?n.families:[]}async releaseFingerprint(t=false){let r=await this.post("fingerprint",{includeSubsites:t}),n=String(r.fingerprint||"").trim();if(!/^[a-f0-9]{64}$/.test(n))throw new Error("WordPress returned an invalid release fingerprint.");return n}async establishBaseline(t){return this.post("baseline",t)}async acknowledge(t){return this.post("ack",t)}async importCookieObservations(t){return this.post("cookie-observations",t,"privacy")}};function Wt(e){let t=v.resolve(e);return {state:v.join(t,"content-sync-state.json"),current:v.join(t,"content-sync-current.json"),impact:v.join(t,"content-sync-impact-plan.json"),checkpoint:v.join(t,"content-sync-checkpoint.json"),baseline:v.join(t,"content-sync-baseline.json"),activeRules:v.join(t,"content-sync-active-rules.json"),releaseCutoff:v.join(t,"content-sync-release-cutoff.json"),candidateManifest:v.join(t,"content-sync-candidate-manifest.json"),trustedManifest:v.join(t,"crawl-manifest.json"),invalidation:v.join(t,"content-sync-invalidation.json"),deployPlan:v.join(t,"deploy-plan.json")}}async function Ar(e){let t=await vt(e.releaseCutoff);if(t===null)return {schemaVersion:1,updatedAt:"",entries:{}};let r=t;if(r.schemaVersion!==1||typeof r.updatedAt!="string"||!r.entries||typeof r.entries!="object"||Array.isArray(r.entries))throw new Error("Invalid content-sync release-cutoff store.");return r}async function Fn(e,t){await it(e.releaseCutoff,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function it(e,t){await F.mkdir(v.dirname(e),{recursive:true});let r=`${e}.${process.pid}.${Date.now()}.tmp`;await F.writeFile(r,JSON.stringify(t,null,2),"utf8"),await F.rename(r,e);}async function vt(e){try{return JSON.parse(await F.readFile(e,"utf8"))}catch(t){if(t.code==="ENOENT")return null;throw new Error(`Invalid or unreadable content-sync state file ${e}: ${t instanceof Error?t.message:String(t)}`,{cause:t})}}async function Er(e){let t=await vt(e.baseline);if(t===null)return {schemaVersion:1,updatedAt:"",entries:{}};let r=t;if(r.schemaVersion!==1||typeof r.updatedAt!="string"||!r.entries||typeof r.entries!="object"||Array.isArray(r.entries))throw new Error("Invalid content-sync baseline store.");return r}async function Dn(e,t){await it(e.baseline,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function $r(e){let t=await vt(e.current);if(t===null)return null;let r=t;if(r.schemaVersion!==1||typeof r.jobId!="string"||typeof r.phase!="string"||!Number.isSafeInteger(r.fromSequence)||!Number.isSafeInteger(r.toSequence))throw new Error("Invalid content-sync current-range state.");return r}async function Un(e,t){await it(e.current,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Ln(e){let t=await vt(e.impact);if(t===null)return null;let r=t;return Rt(r),r}async function qn(e,t){Rt(t),await it(e.impact,t);}async function Wn(e,t){await it(e.checkpoint,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Nt(e){let t=await vt(e.state);if(t===null)return {schemaVersion:1,updatedAt:"",rules:{}};let r=t;if(r.schemaVersion!==1||typeof r.updatedAt!="string"||!r.rules||typeof r.rules!="object"||Array.isArray(r.rules))throw new Error("Invalid content-sync state store.");return r}async function _t(e,t){await it(e.state,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Or(e){await Promise.all([e.current,e.checkpoint].map(async t=>{try{await F.unlink(t);}catch(r){if(r.code!=="ENOENT")throw r}}));}async function Nn(e,t){let r=await $r(e);return !r||r.coalesceKey!==t?false:(await Promise.all([e.current,e.checkpoint,e.impact,e.candidateManifest,e.invalidation,e.deployPlan].map(async n=>{try{await F.unlink(n);}catch(s){if(s.code!=="ENOENT")throw s}})),true)}var Mr=["/sitemap_index.xml","/wp-sitemap.xml","/sitemap.xml"];function Ct(e){let t=new Set;for(let r of [...e,...Mr]){let n=String(r||"").trim();n&&t.add(n);}return [...t]}function jr(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function _n(e){if(!e||!/^https?:\/\//i.test(e))return false;try{return jr(new URL(e))}catch{return false}}function Vn(e){let t=e.trim();return t==="."?".":t.replace(/\/$/,"")}function Go(e){let t=String(e??"").trim();if(!t)return "";let r=t;if(/^https?:\/\//i.test(r))try{r=new URL(r).pathname;}catch{return ""}if(r=r.split(/[?#]/,1)[0]?.replace(/\\/g,"/").trim()??"",!r)return "";let n=r.endsWith("/"),s=r.replace(/^\/+/,"").split("/").map(a=>a.replace(/[^A-Za-z0-9._-]/g,"")).filter(a=>a.length>0&&a!=="."&&a!=="..");if(s.length===0)return "";let o=`/${s.join("/")}`;return n&&v.extname(o)===""&&(o+="/"),o==="/"?"":o}function Fr(e){return !e||typeof e!="object"?{}:Object.fromEntries(Object.entries(e).map(([t,r])=>[t.trim(),String(r??"")]).filter(([t])=>t.length>0))}function Zo(e){if(!e||typeof e!="object")return {};let t={};for(let[r,n]of Object.entries(e)){let s=r.trim();if(!s||!n||typeof n!="object")continue;let o=n,a={};if(typeof o.targetOrigin=="string"){let i=Vn(o.targetOrigin);i&&(a.targetOrigin=i);}let c=Fr(o.extraReplacements);if(Object.keys(c).length>0&&(a.extraReplacements=c),o.s3&&typeof o.s3=="object"){let i={},d=o.s3;typeof d.bucket=="string"&&(i.bucket=d.bucket.trim()),typeof d.prefix=="string"&&(i.prefix=d.prefix.trim()),typeof d.region=="string"&&(i.region=d.region.trim()),typeof d.htmlCacheControl=="string"&&(i.htmlCacheControl=d.htmlCacheControl.trim()),typeof d.assetCacheControl=="string"&&(i.assetCacheControl=d.assetCacheControl.trim()),Object.keys(i).length>0&&(a.s3=i);}if(o.cloudFront&&typeof o.cloudFront=="object"){let i={},d=o.cloudFront;typeof d.distributionId=="string"&&(i.distributionId=d.distributionId.trim()),Array.isArray(d.invalidationPaths)&&(i.invalidationPaths=d.invalidationPaths.map(l=>String(l??"").trim()).filter(l=>l.length>0)),Object.keys(i).length>0&&(a.cloudFront=i);}t[s]=a;}return t}function Ur(e){return e==="PROFESSIONAL"||e==="AGENCY"?e:void 0}function Yo(e,t){if(!e||typeof e!="object")return null;let r=e,n=r.command;if(n!=="publish"&&n!=="crawl"&&n!=="deploy"&&n!=="invalidate"&&n!=="retry-timeouts"&&n!=="url"&&n!=="content-sync")return null;let s=Number.parseInt(String(r.intervalMinutes??"0"),10);if(!Number.isFinite(s)||s<1)return null;let o=String(r.id??`${n}-${t+1}`).trim();if(!o)return null;let a=String(r.deploymentProfile??"").trim(),c=String(r.url??"").trim(),i=Array.isArray(r.postTypes)?[...new Set(r.postTypes.map(l=>String(l??"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"")).filter(Boolean))]:[],d=Array.isArray(r.listingPaths)?[...new Set(r.listingPaths.map(l=>String(l??"").trim()).filter(Boolean))]:[];return n==="content-sync"&&i.length===0?null:{id:o,enabled:r.enabled!==false,command:n,intervalMinutes:s,...n==="publish"||n==="crawl"?{crawlMode:r.crawlMode==="incremental"?"incremental":"full"}:{},...(n==="publish"||n==="deploy"||n==="invalidate"||n==="content-sync")&&a?{deploymentProfile:a}:{},...c?{url:c}:{},...i.length>0?{postTypes:i}:{},...d.length>0?{listingPaths:d}:{},...typeof r.includeSubsites=="boolean"?{includeSubsites:r.includeSubsites}:{},...typeof r.includePostTypeArchives=="boolean"?{includePostTypeArchives:r.includePostTypeArchives}:{},...typeof r.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:r.includeTaxonomyArchives}:{},...typeof r.includeAuthorArchives=="boolean"?{includeAuthorArchives:r.includeAuthorArchives}:{},...typeof r.includeDateArchives=="boolean"?{includeDateArchives:r.includeDateArchives}:{},...typeof r.includePostsPage=="boolean"?{includePostsPage:r.includePostsPage}:{},...typeof r.includeSitemapChain=="boolean"?{includeSitemapChain:r.includeSitemapChain}:{}}}function Kn(e){let t=e&&typeof e=="object"?e:{},r=Array.isArray(t.rules)?t.rules.map((n,s)=>Yo(n,s)).filter(n=>!!n):[];return {enabled:t.enabled===true,timezone:typeof t.timezone=="string"&&t.timezone.trim()!==""?t.timezone.trim():"UTC",rules:r}}function Xo(e){let t=e&&typeof e=="object"?e:{},r=t.render&&typeof t.render=="object"?t.render:{},n=Number(r.concurrency??0),s=Number(r.batchSize??0),o=Number(r.maxAttempts??0),a=t.rewrite&&typeof t.rewrite=="object"?t.rewrite:{},c=t.deploy&&typeof t.deploy=="object"?t.deploy:{},i=(d,l)=>({enabled:typeof d.enabled=="boolean"?d.enabled:r.enabled===true,concurrency:Math.min(100,Math.max(1,Number(d.concurrency||l.concurrency))),batchSize:Math.min(500,Math.max(1,Number(d.batchSize||l.batchSize))),maxAttempts:Math.min(5,Math.max(1,Number(d.maxAttempts||2)))});return {render:{enabled:r.enabled===true,...Number.isInteger(n)&&n>0?{concurrency:n}:{},batchSize:Number.isInteger(s)&&s>0?Math.min(20,s):5,...Number.isInteger(o)&&o>0?{maxAttempts:Math.min(5,o)}:{}},rewrite:i(a,{concurrency:8,batchSize:25}),deploy:i(c,{concurrency:8,batchSize:50})}}function ei(e){if(!e||typeof e!="object")return;let t=e,r={};for(let s of ["accountId","siteId"]){let o=t[s];typeof o=="string"&&o.trim()!==""&&(r[s]=o.trim());}let n=Number(t.lastUpdate??0);return Number.isFinite(n)&&n>0&&(r.lastUpdate=Math.floor(n)),t.subscriber===true&&(r.subscriber=true),Object.keys(r).length>0?r:void 0}function Lr(e){let t=e&&typeof e=="object"?e:{},r=String(t.accountId??"").trim(),n=String(t.siteId??"").trim(),s=t.subscriber===true,o=ei(t.siteSettings),a={...o??{},...r?{accountId:o?.accountId??r}:{},...n?{siteId:o?.siteId??n}:{},...o?.subscriber===true||s?{subscriber:true}:{}},c={},i=String(t.apiBase??"").trim();i&&(c.apiBase=i);let d=String(t.runtimeToken??t.nonce??"").trim();d&&(c.runtimeToken=d);let l=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();l&&(c.virtualAssetBaseUrl=l),Object.keys(a).length>0&&(c.siteSettings=a);let u=Ur(t.subscriptionType);return u&&(c.subscriptionType=u),c}function ti(e){try{let t=new URL(e);globalThis.location=t;}catch{}}function zn(e){return typeof e=="string"?e:e instanceof URL?e.toString():e.url}function ri(e,t){let r=new Headers(e instanceof Request?e.headers:void 0);if(t?.headers)for(let[n,s]of new Headers(t.headers).entries())r.set(n,s);return r}async function Hn(e,t,r=5){let n=new URL(zn(e)),s=String(t?.method??(e instanceof Request?e.method:"GET")).toUpperCase(),o=n.protocol==="http:"?Vo:jn,a=ri(e,t);return await new Promise((c,i)=>{let d=o.request(n,{method:s,headers:Object.fromEntries(a.entries()),...n.protocol==="https:"?{rejectUnauthorized:false}:{}},l=>{let u=[];l.on("data",g=>{u.push(Buffer.isBuffer(g)?g:Buffer.from(g));}),l.on("error",i),l.on("end",()=>{let g=l.statusCode??0,f=l.headers.location;if(r>0&&f&&[301,302,303,307,308].includes(g)){c(Hn(new URL(f,n),{method:g===303?"GET":s},r-1));return}let m=new Headers;for(let[w,p]of Object.entries(l.headers))Array.isArray(p)?m.set(w,p.join(", ")):typeof p=="string"&&m.set(w,p);c(new Response(Buffer.concat(u),{status:g,statusText:l.statusMessage??"",headers:m}));});});d.on("error",i),d.end();})}function ni(e){let t=Lr(e.wpsuite),r={...t.siteSettings??{},...t.siteSettings?.subscriber===true||t.subscriptionType==="PROFESSIONAL"||t.subscriptionType==="AGENCY"?{subscriber:true}:{}},n=String(r.accountId??"").trim(),s=String(r.siteId??"").trim(),o=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();if(e.wpsuite={...t.apiBase?{apiBase:t.apiBase}:{},...t.runtimeToken?{runtimeToken:t.runtimeToken}:{},...o?{virtualAssetBaseUrl:o}:{},...Object.keys(r).length>0?{siteSettings:r}:{},...t.subscriptionType?{subscriptionType:t.subscriptionType}:{}},!n||!s||!o)return false;ti(e.sourceOrigin);let a=globalThis,i={...a.WpSuite??{},siteSettings:r,uploadUrl:o};return t.apiBase&&(i.apiBase=t.apiBase),a.WpSuite=i,true}async function si(e){let t=String(e.wpsuite?.virtualAssetBaseUrl??e.wpsuite?.uploadUrl??"").trim();if(!ni(e)){let s=e.wpsuite?.siteSettings,o=[String(s?.accountId??"").trim()?"":"accountId",String(s?.siteId??"").trim()?"":"siteId",t?"":"virtualAssetBaseUrl"].filter(Boolean);return {remote:null,diagnostic:{status:"invalid-runtime",virtualAssetBaseUrl:t,subscriptionType:null,error:`Missing WP Suite runtime field(s): ${o.join(", ")}.`,requests:[]}}}let r=globalThis.fetch,n=[];try{typeof r=="function"&&/^https?:\/\//i.test(t)&&(globalThis.fetch=(async(i,d)=>{let l=zn(i);if(l.startsWith(t)){let u=(()=>{try{return new URL(l).pathname}catch{return l}})();try{let g=e.ignoreHttpsErrors&&l.startsWith("https://")?await Hn(i,d):await r(i,d);return n.push({path:u,status:g.status,ok:g.ok,error:null}),g}catch(g){throw n.push({path:u,status:null,ok:!1,error:g instanceof Error?g.message:String(g)}),g}}return r(i,d)}));let{getConfig:s}=await import('@smart-cloud/wpsuite-core'),o=await s("publisher"),a=o&&typeof o=="object"?o:null,c=Ur(a?.subscriptionType);return {remote:a,diagnostic:{status:a?"loaded":"unavailable",virtualAssetBaseUrl:t,subscriptionType:c??null,error:a?null:"WP Suite publisher config loader returned no configuration.",requests:n}}}catch(s){return {remote:null,diagnostic:{status:"unavailable",virtualAssetBaseUrl:t,subscriptionType:null,error:s instanceof Error?s.message:String(s),requests:n}}}finally{typeof r=="function"&&(globalThis.fetch=r);}}function oi(e,t){let r=Zo(t?.deploymentProfiles),n=String(t?.defaultDeploymentProfile??"").trim(),s=r[n]?n:"",o=Ur(t?.subscriptionType),a=Lr(e.wpsuite);return {...e,scheduler:Kn(t?.scheduler),deploymentProfiles:r,defaultDeploymentProfile:s,...o?{subscriptionType:o}:{},wpsuite:{...a,...a.siteSettings||o?{siteSettings:{...a.siteSettings??{},...a.siteSettings?.subscriber===true||o==="PROFESSIONAL"||o==="AGENCY"?{subscriber:true}:{}}}:{},...o?{subscriptionType:o}:{}}}}function Dr(e,t){let n=String(e||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!n)return t;let s=n.split("/").map(o=>o.trim()).filter(o=>o.length>0&&o!=="."&&o!=="..");return s.length>0?s.join("/"):t}function ii(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?v.resolve(e):""}function Bn(e,t,r){let n=String(t||"").trim();return n&&v.isAbsolute(n)?v.resolve(n):v.resolve(e,Dr(n,r))}async function xe(e,t={}){let r=String(e??"").trim()||process.env.PUBLISHER_CONFIG||"publisher.config.json",n=await F.readFile(r,"utf8"),s=JSON.parse(n);s.sourceOrigin=s.sourceOrigin.replace(/\/$/,""),s.targetOrigin=Vn(s.targetOrigin),s.ignoreHttpsErrors??=false,s.outputDir=String(s.outputDir||"export").trim()||"export",s.urlRewriteMode||=s.targetOrigin==="."?"relative":"absolute",s.noJavaScriptRenderPathPrefixes||=[],s.seedPaths||=[],s.generated404RequestPath=Go(s.generated404RequestPath),s.sitemapPaths||=[...Mr],s.allowedAssetHosts||=[],s.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],s.blockedPathPrefixes||=[],s.blockedSearchFragments||=[];let o=Number(s.processingConcurrency)>0?Math.min(100,Math.max(1,Number(s.processingConcurrency))):null;s.concurrency=o??s.concurrency??1,s.maxPages||=0,s.extraReplacements=Fr(s.extraReplacements),s.postCrawlCopyMap=Fr(s.postCrawlCopyMap),s.logDir=String(s.logDir||"logs").trim()||"logs",s.verbose??=false,s.logLevel||=s.verbose?"debug":"info",s.s3SyncMode||="sdk-upload-delete",s.readiness||={waitForSelector:null,waitForFunction:null,timeoutMs:1500,fallbackWaitMs:1500},s.readiness.timeoutMs??=1500,s.readiness.fallbackWaitMs??=1500,s.viewport||={width:1440,height:1200},s.navigationTimeoutMs||=3e4,s.assetDownloadConcurrency=o??(Number(s.assetDownloadConcurrency)>0?Number(s.assetDownloadConcurrency):s.concurrency),s.rewriteConcurrency=o??(Number(s.rewriteConcurrency)>0?Number(s.rewriteConcurrency):s.assetDownloadConcurrency),s.wpsuite=Lr(s.wpsuite),s.scheduler=Kn(void 0),s.remoteWorkers=Xo(s.remoteWorkers),typeof s.lambdaDelegationEnabled=="boolean"&&(s.remoteWorkers.render??={},s.remoteWorkers.rewrite??={},s.remoteWorkers.deploy??={},s.remoteWorkers.render.enabled=s.lambdaDelegationEnabled,s.remoteWorkers.rewrite.enabled=s.lambdaDelegationEnabled,s.remoteWorkers.deploy.enabled=s.lambdaDelegationEnabled),o!==null&&(s.processingConcurrency=o,s.remoteWorkers.render??={},s.remoteWorkers.rewrite??={},s.remoteWorkers.deploy??={},s.remoteWorkers.render.concurrency=o,s.remoteWorkers.rewrite.concurrency=o,s.remoteWorkers.deploy.concurrency=o),s.deploymentProfiles={},s.defaultDeploymentProfile="",s.deploymentTargetOverride=String(s.deploymentTargetOverride??"").trim();let a=await si(s);t.onRemotePublisherConfigDiagnostic?.(a.diagnostic);let c=oi(s,a.remote),i=ii(),d=i?v.resolve(i,".."):"";return d?(c.outputDir=Bn(d,c.outputDir,"export"),c.logDir=Bn(d,c.logDir,"logs")):(v.isAbsolute(c.outputDir)||(c.outputDir=Dr(c.outputDir,"export")),v.isAbsolute(c.logDir)||(c.logDir=Dr(c.logDir,"logs"))),c}var ai=".deploy-plan.json",ci="deploy-plan.json",li=".crawl-incomplete.json",ui="crawl-incomplete.json";function Jn(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?v.resolve(e):""}function Qn(e){let t=String(e||"").replace(/\\/g,"/").replace(/^\/+/,"").trim(),r=v.posix.normalize(t);return !t||!r||r==="."||/^[a-zA-Z]:/.test(r)||r.startsWith("../")||r===".."?null:r}function di(e){let t=String(e||"").trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("*")||t.includes("#"))return null;try{let r=new URL(t,"https://content-sync.invalid");return r.origin!=="https://content-sync.invalid"?null:`${v.posix.normalize(r.pathname)}${r.search}`}catch{return null}}function Ie(e){return [...new Set(e.map(Qn).filter(t=>t!==null))]}function Gn(e,t){let r={generatedAt:String(t.generatedAt||new Date().toISOString()),outputDir:v.resolve(e.outputDir),runMode:t.runMode,crawlMode:t.crawlMode,fullSyncRequired:!!t.fullSyncRequired,changedFiles:Ie(t.changedFiles||[]),deletedFiles:Ie(t.deletedFiles||[]),rewriteTargets:Ie(t.rewriteTargets||[]),revalidateFiles:Ie(t.revalidateFiles||[])};return t.schemaVersion===2?{...r,schemaVersion:2,runMode:"content-sync",crawlMode:"incremental",fullSyncRequired:false,consumerId:String(t.consumerId||"").trim(),fromSequence:Math.max(0,Number(t.fromSequence)||0),toSequence:Math.max(0,Number(t.toSequence)||0),impactHash:String(t.impactHash||"").trim(),resolvedSitemapUrls:[...new Set((t.resolvedSitemapUrls||[]).map(n=>String(n||"").trim()).filter(n=>{try{let s=new URL(n);return s.protocol==="http:"||s.protocol==="https:"}catch{return false}}))],uploadGroups:{assets:Ie(t.uploadGroups?.assets||[]),content:Ie(t.uploadGroups?.content||[]),listings:Ie(t.uploadGroups?.listings||[]),resources:Ie(t.uploadGroups?.resources||[]),sitemapLeaves:Ie(t.uploadGroups?.sitemapLeaves||[]),sitemapIndexes:Ie(t.uploadGroups?.sitemapIndexes||[])},invalidationPaths:[...new Set((t.invalidationPaths||[]).map(di).filter(n=>n!==null))].sort()}:{schemaVersion:1,...r,runMode:t.runMode}}function pi(e){if(!e||typeof e!="object")return false;let t=e;if(t.schemaVersion===2){let r=t;return r.runMode==="content-sync"&&r.crawlMode==="incremental"&&r.fullSyncRequired===false&&typeof r.generatedAt=="string"&&typeof r.outputDir=="string"&&typeof r.consumerId=="string"&&r.consumerId.trim()!==""&&Number.isSafeInteger(r.fromSequence)&&Number.isSafeInteger(r.toSequence)&&Number(r.toSequence)>=Number(r.fromSequence)&&typeof r.impactHash=="string"&&/^[a-f0-9]{64}$/.test(r.impactHash)&&Array.isArray(r.resolvedSitemapUrls)&&Array.isArray(r.changedFiles)&&Array.isArray(r.deletedFiles)&&Array.isArray(r.rewriteTargets)&&(r.revalidateFiles===void 0||Array.isArray(r.revalidateFiles))&&!!r.uploadGroups&&Array.isArray(r.uploadGroups.assets)&&Array.isArray(r.uploadGroups.content)&&Array.isArray(r.uploadGroups.listings)&&Array.isArray(r.uploadGroups.resources)&&Array.isArray(r.uploadGroups.sitemapLeaves)&&Array.isArray(r.uploadGroups.sitemapIndexes)&&Array.isArray(r.invalidationPaths)}return t.schemaVersion===1&&typeof t.generatedAt=="string"&&typeof t.outputDir=="string"&&(t.runMode==="full"||t.runMode==="retry-timeouts"||t.runMode==="single-url")&&(t.crawlMode==="full"||t.crawlMode==="incremental")&&typeof t.fullSyncRequired=="boolean"&&Array.isArray(t.changedFiles)&&Array.isArray(t.deletedFiles)&&Array.isArray(t.rewriteTargets)&&(t.revalidateFiles===void 0||Array.isArray(t.revalidateFiles))}function qr(e){let t=v.join(v.resolve(e.outputDir),ai),r=Jn();return r?[v.join(r,ci),t]:[t]}function Wr(e){let t=v.join(v.resolve(e.outputDir),li),r=Jn();return r?[v.join(r,ui),t]:[t]}function me(e,t){let r=v.resolve(e),n=v.resolve(t),s=v.relative(r,n).replace(/\\/g,"/");return Qn(s)}async function at(e){let t=v.resolve(e.outputDir);for(let r of qr(e))try{let n=await F.readFile(r,"utf8"),s=JSON.parse(n);if(!pi(s)||v.resolve(s.outputDir)!==t)continue;return Gn(e,s)}catch{}return null}async function Nr(e,t){let r=Gn(e,t);for(let n of qr(e)){await F.mkdir(v.dirname(n),{recursive:true});let s=`${n}.${process.pid}.${Date.now()}.tmp`;await F.writeFile(s,JSON.stringify(r,null,2),"utf8"),await F.rename(s,n);}}async function Je(e){for(let t of qr(e))try{await F.unlink(t);}catch(r){if(r.code!=="ENOENT")throw r}}async function Zn(e,t){let r={schemaVersion:1,startedAt:String(t.startedAt||new Date().toISOString()),outputDir:v.resolve(e.outputDir)};for(let n of Wr(e)){await F.mkdir(v.dirname(n),{recursive:true});let s=`${n}.${process.pid}.tmp`;await F.writeFile(s,JSON.stringify(r,null,2),"utf8"),await F.rename(s,n);}}async function Yn(e){let t=v.resolve(e.outputDir);for(let r of Wr(e)){let n;try{n=await F.readFile(r,"utf8");}catch(o){if(o.code==="ENOENT")continue;throw o}let s;try{s=JSON.parse(n);}catch{throw new Error(`Invalid incomplete crawl marker: ${r}`)}if(s.schemaVersion!==1||typeof s.startedAt!="string"||typeof s.outputDir!="string"||v.resolve(s.outputDir)!==t)throw new Error(`Invalid incomplete crawl marker: ${r}`);return {schemaVersion:1,startedAt:s.startedAt,outputDir:t}}return null}async function Xn(e){for(let t of Wr(e))try{await F.unlink(t);}catch(r){if(r.code!=="ENOENT")throw r}}function Ae(e,t=10){return rs.createHash("sha1").update(e).digest("hex").slice(0,t)}async function mi(e){await F.mkdir(v.dirname(e),{recursive:true});}async function Le(e,t,r){await mi(e);let n=v.join(v.dirname(e),`.${v.basename(e)}.${process.pid}.${Date.now()}.${rs.randomBytes(6).toString("hex")}.tmp`);try{typeof t=="string"?await F.writeFile(n,t,r??"utf8"):await F.writeFile(n,t),await F.rename(n,e);}catch(s){throw await F.unlink(n).catch(()=>{}),s}}function Ee(e){return [".html",".htm",".css",".js",".mjs",".json",".xml",".xsl",".txt",".svg",".map",".enc",".jws"].includes(v.extname(e).toLowerCase())}function qe(e){return e.replace(/"/g,'"').replace(/"/g,'"').replace(/'/g,"'").replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function ct(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function Bt(e){return e.replace(/\//g,"\\/")}function es(e){return e.replace(/\//g,"\\\\/")}function gi(e){try{let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")return null;let r=t.pathname==="/"&&!t.search&&!t.hash?"":`${t.pathname}${t.search}${t.hash}`;return `//${t.host}${r}`}catch{return null}}function ts(e,t,r){if(!t)return;e[t]=r;let n=Bt(t),s=Bt(r);e[n]=s;let o=es(t),a=es(r);e[o]=a;let c=ct(t),i=ct(r);e[c]=i;let d=ct(n),l=ct(s);e[d]=l;let u=ct(o),g=ct(a);e[u]=g;}function Vt(e,t,r){ts(e,t,r);let n=gi(t);n&&n!==t&&ts(e,n,r);}function _r(e,t){let r=t.startsWith("/")?t:`/${t}`,n=(e||"").replace(/\/$/,"");return !n||n==="."||n==="/"?r:`${n}${r}`}function ns(e,t){try{return new URL(e,t==="."?"https://relative.invalid":t).pathname}catch{return e.startsWith("/")?e:`/${e.replace(/^\.\//,"")}`}}function ss(e,t,r){if(!t)return r;let n=v.dirname(v.resolve(t)),s=v.resolve(e,r.replace(/^\/+/,"")),o=v.relative(n,s).replace(/\\/g,"/");return o?(o.startsWith(".")||(o=`./${o}`),o):"."}async function Kr(e,t){return (t?[...new Set(t)].map(n=>v.resolve(n)).filter(n=>n.startsWith(v.resolve(e.outputDir))).map(n=>v.relative(e.outputDir,n).replace(/\\/g,"/")).filter(n=>n.length>0):await fi(["**/*"],{cwd:e.outputDir,onlyFiles:true,dot:true})).filter(n=>n!=="asset-map.json"&&Ee(n))}var bi=["wp-content/","wp-includes/","wp-admin/","wp-json/","_next/"],Si=new Set([".html",".htm"]),os="WPSuite.io Static Publisher",Pi=os.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function Ri(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function vi(e){return e.startsWith("//")||e.startsWith("\\/\\/")||e.startsWith("\\\\/\\\\/")}function Ci(e,t,r){return vi(t)?e.replace(new RegExp(`(?<!:)${Ri(t)}`,"g"),r):e.split(t).join(r)}function ki(e,t,r){if(e.wpsuite?.siteSettings?.subscriber===true||e.wpsuite?.subscriptionType==="PROFESSIONAL"||e.wpsuite?.subscriptionType==="AGENCY"||!r)return false;let s=v.extname(r).toLowerCase();return Si.has(s)?/<head\b|<html\b|<!doctype html/i.test(t):false}function xi(e){if(new RegExp(`<meta\\b(?=[^>]*\\bname=(["'])generator\\1)(?=[^>]*\\bcontent=(["'])${Pi}\\2)[^>]*\\/?>`,"i").test(e))return e;let t=`<meta name="generator" content="${os}" />`;if(e.match(/(\r?\n)([ \t]*)<\/head>/i))return e.replace(/(\r?\n)([ \t]*)<\/head>/i,`$1$2${t}$1$2</head>`);let n=e.includes(`\r
|
|
1
|
+
import F,{readFile}from'fs/promises';import Zo from'http';import qn from'https';import C from'path';import is,{createHash}from'crypto';import {request,chromium}from'playwright';import {gunzipSync}from'zlib';import {setTimeout as setTimeout$1}from'timers/promises';import Ri from'fast-glob';import Es from'mime-types';import {availableParallelism}from'os';import {Worker}from'worker_threads';import {LambdaClient,InvokeCommand}from'@aws-sdk/client-lambda';import {DynamoDBClient,GetItemCommand}from'@aws-sdk/client-dynamodb';import {S3Client,GetObjectCommand,PutObjectCommand,CopyObjectCommand,ListObjectsV2Command,HeadObjectCommand,DeleteObjectsCommand}from'@aws-sdk/client-s3';import {fromTemporaryCredentials}from'@aws-sdk/credential-providers';import {Upload}from'@aws-sdk/lib-storage';import {CloudFrontClient,waitUntilInvalidationCompleted,CreateInvalidationCommand}from'@aws-sdk/client-cloudfront';var Vo=new Set(["post-type","taxonomy","author","date","posts-page","listing"]);function ze(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))].sort()}function Ko(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))]}function zo(e){return new URL(e).pathname.split("/").filter(Boolean).some(r=>{try{return decodeURIComponent(r).endsWith("__trashed")}catch{return r.endsWith("__trashed")}})}function Ar(e){return Array.isArray(e)?e.map(Ar):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>[t,Ar(r)])):e}function Jo(e){return JSON.stringify(Ar(e))}function Ue(e){return createHash("sha256").update(Jo(e)).digest("hex")}function Mn(e){return Ue({schemaVersion:1,wordpressFingerprint:e.wordpressFingerprint,targetFingerprint:e.targetFingerprint,sourceOrigin:e.sourceOrigin,sitemapPaths:[...e.sitemapPaths].sort(),blockedPathPrefixes:[...e.blockedPathPrefixes].sort(),assetPathPrefixes:[...e.assetPathPrefixes].sort(),noJavaScriptRenderPathPrefixes:[...e.noJavaScriptRenderPathPrefixes].sort(),urlRewriteMode:e.urlRewriteMode})}function Er(e){let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error(`Unsupported source origin protocol: ${t.protocol}`);return t.hash="",t.search="",t.pathname=t.pathname.replace(/\/+$/,""),t.toString().replace(/\/$/,"")}function xe(e,t){Qo(t);let r=new URL(Er(e)),n=new URL(t,`${r.toString().replace(/\/$/,"")}/`);if(n.origin!==r.origin)throw new Error(`Content-sync URL is outside the source origin: ${t}`);let s=r.pathname.replace(/\/+$/,"");if(s&&n.pathname!==s&&!n.pathname.startsWith(`${s}/`))throw new Error(`Content-sync URL is outside the source site path: ${t}`);return n.hash="",n.toString()}function Qo(e){let r=String(e).split(/[?#]/,1)[0];for(let s=0;s<3;s+=1)try{let o=decodeURIComponent(r);if(o===r)break;r=o;}catch{throw new Error(`Content-sync URL has malformed encoding: ${e}`)}if(r.includes("\0")||r.includes("\\"))throw new Error(`Content-sync URL has an unsafe path: ${e}`);if(r.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]*/i,"").split("/").some(s=>s==="."||s===".."))throw new Error(`Content-sync URL has an unsafe path: ${e}`)}function Rt(e){let t=ze((e.postTypes??[]).map(n=>String(n).toLowerCase().replace(/[^a-z0-9_-]/g,"")));if(t.length===0)throw new Error("Content-sync requires at least one public post type.");let r=ze((e.listingPaths??[]).map(n=>{let s=String(n).trim();if(!s)return "";let o=new URL(s,"https://content-sync.invalid/");if(o.origin!=="https://content-sync.invalid"&&/^https?:\/\//i.test(s))throw new Error("Content-sync listing routes must be same-site paths.");let a=`/${o.pathname.replace(/^\/+|\/+$/g,"")}`;return a==="/"?"/":`${a}/`}));return {postTypes:t,listingPaths:r,includeSubsites:e.includeSubsites===true,includePostTypeArchives:e.includePostTypeArchives!==false,includeTaxonomyArchives:e.includeTaxonomyArchives!==false,includeAuthorArchives:e.includeAuthorArchives===true,includeDateArchives:e.includeDateArchives===true,includePostsPage:e.includePostsPage!==false,includeSitemapChain:e.includeSitemapChain!==false}}function jn(e,t,r){return Ue({schemaVersion:1,sourceOrigin:Er(e),ruleId:t.trim(),scope:Rt(r)})}function Fn(e){return Ue({schemaVersion:1,...e})}function Dn(e){let t=String(e.siteId??"").trim()||String(e.accountId??"").trim()||Er(e.sourceOrigin);return `content-sync:${Ue({siteIdentity:t,ruleId:e.ruleId.trim(),targetFingerprint:e.targetFingerprint}).slice(0,48)}`}function Un(e){let t=[...e].sort((s,o)=>s.sequence-o.sequence),r=new Map,n=-1;for(let s of t){if(!Number.isSafeInteger(s.sequence)||s.sequence<=n)throw new Error("Content-sync journal events are not strictly ordered.");if(n=s.sequence,!Number.isSafeInteger(s.blogId)||s.blogId<1)throw new Error("Content-sync journal event has an invalid multisite identity.");let o=`${s.blogId}:${s.postType}:${s.postId}`,a=r.get(o);if(!a){r.set(o,{postId:s.postId,blogId:s.blogId,postType:s.postType,fromSequence:s.sequence,toSequence:s.sequence,before:s.before,after:s.after,operations:[s.operation],correlationIds:s.correlationId?[s.correlationId]:[]});continue}a.toSequence=s.sequence,a.after=s.after,a.operations.push(s.operation),s.correlationId&&!a.correlationIds.includes(s.correlationId)&&a.correlationIds.push(s.correlationId);}return [...r.values()].sort((s,o)=>s.fromSequence-o.fromSequence)}function On(e){return e?.status==="publish"&&!!e.url}function Go(e,t){return e==="post-type"?t.includePostTypeArchives:e==="taxonomy"?t.includeTaxonomyArchives:e==="author"?t.includeAuthorArchives:e==="date"?t.includeDateArchives:e==="posts-page"?t.includePostsPage:e==="listing"}function $r(e){let t=Rt(e.scope),r=new Map;Un(e.events);for(let n of e.events)for(let s of [n.before,n.after])for(let o of s?.archiveFamilies??[]){if(!Vo.has(o.kind)||!Go(o.kind,t))continue;let a={...o,url:xe(e.sourceOrigin,o.url)};r.set(`${a.kind}|${a.url}`,a);}for(let n of t.listingPaths){let s=xe(e.sourceOrigin,n);r.set(`listing|${s}`,{kind:"listing",url:s});}return [...r.values()].sort((n,s)=>n.url.localeCompare(s.url))}function Ln(e){let t=Rt(e.scope),r=Un(e.events),n=new Set,s=new Set,o=new Map,a=new Map($r({events:e.events,scope:t,sourceOrigin:e.sourceOrigin}).map(g=>[`${g.kind}|${g.url}`,g]));for(let g of r){let w=g.before,m=g.after,h=On(w),y=On(m);y&&m.url&&n.add(xe(e.sourceOrigin,m.url)),h&&w.url&&(!y||w.url!==m.url)&&s.add(xe(e.sourceOrigin,w.url));}for(let g of [...e.events].sort((w,m)=>w.sequence-m.sequence)){for(let w of [g.before,g.after])for(let m of w?.resourceDeleteUrls??[])o.set(xe(e.sourceOrigin,m),"delete");for(let w of g.after?.resourceRenderUrls??[])o.set(xe(e.sourceOrigin,w),"render");}let c=[...o].filter(([,g])=>g==="render").map(([g])=>g),i=[...o].filter(([,g])=>g==="delete").map(([g])=>g),d=new Map(e.resolvedArchiveFamilies.map(g=>[`${g.kind}|${xe(e.sourceOrigin,g.url)}`,{...g,url:xe(e.sourceOrigin,g.url),pageUrls:ze(g.pageUrls.map(w=>xe(e.sourceOrigin,w)))}])),l=[...a.entries()].map(([g,w])=>{let m=d.get(g);if(!m)throw new Error(`WordPress did not resolve archive family ${g}.`);return {...w,...m}}).sort((g,w)=>g.url.localeCompare(w.url)),u=ze(l.flatMap(g=>g.pageUrls)),f=t.includeSitemapChain?Ko(e.sitemapUrls.map(g=>xe(e.sourceOrigin,g))):[],p={schemaVersion:1,generatedAt:new Date().toISOString(),jobId:e.jobId,ruleId:e.ruleId,consumerId:e.consumerId,coalesceKey:e.coalesceKey,scopeFingerprint:e.scopeFingerprint,targetFingerprint:e.targetFingerprint,baselineId:e.baselineId,fromSequence:e.fromSequence,toSequence:e.toSequence,eventCount:e.events.length,foldedCount:r.length,directRenderUrls:ze([...n]),archiveFamilyUrls:u,sitemapUrls:f,deleteUrls:ze([...s]),resourceRenderUrls:ze(c),resourceDeleteUrls:ze(i),archiveFamilies:l};return {...p,impactHash:Ue(p)}}function vt(e){let{impactHash:t,...r}=e;if(e.schemaVersion!==1||!t)throw new Error("Invalid content-sync impact plan schema.");if(!Array.isArray(e.resourceRenderUrls)||!Array.isArray(e.resourceDeleteUrls))throw new Error("Invalid content-sync resource impact contract.");if(Ue(r)!==t)throw new Error("Content-sync impact plan hash mismatch.");for(let n of [...e.directRenderUrls,...e.deleteUrls,...e.resourceRenderUrls,...e.resourceDeleteUrls])if(zo(n))throw new Error(`Content-sync impact contains a WordPress trash alias instead of the last public URL: ${n}`)}var Yo="wp-json/smartcloud-static-publisher/v1/content-sync/",Xo=25*1024*1024,qt=class extends Error{status;code;constructor(t,r,n){super(n),this.name="ContentSyncApiError",this.status=t,this.code=r;}},Wt=class{options;constructor(t){if(!t.runtimeToken.trim())throw new Error("Content-sync requires a WordPress runtime token.");this.options={...t,timeoutMs:t.timeoutMs??6e4};}endpoint(t,r="content-sync"){let n=this.options.sourceOrigin.replace(/\/+$/,"")+"/",s=r==="content-sync"?Yo:`wp-json/smartcloud-static-publisher/v1/${r}/`;return new URL(`${s}${t}`,n)}async post(t,r,n="content-sync"){let s=this.endpoint(t,n),o=Buffer.from(JSON.stringify(r),"utf8"),a=s.protocol==="https:"?qn:Zo,c=s.protocol==="https:"?new qn.Agent({rejectUnauthorized:!this.options.ignoreHttpsErrors}):void 0;return new Promise((i,d)=>{let l=a.request(s,{method:"POST",agent:c,headers:{"content-type":"application/json","content-length":String(o.byteLength),"x-static-publisher-token":this.options.runtimeToken},timeout:this.options.timeoutMs},u=>{let f=[],p=0;u.on("data",g=>{if(p+=g.byteLength,p>Xo){u.destroy(new Error("Content-sync API response exceeded the size limit."));return}f.push(g);}),u.on("error",d),u.on("end",()=>{let g=Buffer.concat(f).toString("utf8"),w;try{w=g?JSON.parse(g):{};}catch{d(new qt(u.statusCode??500,"invalid-json","Content-sync API returned invalid JSON."));return}let m=u.statusCode??500;if(m<200||m>=300){d(new qt(m,String(w.code??"request-failed"),String(w.message??`Content-sync API request failed (${m}).`)));return}i(w);});});l.on("timeout",()=>l.destroy(new Error(`Content-sync API request timed out: ${t}`))),l.on("error",d),l.end(o);})}async head(t){return this.post("head",t)}async unboundHead(t,r){return this.post("head",{postTypes:t,includeSubsites:r})}async events(t){let r=[],n=t.afterSequence,s=new Set(t.postTypes);for(;n<t.throughSequence;){let o=await this.post("events",{...t,afterSequence:n,limit:250});if(o.fromSequence!==n||o.throughSequence!==t.throughSequence||o.nextSequence<n||o.nextSequence>t.throughSequence)throw new Error("Content-sync API returned an inconsistent event page.");if(!Array.isArray(o.items))throw new Error("Content-sync API returned a malformed event page.");let a=n;for(let c of o.items){if(!Number.isSafeInteger(c.sequence)||c.sequence<=a||c.sequence>t.throughSequence||!Number.isSafeInteger(c.postId)||c.postId<=0||!Number.isSafeInteger(c.blogId)||c.blogId<=0||!s.has(c.postType)||typeof c.operation!="string"||!c.operation)throw new Error("Content-sync API returned an invalid or out-of-scope journal event.");a=c.sequence;}if(o.items.length>0&&o.nextSequence!==a)throw new Error("Content-sync API event cursor does not match the final returned event.");if(r.push(...o.items),!o.hasMore)break;if(o.nextSequence===n)throw new Error("Content-sync API event pagination did not advance.");n=o.nextSequence;}if(t.throughSequence>t.afterSequence&&r.at(-1)?.sequence!==t.throughSequence)throw new Error("Content-sync API omitted the claimed journal high-water event.");return r}async resolveImpactFamilies(t,r){let n=await this.post("impact",{families:t,includeSubsites:r});return Array.isArray(n.families)?n.families:[]}async releaseFingerprint(t=false){let r=await this.post("fingerprint",{includeSubsites:t}),n=String(r.fingerprint||"").trim();if(!/^[a-f0-9]{64}$/.test(n))throw new Error("WordPress returned an invalid release fingerprint.");return n}async establishBaseline(t){return this.post("baseline",t)}async acknowledge(t){return this.post("ack",t)}async importCookieObservations(t){return this.post("cookie-observations",t,"privacy")}};function Nt(e){let t=C.resolve(e);return {state:C.join(t,"content-sync-state.json"),current:C.join(t,"content-sync-current.json"),impact:C.join(t,"content-sync-impact-plan.json"),checkpoint:C.join(t,"content-sync-checkpoint.json"),baseline:C.join(t,"content-sync-baseline.json"),activeRules:C.join(t,"content-sync-active-rules.json"),releaseCutoff:C.join(t,"content-sync-release-cutoff.json"),candidateManifest:C.join(t,"content-sync-candidate-manifest.json"),trustedManifest:C.join(t,"crawl-manifest.json"),invalidation:C.join(t,"content-sync-invalidation.json"),deployPlan:C.join(t,"deploy-plan.json")}}async function Or(e){let t=await Ct(e.releaseCutoff);if(t===null)return {schemaVersion:1,updatedAt:"",entries:{}};let r=t;if(r.schemaVersion!==1||typeof r.updatedAt!="string"||!r.entries||typeof r.entries!="object"||Array.isArray(r.entries))throw new Error("Invalid content-sync release-cutoff store.");return r}async function Wn(e,t){await at(e.releaseCutoff,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function at(e,t){await F.mkdir(C.dirname(e),{recursive:true});let r=`${e}.${process.pid}.${Date.now()}.tmp`;await F.writeFile(r,JSON.stringify(t,null,2),"utf8"),await F.rename(r,e);}async function Ct(e){try{return JSON.parse(await F.readFile(e,"utf8"))}catch(t){if(t.code==="ENOENT")return null;throw new Error(`Invalid or unreadable content-sync state file ${e}: ${t instanceof Error?t.message:String(t)}`,{cause:t})}}async function Mr(e){let t=await Ct(e.baseline);if(t===null)return {schemaVersion:1,updatedAt:"",entries:{}};let r=t;if(r.schemaVersion!==1||typeof r.updatedAt!="string"||!r.entries||typeof r.entries!="object"||Array.isArray(r.entries))throw new Error("Invalid content-sync baseline store.");return r}async function Nn(e,t){await at(e.baseline,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function jr(e){let t=await Ct(e.current);if(t===null)return null;let r=t;if(r.schemaVersion!==1||typeof r.jobId!="string"||typeof r.phase!="string"||!Number.isSafeInteger(r.fromSequence)||!Number.isSafeInteger(r.toSequence))throw new Error("Invalid content-sync current-range state.");return r}async function _n(e,t){await at(e.current,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Bn(e){let t=await Ct(e.impact);if(t===null)return null;let r=t;return vt(r),r}async function Hn(e,t){vt(t),await at(e.impact,t);}async function Vn(e,t){await at(e.checkpoint,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function _t(e){let t=await Ct(e.state);if(t===null)return {schemaVersion:1,updatedAt:"",rules:{}};let r=t;if(r.schemaVersion!==1||typeof r.updatedAt!="string"||!r.rules||typeof r.rules!="object"||Array.isArray(r.rules))throw new Error("Invalid content-sync state store.");return r}async function Bt(e,t){await at(e.state,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Fr(e){await Promise.all([e.current,e.checkpoint].map(async t=>{try{await F.unlink(t);}catch(r){if(r.code!=="ENOENT")throw r}}));}async function Kn(e,t){let r=await jr(e);return !r||r.coalesceKey!==t?false:(await Promise.all([e.current,e.checkpoint,e.impact,e.candidateManifest,e.invalidation,e.deployPlan].map(async n=>{try{await F.unlink(n);}catch(s){if(s.code!=="ENOENT")throw s}})),true)}var Dr=["/sitemap_index.xml","/wp-sitemap.xml","/sitemap.xml"];function kt(e){let t=new Set;for(let r of [...e,...Dr]){let n=String(r||"").trim();n&&t.add(n);}return [...t]}function Ur(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function zn(e){if(!e||!/^https?:\/\//i.test(e))return false;try{return Ur(new URL(e))}catch{return false}}function Qn(e){let t=e.trim();return t==="."?".":t.replace(/\/$/,"")}function ni(e){let t=String(e??"").trim();if(!t)return "";let r=t;if(/^https?:\/\//i.test(r))try{r=new URL(r).pathname;}catch{return ""}if(r=r.split(/[?#]/,1)[0]?.replace(/\\/g,"/").trim()??"",!r)return "";let n=r.endsWith("/"),s=r.replace(/^\/+/,"").split("/").map(a=>a.replace(/[^A-Za-z0-9._-]/g,"")).filter(a=>a.length>0&&a!=="."&&a!=="..");if(s.length===0)return "";let o=`/${s.join("/")}`;return n&&C.extname(o)===""&&(o+="/"),o==="/"?"":o}function Lr(e){return !e||typeof e!="object"?{}:Object.fromEntries(Object.entries(e).map(([t,r])=>[t.trim(),String(r??"")]).filter(([t])=>t.length>0))}function si(e){if(!e||typeof e!="object")return {};let t={};for(let[r,n]of Object.entries(e)){let s=r.trim();if(!s||!n||typeof n!="object")continue;let o=n,a={};if(typeof o.targetOrigin=="string"){let i=Qn(o.targetOrigin);i&&(a.targetOrigin=i);}let c=Lr(o.extraReplacements);if(Object.keys(c).length>0&&(a.extraReplacements=c),o.s3&&typeof o.s3=="object"){let i={},d=o.s3;typeof d.bucket=="string"&&(i.bucket=d.bucket.trim()),typeof d.prefix=="string"&&(i.prefix=d.prefix.trim()),typeof d.region=="string"&&(i.region=d.region.trim()),typeof d.htmlCacheControl=="string"&&(i.htmlCacheControl=d.htmlCacheControl.trim()),typeof d.assetCacheControl=="string"&&(i.assetCacheControl=d.assetCacheControl.trim()),Object.keys(i).length>0&&(a.s3=i);}if(o.cloudFront&&typeof o.cloudFront=="object"){let i={},d=o.cloudFront;typeof d.distributionId=="string"&&(i.distributionId=d.distributionId.trim()),Array.isArray(d.invalidationPaths)&&(i.invalidationPaths=d.invalidationPaths.map(l=>String(l??"").trim()).filter(l=>l.length>0)),Object.keys(i).length>0&&(a.cloudFront=i);}t[s]=a;}return t}function Wr(e){return e==="PROFESSIONAL"||e==="AGENCY"?e:void 0}function oi(e,t){if(!e||typeof e!="object")return null;let r=e,n=r.command;if(n!=="publish"&&n!=="crawl"&&n!=="deploy"&&n!=="invalidate"&&n!=="retry-timeouts"&&n!=="url"&&n!=="content-sync")return null;let s=Number.parseInt(String(r.intervalMinutes??"0"),10);if(!Number.isFinite(s)||s<1)return null;let o=String(r.id??`${n}-${t+1}`).trim();if(!o)return null;let a=String(r.deploymentProfile??"").trim(),c=String(r.url??"").trim(),i=Array.isArray(r.postTypes)?[...new Set(r.postTypes.map(l=>String(l??"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"")).filter(Boolean))]:[],d=Array.isArray(r.listingPaths)?[...new Set(r.listingPaths.map(l=>String(l??"").trim()).filter(Boolean))]:[];return n==="content-sync"&&i.length===0?null:{id:o,enabled:r.enabled!==false,command:n,intervalMinutes:s,...n==="publish"||n==="crawl"?{crawlMode:r.crawlMode==="incremental"?"incremental":"full"}:{},...(n==="publish"||n==="deploy"||n==="invalidate"||n==="content-sync")&&a?{deploymentProfile:a}:{},...c?{url:c}:{},...i.length>0?{postTypes:i}:{},...d.length>0?{listingPaths:d}:{},...typeof r.includeSubsites=="boolean"?{includeSubsites:r.includeSubsites}:{},...typeof r.includePostTypeArchives=="boolean"?{includePostTypeArchives:r.includePostTypeArchives}:{},...typeof r.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:r.includeTaxonomyArchives}:{},...typeof r.includeAuthorArchives=="boolean"?{includeAuthorArchives:r.includeAuthorArchives}:{},...typeof r.includeDateArchives=="boolean"?{includeDateArchives:r.includeDateArchives}:{},...typeof r.includePostsPage=="boolean"?{includePostsPage:r.includePostsPage}:{},...typeof r.includeSitemapChain=="boolean"?{includeSitemapChain:r.includeSitemapChain}:{}}}function Gn(e){let t=e&&typeof e=="object"?e:{},r=Array.isArray(t.rules)?t.rules.map((n,s)=>oi(n,s)).filter(n=>!!n):[];return {enabled:t.enabled===true,timezone:typeof t.timezone=="string"&&t.timezone.trim()!==""?t.timezone.trim():"UTC",rules:r}}function ii(e){let t=e&&typeof e=="object"?e:{},r=t.render&&typeof t.render=="object"?t.render:{},n=Number(r.concurrency??0),s=Number(r.batchSize??0),o=Number(r.maxAttempts??0),a=t.rewrite&&typeof t.rewrite=="object"?t.rewrite:{},c=t.deploy&&typeof t.deploy=="object"?t.deploy:{},i=(d,l)=>({enabled:typeof d.enabled=="boolean"?d.enabled:r.enabled===true,concurrency:Math.min(100,Math.max(1,Number(d.concurrency||l.concurrency))),batchSize:Math.min(500,Math.max(1,Number(d.batchSize||l.batchSize))),maxAttempts:Math.min(5,Math.max(1,Number(d.maxAttempts||2)))});return {render:{enabled:r.enabled===true,...Number.isInteger(n)&&n>0?{concurrency:n}:{},batchSize:Number.isInteger(s)&&s>0?Math.min(20,s):5,...Number.isInteger(o)&&o>0?{maxAttempts:Math.min(5,o)}:{}},rewrite:i(a,{concurrency:8,batchSize:25}),deploy:i(c,{concurrency:8,batchSize:50})}}function ai(e){if(!e||typeof e!="object")return;let t=e,r={};for(let s of ["accountId","siteId"]){let o=t[s];typeof o=="string"&&o.trim()!==""&&(r[s]=o.trim());}let n=Number(t.lastUpdate??0);return Number.isFinite(n)&&n>0&&(r.lastUpdate=Math.floor(n)),t.subscriber===true&&(r.subscriber=true),Object.keys(r).length>0?r:void 0}function Nr(e){let t=e&&typeof e=="object"?e:{},r=String(t.accountId??"").trim(),n=String(t.siteId??"").trim(),s=t.subscriber===true,o=ai(t.siteSettings),a={...o??{},...r?{accountId:o?.accountId??r}:{},...n?{siteId:o?.siteId??n}:{},...o?.subscriber===true||s?{subscriber:true}:{}},c={},i=String(t.apiBase??"").trim();i&&(c.apiBase=i);let d=String(t.runtimeToken??t.nonce??"").trim();d&&(c.runtimeToken=d);let l=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();l&&(c.virtualAssetBaseUrl=l),Object.keys(a).length>0&&(c.siteSettings=a);let u=Wr(t.subscriptionType);return u&&(c.subscriptionType=u),c}function ci(e){try{let t=new URL(e);globalThis.location=t;}catch{}}function Zn(e){return typeof e=="string"?e:e instanceof URL?e.toString():e.url}function li(e,t){let r=new Headers(e instanceof Request?e.headers:void 0);if(t?.headers)for(let[n,s]of new Headers(t.headers).entries())r.set(n,s);return r}async function Yn(e,t,r=5){let n=new URL(Zn(e)),s=String(t?.method??(e instanceof Request?e.method:"GET")).toUpperCase(),o=n.protocol==="http:"?Zo:qn,a=li(e,t);return await new Promise((c,i)=>{let d=o.request(n,{method:s,headers:Object.fromEntries(a.entries()),...n.protocol==="https:"?{rejectUnauthorized:false}:{}},l=>{let u=[];l.on("data",f=>{u.push(Buffer.isBuffer(f)?f:Buffer.from(f));}),l.on("error",i),l.on("end",()=>{let f=l.statusCode??0,p=l.headers.location;if(r>0&&p&&[301,302,303,307,308].includes(f)){c(Yn(new URL(p,n),{method:f===303?"GET":s},r-1));return}let g=new Headers;for(let[w,m]of Object.entries(l.headers))Array.isArray(m)?g.set(w,m.join(", ")):typeof m=="string"&&g.set(w,m);c(new Response(Buffer.concat(u),{status:f,statusText:l.statusMessage??"",headers:g}));});});d.on("error",i),d.end();})}function ui(e){let t=Nr(e.wpsuite),r={...t.siteSettings??{},...t.siteSettings?.subscriber===true||t.subscriptionType==="PROFESSIONAL"||t.subscriptionType==="AGENCY"?{subscriber:true}:{}},n=String(r.accountId??"").trim(),s=String(r.siteId??"").trim(),o=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();if(e.wpsuite={...t.apiBase?{apiBase:t.apiBase}:{},...t.runtimeToken?{runtimeToken:t.runtimeToken}:{},...o?{virtualAssetBaseUrl:o}:{},...Object.keys(r).length>0?{siteSettings:r}:{},...t.subscriptionType?{subscriptionType:t.subscriptionType}:{}},!n||!s||!o)return false;ci(e.sourceOrigin);let a=globalThis,i={...a.WpSuite??{},siteSettings:r,uploadUrl:o};return t.apiBase&&(i.apiBase=t.apiBase),a.WpSuite=i,true}async function di(e){let t=String(e.wpsuite?.virtualAssetBaseUrl??e.wpsuite?.uploadUrl??"").trim();if(!ui(e)){let s=e.wpsuite?.siteSettings,o=[String(s?.accountId??"").trim()?"":"accountId",String(s?.siteId??"").trim()?"":"siteId",t?"":"virtualAssetBaseUrl"].filter(Boolean);return {remote:null,diagnostic:{status:"invalid-runtime",virtualAssetBaseUrl:t,subscriptionType:null,error:`Missing WP Suite runtime field(s): ${o.join(", ")}.`,requests:[]}}}let r=globalThis.fetch,n=[];try{typeof r=="function"&&/^https?:\/\//i.test(t)&&(globalThis.fetch=(async(i,d)=>{let l=Zn(i);if(l.startsWith(t)){let u=(()=>{try{return new URL(l).pathname}catch{return l}})();try{let f=e.ignoreHttpsErrors&&l.startsWith("https://")?await Yn(i,d):await r(i,d);return n.push({path:u,status:f.status,ok:f.ok,error:null}),f}catch(f){throw n.push({path:u,status:null,ok:!1,error:f instanceof Error?f.message:String(f)}),f}}return r(i,d)}));let{getConfig:s}=await import('@smart-cloud/wpsuite-core'),o=await s("publisher"),a=o&&typeof o=="object"?o:null,c=Wr(a?.subscriptionType);return {remote:a,diagnostic:{status:a?"loaded":"unavailable",virtualAssetBaseUrl:t,subscriptionType:c??null,error:a?null:"WP Suite publisher config loader returned no configuration.",requests:n}}}catch(s){return {remote:null,diagnostic:{status:"unavailable",virtualAssetBaseUrl:t,subscriptionType:null,error:s instanceof Error?s.message:String(s),requests:n}}}finally{typeof r=="function"&&(globalThis.fetch=r);}}function pi(e,t){let r=si(t?.deploymentProfiles),n=String(t?.defaultDeploymentProfile??"").trim(),s=r[n]?n:"",o=Wr(t?.subscriptionType),a=Nr(e.wpsuite);return {...e,scheduler:Gn(t?.scheduler),deploymentProfiles:r,defaultDeploymentProfile:s,...o?{subscriptionType:o}:{},wpsuite:{...a,...a.siteSettings||o?{siteSettings:{...a.siteSettings??{},...a.siteSettings?.subscriber===true||o==="PROFESSIONAL"||o==="AGENCY"?{subscriber:true}:{}}}:{},...o?{subscriptionType:o}:{}}}}function qr(e,t){let n=String(e||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!n)return t;let s=n.split("/").map(o=>o.trim()).filter(o=>o.length>0&&o!=="."&&o!=="..");return s.length>0?s.join("/"):t}function mi(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?C.resolve(e):""}function Jn(e,t,r){let n=String(t||"").trim();return n&&C.isAbsolute(n)?C.resolve(n):C.resolve(e,qr(n,r))}async function Ie(e,t={}){let r=String(e??"").trim()||process.env.PUBLISHER_CONFIG||"publisher.config.json",n=await F.readFile(r,"utf8"),s=JSON.parse(n);s.sourceOrigin=s.sourceOrigin.replace(/\/$/,""),s.targetOrigin=Qn(s.targetOrigin),s.ignoreHttpsErrors??=false,s.outputDir=String(s.outputDir||"export").trim()||"export",s.urlRewriteMode||=s.targetOrigin==="."?"relative":"absolute",s.noJavaScriptRenderPathPrefixes||=[],s.seedPaths||=[],s.generated404RequestPath=ni(s.generated404RequestPath),s.sitemapPaths||=[...Dr],s.allowedAssetHosts||=[],s.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],s.blockedPathPrefixes||=[],s.blockedSearchFragments||=[],s.pageCache={purgeBeforeCrawl:s.pageCache?.purgeBeforeCrawl===true};let o=Number(s.processingConcurrency)>0?Math.min(100,Math.max(1,Number(s.processingConcurrency))):null;s.concurrency=o??s.concurrency??1,s.maxPages||=0,s.extraReplacements=Lr(s.extraReplacements),s.postCrawlCopyMap=Lr(s.postCrawlCopyMap),s.logDir=String(s.logDir||"logs").trim()||"logs",s.verbose??=false,s.logLevel||=s.verbose?"debug":"info",s.s3SyncMode||="sdk-upload-delete",s.readiness||={waitForSelector:null,waitForFunction:null,timeoutMs:1500,fallbackWaitMs:1500},s.readiness.timeoutMs??=1500,s.readiness.fallbackWaitMs??=1500,s.viewport||={width:1440,height:1200},s.navigationTimeoutMs||=3e4,s.assetDownloadConcurrency=o??(Number(s.assetDownloadConcurrency)>0?Number(s.assetDownloadConcurrency):s.concurrency),s.rewriteConcurrency=o??(Number(s.rewriteConcurrency)>0?Number(s.rewriteConcurrency):s.assetDownloadConcurrency),s.wpsuite=Nr(s.wpsuite),s.scheduler=Gn(void 0),s.remoteWorkers=ii(s.remoteWorkers),typeof s.lambdaDelegationEnabled=="boolean"&&(s.remoteWorkers.render??={},s.remoteWorkers.rewrite??={},s.remoteWorkers.deploy??={},s.remoteWorkers.render.enabled=s.lambdaDelegationEnabled,s.remoteWorkers.rewrite.enabled=s.lambdaDelegationEnabled,s.remoteWorkers.deploy.enabled=s.lambdaDelegationEnabled),o!==null&&(s.processingConcurrency=o,s.remoteWorkers.render??={},s.remoteWorkers.rewrite??={},s.remoteWorkers.deploy??={},s.remoteWorkers.render.concurrency=o,s.remoteWorkers.rewrite.concurrency=o,s.remoteWorkers.deploy.concurrency=o),s.deploymentProfiles={},s.defaultDeploymentProfile="",s.deploymentTargetOverride=String(s.deploymentTargetOverride??"").trim();let a=await di(s);t.onRemotePublisherConfigDiagnostic?.(a.diagnostic);let c=pi(s,a.remote),i=mi(),d=i?C.resolve(i,".."):"";return d?(c.outputDir=Jn(d,c.outputDir,"export"),c.logDir=Jn(d,c.logDir,"logs")):(C.isAbsolute(c.outputDir)||(c.outputDir=qr(c.outputDir,"export")),C.isAbsolute(c.logDir)||(c.logDir=qr(c.logDir,"logs"))),c}var gi=".deploy-plan.json",fi="deploy-plan.json",hi=".crawl-incomplete.json",wi="crawl-incomplete.json";function Xn(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?C.resolve(e):""}function es(e){let t=String(e||"").replace(/\\/g,"/").replace(/^\/+/,"").trim(),r=C.posix.normalize(t);return !t||!r||r==="."||/^[a-zA-Z]:/.test(r)||r.startsWith("../")||r===".."?null:r}function yi(e){let t=String(e||"").trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("*")||t.includes("#"))return null;try{let r=new URL(t,"https://content-sync.invalid");return r.origin!=="https://content-sync.invalid"?null:`${C.posix.normalize(r.pathname)}${r.search}`}catch{return null}}function Te(e){return [...new Set(e.map(es).filter(t=>t!==null))]}function ts(e,t){let r={generatedAt:String(t.generatedAt||new Date().toISOString()),outputDir:C.resolve(e.outputDir),runMode:t.runMode,crawlMode:t.crawlMode,fullSyncRequired:!!t.fullSyncRequired,changedFiles:Te(t.changedFiles||[]),deletedFiles:Te(t.deletedFiles||[]),rewriteTargets:Te(t.rewriteTargets||[]),revalidateFiles:Te(t.revalidateFiles||[])};return t.schemaVersion===2?{...r,schemaVersion:2,runMode:"content-sync",crawlMode:"incremental",fullSyncRequired:false,consumerId:String(t.consumerId||"").trim(),fromSequence:Math.max(0,Number(t.fromSequence)||0),toSequence:Math.max(0,Number(t.toSequence)||0),impactHash:String(t.impactHash||"").trim(),resolvedSitemapUrls:[...new Set((t.resolvedSitemapUrls||[]).map(n=>String(n||"").trim()).filter(n=>{try{let s=new URL(n);return s.protocol==="http:"||s.protocol==="https:"}catch{return false}}))],uploadGroups:{assets:Te(t.uploadGroups?.assets||[]),content:Te(t.uploadGroups?.content||[]),listings:Te(t.uploadGroups?.listings||[]),resources:Te(t.uploadGroups?.resources||[]),sitemapLeaves:Te(t.uploadGroups?.sitemapLeaves||[]),sitemapIndexes:Te(t.uploadGroups?.sitemapIndexes||[])},invalidationPaths:[...new Set((t.invalidationPaths||[]).map(yi).filter(n=>n!==null))].sort()}:{schemaVersion:1,...r,runMode:t.runMode}}function bi(e){if(!e||typeof e!="object")return false;let t=e;if(t.schemaVersion===2){let r=t;return r.runMode==="content-sync"&&r.crawlMode==="incremental"&&r.fullSyncRequired===false&&typeof r.generatedAt=="string"&&typeof r.outputDir=="string"&&typeof r.consumerId=="string"&&r.consumerId.trim()!==""&&Number.isSafeInteger(r.fromSequence)&&Number.isSafeInteger(r.toSequence)&&Number(r.toSequence)>=Number(r.fromSequence)&&typeof r.impactHash=="string"&&/^[a-f0-9]{64}$/.test(r.impactHash)&&Array.isArray(r.resolvedSitemapUrls)&&Array.isArray(r.changedFiles)&&Array.isArray(r.deletedFiles)&&Array.isArray(r.rewriteTargets)&&(r.revalidateFiles===void 0||Array.isArray(r.revalidateFiles))&&!!r.uploadGroups&&Array.isArray(r.uploadGroups.assets)&&Array.isArray(r.uploadGroups.content)&&Array.isArray(r.uploadGroups.listings)&&Array.isArray(r.uploadGroups.resources)&&Array.isArray(r.uploadGroups.sitemapLeaves)&&Array.isArray(r.uploadGroups.sitemapIndexes)&&Array.isArray(r.invalidationPaths)}return t.schemaVersion===1&&typeof t.generatedAt=="string"&&typeof t.outputDir=="string"&&(t.runMode==="full"||t.runMode==="retry-timeouts"||t.runMode==="single-url")&&(t.crawlMode==="full"||t.crawlMode==="incremental")&&typeof t.fullSyncRequired=="boolean"&&Array.isArray(t.changedFiles)&&Array.isArray(t.deletedFiles)&&Array.isArray(t.rewriteTargets)&&(t.revalidateFiles===void 0||Array.isArray(t.revalidateFiles))}function _r(e){let t=C.join(C.resolve(e.outputDir),gi),r=Xn();return r?[C.join(r,fi),t]:[t]}function Br(e){let t=C.join(C.resolve(e.outputDir),hi),r=Xn();return r?[C.join(r,wi),t]:[t]}function me(e,t){let r=C.resolve(e),n=C.resolve(t),s=C.relative(r,n).replace(/\\/g,"/");return es(s)}async function ct(e){let t=C.resolve(e.outputDir);for(let r of _r(e))try{let n=await F.readFile(r,"utf8"),s=JSON.parse(n);if(!bi(s)||C.resolve(s.outputDir)!==t)continue;return ts(e,s)}catch{}return null}async function Hr(e,t){let r=ts(e,t);for(let n of _r(e)){await F.mkdir(C.dirname(n),{recursive:true});let s=`${n}.${process.pid}.${Date.now()}.tmp`;await F.writeFile(s,JSON.stringify(r,null,2),"utf8"),await F.rename(s,n);}}async function Qe(e){for(let t of _r(e))try{await F.unlink(t);}catch(r){if(r.code!=="ENOENT")throw r}}async function Vr(e,t){let r={schemaVersion:1,startedAt:String(t.startedAt||new Date().toISOString()),outputDir:C.resolve(e.outputDir)};for(let n of Br(e)){await F.mkdir(C.dirname(n),{recursive:true});let s=`${n}.${process.pid}.tmp`;await F.writeFile(s,JSON.stringify(r,null,2),"utf8"),await F.rename(s,n);}}async function rs(e){let t=C.resolve(e.outputDir);for(let r of Br(e)){let n;try{n=await F.readFile(r,"utf8");}catch(o){if(o.code==="ENOENT")continue;throw o}let s;try{s=JSON.parse(n);}catch{throw new Error(`Invalid incomplete crawl marker: ${r}`)}if(s.schemaVersion!==1||typeof s.startedAt!="string"||typeof s.outputDir!="string"||C.resolve(s.outputDir)!==t)throw new Error(`Invalid incomplete crawl marker: ${r}`);return {schemaVersion:1,startedAt:s.startedAt,outputDir:t}}return null}async function ns(e){for(let t of Br(e))try{await F.unlink(t);}catch(r){if(r.code!=="ENOENT")throw r}}function Ee(e,t=10){return is.createHash("sha1").update(e).digest("hex").slice(0,t)}async function Si(e){await F.mkdir(C.dirname(e),{recursive:true});}async function qe(e,t,r){await Si(e);let n=C.join(C.dirname(e),`.${C.basename(e)}.${process.pid}.${Date.now()}.${is.randomBytes(6).toString("hex")}.tmp`);try{typeof t=="string"?await F.writeFile(n,t,r??"utf8"):await F.writeFile(n,t),await F.rename(n,e);}catch(s){throw await F.unlink(n).catch(()=>{}),s}}function $e(e){return [".html",".htm",".css",".js",".mjs",".json",".xml",".xsl",".txt",".svg",".map",".enc",".jws"].includes(C.extname(e).toLowerCase())}function We(e){return e.replace(/"/g,'"').replace(/"/g,'"').replace(/'/g,"'").replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function lt(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function Ht(e){return e.replace(/\//g,"\\/")}function ss(e){return e.replace(/\//g,"\\\\/")}function Pi(e){try{let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")return null;let r=t.pathname==="/"&&!t.search&&!t.hash?"":`${t.pathname}${t.search}${t.hash}`;return `//${t.host}${r}`}catch{return null}}function os(e,t,r){if(!t)return;e[t]=r;let n=Ht(t),s=Ht(r);e[n]=s;let o=ss(t),a=ss(r);e[o]=a;let c=lt(t),i=lt(r);e[c]=i;let d=lt(n),l=lt(s);e[d]=l;let u=lt(o),f=lt(a);e[u]=f;}function Vt(e,t,r){os(e,t,r);let n=Pi(t);n&&n!==t&&os(e,n,r);}function Kr(e,t){let r=t.startsWith("/")?t:`/${t}`,n=(e||"").replace(/\/$/,"");return !n||n==="."||n==="/"?r:`${n}${r}`}function as(e,t){try{return new URL(e,t==="."?"https://relative.invalid":t).pathname}catch{return e.startsWith("/")?e:`/${e.replace(/^\.\//,"")}`}}function cs(e,t,r){if(!t)return r;let n=C.dirname(C.resolve(t)),s=C.resolve(e,r.replace(/^\/+/,"")),o=C.relative(n,s).replace(/\\/g,"/");return o?(o.startsWith(".")||(o=`./${o}`),o):"."}async function Qr(e,t){return (t?[...new Set(t)].map(n=>C.resolve(n)).filter(n=>n.startsWith(C.resolve(e.outputDir))).map(n=>C.relative(e.outputDir,n).replace(/\\/g,"/")).filter(n=>n.length>0):await Ri(["**/*"],{cwd:e.outputDir,onlyFiles:true,dot:true})).filter(n=>n!=="asset-map.json"&&$e(n))}var xi=["wp-content/","wp-includes/","wp-admin/","wp-json/","_next/"],Ii=new Set([".html",".htm"]),ls="WPSuite.io Static Publisher",Ti=ls.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function Ai(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Ei(e){return e.startsWith("//")||e.startsWith("\\/\\/")||e.startsWith("\\\\/\\\\/")}function $i(e,t,r){return Ei(t)?e.replace(new RegExp(`(?<!:)${Ai(t)}`,"g"),r):e.split(t).join(r)}function Oi(e,t,r){if(e.wpsuite?.siteSettings?.subscriber===true||e.wpsuite?.subscriptionType==="PROFESSIONAL"||e.wpsuite?.subscriptionType==="AGENCY"||!r)return false;let s=C.extname(r).toLowerCase();return Ii.has(s)?/<head\b|<html\b|<!doctype html/i.test(t):false}function Mi(e){if(new RegExp(`<meta\\b(?=[^>]*\\bname=(["'])generator\\1)(?=[^>]*\\bcontent=(["'])${Ti}\\2)[^>]*\\/?>`,"i").test(e))return e;let t=`<meta name="generator" content="${ls}" />`;if(e.match(/(\r?\n)([ \t]*)<\/head>/i))return e.replace(/(\r?\n)([ \t]*)<\/head>/i,`$1$2${t}$1$2</head>`);let n=e.includes(`\r
|
|
2
2
|
`)?`\r
|
|
3
3
|
`:`
|
|
4
|
-
`;return e.replace(/<head\b[^>]*>/i,s=>`${s}${n} ${t}`)}function
|
|
5
|
-
`,"utf8");}function
|
|
6
|
-
`,"utf8");});}enqueueJsonLine(t,r){this.enqueueTask(()=>
|
|
7
|
-
`,"utf8");});}enqueueJsonLine(t,r){this.enqueueTask(()=>
|
|
4
|
+
`;return e.replace(/<head\b[^>]*>/i,s=>`${s}${n} ${t}`)}function ji(e){let t=We(e).trim();return t.startsWith("{")||t.startsWith("[")||t.includes("\\/")||/"@context"|"@type"/.test(t)}function Fi(e,t){let r=[...new Set(t)].filter(o=>o.includes("/")&&!/\\+\//.test(o)).map(o=>[o,Ht(o)]).filter(([o,a])=>o!==a).sort((o,a)=>a[0].length-o[0].length);if(!r.length)return e;let n=o=>{let a=o;for(let[c,i]of r)a=a.split(c).join(i);return a},s=e.replace(/(<script\b[^>]*\btype=["']application\/(?:ld\+)?json["'][^>]*>)([\s\S]*?)(<\/script>)/gi,(o,a,c,i)=>`${a}${n(c)}${i}`);return s=s.replace(/(<meta\b[^>]*\bcontent=(['"]))([\s\S]*?)(\2[^>]*>)/gi,(o,a,c,i,d)=>ji(i)?`${a}${n(i)}${d}`:o),s}function Di(e,t){if(!t)return null;let r=C.dirname(C.resolve(t)),n=C.resolve(e.outputDir),s=C.relative(r,n).replace(/\\/g,"/");return s?(s.startsWith(".")||(s=`./${s}`),s.endsWith("/")?s:`${s}/`):"./"}function Ui(e,t,r){let n=Di(t,r);if(!n)return e;let s=e;for(let o of xi){let a=o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=new RegExp(`(?:\\.{1,}/)+${a}`,"g"),i=new RegExp(`(?<!\\.)/${a}`,"g");s=s.replace(c,`${n}${o}`).replace(i,`${n}${o}`);let d=o.replace(/\//g,"\\/"),l=n.replace(/\//g,"\\/"),u=d.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),f=new RegExp(`(?:\\.{1,}\\\\/)+${u}`,"g"),p=new RegExp(`(?:\\.{1,}(?:\\\\/|\\\\))+${u}`,"g"),g=new RegExp(`(?<![\\.\\\\])\\/${u}`,"g");s=s.replace(f,`${l}${d}`).replace(p,`${l}${d}`).replace(g,`${l}${d}`);}return s}function Jr(e,t,r){if(e.urlRewriteMode==="absolute")return t;let n=(()=>{try{return new URL(t,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin)}catch{return null}})(),s=n?n.pathname:as(t,e.targetOrigin),o=n?`${n.search}${n.hash}`:"";return e.urlRewriteMode==="root-relative"?`${s}${o}`:`${cs(e.outputDir,r,s)}${o}`}function zr(e,t,r,n,s){Vt(e,r,Jr(t,n,s));}function Li(e,t,r,n,s){if(!r||r===n)return;Vt(e,r,n);let o=Jr(t,r,s),a=Jr(t,n,s);Vt(e,o,a);}function Gr(e,t,r,n,s={}){let o=e,a={};zr(a,t,t.sourceOrigin,t.targetOrigin,n);for(let[i,d]of Object.entries(t.extraReplacements))zr(a,t,i,d,n);for(let[i,d]of Object.entries(r))zr(a,t,i,d,n);for(let[i,d]of Object.entries(s)){let l=r[i];!l||l===d||Li(a,t,d,l,n);}let c=Object.entries(a).sort((i,d)=>d[0].length-i[0].length);for(let[i,d]of c)o=$i(o,i,d);return t.urlRewriteMode!=="absolute"&&(o=Ui(o,t,n)),o=Fi(o,c.map(([,i])=>i)),Oi(t,o,n)&&(o=Mi(o)),o}async function qi(e,t,r,n){let s=C.join(e.outputDir,n),o=C.extname(s).toLowerCase(),a;try{a=await F.readFile(s,"utf8");}catch(d){if(d.code!=="ENOENT")throw d;return {changed:false}}let i=Gr(a,e,t,o===".js"||o===".mjs"?void 0:s,r);return i!==a?(await qe(s,i,"utf8"),{changed:true}):{changed:false}}async function Wi(e,t){return await new Promise((r,n)=>{let s=i=>{if(c(),i?.error){n(new Error(i.error));return}r({changed:!!i?.changed});},o=i=>{c(),n(i);},a=i=>{c(),i!==0&&n(new Error(`Rewrite worker exited with code ${i}.`));},c=()=>{e.off("message",s),e.off("error",o),e.off("exit",a);};e.on("message",s),e.on("error",o),e.on("exit",a),e.postMessage({file:t});})}async function Kt(e,t,r={}){let n=await Qr(e,r.files),s=0;if(n.length===0)return 0;let o=Math.max(1,Number(e.rewriteConcurrency||e.assetDownloadConcurrency||1)),a=Math.max(1,Math.min(o,n.length,availableParallelism()));await r.onStart?.({totalFiles:n.length,workerCount:a});let c=0,i=0,d=null;if(a===1){for(let u of n){let f=await qi(e,t,r.previousAssetMap??{},u);f.changed&&(s+=1),i+=1,await r.onProgress?.({index:i,totalFiles:n.length,changedTextFiles:s,file:u,changed:f.changed});}return s}let l=Array.from({length:a},async()=>{let u=new Worker(new URL("./rewrite-worker.js",import.meta.url),{workerData:{config:e,assetMap:t,previousAssetMap:r.previousAssetMap??{}}});try{for(;!d;){let f=c;if(f>=n.length)return;c+=1;let p=n[f],g=await Wi(u,p);g.changed&&(s+=1),i+=1,await r.onProgress?.({index:i,totalFiles:n.length,changedTextFiles:s,file:p,changed:g.changed});}}catch(f){throw d=f instanceof Error?f:new Error(String(f)),d}finally{await u.terminate().catch(()=>{});}});return await Promise.all(l),s}var Me={error:0,warn:1,info:2,debug:3},Ni=/^(?:authorization|proxyAuthorization|runtimeToken|siteKey|nonce|accessToken|refreshToken|accessKeyId|secretAccessKey|sessionToken|xStaticPublisherToken|xApiKey)$/i;function et(e){return e.replace(/((?:x-static-publisher-token|authorization|proxy-authorization|x-api-key|aws-access-key-id|aws-secret-access-key|aws-session-token)\s*:\s*)[^\r\n]+/gi,"$1[REDACTED]").replace(/\b(Basic|Bearer)\s+[^\s]+/gi,"$1 [REDACTED]").replace(/([?&](?:token|access_token|refresh_token|api_key|key|nonce)=)[^&\s]+/gi,"$1[REDACTED]").replace(/((?:"|')?(?:runtimeToken|siteKey|nonce|accessToken|refreshToken|accessKeyId|secretAccessKey|sessionToken)(?:"|')?\s*[:=]\s*(?:"|'))[^"']+/gi,"$1[REDACTED]")}function Jt(e){return typeof e=="string"?et(e):Array.isArray(e)?e.map(t=>Jt(t)):e instanceof Error?{name:e.name,message:et(e.message),...e.stack?{stack:et(e.stack)}:{}}:e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Ni.test(t)?"[REDACTED]":Jt(r)])):e}function Gt(e){return e?Jt(e):void 0}var us=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",zt=us?C.join(us,"current-progress.json"):"",ds=Promise.resolve();function ps(e){return e.includes("crawl")?"crawl":e.includes("deploy")?"deploy":e.includes("invalidate")?"invalidate":e}function _i(e,t){let r={...e},n=typeof e.phase=="string"?e.phase.trim():"",s=typeof t.phase=="string"?t.phase.trim():"";if(s!==""&&(s==="deploy"||s.startsWith("deploy-"))&&n!==s)for(let c of ["index","totalFiles","staged","uploaded","skipped","failed","deleted","workerCount","completedBatches","totalBatches"])delete r[c];let a=new Set(["pagesQueued","pagesRendered","assetsQueued","sitemapsQueued","pagesDiscovered","assetsDiscovered","sitemapsDiscovered","pagesSaved","assetsSaved","donePages","doneAssets","doneSitemaps","changedTextFiles","uploaded","failed","index","totalFiles","completedBatches","totalBatches","pageQueue","assetQueue","sitemapQueue"]);for(let[c,i]of Object.entries(t)){let d=r[c];if(typeof d=="number"&&typeof i=="number"&&a.has(c)){r[c]=Math.max(d,i);continue}r[c]=i;}return r}function ms(e,t,r){zt&&(ds=ds.then(async()=>{let n=new Date,s=n.toISOString();await F.mkdir(C.dirname(zt),{recursive:true});let o=await F.readFile(zt,"utf8").then(h=>JSON.parse(h)).catch(()=>null),a=o&&typeof o.details=="object"&&o.details?o.details:{},c=ps(e),i=o?.currentStep||ps(o?.source||""),d=o?.startedAt||s,l={...o?.stepDurationsSec??{}},u=o?.stepStartedAt||s;if(i&&i!==c&&o?.stepStartedAt){let h=Math.max(0,Math.round((n.getTime()-new Date(o.stepStartedAt).getTime())/1e3));l[i]=(l[i]??0)+h,u=s;}let f=Math.max(0,Math.round((n.getTime()-new Date(u).getTime())/1e3)),p=Math.max(0,Math.round((n.getTime()-new Date(d).getTime())/1e3)),g=et(t),w=Gt(r)??{},m={checkedAt:s,source:e,message:g,details:_i(a,w),startedAt:d,currentStep:c,stepStartedAt:u,stepElapsedSec:f,totalElapsedSec:p,stepDurationsSec:l};await F.writeFile(zt,JSON.stringify(m,null,2),"utf8");}).catch(()=>{}));}async function gs(e,t){await F.mkdir(C.dirname(e),{recursive:true}),await F.appendFile(e,`${JSON.stringify(Jt(t))}
|
|
5
|
+
`,"utf8");}function Bi(e,t){let r=typeof t?.phase=="string"?t.phase.trim():"";return r||(e==="page"?"render-pages":e==="asset"?"download-assets":e==="sitemap"?"discovery":e==="timing"&&typeof t?.name=="string"&&t.name.trim()||"crawl")}function Hi(e,t,r){let n=Gt(r);return {checkedAt:new Date().toISOString(),currentStep:Bi(e,n),level:e,message:et(t),details:n??{}}}var ut=class{constructor(t,r,n="info"){this.logDir=t;this.logFile=r;this.level=n;this.ensureLogFileReady();}logDir;logFile;level;startedAt=Date.now();marks=new Map;initPromise=null;writeQueue=Promise.resolve();writeError=null;get logPath(){return C.join(this.logDir,this.logFile)}artifactPath(t){return this.logFile.endsWith(".log.jsonl")?C.join(this.logDir,this.logFile.replace(/\.log\.jsonl$/u,`${t}.jsonl`)):C.join(this.logDir,`${this.logFile}${t}.jsonl`)}get errorsPath(){return this.artifactPath(".errors")}get rejectedPath(){return this.artifactPath(".rejected")}ensureLogFileReady(){return this.initPromise||(this.initPromise=(async()=>{await F.mkdir(this.logDir,{recursive:true}),await F.writeFile(this.logPath,"","utf8");})()),this.initPromise}enqueueTask(t){this.writeQueue=this.writeQueue.then(t).catch(r=>{this.writeError=r instanceof Error?r:new Error(String(r));});}enqueueLine(t){this.enqueueTask(async()=>{await this.ensureLogFileReady(),await F.appendFile(this.logPath,`${t}
|
|
6
|
+
`,"utf8");});}enqueueJsonLine(t,r){this.enqueueTask(()=>gs(t,r));}accepts(t){return Me[t]<=Me[this.level]}push(t,r,n){if(!this.accepts(t))return;let s=et(r),o=Gt(n),a=JSON.stringify({time:new Date().toISOString(),level:t,message:s,...o||{}});this.enqueueLine(a),t==="error"?console.error(`[ERROR] ${s}`,o?JSON.stringify(o):""):t==="warn"?console.warn(`[WARN] ${s}`,o?JSON.stringify(o):""):console.log(`[${t.toUpperCase().padEnd(5)}] ${s}`);}info(t,r){this.push("info",t,r);}progress(t,r){ms(this.logFile,t,r);}debug(t,r){this.push("debug",t,r);}warn(t,r){this.push("warn",t,r);}reject(t,r,n,s,o){let a={kind:t,url:r,reason:n,...s?{source:s}:{},...o||{}};this.enqueueJsonLine(this.rejectedPath,a),this.accepts("debug")&&this.push("debug",`Rejected ${t} ${r}: ${n}`,a);}error(t,r){this.enqueueJsonLine(this.errorsPath,{message:t,...r||{}}),this.push("error",t,r);}mark(t){this.marks.set(t,Date.now());}endMark(t,r){let n=this.marks.get(t);if(!n)return;let s=Date.now()-n,o=Number((s/1e3).toFixed(2));this.push("info",`Timing ${t}: ${o}s`,{name:t,ms:s,seconds:o,...r||{}});}async flush(){let t=Date.now()-this.startedAt,r=Number((t/1e3).toFixed(2));if(this.push("info",`Total time: ${r}s`,{name:"total",ms:t,seconds:r}),await this.writeQueue,this.writeError)throw this.writeError}},Qt=class{constructor(t,r="info"){this.logDir=t;this.level=typeof r=="boolean"?r?"debug":"info":r,this.ensureLogFileReady();}logDir;startedAt=Date.now();marks=new Map;initPromise=null;writeQueue=Promise.resolve();writeError=null;level;get logPath(){return C.join(this.logDir,"crawl.log.jsonl")}get currentEventPath(){return C.join(this.logDir,"current-crawl-event.json")}get rejectedPath(){return C.join(this.logDir,"rejected.jsonl")}get ignoredPath(){return C.join(this.logDir,"ignored.jsonl")}get skippedPath(){return C.join(this.logDir,"skipped-http.jsonl")}get errorsPath(){return C.join(this.logDir,"errors.jsonl")}get timingsPath(){return C.join(this.logDir,"timings.jsonl")}ensureLogFileReady(){return this.initPromise||(this.initPromise=(async()=>{await F.mkdir(this.logDir,{recursive:true}),await F.writeFile(this.logPath,"","utf8");})()),this.initPromise}enqueueTask(t){this.writeQueue=this.writeQueue.then(t).catch(r=>{this.writeError=r instanceof Error?r:new Error(String(r));});}enqueueLine(t){this.enqueueTask(async()=>{await this.ensureLogFileReady(),await F.appendFile(this.logPath,`${t}
|
|
7
|
+
`,"utf8");});}enqueueJsonLine(t,r){this.enqueueTask(()=>gs(t,r));}updateCurrentEvent(t,r,n){let s=Hi(t,r,n);this.enqueueTask(async()=>{await F.mkdir(this.logDir,{recursive:true}),await F.writeFile(this.currentEventPath,JSON.stringify(s,null,2),"utf8");});}push(t,r,n){let s=et(r),o=Gt(n),a=JSON.stringify({time:new Date().toISOString(),level:t,message:s,...o||{}});this.enqueueLine(a),this.updateCurrentEvent(t,s,o),t==="error"?console.error(s,o||""):t==="warn"?console.warn(s,o||""):(Me[this.level]>=Me.debug||["summary","page","sitemap","asset","timing"].includes(t))&&console.log(s);}info(t,r){this.push("info",t,r);}debug(t,r){Me[this.level]<Me.debug||this.push("debug",t,r);}progress(t,r){ms("crawl.log.jsonl",t,r),this.updateCurrentEvent("progress",t,r);}checkpoint(t,r){this.updateCurrentEvent("checkpoint",t,r);}page(t,r){this.push("page",t,r);}sitemap(t,r){this.push("sitemap",t,r);}asset(t,r){this.push("asset",t,r);}warn(t,r){this.push("warn",t,r);}error(t,r){this.enqueueJsonLine(this.errorsPath,{message:t,...r||{}}),this.push("error",t,r);}summary(t,r){this.push("summary",t,r);}mark(t){this.marks.set(t,Date.now());}endMark(t,r){let n=this.marks.get(t);if(!n)return;let s=Date.now()-n,o={name:t,ms:s,seconds:Number((s/1e3).toFixed(2)),...r||{}};this.enqueueJsonLine(this.timingsPath,o),this.push("timing",`Timing ${t}: ${o.seconds}s`,o);}reject(t,r,n,s){let o={kind:t,url:r,reason:n,source:s};this.enqueueJsonLine(this.rejectedPath,o),Me[this.level]>=Me.debug&&this.push("reject",`Rejected ${t} ${r}: ${n}`,o);}ignore(t,r,n,s){let o={kind:t,url:r,reason:n,source:s};this.enqueueJsonLine(this.ignoredPath,o),Me[this.level]>=Me.debug&&this.push("ignore",`Ignored ${t} ${r}: ${n}`,o);}skip(t,r,n,s){let o={kind:t,url:r,status:n,source:s};this.enqueueJsonLine(this.skippedPath,o),this.push("warn",`Skipped ${t} ${r}: HTTP ${n}`,o);}async flush(){let t=Date.now()-this.startedAt,r={name:"total",ms:t,seconds:Number((t/1e3).toFixed(2))};if(this.enqueueJsonLine(this.timingsPath,r),await this.writeQueue,this.writeError)throw this.writeError}};var fs="(?:css|js|mjs|json|map|xml|xsl|rss|atom|txt|enc|jws|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|pdf|mp4|webm)";function ws(e){let t=new RegExp(`(?:https?:)?//[^\\s'"<>\\);]+\\.${fs}(?:[?#][^\\s'"<>\\);]*)?(?=[\\s'"<>\\);]|$)|(?<![A-Za-z0-9._-])/[^\\s'"<>\\);]+\\.${fs}(?:[?#][^\\s'"<>\\);]*)?(?=[\\s'"<>\\);]|$)`,"gi");return [...e.matchAll(t)].map(r=>r[0])}function hs(e){return !!e&&/^(?:\.{1,2}\/)?[A-Za-z0-9@_][A-Za-z0-9@._/-]*\.(?:js|mjs)(?:[?#][^\s<>\\]*)?$/i.test(e)&&!e.startsWith("/")&&!e.startsWith("//")&&!/^[a-z][a-z0-9+.-]*:/i.test(e)&&!/(?:^|\/)node_modules(?:\/|$)|(?:^|\/)\.pnpm(?:\/|$)/i.test(e)}function ys(e){let t=new Set,r=[],n=/\bimport\s*\(\s*["'`]([^"'`\s<>\\]+)["'`]\s*\)/g,s=/\b(?:[A-Za-z_$][\w$]*\.)?u\s*=\s*(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>\s*["'`]([^"'`\s<>\\]+)["'`]/g;for(let o of e.matchAll(n))o[1]&&hs(o[1])&&r.push({index:o.index??0,value:o[1]});for(let o of e.matchAll(s))o[1]&&hs(o[1])&&r.push({index:o.index??0,value:o[1]});for(let o of r.sort((a,c)=>a.index-c.index))t.add(o.value);return [...t]}function bs(e,t){let r=C.relative(t,e);return r===""||!r.startsWith("..")&&!C.isAbsolute(r)}function Ss(e,t,r,n){let s=C.resolve(e),o=C.resolve(t),a=C.extname(s).toLowerCase();return !bs(s,o)||a!==".html"&&a!==".htm"||r.has(s)?false:!n.some(c=>bs(s,C.resolve(c)))}function Zr(e,t){return typeof e=="string"&&e.length>0&&t?.supported===true&&typeof t.token=="string"&&t.token.length>0&&e===t.token}function Yr(e,t){try{let r=new URL(e),n=new URL(t,r);if(n.origin!==r.origin)return !1;let s=r.pathname.replace(/\/+$/,"");if(s&&n.pathname!==s&&!n.pathname.startsWith(`${s}/`))return !1;let o=s?n.pathname.slice(s.length)||"/":n.pathname;return ["/wp-includes/","/wp-content/plugins/","/wp-content/themes/","/wp-content/mu-plugins/"].some(a=>o.startsWith(a))}catch{return false}}function Ps(e){return e<1}function Rs(e){let t=String(e??"").toLowerCase();return t==="strict"?"Strict":t==="lax"?"Lax":t==="none"?"None":"Unspecified"}function Ki(e){let t=e.pathname||"/";if(!t.startsWith("/")||t==="/")return "/";let r=t.lastIndexOf("/");return r<=0?"/":t.slice(0,r)}function It(e){return `${e.name.toLowerCase()}
|
|
8
8
|
${e.domain.toLowerCase()}
|
|
9
|
-
${e.path}`}function
|
|
10
|
-
`,{encoding:"utf8",mode:384}),await F.rename(r,e);}function It(e){let t=e;for(let n=0;n<3;n+=1){if(/%(?:2f|5c)/i.test(t))return null;try{let s=decodeURIComponent(t);if(s===t)break;t=s;}catch{return null}}return t.includes("\0")||t.includes("\\")||t.split("/").some(n=>n==="."||n==="..")?null:t}function Tt(e,t){let r=It(t);if(r===null)throw new Error(`Unsafe output URL pathname: ${t}`);let n=v.resolve(e),s=v.resolve(n,r.replace(/^\/+/,""));if(s!==n&&!s.startsWith(`${n}${v.sep}`))throw new Error(`Output path escapes configured root: ${t}`);return s}var Z=1,Ps=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function ne(e,t){let r=String(e??"").trim();if(!Ps.test(r))throw new Error(`${t} must match ${Ps.source} and be at most 128 characters.`);return r}function Rs(e){let t=String(e??"").trim().replace(/^\/+|\/+$/g,"");if(!t)return "";let r=t.split("/").filter(Boolean);if(r.some(n=>n==="."||n===".."))throw new Error("S3 prefix contains an unsafe dot path segment.");return `${r.join("/")}/`}function dt(e,...t){let r=Rs(e),n=t.map((s,o)=>{let a=String(s??"").replace(/^\/+|\/+$/g,"");if(!a||a.split("/").some(c=>c==="."||c===".."))throw new Error(`Unsafe S3 key segment at index ${o}.`);return a});return `${r}${n.join("/")}`}function Re(e){return createHash("sha256").update(e).digest("hex")}function We(e,t){let r=String(e??"").replace(/^\/+/,""),n=Rs(t);if(!r||r.includes("\0"))throw new Error("S3 object key is empty or invalid.");if(n&&!r.startsWith(n))throw new Error(`S3 object key is outside the configured workspace prefix: ${r}`);if(r.split("/").some(s=>s===".."))throw new Error("S3 object key contains an unsafe parent segment.");return r}function ae(e,t,{optional:r=false}={}){if(!(r&&(e==null||e===""))){if(typeof e!="string"||!e.trim())throw new Error(`${t} must be a non-empty string.`);return e.trim()}}function Yi(e){if(!e||typeof e!="object")throw new Error("Remote worker config must be a JSON object.");let t=e;if(t.schemaVersion!==1)throw new Error(`Unsupported remote worker config version: ${String(t.schemaVersion)}.`);if(t.protocolVersion!==Z)throw new Error(`Remote worker protocol mismatch: expected ${Z}, received ${String(t.protocolVersion)}.`);let r=t.workspace,n=t.functions;if(!r||!n)throw new Error("Remote worker config requires workspace and functions objects.");return {schemaVersion:1,region:ae(t.region,"region"),...ae(t.roleArn,"roleArn",{optional:true})?{roleArn:ae(t.roleArn,"roleArn")}:{},...ae(t.roleSessionName,"roleSessionName",{optional:true})?{roleSessionName:ae(t.roleSessionName,"roleSessionName")}:{},workspace:{bucket:ae(r.bucket,"workspace.bucket"),prefix:String(r.prefix??"")},...t.status&&typeof t.status=="object"?{status:{tableName:ae(t.status.tableName,"status.tableName")}}:{},functions:{render:ae(n.render,"functions.render"),...ae(n.asset,"functions.asset",{optional:true})?{asset:ae(n.asset,"functions.asset")}:{},rewrite:ae(n.rewrite,"functions.rewrite"),"deploy-copy":ae(n["deploy-copy"],"functions.deploy-copy")},targets:Array.isArray(t.targets)?t.targets.map((s,o)=>{if(!s||typeof s!="object")throw new Error(`targets[${o}] must be an object.`);let a=s;return {id:ae(a.id,`targets[${o}].id`),bucketName:ae(a.bucketName,`targets[${o}].bucketName`),prefix:String(a.prefix??""),region:ae(a.region,`targets[${o}].region`)}}):[],protocolVersion:Z}}async function Yt(e){let t=v.resolve(e);try{return Yi(JSON.parse(await readFile(t,"utf8")))}catch(r){throw new Error(`Unable to load remote worker config ${t}: ${r instanceof Error?r.message:String(r)}`,{cause:r})}}var pt=class{config;lambda;s3;dynamodb;#e;constructor(t,r={},n={}){this.config=t;let s=t.roleArn?fromTemporaryCredentials({params:{RoleArn:t.roleArn,RoleSessionName:t.roleSessionName??"publisher-exporter-remote-worker"},clientConfig:{region:t.region}}):void 0;this.lambda=new LambdaClient({region:t.region,...s?{credentials:s}:{},...r}),this.s3=new S3Client({region:t.region,...s?{credentials:s}:{}}),this.dynamodb=t.status?new DynamoDBClient({region:t.region,...s?{credentials:s}:{}}):null,this.#e=n;}async#n(t){if(!this.dynamodb||!this.config.status)return null;let n=(await this.dynamodb.send(new GetItemCommand({TableName:this.config.status.tableName,ConsistentRead:true,Key:{jobId:{S:t.jobId},taskId:{S:t.taskId}}}))).Item;if(!n)return null;let s=n.operation?.S,o=n.status?.S;return !s||!["render","asset","rewrite","deploy-copy"].includes(s)||!o||!["running","succeeded","partial","failed"].includes(o)?null:{jobId:n.jobId?.S??t.jobId,taskId:n.taskId?.S??t.taskId,operation:s,status:o,completedItems:Number(n.completedItems?.N??0),failedItems:Number(n.failedItems?.N??0),totalItems:Number(n.totalItems?.N??0),sequence:Number(n.sequence?.N??0),updatedAt:n.updatedAt?.S??new Date(0).toISOString(),requestId:n.requestId?.S??null}}async#t(t,r){let n=this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify(t),"utf8")}));if(t.operation==="health"||!this.dynamodb||!this.#e.onProgress)return await n;let s=false,o=n.finally(()=>{s=true;}),a=Math.max(500,Math.min(3e4,this.#e.progressPollIntervalMs??2e3)),c=-1;for(;!s;){await Promise.race([o.then(()=>{},()=>{}),new Promise(i=>setTimeout(i,a))]);try{let i=await this.#n(t);i&&i.sequence>c&&(c=i.sequence,await this.#e.onProgress(i));}catch(i){await this.#e.onProgressError?.(i instanceof Error?i:new Error(String(i)));}}return await o}async invoke(t){let r=t.operation==="health"?this.config.functions.render:this.config.functions[t.operation];if(!r)throw new Error(`Remote worker configuration does not provide a ${t.operation} function. Redeploy the Lambda workers and reinstall remote-workers.json.`);let n=await this.#t(t,r),s=n.Payload?JSON.parse(new TextDecoder().decode(n.Payload)):null;if(n.FunctionError)throw new Error(`Remote ${t.operation} worker failed (${n.FunctionError}): ${JSON.stringify(s)}`);if(!s||typeof s!="object")throw new Error(`Remote ${t.operation} worker returned no JSON response.`);let o=s;if(o.schemaVersion!==Z||o.operation!==t.operation||o.jobId!==t.jobId||o.taskId!==t.taskId)throw new Error(`Remote ${t.operation} worker returned a mismatched response.`);return o}async readResult(t){if(!t.resultKey)throw new Error(`Remote ${t.operation} response does not contain a resultKey.`);let r=We(t.resultKey,this.config.workspace.prefix),n=await this.s3.send(new GetObjectCommand({Bucket:this.config.workspace.bucket,Key:r}));if(!n.Body)throw new Error(`Remote worker result has no body: ${r}`);return JSON.parse(await n.Body.transformToString("utf8"))}async readObject(t){if(t.bucket!==this.config.workspace.bucket)throw new Error(`Remote worker object bucket mismatch: ${t.bucket}.`);let r=We(t.key,this.config.workspace.prefix),n=await this.s3.send(new GetObjectCommand({Bucket:this.config.workspace.bucket,Key:r,...t.versionId?{VersionId:t.versionId}:{}}));if(!n.Body)throw new Error(`Remote worker object has no body: ${r}`);let s=await n.Body.transformToByteArray();if(s.byteLength!==t.bytes)throw new Error(`Remote worker object length mismatch for ${r}: expected ${t.bytes}, received ${s.byteLength}.`);if(Re(s)!==t.sha256)throw new Error(`Remote worker object checksum mismatch for ${r}.`);return s}async readObjectText(t){return new TextDecoder("utf8",{fatal:true}).decode(await this.readObject(t))}async health(t){let r=this.config.functions[t];if(!r)throw new Error(`Remote worker configuration does not provide a ${t} function.`);let n=`${t}-${Date.now()}`,s=await this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify({schemaVersion:Z,operation:"health",jobId:"health",taskId:n}),"utf8")})),o=s.Payload?JSON.parse(new TextDecoder().decode(s.Payload)):null;if(s.FunctionError||!o||typeof o!="object")throw new Error(`Remote ${t} health check failed: ${JSON.stringify(o)}`);return o}async writeWorkspaceObject(t){let r=We(t.key,this.config.workspace.prefix),n=typeof t.body=="string"?Buffer.from(t.body,"utf8"):t.body,s=Re(n),o=await this.s3.send(new PutObjectCommand({Bucket:this.config.workspace.bucket,Key:r,Body:n,ContentType:t.contentType,...t.cacheControl?{CacheControl:t.cacheControl}:{},Metadata:{sha256:s,...t.metadata??{}}}));return {bucket:this.config.workspace.bucket,key:r,sha256:s,bytes:n.byteLength,contentType:t.contentType,...o.ETag?{etag:o.ETag}:{},...o.VersionId?{versionId:o.VersionId}:{}}}async copyWorkspaceObject(t,r){if(t.bucket!==this.config.workspace.bucket)throw new Error(`Remote worker object bucket mismatch: ${t.bucket}.`);let n=We(t.key,this.config.workspace.prefix),s=We(r,this.config.workspace.prefix),o=`${t.bucket}/${n.split("/").map(c=>encodeURIComponent(c)).join("/")}`,a=await this.s3.send(new CopyObjectCommand({Bucket:t.bucket,Key:s,CopySource:o,MetadataDirective:"COPY"}));return {...t,key:s,...a.CopyObjectResult?.ETag?{etag:a.CopyObjectResult.ETag}:{},...a.VersionId?{versionId:a.VersionId}:{}}}};function Xi(e,t,r){if(!e||typeof e!="object")throw new Error("Remote render result must be a JSON object.");let n=e;if(n.schemaVersion!==Z||!n.response||n.response.operation!=="render"||n.response.jobId!==t.jobId||n.response.taskId!==t.taskId||!n.detail||!Array.isArray(n.detail.pages)||n.detail.pages.length!==r.length)throw new Error("Remote render result has an invalid envelope.");for(let[s,o]of r.entries())if(n.detail.pages[s]?.requestedUrl!==o)throw new Error("Remote render result does not match the requested URLs.");return n}function Zr(e){return e instanceof Error?e.message:String(e)}var Xt=class{#e;#n;#t;#s;#c;#l;#r=[];#u=0;#o=0;#i=false;constructor(t){this.#e=t.client,this.#n=ne(t.jobId,"jobId"),this.#t=Math.max(1,Math.min(5,t.maxAttempts??2)),this.#s=t.onRetry,this.#c=Math.max(1,Math.min(20,t.batchSize??1)),this.#l=Math.max(1,Math.min(100,t.maxConcurrentBatches??1));}async renderBatch(t){let r=[...new Set(t.urls)];if(r.length<1||r.length>20)throw new Error("Remote render batches require between 1 and 20 unique URLs.");let n=new Map,s=new Map,o=r;for(let a=1;a<=this.#t&&o.length>0;a+=1){this.#u+=1;let c=ne(`render-${this.#u}-${Re(o.join(`
|
|
11
|
-
`)).slice(0,24)}-a${
|
|
12
|
-
`)).slice(0,24)}-a${s}`,"taskId");try{let a=await this.#e.invoke({schemaVersion:
|
|
13
|
-
`)).slice(0,16)}`,"taskId"),
|
|
14
|
-
`)).slice(0,16)}`,"taskId");try{let x=await n.client.invoke({schemaVersion:
|
|
15
|
-
`,"utf8");}async function
|
|
16
|
-
${r}`,40),tokenSource:t.tokenSource?`${t.tokenSource}+site-subscriber`:"site-subscriber"}}async function
|
|
9
|
+
${e.path}`}function vs(e,t){let r;try{r=new URL(t);}catch{return null}let n=e.split(";"),s=n.shift()?.trim()??"",o=s.indexOf("=");if(o<=0)return null;let a=s.slice(0,o).trim();if(!a||[...a].some(w=>w<=" "||"=;,".includes(w)))return null;let c=r.hostname.toLowerCase(),i=Ki(r),d=null,l=true,u=false,f=false,p="Unspecified",g=false;for(let w of n){let m=w.indexOf("="),h=(m<0?w:w.slice(0,m)).trim().toLowerCase(),y=m<0?"":w.slice(m+1).trim();if(h==="domain"&&y)c=y.toLowerCase();else if(h==="path"&&y.startsWith("/"))i=y;else if(h==="expires"){let b=Date.parse(y);Number.isFinite(b)&&(d=Math.floor(b/1e3),l=false);}else if(h==="max-age"&&/^-?\d+$/u.test(y)){let b=Number.parseInt(y,10);d=Math.floor(Date.now()/1e3)+b,l=false;}else h==="secure"?u=true:h==="httponly"?f=true:h==="samesite"?p=Rs(y):h==="partitioned"&&(g=true);}return {name:a,domain:c,path:i,expires:d,session:l,secure:u,httpOnly:f,sameSite:p,partitioned:g}}function zi(e){let t=!Number.isFinite(e.expires)||e.expires<=0;return {name:e.name,domain:e.domain.toLowerCase(),path:e.path||"/",expires:t?null:e.expires,session:t,secure:e.secure,httpOnly:e.httpOnly,sameSite:Rs(e.sameSite),partitioned:e.partitioned===true}}function Cs(e,t){let r=new Map(e.map(n=>[It(n),n.value]));return t.filter(n=>r.get(It(n))!==n.value).map(zi)}function Ji(e,t){let r=e.session||t.session;return {...e,expires:r?null:Math.max(e.expires??0,t.expires??0)||null,session:r,secure:e.secure&&t.secure,httpOnly:e.httpOnly&&t.httpOnly,sameSite:e.sameSite===t.sameSite?e.sameSite:"Unspecified",partitioned:e.partitioned&&t.partitioned}}var Zt=class{#e=new Map;add(t){if(!t)return;let r={...t,domain:t.domain.toLowerCase(),path:t.path||"/"},n=It(r),s=this.#e.get(n);this.#e.set(n,s?Ji(s,r):r);}addAll(t){for(let r of t)this.add(r);}artifact(){return {schemaVersion:1,observations:[...this.#e.values()].sort((t,r)=>It(t).localeCompare(It(r)))}}};async function Yt(e,t){await F.mkdir(C.dirname(e),{recursive:true});let r=`${e}.${process.pid}.tmp`;await F.writeFile(r,`${JSON.stringify(t,null,2)}
|
|
10
|
+
`,{encoding:"utf8",mode:384}),await F.rename(r,e);}function Tt(e){let t=e;for(let n=0;n<3;n+=1){if(/%(?:2f|5c)/i.test(t))return null;try{let s=decodeURIComponent(t);if(s===t)break;t=s;}catch{return null}}return t.includes("\0")||t.includes("\\")||t.split("/").some(n=>n==="."||n==="..")?null:t}function At(e,t){let r=Tt(t);if(r===null)throw new Error(`Unsafe output URL pathname: ${t}`);let n=C.resolve(e),s=C.resolve(n,r.replace(/^\/+/,""));if(s!==n&&!s.startsWith(`${n}${C.sep}`))throw new Error(`Output path escapes configured root: ${t}`);return s}var ee=1,ks=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function ne(e,t){let r=String(e??"").trim();if(!ks.test(r))throw new Error(`${t} must match ${ks.source} and be at most 128 characters.`);return r}function xs(e){let t=String(e??"").trim().replace(/^\/+|\/+$/g,"");if(!t)return "";let r=t.split("/").filter(Boolean);if(r.some(n=>n==="."||n===".."))throw new Error("S3 prefix contains an unsafe dot path segment.");return `${r.join("/")}/`}function pt(e,...t){let r=xs(e),n=t.map((s,o)=>{let a=String(s??"").replace(/^\/+|\/+$/g,"");if(!a||a.split("/").some(c=>c==="."||c===".."))throw new Error(`Unsafe S3 key segment at index ${o}.`);return a});return `${r}${n.join("/")}`}function ve(e){return createHash("sha256").update(e).digest("hex")}function Ne(e,t){let r=String(e??"").replace(/^\/+/,""),n=xs(t);if(!r||r.includes("\0"))throw new Error("S3 object key is empty or invalid.");if(n&&!r.startsWith(n))throw new Error(`S3 object key is outside the configured workspace prefix: ${r}`);if(r.split("/").some(s=>s===".."))throw new Error("S3 object key contains an unsafe parent segment.");return r}function ae(e,t,{optional:r=false}={}){if(!(r&&(e==null||e===""))){if(typeof e!="string"||!e.trim())throw new Error(`${t} must be a non-empty string.`);return e.trim()}}function oa(e){if(!e||typeof e!="object")throw new Error("Remote worker config must be a JSON object.");let t=e;if(t.schemaVersion!==1)throw new Error(`Unsupported remote worker config version: ${String(t.schemaVersion)}.`);if(t.protocolVersion!==ee)throw new Error(`Remote worker protocol mismatch: expected ${ee}, received ${String(t.protocolVersion)}.`);let r=t.workspace,n=t.functions;if(!r||!n)throw new Error("Remote worker config requires workspace and functions objects.");return {schemaVersion:1,region:ae(t.region,"region"),...ae(t.roleArn,"roleArn",{optional:true})?{roleArn:ae(t.roleArn,"roleArn")}:{},...ae(t.roleSessionName,"roleSessionName",{optional:true})?{roleSessionName:ae(t.roleSessionName,"roleSessionName")}:{},workspace:{bucket:ae(r.bucket,"workspace.bucket"),prefix:String(r.prefix??"")},...t.status&&typeof t.status=="object"?{status:{tableName:ae(t.status.tableName,"status.tableName")}}:{},functions:{render:ae(n.render,"functions.render"),...ae(n.asset,"functions.asset",{optional:true})?{asset:ae(n.asset,"functions.asset")}:{},rewrite:ae(n.rewrite,"functions.rewrite"),"deploy-copy":ae(n["deploy-copy"],"functions.deploy-copy")},targets:Array.isArray(t.targets)?t.targets.map((s,o)=>{if(!s||typeof s!="object")throw new Error(`targets[${o}] must be an object.`);let a=s;return {id:ae(a.id,`targets[${o}].id`),bucketName:ae(a.bucketName,`targets[${o}].bucketName`),prefix:String(a.prefix??""),region:ae(a.region,`targets[${o}].region`)}}):[],protocolVersion:ee}}async function Xt(e){let t=C.resolve(e);try{return oa(JSON.parse(await readFile(t,"utf8")))}catch(r){throw new Error(`Unable to load remote worker config ${t}: ${r instanceof Error?r.message:String(r)}`,{cause:r})}}var mt=class{config;lambda;s3;dynamodb;#e;constructor(t,r={},n={}){this.config=t;let s=t.roleArn?fromTemporaryCredentials({params:{RoleArn:t.roleArn,RoleSessionName:t.roleSessionName??"publisher-exporter-remote-worker"},clientConfig:{region:t.region}}):void 0;this.lambda=new LambdaClient({region:t.region,...s?{credentials:s}:{},...r}),this.s3=new S3Client({region:t.region,...s?{credentials:s}:{}}),this.dynamodb=t.status?new DynamoDBClient({region:t.region,...s?{credentials:s}:{}}):null,this.#e=n;}async#n(t){if(!this.dynamodb||!this.config.status)return null;let n=(await this.dynamodb.send(new GetItemCommand({TableName:this.config.status.tableName,ConsistentRead:true,Key:{jobId:{S:t.jobId},taskId:{S:t.taskId}}}))).Item;if(!n)return null;let s=n.operation?.S,o=n.status?.S;return !s||!["render","asset","rewrite","deploy-copy"].includes(s)||!o||!["running","succeeded","partial","failed"].includes(o)?null:{jobId:n.jobId?.S??t.jobId,taskId:n.taskId?.S??t.taskId,operation:s,status:o,completedItems:Number(n.completedItems?.N??0),failedItems:Number(n.failedItems?.N??0),totalItems:Number(n.totalItems?.N??0),sequence:Number(n.sequence?.N??0),updatedAt:n.updatedAt?.S??new Date(0).toISOString(),requestId:n.requestId?.S??null}}async#t(t,r){let n=this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify(t),"utf8")}));if(t.operation==="health"||!this.dynamodb||!this.#e.onProgress)return await n;let s=false,o=n.finally(()=>{s=true;}),a=Math.max(500,Math.min(3e4,this.#e.progressPollIntervalMs??2e3)),c=-1;for(;!s;){await Promise.race([o.then(()=>{},()=>{}),new Promise(i=>setTimeout(i,a))]);try{let i=await this.#n(t);i&&i.sequence>c&&(c=i.sequence,await this.#e.onProgress(i));}catch(i){await this.#e.onProgressError?.(i instanceof Error?i:new Error(String(i)));}}return await o}async invoke(t){let r=t.operation==="health"?this.config.functions.render:this.config.functions[t.operation];if(!r)throw new Error(`Remote worker configuration does not provide a ${t.operation} function. Redeploy the Lambda workers and reinstall remote-workers.json.`);let n=await this.#t(t,r),s=n.Payload?JSON.parse(new TextDecoder().decode(n.Payload)):null;if(n.FunctionError)throw new Error(`Remote ${t.operation} worker failed (${n.FunctionError}): ${JSON.stringify(s)}`);if(!s||typeof s!="object")throw new Error(`Remote ${t.operation} worker returned no JSON response.`);let o=s;if(o.schemaVersion!==ee||o.operation!==t.operation||o.jobId!==t.jobId||o.taskId!==t.taskId)throw new Error(`Remote ${t.operation} worker returned a mismatched response.`);return o}async readResult(t){if(!t.resultKey)throw new Error(`Remote ${t.operation} response does not contain a resultKey.`);let r=Ne(t.resultKey,this.config.workspace.prefix),n=await this.s3.send(new GetObjectCommand({Bucket:this.config.workspace.bucket,Key:r}));if(!n.Body)throw new Error(`Remote worker result has no body: ${r}`);return JSON.parse(await n.Body.transformToString("utf8"))}async readObject(t){if(t.bucket!==this.config.workspace.bucket)throw new Error(`Remote worker object bucket mismatch: ${t.bucket}.`);let r=Ne(t.key,this.config.workspace.prefix),n=await this.s3.send(new GetObjectCommand({Bucket:this.config.workspace.bucket,Key:r,...t.versionId?{VersionId:t.versionId}:{}}));if(!n.Body)throw new Error(`Remote worker object has no body: ${r}`);let s=await n.Body.transformToByteArray();if(s.byteLength!==t.bytes)throw new Error(`Remote worker object length mismatch for ${r}: expected ${t.bytes}, received ${s.byteLength}.`);if(ve(s)!==t.sha256)throw new Error(`Remote worker object checksum mismatch for ${r}.`);return s}async readObjectText(t){return new TextDecoder("utf8",{fatal:true}).decode(await this.readObject(t))}async health(t){let r=this.config.functions[t];if(!r)throw new Error(`Remote worker configuration does not provide a ${t} function.`);let n=`${t}-${Date.now()}`,s=await this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify({schemaVersion:ee,operation:"health",jobId:"health",taskId:n}),"utf8")})),o=s.Payload?JSON.parse(new TextDecoder().decode(s.Payload)):null;if(s.FunctionError||!o||typeof o!="object")throw new Error(`Remote ${t} health check failed: ${JSON.stringify(o)}`);return o}async writeWorkspaceObject(t){let r=Ne(t.key,this.config.workspace.prefix),n=typeof t.body=="string"?Buffer.from(t.body,"utf8"):t.body,s=ve(n),o=await this.s3.send(new PutObjectCommand({Bucket:this.config.workspace.bucket,Key:r,Body:n,ContentType:t.contentType,...t.cacheControl?{CacheControl:t.cacheControl}:{},Metadata:{sha256:s,...t.metadata??{}}}));return {bucket:this.config.workspace.bucket,key:r,sha256:s,bytes:n.byteLength,contentType:t.contentType,...o.ETag?{etag:o.ETag}:{},...o.VersionId?{versionId:o.VersionId}:{}}}async copyWorkspaceObject(t,r){if(t.bucket!==this.config.workspace.bucket)throw new Error(`Remote worker object bucket mismatch: ${t.bucket}.`);let n=Ne(t.key,this.config.workspace.prefix),s=Ne(r,this.config.workspace.prefix),o=`${t.bucket}/${n.split("/").map(c=>encodeURIComponent(c)).join("/")}`,a=await this.s3.send(new CopyObjectCommand({Bucket:t.bucket,Key:s,CopySource:o,MetadataDirective:"COPY"}));return {...t,key:s,...a.CopyObjectResult?.ETag?{etag:a.CopyObjectResult.ETag}:{},...a.VersionId?{versionId:a.VersionId}:{}}}};function er(e){return Number.isInteger(e)&&e>=500&&e<=599}var tn=3;function tr(e){return Math.min(3e4,5e3*2**Math.max(0,e-1))}var we=class extends Error{constructor(r,n,s,o){let a=`Page failed after ${s} attempt(s), last server response HTTP ${n}: ${r}`;super(a+(o&&o!==a?`; ${o}`:""));this.url=r;this.status=n;this.attempts=s;this.name="PageHttpError";}url;status;attempts};function As(e){if(e.size===0)return;let t=[...e.values()].slice(0,5).map(r=>`HTTP ${r.status}: ${r.url}`).join("; ");throw new Error(`Crawl incomplete: ${e.size} page(s) failed after HTTP 5xx retries. Deployment is blocked; no complete deploy plan was produced. ${t}`)}function aa(e,t,r){if(!e||typeof e!="object")throw new Error("Remote render result must be a JSON object.");let n=e;if(n.schemaVersion!==ee||!n.response||n.response.operation!=="render"||n.response.jobId!==t.jobId||n.response.taskId!==t.taskId||!n.detail||!Array.isArray(n.detail.pages)||n.detail.pages.length!==r.length)throw new Error("Remote render result has an invalid envelope.");for(let[s,o]of r.entries())if(n.detail.pages[s]?.requestedUrl!==o)throw new Error("Remote render result does not match the requested URLs.");return n}function rn(e){return e instanceof Error?e.message:String(e)}var rr=class{#e;#n;#t;#s;#c;#l;#u;#r=[];#d=0;#o=0;#i=false;constructor(t){this.#e=t.client,this.#n=ne(t.jobId,"jobId"),this.#t=Math.max(1,Math.min(5,t.maxAttempts??2)),this.#s=t.onRetry,this.#u=t.sleep??setTimeout$1,this.#c=Math.max(1,Math.min(20,t.batchSize??1)),this.#l=Math.max(1,Math.min(100,t.maxConcurrentBatches??1));}async renderBatch(t){let r=[...new Set(t.urls)];if(r.length<1||r.length>20)throw new Error("Remote render batches require between 1 and 20 unique URLs.");let n=new Map,s=new Map,o=new Map,a=new Map,c=r;for(let i=1;i<=this.#t&&c.length>0;i+=1){this.#d+=1;let d=ne(`render-${this.#d}-${ve(c.join(`
|
|
11
|
+
`)).slice(0,24)}-a${i}`,"taskId"),l=[];try{let u=await this.#e.invoke({schemaVersion:ee,operation:"render",jobId:this.#n,taskId:d,sourceOrigin:new URL(t.sourceOrigin).origin,urls:c,options:t.options}),f=aa(await this.#e.readResult(u),u,c);for(let p of f.detail.pages){if(o.delete(p.requestedUrl),er(p.httpStatus)){let g=p.httpStatus;o.set(p.requestedUrl,g),a.set(p.requestedUrl,g),s.set(p.requestedUrl,new we(p.requestedUrl,g,i).message),l.push(p.requestedUrl);continue}if(p.httpStatus!==null&&p.httpStatus!==void 0)a.delete(p.requestedUrl);else if(a.has(p.requestedUrl)){s.set(p.requestedUrl,p.error||"Remote render returned no HTTP status after a server error."),l.push(p.requestedUrl);continue}if(p.outcome==="failed"||p.outcome==="deferred"||!p.html){let g=p.error||`Remote render ended with ${p.outcome}.`;s.set(p.requestedUrl,g),l.push(p.requestedUrl);continue}try{n.set(p.requestedUrl,{page:p,html:t.downloadHtml===!1?null:await this.#e.readObjectText(p.html),taskId:d,attempts:i}),s.delete(p.requestedUrl);}catch(g){s.set(p.requestedUrl,rn(g)),l.push(p.requestedUrl);}}}catch(u){let f=rn(u);for(let p of c)o.delete(p),s.set(p,f),l.push(p);}if(i<this.#t){let u=l.some(f=>o.has(f))?tr(i):0;for(let f of l){let p=o.get(f);this.#s?.({url:f,attempt:i,maxAttempts:this.#t,reason:s.get(f)??"Remote render failed.",...p===void 0?{}:{status:p,delayMs:u}});}u>0&&await this.#u(u);}c=l;}return {pages:r.flatMap(i=>{let d=n.get(i);return d?[d]:[]}),failures:c.map(i=>({url:i,attempts:this.#t,error:s.get(i)??"Remote render failed.",...a.has(i)?{httpStatus:a.get(i)}:{}}))}}async render(t){let r=JSON.stringify({sourceOrigin:new URL(t.sourceOrigin).origin,options:t.options,downloadHtml:t.downloadHtml!==false});return await new Promise((n,s)=>{this.#r.push({input:t,key:r,resolve:n,reject:s}),this.#a();})}#a(){this.#i||this.#r.length===0||(this.#i=true,setTimeout(()=>{this.#i=false,this.#p();},0));}#p(){for(;this.#o<this.#l&&this.#r.length>0;){let t=this.#r.shift();if(!t)break;let r=[t];for(let n=0;n<this.#r.length&&r.length<this.#c;){let s=this.#r[n];s?.key===t.key?(r.push(s),this.#r.splice(n,1)):n+=1;}this.#o+=1,this.renderBatch({sourceOrigin:t.input.sourceOrigin,urls:r.map(n=>n.input.url),options:t.input.options,...t.input.downloadHtml===void 0?{}:{downloadHtml:t.input.downloadHtml}}).then(n=>{let s=new Map(n.pages.map(a=>[a.page.requestedUrl,a])),o=new Map(n.failures.map(a=>[a.url,a]));for(let a of r){let c=s.get(a.input.url);if(c){a.resolve(c);continue}let i=o.get(a.input.url);a.reject(i?.httpStatus===void 0?new Error(`Remote render failed after ${i?.attempts??this.#t} attempt(s) for ${a.input.url}: ${i?.error??"Unknown remote render failure."}`):new we(a.input.url,i.httpStatus,i.attempts,i.error));}}).catch(n=>{let s=rn(n);for(let o of r)o.reject(new Error(s,{cause:n}));}).finally(()=>{this.#o-=1,this.#a();});}this.#r.length>0&&this.#a();}};function ca(e,t,r){if(!e||typeof e!="object")throw new Error("Remote asset result must be a JSON object.");let n=e;if(n.schemaVersion!==ee||n.response?.operation!=="asset"||n.response.jobId!==t.jobId||n.response.taskId!==t.taskId||!n.detail||!Array.isArray(n.detail.assets)||n.detail.assets.length!==r.length)throw new Error("Remote asset result has an invalid envelope.");for(let s=0;s<r.length;s+=1)if(n.detail.assets[s]?.requestedUrl!==r[s])throw new Error("Remote asset result does not match the requested URLs.");return n}var nr=class{#e;#n;#t;#s=0;constructor(t){this.#e=t.client,this.#n=ne(t.jobId,"jobId"),this.#t=Math.max(1,Math.min(5,t.maxAttempts??2));}async fetch(t){let r=[...t.urls];if(r.length<1||r.length>20)throw new Error("Remote asset batches require between 1 and 20 URLs.");let n=null;for(let s=1;s<=this.#t;s+=1){this.#s+=1;let o=ne(`asset-${this.#s}-${ve(r.join(`
|
|
12
|
+
`)).slice(0,24)}-a${s}`,"taskId");try{let a=await this.#e.invoke({schemaVersion:ee,operation:"asset",jobId:this.#n,taskId:o,urls:r,options:{ignoreHttpsErrors:t.ignoreHttpsErrors,timeoutMs:Math.max(1e3,Math.min(12e4,t.timeoutMs??6e4))}});return {assets:ca(await this.#e.readResult(a),a,r).detail.assets,taskId:o,attempts:s}}catch(a){n=a;}}throw new Error(`Remote asset batch failed after ${this.#t} attempt(s): ${n instanceof Error?n.message:String(n)}`,{cause:n})}};function $s(e,t){let r=[];for(let n=0;n<e.length;n+=t)r.push(e.slice(n,n+t));return r}function Os(e){return {sourceOrigin:e.sourceOrigin,targetOrigin:e.targetOrigin,urlRewriteMode:e.urlRewriteMode,outputDir:"/workspace",extraReplacements:e.extraReplacements,wpsuite:{...e.wpsuite?.subscriptionType?{subscriptionType:e.wpsuite.subscriptionType}:{},...e.wpsuite?.siteSettings?{siteSettings:{subscriber:e.wpsuite.siteSettings.subscriber===true}}:{}}}}function Ms(e,t){if(!e||typeof e!="object")throw new Error("Remote rewrite result must be a JSON object.");let r=e;if(r.schemaVersion!==ee||r.response?.operation!=="rewrite"||r.response.jobId!==t.jobId||r.response.taskId!==t.taskId||!r.detail||!Array.isArray(r.detail.objects))throw new Error("Remote rewrite result has an invalid envelope.");return r}async function sr(e,t,r){let n=r.options??{},s=await Qr(e,n.files);if(s.length===0)return 0;let o=ne(r.jobId,"jobId"),a=pt(r.client.config.workspace.prefix,"jobs",o,"rewrite-inputs"),c=`${a}/config.json`.replace(/\/+/g,"/"),i=`${a}/asset-map.json`.replace(/\/+/g,"/"),d=`${a}/previous-asset-map.json`.replace(/\/+/g,"/");await Promise.all([r.client.writeWorkspaceObject({key:c,body:JSON.stringify(Os(e)),contentType:"application/json; charset=utf-8"}),r.client.writeWorkspaceObject({key:i,body:JSON.stringify(t),contentType:"application/json; charset=utf-8"}),r.client.writeWorkspaceObject({key:d,body:JSON.stringify(n.previousAssetMap??{}),contentType:"application/json; charset=utf-8"})]);let l=Math.max(1,Math.min(500,r.batchSize)),u=Math.ceil(s.length/l),f=Math.max(1,Math.min(Math.max(1,r.concurrency),u));await n.onStart?.({totalFiles:s.length,workerCount:f});let p=[],g=0,w=0;await Promise.all(Array.from({length:Math.min(16,s.length)},async()=>{for(;;){let O=g;if(O>=s.length)return;g+=1;let x=s[O],k=C.join(e.outputDir,x),R=Es.lookup(x),A=R?Es.contentType(R)||R:"text/plain; charset=utf-8",I=`${a}/files/${ve(x)}.txt`.replace(/\/+/g,"/");await r.client.writeWorkspaceObject({key:I,body:await F.readFile(k),contentType:A}),p[O]={relativePath:x,key:I,fullPath:k,contentType:A},w+=1,await r.onStageProgress?.({index:w,totalFiles:s.length,file:x});}}));let m=$s(p,l),h=0,y=0,b=0,P=Array.from({length:f},async()=>{for(;;){let O=h;if(O>=m.length)return;h+=1;let x=m[O],k=null,R=null;for(let A=1;A<=Math.max(1,Math.min(5,r.maxAttempts));A+=1){let I=ne(`rewrite-${O+1}-a${A}-${ve(x.map(D=>D.relativePath).join(`
|
|
13
|
+
`)).slice(0,16)}`,"taskId"),K={schemaVersion:ee,operation:"rewrite",jobId:o,taskId:I,configKey:c,assetMapKey:i,previousAssetMapKey:d,items:x.map(D=>({inputKey:D.key,outputKey:D.key,relativePath:D.relativePath,contentType:D.contentType}))};try{let D=await r.client.invoke(K);R=Ms(await r.client.readResult(D),D);break}catch(D){k=D;}}if(!R)throw new Error(`Remote rewrite batch ${O+1}/${m.length} failed: ${k instanceof Error?k.message:String(k)}`,{cause:k});for(let A of x){let I=R.detail.objects.find(K=>K.outputKey===A.key);if(!I)throw new Error(`Remote rewrite result omitted ${A.relativePath}.`);await qe(A.fullPath,Buffer.from(await r.client.readObject(I.output))),I.changed&&(b+=1),y+=1,await n.onProgress?.({index:y,totalFiles:s.length,changedTextFiles:b,file:A.relativePath,changed:I.changed});}}});return await Promise.all(P),b}async function or(e,t,r,n){let s=n.relativePaths?new Set([...n.relativePaths].map(m=>m.replace(/\\/g,"/"))):null,o=Object.values(t.objects).filter(m=>m.isText&&(!s||s.has(m.relativePath))).sort((m,h)=>m.relativePath.localeCompare(h.relativePath));if(o.length===0)return 0;let a=ne(n.jobId,"jobId"),c=pt(n.client.config.workspace.prefix,"jobs",a,"rewrite-config"),i=`${c}/config.json`.replace(/\/+/g,"/"),d=`${c}/asset-map.json`.replace(/\/+/g,"/");await Promise.all([n.client.writeWorkspaceObject({key:i,body:JSON.stringify(Os(e)),contentType:"application/json; charset=utf-8"}),n.client.writeWorkspaceObject({key:d,body:JSON.stringify(r),contentType:"application/json; charset=utf-8"})]);let l=Math.max(1,Math.min(500,n.batchSize)),u=$s(o,l),f=Math.max(1,Math.min(Math.max(1,n.concurrency),u.length)),p=0,g=0,w=0;return await Promise.all(Array.from({length:f},async()=>{for(;;){let m=p;if(m>=u.length)return;p+=1;let h=u[m],y=null,b=null;for(let P=1;P<=Math.max(1,Math.min(5,n.maxAttempts));P+=1){let O=ne(`rewrite-object-${m+1}-a${P}-${ve(h.map(x=>x.relativePath).join(`
|
|
14
|
+
`)).slice(0,16)}`,"taskId");try{let x=await n.client.invoke({schemaVersion:ee,operation:"rewrite",jobId:a,taskId:O,configKey:i,assetMapKey:d,items:h.map(k=>({inputKey:k.object.key,outputKey:k.object.key,relativePath:k.relativePath,contentType:k.contentType||k.object.contentType}))});y=Ms(await n.client.readResult(x),x);break}catch(x){b=x;}}if(!y)throw new Error(`Remote object rewrite batch ${m+1}/${u.length} failed: ${b instanceof Error?b.message:String(b)}`,{cause:b});for(let P of h){let O=y.detail.objects.find(x=>x.outputKey===P.object.key);if(!O)throw new Error(`Remote rewrite result omitted ${P.relativePath}.`);P.object=O.output,O.changed&&(w+=1),g+=1,await n.onProgress?.({index:g,totalFiles:o.length,changedTextFiles:w,file:P.relativePath,changed:O.changed});}}})),t.assetMap={...r},t.generatedAt=new Date().toISOString(),w}var da="remote-workers.json";function ir(e={}){let t=String(e.explicitPath??"").trim();if(t)return C.resolve(t);let r=String(e.runtimeDir??process.env.STATIC_PUBLISHER_RUNTIME_DIR??process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR??"").trim();return r?C.join(C.resolve(r),da):""}function js(e,t,r,n=250){let s=Math.max(1,Math.floor(n)),o=[],a=new Set;for(let c of [e,...t]){let i=c.trim();if(!(!i||a.has(i)||r(i))&&(a.add(i),o.push(i),o.length>=s))break}return o}async function Fs(e,t){let r=String(e.wpsuite?.runtimeToken||"").trim();if(!r)throw new Error("Page-cache purge is enabled, but the WordPress runtime token is missing.");let n=new URL("/wp-json/smartcloud-static-publisher/v1/page-cache/purge",e.sourceOrigin).toString(),s=await t.post(n,{timeout:3e4,failOnStatusCode:false,maxRedirects:0,headers:{"content-type":"application/json","x-static-publisher-token":r},data:JSON.stringify({scope:"all"})});try{let o=await s.text();if(o.length>65536)throw new Error("WordPress page-cache purge response was too large.");let a=null;try{a=JSON.parse(o);}catch{throw new Error(`WordPress page-cache purge returned invalid JSON (HTTP ${s.status()}).`)}if(!s.ok()){let c=a&&typeof a=="object"&&"message"in a?String(a.message||""):"";throw new Error(`WordPress page-cache purge failed with HTTP ${s.status()}${c?`: ${c}`:""}`)}if(!a||typeof a!="object"||a.purged!==!0)throw new Error("WordPress page-cache provider did not confirm a complete purge.");return {purged:!0,provider:String(a.provider||"custom"),scope:"all",...typeof a.purgedAt=="string"?{purgedAt:a.purgedAt}:{}}}finally{await s.dispose().catch(()=>{});}}function pa(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?C.resolve(e):""}function ar(e){let t=String(process.env.STATIC_PUBLISHER_REMOTE_EXPORT_MANIFEST_PATH||"").trim();if(t)return C.resolve(t);let r=pa();if(r)return C.join(r,"remote-export-manifest.json");let n=C.resolve(e.outputDir);return C.join(C.dirname(n),`.${C.basename(n)}-remote-export-manifest.json`)}function sn(e){let t=C.posix.normalize(String(e||"").replace(/\\/g,"/").replace(/^\/+/,""));if(!t||t==="."||t===".."||t.startsWith("../")||/^[A-Za-z]:/.test(t))throw new Error(`Invalid remote export relative path: ${e}`);return t}function Us(e,t,r){let n=r?.workspace.bucket===t.workspace.bucket&&r.workspace.prefix===t.workspace.prefix;return {schemaVersion:1,generatedAt:new Date().toISOString(),jobId:e,workspace:{...t.workspace},objects:n?{...r.objects}:{},assetMap:n?{...r.assetMap}:{}}}function gt(e,t){let r=sn(t.relativePath);if(t.object.bucket!==e.workspace.bucket)throw new Error(`Remote export object bucket mismatch for ${r}.`);Ne(t.object.key,e.workspace.prefix),e.objects[r]={...t,relativePath:r},e.generatedAt=new Date().toISOString();}function Ls(e,t){delete e.objects[sn(t)],e.generatedAt=new Date().toISOString();}async function qs(e,t){t.generatedAt=new Date().toISOString();let r=ar(e);await F.mkdir(C.dirname(r),{recursive:true}),await qe(r,`${JSON.stringify(t,null,2)}
|
|
15
|
+
`,"utf8");}async function cr(e){try{let t=JSON.parse(await F.readFile(ar(e),"utf8"));if(t.schemaVersion!==1||typeof t.jobId!="string"||!t.workspace||typeof t.workspace.bucket!="string"||typeof t.workspace.prefix!="string"||!t.objects||typeof t.objects!="object"||!t.assetMap||typeof t.assetMap!="object")return null;let r=t;for(let[n,s]of Object.entries(r.objects)){if(sn(n),!s||s.relativePath!==n||s.object?.bucket!==r.workspace.bucket)return null;Ne(s.object.key,r.workspace.prefix);}return r}catch{return null}}var ha=["text/css","javascript","image/","font/","application/font","application/json","application/xml","text/xml","application/rss+xml","application/atom+xml","application/xslt+xml","text/xsl","image/svg+xml"],Xs=new Set([".css",".js",".mjs",".json",".map",".xml",".xsl",".rss",".atom",".txt",".enc",".jws",".png",".jpg",".jpeg",".gif",".webp",".avif",".svg",".ico",".woff",".woff2",".ttf",".otf",".eot",".pdf",".mp4",".webm"]),eo=new Set(["",".html",".htm"]),wa=new Set([".css",".xml",".xsl",".svg",".json",".html",".htm",".txt",".enc",".jws"]),ya=["/wp-content/","/wp-includes/","/wp-admin/","/static/","/assets/","/build/","/_next/"];function ba(e){let t=[],r="full",n="full",s=false,o=false,a="",c=null,i="";for(let d=0;d<e.length;d++){let l=e[d];if(l==="--retry-timeouts")r="retry-timeouts",s=true;else if(l==="--resume")s=true;else if(l==="--resume-rewrite")s=true,o=true;else if(l==="--crawl-mode"){let u=e[++d];if(!u)throw new Error("--crawl-mode requires a value");n=u==="incremental"?"incremental":"full",s||=n==="incremental";}else if(l.startsWith("--crawl-mode="))n=l.slice(13)==="incremental"?"incremental":"full",s||=n==="incremental";else if(l==="--incremental")n="incremental",s=true;else if(l==="--url"){let u=e[++d];if(!u)throw new Error("--url requires a value");r="single-url",s=true,t.push(u);}else if(l.startsWith("--url="))r="single-url",s=true,t.push(l.slice(6));else if(l==="--urls"){let u=e[++d];if(!u)throw new Error("--urls requires a file path");r="single-url",s=true,t.push(`@${u}`);}else if(l==="--content-sync-plan"){let u=e[++d];if(!u)throw new Error("--content-sync-plan requires a file path");r="content-sync",n="incremental",s=true,a=C.resolve(u);}else if(l.startsWith("--content-sync-plan="))r="content-sync",n="incremental",s=true,a=C.resolve(l.slice(20));else if(l==="--remote-render")c=true;else if(l==="--local-render")c=false;else if(l==="--remote-worker-config"){let u=e[++d];if(!u)throw new Error("--remote-worker-config requires a file path");i=C.resolve(u);}else l.startsWith("--remote-worker-config=")&&(i=C.resolve(l.slice(23)));}return {mode:r,crawlMode:n,urls:t,preserveOutput:s,resumeRewrite:o,contentSyncPlanPath:a,remoteRender:c,remoteWorkerConfigPath:i}}function Ft(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?C.resolve(e):""}function Sa(){let e=Ft();return e?C.join(e,"privacy","cookie-observations.json"):null}function Pa(){let e=Ft();return e?C.resolve(e,".."):""}function Ra(){let e=process.env.STATIC_PUBLISHER_WP_ROOT||process.env.WPSUITE_STATIC_PUBLISHER_WP_ROOT||"";return e.trim()?C.resolve(e):""}function va(e){let t=e.trim(),r=[{alias:"@storage-root",root:Pa(),requiredEnv:"STATIC_PUBLISHER_RUNTIME_DIR or WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR"},{alias:"@runtime",root:Ft(),requiredEnv:"STATIC_PUBLISHER_RUNTIME_DIR or WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR"},{alias:"@wp-root",root:Ra(),requiredEnv:"STATIC_PUBLISHER_WP_ROOT or WPSUITE_STATIC_PUBLISHER_WP_ROOT"}];for(let n of r){if(t!==n.alias&&!t.startsWith(`${n.alias}/`))continue;if(!n.root)return {resolvedPath:null,alias:n.alias,requiredEnv:n.requiredEnv};let s=t.slice(n.alias.length).replace(/^\/+/,"");return {resolvedPath:s?C.resolve(n.root,s):n.root,alias:n.alias}}return {resolvedPath:C.resolve(t)}}function to(e){let t=String(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH||"").trim();if(t)return C.resolve(t);let r=Ft();return r?C.join(r,"crawl-manifest.json"):C.join(e.outputDir,".crawl-manifest.json")}function ro(){return {schemaVersion:6,updatedAt:"",pages:{},assets:{}}}function _s(e){return {url:String(e.url||""),outputPath:String(e.outputPath||""),contentType:typeof e.contentType=="string"&&e.contentType?e.contentType:null,changeToken:typeof e.changeToken=="string"?e.changeToken:null,tokenSource:typeof e.tokenSource=="string"?e.tokenSource:null,sitemapLastmod:typeof e.sitemapLastmod=="string"?e.sitemapLastmod:null,discoveredPages:Array.isArray(e.discoveredPages)?e.discoveredPages.map(t=>String(t)):[],discoveredAssets:Array.isArray(e.discoveredAssets)?e.discoveredAssets.map(t=>String(t)):[],lastCrawledAt:String(e.lastCrawledAt||""),lastSeenRunId:String(e.lastSeenRunId||""),rewriteComplete:e.rewriteComplete===true}}function Ca(e){let t=e.isText===true;return {url:String(e.url||""),outputPath:String(e.outputPath||""),isText:t,contentType:typeof e.contentType=="string"&&e.contentType?e.contentType:null,cacheControl:typeof e.cacheControl=="string"&&e.cacheControl?e.cacheControl:null,changeToken:typeof e.changeToken=="string"?e.changeToken:null,tokenSource:typeof e.tokenSource=="string"?e.tokenSource:null,discoveredAssets:Array.isArray(e.discoveredAssets)?e.discoveredAssets.map(r=>String(r)):[],lastCrawledAt:String(e.lastCrawledAt||""),lastSeenRunId:String(e.lastSeenRunId||""),unreferencedRuns:Math.max(0,Number(e.unreferencedRuns)||0),rewriteComplete:e.rewriteComplete===true||!t}}function cn(e){let t=e?.["content-type"]?.trim();return t||null}function ln(e){let t=e?.["cache-control"]?.trim();return t||null}function ka(e){return e?e.split(",").map(t=>t.trim().toLowerCase()).some(t=>t==="no-cache"||t==="no-store"||/^max-age\s*=\s*0$/.test(t)):false}function xa(){return {rewriteTargets:new Set,changedFiles:new Set,deletedFiles:new Set,revalidateFiles:new Set}}function ft(e,t,r,n){let s=me(t.outputDir,r);s&&(ka(n)?e.revalidateFiles.add(s):e.revalidateFiles.delete(s));}function le(e,t,r){let n=me(t.outputDir,r);n&&(e.changedFiles.add(n),e.deletedFiles.delete(n));}function un(e,t,r){let n=me(t.outputDir,r);n&&(e.deletedFiles.add(n),e.changedFiles.delete(n),e.revalidateFiles.delete(n));}function Ce(e,t){e.rewriteTargets.add(C.resolve(t));}async function Ia(e){try{let t=await F.readFile(to(e),"utf8"),r=JSON.parse(t);if(r&&typeof r=="object"&&r.pages&&typeof r.pages=="object"){if((r.schemaVersion===2||r.schemaVersion===3||r.schemaVersion===4||r.schemaVersion===5||r.schemaVersion===6)&&r.assets&&typeof r.assets=="object")return {schemaVersion:6,updatedAt:String(r.updatedAt||""),pages:Object.fromEntries(Object.entries(r.pages).map(([n,s])=>[n,_s(s)])),assets:Object.fromEntries(Object.entries(r.assets).map(([n,s])=>[n,Ca(s)]))};if(r.schemaVersion===1)return {schemaVersion:6,updatedAt:String(r.updatedAt||""),pages:Object.fromEntries(Object.entries(r.pages).map(([n,s])=>[n,_s(s)])),assets:{}}}}catch{}return ro()}function dn(e){return JSON.parse(JSON.stringify(e))}async function Ta(e,t){let r=to(e);await F.mkdir(C.dirname(r),{recursive:true}),await F.writeFile(r,JSON.stringify(t,null,2),"utf8");}async function He(e,t,r=false){if(!t.trackManifest)return;t.manifestPendingChanges+=1;let n=Date.now();if(!r&&t.manifestPendingChanges<25&&n-t.lastManifestSavedAt<5e3)return;t.manifestPendingChanges=0,t.lastManifestSavedAt=n;let s=async()=>{let o=dn(t.manifest);o.updatedAt=new Date().toISOString(),t.manifest.updatedAt=o.updatedAt,await Ta(e,o);};t.manifestSaveChain=t.manifestSaveChain.then(s,s),await t.manifestSaveChain;}function tt(e){if(!e)return null;let t=e.trim();return t||null}function Aa(e,t){let r=new Set,n=new Set([...Object.keys(e),...Object.keys(t)]);for(let s of n){let o=e[s],a=t[s];!o||!a||o===a||r.add(s);}return r}async function no(e,t,r,n){let s=[...new Set(r.map(c=>c.trim()).filter(Boolean))],o=String(e.wpsuite?.runtimeToken||"").trim();if(s.length===0||!o)return new Map;let a=new URL("/wp-json/smartcloud-static-publisher/v1/change-tokens",e.sourceOrigin).toString();try{let c=await t.post(a,{timeout:3e4,failOnStatusCode:!1,headers:{"content-type":"application/json","x-static-publisher-token":o},data:JSON.stringify({urls:s})});if(!c.ok())return n.warn(`Change token lookup failed with HTTP ${c.status()}`,{endpoint:a,status:c.status()}),new Map;let i=await c.json().catch(()=>null);if(!i||!Array.isArray(i.items))return new Map;let d=new Map;for(let l of i.items)!l||typeof l.url!="string"||d.set(l.url,l);return d}catch(c){return n.warn("Change token lookup failed; falling back to sitemap metadata",{endpoint:a,error:c instanceof Error?`${c.name}: ${c.message.split(/\r?\n/u,1)[0]}`:"Unknown change-token request failure"}),new Map}}async function ur(e,t,r,n,s){if(!r.enabled&&!r.trackManifest)return null;if(r.changeTokenCache.has(n))return r.changeTokenCache.get(n)??null;let a=(await no(e,t,[n],s)).get(n)??null;return wr(e,n)&&(!a||a.supported!==true||!a.token)&&(a=await Oa(e,t,n,s)),a=so(e,a),r.changeTokenCache.set(n,a),a}async function yn(e,t,r,n,s){if(!r.trackManifest)return;let o=[...new Set(n.map(a=>a.trim()).filter(Boolean))].filter(a=>!r.changeTokenCache.has(a));for(let a=0;a<o.length;a+=250){let c=o.slice(a,a+250),i=await no(e,t,c,s);for(let d of c)r.changeTokenCache.set(d,so(e,i.get(d)??null));}}async function Ea(e,t,r,n,s,o){if(!(!n.trackManifest||n.changeTokenCache.has(s)))for(;!n.changeTokenCache.has(s);){if(!n.pageChangeTokenPrimePromise){let a=js(s,r.pageQueue,i=>n.changeTokenCache.has(i));if(a.length===0)return;o.info(`Loading ${a.length} page change tokens in bulk.`,{phase:"prime-page-change-tokens",batchSize:a.length,remainingPages:r.pageQueue.length});let c=yn(e,t,n,a,o).finally(()=>{n.pageChangeTokenPrimePromise===c&&(n.pageChangeTokenPrimePromise=null);});n.pageChangeTokenPrimePromise=c;}await n.pageChangeTokenPrimePromise;}}function $a(e){return `subscriber=${e.wpsuite?.siteSettings?.subscriber===true?"1":"0"}`}function so(e,t){if(!t?.supported||!t.token||t.tokenSource==="wp-media-file")return t;let r=$a(e);return {...t,token:Ee(`${t.token}
|
|
16
|
+
${r}`,40),tokenSource:t.tokenSource?`${t.tokenSource}+site-subscriber`:"site-subscriber"}}async function Oa(e,t,r,n){try{let s=await t.get(r,{timeout:Math.min(e.navigationTimeoutMs,15e3),failOnStatusCode:!1});if(s.status()!==404)return n.warn(`Generated 404 fallback token skipped for ${r}`,{url:r,status:s.status(),requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),null;let o=await s.text().catch(()=>""),a=Ee(`${r}
|
|
17
17
|
404
|
|
18
|
-
${o}`,40);return n.info(`Using generated 404 fallback change token for ${r}`,{url:r,requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),{url:r,supported:!0,token:a,tokenSource:"generated-404-response-hash",postId:null,dependencyPostIds:[],reason:null}}catch(s){return n.warn(`Generated 404 fallback token lookup failed for ${r}`,{url:r,error:String(s),requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),null}}async function Ys(e,t,r,n,s,o){let a=gr(e,s);if(await Ra(e,t,r,n,s,o),!n.enabled)return {action:"render",changeToken:n.trackManifest?await ar(e,t,n,s,o):null};let c=n.manifest.pages[s];if(!c)return {action:"render",changeToken:await ar(e,t,n,s,o)};let i=await ar(e,t,n,s,o);if(i?.supported&&i.token)return c.changeToken===i.token?a&&!await ka(e,t,s,o)?{action:"render",changeToken:i}:{action:"reuse",changeToken:i}:{action:"render",changeToken:i};let d=et(r.sitemapLastmodByPage[s]);return d&&c.sitemapLastmod&&c.sitemapLastmod===d?{action:"reuse",changeToken:i}:{action:"render",changeToken:i}}async function ka(e,t,r,n){try{let o=(await t.get(r,{timeout:Math.min(e.navigationTimeoutMs,15e3),failOnStatusCode:!1})).status();return o===404?!0:(n.warn(`Generated 404 request path no longer returns 404 for ${r}`,{url:r,status:o,requestPath:e.generated404RequestPath,source:"generated-404-status-probe"}),!1)}catch(s){return n.warn(`Generated 404 status probe failed for ${r}`,{url:r,error:String(s),requestPath:e.generated404RequestPath,source:"generated-404-status-probe"}),false}}async function xa(e,t,r,n,s){let o=Ds(r.previousManifest,void 0,n,"previous-manifest"),a=0;for(let[g,f]of Object.entries(r.manifest.pages))if(!r.seenPages.has(g)){sn(s,e,f.outputPath);try{await F.unlink(f.outputPath);}catch(m){(m.code||"")!=="ENOENT"&&n.warn(`Failed to remove stale incremental page output for ${g}`,{url:g,outputPath:f.outputPath,error:String(m)});}delete r.manifest.pages[g],a++;}let c=Ds(r.manifest,r.runId,n,"active-manifest"),i=new Set,d=new Set;for(let g of c){for(let w of $t(e,g))i.add(w);let f=r.manifest.assets[g]?.outputPath;f&&d.add(f);let m=ft(e,t.assetMap,g);m&&d.add(m);}for(let g of Object.keys(r.manifest.assets)){if(c.has(g)){r.manifest.assets[g].unreferencedRuns=0;continue}let f=r.manifest.assets[g];if(ws(f.unreferencedRuns)){f.unreferencedRuns+=1,n.warn(`Deferred deletion of newly unreferenced incremental asset ${g}.`,{url:g,unreferencedRuns:f.unreferencedRuns,phase:"incremental-cleanup",source:"asset-deletion-grace"});continue}delete r.manifest.assets[g];}let l=0,u=0;for(let g of o){if(r.manifest.assets[g])continue;let f=new Set,m=r.previousManifest.assets[g]?.outputPath;m&&f.add(m);let w=ft(e,t.assetMap,g);if(!c.has(g)&&w)f.add(w);else if(!c.has(g)){let p=Ba(e,g,n,"incremental-cleanup");p&&(f.add(p.originalFilePath),p.hashedFilePath&&f.add(p.hashedFilePath));}for(let p of f)if(!d.has(p)){sn(s,e,p);try{await F.unlink(p),l++;}catch(h){(h.code||"")!=="ENOENT"&&n.warn(`Failed to remove stale incremental asset output for ${g}`,{url:g,outputPath:p,error:String(h)});}}for(let p of $t(e,g))i.has(p)||Object.prototype.hasOwnProperty.call(t.assetMap,p)&&(delete t.assetMap[p],u++);}(a>0||l>0||u>0)&&n.info(`Incremental cleanup removed ${a} stale pages, ${l} stale assets, ${u} stale asset mappings`,{removedPages:a,removedAssets:l,removedAssetMappings:u,phase:"incremental-cleanup"});}async function Ia(e,t,r,n){let s=new Set([...Object.values(t.manifest.pages),...Object.values(t.manifest.assets)].map(i=>String(i.outputPath||"").trim()).filter(Boolean).map(i=>v.resolve(i))),o=Object.values(e.postCrawlCopyMap||{}).map(i=>cr(String(i||""))).filter(i=>!!i).map(i=>v.resolve(e.outputDir,i)),c=(await fi(["**/*.html","**/*.htm"],{cwd:e.outputDir,onlyFiles:true,dot:true})).filter(i=>hs(v.join(e.outputDir,i),e.outputDir,s,o));for(let i of c){let d=v.join(e.outputDir,i);sn(n,e,d),await F.unlink(d);}c.length>0&&r.info(`Removed ${c.length} orphaned HTML output file(s) that are absent from the current crawl manifest.`,{phase:"incremental-cleanup",source:"manifest-output-reconciliation",removedPages:c.length,samples:c.slice(0,20)});}function Ds(e,t,r,n){let s=new Set,o=a=>{let c=a.trim();if(c){if(r){let i=Ce(c,r,"asset",n??"manifest");if(!i)return;s.add(i.toString());return}s.add(c);}};for(let a of Object.values(e.pages))for(let c of a.discoveredAssets||[])o(c);for(let[a,c]of Object.entries(e.assets||{}))t&&c.lastSeenRunId!==t||o(a);return s}function Us(e,t,r){for(let n of t)for(let s of $t(e,n))if(r.has(s))return true;return false}function Ta(e,t,r,n,s){let o=new Set(r.rewriteTargets);for(let c of r.changedFiles)o.add(v.resolve(e.outputDir,c));for(let c of Object.values(t.manifest.pages))c.rewriteComplete||o.add(v.resolve(c.outputPath));for(let c of Object.values(t.manifest.assets))c.isText&&!c.rewriteComplete&&o.add(v.resolve(c.outputPath));let a=Pa(n,s);if(a.size===0)return [...o];for(let c of Object.values(t.manifest.pages))Us(e,c.discoveredAssets,a)&&o.add(v.resolve(c.outputPath));for(let[c,i]of Object.entries(t.manifest.assets)){i.isText&&Us(e,i.discoveredAssets,a)&&o.add(v.resolve(i.outputPath));for(let d of $t(e,c))if(a.has(d)){ue(r,e,i.outputPath),i.isText&&o.add(v.resolve(i.outputPath));break}}return [...o]}function Aa(e,t){let r=t?new Set(Array.from(t,s=>v.resolve(s))):null,n=s=>r===null||r.has(v.resolve(s));for(let s of Object.values(e.manifest.pages))n(s.outputPath)&&(s.rewriteComplete=true);for(let s of Object.values(e.manifest.assets)){if(!s.isText){s.rewriteComplete=true;continue}n(s.outputPath)&&(s.rewriteComplete=true);}}function Ea(e,t,r){let n=new Set,s=o=>{if(!o)return;let a=me(e.outputDir,o);a&&n.add(a);};for(let o of t.donePages)s(Me(e,o));for(let o of Object.values(r.manifest.pages))o.lastSeenRunId===r.runId&&s(o.outputPath);for(let o of t.doneAssets)s(ft(e,t.assetMap,o));for(let o of Object.values(r.manifest.assets))o.lastSeenRunId===r.runId&&s(o.outputPath);return n}async function $a(e,t,r,n,s,o){let a=[...n.deletedFiles].sort(),c=Ea(e,t,r),i=0;for(let u of [...c].sort())if(!o?.objects[u]){try{if((await F.stat(v.join(e.outputDir,u))).isFile())continue}catch{}i++,s.warn(`Active output is missing after crawl: ${u}`,{phase:"deploy-plan",file:u,outputPath:v.join(e.outputDir,u)});}if(i>0&&s.warn(`Detected ${i} active output file(s) missing before deploy plan save.`,{phase:"deploy-plan",missingActiveOutputs:i}),a.length===0)return [];let d=[],l=0;for(let u of a){if(!c.has(u)){d.push(u);continue}l++;let g=v.join(e.outputDir,u),f;try{f=(await F.stat(g)).isFile();}catch{f=false;}s.warn(`Deploy plan protected active output from deletion: ${u}`,{phase:"deploy-plan",file:u,outputPath:g,exists:f});}return l>0&&s.info(`Deploy plan skipped ${l} active output deletion(s).`,{phase:"deploy-plan",protectedDeletes:l,deletedFiles:d.length}),d}function $t(e,t){let r=new Set([t]);try{let n=new URL(t),o=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{o.push(new URL(e.targetOrigin).origin);}catch{}for(let a of o)try{r.add(new URL(a).origin+n.pathname+n.search);}catch{}r.add(n.pathname+n.search),r.add(n.pathname);}catch{}return [...r]}function Oa(e,t){let r=new Set([t]);try{let n=new URL(t),o=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{o.push(new URL(e.targetOrigin).origin);}catch{}for(let a of o)try{r.add(new URL(a).origin+n.pathname+n.search);}catch{}r.add(n.pathname+n.search);}catch{}return [...r]}function Xs(e,t){let r=e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/"?e.targetOrigin:"https://relative.invalid/";try{let n=new URL(t,r);return Tt(e.outputDir,n.pathname)}catch{return null}}function eo(e,t,r){for(let n of Oa(e,r)){let s=t[n];if(!s)continue;let o=Xs(e,s);if(o)return {outputPath:o,publicUrl:s}}return null}function Ma(e,t,r){for(let n of $t(e,r)){let s=t[n];if(!s)continue;let o=Xs(e,s);if(o)return o}return null}function ft(e,t,r){let n=Ma(e,t,r);if(n)return n;try{return Ft(e,r).originalFilePath}catch{return null}}function ja(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?v.join(v.resolve(e),"queue-runner-heartbeat.json"):""}async function en(e){let t=ja();if(t)try{let r=await F.readFile(t,"utf8"),n=JSON.parse(r);if(!n||typeof n!="object")return;await F.writeFile(t,JSON.stringify({...n,checkedAt:new Date().toISOString(),status:"running",currentStep:"rewrite",message:e},null,2),"utf8");}catch{}}function Fa(e,t){let r=new Set;for(let n of t.donePages)r.add(v.resolve(Me(e,n)));for(let n of t.doneAssets){let s=ft(e,t.assetMap,n);!s||!Ee(s)||r.add(v.resolve(s));}for(let n of t.doneSitemaps){let s=ft(e,t.assetMap,n);!s||!Ee(s)||r.add(v.resolve(s));}return [...r]}var lr="re:",ir=new Map;function Da(e){if(!e.startsWith(lr))return null;let t=ir.get(e);if(t!==void 0)return t||null;let r=e.slice(lr.length).trim();if(!r)return ir.set(e,false),null;try{let n=new RegExp(r);return ir.set(e,n),n}catch{return console.warn(`[crawl] Ignoring invalid path matcher regex: ${e}`),ir.set(e,false),null}}function gn(e,t){let r=Da(t);return r?r.test(e):t.startsWith(lr)?false:e.startsWith(t)}function Ua(e,t){return t.find(r=>gn(e,r))}function to(e,t){let r=Ua(t.pathname,e.blockedPathPrefixes);if(r)return r.startsWith(lr)?`blocked path regex: ${r}`:`blocked path prefix: ${r}`;let n=e.blockedSearchFragments.find(s=>t.search.includes(s));return n?`blocked search fragment: ${n}`:null}function La(e){let t=new URL(e.sourceOrigin),r=new Set([t.hostname,...e.allowedAssetHosts]);if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{r.add(new URL(e.targetOrigin).hostname);}catch{}for(let n of Object.keys(e.extraReplacements||{}))try{r.add(new URL(n).hostname);}catch{}return r}function qa(e,t){return La(e).has(t.hostname)}function Wa(e){let t=qe(e.trim()).replace(/\\\//g,"/").replace(/^['"]|['"]$/g,"").trim();return t=t.replace(/[)]+$/g,"").trim(),t=t.replace(/;.*$/g,"").trim(),t}function an(e){let t=qe(e).replace(/\\\//g,"/");return /[{}]|\bwindow\.|\blocation\.|\bincludes\(|\?\?null|\+|%7B|%7D|%22|<|>|\s/.test(t)||/[()[\]'"]/.test(t)}function Na(e){let t=qe(e).replace(/\\\//g,"/").trim(),r=v.extname(t).toLowerCase();return zs.has(r)||Hs.has(r)?false:/^(?:this|[A-Za-z_$][\w$]*)\.[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(t)}function tt(e){return ua.some(t=>e.pathname.startsWith(t))}function oe(e,t,r=e.sourceOrigin,n,s="url",o=false){let a=Wa(t);if(!a||a.startsWith("data:")||a.startsWith("blob:")||a.startsWith("mailto:")||a.startsWith("tel:")||a.startsWith("#"))return n?.ignore(s,t,"empty or unsupported scheme",r),null;if(an(a))return n?.ignore(s,t,"looks like JavaScript/code fragment",r),null;if(Na(a))return n?.ignore(s,t,"looks like JavaScript property access",r),null;try{let c=new URL(a,r);if(ro(c))return n?.reject(s,t,"malformed URL encoding",r),null;if(!["http:","https:"].includes(c.protocol))return n?.ignore(s,t,"unsupported protocol: ",r),null;if(!qa(e,c))return n?.ignore(s,c.toString(),"host not allowed",r),null;let i=to(e,c);if(i&&!(o&&jr(c)))return n?.reject(s,c.toString(),i,r),null;let d=new URL(e.sourceOrigin);return c.protocol=d.protocol,c.host=d.host,c.hash="",c}catch{return n?.reject(s,t,"invalid URL",r),null}}function ro(e){try{return decodeURIComponent(e.pathname),decodeURIComponent(e.search),decodeURIComponent(e.hash),!1}catch{return true}}function Ce(e,t,r,n){try{let s=new URL(e);return ro(s)?(t.reject(r,e,"malformed URL encoding",n),null):It(s.pathname)===null?(t.reject(r,e,"unsafe URL pathname",n),null):s.protocol!=="http:"&&s.protocol!=="https:"?(t.reject(r,e,`unsupported protocol: ${s.protocol}`,n),null):s}catch{return t.reject(r,e,"invalid URL",n),null}}function no(e){return zs.has(v.extname(e.pathname).toLowerCase())}function Ve(e){return tt(e)?false:Hs.has(v.extname(e.pathname).toLowerCase())}function wt(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function z(e,t){return !!(wt(t)||t.pathname==="/robots.txt"||t.pathname==="/llms.txt"||t.pathname.toLowerCase().endsWith(".xsl")||e.assetPathPrefixes.length>0&&e.assetPathPrefixes.some(r=>gn(t.pathname,r))||no(t)||!Ve(t)&&!tt(t))}function Me(e,t){let r=new URL(t),n=It(r.pathname);if(n===null)throw new Error(`Unsafe page URL pathname: ${r.pathname}`);return n.endsWith("/")?n+="index.html":v.extname(n)||(n+="/index.html"),Tt(e.outputDir,n)}function _a(e){if(!e.generated404RequestPath)return null;try{let t=new URL(e.generated404RequestPath,e.sourceOrigin);return !t.pathname.endsWith("/")&&v.extname(t.pathname)===""&&(t.pathname+="/"),t.hash="",t.toString()}catch{return null}}function gr(e,t){let r=_a(e);if(!r)return false;try{return new URL(t,e.sourceOrigin).toString()===r}catch{return false}}function Ft(e,t){let r=new URL(t),n=It(r.pathname);if(n===null)throw new Error(`Unsafe asset URL pathname: ${r.pathname}`);n.endsWith("/")&&(n+="index.html");let s=!!r.search,o=n,a=Tt(e.outputDir,o),c=_r(e.targetOrigin,o),i=`${c}${r.search}`;if(!s)return {originalPathname:o,originalFilePath:a,originalPublicUrl:c,originalPublicUrlWithSearch:i,preferQueryHashed:s};let d=v.extname(n),u=`${d?n.slice(0,-d.length):n}.${Ae(r.search)}${d||".bin"}`;return {originalPathname:o,originalFilePath:a,originalPublicUrl:c,originalPublicUrlWithSearch:i,preferQueryHashed:s,hashedPathname:u,hashedFilePath:Tt(e.outputDir,u),hashedPublicUrl:_r(e.targetOrigin,u)}}function Ba(e,t,r,n){let s=Ce(t,r,"asset",n);return s?Ft(e,s.toString()):null}function cn(e,t,r,n,s){t[r]=n;try{let o=new URL(r),c=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{c.push(new URL(e.targetOrigin).origin);}catch{}for(let i of c)try{let d=new URL(i);t[d.origin+o.pathname+o.search]=n;}catch{}try{let i=(()=>{let d=new URL(n,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin);return `${d.pathname}${d.search}`})();t[o.pathname+o.search]=i;}catch{}try{let i=new URL(n,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[o.pathname]=i;}catch{}try{let i=new URL(s,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[o.pathname]=i;}catch{}}catch{}}async function so(e){try{return await F.readFile(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}async function Ge(e){try{return await F.stat(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}function Va(e){let t=String(e["content-length"]||"").trim();if(!t)return null;let r=Number.parseInt(t,10);return Number.isFinite(r)&&r>=0?r:null}function oo(e){let t=String(e["last-modified"]||"").trim();if(!t)return null;let r=Date.parse(t);return Number.isFinite(r)?r:null}function Ka(e,t){let r=oo(t),n=Va(t),s=e?.mtime.getTime();return r!==null&&Math.abs((s??0)-r)>=1e3||n!==null&&e?.size!==n?false:r!==null||n!==null}async function za(e,t){if(!t)return;let r=oo(t);if(r===null)return;let n=await Ge(e);if(!n)return;let s=new Date(r);await F.utimes(e,n.atime,s).catch(()=>{});}function ln(e,t){let r=v.extname(e.pathname).toLowerCase(),n=t["content-type"]||"";return la.has(r)||ca.some(s=>n.includes(s))&&!n.startsWith("image/")&&!n.includes("font")}function Ha(e){try{let t=v.extname(new URL(e).pathname).toLowerCase();return t===".js"||t===".mjs"}catch{return false}}function Qe(e,t){(e.doneAssets.size%25===0||e.doneAssets.size===1||e.doneAssets.size===e.stats.assetsQueued)&&t.progress(`Asset processing progress: processed ${e.doneAssets.size}, discovered ${e.stats.assetsQueued}.`,{doneAssets:e.doneAssets.size,assetsQueued:e.stats.assetsQueued,phase:"download-assets"});}function Ja(e){return Ae(e.toString("base64"),40)}function io(e,t,r){let n=e.assetVariantDigestsByOriginalPath.get(t);if(!n||n.size===0)return false;for(let s of n)if(s!==r)return true;return false}function ao(e,t,r){let n=e.assetVariantDigestsByOriginalPath.get(t);n||(n=new Set,e.assetVariantDigestsByOriginalPath.set(t,n)),n.add(r);}async function un(e,t,r,n,s,o,a){let c=Ft(e,r),i=Ja(n),d=c.originalFilePath,l=c.originalPublicUrlWithSearch;if(c.preferQueryHashed&&c.hashedFilePath&&c.hashedPublicUrl&&io(s,c.originalFilePath,i)){let m=eo(e,t,r);m?(d=m.outputPath,l=m.publicUrl):(d=c.hashedFilePath,l=c.hashedPublicUrl);}cn(e,t,r,l,c.originalPublicUrl);let u=Ee(d)?Buffer.from(zr(n.toString("utf8"),e,t,d),"utf8"):n,g=await so(d),f=false;return (g===null||!g.equals(u))&&(await Le(d,u),f=true),o?.debug(`${f?"Saved":"Skipped unchanged"} asset output ${r}`,{phase:"download-assets",url:r,outputPath:d,bytes:u.length,wroteFile:f}),ao(s,c.originalFilePath,i),await za(d,a),s.stats.assetsSaved++,o&&(s.stats.assetsSaved%50===0||s.stats.assetsSaved===1)&&o.progress(`Asset progress: saved ${s.stats.assetsSaved}, discovered ${s.stats.assetsQueued}, pending ${s.assetQueue.length}.`,{assetsSaved:s.stats.assetsSaved,assetsQueued:s.stats.assetsQueued,assetQueue:s.assetQueue.length,phase:"download-assets"}),{outputPath:d,publicUrl:l,wroteFile:f}}function rt(e,t,r,n,s){let o=()=>{let u=String(s??"").trim();if(!u)return {discoveredFrom:"",discoveredFromType:"unknown"};if(u==="seed-path"||u==="cli"||u==="generated-404-request-path")return {discoveredFrom:u,discoveredFromType:u};if(/^https?:\/\//i.test(u))try{let g=new URL(u);return wt(g)?{discoveredFrom:u,discoveredFromType:"sitemap"}:z(e,g)?{discoveredFrom:u,discoveredFromType:"asset"}:Ve(g)&&!tt(g)?{discoveredFrom:u,discoveredFromType:"page"}:{discoveredFrom:u,discoveredFromType:"url"}}catch{return {discoveredFrom:u,discoveredFromType:"url"}}return {discoveredFrom:u,discoveredFromType:"url"}},a=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,c=oe(e,r,a,n,"page");if(!c)return;if(!Ve(c)||no(c)){if(z(e,c)){n.info(`Seeded/non-page URL queued as asset: ${c.toString()}`,{url:c.toString(),source:s}),K(e,t,c.toString(),n,s);return}n.reject("page",c.toString(),tt(c)?"asset/internal path cannot be page":"not page-like",s);return}let i=c.toString(),{discoveredFrom:d,discoveredFromType:l}=o();d&&!t.pageDiscoverySources.has(i)&&t.pageDiscoverySources.set(i,d),!t.donePages.has(i)&&!t.queuedPages.has(i)&&(t.queuedPages.add(i),t.pageQueue.push(i),t.stats.pagesQueued++,n.debug(`Queued discovered page ${i}`,{phase:"discovery",url:i,discoveredFrom:d,discoveredFromType:l,outputPath:Me(e,i)}),(t.stats.pagesQueued%25===0||t.stats.pagesQueued===1)&&n.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,pageQueue:t.pageQueue.length,phase:"discovery"}));}function K(e,t,r,n,s){let o=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,a=oe(e,r,o,n,"asset");if(!a)return;if(!z(e,a)){n.reject("asset",a.toString(),"not a safe asset path/prefix",s);return}let c=a.toString();!t.doneAssets.has(c)&&!t.queuedAssets.has(c)&&(t.queuedAssets.add(c),t.assetQueue.push(c),t.stats.assetsQueued++,(t.stats.assetsQueued%100===0||t.stats.assetsQueued===1)&&n.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,assetQueue:t.assetQueue.length,phase:"discovery"}));}function ur(e,t,r,n,s){let o=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,a=oe(e,r,o,n,"sitemap",_n(s));if(!a)return;if(!wt(a)){n.reject("sitemap",a.toString(),"not sitemap-like",s);return}let c=a.toString();!t.doneSitemaps.has(c)&&!t.queuedSitemaps.has(c)&&(t.queuedSitemaps.add(c),t.sitemapQueue.push(c),t.stats.sitemapsQueued++,(t.stats.sitemapsQueued%10===0||t.stats.sitemapsQueued===1)&&n.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,sitemapQueue:t.sitemapQueue.length,phase:"discovery"}));}function Qa(e){let t=qe(e),r=[...t.matchAll(/<url>\s*([\s\S]*?)\s*<\/url>/gi)].map(n=>n[1]);return r.length>0?r.map(n=>{let s=n.match(/<loc>\s*([^<]+?)\s*<\/loc>/i);if(!s?.[1])return null;let o=n.match(/<lastmod>\s*([^<]+?)\s*<\/lastmod>/i);return {loc:s[1].trim(),lastmod:et(o?.[1]??null)}}).filter(n=>!!n):[...t.matchAll(/<loc>\s*([^<]+?)\s*<\/loc>/gi)].map(n=>({loc:n[1].trim(),lastmod:null})).filter(n=>n.loc)}function Ga(e){return e.split(",").map(t=>t.trim().split(/\s+/)[0]).filter(Boolean)}function Za(e){let t=[],r=/url\(\s*(?:"([^"]+)"|'([^']+)'|([^)]*?))\s*\)/gi;for(let n of e.matchAll(r)){let s=e.slice(Math.max(0,n.index-8),n.index);if(/\bnew\s+$/i.test(s))continue;let o=(n[1]||n[2]||n[3]||"").trim();o&&t.push(o);}return t}function Ya(e){return e.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>/gi,"")}function Xa(e,t){if(t==="dom-style")return true;let r=(()=>{try{return v.extname(new URL(e).pathname).toLowerCase()}catch{return ""}})();return !(r===".js"||r===".mjs"||r===".map"||t.includes("javascript"))}function cr(e){return e.trim().replace(/\\/g,"/").replace(/^https?:\/\/[^/]+/i,"").replace(/^\/+/,"")}async function co(e,t,r,n){let s=[];await F.mkdir(t,{recursive:true});let o=await F.readdir(e,{withFileTypes:true});for(let a of o){let c=v.join(e,a.name),i=v.join(t,a.name);if(a.isDirectory()){s.push(...await co(c,i,r,n));continue}await lo(c,i,r,n)&&s.push(i);}return s}async function ec(e,t){try{let[r,n]=await Promise.all([F.stat(e),F.stat(t)]);if(r.size!==n.size)return !1;let[s,o]=await Promise.all([F.readFile(e),F.readFile(t)]);return s.equals(o)}catch{return false}}async function lo(e,t,r,n){let s=v.resolve(t);return r.has(s)?(n.debug("Skipped post-crawl copy over crawled page output",{phase:"copy-extra-paths",sourcePath:e,targetPath:t}),false):await ec(e,t)?(n.debug("Skipped unchanged post-crawl copy target",{phase:"copy-extra-paths",sourcePath:e,targetPath:t}),false):(await F.mkdir(v.dirname(t),{recursive:true}),await F.copyFile(e,t),true)}async function tc(e,t,r){let n=Object.entries(e.postCrawlCopyMap||{}).map(([c,i])=>({sourcePath:c.trim(),prefix:String(i||"").trim()}));if(n.length===0)return [];let s=0,o=[],a=new Set([...t.donePages].map(c=>v.resolve(Me(e,c))));r.mark("copy-extra-paths");for(let c of n){let i=c.sourcePath,d=c.prefix;if(!i||!d){r.warn("Skipped post-crawl copy mapping with empty key/value",{sourcePath:i,prefixPath:d});continue}let l=fa(i);if(!l.resolvedPath){r.warn("Skipped post-crawl copy source because alias root is not configured",{sourcePath:i,alias:l.alias||"",requiredEnv:l.requiredEnv||"",prefixPath:d});continue}let u=l.resolvedPath,g=cr(d);if(!g){r.warn("Skipped post-crawl copy mapping with invalid export prefix",{sourcePath:i,prefixPath:d});continue}let f;try{f=await F.stat(u);}catch{r.warn("Skipped post-crawl copy source because it does not exist",{sourcePath:i,sourceAbs:u,prefixPath:d});continue}let m=v.resolve(e.outputDir,g);if(f.isDirectory()){let y=await co(u,m,a,r);o.push(...y),s+=y.length,y.length>0&&r.progress(`Copied static directory to export: ${u} -> /${g}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${g}`,copiedItems:s,changedFiles:y.length});continue}let w=v.basename(u),p=d.endsWith("/")?v.join(m,w):m;await lo(u,p,a,r)&&(o.push(p),s++,r.progress(`Copied static file to export: ${u} -> /${cr(d.endsWith("/")?`${d}${w}`:d)}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${cr(d.endsWith("/")?`${d}${w}`:d)}`,copiedItems:s}));}return r.endMark("copy-extra-paths",{mappedSources:n.length,copiedItems:s}),o}function ht(e,t,r,n,s){let o=new Set,a=qe(r).replace(/\\\//g,"/"),c=s==="page-html"?Ya(a):a,i=Xa(t,s);if(i){for(let d of Za(c)){let l=oe(e,d,t,n,`${s}:css-url`);l&&z(e,l)&&o.add(l.toString());}for(let d of c.matchAll(/@import\s+(?:url\()?\s*['"]?([^'"\s;]+)['"]?\s*\)?/gi)){let l=oe(e,d[1],t,n,`${s}:css-import`);l&&z(e,l)&&o.add(l.toString());}}if(i||s==="page-html")for(let d of c.matchAll(/<\?xml-stylesheet[^>]+href=["']([^"']+)["'][^>]*\?>/gi)){let l=oe(e,d[1],t,n,`${s}:xml-stylesheet`);l&&z(e,l)&&o.add(l.toString());}if(s==="page-html")for(let d of ms(a)){let l=d.startsWith("//")?`${new URL(e.sourceOrigin).protocol}${d}`:d;if(an(l)){n.ignore(`${s}:serialized-url`,l,"looks like JavaScript/code fragment",t);continue}let u=oe(e,l,t,n,`${s}:serialized-url`);u&&z(e,u)?o.add(u.toString()):u&&n.ignore("asset",u.toString(),"serialized URL did not pass safe asset path filter",t);}if(s!=="page-html"&&Ha(t))for(let d of gs(a)){if(an(d)||!/\.(?:js|mjs)(?:[?#]|$)/i.test(d))continue;let l=oe(e,d,t,n,`${s}:relative-asset`);l&&z(e,l)&&o.add(l.toString());}return [...o]}function uo(e,t,r,n){let s=new Set,o=qe(r);for(let a of o.matchAll(/href=["']([^"'#\s][^"']*?)["']/gi)){let c=a[1],i=oe(e,c,t,n,"page-link");i&&(to(e,i)||Ve(i)&&!tt(i)&&!z(e,i)&&s.add(i.toString()));}return [...s]}async function Ls(e,t,r,n,s,o,a=false,c=[]){let i=new Set(c),d=0,l=new Map,u=(g,f)=>{let m=[f],w=new Set;for(;m.length>0;){let p=m.pop();if(p===g)return true;w.has(p)||(w.add(p),m.push(...l.get(p)??[]));}return false};for(;r.sitemapQueue.length>0;){let g=r.sitemapQueue.shift();r.queuedSitemaps.delete(g);let f=Ce(g,n,"sitemap","sitemap-queue");if(!f)continue;let m=f.toString();if(r.doneSitemaps.has(m))continue;r.doneSitemaps.add(m),n.sitemap(`Fetching sitemap ${m}`,{url:m});let w=true;try{let p=await t.get(m,{timeout:6e4});if(w=!1,!p.ok()){if(n.skip("sitemap",m,p.status()),a&&!i.has(m))throw new Error(`Required child content-sync sitemap returned HTTP ${p.status()}: ${m}`);continue}let h=await p.body(),y=p.url()||m,b=Ce(y,n,"sitemap-response",m);if(!b)continue;let P=b.toString();r.successfulSitemaps.add(m),r.successfulSitemaps.add(P),i.has(m)&&(r.resolvedSitemapRoots.add(P),d+=1);let $=await un(e,r.assetMap,P,h,r,n);ue(s,e,$.outputPath),ve(s,$.outputPath);let x=h.toString("utf8");/<sitemapindex(?:\s|>)/i.test(x)?r.sitemapIndexUrls.add(P):r.sitemapLeafUrls.add(P);let I=ht(e,P,x,n,"sitemap");for(let C of I)K(e,r,C,n,P);let R=[];for(let C of Qa(x)){let O=oe(e,C.loc,P,n,"sitemap-loc",!0);if(!O){if(a)throw new Error(`Content-sync sitemap contains an inadmissible location: ${C.loc}`);continue}if(wt(O)){if(u(P,O.toString()))throw new Error(`Sitemap index cycle detected: ${P} -> ${O.toString()}`);if(l.has(P)||l.set(P,new Set),l.get(P).add(O.toString()),R.push(O.toString()),a&&r.doneSitemaps.has(O.toString())&&!r.successfulSitemaps.has(O.toString()))throw new Error(`Required child content-sync sitemap was not resolved: ${O.toString()}`);ur(e,r,O.toString(),n,P);}else if(a){if(Ve(O)&&!z(e,O)){let V=o.requiredUrls.has(O.toString()),U=o.manifest.pages[O.toString()],S=!!U&&!!await Ge(U.outputPath);if(!V&&!S)throw new Error(`Content-sync sitemap coverage is incomplete for ${O.toString()}.`)}n.ignore("sitemap-loc",O.toString(),"content-sync sitemap-only traversal does not enqueue urlset locations",P);}else z(e,O)?K(e,r,O.toString(),n,P):Ve(O)?(C.lastmod&&(r.sitemapLastmodByPage[O.toString()]=C.lastmod),rt(e,r,O.toString(),n,P)):n.reject("sitemap-loc",O.toString(),"not page/sitemap/asset-like",P);}o.trackManifest&&(o.manifest.assets[P]={url:P,outputPath:$.outputPath,isText:!0,contentType:p.headers()["content-type"]??"application/xml",cacheControl:nn(p.headers()),changeToken:null,tokenSource:null,discoveredAssets:[...new Set([...I,...R])],lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,unreferencedRuns:0,rewriteComplete:!1},await Be(e,o));}catch(p){n.error(`Failed sitemap ${m}`,{url:m,error:String(p)});let h=a&&i.has(m)&&w;if(a&&!h)throw p}}if(a&&i.size>0&&d===0)throw new Error(`None of the configured content-sync sitemap roots could be resolved: ${[...i].join(", ")}`)}async function rc(e,t,r,n,s,o,a){let c=oe(e,n,e.sourceOrigin,s,"asset-fetch");if(!c||!z(e,c))return;let i=c.toString();if(r.doneAssets.has(i))return;let d=o.enabled||o.strictTargeted?o.previousManifest.assets[i]:void 0,l=o.trackManifest?await ar(e,t,o,i,s):null,u=l?.token??null,g=Hr(d?.changeToken,l),f=o.strictTargeted&&(!l?.supported||!l.token)&&Jr(e.sourceOrigin,i),m=o.strictTargeted?o.manifest.assets[i]:void 0;if(m?.lastSeenRunId===o.runId&&await Ge(m.outputPath)){r.doneAssets.add(i);for(let p of m.discoveredAssets||[])K(e,r,p,s,i);ue(a,e,m.outputPath),gt(a,e,m.outputPath,m.cacheControl),m.isText&&ve(a,m.outputPath),s.info(`Resumed completed content-sync asset ${i}`,{url:i,source:"content-sync-checkpoint"}),Qe(r,s);return}if(d&&(g||f)&&await Ge(d.outputPath)){o.manifest.assets[i]={...d,changeToken:u,tokenSource:l?.tokenSource??d.tokenSource,discoveredAssets:[...d.discoveredAssets||[]],lastSeenRunId:o.runId,unreferencedRuns:0},delete o.manifest.pages[i],r.doneAssets.add(i);for(let p of d.discoveredAssets||[])K(e,r,p,s,i);gt(a,e,d.outputPath,d.cacheControl),s.info(`Reused unchanged trusted asset ${i}.`,{url:i,tokenSource:l?.tokenSource??"unknown",phase:"download-assets",source:g?"asset-change-token-match":"content-sync-release-fingerprint"}),Qe(r,s);return}let w=(p,h={})=>{if(!d||o.strictTargeted)return false;o.manifest.assets[i]={...d,discoveredAssets:[...d.discoveredAssets||[]],lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,unreferencedRuns:0},delete o.manifest.pages[i],r.doneAssets.add(i);for(let y of d.discoveredAssets||[])K(e,r,y,s,i);return s.warn(`Keeping previous incremental asset ${i} after fetch issue.`,{url:i,reason:p,preservedFromPreviousManifest:true,...h,phase:"download-assets"}),Qe(r,s),true};s.asset(`Fetching asset ${i}`,{url:i});try{let p=ft(e,r.assetMap,i),h=p?await Ge(p):null;if(p&&h&&!o.strictTargeted)try{let U=await se(`fetch asset headers ${i}`,6e4,()=>t.head(i,{timeout:6e4})),S=U.headers();if(U.ok()&&Ka(h,S)){let W=await so(p);if(W!==null){let ce=U.url()||i,E=Ce(ce,s,"asset-response",i);if(!E)return;let D=E.toString(),j=await un(e,r.assetMap,D,W,r,s,S);j.wroteFile&&(ue(a,e,j.outputPath),Ee(j.outputPath)&&ve(a,j.outputPath));let X=nn(S)||d?.cacheControl||null;gt(a,e,j.outputPath,X),r.doneAssets.add(i),s.info(`Reused existing asset ${i} based on response headers.`,{url:i,filePath:p,lastModified:S["last-modified"]||"",contentLength:S["content-length"]||"",phase:"download-assets"}),Qe(r,s);let Y=ln(c,S),ee=d?.discoveredAssets?[...d.discoveredAssets]:[];if(Y||d?.isText){let H=W.toString("utf8"),de=ht(e,D,H,s,"asset:cached");(de.length>0||!d)&&(ee=de);for(let be of ee)K(e,r,be,s,D);}if(o.trackManifest){let H=Y||!!d?.isText;o.manifest.assets[i]={url:i,outputPath:j.outputPath,isText:H,contentType:rn(S)||d?.contentType||null,cacheControl:X,changeToken:l?.supported?l.token:null,tokenSource:l?.supported?l.tokenSource??null:null,discoveredAssets:ee,lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,unreferencedRuns:0,rewriteComplete:!H},delete o.manifest.pages[i],(o.enabled||o.strictTargeted)&&H&&await Be(e,o);}return}}}catch{}let y=await se(`fetch asset ${i}`,6e4,()=>t.get(i,{timeout:6e4}));if(!y.ok()){if(w(`http-${y.status()}`,{status:y.status()}))return;if(o.strictTargeted)throw new Error(`Required content-sync asset returned HTTP ${y.status()}: ${i}`);s.skip("asset",i,y.status());return}let b=await se(`read asset response ${i}`,6e4,()=>y.body()),P=y.url()||i,$=Ce(P,s,"asset-response",i);if(!$)return;let x=$.toString(),I=y.headers(),R=await un(e,r.assetMap,x,b,r,s,I);R.wroteFile&&(ue(a,e,R.outputPath),Ee(R.outputPath)&&ve(a,R.outputPath));let C=nn(I);gt(a,e,R.outputPath,C),r.doneAssets.add(i),Qe(r,s);let O=ln(c,I),V=[];if(O){let U=b.toString("utf8");V=ht(e,x,U,s,`asset:${v.extname(c.pathname).toLowerCase()||I["content-type"]||"unknown"}`);for(let S of V)K(e,r,S,s,x);}o.trackManifest&&(o.manifest.assets[i]={url:i,outputPath:R.outputPath,isText:O,contentType:rn(I),cacheControl:C,changeToken:l?.supported?l.token:null,tokenSource:l?.supported?l.tokenSource??null:null,discoveredAssets:V,lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,unreferencedRuns:0,rewriteComplete:!O},delete o.manifest.pages[i],(o.enabled||o.strictTargeted)&&O&&await Be(e,o));}catch(p){if(w("fetch-error",{error:String(p)}))return;if(s.error(`Failed asset ${i}`,{url:i,error:String(p)}),o.strictTargeted)throw p}finally{r.doneAssets.has(i)||(r.doneAssets.add(i),Qe(r,s));}}async function nc(e,t,r,n,s,o){let a=Math.max(1,Number(e.assetDownloadConcurrency||e.concurrency||1)),c=Array.from({length:a},async()=>{for(;r.assetQueue.length>0;){let i=r.assetQueue.shift();i&&(r.queuedAssets.delete(i),await rc(e,t,r,i,n,s,o));}});await Promise.all(c);}function dr(e,t){let r=me(e.outputDir,t);if(!r)throw new Error(`Remote export output is outside outputDir: ${t}`);return r}function sc(e,t){return ln(e,{"content-type":t})}function qs(e){return /(?:^|\/)index\.html?$|\.html?$/i.test(e)}async function oc(e,t,r,n,s,o,a,c,i){let d=Math.max(1,Math.min(100,i)),l=20;for(;r.assetQueue.length>0;){let u=r.assetQueue.splice(0,d*l);for(let w of u)r.queuedAssets.delete(w);await mn(e,t,s,u,n);let g=[];for(let w of u){let p=s.manifest.assets[w],h=p?me(e.outputDir,p.outputPath):null,y=h?a.objects[h]:void 0,b=s.changeTokenCache.get(w)??null;if(!(s.enabled&&p&&y?.kind==="asset"&&y.sourceUrl===w&&(Hr(p.changeToken,b)||(!b?.supported||!b.token)&&Jr(e.sourceOrigin,w)))||!p||!h||!y){g.push(w);continue}s.manifest.assets[w]={...p,changeToken:b?.token??null,tokenSource:b?.tokenSource??p.tokenSource,lastSeenRunId:s.runId,unreferencedRuns:0};for(let $ of p.discoveredAssets||[])K(e,r,$,n,w);r.doneAssets.add(w),gt(o,e,p.outputPath,p.cacheControl),n.info(`Reused unchanged S3-native asset ${w}.`,{url:w,relativePath:h,tokenSource:b?.tokenSource??"release-fingerprint",phase:"download-assets",execution:"lambda"}),Qe(r,n);}if(g.length===0)continue;let f=[];for(let w=0;w<g.length;w+=l)f.push(g.slice(w,w+l));let m=await Promise.all(f.map(w=>c.fetch({urls:w,ignoreHttpsErrors:e.ignoreHttpsErrors,timeoutMs:6e4})));for(let w of m)for(let p of w.assets){let h=p.requestedUrl;try{if(p.outcome!=="fetched"||!p.object||!p.finalUrl){let C=p.error||`Remote asset fetch ended with ${p.outcome}.`;if(n.error(`Failed remote asset ${h}`,{url:h,status:p.httpStatus,outcome:p.outcome,error:C,execution:"lambda"}),s.strictTargeted)throw new Error(C);continue}let y=Ce(p.finalUrl,n,"remote-asset-response",h);if(!y)continue;let b=Ft(e,y.toString()),P=b.originalFilePath,$=b.originalPublicUrlWithSearch;if(b.preferQueryHashed&&b.hashedFilePath&&b.hashedPublicUrl&&io(r,b.originalFilePath,p.object.sha256)){let C=eo(e,r.assetMap,y.toString());P=C?.outputPath??b.hashedFilePath,$=C?.publicUrl??b.hashedPublicUrl;}cn(e,r.assetMap,y.toString(),$,b.originalPublicUrl),y.toString()!==h&&cn(e,r.assetMap,h,$,b.originalPublicUrl),ao(r,b.originalFilePath,p.object.sha256);let x=dr(e,P),I=p.contentType?.trim()||"application/octet-stream",R=sc(y,I);mt(a,{relativePath:x,sourceUrl:h,kind:"asset",contentType:I,cacheControl:p.cacheControl,isText:R,object:p.object}),ue(o,e,P),R&&ve(o,P),gt(o,e,P,p.cacheControl);for(let C of p.discoveredAssets)K(e,r,C,n,y.toString());r.stats.assetsSaved++,s.trackManifest&&(s.manifest.assets[h]={url:h,outputPath:P,isText:R,contentType:I,cacheControl:p.cacheControl,changeToken:null,tokenSource:null,discoveredAssets:[...p.discoveredAssets],lastCrawledAt:new Date().toISOString(),lastSeenRunId:s.runId,unreferencedRuns:0,rewriteComplete:!R},delete s.manifest.pages[h]),n.debug(`Remote asset fetch completed ${h}`,{url:h,finalUrl:y.toString(),relativePath:x,bytes:p.object.bytes,taskId:w.taskId,attempts:w.attempts,execution:"lambda"});}finally{r.doneAssets.add(h),Qe(r,n);}}}}async function ic(e,t,r,n){for(let s of [...t.changedFiles].sort()){if(r.objects[s])continue;let o=v.join(e.outputDir,s),a=await F.readFile(o).catch(l=>{throw new Error(`Coordinator-owned output is missing before S3 staging: ${s}`,{cause:l})}),c=Ee(o),i=String(ks.lookup(s)||"")||(c?"text/plain; charset=utf-8":"application/octet-stream"),d=await n.writeWorkspaceObject({key:`${r.workspace.prefix}jobs/${r.jobId}/coordinator/${Ae(s,40)}-${v.basename(s)}`,body:a,contentType:i,cacheControl:qs(s)?e.s3.htmlCacheControl:e.s3.assetCacheControl});mt(r,{relativePath:s,sourceUrl:null,kind:"generated",contentType:i,cacheControl:qs(s)?e.s3.htmlCacheControl:e.s3.assetCacheControl,isText:c,object:d});}}function ac(e){let t=Math.ceil(e/1e3);return `${t} second${t===1?"":"s"}`}function _e(e){return Math.max(6e4,e.navigationTimeoutMs*2,e.readiness.timeoutMs+e.readiness.fallbackWaitMs+15e3)}function Et(e){return Math.max(15e3,Math.min(6e4,_e(e)))}function po(e){return Math.max(15e3,e.readiness.timeoutMs+e.readiness.fallbackWaitMs+1e4)}function fn(e){return e.stats.pagesCompleted}function dn(e){let r=e.options?.browserProcess;return {pid:typeof r?.process?.pid=="number"?r.process.pid:null,kill:typeof r?.kill=="function"?r.kill.bind(r):null}}async function tn(e,t,r){let n=dn(e);try{if(n.kill){await n.kill(),t.warn(`Force-killed crawl worker browser after ${r}`,{browserPid:n.pid,reason:r});return}if(n.pid!==null){process.kill(n.pid,"SIGKILL"),t.warn(`Sent SIGKILL to crawl worker browser after ${r}`,{browserPid:n.pid,reason:r});return}t.warn(`Could not resolve crawl worker browser PID after ${r}`,{reason:r});}catch(s){t.error(`Failed to force-kill crawl worker browser after ${r}`,{browserPid:n.pid,reason:r,error:String(s)});}}async function se(e,t,r){let n;try{return await Promise.race([r(),new Promise((s,o)=>{n=globalThis.setTimeout(()=>{o(new Ot(e,t));},t);})])}finally{n!==void 0&&globalThis.clearTimeout(n);}}var Ot=class extends Error{constructor(r,n){super(`${r} timed out after ${ac(n)}.`);this.operation=r;this.timeoutMs=n;this.name="OperationTimeoutError";}operation;timeoutMs};async function cc(e,t){let r=po(e);await t.evaluate(async n=>{await new Promise(s=>{let o=0,a=700,c=Date.now(),i=()=>{window.clearInterval(d),window.scrollTo(0,0),s();},d=window.setInterval(()=>{if(Date.now()-c>=n.maxDurationMs){i();return}window.scrollBy(0,a),o+=a;let l=document.body?.scrollHeight||0,u=document.documentElement?.scrollHeight||0,g=Math.max(l,u);o>=g+window.innerHeight&&i();},120);});},{maxDurationMs:r});}async function lc(e,t){await t.waitForLoadState("domcontentloaded",{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForSelector&&await t.waitForSelector(e.readiness.waitForSelector,{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForFunction&&await t.waitForFunction(e.readiness.waitForFunction,void 0,{timeout:e.readiness.timeoutMs}).catch(()=>{}),await cc(e,t),await t.waitForTimeout(e.readiness.fallbackWaitMs);}async function uc(e,t){await t.waitForLoadState("domcontentloaded",{timeout:e.readiness.timeoutMs}).catch(()=>{}),await t.waitForLoadState("load",{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForSelector&&await t.waitForSelector(e.readiness.waitForSelector,{timeout:e.readiness.timeoutMs}).catch(()=>{}),await t.waitForTimeout(e.readiness.fallbackWaitMs);}function mo(e,t){return e.noJavaScriptRenderPathPrefixes.some(r=>gn(t,r))}async function dc(e,t,r,n,s=true){let o=new Set;if(s){let c=await t.evaluate(()=>{let i=new Set,d=["href","src","poster","data-src","data-lazy-src","data-original","data-bg","data-background","data-href","data-resource-url"],l=new Set,u=["srcset","data-srcset","data-lazy-srcset"],g=f=>{f.querySelectorAll("*").forEach(m=>{for(let p of d){let h=m.getAttribute(p);h&&i.add(h);}for(let p of u){let h=m.getAttribute(p);h&&h.split(",").forEach(y=>{let b=y.trim().split(/\s+/)[0];b&&i.add(b);});}let w=m.getAttribute("style");w&&l.add(w),m.shadowRoot&&g(m.shadowRoot);});};return g(document),{attrs:[...i],styles:[...l]}});for(let i of c.attrs)for(let d of Ga(i)){let l=oe(e,d,r,n,"dom-attr");l&&z(e,l)&&o.add(l.toString());}for(let i of c.styles)for(let d of ht(e,r,i,n,"dom-style"))o.add(d);}let a=await t.content();for(let c of ht(e,r,a,n,"page-html"))o.add(c);return [...o]}async function Ws(e){return await e.evaluate(()=>{document.querySelectorAll("#wpsuite-consent-root").forEach(t=>t.remove()),document.documentElement.classList.remove("wpsuite-consent-scroll-locked"),document.body.classList.remove("wpsuite-consent-scroll-locked");}),e.content()}async function pn(e,t,r,n,s){let o=Me(e,t);await Le(o,r,"utf8");let a=await F.stat(o);s?.debug(`Saved page output ${t}`,{phase:"save-pages",url:t,outputPath:o,bytes:a.size});let c=pr(n,o),i=Math.min(n.stats.pagesQueued,fn(n)+1);s&&c&&(n.stats.pagesSaved%10===0||n.stats.pagesSaved===1)&&s.progress(`Page progress: processed ${i}, rendered ${n.stats.pagesRendered}, saved ${n.stats.pagesSaved}, discovered ${n.stats.pagesQueued}.`,{donePages:i,claimedPages:n.donePages.size,pagesRendered:n.stats.pagesRendered,pagesSaved:n.stats.pagesSaved,pagesQueued:n.stats.pagesQueued,pageQueue:n.pageQueue.length,phase:"save-pages"});}function pr(e,t){let r=v.resolve(t);return e.savedPageOutputs.has(r)?false:(e.savedPageOutputs.add(r),e.stats.pagesSaved=e.savedPageOutputs.size,true)}async function mr(e,t,r,n,s){let o=me(e.outputDir,n);if(!o)return;if(s){let c=s.objects[o];c?.kind==="page"&&c.sourceUrl===r&&c.object?.bucket===s.workspace.bucket&&typeof c.object.key=="string"&&c.object.key.startsWith(s.workspace.prefix)&&pr(t,n);return}(await Ge(n).catch(()=>null))?.isFile()&&pr(t,n);}function go(e){let t=fn(e);return t%5===0||t===1||t===e.stats.pagesQueued}function fo(e,t){let r=fn(e);t.progress(`Render progress: processed ${r}, rendered ${e.stats.pagesRendered}, saved ${e.stats.pagesSaved}, discovered ${e.stats.pagesQueued}.`,{donePages:r,claimedPages:e.donePages.size,pagesRendered:e.stats.pagesRendered,pagesSaved:e.stats.pagesSaved,pagesQueued:e.stats.pagesQueued,phase:"render-pages"});}async function pc(e){await e.addInitScript(()=>{Object.defineProperty(window,"__WPSUITE_STATIC_EXPORT__",{value:true,writable:false,configurable:true});let t=r=>{if(r==null||String(r)==="")return true;try{let n=new URL(String(r),window.location.href),s=new URL(window.location.href);return n.hash="",s.hash="",n.href===s.href}catch{return false}};try{let r=window.location.assign.bind(window.location),n=window.location.replace.bind(window.location),s=window.location.reload.bind(window.location);Object.defineProperty(window.location,"assign",{configurable:!0,value:o=>{if(t(o)){console.warn("[smartcloud-static-publisher] blocked same-page location.assign",o??"");return}return r(o)}}),Object.defineProperty(window.location,"replace",{configurable:!0,value:o=>{if(t(o)){console.warn("[smartcloud-static-publisher] blocked same-page location.replace",o??"");return}return n(o)}}),Object.defineProperty(window.location,"reload",{configurable:!0,value:()=>{console.warn("[smartcloud-static-publisher] blocked location.reload");}});}catch{}});}async function mc(e,t,r){let n=await e.newContext({viewport:t.viewport,userAgent:"WPSuiteStaticPublisher/0.8 Playwright SitemapOnly",ignoreHTTPSErrors:t.ignoreHttpsErrors,...r?{javaScriptEnabled:false}:{}});return r||await pc(n),n}async function gc(e,t,r,n,s,o,a,c,i,d){for(;t.pageQueue.length>0&&!(e.maxPages>0&&t.donePages.size>=e.maxPages);){let l=t.pageQueue.shift();if(!l)break;t.queuedPages.delete(l);try{let u=Ce(l,r,"page","page-queue");if(!u)continue;let g=u.toString();if(l=g,t.queuedPages.delete(l),t.donePages.has(l))continue;t.donePages.add(l),o.enabled&&o.seenPages.add(l);let f=gr(e,l),m=mo(e,u.pathname);if(!Ve(u)||z(e,u)||tt(u)){if(z(e,u)){r.info(`Remote worker redirected non-page URL to asset queue: ${l}`,{url:l,source:"remote-worker-guard"}),K(e,t,l,r,"remote-worker-guard");continue}r.reject("page",l,"guard rejected non-page URL before remote rendering","remote-worker");continue}let w=o.strictTargeted?o.manifest.pages[l]:void 0;if(w?.lastSeenRunId===o.runId&&await Ge(w.outputPath)){o.seenPages.add(l);for(let R of w.discoveredAssets||[])K(e,t,R,r,l);ue(a,e,w.outputPath),ve(a,w.outputPath),await mr(e,t,l,w.outputPath,d),r.info(`Resumed completed content-sync page ${l}`,{url:l,source:"content-sync-checkpoint"});continue}let p=await Ys(e,s,t,o,l,r);if(o.enabled&&n!=="single-url"&&n!=="content-sync"){let R=o.manifest.pages[l];if(p.action==="reuse"&&R){for(let C of R.discoveredAssets)K(e,t,C,r,l);for(let C of R.discoveredPages)rt(e,t,C,r,l);R.lastSeenRunId=o.runId,R.sitemapLastmod=et(t.sitemapLastmodByPage[l])??R.sitemapLastmod,p.changeToken?.supported&&(R.changeToken=p.changeToken.token,R.tokenSource=p.changeToken.tokenSource??R.tokenSource),await mr(e,t,l,R.outputPath,d),r.info(`Incremental reuse skipped unchanged page ${l}`,{url:l,mode:"incremental",reason:p.changeToken?.supported===!0?"change-token-match":"sitemap-lastmod-match"});continue}}r.page(`Rendering remotely ${l}`,{url:l,execution:"lambda"});let h=await i.render({sourceOrigin:e.sourceOrigin,url:l,options:{ignoreHttpsErrors:e.ignoreHttpsErrors,javaScriptEnabled:!m,viewport:e.viewport,navigationTimeoutMs:e.navigationTimeoutMs,autoScrollTimeoutMs:po(e),readiness:e.readiness},downloadHtml:!d}),y=h.page,b=y.finalUrl?Ce(y.finalUrl,r,"remote-final-response",l)?.toString():void 0;if(n==="content-sync"&&b&&b!==g){if(o.deleteOnMissingUrls.has(l)){await Mt(e,o,a,l,o.deleteOnMissingUrls),r.info(`Removed stale content-sync archive route redirected to ${b}`,{url:l,finalResponseUrl:b,source:"content-sync-tombstone"});continue}throw new Error(`Required content-sync route redirected outside its planned URL: ${l} -> ${b}`)}let P=y.httpStatus;if(f){if(P!==404){r.error(`Generated 404 request path returned unexpected status for ${l}`,{url:l,expectedStatus:404,status:P,requestPath:e.generated404RequestPath,execution:"lambda"});continue}}else if(P!==null&&P>=400){if(n==="content-sync"&&(P===404||P===410)&&o.deleteOnMissingUrls.has(l)){await Mt(e,o,a,l,o.deleteOnMissingUrls),r.info(`Removed stale content-sync archive page ${l}`,{url:l,status:P,source:"content-sync-tombstone"});continue}if(n==="content-sync")throw new Error(`Required content-sync route returned HTTP ${P}: ${l}`);r.skip("page",l,P,t.pageDiscoverySources.get(l));continue}t.stats.pagesRendered++;let $=new Set;if(!d){if(h.html===null)throw new Error("Remote render did not return HTML for local output mode.");for(let R of ht(e,g,h.html,r,"remote-page-html"))$.add(R);}for(let R of [...y.discoveredAssets,...y.networkUrls]){let C=oe(e,R,g,r,"remote-render");C&&z(e,C)&&$.add(C.toString());}for(let R of $)K(e,t,R,r,l);let x=n!=="single-url"&&n!=="content-sync"&&!f?[...new Set([...!d&&h.html!==null?uo(e,l,h.html,r):[],...y.discoveredPages])]:[];for(let R of x)rt(e,t,R,r,l);for(let R of y.cookies){let C=R.sameSite==="Strict"||R.sameSite==="Lax"||R.sameSite==="None"?R.sameSite:"Unspecified",O=!Number.isFinite(R.expires)||R.expires<=0;c.add({name:R.name,domain:R.domain,path:R.path||"/",expires:O?null:R.expires,session:O,secure:R.secure,httpOnly:R.httpOnly,sameSite:C,partitioned:R.partitioned===!0});}let I=Me(e,l);if(d){if(!y.html)throw new Error("Remote render completed without a workspace HTML object.");mt(d,{relativePath:dr(e,I),sourceUrl:l,kind:"page",contentType:y.contentType?.trim()||"text/html; charset=utf-8",cacheControl:e.s3.htmlCacheControl,isText:!0,object:y.html}),pr(t,I);}else {if(h.html===null)throw new Error("Remote render did not return HTML for local output mode.");await pn(e,l,h.html,t,r);}ue(a,e,I),ve(a,I),o.trackManifest&&(o.manifest.pages[l]={url:l,outputPath:I,contentType:y.contentType?.trim()||null,changeToken:p.changeToken?.supported?p.changeToken.token:null,tokenSource:p.changeToken?.supported?p.changeToken.tokenSource??null:null,sitemapLastmod:et(t.sitemapLastmodByPage[l])??null,discoveredPages:x,discoveredAssets:[...$],lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,rewriteComplete:!1},(o.enabled||o.strictTargeted)&&await Be(e,o)),r.debug(`Remote render completed ${l}`,{url:l,taskId:h.taskId,attempts:h.attempts,execution:"lambda"});}catch(u){if(r.error(`Failed remote page ${l}`,{url:l,error:String(u),execution:"lambda"}),o.strictTargeted)throw u}finally{t.stats.pagesCompleted++,go(t)&&fo(t,r);}}}async function fc(e,t,r,n,s,o,a,c){let i=await chromium.launch({headless:true}),d=dn(i);d.pid!==null&&r.debug(`Launched crawl worker browser PID ${d.pid}`,{browserPid:d.pid});try{for(;t.pageQueue.length>0;){i||(i=await chromium.launch({headless:!0}),d=dn(i),d.pid!==null&&r.debug(`Relaunched crawl worker browser PID ${d.pid}`,{browserPid:d.pid}));let l=i;if(e.maxPages>0&&t.donePages.size>=e.maxPages)break;let u=t.pageQueue.shift();if(!u)break;t.queuedPages.delete(u);let g=null,f=null,m=!1,w=[],p=new Set;try{let h=Ce(u,r,"page","page-queue");if(!h)continue;let y=h.toString();if(u=y,t.queuedPages.delete(u),t.donePages.has(u))continue;t.donePages.add(u),o.enabled&&o.seenPages.add(u);let b=gr(e,u),P=mo(e,h.pathname);if(!Ve(h)||z(e,h)||tt(h)){if(z(e,h)){r.info(`Worker redirected non-page URL to asset queue: ${u}`,{url:u,source:"worker-guard"}),K(e,t,u,r,"worker-guard");continue}r.reject("page",u,"guard rejected non-page URL before rendering","worker");continue}let $=o.strictTargeted?o.manifest.pages[u]:void 0;if($?.lastSeenRunId===o.runId&&await Ge($.outputPath)){o.seenPages.add(u);for(let E of $.discoveredAssets||[])K(e,t,E,r,u);ue(a,e,$.outputPath),ve(a,$.outputPath),await mr(e,t,u,$.outputPath),r.info(`Resumed completed content-sync page ${u}`,{url:u,source:"content-sync-checkpoint"});continue}let x=await Ys(e,s,t,o,u,r);if(o.enabled&&n!=="single-url"&&n!=="content-sync"){let E=o.manifest.pages[u];if(x.action==="reuse"&&E){for(let D of E.discoveredAssets)K(e,t,D,r,u);for(let D of E.discoveredPages)rt(e,t,D,r,u);E.lastSeenRunId=o.runId,E.sitemapLastmod=et(t.sitemapLastmodByPage[u])??E.sitemapLastmod,x.changeToken?.supported&&(E.changeToken=x.changeToken.token,E.tokenSource=x.changeToken.tokenSource??E.tokenSource),await mr(e,t,u,E.outputPath),r.info(`Incremental reuse skipped unchanged page ${u}`,{url:u,mode:"incremental",reason:x.changeToken?.supported===!0?"change-token-match":"sitemap-lastmod-match"});continue}}g=await se(`create page context ${u}`,_e(e),()=>mc(l,e,P)),f=await se(`create page ${u}`,_e(e),()=>g.newPage()),w=await g.cookies();let I=!1,R=new Set;await f.route("**/*",async E=>{let D=E.request();try{let j=oe(e,D.url(),e.sourceOrigin,r,"network-request");j&&z(e,j)&&(R.add(j.toString()),K(e,t,j.toString(),r,u));}catch{}if(D.isNavigationRequest()&&D.frame()===f.mainFrame())try{let j=new URL(D.url()),X=new URL(y);if(j.hash="",X.hash="",j.href===X.href){if(I){r.warn(`Blocked same-page navigation/reload for ${u}`,{url:u,requestUrl:D.url()});try{await E.abort("aborted");}catch(Y){r.debug(`Ignored canceled route while blocking reload for ${u}`,{url:u,error:String(Y)});}return}I=!0;}}catch{}try{await E.continue();}catch(j){r.debug(`Ignored canceled network route for ${u}`,{url:u,requestUrl:D.url(),error:String(j)});}}),f.on("response",E=>{try{let j=oe(e,E.url(),e.sourceOrigin,r,"network-response");j&&z(e,j)&&(R.add(j.toString()),K(e,t,j.toString(),r,u));}catch{}let D=E.headerValues("set-cookie").then(j=>{for(let X of j)c.add(bs(X,E.url()));}).catch(()=>{}).then(()=>{});p.add(D),D.finally(()=>p.delete(D));}),r.page(`Rendering ${u}`,{url:u});let C=null,O=null;try{if(C=await f.goto(u,{waitUntil:"domcontentloaded",timeout:e.navigationTimeoutMs}),C&&C.ok())try{O=await se(`read response body ${u}`,_e(e),()=>C.text());}catch{O=null;}}catch(E){r.warn(`Navigation issue for ${u}; saving current DOM if available`,{url:u,error:String(E)});}if(n==="content-sync"&&C){let E=Ce(C.url(),r,"content-sync-final-response",u)?.toString();if(E&&E!==y){if(o.deleteOnMissingUrls.has(u)){await Mt(e,o,a,u,o.deleteOnMissingUrls),r.info(`Removed stale content-sync archive route redirected to ${E}`,{url:u,finalResponseUrl:E,source:"content-sync-tombstone"});continue}throw new Error(`Required content-sync route redirected outside its planned URL: ${u} -> ${E}`)}}if(b){let E=C?.status()??null;if(E!==404){r.error(`Generated 404 request path returned unexpected status for ${u}`,{url:u,expectedStatus:404,status:E,requestPath:e.generated404RequestPath});continue}r.info(`Capturing rendered 404 page for ${u}`,{url:u,status:E,outputPath:Me(e,u)});}else if(C&&!C.ok()){if(n==="content-sync"&&(C.status()===404||C.status()===410)&&o.deleteOnMissingUrls.has(u)){await Mt(e,o,a,u,o.deleteOnMissingUrls),r.info(`Removed stale content-sync archive page ${u}`,{url:u,status:C.status(),source:"content-sync-tombstone"}),await f.close();continue}if(n==="content-sync")throw new Error(`Required content-sync route returned HTTP ${C.status()}: ${u}`);r.skip("page",u,C.status(),t.pageDiscoverySources.get(u)),await f.close();continue}P?(r.info(`Rendering without JS execution for ${u}`,{url:u,mode:"no-js"}),await se(`wait for rendered page ${u}`,_e(e),()=>uc(e,f))):await se(`wait for rendered page ${u}`,_e(e),()=>lc(e,f)),t.stats.pagesRendered++;let V=await se(`extract rendered assets ${u}`,_e(e),()=>dc(e,f,y,r,!P));for(let E of V)K(e,t,E,r,u);let U=[...new Set([...V,...R])],S=O??await se(`capture rendered html ${u}`,_e(e),()=>Ws(f)),W=n!=="single-url"&&n!=="content-sync"&&!b?uo(e,u,S,r):[];if(n!=="single-url"&&n!=="content-sync"&&!b)for(let E of W)rt(e,t,E,r,u);await pn(e,u,S,t,r);let ce=Me(e,u);if(ue(a,e,ce),ve(a,ce),o.trackManifest){let E=C?.headers();o.manifest.pages[u]={url:u,outputPath:ce,contentType:rn(E),changeToken:x.changeToken?.supported?x.changeToken.token:null,tokenSource:x.changeToken?.supported?x.changeToken.tokenSource??null:null,sitemapLastmod:et(t.sitemapLastmodByPage[u])??null,discoveredPages:W,discoveredAssets:U,lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,rewriteComplete:!1},(o.enabled||o.strictTargeted)&&await Be(e,o);}}catch(h){if(m=h instanceof Ot,o.strictTargeted)throw r.error(`Failed required content-sync page ${u}`,{url:u,error:String(h)}),h;if(m)r.warn(`Skipped partial DOM for timed-out page ${u}`,{url:u,error:String(h),recovery:"recycle-worker-browser"});else try{let y=f?await se(`capture partial html ${u}`,_e(e),()=>Ws(f)):"";if(y&&y.trim()){await pn(e,u,y,t,r);let b=Me(e,u);if(ue(a,e,b),ve(a,b),o.trackManifest){let P=o.manifest.pages[u]??o.previousManifest.pages[u];o.manifest.pages[u]={url:u,outputPath:b,contentType:P?.contentType??null,changeToken:null,tokenSource:null,sitemapLastmod:et(t.sitemapLastmodByPage[u])??P?.sitemapLastmod??null,discoveredPages:P?.discoveredPages?[...P.discoveredPages]:[],discoveredAssets:P?.discoveredAssets?[...P.discoveredAssets]:[],lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,rewriteComplete:!1},(o.enabled||o.strictTargeted)&&await Be(e,o);}r.warn(`Saved partial DOM for ${u}`,{url:u,error:String(h)});}}catch(y){y instanceof Ot&&(m=!0),r.error(`Could not save partial DOM for ${u}`,{url:u,error:String(y)});}r.error(`Failed page ${u}`,{url:u,error:String(h)});}finally{if(!m&&f&&await se(`drain network routes ${u}`,Et(e),()=>f.unrouteAll({behavior:"wait"})).catch(h=>{m=!0,r.warn(`Could not drain network routes for ${u}`,{url:u,browserPid:d.pid,error:String(h),recovery:"recycle-worker-browser"});}),m&&(i=null,await tn(l,r,`page operation timeout for ${u}`),await l.close().catch(()=>{})),p.size>0&&await Promise.allSettled([...p]),!m&&g)try{let h=await g.cookies();c.addAll(Ss(w,h));}catch{}t.stats.pagesCompleted++,go(t)&&fo(t,r),!m&&f&&await se(`close page ${u}`,Et(e),()=>f.close()).catch(h=>{m=!0,r.warn(`Timed out while closing page ${u}`,{url:u,browserPid:d.pid,error:String(h),recovery:"recycle-worker-browser"});}),!m&&g&&await se(`close page context ${u}`,Et(e),()=>g.close()).catch(h=>{m=!0,r.warn(`Timed out while closing page context for ${u}`,{url:u,browserPid:d.pid,error:String(h),recovery:"recycle-worker-browser"});}),m&&i===l&&(i=null,await tn(l,r,`page cleanup timeout for ${u}`),await l.close().catch(()=>{}));}}}finally{if(i){let l=i;await se("close worker browser",Et(e),()=>l.close()).catch(u=>(r.warn("Timed out while closing crawl worker browser",{browserPid:d.pid,error:String(u)}),tn(l,r,"browser.close timeout")));}}}async function hc(e){try{let t=await F.readFile(e),n=(e.endsWith(".gz")?gunzipSync(t):t).toString("utf8").trim();if(!n)return [];try{let s=JSON.parse(n);if(Array.isArray(s))return s;if(s&&typeof s=="object")return [s]}catch{return n.split(/\r?\n/).map(s=>s.trim()).filter(Boolean).map(s=>{try{let o=JSON.parse(s);return o&&typeof o=="object"?o:null}catch{return null}}).filter(s=>s!==null)}return []}catch{return []}}function Ns(e){let t=String(e||"").toLowerCase();return t.includes("timeout")||t.includes("timed out")||t.includes("navigation timeout")}function wc(e){let t=String(e?.job?.command||"").trim(),r=String(e?.job?.crawlMode||"full").trim();return t!=="publish"&&t!=="crawl"?false:r!=="incremental"}function yc(e){let t=[e?.archivedAt,e?.job?.endedAt,e?.job?.startedAt];for(let r of t){let n=Date.parse(String(r||""));if(Number.isFinite(n))return n}return 0}async function ho(e){try{let t=await F.readFile(e,"utf8"),r=JSON.parse(t);return r&&typeof r=="object"&&!Array.isArray(r)?r:null}catch{return null}}function _s(e){let t=String(e.originalFileName||"").toLowerCase();return t.endsWith("errors.jsonl")?0:t.endsWith("errors.json")?1:2}function bc(e,t){let r=Array.isArray(t?.artifacts)?t.artifacts.filter(n=>String(n?.role||"").trim()==="errors"&&String(n?.storedFileName||"").trim()!=="").sort((n,s)=>_s(n)-_s(s)).map(n=>v.join(e,String(n.storedFileName))):[];return [...new Set([...r,v.join(e,"errors.jsonl"),v.join(e,"errors.json"),v.join(e,"errors.jsonl.gz"),v.join(e,"errors.json.gz")])]}async function Bs(e){let t=await ho(v.join(e,"job.json"));for(let r of bc(e,t)){let n=await hc(r);if(n.length>0)return n}return []}async function Sc(e){let t=v.join(e.logDir,"archive"),r;try{r=await F.readdir(t);}catch{return ""}let n="",s=0;for(let o of r){let a=v.join(t,o);if(!(await F.stat(a).catch(()=>null))?.isDirectory())continue;let i=await ho(v.join(a,"job.json"));if(!wc(i))continue;let d=yc(i);d>=s&&(s=d,n=a);}return n}async function Pc(e){let t=await Sc(e),r=t!==""?await Bs(t):await Bs(e.logDir),n=new Set;for(let s of r)if(Ns(s.error)||Ns(s.message)){let o=s.url;typeof o=="string"&&o&&n.add(o);}return [...n]}async function Rc(e){let t=[];for(let r of e)if(r.startsWith("@")){let n=r.slice(1),s=await F.readFile(n,"utf8");t.push(...s.split(/\r?\n/).map(o=>o.trim()).filter(o=>o&&!o.startsWith("#")));}else t.push(r);return t}async function vc(e){if(!e)throw new Error("Content-sync crawl requires an immutable impact plan.");let t=JSON.parse(await F.readFile(e,"utf8"));return Rt(t),t}function Cc(e,t){let r;try{r=new URL(e);}catch{return false}return t.archiveFamilies.some(n=>{let s=new URL(n.url);if(r.origin!==s.origin)return false;if(r.toString()===s.toString())return true;if(r.searchParams.has("paged")&&r.pathname===s.pathname)return /^\d+$/.test(r.searchParams.get("paged")||"");let o=s.pathname.replace(/\/+$/,""),a=r.pathname.slice(o.length).replace(/^\/+/,""),c=String(n.paginationBase||"page").replace(/^\/+|\/+$/g,"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return r.pathname.startsWith(`${o}/`)&&new RegExp(`^${c}/\\d+/?$`).test(a)})}function At(e,t,r){let n=r==="page"?Me(e,t):Ft(e,t).originalFilePath;return me(e.outputDir,n)}async function Mt(e,t,r,n,s){let o=t.manifest.pages[n];if(!o)return;let a=me(e.outputDir,o.outputPath);if(!a)throw new Error(`Manifest-owned page path escaped output root: ${n}`);let c=v.resolve(o.outputPath);Object.entries(t.manifest.pages).some(([d,l])=>d!==n&&!s.has(d)&&v.resolve(l.outputPath)===c)||(await F.rm(o.outputPath,{force:true}),r.deletedFiles.add(a),r.revalidateFiles.delete(a)),delete t.manifest.pages[n];}async function kc(e,t,r,n,s){let o=t.manifest.assets[n];if(!o)return;let a=me(e.outputDir,o.outputPath);if(!a)throw new Error(`Manifest-owned resource path escaped output root: ${n}`);let c=v.resolve(o.outputPath);Object.entries(t.manifest.assets).some(([d,l])=>d!==n&&!s.has(d)&&v.resolve(l.outputPath)===c)||(await F.rm(o.outputPath,{force:true}),r.deletedFiles.add(a)),delete t.manifest.assets[n];}function xc(e,t){let r=new Set,n=[...t];for(;n.length>0;){let s=n.shift();if(r.has(s))continue;r.add(s);let o=e.assets[s];for(let a of o?.discoveredAssets??[])try{wt(new URL(a))&&n.push(a);}catch{}}return r}async function Ic(e,t,r,n,s){let o=xc(r.previousManifest,s);for(let a of o){if(t.successfulSitemaps.has(a))continue;let c=r.previousManifest.assets[a];if(!c)continue;let i=me(e.outputDir,c.outputPath);if(!i)throw new Error(`Manifest-owned sitemap path escaped output root: ${a}`);await F.rm(c.outputPath,{force:true}),n.deletedFiles.add(i),delete r.manifest.assets[a];}await Be(e,r);}async function Tc(e){try{let t=await F.readFile(v.join(e.outputDir,"asset-map.json"),"utf8");return JSON.parse(t)}catch{return {}}}async function Ac(e){let t=["crawl.log.jsonl","current-crawl-event.json","rejected.jsonl","ignored.jsonl","skipped-http.jsonl","errors.jsonl","timings.jsonl","rejected.json","ignored.json","skipped-http.json","errors.json","timings.json"];await F.mkdir(e,{recursive:true}),await Promise.all(t.map(async r=>{try{await F.unlink(v.join(e,r));}catch(n){if(n.code!=="ENOENT")throw n}}));}function Vs(e,t,r,n,s){let o=oe(e,r,e.sourceOrigin,n,"manual-url");o&&(wt(o)?ur(e,t,o.toString(),n,s):z(e,o)?K(e,t,o.toString(),n,s):Ve(o)?rt(e,t,o.toString(),n,s):n.reject("manual-url",o.toString(),"not page/sitemap/asset-like",s));}async function wo(e=process.argv.slice(2)){let t=[],r=await xe(void 0,{onRemotePublisherConfigDiagnostic:k=>{t.push(k);}}),n=Ct(r.sitemapPaths),s=t.at(-1)??null,o=da(e),a=o.mode==="content-sync"?await vc(o.contentSyncPlanPath):null;if(o.resumeRewrite&&o.mode!=="full")throw new Error("--resume-rewrite is only supported for full crawl/publish jobs.");let c=[];o.mode==="retry-timeouts"&&(c=await Pc(r)),o.mode==="single-url"&&(c=await Rc(o.urls)),a&&(c=[...a.directRenderUrls,...a.archiveFamilyUrls,...a.resourceRenderUrls]);let i=o.crawlMode==="incremental"&&o.mode==="full",d=i&&typeof r.subscriptionType=="string"&&r.subscriptionType.trim()!=="";if(a&&r.subscriptionType!=="PROFESSIONAL"&&r.subscriptionType!=="AGENCY")throw new Error("Content-sync requires an active Professional or Agency subscription.");let l=(o.mode==="full"||o.mode==="single-url"||o.mode==="content-sync")&&!o.resumeRewrite,u=o.mode!=="full"||o.resumeRewrite||d,g=u?await Tc(r):{},f=d||o.mode==="single-url"||o.mode==="content-sync"?await ba(r):Qs(),m=new Set(c),w=new Set;if(a){for(let k of a.archiveFamilies)if(k.foundPosts===0)for(let L of k.pageUrls)w.add(L);for(let k of Object.keys(f.pages))Cc(k,a)&&!m.has(k)&&(c.push(k),w.add(k));}let p={enabled:d,trackManifest:l,manifest:on(f),previousManifest:on(f),runId:a?.jobId??`${Date.now()}`,seenPages:new Set,changeTokenCache:new Map,pageChangeTokenPrimePromise:null,manifestSaveChain:Promise.resolve(),manifestPendingChanges:0,lastManifestSavedAt:Date.now(),strictTargeted:!!a,requiredUrls:m,deleteOnMissingUrls:w};await Ac(r.logDir);let h=new Jt(r.logDir,r.logLevel),y=o.remoteRender??r.remoteWorkers?.render?.enabled===true,b=nr({explicitPath:o.remoteWorkerConfigPath,runtimeDir:jt()}),P=null,$=null,x=null,I=null,R=Math.max(1,r.concurrency),C=1,O=r.remoteWorkers?.rewrite?.enabled===true,V=r.remoteWorkers?.deploy?.enabled===true,U=y&&O&&V&&!o.resumeRewrite;if(!U&&o.mode==="full"&&!o.resumeRewrite&&await F.rm(sr(r),{force:true}),y&&!o.resumeRewrite||O){if(!b)throw new Error("Remote Lambda workers are enabled, but the runtime directory is unknown. Run through queue-runner with --runtime-dir, set STATIC_PUBLISHER_RUNTIME_DIR, or use --remote-worker-config for a diagnostic run.");let k=await Yt(b),L=false;if(x=new pt(k,{},{onProgress:M=>{h.progress(`Lambda ${M.operation} batch: ${M.completedItems+M.failedItems}/${M.totalItems}`,{remoteWorkerOperation:M.operation,remoteWorkerTaskId:M.taskId,remoteWorkerStatus:M.status,remoteWorkerCompletedItems:M.completedItems,remoteWorkerFailedItems:M.failedItems,remoteWorkerTotalItems:M.totalItems,remoteWorkerUpdatedAt:M.updatedAt});},onProgressError:M=>{L||(L=true,h.warn("Lambda progress status could not be read; task execution continues.",{error:M.message}));}}),U){if(!k.functions.asset)throw new Error("Full Lambda delegation requires an asset worker. Redeploy the Lambda worker stack and reinstall remote-workers.json.");let M=u?await or(r):null;I=$s(`crawl-${Ae(p.runId,40)}`,k,M),$=new er({client:x,jobId:I.jobId,maxAttempts:2}),h.info("S3-native Lambda data plane is enabled.",{execution:"lambda",assetWorker:k.functions.asset,workspaceBucket:k.workspace.bucket,workspacePrefix:k.workspace.prefix});}}if(y&&!o.resumeRewrite){if(!x)throw new Error("Remote render worker client was not initialized.");R=Math.max(1,Math.min(100,U?r.concurrency:r.remoteWorkers?.render?.concurrency??r.concurrency)),C=Math.max(1,Math.min(20,r.remoteWorkers?.render?.batchSize??5)),P=new Xt({client:x,jobId:`crawl-${Ae(p.runId,40)}`,maxAttempts:r.remoteWorkers?.render?.maxAttempts??2,batchSize:C,maxConcurrentBatches:R,onRetry:k=>{h.warn(`Retrying remote render for ${k.url}`,{url:k.url,attempt:k.attempt,maxAttempts:k.maxAttempts,reason:k.reason,execution:"lambda"});}}),h.info("Lambda page rendering is enabled.",{remoteWorkerConfigPath:v.resolve(b),concurrency:R,maxAttempts:r.remoteWorkers?.render?.maxAttempts??2,batchSize:C,execution:"lambda"});}if(s){let k={status:s.status,virtualAssetBaseUrl:s.virtualAssetBaseUrl,subscriptionType:s.subscriptionType??null,error:s.error,requests:s.requests,source:"remote-publisher-config"};s.status==="loaded"&&s.subscriptionType?h.info("Loaded remote WP Suite publisher configuration.",k):h.warn("Remote WP Suite publisher configuration is unavailable or has no active subscription type.",k);}if(i&&!d){let k="Incremental crawl requires an active remote publisher subscription; refusing to fall back to a destructive full crawl.";throw h.error(k,{requestedMode:o.crawlMode,subscriptionType:r.subscriptionType??null,source:"incremental-subscription-guard"}),await h.flush(),new Error(k)}let S={pageQueue:[],queuedPages:new Set,donePages:new Set,savedPageOutputs:new Set,pageDiscoverySources:new Map,assetQueue:[],queuedAssets:new Set,doneAssets:new Set,sitemapQueue:[],queuedSitemaps:new Set,doneSitemaps:new Set,successfulSitemaps:new Set,resolvedSitemapRoots:new Set,sitemapIndexUrls:new Set,sitemapLeafUrls:new Set,sitemapLastmodByPage:{},assetMap:{...g},assetVariantDigestsByOriginalPath:new Map,stats:{pagesQueued:0,pagesRendered:0,pagesCompleted:0,assetsQueued:0,sitemapsQueued:0,assetsSaved:0,pagesSaved:0}},W=ya(),ce=new Gt,E=pa();if(E&&!o.resumeRewrite&&await Zt(E,ce.artifact()),await Je(r),await Zn(r,{startedAt:new Date().toISOString(),outputDir:v.resolve(r.outputDir)}),u||await F.rm(r.outputDir,{recursive:true,force:true}),await F.mkdir(r.outputDir,{recursive:true}),a){let k=new Set([...a.deleteUrls,...p.deleteOnMissingUrls]);for(let M of a.deleteUrls)await Mt(r,p,W,M,k);let L=new Set(a.resourceDeleteUrls);for(let M of a.resourceDeleteUrls)await kc(r,p,W,M,L);}if(o.resumeRewrite)h.info("Resuming final rewrite from existing output.",{phase:"rewrite-text",mode:o.mode,crawlMode:o.crawlMode});else {let k=await request.newContext({ignoreHTTPSErrors:r.ignoreHttpsErrors});try{if(h.mark("discovery"),o.mode==="full"?(n.forEach(M=>ur(r,S,M,h)),await Ls(r,k,S,h,W,p),r.seedPaths.forEach(M=>Vs(r,S,M,h,"seed-path")),r.generated404RequestPath&&rt(r,S,r.generated404RequestPath,h,"generated-404-request-path")):(c.forEach(M=>Vs(r,S,M,h,"cli")),a?.sitemapUrls.forEach(M=>ur(r,S,M,h,"content-sync-impact")),await Ls(r,k,S,h,W,p,o.mode==="content-sync",a?.sitemapUrls??[]),a&&await Ic(r,S,p,W,a.sitemapUrls)),h.endMark("discovery",{pages:S.pageQueue.length,assets:S.assetQueue.length,sitemaps:S.sitemapQueue.length}),h.summary(`Queued ${S.pageQueue.length} pages, ${S.assetQueue.length} assets, ${S.sitemapQueue.length} sitemaps.`,{mode:o.mode,crawlMode:o.crawlMode,queuedPages:S.pageQueue.length,queuedAssets:S.assetQueue.length,queuedSitemaps:S.sitemapQueue.length}),o.mode==="retry-timeouts"&&S.pageQueue.length===0&&S.assetQueue.length===0&&S.sitemapQueue.length===0){h.summary("No timed-out URLs were queued. Skipping retry crawl.",{mode:o.mode,crawlMode:o.crawlMode,queuedPages:0,queuedAssets:0,queuedSitemaps:0}),await h.flush(),E&&await Zt(E,ce.artifact());return}h.mark("render-pages");let L=Array.from({length:P?R*C:R},()=>P?gc(r,S,h,o.mode,k,p,W,ce,P,I??void 0):fc(r,S,h,o.mode,k,p,W,ce));if(await Promise.all(L),E&&await Zt(E,ce.artifact()),h.endMark("render-pages",{pages:S.stats.pagesCompleted}),h.mark("download-assets"),h.progress("Asset download phase started.",{phase:"download-assets",doneAssets:S.doneAssets.size,assetsQueued:S.stats.assetsQueued,assetQueue:S.assetQueue.length}),I&&$?await oc(r,k,S,h,p,W,I,$,r.concurrency):(await mn(r,k,p,[...S.assetQueue],h),await nc(r,k,S,h,p,W)),h.endMark("download-assets",{assets:S.doneAssets.size}),p.enabled&&r.maxPages===0&&(await xa(r,S,p,h,W),o.mode==="full"&&await Ia(r,p,h,W)),o.mode==="full"){let M=await tc(r,S,h);for(let G of M)if(ue(W,r,G),I&&x){let te=dr(r,G),A=await F.readFile(G),_=Ee(G),T=String(ks.lookup(te)||"")||(_?"text/plain; charset=utf-8":"application/octet-stream"),re=await x.writeWorkspaceObject({key:`${I.workspace.prefix}jobs/${I.jobId}/copied/${Ae(te,40)}-${v.basename(te)}`,body:A,contentType:T});mt(I,{relativePath:te,sourceUrl:null,kind:"generated",contentType:re.contentType,cacheControl:null,isText:_,object:re}),_&&ve(W,G);}}}finally{await se("dispose crawl request context",Et(r),()=>k.dispose()).catch(L=>{h.warn("Timed out while disposing crawl request context",{error:String(L)});});}}if(p.trackManifest&&await Be(r,p,true),I)for(let k of W.deletedFiles)Os(I,k);let D=JSON.stringify(S.assetMap,null,2);if(await F.writeFile(v.join(r.outputDir,"asset-map.json"),D,"utf8"),I&&x){let k=await x.writeWorkspaceObject({key:`${I.workspace.prefix}jobs/${I.jobId}/generated/asset-map.json`,body:D,contentType:"application/json; charset=utf-8"});mt(I,{relativePath:"asset-map.json",sourceUrl:null,kind:"generated",contentType:"application/json; charset=utf-8",cacheControl:r.s3.assetCacheControl,isText:true,object:k});}JSON.stringify(g,null,2)!==JSON.stringify(S.assetMap,null,2)&&ue(W,r,v.join(r.outputDir,"asset-map.json")),I&&x&&await ic(r,W,I,x);let j=o.mode==="single-url"||o.mode==="content-sync"?Fa(r,S):p.enabled&&!o.resumeRewrite?Ta(r,p,W,g,S.assetMap):void 0;h.mark("rewrite-text");let X=o.mode==="single-url"||o.mode==="content-sync"?`Rewriting text files touched by URL crawl: 0/${j?.length??0}`:"Rewriting text files...";h.progress(X,{phase:"rewrite-text",index:0,totalFiles:j?.length,changedTextFiles:0}),await en(X);let Y=Date.now(),ee={files:j,previousAssetMap:g,onStart:({totalFiles:k,workerCount:L})=>{h.info(`Rewrite phase scanning ${k} text files.`,{phase:"rewrite-text",totalFiles:k,workerCount:L});},onProgress:async({index:k,totalFiles:L,changedTextFiles:M,file:G,changed:te})=>{te&&ue(W,r,v.join(r.outputDir,G)),h.checkpoint(`Rewriting text file ${k}/${L}`,{phase:"rewrite-text",index:k,totalFiles:L,changedTextFiles:M,file:G}),h.debug(`${te?"Rewrote":"Checked unchanged"} text file ${k}/${L}: ${G}`,{phase:"rewrite-text",index:k,totalFiles:L,changedTextFiles:M,file:G,changed:te});let A=Date.now();if(!(k===1||k===L||k%50===0||A-Y>=5e3))return;Y=A;let T=`Rewriting text files: ${k}/${L}`;h.progress(T,{phase:"rewrite-text",index:k,totalFiles:L,changedTextFiles:M,file:G}),await en(T);}},H;if(I&&x){let k=j?.map(M=>dr(r,v.isAbsolute(M)?M:v.join(r.outputDir,M))),L=Object.values(I.objects).filter(M=>M.isText&&(!k||k.includes(M.relativePath))).length;await ee.onStart?.({totalFiles:L,workerCount:Math.min(r.concurrency,L)}),H=await rr(r,I,S.assetMap,{client:x,jobId:I.jobId,concurrency:r.concurrency,batchSize:25,maxAttempts:2,...k?{relativePaths:k}:{},onProgress:ee.onProgress}),await Ms(r,I);}else O&&x?H=await tr(r,S.assetMap,{client:x,jobId:`crawl-${Ae(p.runId,40)}`,concurrency:r.remoteWorkers?.rewrite?.concurrency??r.rewriteConcurrency,batchSize:r.remoteWorkers?.rewrite?.batchSize??25,maxAttempts:r.remoteWorkers?.rewrite?.maxAttempts??2,onStageProgress:async({index:k,totalFiles:L,file:M})=>{let G=Date.now();if(k!==1&&k!==L&&k%25!==0&&G-Y<5e3)return;Y=G;let te=`Staging text files for Lambda rewrite: ${k}/${L}`;h.progress(te,{phase:"rewrite-stage",index:k,totalFiles:L,file:M,execution:"lambda"}),await en(te);},options:ee}):H=await Kt(r,S.assetMap,ee);p.trackManifest&&(Aa(p,j),await Be(r,p,true)),h.endMark("rewrite-text",{changedTextFiles:H});let de=a?[...W.deletedFiles].sort():p.enabled&&!o.resumeRewrite?await $a(r,S,p,W,h,I):[],be=[...new Set((j||[]).map(k=>me(r.outputDir,v.isAbsolute(k)?k:v.join(r.outputDir,k))).filter(k=>k!==null))].sort();if(a){let k=[...W.changedFiles].sort(),L=new Set(k),M=new Set(a.directRenderUrls.map(q=>At(r,q,"page")).filter(q=>!!q&&L.has(q))),G=new Set(a.archiveFamilyUrls.map(q=>At(r,q,"page")).filter(q=>!!q&&L.has(q))),te=new Set(a.resourceRenderUrls.map(q=>At(r,q,"asset")).filter(q=>!!q&&L.has(q))),A=new Set([...S.sitemapLeafUrls].map(q=>At(r,q,"asset")).filter(q=>!!q&&L.has(q))),_=new Set([...S.sitemapIndexUrls].map(q=>At(r,q,"asset")).filter(q=>!!q&&L.has(q))),T=new Set([...M,...G,...te,...A,..._]),re=k.filter(q=>!T.has(q)),he=[...new Set([...a.directRenderUrls,...a.archiveFamilyUrls,...S.resolvedSitemapRoots,...S.sitemapLeafUrls,...S.sitemapIndexUrls,...a.deleteUrls,...a.resourceRenderUrls,...a.resourceDeleteUrls].map(q=>{let Se=new URL(q);return `${Se.pathname}${Se.search}`}))].sort();await Nr(r,{schemaVersion:2,generatedAt:new Date().toISOString(),outputDir:v.resolve(r.outputDir),runMode:"content-sync",crawlMode:"incremental",fullSyncRequired:false,changedFiles:k,deletedFiles:de,rewriteTargets:be,revalidateFiles:[...W.revalidateFiles].sort(),consumerId:a.consumerId,fromSequence:a.fromSequence,toSequence:a.toSequence,impactHash:a.impactHash,resolvedSitemapUrls:[...S.resolvedSitemapRoots],uploadGroups:{assets:re,content:[...M].sort(),listings:[...G].sort(),resources:[...te].sort(),sitemapLeaves:[...A].sort(),sitemapIndexes:[..._].reverse()},invalidationPaths:he});}else await Nr(r,{schemaVersion:1,generatedAt:new Date().toISOString(),outputDir:v.resolve(r.outputDir),runMode:o.mode,crawlMode:o.crawlMode,fullSyncRequired:!(p.enabled&&!o.resumeRewrite),changedFiles:p.enabled&&!o.resumeRewrite?[...W.changedFiles].sort():[],deletedFiles:p.enabled&&!o.resumeRewrite?de:[],rewriteTargets:p.enabled&&!o.resumeRewrite?be:[],revalidateFiles:[...W.revalidateFiles].sort()});await Xn(r),h.summary(o.resumeRewrite?`Done. Resumed final rewrite over existing output and changed ${H} text files.`:`Done. Rendered ${S.stats.pagesRendered} pages, processed ${S.doneSitemaps.size} sitemaps and ${S.doneAssets.size} assets.`,{mode:o.mode,crawlMode:o.crawlMode,resumeRewrite:o.resumeRewrite,...S.stats,pagesRendered:S.stats.pagesRendered,donePages:S.stats.pagesCompleted,claimedPages:S.donePages.size,doneSitemaps:S.doneSitemaps.size,doneAssets:S.doneAssets.size,changedTextFiles:H}),await h.flush();}function Ec(e){let t=e/6e4;if(Number.isInteger(t)&&t>=1)return `${t} minute${t===1?"":"s"}`;let r=Math.ceil(e/1e3);return `${r} second${r===1?"":"s"}`}async function we(e,t,r){let n=new AbortController,s=globalThis.setTimeout(()=>{n.abort(new Error(`${e} timed out after ${Ec(t)}.`));},t);try{return await r({abortController:n,httpOptions:{abortSignal:n.signal,requestTimeout:t}})}finally{globalThis.clearTimeout(s);}}function $c(e){return typeof e.subscriptionType=="string"&&e.subscriptionType.trim()!==""}function fr(e){let t="";for(let n=0;n<e.length;n++){let s=e[n];if(s==="--profile"){let o=(e[n+1]||"").trim();if(!o)throw new Error("Missing value for --profile.");t=o,n+=1;}else if(s.startsWith("--profile=")){let o=s.slice(10).trim();if(!o)throw new Error("Missing value for --profile.");t=o;}}let r=String(process.env.PUBLISHER_DEPLOY_PROFILE||process.env.PUBLISHER_DEPLOYMENT_PROFILE||"").trim();return t||r||null}function Oc(e,t){return {...e,...t??{}}}function Mc(e,t){return {...e,...t??{},invalidationPaths:[...(t?.invalidationPaths??e.invalidationPaths)||[]]}}function yt(e,t){let r=String(t??e.deploymentTargetOverride??"").trim();if(!$c(e)){if(r)throw new Error(`Deployment target "${r}" requires an active WPSuite subscription and remote publisher config.`);return {name:null,profile:null,config:e}}let n=String(r||e.defaultDeploymentProfile||"").trim();if(!n)return {name:null,profile:null,config:e};let s=e.deploymentProfiles?.[n];if(!s)throw new Error(`Unknown deployment profile "${n}". Check the linked WPSuite publisher configuration.`);return {name:n,profile:s,config:{...e,targetOrigin:s.targetOrigin??e.targetOrigin,s3:Oc(e.s3,s.s3),cloudFront:Mc(e.cloudFront,s.cloudFront)}}}function hn(e){return String(e??"").split(";").map(t=>t.trim().toLowerCase()).filter(Boolean).join(";")}var Ro="wpsuite-sha256",vo="wpsuite-normalized-sha256",bn="public, max-age=0, must-revalidate",Nc=/(?:^|[-_:.])(id|uid|nonce|token|hash|instance)(?:$|[-_:.])/i,Sn=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,_c=["SIGINT","SIGTERM"],yr=new Set,hr=new Map,yo=null;function Bc(e){yr.add(e);let t=false;return ()=>{t||(t=true,yr.delete(e));}}async function Vc(){let e=[...yr];e.length!==0&&await Promise.allSettled(e.map(async t=>{yr.delete(t),await F.rm(t,{recursive:true,force:true});}));}function Kc(){if(!(hr.size>0))for(let e of _c){let t=()=>{yo||(yo=Vc().finally(()=>{for(let[r,n]of hr)process.off(r,n);hr.clear(),process.exit(1);}));};hr.set(e,t),process.on(e,t);}}Kc();function zc(e,t){let r=String(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH||"").trim();if(r)return v.resolve(r);let n=t.trim();return n?v.join(v.resolve(n),"crawl-manifest.json"):v.join(v.resolve(e),".crawl-manifest.json")}function Ze(e){return v.normalize(e).split(v.sep).join("/")}function bo(e,t){let r=v.relative(v.resolve(e),v.resolve(t));return !r||r.startsWith("..")||v.isAbsolute(r)?null:Ze(r)}async function Hc(e,t,r){let n=zc(e.outputDir,t),s;try{s=await F.readFile(n,"utf8");}catch(l){return l.code==="ENOENT"?(r.warn("Deploy rewrite guard disabled because the crawl manifest is missing.",{manifestPath:n,source:"deploy-guard"}),null):(r.warn("Deploy rewrite guard disabled because the crawl manifest could not be read.",{manifestPath:n,error:l instanceof Error?l.message:String(l),source:"deploy-guard"}),null)}let o;try{o=JSON.parse(s);}catch(l){return r.warn("Deploy rewrite guard disabled because the crawl manifest is invalid JSON.",{manifestPath:n,error:l instanceof Error?l.message:String(l),source:"deploy-guard"}),null}let a=new Map,c=new Map,i=0,d=0;for(let[l,u]of Object.entries(o.pages||{})){let g=String(u?.outputPath||"").trim(),f=g?bo(e.outputDir,g):null;if(f){let m=typeof u?.contentType=="string"&&u.contentType?u.contentType:null;m&&c.set(f,m);}!g||u?.rewriteComplete===true||f&&(i++,a.has(f)||a.set(f,{kind:"page",sourceUrl:l,outputPath:v.resolve(g),relativePath:f}));}for(let[l,u]of Object.entries(o.assets||{})){let g=String(u?.outputPath||"").trim(),f=u?.isText===true,m=g?bo(e.outputDir,g):null;if(m){let w=typeof u?.contentType=="string"&&u.contentType?u.contentType:null;w&&c.set(m,w);}!g||!f||u?.rewriteComplete===true||m&&(d++,a.has(m)||a.set(m,{kind:"asset",sourceUrl:l,outputPath:v.resolve(g),relativePath:m}));}return {manifestPath:n,byRelativePath:a,contentTypeByRelativePath:c,pendingPages:i,pendingTextAssets:d}}function Jc(e){return e&&(Sn.test(e)?"__uuid__":/^[0-9a-f]{6,}$/i.test(e)?"__hex__":/^[0-9]{8,}$/.test(e)?"__num__":/^(?=.*[a-z])(?=.*\d)[a-z0-9]{8,}$/i.test(e)?"__alnum__":e)}function wn(e){return e.split(/([_:.\-/=?&#]+)/g).map((t,r)=>r%2===1?t:Jc(t)).join("")}function Qc(e){return e.split(/([_:.\-/=?&#]+)/g).map((t,r)=>r%2===1?t:Sn.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)?"__hex__":/^[0-9]{6,}$/.test(t)?"__num__":/^[a-z0-9_-]{6,}$/i.test(t)?"__id__":t).join("")}function br(e,t){return Array.isArray(e)?e.map(r=>br(r,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([r,n])=>[r,br(n,r)])):typeof e!="string"?e:t&&Nc.test(t)?Qc(e):Sn.test(e)?"__uuid__":/^[0-9a-f]{6,}$/i.test(e)||/^[0-9]{8,}$/.test(e)?wn(e):e}function Gc(e){return e.replace(/((?:https?:\/\/[^"'\s>]+|\/)(?:wp-content|wp-includes)\/[^"'\s>?]+)\?ver=[A-Za-z0-9._-]+(?=$|[#"'])/gi,"$1")}function Zc(e,t){let r=t.trim();if((r.startsWith("{")||r.startsWith("[")||r.startsWith('"'))&&e.startsWith("data-"))try{let s=JSON.parse(r);return JSON.stringify(br(s))}catch{}if(e.startsWith("data-")&&/^[A-Za-z0-9+/=]+$/.test(r))try{let s=Buffer.from(r,"base64").toString("utf8"),o=JSON.parse(s),a=JSON.stringify(br(o));return Buffer.from(a,"utf8").toString("base64")}catch{}return t}function Yc(e,t){let r=e.toLowerCase();return r==="class"?t.split(/(\s+)/).map((n,s)=>s%2===1?n:wn(n)).join(""):r==="id"||r==="for"||r==="aria-controls"||r==="aria-labelledby"||r==="aria-describedby"||r==="aria-owns"||r==="aria-activedescendant"||r==="name"?wn(t):r==="href"||r==="src"?Gc(t):Zc(r,t)}function Xc(e){return e.replace(/<([a-z][^\s/>]*)([^<>]*?)>/gi,(t,r,n)=>{if(r.startsWith("/"))return t;let s=n.replace(/\s([:@a-zA-Z_][-:.a-zA-Z0-9_]*?)=(['"])([\s\S]*?)\2/g,(o,a,c,i)=>{let d=Yc(a,i);return ` ${a}=${c}${d}${c}`});return `<${r}${s}>`})}function bt(e){let t=v.extname(e).toLowerCase();return [".html",".htm",".xml",".xsl",".txt"].includes(t)||["robots.txt","sitemap.xml"].includes(v.basename(e))}function wr(e,t){return [e.replace(/^\/+|\/+$/g,""),t.replace(/^\/+/,"")].filter(Boolean).join("/")}async function el(e,t,r,n){let s=new Map,o,a=0;do{a++;let c=await we(`S3 list objects page ${a} for s3://${t}/${r||""}`,3e5,({httpOptions:i})=>e.send(new ListObjectsV2Command({Bucket:t,Prefix:r||void 0,ContinuationToken:o}),i));for(let i of c.Contents||[]){if(!i.Key)continue;let d=(i.ETag||"").replace(/^"|"$/g,"").toLowerCase(),l=Number(i.Size??0);s.set(i.Key,{etag:d,size:l,cacheControl:void 0,contentType:void 0});}o=c.NextContinuationToken,n.debug(`Listed S3 keys page ${a}: ${s.size} keys so far`);}while(o);return s}async function tl(e,t,r,n){if(n.has(r))return n.get(r)??null;try{let s=await we(`S3 head object ${r}`,3e5,({httpOptions:a})=>e.send(new HeadObjectCommand({Bucket:t,Key:r}),a)),o={etag:(s.ETag||"").replace(/^"|"$/g,"").toLowerCase(),size:Number(s.ContentLength??0),cacheControl:s.CacheControl?.trim()||null,contentType:s.ContentType?.trim()||null};return n.set(r,o),o}catch{return n.set(r,null),null}}async function rl(e,t,r,n){if(n.cacheControl!==void 0&&n.contentType!==void 0)return {cacheControl:n.cacheControl,contentType:n.contentType};try{let s=await we(`S3 head cache metadata ${r}`,3e5,({httpOptions:o})=>e.send(new HeadObjectCommand({Bucket:t,Key:r}),o));n.cacheControl=s.CacheControl?.trim()||null,n.contentType=s.ContentType?.trim()||null;}catch{n.cacheControl=null,n.contentType=null;}return {cacheControl:n.cacheControl,contentType:n.contentType}}function So(e){return String(e||"").split(",").map(t=>t.trim().toLowerCase()).filter(Boolean).sort().join(",")}async function nl(e,t,r,n){let s=[...new Set(Array.from(r).filter(Boolean))];if(s.length===0)return n.info("No explicitly tombstoned S3 objects to delete."),[];n.info(`Deleting ${s.length} explicitly tombstoned S3 object(s)\u2026`);for(let o=0;o<s.length;o+=1e3){let a=s.slice(o,o+1e3);if(a.length===0)continue;let c=await we(`S3 delete objects batch ${Math.floor(o/1e3)+1}`,3e5,({httpOptions:i})=>e.send(new DeleteObjectsCommand({Bucket:t,Delete:{Objects:a.map(d=>({Key:d}))}}),i));if(c.Errors&&c.Errors.length>0){let i=c.Errors.map(d=>`${d.Key||"(unknown)"}: ${d.Code||"DeleteFailed"}`);throw new Error(`S3 reported ${i.length} object deletion error(s): ${i.join(", ")}`)}n.info(`Deleted batch of ${a.length} object(s).`);for(let i of a)n.debug(` deleted: ${i}`);}return s}function sl(e){return createHash("md5").update(e).digest("hex")}function Ye(e){return createHash("sha256").update(e).digest("hex")}function Sr(e){return createHash("sha256").update(Xc(e.toString("utf8"))).digest("hex")}async function ol(e,t,r,n){if(n.has(r))return n.get(r)??null;try{let a=((await we(`S3 head object metadata ${r}`,3e5,({httpOptions:c})=>e.send(new HeadObjectCommand({Bucket:t,Key:r}),c))).Metadata?.[Ro]||"").trim().toLowerCase()||null;return n.set(r,a),a}catch{return n.set(r,null),null}}async function il(e,t,r,n,s){if(n.has(r))return n.get(r)??null;try{let a=((await we(`S3 head object normalized metadata ${r}`,3e5,({httpOptions:c})=>e.send(new HeadObjectCommand({Bucket:t,Key:r}),c))).Metadata?.[vo]||"").trim().toLowerCase();if(a)return n.set(r,a),a}catch{return n.set(r,null),null}if(s.has(r)){let o=s.get(r)??null;return n.set(r,o),o}try{let a=await(await we(`S3 get object ${r}`,3e5,({httpOptions:i})=>e.send(new GetObjectCommand({Bucket:t,Key:r}),i))).Body?.transformToByteArray(),c=a?Sr(Buffer.from(a)):null;return s.set(r,c),n.set(r,c),c}catch{return s.set(r,null),n.set(r,null),null}}function al(e){return e.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"profile"}function cl(e,t){let r=e,n=Object.entries(t).sort((s,o)=>o[0].length-s[0].length);for(let[s,o]of n)s&&(r=r.split(s).join(o));return r}async function ll(e,t,r,n){let s=v.join(e,"asset-map.json"),o;try{o=await F.readFile(s,"utf8");}catch(i){if(i.code==="ENOENT")return;throw i}let a=JSON.parse(o);if(!a||typeof a!="object")return;let c=Object.fromEntries(Object.entries(a).map(([i,d])=>{let l=String(d??"");return t.urlRewriteMode==="absolute"&&t.targetOrigin&&r.targetOrigin&&t.targetOrigin!==r.targetOrigin&&(l=l.split(t.targetOrigin).join(r.targetOrigin)),l=cl(l,n),[i,l]}));await F.writeFile(s,JSON.stringify(c,null,2),"utf8");}async function ul(e,t,r,n,s,o,a){let c=e.targetOrigin!==t.targetOrigin,i=Object.keys(n).length>0;if(!r||!c&&!i)return {outputDir:e.outputDir,cleanup:async()=>{}};if(c&&e.urlRewriteMode!=="absolute")throw new Error(`Deployment profile "${r}" changes targetOrigin, but the base crawl output must use urlRewriteMode "absolute" for multi-target redeploys.`);let d=v.join(v.dirname(e.outputDir),`.deploy-profile-${al(r)}-${Date.now()}`),l=Bc(d);s.info(`Preparing deployment profile "${r}" from existing crawl output to ${d}...`);try{if(await F.rm(d,{recursive:!0,force:!0}),o){await F.mkdir(d,{recursive:!0});for(let w of o){let p=v.join(e.outputDir,w),h=v.join(d,w);await F.mkdir(v.dirname(h),{recursive:!0}),await F.copyFile(p,h);}}else await F.cp(e.outputDir,d,{recursive:!0});let u={...e,sourceOrigin:e.targetOrigin,targetOrigin:t.targetOrigin,extraReplacements:n,outputDir:d},g=1;s.info(`Rewriting text files for deployment profile "${r}"...`);let f={files:o,onStart:({totalFiles:w,workerCount:p})=>{g=p,s.info(`Rewriting ${w} text file(s) for deployment profile "${r}" with ${p} worker(s).`);},onProgress:({index:w,totalFiles:p,changedTextFiles:h,file:y,changed:b})=>{let $=`Rewriting [${w}/${p}] ${y} (${b?"rewrote":"checked"}; ${h} changed so far)`;p<=200||w<=5||w%10===0||w===p?(s.progress($,{file:y,index:w,totalFiles:p,changed:b,changedTextFiles:h,workerCount:g}),s.info($)):s.debug($);}},m=a?await tr(u,{},{...a,options:f}):await Kt(u,{},f);return await ll(d,e,t,n),s.info(`Prepared deployment profile "${r}" in ${d} (${m} rewritten text file(s)).`),{outputDir:d,cleanup:async()=>{l(),await F.rm(d,{recursive:!0,force:!0});}}}catch(u){throw s.error(`Failed to prepare deployment profile "${r}" temporary output.`,{tempDir:d,outputDir:e.outputDir,error:u instanceof Error?u.message:String(u),...u instanceof Error&&u.stack?{stack:u.stack}:{}}),await F.rm(d,{recursive:true,force:true}).catch(()=>{}),l(),await s.flush().catch(()=>{}),u}}function Co(e,t){let r=s=>s.replace(/^\/+|\/+$/g,""),n=e.targets.find(s=>s.bucketName===t.s3.bucket&&r(s.prefix)===r(t.s3.prefix)&&s.region===t.s3.region);if(!n)throw new Error(`No CDK Lambda deployment target matches s3://${t.s3.bucket}/${t.s3.prefix||""} in ${t.s3.region}. Redeploy the CDK with this target and reinstall remote-workers.json.`);return n}function dl(e,t){if(!e||typeof e!="object")throw new Error("Remote deploy result must be a JSON object.");let r=e;if(r.schemaVersion!==Z||r.response?.operation!=="deploy-copy"||r.response.jobId!==t.jobId||r.response.taskId!==t.taskId||!r.detail||!Array.isArray(r.detail.objects)||!Array.isArray(r.detail.deletedKeys)||!Array.isArray(r.detail.deleteErrors))throw new Error("Remote deploy result has an invalid envelope.");return r}async function Pr(e){let t=null;for(let r=1;r<=Math.max(1,Math.min(5,e.maxAttempts));r+=1){let n=ne(`deploy-${e.batchIndex}-a${r}-${Date.now()}`,"taskId");try{let s=await e.client.invoke({schemaVersion:Z,operation:"deploy-copy",jobId:e.jobId,taskId:n,targetId:e.targetId,items:e.items,...e.deleteRelativeKeys?{deleteRelativeKeys:e.deleteRelativeKeys}:{}}),o=dl(await e.client.readResult(s),s);if(o.response.status==="partial")throw new Error(`Worker reported ${o.response.failedItems} failed item(s).`);return o}catch(s){t=s;}}throw new Error(`Remote deploy task failed after ${e.maxAttempts} attempt(s): ${t instanceof Error?t.message:String(t)}`,{cause:t})}async function pl(e){let t=Co(e.remoteConfig,e.config),r=ne(`deploy-${Date.now()}-${Ye(Buffer.from(`${t.id}:${e.config.outputDir}`)).slice(0,12)}`,"jobId"),n=dt(e.remoteConfig.workspace.prefix,"jobs",r,"deploy-inputs");e.log.progress(`Staging export for Lambda deploy: 0/${e.files.length}`,{phase:"deploy-stage",index:0,totalFiles:e.files.length,uploaded:0,skipped:0,failed:0,mode:"lambda-s3-copy"});let s=0,o=[],a=Math.max(1,Math.min(16,e.concurrency*2)),c=0;await Promise.all(Array.from({length:Math.min(a,e.files.length)},async()=>{for(;;){let y=c;if(y>=e.files.length)return;c+=1;let b=e.files[y],P=await F.readFile(v.join(e.config.outputDir,b)),$=e.contentTypeByRelativePath?.get(b)||ks.lookup(b)||"application/octet-stream",x=e.revalidateFiles.has(Ze(b))?bn:bt(b)?e.config.s3.htmlCacheControl:e.config.s3.assetCacheControl,I=Ye(P),R=bt(b)?Sr(P):void 0,C=`${n}/files/${Ye(Buffer.from(b))}-${v.basename(b)}`.replace(/\/+/g,"/");await e.client.writeWorkspaceObject({key:C,body:P,contentType:String($),cacheControl:x,metadata:{"wpsuite-sha256":I,...R?{"wpsuite-normalized-sha256":R}:{}}}),o[y]={sourceKey:C,targetRelativeKey:b,sha256:I,...R?{normalizedSha256:R}:{},bytes:P.byteLength,contentType:String($),cacheControl:x},s+=1,(s===e.files.length||s<=5||s%25===0)&&e.log.progress(`Staging export for Lambda deploy: ${s}/${e.files.length}`,{phase:"deploy-stage",index:s,totalFiles:e.files.length,staged:s,mode:"lambda-s3-copy"});}}));let i=[],d=Math.max(1,Math.min(500,e.batchSize));for(let y=0;y<o.length;y+=d)i.push(o.slice(y,y+d));let l=[],u=[],g=[],f=0,m=0,w=0,p=Math.max(1,Math.min(Math.max(1,e.concurrency),i.length));if(e.log.progress(`Lambda deploy: 0/${e.files.length}`,{phase:"deploy-copy",index:0,totalFiles:e.files.length,uploaded:0,skipped:0,failed:0,mode:"lambda-s3-copy",workerCount:p,completedBatches:0,totalBatches:i.length}),await Promise.all(Array.from({length:p},async()=>{for(;;){let y=w;if(y>=i.length)return;w+=1;let b=Date.now(),P=await Pr({client:e.client,jobId:r,targetId:t.id,batchIndex:y+1,items:i[y],maxAttempts:e.maxAttempts}),$=0,x=0,I=0;for(let C of P.detail.objects)f+=1,C.status==="copied"?(l.push(C.targetKey),$+=1):C.status==="skipped"?(u.push(C.targetKey),x+=1):(g.push(C.targetKey),I+=1),e.log.debug(`Lambda deploy ${C.status}: ${C.targetKey}`,{phase:"deploy-copy",batch:y+1,sourceKey:C.sourceKey,targetKey:C.targetKey,status:C.status,...C.error?{error:C.error}:{}});m+=1;let R=Date.now()-b;e.log.info(`Lambda deploy batch ${y+1}/${i.length} completed: ${$} copied, ${x} skipped unchanged, ${I} failed.`,{phase:"deploy-copy",batch:y+1,totalBatches:i.length,items:P.detail.objects.length,copied:$,skipped:x,failed:I,elapsedMs:R,elapsedSeconds:Math.round(R/10)/100,workerExporterVersion:P.response.exporterVersion,...P.requestId?{lambdaRequestId:P.requestId}:{},...P.completedAt?{workerCompletedAt:P.completedAt}:{}}),e.log.progress(`Lambda deploy: ${f}/${e.files.length}`,{phase:"deploy-copy",index:f,totalFiles:e.files.length,uploaded:l.length,skipped:u.length,failed:g.length,mode:"lambda-s3-copy",workerCount:p,completedBatches:m,totalBatches:i.length});}})),g.length>0)throw new Error(`Remote deployment failed for ${g.length} object(s).`);let h=[];for(let y=0;y<e.deletedFiles.length;y+=1e3){let b=e.deletedFiles.slice(y,y+1e3);if(b.length===0)continue;let P=await Pr({client:e.client,jobId:r,targetId:t.id,batchIndex:i.length+Math.floor(y/1e3)+1,items:[],deleteRelativeKeys:b,maxAttempts:e.maxAttempts});h.push(...P.detail.deletedKeys),e.log.progress(`Lambda deploy deletions: ${h.length}/${e.deletedFiles.length}`,{phase:"deploy-delete",index:h.length,totalFiles:e.deletedFiles.length,deleted:h.length,mode:"lambda-s3-copy"});}return {uploadedKeys:l,skippedKeys:u,failedKeys:g,deletedKeys:h}}async function ml(e){let t=Co(e.remoteConfig,e.config),r=ne(`deploy-manifest-${Date.now()}-${Ye(Buffer.from(t.id)).slice(0,12)}`,"jobId"),n=e.objects.map(f=>({sourceKey:f.object.key,targetRelativeKey:f.relativePath,sha256:f.object.sha256,bytes:f.object.bytes,contentType:f.contentType||"application/octet-stream",cacheControl:e.revalidateFiles.has(Ze(f.relativePath))?bn:bt(f.relativePath)?e.config.s3.htmlCacheControl:e.config.s3.assetCacheControl})),s=[],o=Math.max(1,Math.min(500,e.batchSize));for(let f=0;f<n.length;f+=o)s.push(n.slice(f,f+o));let a=[],c=[],i=[],d=0,l=0,u=Math.max(1,Math.min(Math.max(1,e.concurrency),Math.max(1,s.length)));if(e.log.progress(`Lambda deploy: 0/${n.length}`,{phase:"deploy-copy",index:0,totalFiles:n.length,mode:"lambda-s3-native",workerCount:u}),await Promise.all(Array.from({length:s.length===0?0:u},async()=>{for(;;){let f=d;if(f>=s.length)return;d+=1;let m=await Pr({client:e.client,jobId:r,targetId:t.id,batchIndex:f+1,items:s[f],maxAttempts:e.maxAttempts});for(let w of m.detail.objects)l+=1,w.status==="copied"?a.push(w.targetKey):w.status==="skipped"?c.push(w.targetKey):i.push(w.targetKey);e.log.progress(`Lambda deploy: ${l}/${n.length}`,{phase:"deploy-copy",index:l,totalFiles:n.length,uploaded:a.length,skipped:c.length,failed:i.length,mode:"lambda-s3-native",workerCount:u});}})),i.length>0)throw new Error(`Remote deployment failed for ${i.length} object(s).`);let g=[];for(let f=0;f<e.deletedFiles.length;f+=1e3){let m=e.deletedFiles.slice(f,f+1e3);if(m.length===0)continue;let w=await Pr({client:e.client,jobId:r,targetId:t.id,batchIndex:s.length+Math.floor(f/1e3)+1,items:[],deleteRelativeKeys:m,maxAttempts:e.maxAttempts});g.push(...w.detail.deletedKeys);}return {uploadedKeys:a,skippedKeys:c,failedKeys:i,deletedKeys:g}}async function gl(e,t,r,n,s){let o={...t,jobId:ne(`profile-${Ye(Buffer.from(n)).slice(0,16)}-${Date.now()}`,"jobId"),objects:{},assetMap:{...t.assetMap},generatedAt:new Date().toISOString()},a=0,c=Math.max(1,Math.min(Math.max(1,s),Math.max(1,r.length)));return await Promise.all(Array.from({length:r.length===0?0:c},async()=>{for(;;){let i=a;if(i>=r.length)return;a+=1;let d=r[i],l=dt(e.config.workspace.prefix,"jobs",o.jobId,"profile",Ye(Buffer.from(d.relativePath)),v.basename(d.relativePath));o.objects[d.relativePath]={...d,object:await e.copyWorkspaceObject(d.object,l)};}})),o}async function ko(e=process.argv.slice(2)){let t=await xe(),r=fr(e),n=yt(t,r),s=v.resolve(n.config.logDir||"logs"),o=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",a=o?v.join(v.resolve(o),"deploy-diff.json"):"",c=new lt(s,"deploy.log.jsonl",n.config.logLevel??"info"),i=n.profile?.extraReplacements??{},d=async()=>{};try{let l=await at(t);if(e.includes("--content-sync")&&l?.schemaVersion!==2)throw new Error("Content-sync deployment requires a valid schema-2 targeted deploy plan.");let g=await Yn(t);if(g)throw new Error(`Deployment blocked: the crawl started at ${g.startedAt} did not complete its final rewrite. Run a successful crawl or resume the rewrite before deploying.`);let f=t.remoteWorkers?.rewrite?.enabled===!0,m=t.remoteWorkers?.deploy?.enabled===!0,w=null,p=null;if(f||m){let A=nr({runtimeDir:o});if(!A)throw new Error("Remote Lambda workers are enabled, but the runtime directory is unknown.");w=await Yt(A);let _=!1;p=new pt(w,{},{onProgress:T=>{c.progress(`Lambda ${T.operation} batch: ${T.completedItems+T.failedItems}/${T.totalItems}`,{remoteWorkerOperation:T.operation,remoteWorkerTaskId:T.taskId,remoteWorkerStatus:T.status,remoteWorkerCompletedItems:T.completedItems,remoteWorkerFailedItems:T.failedItems,remoteWorkerTotalItems:T.totalItems,remoteWorkerUpdatedAt:T.updatedAt});},onProgressError:T=>{_||(_=!0,c.warn("Lambda progress status could not be read; task execution continues.",{error:T.message}));}});}let h=m&&f&&t.remoteWorkers?.render?.enabled===!0&&p&&w?.functions.asset?await or(t):null;if(h&&p&&w){if(h.workspace.bucket!==w.workspace.bucket||h.workspace.prefix!==w.workspace.prefix)throw new Error("Remote export manifest workspace does not match remote-workers.json.");let A=n.config,_=A.s3SyncMode??"sdk-upload-delete";if(l?.schemaVersion===2&&l.deletedFiles.length>0&&_!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let T=l?.schemaVersion===2?[...l.uploadGroups.assets,...l.uploadGroups.content,...l.uploadGroups.listings,...l.uploadGroups.resources,...l.uploadGroups.sitemapLeaves,...l.uploadGroups.sitemapIndexes]:l?.changedFiles??[];if(l?.schemaVersion===2){let le=[...new Set(T)],Fe=[...new Set(l.changedFiles)];if(le.length!==Fe.length||Fe.some(st=>!le.includes(st)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let he=!!l&&!l.fullSyncRequired?[...new Set(T.map(Ze))]:Object.keys(h.objects).sort(),q=he.filter(le=>!h.objects[le]);if(q.length>0)throw new Error(`Remote export manifest is missing ${q.length} planned object(s): ${q.slice(0,10).join(", ")}`);let Se=h,B=he.map(le=>h.objects[le]);n.name&&(t.targetOrigin!==A.targetOrigin||Object.keys(i).length>0)&&(Se=await gl(p,h,B,n.name||"default",t.concurrency),await rr(A,Se,Se.assetMap,{client:p,jobId:Se.jobId,concurrency:t.concurrency,batchSize:25,maxAttempts:2}),B=he.map(le=>Se.objects[le])),n.name&&c.info(`Using deployment profile: ${n.name}`),c.info(`Starting S3-native Lambda deploy - s3://${A.s3.bucket}/${A.s3.prefix||""} (${A.s3.region}).`),c.mark("deploy");let ie=await ml({client:p,remoteConfig:w,config:A,objects:B,deletedFiles:_==="sdk-upload-delete"?l?.deletedFiles??[]:[],revalidateFiles:new Set((l?.revalidateFiles??[]).map(Ze)),concurrency:t.concurrency,batchSize:50,maxAttempts:2,log:c});a&&(await F.mkdir(v.dirname(a),{recursive:!0}),await F.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:"lambda-s3-native",summary:{totalFiles:B.length,eligibleFiles:B.length,uploaded:ie.uploadedKeys.length,skipped:ie.skippedKeys.length,rejected:0,failed:ie.failedKeys.length,deleted:ie.deletedKeys.length,protected:0,...n.name?{profile:n.name}:{}},uploadedKeys:ie.uploadedKeys,skippedKeys:ie.skippedKeys,rejectedKeys:[],failedKeys:ie.failedKeys,deletedKeys:ie.deletedKeys,protectedRemoteOnlyKeys:[]},null,2),"utf8")),l?.schemaVersion!==2&&await Je(t),c.endMark("deploy"),await c.flush();return}let y=await ul(t,n.config,n.name,i,c,l?.schemaVersion===2?l.changedFiles:void 0,f&&p?{client:p,jobId:`profile-${Date.now()}`,concurrency:t.remoteWorkers?.rewrite?.concurrency??t.rewriteConcurrency,batchSize:t.remoteWorkers?.rewrite?.batchSize??25,maxAttempts:t.remoteWorkers?.rewrite?.maxAttempts??2,onStageProgress:({index:A,totalFiles:_,file:T})=>{(A===1||A===_||A%25===0)&&c.progress(`Staging deployment-profile rewrite: ${A}/${_}`,{phase:"rewrite-stage",index:A,totalFiles:_,file:T,execution:"lambda"});}}:void 0);d=y.cleanup;let b={...n.config,outputDir:y.outputDir},P=b.s3SyncMode??"sdk-upload-delete";if(l?.schemaVersion===2&&l.deletedFiles.length>0&&P!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let $=l?.schemaVersion!==2&&y.outputDir!==t.outputDir&&(t.targetOrigin!==n.config.targetOrigin||Object.keys(i).length>0),x=!!l&&!l.fullSyncRequired&&!$;if(l?.schemaVersion===2&&!x)throw new Error("Content-sync deployment cannot widen into a full-output deployment.");n.name&&c.info(`Using deployment profile: ${n.name}`),c.info(`Starting deploy \u2014 s3://${b.s3.bucket}/${b.s3.prefix||""} (region: ${b.s3.region})`),c.info(`S3 sync mode: ${P}`),l&&l.fullSyncRequired?c.info("Deploy plan requests a full sync; scanning the whole output tree."):l&&$?c.info("Ignoring incremental deploy plan because deployment-profile rewrites require a full sync."):x&&c.info(`Using incremental deploy plan: ${l.changedFiles.length} changed file(s), ${l.deletedFiles.length} deleted file(s).`),c.mark("deploy");let I=new S3Client({region:b.s3.region}),R=y.outputDir===t.outputDir?await Hc(t,o,c):null,C=l?.schemaVersion===2?[...l.uploadGroups.assets,...l.uploadGroups.content,...l.uploadGroups.listings,...l.uploadGroups.resources,...l.uploadGroups.sitemapLeaves,...l.uploadGroups.sitemapIndexes]:l?.changedFiles??[];if(l?.schemaVersion===2){let A=[...new Set(C)],_=[...new Set(l.changedFiles)];if(A.length!==_.length||_.some(T=>!A.includes(T)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let O=x?(await Promise.all(C.map(async A=>{try{return (await F.stat(v.join(b.outputDir,A))).isFile()?A:null}catch{if(l?.schemaVersion===2)throw new Error(`Content-sync planned upload is missing: ${A}`);return null}}))).filter(A=>A!==null):await fi(["**/*"],{cwd:b.outputDir,onlyFiles:!0,dot:!0}),V=[],U=[],S=O.filter(A=>{let _=R?.byRelativePath.get(Ze(A));if(!_)return !0;let T=wr(b.s3.prefix,A);return V.push(A),U.push(T),c.reject(_.kind,_.sourceUrl||A,"rewrite not completed; deploy upload blocked","deploy-guard",{file:A,key:T,outputPath:_.outputPath,manifestPath:R?.manifestPath}),!1}),W=new Set((l?.revalidateFiles||[]).map(Ze)),ce=new Set((x?S:O).map(A=>wr(b.s3.prefix,A)));R&&(R.pendingPages>0||R.pendingTextAssets>0)&&c.info(`Deploy rewrite guard loaded ${R.pendingPages} pending page(s) and ${R.pendingTextAssets} pending text asset(s) from crawl manifest.`,{manifestPath:R.manifestPath,pendingPages:R.pendingPages,pendingTextAssets:R.pendingTextAssets,source:"deploy-guard"}),V.length>0&&c.warn(`Deploy rewrite guard blocked ${V.length} file(s) from upload because final crawl rewrite is incomplete.`,{rejected:V.length,manifestPath:R?.manifestPath,source:"deploy-guard"}),x?c.info(`Using ${S.length} eligible planned changed file(s) from deploy plan for upload${V.length>0?` (${V.length} blocked by deploy rewrite guard)`:""}.`):c.info(`Found ${O.length} file(s) in output directory "${b.outputDir}"${V.length>0?`; ${S.length} remain eligible for upload after deploy rewrite guard filtering`:""}.`),c.progress("Deploy preflight: comparing local output with remote S3 state.",{phase:"deploy",mode:P,totalFiles:S.length,scannedFiles:O.length,rejected:V.length,deploymentProfile:n.name||"",s3Bucket:b.s3.bucket,s3Prefix:b.s3.prefix||"",targetedPlan:x,deployGuardEnabled:y.outputDir===t.outputDir});let E=0,D=0,j=0,X=[],Y=[],ee=[],H=[],de=[],be=new Map,k=new Map,L=new Map,M=new Map,G=new Map;if(m){if(!p||!w)throw new Error("Remote deploy worker client was not initialized.");if(P!=="sdk-upload-delete"&&P!=="sdk-upload-only")throw new Error(`Unsupported remote deploy mode: ${P}`);let A=await pl({client:p,remoteConfig:w,config:b,files:S,deletedFiles:P==="sdk-upload-delete"?l?.deletedFiles??[]:[],revalidateFiles:W,contentTypeByRelativePath:R?.contentTypeByRelativePath,concurrency:b.remoteWorkers?.deploy?.concurrency??b.assetDownloadConcurrency,batchSize:b.remoteWorkers?.deploy?.batchSize??50,maxAttempts:b.remoteWorkers?.deploy?.maxAttempts??2,log:c});X.push(...A.uploadedKeys),Y.push(...A.skippedKeys),ee.push(...A.failedKeys),H=A.deletedKeys,E=X.length,D=Y.length,j=ee.length,c.info(`Lambda deploy complete: ${E} copied, ${D} skipped unchanged, ${H.length} deleted, ${j} failed.`),a&&(await F.mkdir(v.dirname(a),{recursive:!0}),await F.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:"lambda-s3-copy",summary:{totalFiles:O.length,eligibleFiles:S.length,uploaded:E,skipped:D,rejected:U.length,failed:j,deleted:H.length,protected:0,...n.name?{profile:n.name}:{}},uploadedKeys:X,skippedKeys:Y,rejectedKeys:U,failedKeys:ee,deletedKeys:H,protectedRemoteOnlyKeys:[]},null,2),"utf8")),l?.schemaVersion!==2&&await Je(t),c.endMark("deploy"),await c.flush();return}x||(c.info("Listing existing S3 objects to detect unchanged files..."),be=await el(I,b.s3.bucket,b.s3.prefix,c),c.info(`Found ${be.size} existing key(s) in S3.`));let te=async A=>be.has(A)?be.get(A)??null:x?tl(I,b.s3.bucket,A,k):null;for(let A of S){let _=v.join(b.outputDir,A),T=wr(b.s3.prefix,A),re=R?.contentTypeByRelativePath.get(A),he=re&&re!=="application/octet-stream"?re:ks.lookup(A)||re||"application/octet-stream",q=W.has(Ze(A)),Se=q?bn:bt(A)?b.s3.htmlCacheControl:b.s3.assetCacheControl,B=E+D+j+1;S.length<=200||B<=5||B%10===0||B===S.length?(c.progress(`Uploading [${B}/${S.length}] ${T} (${he})`,{file:A,key:T,index:B,totalFiles:S.length,contentType:he,mode:P}),c.info(`Uploading [${B}/${S.length}] ${T} (${he})`)):c.debug(`Uploading [${B}/${S.length}] ${T} (${he})`);try{let Pe=await F.readFile(_),ie=await te(T),le=null,Fe=null;if(ie){let st=await rl(I,b.s3.bucket,T,ie),Mo=!q||So(st.cacheControl)===So(Se),jo=hn(st.contentType)===hn(String(he)),kr=Mo&&jo,Fo=Pe.byteLength;if(ie.size===Fo){let Ut=ie.etag.includes("-");if(ie.etag!==""&&!Ut){let Do=sl(Pe);if(ie.etag===Do&&kr){D++,S.length<=200||D<=5||D%25===0?(c.progress(`Skipped unchanged [${B}/${S.length}] ${T}`,{file:A,key:T,index:B,totalFiles:S.length,uploaded:E,skipped:D,failed:j,mode:P,reason:"etag-md5-match"}),c.info(`Skipped unchanged [${B}/${S.length}] ${T}`)):c.debug(`Skipped unchanged [${B}/${S.length}] ${T}`),Y.push(T);continue}}le=Ye(Pe);let xn=await ol(I,b.s3.bucket,T,L);if(xn&&xn===le&&kr){D++,S.length<=200||D<=5||D%25===0?(c.progress(`Skipped unchanged [${B}/${S.length}] ${T}`,{file:A,key:T,index:B,totalFiles:S.length,uploaded:E,skipped:D,failed:j,mode:P,reason:"metadata-sha256-match"}),c.info(`Skipped unchanged [${B}/${S.length}] ${T}`)):c.debug(`Skipped unchanged [${B}/${S.length}] ${T}`),Y.push(T);continue}}if(bt(A)){Fe=Sr(Pe);let Ut=await il(I,b.s3.bucket,T,M,G);if(Ut&&Ut===Fe&&kr){D++,S.length<=200||D<=5||D%25===0?(c.progress(`Skipped semantically unchanged [${B}/${S.length}] ${T}`,{file:A,key:T,index:B,totalFiles:S.length,uploaded:E,skipped:D,failed:j,mode:P,reason:"normalized-html-match"}),c.info(`Skipped semantically unchanged [${B}/${S.length}] ${T}`)):c.debug(`Skipped semantically unchanged [${B}/${S.length}] ${T}`),Y.push(T);continue}}}le=le??Ye(Pe),Fe=Fe??(bt(A)?Sr(Pe):null),await we(`S3 upload ${T}`,9e5,({abortController:st})=>new Upload({client:I,abortController:st,params:{Bucket:b.s3.bucket,Key:T,Body:Pe,ContentType:he,CacheControl:Se,Metadata:{[Ro]:le,...Fe?{[vo]:Fe}:{}}}}).done()),E++,X.push(T),(E%25===0||E===S.length)&&(c.progress(`Uploaded ${E}/${S.length} file(s)\u2026`,{uploaded:E,skipped:D,failed:j,totalFiles:S.length,mode:P}),c.info(`Uploaded ${E}/${S.length} file(s)\u2026`));}catch(Pe){j++,ee.push(T),c.error(`Failed to upload ${T}: ${Pe.message}`,{key:T,error:String(Pe)});}}if(c.info(`Upload complete: ${E} uploaded, ${D} skipped unchanged, ${U.length} rejected by guard, ${j} failed.`),ee.length>0||U.length>0)throw new Error(`Deployment stopped before deletion because ${ee.length} upload(s) failed and ${U.length} upload(s) were rejected.`);if(P==="sdk-upload-delete"){let A=new Set((l?.deletedFiles??[]).map(T=>wr(b.s3.prefix,T))),_=[...A].filter(T=>!ce.has(T));if(!x&&(de=[...be.keys()].filter(re=>!ce.has(re)).filter(re=>!A.has(re)),de.length>0)){c.warn(`Protected ${de.length} remote-only S3 object(s) from deletion because the crawl did not provide explicit tombstones.`,{protected:de.length,source:"deploy-delete-guard"});for(let re of de)c.debug(` protected remote-only object: ${re}`);}H=await nl(I,b.s3.bucket,x?_:_.filter(T=>be.has(T)),c);}else c.info("Sync mode is sdk-upload-only \u2014 skipping stale object deletion.");a&&(await F.mkdir(v.dirname(a),{recursive:!0}),await F.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:P,summary:{totalFiles:O.length,eligibleFiles:S.length,uploaded:X.length,skipped:Y.length,rejected:U.length,failed:ee.length,deleted:H.length,protected:de.length,...n.name?{profile:n.name}:{}},uploadedKeys:X,skippedKeys:Y,rejectedKeys:U,failedKeys:ee,deletedKeys:H,protectedRemoteOnlyKeys:de},null,2),"utf8")),l?.schemaVersion!==2&&await Je(t),c.endMark("deploy"),await c.flush();}finally{await d().catch(()=>{});}}function hl(e){let t=e;return t.endsWith("/")?t+="index.html":v.posix.basename(t).includes(".")||(t+="/index.html"),t}function wl(e,t){let r=t.trim().replace(/^\/+|\/+$/g,"");if(!r)return null;let n=`/${r}`;return e===n||e.startsWith(`${n}/`)?e:`${n}${e.startsWith("/")?e:`/${e}`}`}function xo(e,t){let r=new Set;for(let n of e){let s=new URL(n,"https://content-sync.invalid");if(s.origin!=="https://content-sync.invalid")continue;let o=`${s.pathname}${s.search}`,a=hl(s.pathname);r.add(o),r.add(`${a}${s.search}`);let c=wl(a,t);c&&r.add(`${c}${s.search}`);}return [...r].sort()}function Pl(){let e=String(process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"").trim();return e?v.join(v.resolve(e),"content-sync-invalidation.json"):""}async function Pn(e,t){if(!e)return;await F.mkdir(v.dirname(e),{recursive:true});let r=`${e}.${process.pid}.${Date.now()}.tmp`;await F.writeFile(r,JSON.stringify({...t,updatedAt:new Date().toISOString()},null,2),"utf8"),await F.rename(r,e);}async function Rl(e,t,r,n){if(!e)return null;try{let s=JSON.parse(await F.readFile(e,"utf8"));if(s.schemaVersion!==1||s.distributionId!==t||s.impactHash!==r||!Array.isArray(s.batches))throw new Error("Content-sync invalidation state does not match the deploy plan.");let o=s.batches.flatMap(a=>a.paths);return o.length!==n.length||o.some((a,c)=>a!==n[c])?null:s}catch(s){if(s.code==="ENOENT")return null;throw s}}function vl(e,t=3e3){let r=[];for(let n=0;n<e.length;n+=t)r.push(e.slice(n,n+t));return r}async function To(e=process.argv.slice(2)){let t=await xe(),r=fr(e),n=yt(t,r),s=n.config,o=new lt(s.logDir||"logs","invalidate.log.jsonl",s.logLevel??"info"),a=e.includes("--content-sync"),c=await at(t);if(a&&c?.schemaVersion!==2)throw new Error("Content-sync invalidation requires a valid schema-2 targeted deploy plan.");if(n.name&&o.info(`Using deployment profile: ${n.name}`),!s.cloudFront.distributionId){o.info("No CloudFront distributionId configured; skipping invalidation."),await o.flush();return}let i=c?.schemaVersion===2?c.invalidationPaths:s.cloudFront.invalidationPaths.length>0?s.cloudFront.invalidationPaths:["/*"],d=c?.schemaVersion===2?xo(i,s.s3.prefix||""):i;if(c?.schemaVersion===2&&d.some(m=>m==="/*"))throw new Error("Content-sync cannot use a whole-distribution invalidation.");if(d.length===0){o.info("The targeted deploy plan has no CloudFront paths to invalidate."),await o.flush();return}let l=s.cloudFront.distributionId,u=new CloudFrontClient({region:"us-east-1",maxAttempts:5});if(o.mark("invalidate"),c?.schemaVersion!==2){let m=`smartcloud-static-publisher-${Date.now()}`;await we(`CloudFront invalidation for distribution ${l}`,3e5,({httpOptions:w})=>u.send(new CreateInvalidationCommand({DistributionId:l,InvalidationBatch:{CallerReference:m,Paths:{Quantity:d.length,Items:d}}}),w)),o.endMark("invalidate"),await o.flush();return}let g=Pl(),f=await Rl(g,l,c.impactHash,d);if(!f){let m=createHash("sha256").update(JSON.stringify(d)).digest("hex");f={schemaVersion:1,distributionId:l,impactHash:c.impactHash,updatedAt:new Date().toISOString(),batches:vl(d).map((w,p)=>({index:p,callerReference:`wpsuite-content-sync-${c.impactHash.slice(0,24)}-${m.slice(0,24)}-${p}`,paths:w,invalidationId:null,status:"pending"}))},await Pn(g,f);}for(let m of f.batches){if(!m.invalidationId){let w=await we(`CloudFront targeted invalidation batch ${m.index+1}`,3e5,({httpOptions:h})=>u.send(new CreateInvalidationCommand({DistributionId:l,InvalidationBatch:{CallerReference:m.callerReference,Paths:{Quantity:m.paths.length,Items:m.paths}}}),h)),p=String(w.Invalidation?.Id||"").trim();if(!p)throw new Error("CloudFront did not return an invalidation ID.");m.invalidationId=p,m.status="created",await Pn(g,f);}await waitUntilInvalidationCompleted({client:u,maxWaitTime:900,minDelay:2,maxDelay:15},{DistributionId:l,Id:m.invalidationId}),m.status="completed",await Pn(g,f),o.info(`CloudFront invalidation batch ${m.index+1}/${f.batches.length} completed.`,{invalidationId:m.invalidationId,pathCount:m.paths.length});}o.endMark("invalidate"),await o.flush();}function Cr(e){let t=new URL(e);return t.hash="",t.href}function Ao(e,t,r){let n=new Set([...t].map(i=>Cr(i))),s=new Map,o=new Map,a=i=>{s.set(Cr(i),i);},c=i=>{if(!i)return;let d=Cr(i);s.has(d)||o.set(d,i);};for(let i of e.deleteUrls)a(i);for(let i of e.resourceDeleteUrls)a(i);for(let i of e.archiveFamilies)if(i.foundPosts===0)for(let d of i.pageUrls)n.has(Cr(d))||a(d);for(let i of e.directRenderUrls)c(i);for(let i of e.resourceRenderUrls)c(i);for(let i of e.archiveFamilies)c(i.pageUrls[0]),c(i.pageUrls.at(-1));for(let i of r)c(i);return {expectedAvailable:[...o.values()],expectedMissing:[...s.values()]}}var $o=["claimed","impact-planned","rendered","deployed","invalidated","verified","acknowledged"];function Cn(){let e=String(process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"").trim();if(!e)throw new Error("Content-sync requires a runtime directory.");return v.resolve(e)}function St(e,t){return $o.indexOf(e)>=$o.indexOf(t)}async function Ke(e,t,r,n,s={}){let o={timestamp:new Date().toISOString(),eventType:t,status:t.endsWith("failed")?"failed":"success",actorSource:"content-sync",jobId:r.id||"",command:"content-sync",message:n,details:s};await F.mkdir(e,{recursive:true}),await F.appendFile(v.join(e,"audit-events.jsonl"),`${JSON.stringify(o)}
|
|
19
|
-
`,"utf8");}function kl(e){return Pt({postTypes:e.postTypes??[],listingPaths:e.listingPaths??[],includeSubsites:e.includeSubsites,includePostTypeArchives:e.includePostTypeArchives,includeTaxonomyArchives:e.includeTaxonomyArchives,includeAuthorArchives:e.includeAuthorArchives,includeDateArchives:e.includeDateArchives,includePostsPage:e.includePostsPage,includeSitemapChain:e.includeSitemapChain})}function xl(e,t){let r=(e.scheduler?.rules??[]).filter(s=>s.command==="content-sync"&&s.id===t);if(r.length===0)throw new Error(`Content-sync scheduler rule not found: ${t}`);if(r.length>1)throw new Error(`Content-sync scheduler rule ID is not unique: ${t}`);let n=r[0];if(n.enabled===false)throw new Error(`Content-sync scheduler rule is disabled: ${t}`);return n}async function kn(e,t){if(e.subscriptionType!=="PROFESSIONAL"&&e.subscriptionType!=="AGENCY")throw new Error("Content-sync requires an active Professional or Agency subscription.");let r=kl(t),n=yt(e,t.deploymentProfile),s=n.name||"",o=An(e.sourceOrigin,String(t.id||""),r),a=En({sourceOrigin:e.sourceOrigin,targetOrigin:n.config.targetOrigin,deploymentProfile:s,s3Bucket:n.config.s3.bucket,s3Prefix:n.config.s3.prefix,cloudFrontDistributionId:n.config.cloudFront.distributionId,urlRewriteMode:n.config.urlRewriteMode,extraReplacements:n.profile?.extraReplacements??{}}),c=$n({siteId:e.wpsuite?.siteSettings?.siteId,accountId:e.wpsuite?.siteSettings?.accountId,sourceOrigin:e.sourceOrigin,ruleId:String(t.id||""),targetFingerprint:a}),i=`content-sync:${String(t.id||"")}:${De({scopeFingerprint:o,targetFingerprint:a}).slice(0,32)}`,d=new qt({sourceOrigin:e.sourceOrigin,runtimeToken:String(e.wpsuite?.runtimeToken||""),ignoreHttpsErrors:e.ignoreHttpsErrors}),l=await d.releaseFingerprint(r.includeSubsites),u=Tn({wordpressFingerprint:l,targetFingerprint:a,sourceOrigin:e.sourceOrigin,sitemapPaths:Ct(e.sitemapPaths),blockedPathPrefixes:e.blockedPathPrefixes,assetPathPrefixes:e.assetPathPrefixes,noJavaScriptRenderPathPrefixes:e.noJavaScriptRenderPathPrefixes,urlRewriteMode:e.urlRewriteMode});return {rule:t,scope:r,deployment:n,deploymentProfile:s,scopeFingerprint:o,targetFingerprint:a,consumerId:c,coalesceKey:i,client:d,releaseFingerprint:u}}async function Il(e){let t=Cn(),r=Wt(t),n=await xe(),s=(n.scheduler?.rules??[]).filter(d=>d.command==="content-sync"&&d.enabled!==false);if(s.length===0)return 0;let o=await Er(r),a=await Nt(r),c=await Ar(r),i=0;for(let d of s){let l=await kn(n,d),u=c.entries[l.coalesceKey];if(!u||u.releaseJobId!==e||u.scopeFingerprint!==l.scopeFingerprint||u.targetFingerprint!==l.targetFingerprint||u.releaseFingerprint!==l.releaseFingerprint)throw new Error(`The normal release has no matching pre-crawl content-sync cutoff for rule ${String(d.id||"")}.`);let g=De({releaseJobId:e,releaseFingerprint:l.releaseFingerprint,scopeFingerprint:l.scopeFingerprint,targetFingerprint:l.targetFingerprint,sequence:u.sequence}),f=await l.client.establishBaseline({consumerId:l.consumerId,scopeFingerprint:l.scopeFingerprint,baselineId:g,postTypes:l.scope.postTypes,includeSubsites:l.scope.includeSubsites,sequence:u.sequence}),m={schemaVersion:1,ruleId:String(d.id||""),consumerId:l.consumerId,coalesceKey:l.coalesceKey,scopeFingerprint:l.scopeFingerprint,targetFingerprint:l.targetFingerprint,releaseFingerprint:l.releaseFingerprint,baselineId:g,deploymentProfile:l.deploymentProfile,committedSequence:f.committedSequence,releaseJobId:e,verifiedAt:new Date().toISOString()};o.entries[l.coalesceKey]=m;let w=a.rules[l.coalesceKey];a.rules[l.coalesceKey]={ruleId:String(d.id||""),consumerId:l.consumerId,coalesceKey:l.coalesceKey,committedSequence:f.committedSequence,observedHeadSequence:f.headSequence,lag:Math.max(0,f.headSequence-f.committedSequence),lastSuccessfulJobId:w?.lastSuccessfulJobId||e,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:f.headSequence>f.committedSequence,retryAttempt:0,nextRetryAt:null,lastError:null,baselineStatus:"ready",baselineReason:null};let p=await Nn(r,l.coalesceKey);await Ke(t,"content-sync-baseline-established",{id:e},"A normal release established a verified content-sync baseline.",{ruleId:d.id,consumerId:l.consumerId,committedSequence:f.committedSequence,supersededCurrent:p}),i++;}return await Dn(r,o),await _t(r,a),await F.rm(r.releaseCutoff,{force:true}),i}async function Tl(e){let t=Cn(),r=Wt(t),n=await xe(),s=(n.scheduler?.rules??[]).filter(c=>c.command==="content-sync"&&c.enabled!==false);if(s.length===0)return 0;let o=await Ar(r),a=0;for(let c of s){let i=await kn(n,c),d=Object.values(o.entries).find(g=>g.releaseJobId===e&&g.ruleId===String(c.id||""));if(d){if(d.coalesceKey===i.coalesceKey&&d.scopeFingerprint===i.scopeFingerprint&&d.targetFingerprint===i.targetFingerprint&&d.releaseFingerprint===i.releaseFingerprint){a++;continue}throw new Error(`The normal release scope changed after its journal cutoff was captured for rule ${String(c.id||"")}. Start a new normal publish instead of resuming this release.`)}let l=await i.client.unboundHead(i.scope.postTypes,i.scope.includeSubsites),u={schemaVersion:1,releaseJobId:e,ruleId:String(c.id||""),coalesceKey:i.coalesceKey,scopeFingerprint:i.scopeFingerprint,targetFingerprint:i.targetFingerprint,releaseFingerprint:i.releaseFingerprint,sequence:l.headSequence,capturedAt:new Date().toISOString()};o.entries[i.coalesceKey]=u,await Ke(t,"content-sync-release-cutoff-captured",{id:e},"A normal release captured its pre-crawl content-sync journal cutoff.",{ruleId:c.id,consumerId:i.consumerId,sequence:l.headSequence}),a++;}return await Fn(r,o),a}async function Al(e,t){let r=JSON.parse(await F.readFile(v.join(e,"current-run.json"),"utf8"));if(r.id!==t||r.command!=="content-sync"||!String(r.ruleId||"").trim())throw new Error("The active queue job is not the requested content-sync job.");return r}async function vn(e,t,r=0){let n=e.protocol==="https:"?jn:Vo,s=e.protocol==="https:"?new jn.Agent({rejectUnauthorized:!t}):void 0;return new Promise((o,a)=>{let c=n.get(e,{agent:s,timeout:3e4,headers:{"user-agent":"WP-Suite-Content-Sync/1"}},i=>{let d=i.statusCode??500,l=i.headers.location;if(d>=300&&d<400&&l&&r<5){i.resume(),vn(new URL(l,e),t,r+1).then(o,a);return}let u=[],g=0;i.on("data",f=>{g+=f.byteLength,g<=1048576&&u.push(f);}),i.on("error",a),i.on("end",()=>o({status:d,body:Buffer.concat(u).toString("utf8"),contentType:String(i.headers["content-type"]||"")}));});c.on("timeout",()=>c.destroy(new Error(`Verification timed out: ${e}`))),c.on("error",a);})}async function El(e,t,r,n){let s=t.deployment.config.targetOrigin;if(!/^https?:\/\//i.test(s))throw new Error("Content-sync verification requires an absolute HTTP(S) target origin.");let o=JSON.parse(await F.readFile(n,"utf8")),a=new Set;for(let[l,u]of Object.entries(o.pages??{}))a.add(l),typeof u.url=="string"&&a.add(u.url);let c=await at(e);if(c?.schemaVersion!==2||c.impactHash!==r.impactHash)throw new Error("Content-sync verification requires the matching targeted deploy plan.");let i=Ao(r,a,c.resolvedSitemapUrls),d=new Set(r.resourceRenderUrls.map(l=>{let u=new URL(l);return u.hash="",u.href}));for(let l of i.expectedAvailable){let u=new URL(l),g=new URL(`${u.pathname}${u.search}`,s),f=await vn(g,e.ignoreHttpsErrors);if(f.status<200||f.status>=400)throw new Error(`Content-sync verification failed (${f.status}): ${g}`);let m=new URL(l);if(m.hash="",d.has(m.href)){if(!f.contentType.toLowerCase().startsWith("application/json"))throw new Error(`Resource verification expected application/json: ${g}`);try{JSON.parse(f.body);}catch{throw new Error(`Resource verification received invalid JSON: ${g}`)}}}for(let l of i.expectedMissing){let u=new URL(l),g=new URL(`${u.pathname}${u.search}`,s),f=await vn(g,e.ignoreHttpsErrors);if(f.status>=200&&f.status<300)throw new Error(`Deleted content is still publicly available: ${g}`)}}async function $l(e){let t=await F.readFile(e.candidateManifest,"utf8");JSON.parse(t);let r=`${e.trustedManifest}.${process.pid}.tmp`;await F.writeFile(r,t,"utf8"),await F.rename(r,e.trustedManifest);}async function Ol(e,t){try{let r=JSON.parse(await F.readFile(e.candidateManifest,"utf8"));if([...Object.values(r.pages??{}),...Object.values(r.assets??{})].some(s=>s?.lastSeenRunId===t))return "resumed"}catch(r){if(r.code!=="ENOENT")throw new Error(`The content-sync candidate manifest is invalid: ${r instanceof Error?r.message:String(r)}`,{cause:r})}return await F.copyFile(e.trustedManifest,e.candidateManifest).catch(r=>{throw new Error(`A trusted crawl manifest is required before content-sync: ${r instanceof Error?r.message:String(r)}`,{cause:r})}),"initialized"}async function nt(e,t,r,n,s={},o=0,a=async()=>{}){t.phase=r,await Un(e,t),await Wn(e,{schemaVersion:1,jobId:t.jobId,phase:r,completedItems:n,totalItems:n,attempt:o,updatedAt:new Date().toISOString(),details:s}),await Ke(v.dirname(e.state),"content-sync-checkpoint",{id:t.jobId},`Content-sync checkpoint completed: ${r}.`,{phase:r,completedItems:n,totalItems:n,attempt:o,...s}),await a(r,t);}async function Ml(e,t={}){let r={loadConfig:xe,resolveRuleContext:kn,runCrawl:wo,runDeploy:ko,runInvalidate:To,verifyDeployment:El,promoteCandidateManifest:$l,clearDeployPlan:Je,afterCheckpoint:async()=>{},...t},n=Cn(),s=Wt(n),o=await Al(n,e),a=await r.loadConfig(),c=xl(a,String(o.ruleId)),i=await r.resolveRuleContext(a,c);if(o.coalesceKey&&o.coalesceKey!==i.coalesceKey)throw new Error("Queued content-sync demand no longer matches the active rule scope.");let l=(await Er(s)).entries[i.coalesceKey];if(!l||l.scopeFingerprint!==i.scopeFingerprint||l.targetFingerprint!==i.targetFingerprint||l.releaseFingerprint!==i.releaseFingerprint)throw await Ke(n,"content-sync-baseline-rejected",o,"Content-sync requires a new verified full or incremental release baseline.",{ruleId:c.id,reason:l?"mismatch":"missing"}),new Error("Content-sync baseline is missing or stale. Run a successful normal publish first.");let u=await $r(s),g=await i.client.head({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites});if(u&&u.jobId!==o.id)throw new Error("Another immutable content-sync range is still active.");if(u||(u={schemaVersion:1,jobId:o.id,ruleId:String(c.id||""),consumerId:i.consumerId,coalesceKey:i.coalesceKey,scopeFingerprint:i.scopeFingerprint,targetFingerprint:i.targetFingerprint,baselineId:l.baselineId,fromSequence:g.committedSequence,toSequence:g.headSequence,phase:"claimed",impactHash:null,startedAt:new Date().toISOString(),updatedAt:new Date().toISOString()},await nt(s,u,"claimed",0,{fromSequence:u.fromSequence,toSequence:u.toSequence},0,r.afterCheckpoint),await Ke(n,"content-sync-range-claimed",o,"Content-sync claimed a closed journal range.",{fromSequence:u.fromSequence,toSequence:u.toSequence})),u.fromSequence===u.toSequence){let h=await Nt(s);h.rules[i.coalesceKey]={ruleId:String(c.id||""),consumerId:i.consumerId,coalesceKey:i.coalesceKey,committedSequence:u.toSequence,observedHeadSequence:g.headSequence,lag:Math.max(0,g.headSequence-u.toSequence),lastSuccessfulJobId:o.id,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:false,retryAttempt:0,nextRetryAt:null,lastError:null},await _t(s,h),await Or(s);return}let f=await Ln(s);if(!St(u.phase,"impact-planned")){let h=await i.client.events({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites,afterSequence:u.fromSequence,throughSequence:u.toSequence}),y=Tr({events:h,scope:i.scope,sourceOrigin:a.sourceOrigin}),b=await i.client.resolveImpactFamilies(y,i.scope.includeSubsites);f=Mn({jobId:o.id,ruleId:String(c.id||""),consumerId:i.consumerId,coalesceKey:i.coalesceKey,scopeFingerprint:i.scopeFingerprint,targetFingerprint:i.targetFingerprint,baselineId:l.baselineId,sourceOrigin:a.sourceOrigin,scope:i.scope,fromSequence:u.fromSequence,toSequence:u.toSequence,events:h,resolvedArchiveFamilies:b,sitemapUrls:Ct(a.sitemapPaths)}),await qn(s,f),u.impactHash=f.impactHash,await nt(s,u,"impact-planned",h.length,{eventCount:h.length,foldedCount:f.foldedCount,impactHash:f.impactHash},0,r.afterCheckpoint),await Ke(n,"content-sync-impact-planned",o,"Content-sync persisted an immutable impact plan.",{impactHash:f.impactHash,eventCount:h.length});}if(!f||f.jobId!==o.id||u.impactHash!==f.impactHash)throw new Error("The immutable content-sync impact plan is missing or mismatched.");if(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH=s.candidateManifest,!St(u.phase,"rendered")){let h=await Ol(s,o.id);await Ke(n,h==="resumed"?"content-sync-render-resumed":"content-sync-render-initialized",o,h==="resumed"?"Content-sync resumed its candidate crawl manifest.":"Content-sync initialized a candidate crawl manifest.",{impactHash:f.impactHash}),await r.runCrawl(["--content-sync-plan",s.impact]),await nt(s,u,"rendered",f.directRenderUrls.length+f.archiveFamilyUrls.length+f.resourceRenderUrls.length,{impactHash:f.impactHash},o.attempt??0,r.afterCheckpoint);}let m=i.deploymentProfile?["--profile",i.deploymentProfile]:[];if(St(u.phase,"deployed")||(await r.runDeploy([...m,"--content-sync"]),await nt(s,u,"deployed",1,{impactHash:f.impactHash},0,r.afterCheckpoint),await Ke(n,"content-sync-deployed",o,"Content-sync targeted deployment completed.",{impactHash:f.impactHash})),St(u.phase,"invalidated")?St(u.phase,"verified")||await r.runInvalidate([...m,"--content-sync"]):(await r.runInvalidate([...m,"--content-sync"]),await nt(s,u,"invalidated",1,{impactHash:f.impactHash},0,r.afterCheckpoint)),St(u.phase,"verified")||(await r.verifyDeployment(a,i,f,s.candidateManifest),await r.promoteCandidateManifest(s),await nt(s,u,"verified",1,{impactHash:f.impactHash},0,r.afterCheckpoint)),g=await i.client.head({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites}),g.committedSequence===u.fromSequence)await i.client.acknowledge({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,expectedSequence:u.fromSequence,sequence:u.toSequence,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites});else if(g.committedSequence!==u.toSequence)throw new Error("Content-sync acknowledgement cursor is in an unexpected state.");await nt(s,u,"acknowledged",1,{sequence:u.toSequence},0,r.afterCheckpoint),await Ke(n,"content-sync-cursor-acknowledged",o,"Content-sync committed its journal cursor after verification.",{sequence:u.toSequence});let w=await i.client.head({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites}),p=await Nt(s);p.rules[i.coalesceKey]={ruleId:String(c.id||""),consumerId:i.consumerId,coalesceKey:i.coalesceKey,committedSequence:u.toSequence,observedHeadSequence:w.headSequence,lag:Math.max(0,w.headSequence-u.toSequence),lastSuccessfulJobId:o.id,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:w.headSequence>u.toSequence,retryAttempt:0,nextRetryAt:null,lastError:null},await _t(s,p),await r.clearDeployPlan(a),await F.rm(v.join(n,"content-sync-invalidation.json"),{force:true}),await F.rm(s.candidateManifest,{force:true}),await Or(s);}async function Oo(e=process.argv.slice(2)){let r=e.indexOf("--capture-baseline-cutoffs");if(r>=0){let a=String(e[r+1]||"").trim();if(!a)throw new Error("--capture-baseline-cutoffs requires a release job ID.");await Tl(a);return}let n=e.indexOf("--establish-baselines");if(n>=0){let a=String(e[n+1]||"").trim();if(!a)throw new Error("--establish-baselines requires a release job ID.");await Il(a);return}let s=e.indexOf("--job-id"),o=s>=0?String(e[s+1]||"").trim():"";if(!o)throw new Error("Content-sync requires --job-id.");await Ml(o);}Oo().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exit(1);});
|
|
18
|
+
${o}`,40);return n.info(`Using generated 404 fallback change token for ${r}`,{url:r,requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),{url:r,supported:!0,token:a,tokenSource:"generated-404-response-hash",postId:null,dependencyPostIds:[],reason:null}}catch(s){return n.warn(`Generated 404 fallback token lookup failed for ${r}`,{url:r,error:String(s),requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),null}}async function oo(e,t,r,n,s,o){let a=wr(e,s);if(await Ea(e,t,r,n,s,o),!n.enabled)return {action:"render",changeToken:n.trackManifest?await ur(e,t,n,s,o):null};let c=n.manifest.pages[s];if(!c)return {action:"render",changeToken:await ur(e,t,n,s,o)};let i=await ur(e,t,n,s,o);if(i?.supported&&i.token)return c.changeToken===i.token?a&&!await Ma(e,t,s,o)?{action:"render",changeToken:i}:{action:"reuse",changeToken:i}:{action:"render",changeToken:i};let d=tt(r.sitemapLastmodByPage[s]);return d&&c.sitemapLastmod&&c.sitemapLastmod===d?{action:"reuse",changeToken:i}:{action:"render",changeToken:i}}async function Ma(e,t,r,n){try{let o=(await t.get(r,{timeout:Math.min(e.navigationTimeoutMs,15e3),failOnStatusCode:!1})).status();return o===404?!0:(n.warn(`Generated 404 request path no longer returns 404 for ${r}`,{url:r,status:o,requestPath:e.generated404RequestPath,source:"generated-404-status-probe"}),!1)}catch(s){return n.warn(`Generated 404 status probe failed for ${r}`,{url:r,error:String(s),requestPath:e.generated404RequestPath,source:"generated-404-status-probe"}),false}}async function ja(e,t,r,n,s){let o=Bs(r.previousManifest,void 0,n,"previous-manifest"),a=0;for(let[f,p]of Object.entries(r.manifest.pages))if(!r.seenPages.has(f)){un(s,e,p.outputPath);try{await F.unlink(p.outputPath);}catch(g){(g.code||"")!=="ENOENT"&&n.warn(`Failed to remove stale incremental page output for ${f}`,{url:f,outputPath:p.outputPath,error:String(g)});}delete r.manifest.pages[f],a++;}let c=Bs(r.manifest,r.runId,n,"active-manifest"),i=new Set,d=new Set;for(let f of c){for(let w of Ot(e,f))i.add(w);let p=r.manifest.assets[f]?.outputPath;p&&d.add(p);let g=ht(e,t.assetMap,f);g&&d.add(g);}for(let f of Object.keys(r.manifest.assets)){if(c.has(f)){r.manifest.assets[f].unreferencedRuns=0;continue}let p=r.manifest.assets[f];if(Ps(p.unreferencedRuns)){p.unreferencedRuns+=1,n.warn(`Deferred deletion of newly unreferenced incremental asset ${f}.`,{url:f,unreferencedRuns:p.unreferencedRuns,phase:"incremental-cleanup",source:"asset-deletion-grace"});continue}delete r.manifest.assets[f];}let l=0,u=0;for(let f of o){if(r.manifest.assets[f])continue;let p=new Set,g=r.previousManifest.assets[f]?.outputPath;g&&p.add(g);let w=ht(e,t.assetMap,f);if(!c.has(f)&&w)p.add(w);else if(!c.has(f)){let m=Za(e,f,n,"incremental-cleanup");m&&(p.add(m.originalFilePath),m.hashedFilePath&&p.add(m.hashedFilePath));}for(let m of p)if(!d.has(m)){un(s,e,m);try{await F.unlink(m),l++;}catch(h){(h.code||"")!=="ENOENT"&&n.warn(`Failed to remove stale incremental asset output for ${f}`,{url:f,outputPath:m,error:String(h)});}}for(let m of Ot(e,f))i.has(m)||Object.prototype.hasOwnProperty.call(t.assetMap,m)&&(delete t.assetMap[m],u++);}(a>0||l>0||u>0)&&n.info(`Incremental cleanup removed ${a} stale pages, ${l} stale assets, ${u} stale asset mappings`,{removedPages:a,removedAssets:l,removedAssetMappings:u,phase:"incremental-cleanup"});}async function Fa(e,t,r,n){let s=new Set([...Object.values(t.manifest.pages),...Object.values(t.manifest.assets)].map(i=>String(i.outputPath||"").trim()).filter(Boolean).map(i=>C.resolve(i))),o=Object.values(e.postCrawlCopyMap||{}).map(i=>dr(String(i||""))).filter(i=>!!i).map(i=>C.resolve(e.outputDir,i)),c=(await Ri(["**/*.html","**/*.htm"],{cwd:e.outputDir,onlyFiles:true,dot:true})).filter(i=>Ss(C.join(e.outputDir,i),e.outputDir,s,o));for(let i of c){let d=C.join(e.outputDir,i);un(n,e,d),await F.unlink(d);}c.length>0&&r.info(`Removed ${c.length} orphaned HTML output file(s) that are absent from the current crawl manifest.`,{phase:"incremental-cleanup",source:"manifest-output-reconciliation",removedPages:c.length,samples:c.slice(0,20)});}function Bs(e,t,r,n){let s=new Set,o=a=>{let c=a.trim();if(c){if(r){let i=ke(c,r,"asset",n??"manifest");if(!i)return;s.add(i.toString());return}s.add(c);}};for(let a of Object.values(e.pages))for(let c of a.discoveredAssets||[])o(c);for(let[a,c]of Object.entries(e.assets||{}))t&&c.lastSeenRunId!==t||o(a);return s}function Hs(e,t,r){for(let n of t)for(let s of Ot(e,n))if(r.has(s))return true;return false}function Da(e,t,r,n,s){let o=new Set(r.rewriteTargets);for(let c of r.changedFiles)o.add(C.resolve(e.outputDir,c));for(let c of Object.values(t.manifest.pages))c.rewriteComplete||o.add(C.resolve(c.outputPath));for(let c of Object.values(t.manifest.assets))c.isText&&!c.rewriteComplete&&o.add(C.resolve(c.outputPath));let a=Aa(n,s);if(a.size===0)return [...o];for(let c of Object.values(t.manifest.pages))Hs(e,c.discoveredAssets,a)&&o.add(C.resolve(c.outputPath));for(let[c,i]of Object.entries(t.manifest.assets)){i.isText&&Hs(e,i.discoveredAssets,a)&&o.add(C.resolve(i.outputPath));for(let d of Ot(e,c))if(a.has(d)){le(r,e,i.outputPath),i.isText&&o.add(C.resolve(i.outputPath));break}}return [...o]}function Ua(e,t){let r=t?new Set(Array.from(t,s=>C.resolve(s))):null,n=s=>r===null||r.has(C.resolve(s));for(let s of Object.values(e.manifest.pages))n(s.outputPath)&&(s.rewriteComplete=true);for(let s of Object.values(e.manifest.assets)){if(!s.isText){s.rewriteComplete=true;continue}n(s.outputPath)&&(s.rewriteComplete=true);}}function La(e,t,r){let n=new Set,s=o=>{if(!o)return;let a=me(e.outputDir,o);a&&n.add(a);};for(let o of t.donePages)s(je(e,o));for(let o of Object.values(r.manifest.pages))o.lastSeenRunId===r.runId&&s(o.outputPath);for(let o of t.doneAssets)s(ht(e,t.assetMap,o));for(let o of Object.values(r.manifest.assets))o.lastSeenRunId===r.runId&&s(o.outputPath);return n}async function qa(e,t,r,n,s,o){let a=[...n.deletedFiles].sort(),c=La(e,t,r),i=0;for(let u of [...c].sort())if(!o?.objects[u]){try{if((await F.stat(C.join(e.outputDir,u))).isFile())continue}catch{}i++,s.warn(`Active output is missing after crawl: ${u}`,{phase:"deploy-plan",file:u,outputPath:C.join(e.outputDir,u)});}if(i>0&&s.warn(`Detected ${i} active output file(s) missing before deploy plan save.`,{phase:"deploy-plan",missingActiveOutputs:i}),a.length===0)return [];let d=[],l=0;for(let u of a){if(!c.has(u)){d.push(u);continue}l++;let f=C.join(e.outputDir,u),p;try{p=(await F.stat(f)).isFile();}catch{p=false;}s.warn(`Deploy plan protected active output from deletion: ${u}`,{phase:"deploy-plan",file:u,outputPath:f,exists:p});}return l>0&&s.info(`Deploy plan skipped ${l} active output deletion(s).`,{phase:"deploy-plan",protectedDeletes:l,deletedFiles:d.length}),d}function Ot(e,t){let r=new Set([t]);try{let n=new URL(t),o=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{o.push(new URL(e.targetOrigin).origin);}catch{}for(let a of o)try{r.add(new URL(a).origin+n.pathname+n.search);}catch{}r.add(n.pathname+n.search),r.add(n.pathname);}catch{}return [...r]}function Wa(e,t){let r=new Set([t]);try{let n=new URL(t),o=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{o.push(new URL(e.targetOrigin).origin);}catch{}for(let a of o)try{r.add(new URL(a).origin+n.pathname+n.search);}catch{}r.add(n.pathname+n.search);}catch{}return [...r]}function io(e,t){let r=e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/"?e.targetOrigin:"https://relative.invalid/";try{let n=new URL(t,r);return At(e.outputDir,n.pathname)}catch{return null}}function ao(e,t,r){for(let n of Wa(e,r)){let s=t[n];if(!s)continue;let o=io(e,s);if(o)return {outputPath:o,publicUrl:s}}return null}function Na(e,t,r){for(let n of Ot(e,r)){let s=t[n];if(!s)continue;let o=io(e,s);if(o)return o}return null}function ht(e,t,r){let n=Na(e,t,r);if(n)return n;try{return Dt(e,r).originalFilePath}catch{return null}}function _a(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?C.join(C.resolve(e),"queue-runner-heartbeat.json"):""}async function on(e){let t=_a();if(t)try{let r=await F.readFile(t,"utf8"),n=JSON.parse(r);if(!n||typeof n!="object")return;await F.writeFile(t,JSON.stringify({...n,checkedAt:new Date().toISOString(),status:"running",currentStep:"rewrite",message:e},null,2),"utf8");}catch{}}function Ba(e,t){let r=new Set;for(let n of t.donePages)r.add(C.resolve(je(e,n)));for(let n of t.doneAssets){let s=ht(e,t.assetMap,n);!s||!$e(s)||r.add(C.resolve(s));}for(let n of t.doneSitemaps){let s=ht(e,t.assetMap,n);!s||!$e(s)||r.add(C.resolve(s));}return [...r]}var pr="re:",lr=new Map;function Ha(e){if(!e.startsWith(pr))return null;let t=lr.get(e);if(t!==void 0)return t||null;let r=e.slice(pr.length).trim();if(!r)return lr.set(e,false),null;try{let n=new RegExp(r);return lr.set(e,n),n}catch{return console.warn(`[crawl] Ignoring invalid path matcher regex: ${e}`),lr.set(e,false),null}}function bn(e,t){let r=Ha(t);return r?r.test(e):t.startsWith(pr)?false:e.startsWith(t)}function Va(e,t){return t.find(r=>bn(e,r))}function co(e,t){let r=Va(t.pathname,e.blockedPathPrefixes);if(r)return r.startsWith(pr)?`blocked path regex: ${r}`:`blocked path prefix: ${r}`;let n=e.blockedSearchFragments.find(s=>t.search.includes(s));return n?`blocked search fragment: ${n}`:null}function Ka(e){let t=new URL(e.sourceOrigin),r=new Set([t.hostname,...e.allowedAssetHosts]);if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{r.add(new URL(e.targetOrigin).hostname);}catch{}for(let n of Object.keys(e.extraReplacements||{}))try{r.add(new URL(n).hostname);}catch{}return r}function za(e,t){return Ka(e).has(t.hostname)}function Ja(e){let t=We(e.trim()).replace(/\\\//g,"/").replace(/^['"]|['"]$/g,"").trim();return t=t.replace(/[)]+$/g,"").trim(),t=t.replace(/;.*$/g,"").trim(),t}function pn(e){let t=We(e).replace(/\\\//g,"/");return /[{}]|\bwindow\.|\blocation\.|\bincludes\(|\?\?null|\+|%7B|%7D|%22|<|>|\s/.test(t)||/[()[\]'"]/.test(t)}function Qa(e){let t=We(e).replace(/\\\//g,"/").trim(),r=C.extname(t).toLowerCase();return Xs.has(r)||eo.has(r)?false:/^(?:this|[A-Za-z_$][\w$]*)\.[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(t)}function rt(e){return ya.some(t=>e.pathname.startsWith(t))}function oe(e,t,r=e.sourceOrigin,n,s="url",o=false){let a=Ja(t);if(!a||a.startsWith("data:")||a.startsWith("blob:")||a.startsWith("mailto:")||a.startsWith("tel:")||a.startsWith("#"))return n?.ignore(s,t,"empty or unsupported scheme",r),null;if(pn(a))return n?.ignore(s,t,"looks like JavaScript/code fragment",r),null;if(Qa(a))return n?.ignore(s,t,"looks like JavaScript property access",r),null;try{let c=new URL(a,r);if(lo(c))return n?.reject(s,t,"malformed URL encoding",r),null;if(!["http:","https:"].includes(c.protocol))return n?.ignore(s,t,"unsupported protocol: ",r),null;if(!za(e,c))return n?.ignore(s,c.toString(),"host not allowed",r),null;let i=co(e,c);if(i&&!(o&&Ur(c)))return n?.reject(s,c.toString(),i,r),null;let d=new URL(e.sourceOrigin);return c.protocol=d.protocol,c.host=d.host,c.hash="",c}catch{return n?.reject(s,t,"invalid URL",r),null}}function lo(e){try{return decodeURIComponent(e.pathname),decodeURIComponent(e.search),decodeURIComponent(e.hash),!1}catch{return true}}function ke(e,t,r,n){try{let s=new URL(e);return lo(s)?(t.reject(r,e,"malformed URL encoding",n),null):Tt(s.pathname)===null?(t.reject(r,e,"unsafe URL pathname",n),null):s.protocol!=="http:"&&s.protocol!=="https:"?(t.reject(r,e,`unsupported protocol: ${s.protocol}`,n),null):s}catch{return t.reject(r,e,"invalid URL",n),null}}function uo(e){return Xs.has(C.extname(e.pathname).toLowerCase())}function Ve(e){return rt(e)?false:eo.has(C.extname(e.pathname).toLowerCase())}function yt(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function G(e,t){return !!(yt(t)||t.pathname==="/robots.txt"||t.pathname==="/llms.txt"||t.pathname.toLowerCase().endsWith(".xsl")||e.assetPathPrefixes.length>0&&e.assetPathPrefixes.some(r=>bn(t.pathname,r))||uo(t)||!Ve(t)&&!rt(t))}function je(e,t){let r=new URL(t),n=Tt(r.pathname);if(n===null)throw new Error(`Unsafe page URL pathname: ${r.pathname}`);return n.endsWith("/")?n+="index.html":C.extname(n)||(n+="/index.html"),At(e.outputDir,n)}function Ga(e){if(!e.generated404RequestPath)return null;try{let t=new URL(e.generated404RequestPath,e.sourceOrigin);return !t.pathname.endsWith("/")&&C.extname(t.pathname)===""&&(t.pathname+="/"),t.hash="",t.toString()}catch{return null}}function wr(e,t){let r=Ga(e);if(!r)return false;try{return new URL(t,e.sourceOrigin).toString()===r}catch{return false}}function Dt(e,t){let r=new URL(t),n=Tt(r.pathname);if(n===null)throw new Error(`Unsafe asset URL pathname: ${r.pathname}`);n.endsWith("/")&&(n+="index.html");let s=!!r.search,o=n,a=At(e.outputDir,o),c=Kr(e.targetOrigin,o),i=`${c}${r.search}`;if(!s)return {originalPathname:o,originalFilePath:a,originalPublicUrl:c,originalPublicUrlWithSearch:i,preferQueryHashed:s};let d=C.extname(n),u=`${d?n.slice(0,-d.length):n}.${Ee(r.search)}${d||".bin"}`;return {originalPathname:o,originalFilePath:a,originalPublicUrl:c,originalPublicUrlWithSearch:i,preferQueryHashed:s,hashedPathname:u,hashedFilePath:At(e.outputDir,u),hashedPublicUrl:Kr(e.targetOrigin,u)}}function Za(e,t,r,n){let s=ke(t,r,"asset",n);return s?Dt(e,s.toString()):null}function mn(e,t,r,n,s){t[r]=n;try{let o=new URL(r),c=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{c.push(new URL(e.targetOrigin).origin);}catch{}for(let i of c)try{let d=new URL(i);t[d.origin+o.pathname+o.search]=n;}catch{}try{let i=(()=>{let d=new URL(n,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin);return `${d.pathname}${d.search}`})();t[o.pathname+o.search]=i;}catch{}try{let i=new URL(n,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[o.pathname]=i;}catch{}try{let i=new URL(s,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[o.pathname]=i;}catch{}}catch{}}async function po(e){try{return await F.readFile(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}async function Ze(e){try{return await F.stat(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}function Ya(e){let t=String(e["content-length"]||"").trim();if(!t)return null;let r=Number.parseInt(t,10);return Number.isFinite(r)&&r>=0?r:null}function mo(e){let t=String(e["last-modified"]||"").trim();if(!t)return null;let r=Date.parse(t);return Number.isFinite(r)?r:null}function Xa(e,t){let r=mo(t),n=Ya(t),s=e?.mtime.getTime();return r!==null&&Math.abs((s??0)-r)>=1e3||n!==null&&e?.size!==n?false:r!==null||n!==null}async function ec(e,t){if(!t)return;let r=mo(t);if(r===null)return;let n=await Ze(e);if(!n)return;let s=new Date(r);await F.utimes(e,n.atime,s).catch(()=>{});}function gn(e,t){let r=C.extname(e.pathname).toLowerCase(),n=t["content-type"]||"";return wa.has(r)||ha.some(s=>n.includes(s))&&!n.startsWith("image/")&&!n.includes("font")}function tc(e){try{let t=C.extname(new URL(e).pathname).toLowerCase();return t===".js"||t===".mjs"}catch{return false}}function Ge(e,t){(e.doneAssets.size%25===0||e.doneAssets.size===1||e.doneAssets.size===e.stats.assetsQueued)&&t.progress(`Asset processing progress: processed ${e.doneAssets.size}, discovered ${e.stats.assetsQueued}.`,{doneAssets:e.doneAssets.size,assetsQueued:e.stats.assetsQueued,phase:"download-assets"});}function rc(e){return Ee(e.toString("base64"),40)}function go(e,t,r){let n=e.assetVariantDigestsByOriginalPath.get(t);if(!n||n.size===0)return false;for(let s of n)if(s!==r)return true;return false}function fo(e,t,r){let n=e.assetVariantDigestsByOriginalPath.get(t);n||(n=new Set,e.assetVariantDigestsByOriginalPath.set(t,n)),n.add(r);}async function fn(e,t,r,n,s,o,a){let c=Dt(e,r),i=rc(n),d=c.originalFilePath,l=c.originalPublicUrlWithSearch;if(c.preferQueryHashed&&c.hashedFilePath&&c.hashedPublicUrl&&go(s,c.originalFilePath,i)){let g=ao(e,t,r);g?(d=g.outputPath,l=g.publicUrl):(d=c.hashedFilePath,l=c.hashedPublicUrl);}mn(e,t,r,l,c.originalPublicUrl);let u=$e(d)?Buffer.from(Gr(n.toString("utf8"),e,t,d),"utf8"):n,f=await po(d),p=false;return (f===null||!f.equals(u))&&(await qe(d,u),p=true),o?.debug(`${p?"Saved":"Skipped unchanged"} asset output ${r}`,{phase:"download-assets",url:r,outputPath:d,bytes:u.length,wroteFile:p}),fo(s,c.originalFilePath,i),await ec(d,a),s.stats.assetsSaved++,o&&(s.stats.assetsSaved%50===0||s.stats.assetsSaved===1)&&o.progress(`Asset progress: saved ${s.stats.assetsSaved}, discovered ${s.stats.assetsQueued}, pending ${s.assetQueue.length}.`,{assetsSaved:s.stats.assetsSaved,assetsQueued:s.stats.assetsQueued,assetQueue:s.assetQueue.length,phase:"download-assets"}),{outputPath:d,publicUrl:l,wroteFile:p}}function nt(e,t,r,n,s){let o=()=>{let u=String(s??"").trim();if(!u)return {discoveredFrom:"",discoveredFromType:"unknown"};if(u==="seed-path"||u==="cli"||u==="generated-404-request-path")return {discoveredFrom:u,discoveredFromType:u};if(/^https?:\/\//i.test(u))try{let f=new URL(u);return yt(f)?{discoveredFrom:u,discoveredFromType:"sitemap"}:G(e,f)?{discoveredFrom:u,discoveredFromType:"asset"}:Ve(f)&&!rt(f)?{discoveredFrom:u,discoveredFromType:"page"}:{discoveredFrom:u,discoveredFromType:"url"}}catch{return {discoveredFrom:u,discoveredFromType:"url"}}return {discoveredFrom:u,discoveredFromType:"url"}},a=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,c=oe(e,r,a,n,"page");if(!c)return;if(!Ve(c)||uo(c)){if(G(e,c)){n.info(`Seeded/non-page URL queued as asset: ${c.toString()}`,{url:c.toString(),source:s}),Q(e,t,c.toString(),n,s);return}n.reject("page",c.toString(),rt(c)?"asset/internal path cannot be page":"not page-like",s);return}let i=c.toString(),{discoveredFrom:d,discoveredFromType:l}=o();d&&!t.pageDiscoverySources.has(i)&&t.pageDiscoverySources.set(i,d),!t.donePages.has(i)&&!t.queuedPages.has(i)&&(t.queuedPages.add(i),t.pageQueue.push(i),t.stats.pagesQueued++,n.debug(`Queued discovered page ${i}`,{phase:"discovery",url:i,discoveredFrom:d,discoveredFromType:l,outputPath:je(e,i)}),(t.stats.pagesQueued%25===0||t.stats.pagesQueued===1)&&n.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,pageQueue:t.pageQueue.length,phase:"discovery"}));}function Q(e,t,r,n,s){let o=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,a=oe(e,r,o,n,"asset");if(!a)return;if(!G(e,a)){n.reject("asset",a.toString(),"not a safe asset path/prefix",s);return}let c=a.toString();!t.doneAssets.has(c)&&!t.queuedAssets.has(c)&&(t.queuedAssets.add(c),t.assetQueue.push(c),t.stats.assetsQueued++,(t.stats.assetsQueued%100===0||t.stats.assetsQueued===1)&&n.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,assetQueue:t.assetQueue.length,phase:"discovery"}));}function mr(e,t,r,n,s){let o=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,a=oe(e,r,o,n,"sitemap",zn(s));if(!a)return;if(!yt(a)){n.reject("sitemap",a.toString(),"not sitemap-like",s);return}let c=a.toString();!t.doneSitemaps.has(c)&&!t.queuedSitemaps.has(c)&&(t.queuedSitemaps.add(c),t.sitemapQueue.push(c),t.stats.sitemapsQueued++,(t.stats.sitemapsQueued%10===0||t.stats.sitemapsQueued===1)&&n.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,sitemapQueue:t.sitemapQueue.length,phase:"discovery"}));}function nc(e){let t=We(e),r=[...t.matchAll(/<url>\s*([\s\S]*?)\s*<\/url>/gi)].map(n=>n[1]);return r.length>0?r.map(n=>{let s=n.match(/<loc>\s*([^<]+?)\s*<\/loc>/i);if(!s?.[1])return null;let o=n.match(/<lastmod>\s*([^<]+?)\s*<\/lastmod>/i);return {loc:s[1].trim(),lastmod:tt(o?.[1]??null)}}).filter(n=>!!n):[...t.matchAll(/<loc>\s*([^<]+?)\s*<\/loc>/gi)].map(n=>({loc:n[1].trim(),lastmod:null})).filter(n=>n.loc)}function sc(e){return e.split(",").map(t=>t.trim().split(/\s+/)[0]).filter(Boolean)}function oc(e){let t=[],r=/url\(\s*(?:"([^"]+)"|'([^']+)'|([^)]*?))\s*\)/gi;for(let n of e.matchAll(r)){let s=e.slice(Math.max(0,n.index-8),n.index);if(/\bnew\s+$/i.test(s))continue;let o=(n[1]||n[2]||n[3]||"").trim();o&&t.push(o);}return t}function ic(e){return e.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>/gi,"")}function ac(e,t){if(t==="dom-style")return true;let r=(()=>{try{return C.extname(new URL(e).pathname).toLowerCase()}catch{return ""}})();return !(r===".js"||r===".mjs"||r===".map"||t.includes("javascript"))}function dr(e){return e.trim().replace(/\\/g,"/").replace(/^https?:\/\/[^/]+/i,"").replace(/^\/+/,"")}async function ho(e,t,r,n){let s=[];await F.mkdir(t,{recursive:true});let o=await F.readdir(e,{withFileTypes:true});for(let a of o){let c=C.join(e,a.name),i=C.join(t,a.name);if(a.isDirectory()){s.push(...await ho(c,i,r,n));continue}await wo(c,i,r,n)&&s.push(i);}return s}async function cc(e,t){try{let[r,n]=await Promise.all([F.stat(e),F.stat(t)]);if(r.size!==n.size)return !1;let[s,o]=await Promise.all([F.readFile(e),F.readFile(t)]);return s.equals(o)}catch{return false}}async function wo(e,t,r,n){let s=C.resolve(t);return r.has(s)?(n.debug("Skipped post-crawl copy over crawled page output",{phase:"copy-extra-paths",sourcePath:e,targetPath:t}),false):await cc(e,t)?(n.debug("Skipped unchanged post-crawl copy target",{phase:"copy-extra-paths",sourcePath:e,targetPath:t}),false):(await F.mkdir(C.dirname(t),{recursive:true}),await F.copyFile(e,t),true)}async function lc(e,t,r){let n=Object.entries(e.postCrawlCopyMap||{}).map(([c,i])=>({sourcePath:c.trim(),prefix:String(i||"").trim()}));if(n.length===0)return [];let s=0,o=[],a=new Set([...t.donePages].map(c=>C.resolve(je(e,c))));r.mark("copy-extra-paths");for(let c of n){let i=c.sourcePath,d=c.prefix;if(!i||!d){r.warn("Skipped post-crawl copy mapping with empty key/value",{sourcePath:i,prefixPath:d});continue}let l=va(i);if(!l.resolvedPath){r.warn("Skipped post-crawl copy source because alias root is not configured",{sourcePath:i,alias:l.alias||"",requiredEnv:l.requiredEnv||"",prefixPath:d});continue}let u=l.resolvedPath,f=dr(d);if(!f){r.warn("Skipped post-crawl copy mapping with invalid export prefix",{sourcePath:i,prefixPath:d});continue}let p;try{p=await F.stat(u);}catch{r.warn("Skipped post-crawl copy source because it does not exist",{sourcePath:i,sourceAbs:u,prefixPath:d});continue}let g=C.resolve(e.outputDir,f);if(p.isDirectory()){let y=await ho(u,g,a,r);o.push(...y),s+=y.length,y.length>0&&r.progress(`Copied static directory to export: ${u} -> /${f}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${f}`,copiedItems:s,changedFiles:y.length});continue}let w=C.basename(u),m=d.endsWith("/")?C.join(g,w):g;await wo(u,m,a,r)&&(o.push(m),s++,r.progress(`Copied static file to export: ${u} -> /${dr(d.endsWith("/")?`${d}${w}`:d)}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${dr(d.endsWith("/")?`${d}${w}`:d)}`,copiedItems:s}));}return r.endMark("copy-extra-paths",{mappedSources:n.length,copiedItems:s}),o}function wt(e,t,r,n,s){let o=new Set,a=We(r).replace(/\\\//g,"/"),c=s==="page-html"?ic(a):a,i=ac(t,s);if(i){for(let d of oc(c)){let l=oe(e,d,t,n,`${s}:css-url`);l&&G(e,l)&&o.add(l.toString());}for(let d of c.matchAll(/@import\s+(?:url\()?\s*['"]?([^'"\s;]+)['"]?\s*\)?/gi)){let l=oe(e,d[1],t,n,`${s}:css-import`);l&&G(e,l)&&o.add(l.toString());}}if(i||s==="page-html")for(let d of c.matchAll(/<\?xml-stylesheet[^>]+href=["']([^"']+)["'][^>]*\?>/gi)){let l=oe(e,d[1],t,n,`${s}:xml-stylesheet`);l&&G(e,l)&&o.add(l.toString());}if(s==="page-html")for(let d of ws(a)){let l=d.startsWith("//")?`${new URL(e.sourceOrigin).protocol}${d}`:d;if(pn(l)){n.ignore(`${s}:serialized-url`,l,"looks like JavaScript/code fragment",t);continue}let u=oe(e,l,t,n,`${s}:serialized-url`);u&&G(e,u)?o.add(u.toString()):u&&n.ignore("asset",u.toString(),"serialized URL did not pass safe asset path filter",t);}if(s!=="page-html"&&tc(t))for(let d of ys(a)){if(pn(d)||!/\.(?:js|mjs)(?:[?#]|$)/i.test(d))continue;let l=oe(e,d,t,n,`${s}:relative-asset`);l&&G(e,l)&&o.add(l.toString());}return [...o]}function yo(e,t,r,n){let s=new Set,o=We(r);for(let a of o.matchAll(/href=["']([^"'#\s][^"']*?)["']/gi)){let c=a[1],i=oe(e,c,t,n,"page-link");i&&(co(e,i)||Ve(i)&&!rt(i)&&!G(e,i)&&s.add(i.toString()));}return [...s]}async function Vs(e,t,r,n,s,o,a=false,c=[]){let i=new Set(c),d=0,l=new Map,u=(f,p)=>{let g=[p],w=new Set;for(;g.length>0;){let m=g.pop();if(m===f)return true;w.has(m)||(w.add(m),g.push(...l.get(m)??[]));}return false};for(;r.sitemapQueue.length>0;){let f=r.sitemapQueue.shift();r.queuedSitemaps.delete(f);let p=ke(f,n,"sitemap","sitemap-queue");if(!p)continue;let g=p.toString();if(r.doneSitemaps.has(g))continue;r.doneSitemaps.add(g),n.sitemap(`Fetching sitemap ${g}`,{url:g});let w=true;try{let m=await t.get(g,{timeout:6e4});if(w=!1,!m.ok()){if(n.skip("sitemap",g,m.status()),a&&!i.has(g))throw new Error(`Required child content-sync sitemap returned HTTP ${m.status()}: ${g}`);continue}let h=await m.body(),y=m.url()||g,b=ke(y,n,"sitemap-response",g);if(!b)continue;let P=b.toString();r.successfulSitemaps.add(g),r.successfulSitemaps.add(P),i.has(g)&&(r.resolvedSitemapRoots.add(P),d+=1);let O=await fn(e,r.assetMap,P,h,r,n);le(s,e,O.outputPath),Ce(s,O.outputPath);let x=h.toString("utf8");/<sitemapindex(?:\s|>)/i.test(x)?r.sitemapIndexUrls.add(P):r.sitemapLeafUrls.add(P);let k=wt(e,P,x,n,"sitemap");for(let A of k)Q(e,r,A,n,P);let R=[];for(let A of nc(x)){let I=oe(e,A.loc,P,n,"sitemap-loc",!0);if(!I){if(a)throw new Error(`Content-sync sitemap contains an inadmissible location: ${A.loc}`);continue}if(yt(I)){if(u(P,I.toString()))throw new Error(`Sitemap index cycle detected: ${P} -> ${I.toString()}`);if(l.has(P)||l.set(P,new Set),l.get(P).add(I.toString()),R.push(I.toString()),a&&r.doneSitemaps.has(I.toString())&&!r.successfulSitemaps.has(I.toString()))throw new Error(`Required child content-sync sitemap was not resolved: ${I.toString()}`);mr(e,r,I.toString(),n,P);}else if(a){if(Ve(I)&&!G(e,I)){let K=o.requiredUrls.has(I.toString()),D=o.manifest.pages[I.toString()],S=!!D&&!!await Ze(D.outputPath);if(!K&&!S)throw new Error(`Content-sync sitemap coverage is incomplete for ${I.toString()}.`)}n.ignore("sitemap-loc",I.toString(),"content-sync sitemap-only traversal does not enqueue urlset locations",P);}else G(e,I)?Q(e,r,I.toString(),n,P):Ve(I)?(A.lastmod&&(r.sitemapLastmodByPage[I.toString()]=A.lastmod),nt(e,r,I.toString(),n,P)):n.reject("sitemap-loc",I.toString(),"not page/sitemap/asset-like",P);}o.trackManifest&&(o.manifest.assets[P]={url:P,outputPath:O.outputPath,isText:!0,contentType:m.headers()["content-type"]??"application/xml",cacheControl:ln(m.headers()),changeToken:null,tokenSource:null,discoveredAssets:[...new Set([...k,...R])],lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,unreferencedRuns:0,rewriteComplete:!1},await He(e,o));}catch(m){n.error(`Failed sitemap ${g}`,{url:g,error:String(m)});let h=a&&i.has(g)&&w;if(a&&!h)throw m}}if(a&&i.size>0&&d===0)throw new Error(`None of the configured content-sync sitemap roots could be resolved: ${[...i].join(", ")}`)}async function uc(e,t,r,n,s,o,a){let c=oe(e,n,e.sourceOrigin,s,"asset-fetch");if(!c||!G(e,c))return;let i=c.toString();if(r.doneAssets.has(i))return;let d=o.enabled||o.strictTargeted?o.previousManifest.assets[i]:void 0,l=o.trackManifest?await ur(e,t,o,i,s):null,u=l?.token??null,f=Zr(d?.changeToken,l),p=o.strictTargeted&&(!l?.supported||!l.token)&&Yr(e.sourceOrigin,i),g=o.strictTargeted?o.manifest.assets[i]:void 0;if(g?.lastSeenRunId===o.runId&&await Ze(g.outputPath)){r.doneAssets.add(i);for(let m of g.discoveredAssets||[])Q(e,r,m,s,i);le(a,e,g.outputPath),ft(a,e,g.outputPath,g.cacheControl),g.isText&&Ce(a,g.outputPath),s.info(`Resumed completed content-sync asset ${i}`,{url:i,source:"content-sync-checkpoint"}),Ge(r,s);return}if(d&&(f||p)&&await Ze(d.outputPath)){o.manifest.assets[i]={...d,changeToken:u,tokenSource:l?.tokenSource??d.tokenSource,discoveredAssets:[...d.discoveredAssets||[]],lastSeenRunId:o.runId,unreferencedRuns:0},delete o.manifest.pages[i],r.doneAssets.add(i);for(let m of d.discoveredAssets||[])Q(e,r,m,s,i);ft(a,e,d.outputPath,d.cacheControl),s.info(`Reused unchanged trusted asset ${i}.`,{url:i,tokenSource:l?.tokenSource??"unknown",phase:"download-assets",source:f?"asset-change-token-match":"content-sync-release-fingerprint"}),Ge(r,s);return}let w=(m,h={})=>{if(!d||o.strictTargeted)return false;o.manifest.assets[i]={...d,discoveredAssets:[...d.discoveredAssets||[]],lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,unreferencedRuns:0},delete o.manifest.pages[i],r.doneAssets.add(i);for(let y of d.discoveredAssets||[])Q(e,r,y,s,i);return s.warn(`Keeping previous incremental asset ${i} after fetch issue.`,{url:i,reason:m,preservedFromPreviousManifest:true,...h,phase:"download-assets"}),Ge(r,s),true};s.asset(`Fetching asset ${i}`,{url:i});try{let m=ht(e,r.assetMap,i),h=m?await Ze(m):null;if(m&&h&&!o.strictTargeted)try{let D=await se(`fetch asset headers ${i}`,6e4,()=>t.head(i,{timeout:6e4})),S=D.headers();if(D.ok()&&Xa(h,S)){let q=await po(m);if(q!==null){let ue=D.url()||i,H=ke(ue,s,"asset-response",i);if(!H)return;let B=H.toString(),T=await fn(e,r.assetMap,B,q,r,s,S);T.wroteFile&&(le(a,e,T.outputPath),$e(T.outputPath)&&Ce(a,T.outputPath));let W=ln(S)||d?.cacheControl||null;ft(a,e,T.outputPath,W),r.doneAssets.add(i),s.info(`Reused existing asset ${i} based on response headers.`,{url:i,filePath:m,lastModified:S["last-modified"]||"",contentLength:S["content-length"]||"",phase:"download-assets"}),Ge(r,s);let U=gn(c,S),z=d?.discoveredAssets?[...d.discoveredAssets]:[];if(U||d?.isText){let J=q.toString("utf8"),de=wt(e,B,J,s,"asset:cached");(de.length>0||!d)&&(z=de);for(let Se of z)Q(e,r,Se,s,B);}if(o.trackManifest){let J=U||!!d?.isText;o.manifest.assets[i]={url:i,outputPath:T.outputPath,isText:J,contentType:cn(S)||d?.contentType||null,cacheControl:W,changeToken:l?.supported?l.token:null,tokenSource:l?.supported?l.tokenSource??null:null,discoveredAssets:z,lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,unreferencedRuns:0,rewriteComplete:!J},delete o.manifest.pages[i],(o.enabled||o.strictTargeted)&&J&&await He(e,o);}return}}}catch{}let y=await se(`fetch asset ${i}`,6e4,()=>t.get(i,{timeout:6e4}));if(!y.ok()){if(w(`http-${y.status()}`,{status:y.status()}))return;if(o.strictTargeted)throw new Error(`Required content-sync asset returned HTTP ${y.status()}: ${i}`);s.skip("asset",i,y.status());return}let b=await se(`read asset response ${i}`,6e4,()=>y.body()),P=y.url()||i,O=ke(P,s,"asset-response",i);if(!O)return;let x=O.toString(),k=y.headers(),R=await fn(e,r.assetMap,x,b,r,s,k);R.wroteFile&&(le(a,e,R.outputPath),$e(R.outputPath)&&Ce(a,R.outputPath));let A=ln(k);ft(a,e,R.outputPath,A),r.doneAssets.add(i),Ge(r,s);let I=gn(c,k),K=[];if(I){let D=b.toString("utf8");K=wt(e,x,D,s,`asset:${C.extname(c.pathname).toLowerCase()||k["content-type"]||"unknown"}`);for(let S of K)Q(e,r,S,s,x);}o.trackManifest&&(o.manifest.assets[i]={url:i,outputPath:R.outputPath,isText:I,contentType:cn(k),cacheControl:A,changeToken:l?.supported?l.token:null,tokenSource:l?.supported?l.tokenSource??null:null,discoveredAssets:K,lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,unreferencedRuns:0,rewriteComplete:!I},delete o.manifest.pages[i],(o.enabled||o.strictTargeted)&&I&&await He(e,o));}catch(m){if(w("fetch-error",{error:String(m)}))return;if(s.error(`Failed asset ${i}`,{url:i,error:String(m)}),o.strictTargeted)throw m}finally{r.doneAssets.has(i)||(r.doneAssets.add(i),Ge(r,s));}}async function dc(e,t,r,n,s,o){let a=Math.max(1,Number(e.assetDownloadConcurrency||e.concurrency||1)),c=Array.from({length:a},async()=>{for(;r.assetQueue.length>0;){let i=r.assetQueue.shift();i&&(r.queuedAssets.delete(i),await uc(e,t,r,i,n,s,o));}});await Promise.all(c);}function gr(e,t){let r=me(e.outputDir,t);if(!r)throw new Error(`Remote export output is outside outputDir: ${t}`);return r}function pc(e,t){return gn(e,{"content-type":t})}function Ks(e){return /(?:^|\/)index\.html?$|\.html?$/i.test(e)}async function mc(e,t,r,n,s,o,a,c,i){let d=Math.max(1,Math.min(100,i)),l=20;for(;r.assetQueue.length>0;){let u=r.assetQueue.splice(0,d*l);for(let w of u)r.queuedAssets.delete(w);await yn(e,t,s,u,n);let f=[];for(let w of u){let m=s.manifest.assets[w],h=m?me(e.outputDir,m.outputPath):null,y=h?a.objects[h]:void 0,b=s.changeTokenCache.get(w)??null;if(!(s.enabled&&m&&y?.kind==="asset"&&y.sourceUrl===w&&(Zr(m.changeToken,b)||(!b?.supported||!b.token)&&Yr(e.sourceOrigin,w)))||!m||!h||!y){f.push(w);continue}s.manifest.assets[w]={...m,changeToken:b?.token??null,tokenSource:b?.tokenSource??m.tokenSource,lastSeenRunId:s.runId,unreferencedRuns:0};for(let O of m.discoveredAssets||[])Q(e,r,O,n,w);r.doneAssets.add(w),ft(o,e,m.outputPath,m.cacheControl),n.info(`Reused unchanged S3-native asset ${w}.`,{url:w,relativePath:h,tokenSource:b?.tokenSource??"release-fingerprint",phase:"download-assets",execution:"lambda"}),Ge(r,n);}if(f.length===0)continue;let p=[];for(let w=0;w<f.length;w+=l)p.push(f.slice(w,w+l));let g=await Promise.all(p.map(w=>c.fetch({urls:w,ignoreHttpsErrors:e.ignoreHttpsErrors,timeoutMs:6e4})));for(let w of g)for(let m of w.assets){let h=m.requestedUrl;try{if(m.outcome!=="fetched"||!m.object||!m.finalUrl){let A=m.error||`Remote asset fetch ended with ${m.outcome}.`;if(n.error(`Failed remote asset ${h}`,{url:h,status:m.httpStatus,outcome:m.outcome,error:A,execution:"lambda"}),s.strictTargeted)throw new Error(A);continue}let y=ke(m.finalUrl,n,"remote-asset-response",h);if(!y)continue;let b=Dt(e,y.toString()),P=b.originalFilePath,O=b.originalPublicUrlWithSearch;if(b.preferQueryHashed&&b.hashedFilePath&&b.hashedPublicUrl&&go(r,b.originalFilePath,m.object.sha256)){let A=ao(e,r.assetMap,y.toString());P=A?.outputPath??b.hashedFilePath,O=A?.publicUrl??b.hashedPublicUrl;}mn(e,r.assetMap,y.toString(),O,b.originalPublicUrl),y.toString()!==h&&mn(e,r.assetMap,h,O,b.originalPublicUrl),fo(r,b.originalFilePath,m.object.sha256);let x=gr(e,P),k=m.contentType?.trim()||"application/octet-stream",R=pc(y,k);gt(a,{relativePath:x,sourceUrl:h,kind:"asset",contentType:k,cacheControl:m.cacheControl,isText:R,object:m.object}),le(o,e,P),R&&Ce(o,P),ft(o,e,P,m.cacheControl);for(let A of m.discoveredAssets)Q(e,r,A,n,y.toString());r.stats.assetsSaved++,s.trackManifest&&(s.manifest.assets[h]={url:h,outputPath:P,isText:R,contentType:k,cacheControl:m.cacheControl,changeToken:null,tokenSource:null,discoveredAssets:[...m.discoveredAssets],lastCrawledAt:new Date().toISOString(),lastSeenRunId:s.runId,unreferencedRuns:0,rewriteComplete:!R},delete s.manifest.pages[h]),n.debug(`Remote asset fetch completed ${h}`,{url:h,finalUrl:y.toString(),relativePath:x,bytes:m.object.bytes,taskId:w.taskId,attempts:w.attempts,execution:"lambda"});}finally{r.doneAssets.add(h),Ge(r,n);}}}}async function gc(e,t,r,n){for(let s of [...t.changedFiles].sort()){if(r.objects[s])continue;let o=C.join(e.outputDir,s),a=await F.readFile(o).catch(l=>{throw new Error(`Coordinator-owned output is missing before S3 staging: ${s}`,{cause:l})}),c=$e(o),i=String(Es.lookup(s)||"")||(c?"text/plain; charset=utf-8":"application/octet-stream"),d=await n.writeWorkspaceObject({key:`${r.workspace.prefix}jobs/${r.jobId}/coordinator/${Ee(s,40)}-${C.basename(s)}`,body:a,contentType:i,cacheControl:Ks(s)?e.s3.htmlCacheControl:e.s3.assetCacheControl});gt(r,{relativePath:s,sourceUrl:null,kind:"generated",contentType:i,cacheControl:Ks(s)?e.s3.htmlCacheControl:e.s3.assetCacheControl,isText:c,object:d});}}function fc(e){let t=Math.ceil(e/1e3);return `${t} second${t===1?"":"s"}`}function Be(e){return Math.max(6e4,e.navigationTimeoutMs*2,e.readiness.timeoutMs+e.readiness.fallbackWaitMs+15e3)}function $t(e){return Math.max(15e3,Math.min(6e4,Be(e)))}function bo(e){return Math.max(15e3,e.readiness.timeoutMs+e.readiness.fallbackWaitMs+1e4)}function Sn(e){return e.stats.pagesCompleted}function hn(e){let r=e.options?.browserProcess;return {pid:typeof r?.process?.pid=="number"?r.process.pid:null,kill:typeof r?.kill=="function"?r.kill.bind(r):null}}async function an(e,t,r){let n=hn(e);try{if(n.kill){await n.kill(),t.warn(`Force-killed crawl worker browser after ${r}`,{browserPid:n.pid,reason:r});return}if(n.pid!==null){process.kill(n.pid,"SIGKILL"),t.warn(`Sent SIGKILL to crawl worker browser after ${r}`,{browserPid:n.pid,reason:r});return}t.warn(`Could not resolve crawl worker browser PID after ${r}`,{reason:r});}catch(s){t.error(`Failed to force-kill crawl worker browser after ${r}`,{browserPid:n.pid,reason:r,error:String(s)});}}async function se(e,t,r){let n;try{return await Promise.race([r(),new Promise((s,o)=>{n=globalThis.setTimeout(()=>{o(new Mt(e,t));},t);})])}finally{n!==void 0&&globalThis.clearTimeout(n);}}var Mt=class extends Error{constructor(r,n){super(`${r} timed out after ${fc(n)}.`);this.operation=r;this.timeoutMs=n;this.name="OperationTimeoutError";}operation;timeoutMs};async function hc(e,t){let r=bo(e);await t.evaluate(async n=>{await new Promise(s=>{let o=0,a=700,c=Date.now(),i=()=>{window.clearInterval(d),window.scrollTo(0,0),s();},d=window.setInterval(()=>{if(Date.now()-c>=n.maxDurationMs){i();return}window.scrollBy(0,a),o+=a;let l=document.body?.scrollHeight||0,u=document.documentElement?.scrollHeight||0,f=Math.max(l,u);o>=f+window.innerHeight&&i();},120);});},{maxDurationMs:r});}async function wc(e,t){await t.waitForLoadState("domcontentloaded",{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForSelector&&await t.waitForSelector(e.readiness.waitForSelector,{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForFunction&&await t.waitForFunction(e.readiness.waitForFunction,void 0,{timeout:e.readiness.timeoutMs}).catch(()=>{}),await hc(e,t),await t.waitForTimeout(e.readiness.fallbackWaitMs);}async function yc(e,t){await t.waitForLoadState("domcontentloaded",{timeout:e.readiness.timeoutMs}).catch(()=>{}),await t.waitForLoadState("load",{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForSelector&&await t.waitForSelector(e.readiness.waitForSelector,{timeout:e.readiness.timeoutMs}).catch(()=>{}),await t.waitForTimeout(e.readiness.fallbackWaitMs);}function So(e,t){return e.noJavaScriptRenderPathPrefixes.some(r=>bn(t,r))}async function bc(e,t,r,n,s=true){let o=new Set;if(s){let c=await t.evaluate(()=>{let i=new Set,d=["href","src","poster","data-src","data-lazy-src","data-original","data-bg","data-background","data-href","data-resource-url"],l=new Set,u=["srcset","data-srcset","data-lazy-srcset"],f=p=>{p.querySelectorAll("*").forEach(g=>{for(let m of d){let h=g.getAttribute(m);h&&i.add(h);}for(let m of u){let h=g.getAttribute(m);h&&h.split(",").forEach(y=>{let b=y.trim().split(/\s+/)[0];b&&i.add(b);});}let w=g.getAttribute("style");w&&l.add(w),g.shadowRoot&&f(g.shadowRoot);});};return f(document),{attrs:[...i],styles:[...l]}});for(let i of c.attrs)for(let d of sc(i)){let l=oe(e,d,r,n,"dom-attr");l&&G(e,l)&&o.add(l.toString());}for(let i of c.styles)for(let d of wt(e,r,i,n,"dom-style"))o.add(d);}let a=await t.content();for(let c of wt(e,r,a,n,"page-html"))o.add(c);return [...o]}async function zs(e){return await e.evaluate(()=>{document.querySelectorAll("#wpsuite-consent-root").forEach(t=>t.remove()),document.documentElement.classList.remove("wpsuite-consent-scroll-locked"),document.body.classList.remove("wpsuite-consent-scroll-locked");}),e.content()}async function wn(e,t,r,n,s){let o=je(e,t);await qe(o,r,"utf8");let a=await F.stat(o);s?.debug(`Saved page output ${t}`,{phase:"save-pages",url:t,outputPath:o,bytes:a.size});let c=fr(n,o),i=Math.min(n.stats.pagesQueued,Sn(n)+1);s&&c&&(n.stats.pagesSaved%10===0||n.stats.pagesSaved===1)&&s.progress(`Page progress: processed ${i}, rendered ${n.stats.pagesRendered}, saved ${n.stats.pagesSaved}, discovered ${n.stats.pagesQueued}.`,{donePages:i,claimedPages:n.donePages.size,pagesRendered:n.stats.pagesRendered,pagesSaved:n.stats.pagesSaved,pagesQueued:n.stats.pagesQueued,pageQueue:n.pageQueue.length,phase:"save-pages"});}function fr(e,t){let r=C.resolve(t);return e.savedPageOutputs.has(r)?false:(e.savedPageOutputs.add(r),e.stats.pagesSaved=e.savedPageOutputs.size,true)}async function hr(e,t,r,n,s){let o=me(e.outputDir,n);if(!o)return;if(s){let c=s.objects[o];c?.kind==="page"&&c.sourceUrl===r&&c.object?.bucket===s.workspace.bucket&&typeof c.object.key=="string"&&c.object.key.startsWith(s.workspace.prefix)&&fr(t,n);return}(await Ze(n).catch(()=>null))?.isFile()&&fr(t,n);}function Po(e){let t=Sn(e);return t%5===0||t===1||t===e.stats.pagesQueued}function Ro(e,t){let r=Sn(e);t.progress(`Render progress: processed ${r}, rendered ${e.stats.pagesRendered}, saved ${e.stats.pagesSaved}, discovered ${e.stats.pagesQueued}.`,{donePages:r,claimedPages:e.donePages.size,pagesRendered:e.stats.pagesRendered,pagesSaved:e.stats.pagesSaved,pagesQueued:e.stats.pagesQueued,phase:"render-pages"});}async function Sc(e){await e.addInitScript(()=>{Object.defineProperty(window,"__WPSUITE_STATIC_EXPORT__",{value:true,writable:false,configurable:true});let t=r=>{if(r==null||String(r)==="")return true;try{let n=new URL(String(r),window.location.href),s=new URL(window.location.href);return n.hash="",s.hash="",n.href===s.href}catch{return false}};try{let r=window.location.assign.bind(window.location),n=window.location.replace.bind(window.location),s=window.location.reload.bind(window.location);Object.defineProperty(window.location,"assign",{configurable:!0,value:o=>{if(t(o)){console.warn("[smartcloud-static-publisher] blocked same-page location.assign",o??"");return}return r(o)}}),Object.defineProperty(window.location,"replace",{configurable:!0,value:o=>{if(t(o)){console.warn("[smartcloud-static-publisher] blocked same-page location.replace",o??"");return}return n(o)}}),Object.defineProperty(window.location,"reload",{configurable:!0,value:()=>{console.warn("[smartcloud-static-publisher] blocked location.reload");}});}catch{}});}async function Pc(e,t,r){let n=await e.newContext({viewport:t.viewport,userAgent:"WPSuiteStaticPublisher/0.8 Playwright SitemapOnly",ignoreHTTPSErrors:t.ignoreHttpsErrors,...r?{javaScriptEnabled:false}:{}});return r||await Sc(n),n}async function Rc(e,t,r,n,s,o,a,c,i,d){for(;t.pageQueue.length>0&&!(e.maxPages>0&&t.donePages.size>=e.maxPages);){let l=t.pageQueue.shift();if(!l)break;t.queuedPages.delete(l);try{let u=ke(l,r,"page","page-queue");if(!u)continue;let f=u.toString();if(l=f,t.queuedPages.delete(l),t.donePages.has(l))continue;t.donePages.add(l),o.enabled&&o.seenPages.add(l);let p=wr(e,l),g=So(e,u.pathname);if(!Ve(u)||G(e,u)||rt(u)){if(G(e,u)){r.info(`Remote worker redirected non-page URL to asset queue: ${l}`,{url:l,source:"remote-worker-guard"}),Q(e,t,l,r,"remote-worker-guard");continue}r.reject("page",l,"guard rejected non-page URL before remote rendering","remote-worker");continue}let w=o.strictTargeted?o.manifest.pages[l]:void 0;if(w?.lastSeenRunId===o.runId&&await Ze(w.outputPath)){o.seenPages.add(l);for(let R of w.discoveredAssets||[])Q(e,t,R,r,l);le(a,e,w.outputPath),Ce(a,w.outputPath),await hr(e,t,l,w.outputPath,d),r.info(`Resumed completed content-sync page ${l}`,{url:l,source:"content-sync-checkpoint"});continue}let m=await oo(e,s,t,o,l,r);if(o.enabled&&n!=="single-url"&&n!=="content-sync"){let R=o.manifest.pages[l];if(m.action==="reuse"&&R){for(let A of R.discoveredAssets)Q(e,t,A,r,l);for(let A of R.discoveredPages)nt(e,t,A,r,l);R.lastSeenRunId=o.runId,R.sitemapLastmod=tt(t.sitemapLastmodByPage[l])??R.sitemapLastmod,m.changeToken?.supported&&(R.changeToken=m.changeToken.token,R.tokenSource=m.changeToken.tokenSource??R.tokenSource),await hr(e,t,l,R.outputPath,d),r.info(`Incremental reuse skipped unchanged page ${l}`,{url:l,mode:"incremental",reason:m.changeToken?.supported===!0?"change-token-match":"sitemap-lastmod-match"});continue}}r.page(`Rendering remotely ${l}`,{url:l,execution:"lambda"});let h=await i.render({sourceOrigin:e.sourceOrigin,url:l,options:{ignoreHttpsErrors:e.ignoreHttpsErrors,javaScriptEnabled:!g,viewport:e.viewport,navigationTimeoutMs:e.navigationTimeoutMs,autoScrollTimeoutMs:bo(e),readiness:e.readiness},downloadHtml:!d}),y=h.page,b=y.finalUrl?ke(y.finalUrl,r,"remote-final-response",l)?.toString():void 0;if(n==="content-sync"&&b&&b!==f){if(o.deleteOnMissingUrls.has(l)){await jt(e,o,a,l,o.deleteOnMissingUrls),r.info(`Removed stale content-sync archive route redirected to ${b}`,{url:l,finalResponseUrl:b,source:"content-sync-tombstone"});continue}throw new Error(`Required content-sync route redirected outside its planned URL: ${l} -> ${b}`)}let P=y.httpStatus;if(p){if(P!==404){r.error(`Generated 404 request path returned unexpected status for ${l}`,{url:l,expectedStatus:404,status:P,requestPath:e.generated404RequestPath,execution:"lambda"});continue}}else if(P!==null&&P>=400){if(n==="content-sync"&&(P===404||P===410)&&o.deleteOnMissingUrls.has(l)){await jt(e,o,a,l,o.deleteOnMissingUrls),r.info(`Removed stale content-sync archive page ${l}`,{url:l,status:P,source:"content-sync-tombstone"});continue}if(n==="content-sync")throw new Error(`Required content-sync route returned HTTP ${P}: ${l}`);r.skip("page",l,P,t.pageDiscoverySources.get(l));continue}t.stats.pagesRendered++;let O=new Set;if(!d){if(h.html===null)throw new Error("Remote render did not return HTML for local output mode.");for(let R of wt(e,f,h.html,r,"remote-page-html"))O.add(R);}for(let R of [...y.discoveredAssets,...y.networkUrls]){let A=oe(e,R,f,r,"remote-render");A&&G(e,A)&&O.add(A.toString());}for(let R of O)Q(e,t,R,r,l);let x=n!=="single-url"&&n!=="content-sync"&&!p?[...new Set([...!d&&h.html!==null?yo(e,l,h.html,r):[],...y.discoveredPages])]:[];for(let R of x)nt(e,t,R,r,l);for(let R of y.cookies){let A=R.sameSite==="Strict"||R.sameSite==="Lax"||R.sameSite==="None"?R.sameSite:"Unspecified",I=!Number.isFinite(R.expires)||R.expires<=0;c.add({name:R.name,domain:R.domain,path:R.path||"/",expires:I?null:R.expires,session:I,secure:R.secure,httpOnly:R.httpOnly,sameSite:A,partitioned:R.partitioned===!0});}let k=je(e,l);if(d){if(!y.html)throw new Error("Remote render completed without a workspace HTML object.");gt(d,{relativePath:gr(e,k),sourceUrl:l,kind:"page",contentType:y.contentType?.trim()||"text/html; charset=utf-8",cacheControl:e.s3.htmlCacheControl,isText:!0,object:y.html}),fr(t,k);}else {if(h.html===null)throw new Error("Remote render did not return HTML for local output mode.");await wn(e,l,h.html,t,r);}le(a,e,k),Ce(a,k),o.trackManifest&&(o.manifest.pages[l]={url:l,outputPath:k,contentType:y.contentType?.trim()||null,changeToken:m.changeToken?.supported?m.changeToken.token:null,tokenSource:m.changeToken?.supported?m.changeToken.tokenSource??null:null,sitemapLastmod:tt(t.sitemapLastmodByPage[l])??null,discoveredPages:x,discoveredAssets:[...O],lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,rewriteComplete:!1},(o.enabled||o.strictTargeted)&&await He(e,o)),r.debug(`Remote render completed ${l}`,{url:l,taskId:h.taskId,attempts:h.attempts,execution:"lambda"});}catch(u){if(r.error(`Failed remote page ${l}`,{url:l,error:String(u),execution:"lambda",...u instanceof we?{status:u.status,attempts:u.attempts}:{}}),u instanceof we){t.pageHttpFailures.set(l,u);continue}if(o.strictTargeted)throw u}finally{t.stats.pagesCompleted++,Po(t)&&Ro(t,r);}}}async function vc(e,t,r,n,s,o,a,c){let i=await chromium.launch({headless:true}),d=hn(i);d.pid!==null&&r.debug(`Launched crawl worker browser PID ${d.pid}`,{browserPid:d.pid});try{for(;t.pageQueue.length>0;){i||(i=await chromium.launch({headless:!0}),d=hn(i),d.pid!==null&&r.debug(`Relaunched crawl worker browser PID ${d.pid}`,{browserPid:d.pid}));let l=i;if(e.maxPages>0&&t.donePages.size>=e.maxPages)break;let u=t.pageQueue.shift();if(!u)break;t.queuedPages.delete(u);let f=null,p=null,g=!1,w=null,m=[],h=new Set;try{let y=ke(u,r,"page","page-queue");if(!y)continue;let b=y.toString();if(u=b,t.queuedPages.delete(u),t.donePages.has(u))continue;t.donePages.add(u),o.enabled&&o.seenPages.add(u);let P=wr(e,u),O=So(e,y.pathname);if(!Ve(y)||G(e,y)||rt(y)){if(G(e,y)){r.info(`Worker redirected non-page URL to asset queue: ${u}`,{url:u,source:"worker-guard"}),Q(e,t,u,r,"worker-guard");continue}r.reject("page",u,"guard rejected non-page URL before rendering","worker");continue}let x=o.strictTargeted?o.manifest.pages[u]:void 0;if(x?.lastSeenRunId===o.runId&&await Ze(x.outputPath)){o.seenPages.add(u);for(let T of x.discoveredAssets||[])Q(e,t,T,r,u);le(a,e,x.outputPath),Ce(a,x.outputPath),await hr(e,t,u,x.outputPath),r.info(`Resumed completed content-sync page ${u}`,{url:u,source:"content-sync-checkpoint"});continue}let k=await oo(e,s,t,o,u,r);if(o.enabled&&n!=="single-url"&&n!=="content-sync"){let T=o.manifest.pages[u];if(k.action==="reuse"&&T){for(let W of T.discoveredAssets)Q(e,t,W,r,u);for(let W of T.discoveredPages)nt(e,t,W,r,u);T.lastSeenRunId=o.runId,T.sitemapLastmod=tt(t.sitemapLastmodByPage[u])??T.sitemapLastmod,k.changeToken?.supported&&(T.changeToken=k.changeToken.token,T.tokenSource=k.changeToken.tokenSource??T.tokenSource),await hr(e,t,u,T.outputPath),r.info(`Incremental reuse skipped unchanged page ${u}`,{url:u,mode:"incremental",reason:k.changeToken?.supported===!0?"change-token-match":"sitemap-lastmod-match"});continue}}f=await se(`create page context ${u}`,Be(e),()=>Pc(l,e,O)),p=await se(`create page ${u}`,Be(e),()=>f.newPage()),m=await f.cookies();let R=!1,A=new Set;await p.route("**/*",async T=>{let W=T.request();try{let U=oe(e,W.url(),e.sourceOrigin,r,"network-request");U&&G(e,U)&&(A.add(U.toString()),Q(e,t,U.toString(),r,u));}catch{}if(W.isNavigationRequest()&&W.frame()===p.mainFrame())try{let U=new URL(W.url()),z=new URL(b);if(U.hash="",z.hash="",U.href===z.href){if(R){r.warn(`Blocked same-page navigation/reload for ${u}`,{url:u,requestUrl:W.url()});try{await T.abort("aborted");}catch(J){r.debug(`Ignored canceled route while blocking reload for ${u}`,{url:u,error:String(J)});}return}R=!0;}}catch{}try{await T.continue();}catch(U){r.debug(`Ignored canceled network route for ${u}`,{url:u,requestUrl:W.url(),error:String(U)});}}),p.on("response",T=>{try{let U=oe(e,T.url(),e.sourceOrigin,r,"network-response");U&&G(e,U)&&(A.add(U.toString()),Q(e,t,U.toString(),r,u));}catch{}let W=T.headerValues("set-cookie").then(U=>{for(let z of U)c.add(vs(z,T.url()));}).catch(()=>{}).then(()=>{});h.add(W),W.finally(()=>h.delete(W));}),r.page(`Rendering ${u}`,{url:u});let I=null,K=null;try{if(I=await p.goto(u,{waitUntil:"domcontentloaded",timeout:e.navigationTimeoutMs}),I&&I.ok())try{K=await se(`read response body ${u}`,Be(e),()=>I.text());}catch{K=null;}}catch(T){let W=t.pageHttpFailures.get(u);if(W){let U=(t.pageHttpAttempts.get(u)??0)+1;throw t.pageHttpAttempts.set(u,U),new we(u,W.status,U,`Retry navigation failed: ${String(T)}`)}r.warn(`Navigation issue for ${u}; saving current DOM if available`,{url:u,error:String(T)});}let D=I?.status();if(er(D)){let T=(t.pageHttpAttempts.get(u)??0)+1;throw t.pageHttpAttempts.set(u,T),new we(u,D,T)}if(I)t.pageHttpFailures.delete(u);else if(t.pageHttpFailures.has(u)){let T=t.pageHttpFailures.get(u),W=(t.pageHttpAttempts.get(u)??0)+1;throw t.pageHttpAttempts.set(u,W),new we(u,T.status,W,"Retry navigation returned no HTTP response.")}if(n==="content-sync"&&I){let T=ke(I.url(),r,"content-sync-final-response",u)?.toString();if(T&&T!==b){if(o.deleteOnMissingUrls.has(u)){await jt(e,o,a,u,o.deleteOnMissingUrls),r.info(`Removed stale content-sync archive route redirected to ${T}`,{url:u,finalResponseUrl:T,source:"content-sync-tombstone"});continue}throw new Error(`Required content-sync route redirected outside its planned URL: ${u} -> ${T}`)}}if(P){let T=I?.status()??null;if(T!==404){r.error(`Generated 404 request path returned unexpected status for ${u}`,{url:u,expectedStatus:404,status:T,requestPath:e.generated404RequestPath});continue}r.info(`Capturing rendered 404 page for ${u}`,{url:u,status:T,outputPath:je(e,u)});}else if(I&&!I.ok()){if(n==="content-sync"&&(I.status()===404||I.status()===410)&&o.deleteOnMissingUrls.has(u)){await jt(e,o,a,u,o.deleteOnMissingUrls),r.info(`Removed stale content-sync archive page ${u}`,{url:u,status:I.status(),source:"content-sync-tombstone"}),await p.close();continue}if(n==="content-sync")throw new Error(`Required content-sync route returned HTTP ${I.status()}: ${u}`);r.skip("page",u,I.status(),t.pageDiscoverySources.get(u)),await p.close();continue}O?(r.info(`Rendering without JS execution for ${u}`,{url:u,mode:"no-js"}),await se(`wait for rendered page ${u}`,Be(e),()=>yc(e,p))):await se(`wait for rendered page ${u}`,Be(e),()=>wc(e,p)),t.stats.pagesRendered++;let S=await se(`extract rendered assets ${u}`,Be(e),()=>bc(e,p,b,r,!O));for(let T of S)Q(e,t,T,r,u);let q=[...new Set([...S,...A])],ue=K??await se(`capture rendered html ${u}`,Be(e),()=>zs(p)),H=n!=="single-url"&&n!=="content-sync"&&!P?yo(e,u,ue,r):[];if(n!=="single-url"&&n!=="content-sync"&&!P)for(let T of H)nt(e,t,T,r,u);await wn(e,u,ue,t,r);let B=je(e,u);if(le(a,e,B),Ce(a,B),o.trackManifest){let T=I?.headers();o.manifest.pages[u]={url:u,outputPath:B,contentType:cn(T),changeToken:k.changeToken?.supported?k.changeToken.token:null,tokenSource:k.changeToken?.supported?k.changeToken.tokenSource??null:null,sitemapLastmod:tt(t.sitemapLastmodByPage[u])??null,discoveredPages:H,discoveredAssets:q,lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,rewriteComplete:!1},(o.enabled||o.strictTargeted)&&await He(e,o);}}catch(y){if(y instanceof we){t.pageHttpFailures.set(u,y),y.attempts<tn?(w=tr(y.attempts),r.warn(`Retrying page after HTTP ${y.status}: ${u}`,{url:u,status:y.status,attempt:y.attempts,maxAttempts:tn,delayMs:w,reason:y.message,execution:"local"})):(t.pageHttpFailures.set(u,y),r.error(`Failed page after HTTP retries ${u}`,{url:u,status:y.status,attempts:y.attempts,error:String(y),execution:"local"}));continue}if(g=y instanceof Mt,o.strictTargeted)throw r.error(`Failed required content-sync page ${u}`,{url:u,error:String(y)}),y;if(g)r.warn(`Skipped partial DOM for timed-out page ${u}`,{url:u,error:String(y),recovery:"recycle-worker-browser"});else try{let b=p?await se(`capture partial html ${u}`,Be(e),()=>zs(p)):"";if(b&&b.trim()){await wn(e,u,b,t,r);let P=je(e,u);if(le(a,e,P),Ce(a,P),o.trackManifest){let O=o.manifest.pages[u]??o.previousManifest.pages[u];o.manifest.pages[u]={url:u,outputPath:P,contentType:O?.contentType??null,changeToken:null,tokenSource:null,sitemapLastmod:tt(t.sitemapLastmodByPage[u])??O?.sitemapLastmod??null,discoveredPages:O?.discoveredPages?[...O.discoveredPages]:[],discoveredAssets:O?.discoveredAssets?[...O.discoveredAssets]:[],lastCrawledAt:new Date().toISOString(),lastSeenRunId:o.runId,rewriteComplete:!1},(o.enabled||o.strictTargeted)&&await He(e,o);}r.warn(`Saved partial DOM for ${u}`,{url:u,error:String(y)});}}catch(b){b instanceof Mt&&(g=!0),r.error(`Could not save partial DOM for ${u}`,{url:u,error:String(b)});}r.error(`Failed page ${u}`,{url:u,error:String(y)});}finally{if(!g&&p&&await se(`drain network routes ${u}`,$t(e),()=>p.unrouteAll({behavior:"wait"})).catch(y=>{g=!0,r.warn(`Could not drain network routes for ${u}`,{url:u,browserPid:d.pid,error:String(y),recovery:"recycle-worker-browser"});}),g&&(i=null,await an(l,r,`page operation timeout for ${u}`),await l.close().catch(()=>{})),h.size>0&&await Promise.allSettled([...h]),!g&&f)try{let y=await f.cookies();c.addAll(Cs(m,y));}catch{}w===null&&(t.stats.pagesCompleted++,Po(t)&&Ro(t,r)),!g&&p&&await se(`close page ${u}`,$t(e),()=>p.close()).catch(y=>{g=!0,r.warn(`Timed out while closing page ${u}`,{url:u,browserPid:d.pid,error:String(y),recovery:"recycle-worker-browser"});}),!g&&f&&await se(`close page context ${u}`,$t(e),()=>f.close()).catch(y=>{g=!0,r.warn(`Timed out while closing page context for ${u}`,{url:u,browserPid:d.pid,error:String(y),recovery:"recycle-worker-browser"});}),g&&i===l&&(i=null,await an(l,r,`page cleanup timeout for ${u}`),await l.close().catch(()=>{})),w!==null&&(await setTimeout$1(w),t.donePages.delete(u),t.queuedPages.add(u),t.pageQueue.push(u));}}}finally{if(i){let l=i;await se("close worker browser",$t(e),()=>l.close()).catch(u=>(r.warn("Timed out while closing crawl worker browser",{browserPid:d.pid,error:String(u)}),an(l,r,"browser.close timeout")));}}}async function Cc(e){try{let t=await F.readFile(e),n=(e.endsWith(".gz")?gunzipSync(t):t).toString("utf8").trim();if(!n)return [];try{let s=JSON.parse(n);if(Array.isArray(s))return s;if(s&&typeof s=="object")return [s]}catch{return n.split(/\r?\n/).map(s=>s.trim()).filter(Boolean).map(s=>{try{let o=JSON.parse(s);return o&&typeof o=="object"?o:null}catch{return null}}).filter(s=>s!==null)}return []}catch{return []}}function Js(e){let t=String(e||"").toLowerCase();return t.includes("timeout")||t.includes("timed out")||t.includes("navigation timeout")}function kc(e){let t=String(e?.job?.command||"").trim(),r=String(e?.job?.crawlMode||"full").trim();return t!=="publish"&&t!=="crawl"?false:r!=="incremental"}function xc(e){let t=[e?.archivedAt,e?.job?.endedAt,e?.job?.startedAt];for(let r of t){let n=Date.parse(String(r||""));if(Number.isFinite(n))return n}return 0}async function vo(e){try{let t=await F.readFile(e,"utf8"),r=JSON.parse(t);return r&&typeof r=="object"&&!Array.isArray(r)?r:null}catch{return null}}function Qs(e){let t=String(e.originalFileName||"").toLowerCase();return t.endsWith("errors.jsonl")?0:t.endsWith("errors.json")?1:2}function Ic(e,t){let r=Array.isArray(t?.artifacts)?t.artifacts.filter(n=>String(n?.role||"").trim()==="errors"&&String(n?.storedFileName||"").trim()!=="").sort((n,s)=>Qs(n)-Qs(s)).map(n=>C.join(e,String(n.storedFileName))):[];return [...new Set([...r,C.join(e,"errors.jsonl"),C.join(e,"errors.json"),C.join(e,"errors.jsonl.gz"),C.join(e,"errors.json.gz")])]}async function Gs(e){let t=await vo(C.join(e,"job.json"));for(let r of Ic(e,t)){let n=await Cc(r);if(n.length>0)return n}return []}async function Tc(e){let t=C.join(e.logDir,"archive"),r;try{r=await F.readdir(t);}catch{return ""}let n="",s=0;for(let o of r){let a=C.join(t,o);if(!(await F.stat(a).catch(()=>null))?.isDirectory())continue;let i=await vo(C.join(a,"job.json"));if(!kc(i))continue;let d=xc(i);d>=s&&(s=d,n=a);}return n}async function Ac(e){let t=await Tc(e),r=t!==""?await Gs(t):await Gs(e.logDir),n=new Set;for(let s of r)if(Js(s.error)||Js(s.message)){let o=s.url;typeof o=="string"&&o&&n.add(o);}return [...n]}async function Ec(e){let t=[];for(let r of e)if(r.startsWith("@")){let n=r.slice(1),s=await F.readFile(n,"utf8");t.push(...s.split(/\r?\n/).map(o=>o.trim()).filter(o=>o&&!o.startsWith("#")));}else t.push(r);return t}async function $c(e){if(!e)throw new Error("Content-sync crawl requires an immutable impact plan.");let t=JSON.parse(await F.readFile(e,"utf8"));return vt(t),t}function Oc(e,t){let r;try{r=new URL(e);}catch{return false}return t.archiveFamilies.some(n=>{let s=new URL(n.url);if(r.origin!==s.origin)return false;if(r.toString()===s.toString())return true;if(r.searchParams.has("paged")&&r.pathname===s.pathname)return /^\d+$/.test(r.searchParams.get("paged")||"");let o=s.pathname.replace(/\/+$/,""),a=r.pathname.slice(o.length).replace(/^\/+/,""),c=String(n.paginationBase||"page").replace(/^\/+|\/+$/g,"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return r.pathname.startsWith(`${o}/`)&&new RegExp(`^${c}/\\d+/?$`).test(a)})}function Et(e,t,r){let n=r==="page"?je(e,t):Dt(e,t).originalFilePath;return me(e.outputDir,n)}async function jt(e,t,r,n,s){let o=t.manifest.pages[n];if(!o)return;let a=me(e.outputDir,o.outputPath);if(!a)throw new Error(`Manifest-owned page path escaped output root: ${n}`);let c=C.resolve(o.outputPath);Object.entries(t.manifest.pages).some(([d,l])=>d!==n&&!s.has(d)&&C.resolve(l.outputPath)===c)||(await F.rm(o.outputPath,{force:true}),r.deletedFiles.add(a),r.revalidateFiles.delete(a)),delete t.manifest.pages[n];}async function Mc(e,t,r,n,s){let o=t.manifest.assets[n];if(!o)return;let a=me(e.outputDir,o.outputPath);if(!a)throw new Error(`Manifest-owned resource path escaped output root: ${n}`);let c=C.resolve(o.outputPath);Object.entries(t.manifest.assets).some(([d,l])=>d!==n&&!s.has(d)&&C.resolve(l.outputPath)===c)||(await F.rm(o.outputPath,{force:true}),r.deletedFiles.add(a)),delete t.manifest.assets[n];}function jc(e,t){let r=new Set,n=[...t];for(;n.length>0;){let s=n.shift();if(r.has(s))continue;r.add(s);let o=e.assets[s];for(let a of o?.discoveredAssets??[])try{yt(new URL(a))&&n.push(a);}catch{}}return r}async function Fc(e,t,r,n,s){let o=jc(r.previousManifest,s);for(let a of o){if(t.successfulSitemaps.has(a))continue;let c=r.previousManifest.assets[a];if(!c)continue;let i=me(e.outputDir,c.outputPath);if(!i)throw new Error(`Manifest-owned sitemap path escaped output root: ${a}`);await F.rm(c.outputPath,{force:true}),n.deletedFiles.add(i),delete r.manifest.assets[a];}await He(e,r);}async function Dc(e){try{let t=await F.readFile(C.join(e.outputDir,"asset-map.json"),"utf8");return JSON.parse(t)}catch{return {}}}async function Uc(e){let t=["crawl.log.jsonl","current-crawl-event.json","rejected.jsonl","ignored.jsonl","skipped-http.jsonl","errors.jsonl","timings.jsonl","rejected.json","ignored.json","skipped-http.json","errors.json","timings.json"];await F.mkdir(e,{recursive:true}),await Promise.all(t.map(async r=>{try{await F.unlink(C.join(e,r));}catch(n){if(n.code!=="ENOENT")throw n}}));}function Zs(e,t,r,n,s){let o=oe(e,r,e.sourceOrigin,n,"manual-url");o&&(yt(o)?mr(e,t,o.toString(),n,s):G(e,o)?Q(e,t,o.toString(),n,s):Ve(o)?nt(e,t,o.toString(),n,s):n.reject("manual-url",o.toString(),"not page/sitemap/asset-like",s));}async function Co(e=process.argv.slice(2)){let t=[],r=await Ie(void 0,{onRemotePublisherConfigDiagnostic:v=>{t.push(v);}}),n=kt(r.sitemapPaths),s=t.at(-1)??null,o=ba(e),a=o.mode==="content-sync"?await $c(o.contentSyncPlanPath):null;if(o.resumeRewrite&&o.mode!=="full")throw new Error("--resume-rewrite is only supported for full crawl/publish jobs.");let c=[];o.mode==="retry-timeouts"&&(c=await Ac(r)),o.mode==="single-url"&&(c=await Ec(o.urls)),a&&(c=[...a.directRenderUrls,...a.archiveFamilyUrls,...a.resourceRenderUrls]);let i=o.crawlMode==="incremental"&&o.mode==="full",d=i&&typeof r.subscriptionType=="string"&&r.subscriptionType.trim()!=="";if(a&&r.subscriptionType!=="PROFESSIONAL"&&r.subscriptionType!=="AGENCY")throw new Error("Content-sync requires an active Professional or Agency subscription.");let l=(o.mode==="full"||o.mode==="single-url"||o.mode==="content-sync")&&!o.resumeRewrite,u=o.mode!=="full"||o.resumeRewrite||d,f=u?await Dc(r):{},p=d||o.mode==="single-url"||o.mode==="content-sync"?await Ia(r):ro(),g=new Set(c),w=new Set;if(a){for(let v of a.archiveFamilies)if(v.foundPosts===0)for(let j of v.pageUrls)w.add(j);for(let v of Object.keys(p.pages))Oc(v,a)&&!g.has(v)&&(c.push(v),w.add(v));}let m={enabled:d,trackManifest:l,manifest:dn(p),previousManifest:dn(p),runId:a?.jobId??`${Date.now()}`,seenPages:new Set,changeTokenCache:new Map,pageChangeTokenPrimePromise:null,manifestSaveChain:Promise.resolve(),manifestPendingChanges:0,lastManifestSavedAt:Date.now(),strictTargeted:!!a,requiredUrls:g,deleteOnMissingUrls:w};await Uc(r.logDir);let h=new Qt(r.logDir,r.logLevel),y=o.remoteRender??r.remoteWorkers?.render?.enabled===true,b=ir({explicitPath:o.remoteWorkerConfigPath,runtimeDir:Ft()}),P=null,O=null,x=null,k=null,R=Math.max(1,r.concurrency),A=1,I=r.remoteWorkers?.rewrite?.enabled===true,K=r.remoteWorkers?.deploy?.enabled===true,D=y&&I&&K&&!o.resumeRewrite;if(!D&&o.mode==="full"&&!o.resumeRewrite&&await F.rm(ar(r),{force:true}),y&&!o.resumeRewrite||I){if(!b)throw new Error("Remote Lambda workers are enabled, but the runtime directory is unknown. Run through queue-runner with --runtime-dir, set STATIC_PUBLISHER_RUNTIME_DIR, or use --remote-worker-config for a diagnostic run.");let v=await Xt(b),j=false;if(x=new mt(v,{},{onProgress:M=>{h.progress(`Lambda ${M.operation} batch: ${M.completedItems+M.failedItems}/${M.totalItems}`,{remoteWorkerOperation:M.operation,remoteWorkerTaskId:M.taskId,remoteWorkerStatus:M.status,remoteWorkerCompletedItems:M.completedItems,remoteWorkerFailedItems:M.failedItems,remoteWorkerTotalItems:M.totalItems,remoteWorkerUpdatedAt:M.updatedAt});},onProgressError:M=>{j||(j=true,h.warn("Lambda progress status could not be read; task execution continues.",{error:M.message}));}}),D){if(!v.functions.asset)throw new Error("Full Lambda delegation requires an asset worker. Redeploy the Lambda worker stack and reinstall remote-workers.json.");let M=u?await cr(r):null;k=Us(`crawl-${Ee(m.runId,40)}`,v,M),O=new nr({client:x,jobId:k.jobId,maxAttempts:2}),h.info("S3-native Lambda data plane is enabled.",{execution:"lambda",assetWorker:v.functions.asset,workspaceBucket:v.workspace.bucket,workspacePrefix:v.workspace.prefix});}}if(y&&!o.resumeRewrite){if(!x)throw new Error("Remote render worker client was not initialized.");R=Math.max(1,Math.min(100,D?r.concurrency:r.remoteWorkers?.render?.concurrency??r.concurrency)),A=Math.max(1,Math.min(20,r.remoteWorkers?.render?.batchSize??5)),P=new rr({client:x,jobId:`crawl-${Ee(m.runId,40)}`,maxAttempts:r.remoteWorkers?.render?.maxAttempts??2,batchSize:A,maxConcurrentBatches:R,onRetry:v=>{h.warn(`Retrying remote render for ${v.url}`,{url:v.url,attempt:v.attempt,maxAttempts:v.maxAttempts,reason:v.reason,status:v.status,delayMs:v.delayMs,execution:"lambda"});}}),h.info("Lambda page rendering is enabled.",{remoteWorkerConfigPath:C.resolve(b),concurrency:R,maxAttempts:r.remoteWorkers?.render?.maxAttempts??2,batchSize:A,execution:"lambda"});}if(s){let v={status:s.status,virtualAssetBaseUrl:s.virtualAssetBaseUrl,subscriptionType:s.subscriptionType??null,error:s.error,requests:s.requests,source:"remote-publisher-config"};s.status==="loaded"&&s.subscriptionType?h.info("Loaded remote WP Suite publisher configuration.",v):h.warn("Remote WP Suite publisher configuration is unavailable or has no active subscription type.",v);}if(i&&!d){let v="Incremental crawl requires an active remote publisher subscription; refusing to fall back to a destructive full crawl.";throw h.error(v,{requestedMode:o.crawlMode,subscriptionType:r.subscriptionType??null,source:"incremental-subscription-guard"}),await h.flush(),new Error(v)}let S={pageQueue:[],queuedPages:new Set,donePages:new Set,savedPageOutputs:new Set,pageHttpAttempts:new Map,pageHttpFailures:new Map,pageDiscoverySources:new Map,assetQueue:[],queuedAssets:new Set,doneAssets:new Set,sitemapQueue:[],queuedSitemaps:new Set,doneSitemaps:new Set,successfulSitemaps:new Set,resolvedSitemapRoots:new Set,sitemapIndexUrls:new Set,sitemapLeafUrls:new Set,sitemapLastmodByPage:{},assetMap:{...f},assetVariantDigestsByOriginalPath:new Map,stats:{pagesQueued:0,pagesRendered:0,pagesCompleted:0,assetsQueued:0,sitemapsQueued:0,assetsSaved:0,pagesSaved:0}},q=xa(),ue=new Zt,H=Sa();if(H&&!o.resumeRewrite&&await Yt(H,ue.artifact()),await Qe(r),await Vr(r,{startedAt:new Date().toISOString(),outputDir:C.resolve(r.outputDir)}),!o.resumeRewrite&&r.pageCache?.purgeBeforeCrawl===true){h.mark("purge-page-cache");let v=await request.newContext({ignoreHTTPSErrors:r.ignoreHttpsErrors});try{let j=await Fs(r,v);h.info("WordPress page cache was purged before crawl discovery.",{provider:j.provider,scope:j.scope,purgedAt:j.purgedAt??null}),h.endMark("purge-page-cache",{provider:j.provider,scope:j.scope});}catch(j){throw h.error("WordPress page-cache purge failed; crawl stopped before changing export output.",{error:j instanceof Error?j.message:String(j)}),await h.flush(),j}finally{await v.dispose();}}if(u||await F.rm(r.outputDir,{recursive:true,force:true}),await F.mkdir(r.outputDir,{recursive:true}),u||await Vr(r,{startedAt:new Date().toISOString(),outputDir:C.resolve(r.outputDir)}),a){let v=new Set([...a.deleteUrls,...m.deleteOnMissingUrls]);for(let M of a.deleteUrls)await jt(r,m,q,M,v);let j=new Set(a.resourceDeleteUrls);for(let M of a.resourceDeleteUrls)await Mc(r,m,q,M,j);}if(o.resumeRewrite)h.info("Resuming final rewrite from existing output.",{phase:"rewrite-text",mode:o.mode,crawlMode:o.crawlMode});else {let v=await request.newContext({ignoreHTTPSErrors:r.ignoreHttpsErrors});try{if(h.mark("discovery"),o.mode==="full"?(n.forEach(M=>mr(r,S,M,h)),await Vs(r,v,S,h,q,m),r.seedPaths.forEach(M=>Zs(r,S,M,h,"seed-path")),r.generated404RequestPath&&nt(r,S,r.generated404RequestPath,h,"generated-404-request-path")):(c.forEach(M=>Zs(r,S,M,h,"cli")),a?.sitemapUrls.forEach(M=>mr(r,S,M,h,"content-sync-impact")),await Vs(r,v,S,h,q,m,o.mode==="content-sync",a?.sitemapUrls??[]),a&&await Fc(r,S,m,q,a.sitemapUrls)),h.endMark("discovery",{pages:S.pageQueue.length,assets:S.assetQueue.length,sitemaps:S.sitemapQueue.length}),h.summary(`Queued ${S.pageQueue.length} pages, ${S.assetQueue.length} assets, ${S.sitemapQueue.length} sitemaps.`,{mode:o.mode,crawlMode:o.crawlMode,queuedPages:S.pageQueue.length,queuedAssets:S.assetQueue.length,queuedSitemaps:S.sitemapQueue.length}),o.mode==="retry-timeouts"&&S.pageQueue.length===0&&S.assetQueue.length===0&&S.sitemapQueue.length===0){h.summary("No timed-out URLs were queued. Skipping retry crawl.",{mode:o.mode,crawlMode:o.crawlMode,queuedPages:0,queuedAssets:0,queuedSitemaps:0}),await h.flush(),H&&await Yt(H,ue.artifact());return}h.mark("render-pages");let j=Array.from({length:P?R*A:R},()=>P?Rc(r,S,h,o.mode,v,m,q,ue,P,k??void 0):vc(r,S,h,o.mode,v,m,q,ue));if(await Promise.all(j),S.pageHttpFailures.size>0&&await h.flush(),As(S.pageHttpFailures),H&&await Yt(H,ue.artifact()),h.endMark("render-pages",{pages:S.stats.pagesCompleted}),h.mark("download-assets"),h.progress("Asset download phase started.",{phase:"download-assets",doneAssets:S.doneAssets.size,assetsQueued:S.stats.assetsQueued,assetQueue:S.assetQueue.length}),k&&O?await mc(r,v,S,h,m,q,k,O,r.concurrency):(await yn(r,v,m,[...S.assetQueue],h),await dc(r,v,S,h,m,q)),h.endMark("download-assets",{assets:S.doneAssets.size}),m.enabled&&r.maxPages===0&&(await ja(r,S,m,h,q),o.mode==="full"&&await Fa(r,m,h,q)),o.mode==="full"){let M=await lc(r,S,h);for(let X of M)if(le(q,r,X),k&&x){let te=gr(r,X),$=await F.readFile(X),_=$e(X),E=String(Es.lookup(te)||"")||(_?"text/plain; charset=utf-8":"application/octet-stream"),re=await x.writeWorkspaceObject({key:`${k.workspace.prefix}jobs/${k.jobId}/copied/${Ee(te,40)}-${C.basename(te)}`,body:$,contentType:E});gt(k,{relativePath:te,sourceUrl:null,kind:"generated",contentType:re.contentType,cacheControl:null,isText:_,object:re}),_&&Ce(q,X);}}}finally{await se("dispose crawl request context",$t(r),()=>v.dispose()).catch(j=>{h.warn("Timed out while disposing crawl request context",{error:String(j)});});}}if(m.trackManifest&&await He(r,m,true),k)for(let v of q.deletedFiles)Ls(k,v);let B=JSON.stringify(S.assetMap,null,2);if(await F.writeFile(C.join(r.outputDir,"asset-map.json"),B,"utf8"),k&&x){let v=await x.writeWorkspaceObject({key:`${k.workspace.prefix}jobs/${k.jobId}/generated/asset-map.json`,body:B,contentType:"application/json; charset=utf-8"});gt(k,{relativePath:"asset-map.json",sourceUrl:null,kind:"generated",contentType:"application/json; charset=utf-8",cacheControl:r.s3.assetCacheControl,isText:true,object:v});}JSON.stringify(f,null,2)!==JSON.stringify(S.assetMap,null,2)&&le(q,r,C.join(r.outputDir,"asset-map.json")),k&&x&&await gc(r,q,k,x);let T=o.mode==="single-url"||o.mode==="content-sync"?Ba(r,S):m.enabled&&!o.resumeRewrite?Da(r,m,q,f,S.assetMap):void 0;h.mark("rewrite-text");let W=o.mode==="single-url"||o.mode==="content-sync"?`Rewriting text files touched by URL crawl: 0/${T?.length??0}`:"Rewriting text files...";h.progress(W,{phase:"rewrite-text",index:0,totalFiles:T?.length,changedTextFiles:0}),await on(W);let U=Date.now(),z={files:T,previousAssetMap:f,onStart:({totalFiles:v,workerCount:j})=>{h.info(`Rewrite phase scanning ${v} text files.`,{phase:"rewrite-text",totalFiles:v,workerCount:j});},onProgress:async({index:v,totalFiles:j,changedTextFiles:M,file:X,changed:te})=>{te&&le(q,r,C.join(r.outputDir,X)),h.checkpoint(`Rewriting text file ${v}/${j}`,{phase:"rewrite-text",index:v,totalFiles:j,changedTextFiles:M,file:X}),h.debug(`${te?"Rewrote":"Checked unchanged"} text file ${v}/${j}: ${X}`,{phase:"rewrite-text",index:v,totalFiles:j,changedTextFiles:M,file:X,changed:te});let $=Date.now();if(!(v===1||v===j||v%50===0||$-U>=5e3))return;U=$;let E=`Rewriting text files: ${v}/${j}`;h.progress(E,{phase:"rewrite-text",index:v,totalFiles:j,changedTextFiles:M,file:X}),await on(E);}},J;if(k&&x){let v=T?.map(M=>gr(r,C.isAbsolute(M)?M:C.join(r.outputDir,M))),j=Object.values(k.objects).filter(M=>M.isText&&(!v||v.includes(M.relativePath))).length;await z.onStart?.({totalFiles:j,workerCount:Math.min(r.concurrency,j)}),J=await or(r,k,S.assetMap,{client:x,jobId:k.jobId,concurrency:r.concurrency,batchSize:25,maxAttempts:2,...v?{relativePaths:v}:{},onProgress:z.onProgress}),await qs(r,k);}else I&&x?J=await sr(r,S.assetMap,{client:x,jobId:`crawl-${Ee(m.runId,40)}`,concurrency:r.remoteWorkers?.rewrite?.concurrency??r.rewriteConcurrency,batchSize:r.remoteWorkers?.rewrite?.batchSize??25,maxAttempts:r.remoteWorkers?.rewrite?.maxAttempts??2,onStageProgress:async({index:v,totalFiles:j,file:M})=>{let X=Date.now();if(v!==1&&v!==j&&v%25!==0&&X-U<5e3)return;U=X;let te=`Staging text files for Lambda rewrite: ${v}/${j}`;h.progress(te,{phase:"rewrite-stage",index:v,totalFiles:j,file:M,execution:"lambda"}),await on(te);},options:z}):J=await Kt(r,S.assetMap,z);m.trackManifest&&(Ua(m,T),await He(r,m,true)),h.endMark("rewrite-text",{changedTextFiles:J});let de=a?[...q.deletedFiles].sort():m.enabled&&!o.resumeRewrite?await qa(r,S,m,q,h,k):[],Se=[...new Set((T||[]).map(v=>me(r.outputDir,C.isAbsolute(v)?v:C.join(r.outputDir,v))).filter(v=>v!==null))].sort();if(a){let v=[...q.changedFiles].sort(),j=new Set(v),M=new Set(a.directRenderUrls.map(L=>Et(r,L,"page")).filter(L=>!!L&&j.has(L))),X=new Set(a.archiveFamilyUrls.map(L=>Et(r,L,"page")).filter(L=>!!L&&j.has(L))),te=new Set(a.resourceRenderUrls.map(L=>Et(r,L,"asset")).filter(L=>!!L&&j.has(L))),$=new Set([...S.sitemapLeafUrls].map(L=>Et(r,L,"asset")).filter(L=>!!L&&j.has(L))),_=new Set([...S.sitemapIndexUrls].map(L=>Et(r,L,"asset")).filter(L=>!!L&&j.has(L))),E=new Set([...M,...X,...te,...$,..._]),re=v.filter(L=>!E.has(L)),he=[...new Set([...a.directRenderUrls,...a.archiveFamilyUrls,...S.resolvedSitemapRoots,...S.sitemapLeafUrls,...S.sitemapIndexUrls,...a.deleteUrls,...a.resourceRenderUrls,...a.resourceDeleteUrls].map(L=>{let Pe=new URL(L);return `${Pe.pathname}${Pe.search}`}))].sort();await Hr(r,{schemaVersion:2,generatedAt:new Date().toISOString(),outputDir:C.resolve(r.outputDir),runMode:"content-sync",crawlMode:"incremental",fullSyncRequired:false,changedFiles:v,deletedFiles:de,rewriteTargets:Se,revalidateFiles:[...q.revalidateFiles].sort(),consumerId:a.consumerId,fromSequence:a.fromSequence,toSequence:a.toSequence,impactHash:a.impactHash,resolvedSitemapUrls:[...S.resolvedSitemapRoots],uploadGroups:{assets:re,content:[...M].sort(),listings:[...X].sort(),resources:[...te].sort(),sitemapLeaves:[...$].sort(),sitemapIndexes:[..._].reverse()},invalidationPaths:he});}else await Hr(r,{schemaVersion:1,generatedAt:new Date().toISOString(),outputDir:C.resolve(r.outputDir),runMode:o.mode,crawlMode:o.crawlMode,fullSyncRequired:!(m.enabled&&!o.resumeRewrite),changedFiles:m.enabled&&!o.resumeRewrite?[...q.changedFiles].sort():[],deletedFiles:m.enabled&&!o.resumeRewrite?de:[],rewriteTargets:m.enabled&&!o.resumeRewrite?Se:[],revalidateFiles:[...q.revalidateFiles].sort()});await ns(r),h.summary(o.resumeRewrite?`Done. Resumed final rewrite over existing output and changed ${J} text files.`:`Done. Rendered ${S.stats.pagesRendered} pages, processed ${S.doneSitemaps.size} sitemaps and ${S.doneAssets.size} assets.`,{mode:o.mode,crawlMode:o.crawlMode,resumeRewrite:o.resumeRewrite,...S.stats,pagesRendered:S.stats.pagesRendered,donePages:S.stats.pagesCompleted,claimedPages:S.donePages.size,doneSitemaps:S.doneSitemaps.size,doneAssets:S.doneAssets.size,changedTextFiles:J}),await h.flush();}function Lc(e){let t=e/6e4;if(Number.isInteger(t)&&t>=1)return `${t} minute${t===1?"":"s"}`;let r=Math.ceil(e/1e3);return `${r} second${r===1?"":"s"}`}async function ye(e,t,r){let n=new AbortController,s=globalThis.setTimeout(()=>{n.abort(new Error(`${e} timed out after ${Lc(t)}.`));},t);try{return await r({abortController:n,httpOptions:{abortSignal:n.signal,requestTimeout:t}})}finally{globalThis.clearTimeout(s);}}function qc(e){return typeof e.subscriptionType=="string"&&e.subscriptionType.trim()!==""}function yr(e){let t="";for(let n=0;n<e.length;n++){let s=e[n];if(s==="--profile"){let o=(e[n+1]||"").trim();if(!o)throw new Error("Missing value for --profile.");t=o,n+=1;}else if(s.startsWith("--profile=")){let o=s.slice(10).trim();if(!o)throw new Error("Missing value for --profile.");t=o;}}let r=String(process.env.PUBLISHER_DEPLOY_PROFILE||process.env.PUBLISHER_DEPLOYMENT_PROFILE||"").trim();return t||r||null}function Wc(e,t){return {...e,...t??{}}}function Nc(e,t){return {...e,...t??{},invalidationPaths:[...(t?.invalidationPaths??e.invalidationPaths)||[]]}}function bt(e,t){let r=String(t??e.deploymentTargetOverride??"").trim();if(!qc(e)){if(r)throw new Error(`Deployment target "${r}" requires an active WPSuite subscription and remote publisher config.`);return {name:null,profile:null,config:e}}let n=String(r||e.defaultDeploymentProfile||"").trim();if(!n)return {name:null,profile:null,config:e};let s=e.deploymentProfiles?.[n];if(!s)throw new Error(`Unknown deployment profile "${n}". Check the linked WPSuite publisher configuration.`);return {name:n,profile:s,config:{...e,targetOrigin:s.targetOrigin??e.targetOrigin,s3:Wc(e.s3,s.s3),cloudFront:Nc(e.cloudFront,s.cloudFront)}}}function Pn(e){return String(e??"").split(";").map(t=>t.trim().toLowerCase()).filter(Boolean).join(";")}var Ao="wpsuite-sha256",Eo="wpsuite-normalized-sha256",Cn="public, max-age=0, must-revalidate",Qc=/(?:^|[-_:.])(id|uid|nonce|token|hash|instance)(?:$|[-_:.])/i,kn=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,Gc=["SIGINT","SIGTERM"],Pr=new Set,br=new Map,ko=null;function Zc(e){Pr.add(e);let t=false;return ()=>{t||(t=true,Pr.delete(e));}}async function Yc(){let e=[...Pr];e.length!==0&&await Promise.allSettled(e.map(async t=>{Pr.delete(t),await F.rm(t,{recursive:true,force:true});}));}function Xc(){if(!(br.size>0))for(let e of Gc){let t=()=>{ko||(ko=Yc().finally(()=>{for(let[r,n]of br)process.off(r,n);br.clear(),process.exit(1);}));};br.set(e,t),process.on(e,t);}}Xc();function el(e,t){let r=String(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH||"").trim();if(r)return C.resolve(r);let n=t.trim();return n?C.join(C.resolve(n),"crawl-manifest.json"):C.join(C.resolve(e),".crawl-manifest.json")}function Ye(e){return C.normalize(e).split(C.sep).join("/")}function xo(e,t){let r=C.relative(C.resolve(e),C.resolve(t));return !r||r.startsWith("..")||C.isAbsolute(r)?null:Ye(r)}async function tl(e,t,r){let n=el(e.outputDir,t),s;try{s=await F.readFile(n,"utf8");}catch(l){return l.code==="ENOENT"?(r.warn("Deploy rewrite guard disabled because the crawl manifest is missing.",{manifestPath:n,source:"deploy-guard"}),null):(r.warn("Deploy rewrite guard disabled because the crawl manifest could not be read.",{manifestPath:n,error:l instanceof Error?l.message:String(l),source:"deploy-guard"}),null)}let o;try{o=JSON.parse(s);}catch(l){return r.warn("Deploy rewrite guard disabled because the crawl manifest is invalid JSON.",{manifestPath:n,error:l instanceof Error?l.message:String(l),source:"deploy-guard"}),null}let a=new Map,c=new Map,i=0,d=0;for(let[l,u]of Object.entries(o.pages||{})){let f=String(u?.outputPath||"").trim(),p=f?xo(e.outputDir,f):null;if(p){let g=typeof u?.contentType=="string"&&u.contentType?u.contentType:null;g&&c.set(p,g);}!f||u?.rewriteComplete===true||p&&(i++,a.has(p)||a.set(p,{kind:"page",sourceUrl:l,outputPath:C.resolve(f),relativePath:p}));}for(let[l,u]of Object.entries(o.assets||{})){let f=String(u?.outputPath||"").trim(),p=u?.isText===true,g=f?xo(e.outputDir,f):null;if(g){let w=typeof u?.contentType=="string"&&u.contentType?u.contentType:null;w&&c.set(g,w);}!f||!p||u?.rewriteComplete===true||g&&(d++,a.has(g)||a.set(g,{kind:"asset",sourceUrl:l,outputPath:C.resolve(f),relativePath:g}));}return {manifestPath:n,byRelativePath:a,contentTypeByRelativePath:c,pendingPages:i,pendingTextAssets:d}}function rl(e){return e&&(kn.test(e)?"__uuid__":/^[0-9a-f]{6,}$/i.test(e)?"__hex__":/^[0-9]{8,}$/.test(e)?"__num__":/^(?=.*[a-z])(?=.*\d)[a-z0-9]{8,}$/i.test(e)?"__alnum__":e)}function Rn(e){return e.split(/([_:.\-/=?&#]+)/g).map((t,r)=>r%2===1?t:rl(t)).join("")}function nl(e){return e.split(/([_:.\-/=?&#]+)/g).map((t,r)=>r%2===1?t:kn.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)?"__hex__":/^[0-9]{6,}$/.test(t)?"__num__":/^[a-z0-9_-]{6,}$/i.test(t)?"__id__":t).join("")}function Rr(e,t){return Array.isArray(e)?e.map(r=>Rr(r,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([r,n])=>[r,Rr(n,r)])):typeof e!="string"?e:t&&Qc.test(t)?nl(e):kn.test(e)?"__uuid__":/^[0-9a-f]{6,}$/i.test(e)||/^[0-9]{8,}$/.test(e)?Rn(e):e}function sl(e){return e.replace(/((?:https?:\/\/[^"'\s>]+|\/)(?:wp-content|wp-includes)\/[^"'\s>?]+)\?ver=[A-Za-z0-9._-]+(?=$|[#"'])/gi,"$1")}function ol(e,t){let r=t.trim();if((r.startsWith("{")||r.startsWith("[")||r.startsWith('"'))&&e.startsWith("data-"))try{let s=JSON.parse(r);return JSON.stringify(Rr(s))}catch{}if(e.startsWith("data-")&&/^[A-Za-z0-9+/=]+$/.test(r))try{let s=Buffer.from(r,"base64").toString("utf8"),o=JSON.parse(s),a=JSON.stringify(Rr(o));return Buffer.from(a,"utf8").toString("base64")}catch{}return t}function il(e,t){let r=e.toLowerCase();return r==="class"?t.split(/(\s+)/).map((n,s)=>s%2===1?n:Rn(n)).join(""):r==="id"||r==="for"||r==="aria-controls"||r==="aria-labelledby"||r==="aria-describedby"||r==="aria-owns"||r==="aria-activedescendant"||r==="name"?Rn(t):r==="href"||r==="src"?sl(t):ol(r,t)}function al(e){return e.replace(/<([a-z][^\s/>]*)([^<>]*?)>/gi,(t,r,n)=>{if(r.startsWith("/"))return t;let s=n.replace(/\s([:@a-zA-Z_][-:.a-zA-Z0-9_]*?)=(['"])([\s\S]*?)\2/g,(o,a,c,i)=>{let d=il(a,i);return ` ${a}=${c}${d}${c}`});return `<${r}${s}>`})}function St(e){let t=C.extname(e).toLowerCase();return [".html",".htm",".xml",".xsl",".txt"].includes(t)||["robots.txt","sitemap.xml"].includes(C.basename(e))}function Sr(e,t){return [e.replace(/^\/+|\/+$/g,""),t.replace(/^\/+/,"")].filter(Boolean).join("/")}async function cl(e,t,r,n){let s=new Map,o,a=0;do{a++;let c=await ye(`S3 list objects page ${a} for s3://${t}/${r||""}`,3e5,({httpOptions:i})=>e.send(new ListObjectsV2Command({Bucket:t,Prefix:r||void 0,ContinuationToken:o}),i));for(let i of c.Contents||[]){if(!i.Key)continue;let d=(i.ETag||"").replace(/^"|"$/g,"").toLowerCase(),l=Number(i.Size??0);s.set(i.Key,{etag:d,size:l,cacheControl:void 0,contentType:void 0});}o=c.NextContinuationToken,n.debug(`Listed S3 keys page ${a}: ${s.size} keys so far`);}while(o);return s}async function ll(e,t,r,n){if(n.has(r))return n.get(r)??null;try{let s=await ye(`S3 head object ${r}`,3e5,({httpOptions:a})=>e.send(new HeadObjectCommand({Bucket:t,Key:r}),a)),o={etag:(s.ETag||"").replace(/^"|"$/g,"").toLowerCase(),size:Number(s.ContentLength??0),cacheControl:s.CacheControl?.trim()||null,contentType:s.ContentType?.trim()||null};return n.set(r,o),o}catch{return n.set(r,null),null}}async function ul(e,t,r,n){if(n.cacheControl!==void 0&&n.contentType!==void 0)return {cacheControl:n.cacheControl,contentType:n.contentType};try{let s=await ye(`S3 head cache metadata ${r}`,3e5,({httpOptions:o})=>e.send(new HeadObjectCommand({Bucket:t,Key:r}),o));n.cacheControl=s.CacheControl?.trim()||null,n.contentType=s.ContentType?.trim()||null;}catch{n.cacheControl=null,n.contentType=null;}return {cacheControl:n.cacheControl,contentType:n.contentType}}function Io(e){return String(e||"").split(",").map(t=>t.trim().toLowerCase()).filter(Boolean).sort().join(",")}async function dl(e,t,r,n){let s=[...new Set(Array.from(r).filter(Boolean))];if(s.length===0)return n.info("No explicitly tombstoned S3 objects to delete."),[];n.info(`Deleting ${s.length} explicitly tombstoned S3 object(s)\u2026`);for(let o=0;o<s.length;o+=1e3){let a=s.slice(o,o+1e3);if(a.length===0)continue;let c=await ye(`S3 delete objects batch ${Math.floor(o/1e3)+1}`,3e5,({httpOptions:i})=>e.send(new DeleteObjectsCommand({Bucket:t,Delete:{Objects:a.map(d=>({Key:d}))}}),i));if(c.Errors&&c.Errors.length>0){let i=c.Errors.map(d=>`${d.Key||"(unknown)"}: ${d.Code||"DeleteFailed"}`);throw new Error(`S3 reported ${i.length} object deletion error(s): ${i.join(", ")}`)}n.info(`Deleted batch of ${a.length} object(s).`);for(let i of a)n.debug(` deleted: ${i}`);}return s}function pl(e){return createHash("md5").update(e).digest("hex")}function Xe(e){return createHash("sha256").update(e).digest("hex")}function vr(e){return createHash("sha256").update(al(e.toString("utf8"))).digest("hex")}async function ml(e,t,r,n){if(n.has(r))return n.get(r)??null;try{let a=((await ye(`S3 head object metadata ${r}`,3e5,({httpOptions:c})=>e.send(new HeadObjectCommand({Bucket:t,Key:r}),c))).Metadata?.[Ao]||"").trim().toLowerCase()||null;return n.set(r,a),a}catch{return n.set(r,null),null}}async function gl(e,t,r,n,s){if(n.has(r))return n.get(r)??null;try{let a=((await ye(`S3 head object normalized metadata ${r}`,3e5,({httpOptions:c})=>e.send(new HeadObjectCommand({Bucket:t,Key:r}),c))).Metadata?.[Eo]||"").trim().toLowerCase();if(a)return n.set(r,a),a}catch{return n.set(r,null),null}if(s.has(r)){let o=s.get(r)??null;return n.set(r,o),o}try{let a=await(await ye(`S3 get object ${r}`,3e5,({httpOptions:i})=>e.send(new GetObjectCommand({Bucket:t,Key:r}),i))).Body?.transformToByteArray(),c=a?vr(Buffer.from(a)):null;return s.set(r,c),n.set(r,c),c}catch{return s.set(r,null),n.set(r,null),null}}function fl(e){return e.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"profile"}function hl(e,t){let r=e,n=Object.entries(t).sort((s,o)=>o[0].length-s[0].length);for(let[s,o]of n)s&&(r=r.split(s).join(o));return r}async function wl(e,t,r,n){let s=C.join(e,"asset-map.json"),o;try{o=await F.readFile(s,"utf8");}catch(i){if(i.code==="ENOENT")return;throw i}let a=JSON.parse(o);if(!a||typeof a!="object")return;let c=Object.fromEntries(Object.entries(a).map(([i,d])=>{let l=String(d??"");return t.urlRewriteMode==="absolute"&&t.targetOrigin&&r.targetOrigin&&t.targetOrigin!==r.targetOrigin&&(l=l.split(t.targetOrigin).join(r.targetOrigin)),l=hl(l,n),[i,l]}));await F.writeFile(s,JSON.stringify(c,null,2),"utf8");}async function yl(e,t,r,n,s,o,a){let c=e.targetOrigin!==t.targetOrigin,i=Object.keys(n).length>0;if(!r||!c&&!i)return {outputDir:e.outputDir,cleanup:async()=>{}};if(c&&e.urlRewriteMode!=="absolute")throw new Error(`Deployment profile "${r}" changes targetOrigin, but the base crawl output must use urlRewriteMode "absolute" for multi-target redeploys.`);let d=C.join(C.dirname(e.outputDir),`.deploy-profile-${fl(r)}-${Date.now()}`),l=Zc(d);s.info(`Preparing deployment profile "${r}" from existing crawl output to ${d}...`);try{if(await F.rm(d,{recursive:!0,force:!0}),o){await F.mkdir(d,{recursive:!0});for(let w of o){let m=C.join(e.outputDir,w),h=C.join(d,w);await F.mkdir(C.dirname(h),{recursive:!0}),await F.copyFile(m,h);}}else await F.cp(e.outputDir,d,{recursive:!0});let u={...e,sourceOrigin:e.targetOrigin,targetOrigin:t.targetOrigin,extraReplacements:n,outputDir:d},f=1;s.info(`Rewriting text files for deployment profile "${r}"...`);let p={files:o,onStart:({totalFiles:w,workerCount:m})=>{f=m,s.info(`Rewriting ${w} text file(s) for deployment profile "${r}" with ${m} worker(s).`);},onProgress:({index:w,totalFiles:m,changedTextFiles:h,file:y,changed:b})=>{let O=`Rewriting [${w}/${m}] ${y} (${b?"rewrote":"checked"}; ${h} changed so far)`;m<=200||w<=5||w%10===0||w===m?(s.progress(O,{file:y,index:w,totalFiles:m,changed:b,changedTextFiles:h,workerCount:f}),s.info(O)):s.debug(O);}},g=a?await sr(u,{},{...a,options:p}):await Kt(u,{},p);return await wl(d,e,t,n),s.info(`Prepared deployment profile "${r}" in ${d} (${g} rewritten text file(s)).`),{outputDir:d,cleanup:async()=>{l(),await F.rm(d,{recursive:!0,force:!0});}}}catch(u){throw s.error(`Failed to prepare deployment profile "${r}" temporary output.`,{tempDir:d,outputDir:e.outputDir,error:u instanceof Error?u.message:String(u),...u instanceof Error&&u.stack?{stack:u.stack}:{}}),await F.rm(d,{recursive:true,force:true}).catch(()=>{}),l(),await s.flush().catch(()=>{}),u}}function $o(e,t){let r=s=>s.replace(/^\/+|\/+$/g,""),n=e.targets.find(s=>s.bucketName===t.s3.bucket&&r(s.prefix)===r(t.s3.prefix)&&s.region===t.s3.region);if(!n)throw new Error(`No CDK Lambda deployment target matches s3://${t.s3.bucket}/${t.s3.prefix||""} in ${t.s3.region}. Redeploy the CDK with this target and reinstall remote-workers.json.`);return n}function bl(e,t){if(!e||typeof e!="object")throw new Error("Remote deploy result must be a JSON object.");let r=e;if(r.schemaVersion!==ee||r.response?.operation!=="deploy-copy"||r.response.jobId!==t.jobId||r.response.taskId!==t.taskId||!r.detail||!Array.isArray(r.detail.objects)||!Array.isArray(r.detail.deletedKeys)||!Array.isArray(r.detail.deleteErrors))throw new Error("Remote deploy result has an invalid envelope.");return r}async function Cr(e){let t=null;for(let r=1;r<=Math.max(1,Math.min(5,e.maxAttempts));r+=1){let n=ne(`deploy-${e.batchIndex}-a${r}-${Date.now()}`,"taskId");try{let s=await e.client.invoke({schemaVersion:ee,operation:"deploy-copy",jobId:e.jobId,taskId:n,targetId:e.targetId,items:e.items,...e.deleteRelativeKeys?{deleteRelativeKeys:e.deleteRelativeKeys}:{}}),o=bl(await e.client.readResult(s),s);if(o.response.status==="partial")throw new Error(`Worker reported ${o.response.failedItems} failed item(s).`);return o}catch(s){t=s;}}throw new Error(`Remote deploy task failed after ${e.maxAttempts} attempt(s): ${t instanceof Error?t.message:String(t)}`,{cause:t})}async function Sl(e){let t=$o(e.remoteConfig,e.config),r=ne(`deploy-${Date.now()}-${Xe(Buffer.from(`${t.id}:${e.config.outputDir}`)).slice(0,12)}`,"jobId"),n=pt(e.remoteConfig.workspace.prefix,"jobs",r,"deploy-inputs");e.log.progress(`Staging export for Lambda deploy: 0/${e.files.length}`,{phase:"deploy-stage",index:0,totalFiles:e.files.length,uploaded:0,skipped:0,failed:0,mode:"lambda-s3-copy"});let s=0,o=[],a=Math.max(1,Math.min(16,e.concurrency*2)),c=0;await Promise.all(Array.from({length:Math.min(a,e.files.length)},async()=>{for(;;){let y=c;if(y>=e.files.length)return;c+=1;let b=e.files[y],P=await F.readFile(C.join(e.config.outputDir,b)),O=e.contentTypeByRelativePath?.get(b)||Es.lookup(b)||"application/octet-stream",x=e.revalidateFiles.has(Ye(b))?Cn:St(b)?e.config.s3.htmlCacheControl:e.config.s3.assetCacheControl,k=Xe(P),R=St(b)?vr(P):void 0,A=`${n}/files/${Xe(Buffer.from(b))}-${C.basename(b)}`.replace(/\/+/g,"/");await e.client.writeWorkspaceObject({key:A,body:P,contentType:String(O),cacheControl:x,metadata:{"wpsuite-sha256":k,...R?{"wpsuite-normalized-sha256":R}:{}}}),o[y]={sourceKey:A,targetRelativeKey:b,sha256:k,...R?{normalizedSha256:R}:{},bytes:P.byteLength,contentType:String(O),cacheControl:x},s+=1,(s===e.files.length||s<=5||s%25===0)&&e.log.progress(`Staging export for Lambda deploy: ${s}/${e.files.length}`,{phase:"deploy-stage",index:s,totalFiles:e.files.length,staged:s,mode:"lambda-s3-copy"});}}));let i=[],d=Math.max(1,Math.min(500,e.batchSize));for(let y=0;y<o.length;y+=d)i.push(o.slice(y,y+d));let l=[],u=[],f=[],p=0,g=0,w=0,m=Math.max(1,Math.min(Math.max(1,e.concurrency),i.length));if(e.log.progress(`Lambda deploy: 0/${e.files.length}`,{phase:"deploy-copy",index:0,totalFiles:e.files.length,uploaded:0,skipped:0,failed:0,mode:"lambda-s3-copy",workerCount:m,completedBatches:0,totalBatches:i.length}),await Promise.all(Array.from({length:m},async()=>{for(;;){let y=w;if(y>=i.length)return;w+=1;let b=Date.now(),P=await Cr({client:e.client,jobId:r,targetId:t.id,batchIndex:y+1,items:i[y],maxAttempts:e.maxAttempts}),O=0,x=0,k=0;for(let A of P.detail.objects)p+=1,A.status==="copied"?(l.push(A.targetKey),O+=1):A.status==="skipped"?(u.push(A.targetKey),x+=1):(f.push(A.targetKey),k+=1),e.log.debug(`Lambda deploy ${A.status}: ${A.targetKey}`,{phase:"deploy-copy",batch:y+1,sourceKey:A.sourceKey,targetKey:A.targetKey,status:A.status,...A.error?{error:A.error}:{}});g+=1;let R=Date.now()-b;e.log.info(`Lambda deploy batch ${y+1}/${i.length} completed: ${O} copied, ${x} skipped unchanged, ${k} failed.`,{phase:"deploy-copy",batch:y+1,totalBatches:i.length,items:P.detail.objects.length,copied:O,skipped:x,failed:k,elapsedMs:R,elapsedSeconds:Math.round(R/10)/100,workerExporterVersion:P.response.exporterVersion,...P.requestId?{lambdaRequestId:P.requestId}:{},...P.completedAt?{workerCompletedAt:P.completedAt}:{}}),e.log.progress(`Lambda deploy: ${p}/${e.files.length}`,{phase:"deploy-copy",index:p,totalFiles:e.files.length,uploaded:l.length,skipped:u.length,failed:f.length,mode:"lambda-s3-copy",workerCount:m,completedBatches:g,totalBatches:i.length});}})),f.length>0)throw new Error(`Remote deployment failed for ${f.length} object(s).`);let h=[];for(let y=0;y<e.deletedFiles.length;y+=1e3){let b=e.deletedFiles.slice(y,y+1e3);if(b.length===0)continue;let P=await Cr({client:e.client,jobId:r,targetId:t.id,batchIndex:i.length+Math.floor(y/1e3)+1,items:[],deleteRelativeKeys:b,maxAttempts:e.maxAttempts});h.push(...P.detail.deletedKeys),e.log.progress(`Lambda deploy deletions: ${h.length}/${e.deletedFiles.length}`,{phase:"deploy-delete",index:h.length,totalFiles:e.deletedFiles.length,deleted:h.length,mode:"lambda-s3-copy"});}return {uploadedKeys:l,skippedKeys:u,failedKeys:f,deletedKeys:h}}async function Pl(e){let t=$o(e.remoteConfig,e.config),r=ne(`deploy-manifest-${Date.now()}-${Xe(Buffer.from(t.id)).slice(0,12)}`,"jobId"),n=e.objects.map(p=>({sourceKey:p.object.key,targetRelativeKey:p.relativePath,sha256:p.object.sha256,bytes:p.object.bytes,contentType:p.contentType||"application/octet-stream",cacheControl:e.revalidateFiles.has(Ye(p.relativePath))?Cn:St(p.relativePath)?e.config.s3.htmlCacheControl:e.config.s3.assetCacheControl})),s=[],o=Math.max(1,Math.min(500,e.batchSize));for(let p=0;p<n.length;p+=o)s.push(n.slice(p,p+o));let a=[],c=[],i=[],d=0,l=0,u=Math.max(1,Math.min(Math.max(1,e.concurrency),Math.max(1,s.length)));if(e.log.progress(`Lambda deploy: 0/${n.length}`,{phase:"deploy-copy",index:0,totalFiles:n.length,mode:"lambda-s3-native",workerCount:u}),await Promise.all(Array.from({length:s.length===0?0:u},async()=>{for(;;){let p=d;if(p>=s.length)return;d+=1;let g=await Cr({client:e.client,jobId:r,targetId:t.id,batchIndex:p+1,items:s[p],maxAttempts:e.maxAttempts});for(let w of g.detail.objects)l+=1,w.status==="copied"?a.push(w.targetKey):w.status==="skipped"?c.push(w.targetKey):i.push(w.targetKey);e.log.progress(`Lambda deploy: ${l}/${n.length}`,{phase:"deploy-copy",index:l,totalFiles:n.length,uploaded:a.length,skipped:c.length,failed:i.length,mode:"lambda-s3-native",workerCount:u});}})),i.length>0)throw new Error(`Remote deployment failed for ${i.length} object(s).`);let f=[];for(let p=0;p<e.deletedFiles.length;p+=1e3){let g=e.deletedFiles.slice(p,p+1e3);if(g.length===0)continue;let w=await Cr({client:e.client,jobId:r,targetId:t.id,batchIndex:s.length+Math.floor(p/1e3)+1,items:[],deleteRelativeKeys:g,maxAttempts:e.maxAttempts});f.push(...w.detail.deletedKeys);}return {uploadedKeys:a,skippedKeys:c,failedKeys:i,deletedKeys:f}}async function Rl(e,t,r,n,s){let o={...t,jobId:ne(`profile-${Xe(Buffer.from(n)).slice(0,16)}-${Date.now()}`,"jobId"),objects:{},assetMap:{...t.assetMap},generatedAt:new Date().toISOString()},a=0,c=Math.max(1,Math.min(Math.max(1,s),Math.max(1,r.length)));return await Promise.all(Array.from({length:r.length===0?0:c},async()=>{for(;;){let i=a;if(i>=r.length)return;a+=1;let d=r[i],l=pt(e.config.workspace.prefix,"jobs",o.jobId,"profile",Xe(Buffer.from(d.relativePath)),C.basename(d.relativePath));o.objects[d.relativePath]={...d,object:await e.copyWorkspaceObject(d.object,l)};}})),o}async function Oo(e=process.argv.slice(2)){let t=await Ie(),r=yr(e),n=bt(t,r),s=C.resolve(n.config.logDir||"logs"),o=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",a=o?C.join(C.resolve(o),"deploy-diff.json"):"",c=new ut(s,"deploy.log.jsonl",n.config.logLevel??"info"),i=n.profile?.extraReplacements??{},d=async()=>{};try{let l=await ct(t);if(e.includes("--content-sync")&&l?.schemaVersion!==2)throw new Error("Content-sync deployment requires a valid schema-2 targeted deploy plan.");let f=await rs(t);if(f)throw new Error(`Deployment blocked: the crawl started at ${f.startedAt} did not complete its final rewrite. Run a successful crawl or resume the rewrite before deploying.`);let p=t.remoteWorkers?.rewrite?.enabled===!0,g=t.remoteWorkers?.deploy?.enabled===!0,w=null,m=null;if(p||g){let $=ir({runtimeDir:o});if(!$)throw new Error("Remote Lambda workers are enabled, but the runtime directory is unknown.");w=await Xt($);let _=!1;m=new mt(w,{},{onProgress:E=>{c.progress(`Lambda ${E.operation} batch: ${E.completedItems+E.failedItems}/${E.totalItems}`,{remoteWorkerOperation:E.operation,remoteWorkerTaskId:E.taskId,remoteWorkerStatus:E.status,remoteWorkerCompletedItems:E.completedItems,remoteWorkerFailedItems:E.failedItems,remoteWorkerTotalItems:E.totalItems,remoteWorkerUpdatedAt:E.updatedAt});},onProgressError:E=>{_||(_=!0,c.warn("Lambda progress status could not be read; task execution continues.",{error:E.message}));}});}let h=g&&p&&t.remoteWorkers?.render?.enabled===!0&&m&&w?.functions.asset?await cr(t):null;if(h&&m&&w){if(h.workspace.bucket!==w.workspace.bucket||h.workspace.prefix!==w.workspace.prefix)throw new Error("Remote export manifest workspace does not match remote-workers.json.");let $=n.config,_=$.s3SyncMode??"sdk-upload-delete";if(l?.schemaVersion===2&&l.deletedFiles.length>0&&_!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let E=l?.schemaVersion===2?[...l.uploadGroups.assets,...l.uploadGroups.content,...l.uploadGroups.listings,...l.uploadGroups.resources,...l.uploadGroups.sitemapLeaves,...l.uploadGroups.sitemapIndexes]:l?.changedFiles??[];if(l?.schemaVersion===2){let ce=[...new Set(E)],De=[...new Set(l.changedFiles)];if(ce.length!==De.length||De.some(ot=>!ce.includes(ot)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let he=!!l&&!l.fullSyncRequired?[...new Set(E.map(Ye))]:Object.keys(h.objects).sort(),L=he.filter(ce=>!h.objects[ce]);if(L.length>0)throw new Error(`Remote export manifest is missing ${L.length} planned object(s): ${L.slice(0,10).join(", ")}`);let Pe=h,V=he.map(ce=>h.objects[ce]);n.name&&(t.targetOrigin!==$.targetOrigin||Object.keys(i).length>0)&&(Pe=await Rl(m,h,V,n.name||"default",t.concurrency),await or($,Pe,Pe.assetMap,{client:m,jobId:Pe.jobId,concurrency:t.concurrency,batchSize:25,maxAttempts:2}),V=he.map(ce=>Pe.objects[ce])),n.name&&c.info(`Using deployment profile: ${n.name}`),c.info(`Starting S3-native Lambda deploy - s3://${$.s3.bucket}/${$.s3.prefix||""} (${$.s3.region}).`),c.mark("deploy");let ie=await Pl({client:m,remoteConfig:w,config:$,objects:V,deletedFiles:_==="sdk-upload-delete"?l?.deletedFiles??[]:[],revalidateFiles:new Set((l?.revalidateFiles??[]).map(Ye)),concurrency:t.concurrency,batchSize:50,maxAttempts:2,log:c});a&&(await F.mkdir(C.dirname(a),{recursive:!0}),await F.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:"lambda-s3-native",summary:{totalFiles:V.length,eligibleFiles:V.length,uploaded:ie.uploadedKeys.length,skipped:ie.skippedKeys.length,rejected:0,failed:ie.failedKeys.length,deleted:ie.deletedKeys.length,protected:0,...n.name?{profile:n.name}:{}},uploadedKeys:ie.uploadedKeys,skippedKeys:ie.skippedKeys,rejectedKeys:[],failedKeys:ie.failedKeys,deletedKeys:ie.deletedKeys,protectedRemoteOnlyKeys:[]},null,2),"utf8")),l?.schemaVersion!==2&&await Qe(t),c.endMark("deploy"),await c.flush();return}let y=await yl(t,n.config,n.name,i,c,l?.schemaVersion===2?l.changedFiles:void 0,p&&m?{client:m,jobId:`profile-${Date.now()}`,concurrency:t.remoteWorkers?.rewrite?.concurrency??t.rewriteConcurrency,batchSize:t.remoteWorkers?.rewrite?.batchSize??25,maxAttempts:t.remoteWorkers?.rewrite?.maxAttempts??2,onStageProgress:({index:$,totalFiles:_,file:E})=>{($===1||$===_||$%25===0)&&c.progress(`Staging deployment-profile rewrite: ${$}/${_}`,{phase:"rewrite-stage",index:$,totalFiles:_,file:E,execution:"lambda"});}}:void 0);d=y.cleanup;let b={...n.config,outputDir:y.outputDir},P=b.s3SyncMode??"sdk-upload-delete";if(l?.schemaVersion===2&&l.deletedFiles.length>0&&P!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let O=l?.schemaVersion!==2&&y.outputDir!==t.outputDir&&(t.targetOrigin!==n.config.targetOrigin||Object.keys(i).length>0),x=!!l&&!l.fullSyncRequired&&!O;if(l?.schemaVersion===2&&!x)throw new Error("Content-sync deployment cannot widen into a full-output deployment.");n.name&&c.info(`Using deployment profile: ${n.name}`),c.info(`Starting deploy \u2014 s3://${b.s3.bucket}/${b.s3.prefix||""} (region: ${b.s3.region})`),c.info(`S3 sync mode: ${P}`),l&&l.fullSyncRequired?c.info("Deploy plan requests a full sync; scanning the whole output tree."):l&&O?c.info("Ignoring incremental deploy plan because deployment-profile rewrites require a full sync."):x&&c.info(`Using incremental deploy plan: ${l.changedFiles.length} changed file(s), ${l.deletedFiles.length} deleted file(s).`),c.mark("deploy");let k=new S3Client({region:b.s3.region}),R=y.outputDir===t.outputDir?await tl(t,o,c):null,A=l?.schemaVersion===2?[...l.uploadGroups.assets,...l.uploadGroups.content,...l.uploadGroups.listings,...l.uploadGroups.resources,...l.uploadGroups.sitemapLeaves,...l.uploadGroups.sitemapIndexes]:l?.changedFiles??[];if(l?.schemaVersion===2){let $=[...new Set(A)],_=[...new Set(l.changedFiles)];if($.length!==_.length||_.some(E=>!$.includes(E)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let I=x?(await Promise.all(A.map(async $=>{try{return (await F.stat(C.join(b.outputDir,$))).isFile()?$:null}catch{if(l?.schemaVersion===2)throw new Error(`Content-sync planned upload is missing: ${$}`);return null}}))).filter($=>$!==null):await Ri(["**/*"],{cwd:b.outputDir,onlyFiles:!0,dot:!0}),K=[],D=[],S=I.filter($=>{let _=R?.byRelativePath.get(Ye($));if(!_)return !0;let E=Sr(b.s3.prefix,$);return K.push($),D.push(E),c.reject(_.kind,_.sourceUrl||$,"rewrite not completed; deploy upload blocked","deploy-guard",{file:$,key:E,outputPath:_.outputPath,manifestPath:R?.manifestPath}),!1}),q=new Set((l?.revalidateFiles||[]).map(Ye)),ue=new Set((x?S:I).map($=>Sr(b.s3.prefix,$)));R&&(R.pendingPages>0||R.pendingTextAssets>0)&&c.info(`Deploy rewrite guard loaded ${R.pendingPages} pending page(s) and ${R.pendingTextAssets} pending text asset(s) from crawl manifest.`,{manifestPath:R.manifestPath,pendingPages:R.pendingPages,pendingTextAssets:R.pendingTextAssets,source:"deploy-guard"}),K.length>0&&c.warn(`Deploy rewrite guard blocked ${K.length} file(s) from upload because final crawl rewrite is incomplete.`,{rejected:K.length,manifestPath:R?.manifestPath,source:"deploy-guard"}),x?c.info(`Using ${S.length} eligible planned changed file(s) from deploy plan for upload${K.length>0?` (${K.length} blocked by deploy rewrite guard)`:""}.`):c.info(`Found ${I.length} file(s) in output directory "${b.outputDir}"${K.length>0?`; ${S.length} remain eligible for upload after deploy rewrite guard filtering`:""}.`),c.progress("Deploy preflight: comparing local output with remote S3 state.",{phase:"deploy",mode:P,totalFiles:S.length,scannedFiles:I.length,rejected:K.length,deploymentProfile:n.name||"",s3Bucket:b.s3.bucket,s3Prefix:b.s3.prefix||"",targetedPlan:x,deployGuardEnabled:y.outputDir===t.outputDir});let H=0,B=0,T=0,W=[],U=[],z=[],J=[],de=[],Se=new Map,v=new Map,j=new Map,M=new Map,X=new Map;if(g){if(!m||!w)throw new Error("Remote deploy worker client was not initialized.");if(P!=="sdk-upload-delete"&&P!=="sdk-upload-only")throw new Error(`Unsupported remote deploy mode: ${P}`);let $=await Sl({client:m,remoteConfig:w,config:b,files:S,deletedFiles:P==="sdk-upload-delete"?l?.deletedFiles??[]:[],revalidateFiles:q,contentTypeByRelativePath:R?.contentTypeByRelativePath,concurrency:b.remoteWorkers?.deploy?.concurrency??b.assetDownloadConcurrency,batchSize:b.remoteWorkers?.deploy?.batchSize??50,maxAttempts:b.remoteWorkers?.deploy?.maxAttempts??2,log:c});W.push(...$.uploadedKeys),U.push(...$.skippedKeys),z.push(...$.failedKeys),J=$.deletedKeys,H=W.length,B=U.length,T=z.length,c.info(`Lambda deploy complete: ${H} copied, ${B} skipped unchanged, ${J.length} deleted, ${T} failed.`),a&&(await F.mkdir(C.dirname(a),{recursive:!0}),await F.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:"lambda-s3-copy",summary:{totalFiles:I.length,eligibleFiles:S.length,uploaded:H,skipped:B,rejected:D.length,failed:T,deleted:J.length,protected:0,...n.name?{profile:n.name}:{}},uploadedKeys:W,skippedKeys:U,rejectedKeys:D,failedKeys:z,deletedKeys:J,protectedRemoteOnlyKeys:[]},null,2),"utf8")),l?.schemaVersion!==2&&await Qe(t),c.endMark("deploy"),await c.flush();return}x||(c.info("Listing existing S3 objects to detect unchanged files..."),Se=await cl(k,b.s3.bucket,b.s3.prefix,c),c.info(`Found ${Se.size} existing key(s) in S3.`));let te=async $=>Se.has($)?Se.get($)??null:x?ll(k,b.s3.bucket,$,v):null;for(let $ of S){let _=C.join(b.outputDir,$),E=Sr(b.s3.prefix,$),re=R?.contentTypeByRelativePath.get($),he=re&&re!=="application/octet-stream"?re:Es.lookup($)||re||"application/octet-stream",L=q.has(Ye($)),Pe=L?Cn:St($)?b.s3.htmlCacheControl:b.s3.assetCacheControl,V=H+B+T+1;S.length<=200||V<=5||V%10===0||V===S.length?(c.progress(`Uploading [${V}/${S.length}] ${E} (${he})`,{file:$,key:E,index:V,totalFiles:S.length,contentType:he,mode:P}),c.info(`Uploading [${V}/${S.length}] ${E} (${he})`)):c.debug(`Uploading [${V}/${S.length}] ${E} (${he})`);try{let Re=await F.readFile(_),ie=await te(E),ce=null,De=null;if(ie){let ot=await ul(k,b.s3.bucket,E,ie),Wo=!L||Io(ot.cacheControl)===Io(Pe),No=Pn(ot.contentType)===Pn(String(he)),Tr=Wo&&No,_o=Re.byteLength;if(ie.size===_o){let Lt=ie.etag.includes("-");if(ie.etag!==""&&!Lt){let Bo=pl(Re);if(ie.etag===Bo&&Tr){B++,S.length<=200||B<=5||B%25===0?(c.progress(`Skipped unchanged [${V}/${S.length}] ${E}`,{file:$,key:E,index:V,totalFiles:S.length,uploaded:H,skipped:B,failed:T,mode:P,reason:"etag-md5-match"}),c.info(`Skipped unchanged [${V}/${S.length}] ${E}`)):c.debug(`Skipped unchanged [${V}/${S.length}] ${E}`),U.push(E);continue}}ce=Xe(Re);let $n=await ml(k,b.s3.bucket,E,j);if($n&&$n===ce&&Tr){B++,S.length<=200||B<=5||B%25===0?(c.progress(`Skipped unchanged [${V}/${S.length}] ${E}`,{file:$,key:E,index:V,totalFiles:S.length,uploaded:H,skipped:B,failed:T,mode:P,reason:"metadata-sha256-match"}),c.info(`Skipped unchanged [${V}/${S.length}] ${E}`)):c.debug(`Skipped unchanged [${V}/${S.length}] ${E}`),U.push(E);continue}}if(St($)){De=vr(Re);let Lt=await gl(k,b.s3.bucket,E,M,X);if(Lt&&Lt===De&&Tr){B++,S.length<=200||B<=5||B%25===0?(c.progress(`Skipped semantically unchanged [${V}/${S.length}] ${E}`,{file:$,key:E,index:V,totalFiles:S.length,uploaded:H,skipped:B,failed:T,mode:P,reason:"normalized-html-match"}),c.info(`Skipped semantically unchanged [${V}/${S.length}] ${E}`)):c.debug(`Skipped semantically unchanged [${V}/${S.length}] ${E}`),U.push(E);continue}}}ce=ce??Xe(Re),De=De??(St($)?vr(Re):null),await ye(`S3 upload ${E}`,9e5,({abortController:ot})=>new Upload({client:k,abortController:ot,params:{Bucket:b.s3.bucket,Key:E,Body:Re,ContentType:he,CacheControl:Pe,Metadata:{[Ao]:ce,...De?{[Eo]:De}:{}}}}).done()),H++,W.push(E),(H%25===0||H===S.length)&&(c.progress(`Uploaded ${H}/${S.length} file(s)\u2026`,{uploaded:H,skipped:B,failed:T,totalFiles:S.length,mode:P}),c.info(`Uploaded ${H}/${S.length} file(s)\u2026`));}catch(Re){T++,z.push(E),c.error(`Failed to upload ${E}: ${Re.message}`,{key:E,error:String(Re)});}}if(c.info(`Upload complete: ${H} uploaded, ${B} skipped unchanged, ${D.length} rejected by guard, ${T} failed.`),z.length>0||D.length>0)throw new Error(`Deployment stopped before deletion because ${z.length} upload(s) failed and ${D.length} upload(s) were rejected.`);if(P==="sdk-upload-delete"){let $=new Set((l?.deletedFiles??[]).map(E=>Sr(b.s3.prefix,E))),_=[...$].filter(E=>!ue.has(E));if(!x&&(de=[...Se.keys()].filter(re=>!ue.has(re)).filter(re=>!$.has(re)),de.length>0)){c.warn(`Protected ${de.length} remote-only S3 object(s) from deletion because the crawl did not provide explicit tombstones.`,{protected:de.length,source:"deploy-delete-guard"});for(let re of de)c.debug(` protected remote-only object: ${re}`);}J=await dl(k,b.s3.bucket,x?_:_.filter(E=>Se.has(E)),c);}else c.info("Sync mode is sdk-upload-only \u2014 skipping stale object deletion.");a&&(await F.mkdir(C.dirname(a),{recursive:!0}),await F.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:P,summary:{totalFiles:I.length,eligibleFiles:S.length,uploaded:W.length,skipped:U.length,rejected:D.length,failed:z.length,deleted:J.length,protected:de.length,...n.name?{profile:n.name}:{}},uploadedKeys:W,skippedKeys:U,rejectedKeys:D,failedKeys:z,deletedKeys:J,protectedRemoteOnlyKeys:de},null,2),"utf8")),l?.schemaVersion!==2&&await Qe(t),c.endMark("deploy"),await c.flush();}finally{await d().catch(()=>{});}}function Cl(e){let t=e;return t.endsWith("/")?t+="index.html":C.posix.basename(t).includes(".")||(t+="/index.html"),t}function kl(e,t){let r=t.trim().replace(/^\/+|\/+$/g,"");if(!r)return null;let n=`/${r}`;return e===n||e.startsWith(`${n}/`)?e:`${n}${e.startsWith("/")?e:`/${e}`}`}function Mo(e,t){let r=new Set;for(let n of e){let s=new URL(n,"https://content-sync.invalid");if(s.origin!=="https://content-sync.invalid")continue;let o=`${s.pathname}${s.search}`,a=Cl(s.pathname);r.add(o),r.add(`${a}${s.search}`);let c=kl(a,t);c&&r.add(`${c}${s.search}`);}return [...r].sort()}function Al(){let e=String(process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"").trim();return e?C.join(C.resolve(e),"content-sync-invalidation.json"):""}async function xn(e,t){if(!e)return;await F.mkdir(C.dirname(e),{recursive:true});let r=`${e}.${process.pid}.${Date.now()}.tmp`;await F.writeFile(r,JSON.stringify({...t,updatedAt:new Date().toISOString()},null,2),"utf8"),await F.rename(r,e);}async function El(e,t,r,n){if(!e)return null;try{let s=JSON.parse(await F.readFile(e,"utf8"));if(s.schemaVersion!==1||s.distributionId!==t||s.impactHash!==r||!Array.isArray(s.batches))throw new Error("Content-sync invalidation state does not match the deploy plan.");let o=s.batches.flatMap(a=>a.paths);return o.length!==n.length||o.some((a,c)=>a!==n[c])?null:s}catch(s){if(s.code==="ENOENT")return null;throw s}}function $l(e,t=3e3){let r=[];for(let n=0;n<e.length;n+=t)r.push(e.slice(n,n+t));return r}async function Fo(e=process.argv.slice(2)){let t=await Ie(),r=yr(e),n=bt(t,r),s=n.config,o=new ut(s.logDir||"logs","invalidate.log.jsonl",s.logLevel??"info"),a=e.includes("--content-sync"),c=await ct(t);if(a&&c?.schemaVersion!==2)throw new Error("Content-sync invalidation requires a valid schema-2 targeted deploy plan.");if(n.name&&o.info(`Using deployment profile: ${n.name}`),!s.cloudFront.distributionId){o.info("No CloudFront distributionId configured; skipping invalidation."),await o.flush();return}let i=c?.schemaVersion===2?c.invalidationPaths:s.cloudFront.invalidationPaths.length>0?s.cloudFront.invalidationPaths:["/*"],d=c?.schemaVersion===2?Mo(i,s.s3.prefix||""):i;if(c?.schemaVersion===2&&d.some(g=>g==="/*"))throw new Error("Content-sync cannot use a whole-distribution invalidation.");if(d.length===0){o.info("The targeted deploy plan has no CloudFront paths to invalidate."),await o.flush();return}let l=s.cloudFront.distributionId,u=new CloudFrontClient({region:"us-east-1",maxAttempts:5});if(o.mark("invalidate"),c?.schemaVersion!==2){let g=`smartcloud-static-publisher-${Date.now()}`;await ye(`CloudFront invalidation for distribution ${l}`,3e5,({httpOptions:w})=>u.send(new CreateInvalidationCommand({DistributionId:l,InvalidationBatch:{CallerReference:g,Paths:{Quantity:d.length,Items:d}}}),w)),o.endMark("invalidate"),await o.flush();return}let f=Al(),p=await El(f,l,c.impactHash,d);if(!p){let g=createHash("sha256").update(JSON.stringify(d)).digest("hex");p={schemaVersion:1,distributionId:l,impactHash:c.impactHash,updatedAt:new Date().toISOString(),batches:$l(d).map((w,m)=>({index:m,callerReference:`wpsuite-content-sync-${c.impactHash.slice(0,24)}-${g.slice(0,24)}-${m}`,paths:w,invalidationId:null,status:"pending"}))},await xn(f,p);}for(let g of p.batches){if(!g.invalidationId){let w=await ye(`CloudFront targeted invalidation batch ${g.index+1}`,3e5,({httpOptions:h})=>u.send(new CreateInvalidationCommand({DistributionId:l,InvalidationBatch:{CallerReference:g.callerReference,Paths:{Quantity:g.paths.length,Items:g.paths}}}),h)),m=String(w.Invalidation?.Id||"").trim();if(!m)throw new Error("CloudFront did not return an invalidation ID.");g.invalidationId=m,g.status="created",await xn(f,p);}await waitUntilInvalidationCompleted({client:u,maxWaitTime:900,minDelay:2,maxDelay:15},{DistributionId:l,Id:g.invalidationId}),g.status="completed",await xn(f,p),o.info(`CloudFront invalidation batch ${g.index+1}/${p.batches.length} completed.`,{invalidationId:g.invalidationId,pathCount:g.paths.length});}o.endMark("invalidate"),await o.flush();}function Ir(e){let t=new URL(e);return t.hash="",t.href}function Do(e,t,r){let n=new Set([...t].map(i=>Ir(i))),s=new Map,o=new Map,a=i=>{s.set(Ir(i),i);},c=i=>{if(!i)return;let d=Ir(i);s.has(d)||o.set(d,i);};for(let i of e.deleteUrls)a(i);for(let i of e.resourceDeleteUrls)a(i);for(let i of e.archiveFamilies)if(i.foundPosts===0)for(let d of i.pageUrls)n.has(Ir(d))||a(d);for(let i of e.directRenderUrls)c(i);for(let i of e.resourceRenderUrls)c(i);for(let i of e.archiveFamilies)c(i.pageUrls[0]),c(i.pageUrls.at(-1));for(let i of r)c(i);return {expectedAvailable:[...o.values()],expectedMissing:[...s.values()]}}var Lo=["claimed","impact-planned","rendered","deployed","invalidated","verified","acknowledged"];function An(){let e=String(process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"").trim();if(!e)throw new Error("Content-sync requires a runtime directory.");return C.resolve(e)}function Pt(e,t){return Lo.indexOf(e)>=Lo.indexOf(t)}async function Ke(e,t,r,n,s={}){let o={timestamp:new Date().toISOString(),eventType:t,status:t.endsWith("failed")?"failed":"success",actorSource:"content-sync",jobId:r.id||"",command:"content-sync",message:n,details:s};await F.mkdir(e,{recursive:true}),await F.appendFile(C.join(e,"audit-events.jsonl"),`${JSON.stringify(o)}
|
|
19
|
+
`,"utf8");}function Ml(e){return Rt({postTypes:e.postTypes??[],listingPaths:e.listingPaths??[],includeSubsites:e.includeSubsites,includePostTypeArchives:e.includePostTypeArchives,includeTaxonomyArchives:e.includeTaxonomyArchives,includeAuthorArchives:e.includeAuthorArchives,includeDateArchives:e.includeDateArchives,includePostsPage:e.includePostsPage,includeSitemapChain:e.includeSitemapChain})}function jl(e,t){let r=(e.scheduler?.rules??[]).filter(s=>s.command==="content-sync"&&s.id===t);if(r.length===0)throw new Error(`Content-sync scheduler rule not found: ${t}`);if(r.length>1)throw new Error(`Content-sync scheduler rule ID is not unique: ${t}`);let n=r[0];if(n.enabled===false)throw new Error(`Content-sync scheduler rule is disabled: ${t}`);return n}async function En(e,t){if(e.subscriptionType!=="PROFESSIONAL"&&e.subscriptionType!=="AGENCY")throw new Error("Content-sync requires an active Professional or Agency subscription.");let r=Ml(t),n=bt(e,t.deploymentProfile),s=n.name||"",o=jn(e.sourceOrigin,String(t.id||""),r),a=Fn({sourceOrigin:e.sourceOrigin,targetOrigin:n.config.targetOrigin,deploymentProfile:s,s3Bucket:n.config.s3.bucket,s3Prefix:n.config.s3.prefix,cloudFrontDistributionId:n.config.cloudFront.distributionId,urlRewriteMode:n.config.urlRewriteMode,extraReplacements:n.profile?.extraReplacements??{}}),c=Dn({siteId:e.wpsuite?.siteSettings?.siteId,accountId:e.wpsuite?.siteSettings?.accountId,sourceOrigin:e.sourceOrigin,ruleId:String(t.id||""),targetFingerprint:a}),i=`content-sync:${String(t.id||"")}:${Ue({scopeFingerprint:o,targetFingerprint:a}).slice(0,32)}`,d=new Wt({sourceOrigin:e.sourceOrigin,runtimeToken:String(e.wpsuite?.runtimeToken||""),ignoreHttpsErrors:e.ignoreHttpsErrors}),l=await d.releaseFingerprint(r.includeSubsites),u=Mn({wordpressFingerprint:l,targetFingerprint:a,sourceOrigin:e.sourceOrigin,sitemapPaths:kt(e.sitemapPaths),blockedPathPrefixes:e.blockedPathPrefixes,assetPathPrefixes:e.assetPathPrefixes,noJavaScriptRenderPathPrefixes:e.noJavaScriptRenderPathPrefixes,urlRewriteMode:e.urlRewriteMode});return {rule:t,scope:r,deployment:n,deploymentProfile:s,scopeFingerprint:o,targetFingerprint:a,consumerId:c,coalesceKey:i,client:d,releaseFingerprint:u}}async function Fl(e){let t=An(),r=Nt(t),n=await Ie(),s=(n.scheduler?.rules??[]).filter(d=>d.command==="content-sync"&&d.enabled!==false);if(s.length===0)return 0;let o=await Mr(r),a=await _t(r),c=await Or(r),i=0;for(let d of s){let l=await En(n,d),u=c.entries[l.coalesceKey];if(!u||u.releaseJobId!==e||u.scopeFingerprint!==l.scopeFingerprint||u.targetFingerprint!==l.targetFingerprint||u.releaseFingerprint!==l.releaseFingerprint)throw new Error(`The normal release has no matching pre-crawl content-sync cutoff for rule ${String(d.id||"")}.`);let f=Ue({releaseJobId:e,releaseFingerprint:l.releaseFingerprint,scopeFingerprint:l.scopeFingerprint,targetFingerprint:l.targetFingerprint,sequence:u.sequence}),p=await l.client.establishBaseline({consumerId:l.consumerId,scopeFingerprint:l.scopeFingerprint,baselineId:f,postTypes:l.scope.postTypes,includeSubsites:l.scope.includeSubsites,sequence:u.sequence}),g={schemaVersion:1,ruleId:String(d.id||""),consumerId:l.consumerId,coalesceKey:l.coalesceKey,scopeFingerprint:l.scopeFingerprint,targetFingerprint:l.targetFingerprint,releaseFingerprint:l.releaseFingerprint,baselineId:f,deploymentProfile:l.deploymentProfile,committedSequence:p.committedSequence,releaseJobId:e,verifiedAt:new Date().toISOString()};o.entries[l.coalesceKey]=g;let w=a.rules[l.coalesceKey];a.rules[l.coalesceKey]={ruleId:String(d.id||""),consumerId:l.consumerId,coalesceKey:l.coalesceKey,committedSequence:p.committedSequence,observedHeadSequence:p.headSequence,lag:Math.max(0,p.headSequence-p.committedSequence),lastSuccessfulJobId:w?.lastSuccessfulJobId||e,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:p.headSequence>p.committedSequence,retryAttempt:0,nextRetryAt:null,lastError:null,baselineStatus:"ready",baselineReason:null};let m=await Kn(r,l.coalesceKey);await Ke(t,"content-sync-baseline-established",{id:e},"A normal release established a verified content-sync baseline.",{ruleId:d.id,consumerId:l.consumerId,committedSequence:p.committedSequence,supersededCurrent:m}),i++;}return await Nn(r,o),await Bt(r,a),await F.rm(r.releaseCutoff,{force:true}),i}async function Dl(e){let t=An(),r=Nt(t),n=await Ie(),s=(n.scheduler?.rules??[]).filter(c=>c.command==="content-sync"&&c.enabled!==false);if(s.length===0)return 0;let o=await Or(r),a=0;for(let c of s){let i=await En(n,c),d=Object.values(o.entries).find(f=>f.releaseJobId===e&&f.ruleId===String(c.id||""));if(d){if(d.coalesceKey===i.coalesceKey&&d.scopeFingerprint===i.scopeFingerprint&&d.targetFingerprint===i.targetFingerprint&&d.releaseFingerprint===i.releaseFingerprint){a++;continue}throw new Error(`The normal release scope changed after its journal cutoff was captured for rule ${String(c.id||"")}. Start a new normal publish instead of resuming this release.`)}let l=await i.client.unboundHead(i.scope.postTypes,i.scope.includeSubsites),u={schemaVersion:1,releaseJobId:e,ruleId:String(c.id||""),coalesceKey:i.coalesceKey,scopeFingerprint:i.scopeFingerprint,targetFingerprint:i.targetFingerprint,releaseFingerprint:i.releaseFingerprint,sequence:l.headSequence,capturedAt:new Date().toISOString()};o.entries[i.coalesceKey]=u,await Ke(t,"content-sync-release-cutoff-captured",{id:e},"A normal release captured its pre-crawl content-sync journal cutoff.",{ruleId:c.id,consumerId:i.consumerId,sequence:l.headSequence}),a++;}return await Wn(r,o),a}async function Ul(e,t){let r=JSON.parse(await F.readFile(C.join(e,"current-run.json"),"utf8"));if(r.id!==t||r.command!=="content-sync"||!String(r.ruleId||"").trim())throw new Error("The active queue job is not the requested content-sync job.");return r}async function Tn(e,t,r=0){let n=e.protocol==="https:"?qn:Zo,s=e.protocol==="https:"?new qn.Agent({rejectUnauthorized:!t}):void 0;return new Promise((o,a)=>{let c=n.get(e,{agent:s,timeout:3e4,headers:{"user-agent":"WP-Suite-Content-Sync/1"}},i=>{let d=i.statusCode??500,l=i.headers.location;if(d>=300&&d<400&&l&&r<5){i.resume(),Tn(new URL(l,e),t,r+1).then(o,a);return}let u=[],f=0;i.on("data",p=>{f+=p.byteLength,f<=1048576&&u.push(p);}),i.on("error",a),i.on("end",()=>o({status:d,body:Buffer.concat(u).toString("utf8"),contentType:String(i.headers["content-type"]||"")}));});c.on("timeout",()=>c.destroy(new Error(`Verification timed out: ${e}`))),c.on("error",a);})}async function Ll(e,t,r,n){let s=t.deployment.config.targetOrigin;if(!/^https?:\/\//i.test(s))throw new Error("Content-sync verification requires an absolute HTTP(S) target origin.");let o=JSON.parse(await F.readFile(n,"utf8")),a=new Set;for(let[l,u]of Object.entries(o.pages??{}))a.add(l),typeof u.url=="string"&&a.add(u.url);let c=await ct(e);if(c?.schemaVersion!==2||c.impactHash!==r.impactHash)throw new Error("Content-sync verification requires the matching targeted deploy plan.");let i=Do(r,a,c.resolvedSitemapUrls),d=new Set(r.resourceRenderUrls.map(l=>{let u=new URL(l);return u.hash="",u.href}));for(let l of i.expectedAvailable){let u=new URL(l),f=new URL(`${u.pathname}${u.search}`,s),p=await Tn(f,e.ignoreHttpsErrors);if(p.status<200||p.status>=400)throw new Error(`Content-sync verification failed (${p.status}): ${f}`);let g=new URL(l);if(g.hash="",d.has(g.href)){if(!p.contentType.toLowerCase().startsWith("application/json"))throw new Error(`Resource verification expected application/json: ${f}`);try{JSON.parse(p.body);}catch{throw new Error(`Resource verification received invalid JSON: ${f}`)}}}for(let l of i.expectedMissing){let u=new URL(l),f=new URL(`${u.pathname}${u.search}`,s),p=await Tn(f,e.ignoreHttpsErrors);if(p.status>=200&&p.status<300)throw new Error(`Deleted content is still publicly available: ${f}`)}}async function ql(e){let t=await F.readFile(e.candidateManifest,"utf8");JSON.parse(t);let r=`${e.trustedManifest}.${process.pid}.tmp`;await F.writeFile(r,t,"utf8"),await F.rename(r,e.trustedManifest);}async function Wl(e,t){try{let r=JSON.parse(await F.readFile(e.candidateManifest,"utf8"));if([...Object.values(r.pages??{}),...Object.values(r.assets??{})].some(s=>s?.lastSeenRunId===t))return "resumed"}catch(r){if(r.code!=="ENOENT")throw new Error(`The content-sync candidate manifest is invalid: ${r instanceof Error?r.message:String(r)}`,{cause:r})}return await F.copyFile(e.trustedManifest,e.candidateManifest).catch(r=>{throw new Error(`A trusted crawl manifest is required before content-sync: ${r instanceof Error?r.message:String(r)}`,{cause:r})}),"initialized"}async function st(e,t,r,n,s={},o=0,a=async()=>{}){t.phase=r,await _n(e,t),await Vn(e,{schemaVersion:1,jobId:t.jobId,phase:r,completedItems:n,totalItems:n,attempt:o,updatedAt:new Date().toISOString(),details:s}),await Ke(C.dirname(e.state),"content-sync-checkpoint",{id:t.jobId},`Content-sync checkpoint completed: ${r}.`,{phase:r,completedItems:n,totalItems:n,attempt:o,...s}),await a(r,t);}async function Nl(e,t={}){let r={loadConfig:Ie,resolveRuleContext:En,runCrawl:Co,runDeploy:Oo,runInvalidate:Fo,verifyDeployment:Ll,promoteCandidateManifest:ql,clearDeployPlan:Qe,afterCheckpoint:async()=>{},...t},n=An(),s=Nt(n),o=await Ul(n,e),a=await r.loadConfig(),c=jl(a,String(o.ruleId)),i=await r.resolveRuleContext(a,c);if(o.coalesceKey&&o.coalesceKey!==i.coalesceKey)throw new Error("Queued content-sync demand no longer matches the active rule scope.");let l=(await Mr(s)).entries[i.coalesceKey];if(!l||l.scopeFingerprint!==i.scopeFingerprint||l.targetFingerprint!==i.targetFingerprint||l.releaseFingerprint!==i.releaseFingerprint)throw await Ke(n,"content-sync-baseline-rejected",o,"Content-sync requires a new verified full or incremental release baseline.",{ruleId:c.id,reason:l?"mismatch":"missing"}),new Error("Content-sync baseline is missing or stale. Run a successful normal publish first.");let u=await jr(s),f=await i.client.head({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites});if(u&&u.jobId!==o.id)throw new Error("Another immutable content-sync range is still active.");if(u||(u={schemaVersion:1,jobId:o.id,ruleId:String(c.id||""),consumerId:i.consumerId,coalesceKey:i.coalesceKey,scopeFingerprint:i.scopeFingerprint,targetFingerprint:i.targetFingerprint,baselineId:l.baselineId,fromSequence:f.committedSequence,toSequence:f.headSequence,phase:"claimed",impactHash:null,startedAt:new Date().toISOString(),updatedAt:new Date().toISOString()},await st(s,u,"claimed",0,{fromSequence:u.fromSequence,toSequence:u.toSequence},0,r.afterCheckpoint),await Ke(n,"content-sync-range-claimed",o,"Content-sync claimed a closed journal range.",{fromSequence:u.fromSequence,toSequence:u.toSequence})),u.fromSequence===u.toSequence){let h=await _t(s);h.rules[i.coalesceKey]={ruleId:String(c.id||""),consumerId:i.consumerId,coalesceKey:i.coalesceKey,committedSequence:u.toSequence,observedHeadSequence:f.headSequence,lag:Math.max(0,f.headSequence-u.toSequence),lastSuccessfulJobId:o.id,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:false,retryAttempt:0,nextRetryAt:null,lastError:null},await Bt(s,h),await Fr(s);return}let p=await Bn(s);if(!Pt(u.phase,"impact-planned")){let h=await i.client.events({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites,afterSequence:u.fromSequence,throughSequence:u.toSequence}),y=$r({events:h,scope:i.scope,sourceOrigin:a.sourceOrigin}),b=await i.client.resolveImpactFamilies(y,i.scope.includeSubsites);p=Ln({jobId:o.id,ruleId:String(c.id||""),consumerId:i.consumerId,coalesceKey:i.coalesceKey,scopeFingerprint:i.scopeFingerprint,targetFingerprint:i.targetFingerprint,baselineId:l.baselineId,sourceOrigin:a.sourceOrigin,scope:i.scope,fromSequence:u.fromSequence,toSequence:u.toSequence,events:h,resolvedArchiveFamilies:b,sitemapUrls:kt(a.sitemapPaths)}),await Hn(s,p),u.impactHash=p.impactHash,await st(s,u,"impact-planned",h.length,{eventCount:h.length,foldedCount:p.foldedCount,impactHash:p.impactHash},0,r.afterCheckpoint),await Ke(n,"content-sync-impact-planned",o,"Content-sync persisted an immutable impact plan.",{impactHash:p.impactHash,eventCount:h.length});}if(!p||p.jobId!==o.id||u.impactHash!==p.impactHash)throw new Error("The immutable content-sync impact plan is missing or mismatched.");if(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH=s.candidateManifest,!Pt(u.phase,"rendered")){let h=await Wl(s,o.id);await Ke(n,h==="resumed"?"content-sync-render-resumed":"content-sync-render-initialized",o,h==="resumed"?"Content-sync resumed its candidate crawl manifest.":"Content-sync initialized a candidate crawl manifest.",{impactHash:p.impactHash}),await r.runCrawl(["--content-sync-plan",s.impact]),await st(s,u,"rendered",p.directRenderUrls.length+p.archiveFamilyUrls.length+p.resourceRenderUrls.length,{impactHash:p.impactHash},o.attempt??0,r.afterCheckpoint);}let g=i.deploymentProfile?["--profile",i.deploymentProfile]:[];if(Pt(u.phase,"deployed")||(await r.runDeploy([...g,"--content-sync"]),await st(s,u,"deployed",1,{impactHash:p.impactHash},0,r.afterCheckpoint),await Ke(n,"content-sync-deployed",o,"Content-sync targeted deployment completed.",{impactHash:p.impactHash})),Pt(u.phase,"invalidated")?Pt(u.phase,"verified")||await r.runInvalidate([...g,"--content-sync"]):(await r.runInvalidate([...g,"--content-sync"]),await st(s,u,"invalidated",1,{impactHash:p.impactHash},0,r.afterCheckpoint)),Pt(u.phase,"verified")||(await r.verifyDeployment(a,i,p,s.candidateManifest),await r.promoteCandidateManifest(s),await st(s,u,"verified",1,{impactHash:p.impactHash},0,r.afterCheckpoint)),f=await i.client.head({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites}),f.committedSequence===u.fromSequence)await i.client.acknowledge({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,expectedSequence:u.fromSequence,sequence:u.toSequence,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites});else if(f.committedSequence!==u.toSequence)throw new Error("Content-sync acknowledgement cursor is in an unexpected state.");await st(s,u,"acknowledged",1,{sequence:u.toSequence},0,r.afterCheckpoint),await Ke(n,"content-sync-cursor-acknowledged",o,"Content-sync committed its journal cursor after verification.",{sequence:u.toSequence});let w=await i.client.head({consumerId:i.consumerId,scopeFingerprint:i.scopeFingerprint,baselineId:l.baselineId,postTypes:i.scope.postTypes,includeSubsites:i.scope.includeSubsites}),m=await _t(s);m.rules[i.coalesceKey]={ruleId:String(c.id||""),consumerId:i.consumerId,coalesceKey:i.coalesceKey,committedSequence:u.toSequence,observedHeadSequence:w.headSequence,lag:Math.max(0,w.headSequence-u.toSequence),lastSuccessfulJobId:o.id,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:w.headSequence>u.toSequence,retryAttempt:0,nextRetryAt:null,lastError:null},await Bt(s,m),await r.clearDeployPlan(a),await F.rm(C.join(n,"content-sync-invalidation.json"),{force:true}),await F.rm(s.candidateManifest,{force:true}),await Fr(s);}async function qo(e=process.argv.slice(2)){let r=e.indexOf("--capture-baseline-cutoffs");if(r>=0){let a=String(e[r+1]||"").trim();if(!a)throw new Error("--capture-baseline-cutoffs requires a release job ID.");await Dl(a);return}let n=e.indexOf("--establish-baselines");if(n>=0){let a=String(e[n+1]||"").trim();if(!a)throw new Error("--establish-baselines requires a release job ID.");await Fl(a);return}let s=e.indexOf("--job-id"),o=s>=0?String(e[s+1]||"").trim():"";if(!o)throw new Error("Content-sync requires --job-id.");await Nl(o);}qo().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exit(1);});
|