@smart-cloud/publisher-exporter 1.1.58 → 1.1.60
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 +2 -0
- package/dist/content-sync.js +10 -10
- package/dist/crawl.js +8 -8
- package/dist/deploy.js +4 -4
- package/dist/invalidate.js +3 -3
- package/dist/queue-runner.js +3 -3
- package/package.json +1 -1
package/dist/content-sync.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import A from'fs/promises';import Rs from'http';import jn from'https';import S from'path';import or,{createHash}from'crypto';import {request,chromium}from'playwright';import {gunzipSync}from'zlib';import Vs from'fast-glob';import {availableParallelism}from'os';import {Worker}from'worker_threads';import {S3Client,ListObjectsV2Command,HeadObjectCommand,GetObjectCommand,DeleteObjectsCommand}from'@aws-sdk/client-s3';import {Upload}from'@aws-sdk/lib-storage';import ca from'mime-types';import {CloudFrontClient,waitUntilInvalidationCompleted,CreateInvalidationCommand}from'@aws-sdk/client-cloudfront';var Ss=new Set(["post-type","taxonomy","author","date","posts-page","listing"]);function ke(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))].sort()}function bs(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))]}function Ps(e){return new URL(e).pathname.split("/").filter(Boolean).some(n=>{try{return decodeURIComponent(n).endsWith("__trashed")}catch{return n.endsWith("__trashed")}})}function qt(e){return Array.isArray(e)?e.map(qt):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,qt(n)])):e}function vs(e){return JSON.stringify(qt(e))}function ue(e){return createHash("sha256").update(vs(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 _t(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 he(e,t){let n=new URL(_t(e)),r=new URL(t,`${n.toString().replace(/\/$/,"")}/`);if(r.origin!==n.origin)throw new Error(`Content-sync URL is outside the source origin: ${t}`);let s=n.pathname.replace(/\/+$/,"");if(s&&r.pathname!==s&&!r.pathname.startsWith(`${s}/`))throw new Error(`Content-sync URL is outside the source site path: ${t}`);return r.hash="",r.toString()}function Je(e){let t=ke((e.postTypes??[]).map(r=>String(r).toLowerCase().replace(/[^a-z0-9_-]/g,"")));if(t.length===0)throw new Error("Content-sync requires at least one public post type.");let n=ke((e.listingPaths??[]).map(r=>{let s=String(r).trim();if(!s)return "";let i=new URL(s,"https://content-sync.invalid/");if(i.origin!=="https://content-sync.invalid"&&/^https?:\/\//i.test(s))throw new Error("Content-sync listing routes must be same-site paths.");let a=`/${i.pathname.replace(/^\/+|\/+$/g,"")}`;return a==="/"?"/":`${a}/`}));return {postTypes:t,listingPaths:n,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 Dn(e,t,n){return ue({schemaVersion:1,sourceOrigin:_t(e),ruleId:t.trim(),scope:Je(n)})}function Fn(e){return ue({schemaVersion:1,...e})}function On(e){let t=String(e.siteId??"").trim()||String(e.accountId??"").trim()||_t(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,i)=>s.sequence-i.sequence),n=new Map,r=-1;for(let s of t){if(!Number.isSafeInteger(s.sequence)||s.sequence<=r)throw new Error("Content-sync journal events are not strictly ordered.");if(r=s.sequence,!Number.isSafeInteger(s.blogId)||s.blogId<1)throw new Error("Content-sync journal event has an invalid multisite identity.");let i=`${s.blogId}:${s.postType}:${s.postId}`,a=n.get(i);if(!a){n.set(i,{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 [...n.values()].sort((s,i)=>s.fromSequence-i.fromSequence)}function En(e){return e?.status==="publish"&&!!e.url}function Cs(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 Nt(e){let t=Je(e.scope),n=new Map;Un(e.events);for(let r of e.events)for(let s of [r.before,r.after])for(let i of s?.archiveFamilies??[]){if(!Ss.has(i.kind)||!Cs(i.kind,t))continue;let a={...i,url:he(e.sourceOrigin,i.url)};n.set(`${a.kind}|${a.url}`,a);}for(let r of t.listingPaths){let s=he(e.sourceOrigin,r);n.set(`listing|${s}`,{kind:"listing",url:s});}return [...n.values()].sort((r,s)=>r.url.localeCompare(s.url))}function Ln(e){let t=Je(e.scope),n=Un(e.events),r=new Set,s=new Set,i=new Map(Nt({events:e.events,scope:t,sourceOrigin:e.sourceOrigin}).map(u=>[`${u.kind}|${u.url}`,u]));for(let u of n){let p=u.before,f=u.after,g=En(p),y=En(f);y&&f.url&&r.add(he(e.sourceOrigin,f.url)),g&&p.url&&(!y||p.url!==f.url)&&s.add(he(e.sourceOrigin,p.url));}let a=new Map(e.resolvedArchiveFamilies.map(u=>[`${u.kind}|${he(e.sourceOrigin,u.url)}`,{...u,url:he(e.sourceOrigin,u.url),pageUrls:ke(u.pageUrls.map(p=>he(e.sourceOrigin,p)))}])),c=[...i.entries()].map(([u,p])=>{let f=a.get(u);if(!f)throw new Error(`WordPress did not resolve archive family ${u}.`);return {...p,...f}}).sort((u,p)=>u.url.localeCompare(p.url)),o=ke(c.flatMap(u=>u.pageUrls)),l=t.includeSitemapChain?bs(e.sitemapUrls.map(u=>he(e.sourceOrigin,u))):[],d={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:n.length,directRenderUrls:ke([...r]),archiveFamilyUrls:o,sitemapUrls:l,deleteUrls:ke([...s]),archiveFamilies:c};return {...d,impactHash:ue(d)}}function Ve(e){let{impactHash:t,...n}=e;if(e.schemaVersion!==1||!t)throw new Error("Invalid content-sync impact plan schema.");if(ue(n)!==t)throw new Error("Content-sync impact plan hash mismatch.");for(let r of [...e.directRenderUrls,...e.deleteUrls])if(Ps(r))throw new Error(`Content-sync impact contains a WordPress trash alias instead of the last public URL: ${r}`)}var xs="wp-json/smartcloud-static-publisher/v1/content-sync/",Is=25*1024*1024,ut=class extends Error{status;code;constructor(t,n,r){super(r),this.name="ContentSyncApiError",this.status=t,this.code=n;}},lt=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){let n=this.options.sourceOrigin.replace(/\/+$/,"")+"/";return new URL(`${xs}${t}`,n)}async post(t,n){let r=this.endpoint(t),s=Buffer.from(JSON.stringify(n),"utf8"),i=r.protocol==="https:"?jn:Rs,a=r.protocol==="https:"?new jn.Agent({rejectUnauthorized:!this.options.ignoreHttpsErrors}):void 0;return new Promise((c,o)=>{let l=i.request(r,{method:"POST",agent:a,headers:{"content-type":"application/json","content-length":String(s.byteLength),"x-static-publisher-token":this.options.runtimeToken},timeout:this.options.timeoutMs},d=>{let u=[],p=0;d.on("data",f=>{if(p+=f.byteLength,p>Is){d.destroy(new Error("Content-sync API response exceeded the size limit."));return}u.push(f);}),d.on("error",o),d.on("end",()=>{let f=Buffer.concat(u).toString("utf8"),g;try{g=f?JSON.parse(f):{};}catch{o(new ut(d.statusCode??500,"invalid-json","Content-sync API returned invalid JSON."));return}let y=d.statusCode??500;if(y<200||y>=300){o(new ut(y,String(g.code??"request-failed"),String(g.message??`Content-sync API request failed (${y}).`)));return}c(g);});});l.on("timeout",()=>l.destroy(new Error(`Content-sync API request timed out: ${t}`))),l.on("error",o),l.end(s);})}async head(t){return this.post("head",t)}async unboundHead(t,n){return this.post("head",{postTypes:t,includeSubsites:n})}async events(t){let n=[],r=t.afterSequence,s=new Set(t.postTypes);for(;r<t.throughSequence;){let i=await this.post("events",{...t,afterSequence:r,limit:250});if(i.fromSequence!==r||i.throughSequence!==t.throughSequence||i.nextSequence<r||i.nextSequence>t.throughSequence)throw new Error("Content-sync API returned an inconsistent event page.");if(!Array.isArray(i.items))throw new Error("Content-sync API returned a malformed event page.");let a=r;for(let c of i.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(i.items.length>0&&i.nextSequence!==a)throw new Error("Content-sync API event cursor does not match the final returned event.");if(n.push(...i.items),!i.hasMore)break;if(i.nextSequence===r)throw new Error("Content-sync API event pagination did not advance.");r=i.nextSequence;}if(t.throughSequence>t.afterSequence&&n.at(-1)?.sequence!==t.throughSequence)throw new Error("Content-sync API omitted the claimed journal high-water event.");return n}async resolveImpactFamilies(t,n){let r=await this.post("impact",{families:t,includeSubsites:n});return Array.isArray(r.families)?r.families:[]}async releaseFingerprint(t=false){let n=await this.post("fingerprint",{includeSubsites:t}),r=String(n.fingerprint||"").trim();if(!/^[a-f0-9]{64}$/.test(r))throw new Error("WordPress returned an invalid release fingerprint.");return r}async establishBaseline(t){return this.post("baseline",t)}async acknowledge(t){return this.post("ack",t)}};function dt(e){let t=S.resolve(e);return {state:S.join(t,"content-sync-state.json"),current:S.join(t,"content-sync-current.json"),impact:S.join(t,"content-sync-impact-plan.json"),checkpoint:S.join(t,"content-sync-checkpoint.json"),baseline:S.join(t,"content-sync-baseline.json"),activeRules:S.join(t,"content-sync-active-rules.json"),releaseCutoff:S.join(t,"content-sync-release-cutoff.json"),candidateManifest:S.join(t,"content-sync-candidate-manifest.json"),trustedManifest:S.join(t,"crawl-manifest.json"),invalidation:S.join(t,"content-sync-invalidation.json"),deployPlan:S.join(t,"deploy-plan.json")}}async function Bt(e){let t=await Ke(e.releaseCutoff);if(t===null)return {schemaVersion:1,updatedAt:"",entries:{}};let n=t;if(n.schemaVersion!==1||typeof n.updatedAt!="string"||!n.entries||typeof n.entries!="object"||Array.isArray(n.entries))throw new Error("Invalid content-sync release-cutoff store.");return n}async function qn(e,t){await Ee(e.releaseCutoff,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Ee(e,t){await A.mkdir(S.dirname(e),{recursive:true});let n=`${e}.${process.pid}.${Date.now()}.tmp`;await A.writeFile(n,JSON.stringify(t,null,2),"utf8"),await A.rename(n,e);}async function Ke(e){try{return JSON.parse(await A.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 Wt(e){let t=await Ke(e.baseline);if(t===null)return {schemaVersion:1,updatedAt:"",entries:{}};let n=t;if(n.schemaVersion!==1||typeof n.updatedAt!="string"||!n.entries||typeof n.entries!="object"||Array.isArray(n.entries))throw new Error("Invalid content-sync baseline store.");return n}async function _n(e,t){await Ee(e.baseline,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Ht(e){let t=await Ke(e.current);if(t===null)return null;let n=t;if(n.schemaVersion!==1||typeof n.jobId!="string"||typeof n.phase!="string"||!Number.isSafeInteger(n.fromSequence)||!Number.isSafeInteger(n.toSequence))throw new Error("Invalid content-sync current-range state.");return n}async function Nn(e,t){await Ee(e.current,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Bn(e){let t=await Ke(e.impact);if(t===null)return null;let n=t;return Ve(n),n}async function Wn(e,t){Ve(t),await Ee(e.impact,t);}async function Hn(e,t){await Ee(e.checkpoint,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function pt(e){let t=await Ke(e.state);if(t===null)return {schemaVersion:1,updatedAt:"",rules:{}};let n=t;if(n.schemaVersion!==1||typeof n.updatedAt!="string"||!n.rules||typeof n.rules!="object"||Array.isArray(n.rules))throw new Error("Invalid content-sync state store.");return n}async function gt(e,t){await Ee(e.state,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function zt(e){await Promise.all([e.current,e.checkpoint].map(async t=>{try{await A.unlink(t);}catch(n){if(n.code!=="ENOENT")throw n}}));}async function zn(e,t){let n=await Ht(e);return !n||n.coalesceKey!==t?false:(await Promise.all([e.current,e.checkpoint,e.impact,e.candidateManifest,e.invalidation,e.deployPlan].map(async r=>{try{await A.unlink(r);}catch(s){if(s.code!=="ENOENT")throw s}})),true)}var Qt=["/sitemap_index.xml","/wp-sitemap.xml","/sitemap.xml"];function Ge(e){let t=new Set;for(let n of [...e,...Qt]){let r=String(n||"").trim();r&&t.add(r);}return [...t]}function Jt(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function Qn(e){if(!e||!/^https?:\/\//i.test(e))return false;try{return Jt(new URL(e))}catch{return false}}function Vn(e){let t=e.trim();return t==="."?".":t.replace(/\/$/,"")}function $s(e){let t=String(e??"").trim();if(!t)return "";let n=t;if(/^https?:\/\//i.test(n))try{n=new URL(n).pathname;}catch{return ""}if(n=n.split(/[?#]/,1)[0]?.replace(/\\/g,"/").trim()??"",!n)return "";let r=n.endsWith("/"),s=n.replace(/^\/+/,"").split("/").map(a=>a.replace(/[^A-Za-z0-9._-]/g,"")).filter(a=>a.length>0&&a!=="."&&a!=="..");if(s.length===0)return "";let i=`/${s.join("/")}`;return r&&S.extname(i)===""&&(i+="/"),i==="/"?"":i}function Vt(e){return !e||typeof e!="object"?{}:Object.fromEntries(Object.entries(e).map(([t,n])=>[t.trim(),String(n??"")]).filter(([t])=>t.length>0))}function Es(e){if(!e||typeof e!="object")return {};let t={};for(let[n,r]of Object.entries(e)){let s=n.trim();if(!s||!r||typeof r!="object")continue;let i=r,a={};if(typeof i.targetOrigin=="string"){let o=Vn(i.targetOrigin);o&&(a.targetOrigin=o);}let c=Vt(i.extraReplacements);if(Object.keys(c).length>0&&(a.extraReplacements=c),i.s3&&typeof i.s3=="object"){let o={},l=i.s3;typeof l.bucket=="string"&&(o.bucket=l.bucket.trim()),typeof l.prefix=="string"&&(o.prefix=l.prefix.trim()),typeof l.region=="string"&&(o.region=l.region.trim()),typeof l.htmlCacheControl=="string"&&(o.htmlCacheControl=l.htmlCacheControl.trim()),typeof l.assetCacheControl=="string"&&(o.assetCacheControl=l.assetCacheControl.trim()),Object.keys(o).length>0&&(a.s3=o);}if(i.cloudFront&&typeof i.cloudFront=="object"){let o={},l=i.cloudFront;typeof l.distributionId=="string"&&(o.distributionId=l.distributionId.trim()),Array.isArray(l.invalidationPaths)&&(o.invalidationPaths=l.invalidationPaths.map(d=>String(d??"").trim()).filter(d=>d.length>0)),Object.keys(o).length>0&&(a.cloudFront=o);}t[s]=a;}return t}function Gt(e){return e==="PROFESSIONAL"||e==="AGENCY"?e:void 0}function Ms(e,t){if(!e||typeof e!="object")return null;let n=e,r=n.command;if(r!=="publish"&&r!=="crawl"&&r!=="deploy"&&r!=="invalidate"&&r!=="retry-timeouts"&&r!=="url"&&r!=="content-sync")return null;let s=Number.parseInt(String(n.intervalMinutes??"0"),10);if(!Number.isFinite(s)||s<1)return null;let i=String(n.id??`${r}-${t+1}`).trim();if(!i)return null;let a=String(n.deploymentProfile??"").trim(),c=String(n.url??"").trim(),o=Array.isArray(n.postTypes)?[...new Set(n.postTypes.map(d=>String(d??"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"")).filter(Boolean))]:[],l=Array.isArray(n.listingPaths)?[...new Set(n.listingPaths.map(d=>String(d??"").trim()).filter(Boolean))]:[];return r==="content-sync"&&o.length===0?null:{id:i,enabled:n.enabled!==false,command:r,intervalMinutes:s,...r==="publish"||r==="crawl"?{crawlMode:n.crawlMode==="incremental"?"incremental":"full"}:{},...(r==="publish"||r==="deploy"||r==="invalidate"||r==="content-sync")&&a?{deploymentProfile:a}:{},...c?{url:c}:{},...o.length>0?{postTypes:o}:{},...l.length>0?{listingPaths:l}:{},...typeof n.includeSubsites=="boolean"?{includeSubsites:n.includeSubsites}:{},...typeof n.includePostTypeArchives=="boolean"?{includePostTypeArchives:n.includePostTypeArchives}:{},...typeof n.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:n.includeTaxonomyArchives}:{},...typeof n.includeAuthorArchives=="boolean"?{includeAuthorArchives:n.includeAuthorArchives}:{},...typeof n.includeDateArchives=="boolean"?{includeDateArchives:n.includeDateArchives}:{},...typeof n.includePostsPage=="boolean"?{includePostsPage:n.includePostsPage}:{},...typeof n.includeSitemapChain=="boolean"?{includeSitemapChain:n.includeSitemapChain}:{}}}function Kn(e){let t=e&&typeof e=="object"?e:{},n=Array.isArray(t.rules)?t.rules.map((r,s)=>Ms(r,s)).filter(r=>!!r):[];return {enabled:t.enabled===true,timezone:typeof t.timezone=="string"&&t.timezone.trim()!==""?t.timezone.trim():"UTC",rules:n}}function Ds(e){if(!e||typeof e!="object")return;let t=e,n={};for(let s of ["accountId","siteId"]){let i=t[s];typeof i=="string"&&i.trim()!==""&&(n[s]=i.trim());}let r=Number(t.lastUpdate??0);return Number.isFinite(r)&&r>0&&(n.lastUpdate=Math.floor(r)),t.subscriber===true&&(n.subscriber=true),Object.keys(n).length>0?n:void 0}function Zt(e){let t=e&&typeof e=="object"?e:{},n=String(t.accountId??"").trim(),r=String(t.siteId??"").trim(),s=t.subscriber===true,i=Ds(t.siteSettings),a={...i??{},...n?{accountId:i?.accountId??n}:{},...r?{siteId:i?.siteId??r}:{},...i?.subscriber===true||s?{subscriber:true}:{}},c={},o=String(t.apiBase??"").trim();o&&(c.apiBase=o);let l=String(t.runtimeToken??t.nonce??"").trim();l&&(c.runtimeToken=l);let d=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();d&&(c.virtualAssetBaseUrl=d),Object.keys(a).length>0&&(c.siteSettings=a);let u=Gt(t.subscriptionType);return u&&(c.subscriptionType=u),c}function Fs(e){try{let t=new URL(e);globalThis.location=t;}catch{}}function Gn(e){return typeof e=="string"?e:e instanceof URL?e.toString():e.url}function Os(e,t){let n=new Headers(e instanceof Request?e.headers:void 0);if(t?.headers)for(let[r,s]of new Headers(t.headers).entries())n.set(r,s);return n}async function Zn(e,t,n=5){let r=new URL(Gn(e)),s=String(t?.method??(e instanceof Request?e.method:"GET")).toUpperCase(),i=r.protocol==="http:"?Rs:jn,a=Os(e,t);return await new Promise((c,o)=>{let l=i.request(r,{method:s,headers:Object.fromEntries(a.entries()),...r.protocol==="https:"?{rejectUnauthorized:false}:{}},d=>{let u=[];d.on("data",p=>{u.push(Buffer.isBuffer(p)?p:Buffer.from(p));}),d.on("error",o),d.on("end",()=>{let p=d.statusCode??0,f=d.headers.location;if(n>0&&f&&[301,302,303,307,308].includes(p)){c(Zn(new URL(f,r),{method:p===303?"GET":s},n-1));return}let g=new Headers;for(let[y,h]of Object.entries(d.headers))Array.isArray(h)?g.set(y,h.join(", ")):typeof h=="string"&&g.set(y,h);c(new Response(Buffer.concat(u),{status:p,statusText:d.statusMessage??"",headers:g}));});});l.on("error",o),l.end();})}function Us(e){let t=Zt(e.wpsuite),n={...t.siteSettings??{},...t.siteSettings?.subscriber===true||t.subscriptionType==="PROFESSIONAL"||t.subscriptionType==="AGENCY"?{subscriber:true}:{}},r=String(n.accountId??"").trim(),s=String(n.siteId??"").trim(),i=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();if(e.wpsuite={...t.apiBase?{apiBase:t.apiBase}:{},...t.runtimeToken?{runtimeToken:t.runtimeToken}:{},...i?{virtualAssetBaseUrl:i}:{},...Object.keys(n).length>0?{siteSettings:n}:{},...t.subscriptionType?{subscriptionType:t.subscriptionType}:{}},!r||!s||!i)return false;Fs(e.sourceOrigin);let a=globalThis,o={...a.WpSuite??{},siteSettings:n,uploadUrl:i};return t.apiBase&&(o.apiBase=t.apiBase),a.WpSuite=o,true}async function Ls(e){let t=String(e.wpsuite?.virtualAssetBaseUrl??e.wpsuite?.uploadUrl??"").trim();if(!Us(e)){let s=e.wpsuite?.siteSettings,i=[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): ${i.join(", ")}.`,requests:[]}}}let n=globalThis.fetch,r=[];try{typeof n=="function"&&/^https?:\/\//i.test(t)&&(globalThis.fetch=(async(o,l)=>{let d=Gn(o);if(d.startsWith(t)){let u=(()=>{try{return new URL(d).pathname}catch{return d}})();try{let p=e.ignoreHttpsErrors&&d.startsWith("https://")?await Zn(o,l):await n(o,l);return r.push({path:u,status:p.status,ok:p.ok,error:null}),p}catch(p){throw r.push({path:u,status:null,ok:!1,error:p instanceof Error?p.message:String(p)}),p}}return n(o,l)}));let{getConfig:s}=await import('@smart-cloud/wpsuite-core'),i=await s("publisher"),a=i&&typeof i=="object"?i:null,c=Gt(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:r}}}catch(s){return {remote:null,diagnostic:{status:"unavailable",virtualAssetBaseUrl:t,subscriptionType:null,error:s instanceof Error?s.message:String(s),requests:r}}}finally{typeof n=="function"&&(globalThis.fetch=n);}}function js(e,t){let n=Es(t?.deploymentProfiles),r=String(t?.defaultDeploymentProfile??"").trim(),s=n[r]?r:"",i=Gt(t?.subscriptionType),a=Zt(e.wpsuite);return {...e,scheduler:Kn(t?.scheduler),deploymentProfiles:n,defaultDeploymentProfile:s,...i?{subscriptionType:i}:{},wpsuite:{...a,...a.siteSettings||i?{siteSettings:{...a.siteSettings??{},...a.siteSettings?.subscriber===true||i==="PROFESSIONAL"||i==="AGENCY"?{subscriber:true}:{}}}:{},...i?{subscriptionType:i}:{}}}}function Kt(e,t){let r=String(e||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!r)return t;let s=r.split("/").map(i=>i.trim()).filter(i=>i.length>0&&i!=="."&&i!=="..");return s.length>0?s.join("/"):t}function qs(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?S.resolve(e):""}function Jn(e,t,n){let r=String(t||"").trim();return r&&S.isAbsolute(r)?S.resolve(r):S.resolve(e,Kt(r,n))}async function ie(e,t={}){let n=String(e??"").trim()||process.env.PUBLISHER_CONFIG||"publisher.config.json",r=await A.readFile(n,"utf8"),s=JSON.parse(r);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=$s(s.generated404RequestPath),s.sitemapPaths||=[...Qt],s.allowedAssetHosts||=[],s.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],s.blockedPathPrefixes||=[],s.blockedSearchFragments||=[],s.concurrency||=1,s.maxPages||=0,s.extraReplacements=Vt(s.extraReplacements),s.postCrawlCopyMap=Vt(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=Number(s.assetDownloadConcurrency)>0?Number(s.assetDownloadConcurrency):s.concurrency,s.rewriteConcurrency=Number(s.rewriteConcurrency)>0?Number(s.rewriteConcurrency):s.assetDownloadConcurrency,s.wpsuite=Zt(s.wpsuite),s.scheduler=Kn(void 0),s.deploymentProfiles={},s.defaultDeploymentProfile="",s.deploymentTargetOverride=String(s.deploymentTargetOverride??"").trim();let i=await Ls(s);t.onRemotePublisherConfigDiagnostic?.(i.diagnostic);let a=js(s,i.remote),c=qs(),o=c?S.resolve(c,".."):"";return o?(a.outputDir=Jn(o,a.outputDir,"export"),a.logDir=Jn(o,a.logDir,"logs")):(S.isAbsolute(a.outputDir)||(a.outputDir=Kt(a.outputDir,"export")),S.isAbsolute(a.logDir)||(a.logDir=Kt(a.logDir,"logs"))),a}var _s=".deploy-plan.json",Ns="deploy-plan.json",Bs=".crawl-incomplete.json",Ws="crawl-incomplete.json";function Yn(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?S.resolve(e):""}function Xn(e){let t=String(e||"").replace(/\\/g,"/").replace(/^\/+/,"").trim(),n=S.posix.normalize(t);return !t||!n||n==="."||/^[a-zA-Z]:/.test(n)||n.startsWith("../")||n===".."?null:n}function Hs(e){let t=String(e||"").trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("*")||t.includes("#"))return null;try{let n=new URL(t,"https://content-sync.invalid");return n.origin!=="https://content-sync.invalid"?null:`${S.posix.normalize(n.pathname)}${n.search}`}catch{return null}}function ye(e){return [...new Set(e.map(Xn).filter(t=>t!==null))]}function er(e,t){let n={generatedAt:String(t.generatedAt||new Date().toISOString()),outputDir:S.resolve(e.outputDir),runMode:t.runMode,crawlMode:t.crawlMode,fullSyncRequired:!!t.fullSyncRequired,changedFiles:ye(t.changedFiles||[]),deletedFiles:ye(t.deletedFiles||[]),rewriteTargets:ye(t.rewriteTargets||[])};return t.schemaVersion===2?{...n,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(r=>String(r||"").trim()).filter(r=>{try{let s=new URL(r);return s.protocol==="http:"||s.protocol==="https:"}catch{return false}}))],uploadGroups:{assets:ye(t.uploadGroups?.assets||[]),content:ye(t.uploadGroups?.content||[]),listings:ye(t.uploadGroups?.listings||[]),sitemapLeaves:ye(t.uploadGroups?.sitemapLeaves||[]),sitemapIndexes:ye(t.uploadGroups?.sitemapIndexes||[])},invalidationPaths:[...new Set((t.invalidationPaths||[]).map(Hs).filter(r=>r!==null))].sort()}:{schemaVersion:1,...n,runMode:t.runMode}}function zs(e){if(!e||typeof e!="object")return false;let t=e;if(t.schemaVersion===2){let n=t;return n.runMode==="content-sync"&&n.crawlMode==="incremental"&&n.fullSyncRequired===false&&typeof n.generatedAt=="string"&&typeof n.outputDir=="string"&&typeof n.consumerId=="string"&&n.consumerId.trim()!==""&&Number.isSafeInteger(n.fromSequence)&&Number.isSafeInteger(n.toSequence)&&Number(n.toSequence)>=Number(n.fromSequence)&&typeof n.impactHash=="string"&&/^[a-f0-9]{64}$/.test(n.impactHash)&&Array.isArray(n.resolvedSitemapUrls)&&Array.isArray(n.changedFiles)&&Array.isArray(n.deletedFiles)&&Array.isArray(n.rewriteTargets)&&!!n.uploadGroups&&Array.isArray(n.uploadGroups.assets)&&Array.isArray(n.uploadGroups.content)&&Array.isArray(n.uploadGroups.listings)&&Array.isArray(n.uploadGroups.sitemapLeaves)&&Array.isArray(n.uploadGroups.sitemapIndexes)&&Array.isArray(n.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)}function Yt(e){let t=S.join(S.resolve(e.outputDir),_s),n=Yn();return n?[S.join(n,Ns),t]:[t]}function Xt(e){let t=S.join(S.resolve(e.outputDir),Bs),n=Yn();return n?[S.join(n,Ws),t]:[t]}function Se(e,t){let n=S.resolve(e),r=S.resolve(t),s=S.relative(n,r).replace(/\\/g,"/");return Xn(s)}async function Me(e){let t=S.resolve(e.outputDir);for(let n of Yt(e))try{let r=await A.readFile(n,"utf8"),s=JSON.parse(r);if(!zs(s)||S.resolve(s.outputDir)!==t)continue;return er(e,s)}catch{}return null}async function en(e,t){let n=er(e,t);for(let r of Yt(e)){await A.mkdir(S.dirname(r),{recursive:true});let s=`${r}.${process.pid}.${Date.now()}.tmp`;await A.writeFile(s,JSON.stringify(n,null,2),"utf8"),await A.rename(s,r);}}async function De(e){for(let t of Yt(e))try{await A.unlink(t);}catch(n){if(n.code!=="ENOENT")throw n}}async function tr(e,t){let n={schemaVersion:1,startedAt:String(t.startedAt||new Date().toISOString()),outputDir:S.resolve(e.outputDir)};for(let r of Xt(e)){await A.mkdir(S.dirname(r),{recursive:true});let s=`${r}.${process.pid}.tmp`;await A.writeFile(s,JSON.stringify(n,null,2),"utf8"),await A.rename(s,r);}}async function nr(e){let t=S.resolve(e.outputDir);for(let n of Xt(e)){let r;try{r=await A.readFile(n,"utf8");}catch(i){if(i.code==="ENOENT")continue;throw i}let s;try{s=JSON.parse(r);}catch{throw new Error(`Invalid incomplete crawl marker: ${n}`)}if(s.schemaVersion!==1||typeof s.startedAt!="string"||typeof s.outputDir!="string"||S.resolve(s.outputDir)!==t)throw new Error(`Invalid incomplete crawl marker: ${n}`);return {schemaVersion:1,startedAt:s.startedAt,outputDir:t}}return null}async function rr(e){for(let t of Xt(e))try{await A.unlink(t);}catch(n){if(n.code!=="ENOENT")throw n}}function Ye(e,t=10){return or.createHash("sha1").update(e).digest("hex").slice(0,t)}async function Qs(e){await A.mkdir(S.dirname(e),{recursive:true});}async function Xe(e,t,n){await Qs(e);let r=S.join(S.dirname(e),`.${S.basename(e)}.${process.pid}.${Date.now()}.${or.randomBytes(6).toString("hex")}.tmp`);try{typeof t=="string"?await A.writeFile(r,t,n??"utf8"):await A.writeFile(r,t),await A.rename(r,e);}catch(s){throw await A.unlink(r).catch(()=>{}),s}}function be(e){return [".html",".htm",".css",".js",".mjs",".json",".xml",".xsl",".txt",".svg",".map",".enc",".jws"].includes(S.extname(e).toLowerCase())}function de(e){return e.replace(/"/g,'"').replace(/"/g,'"').replace(/'/g,"'").replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function Fe(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function ft(e){return e.replace(/\//g,"\\/")}function sr(e){return e.replace(/\//g,"\\\\/")}function Js(e){try{let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")return null;let n=t.pathname==="/"&&!t.search&&!t.hash?"":`${t.pathname}${t.search}${t.hash}`;return `//${t.host}${n}`}catch{return null}}function ir(e,t,n){if(!t)return;e[t]=n;let r=ft(t),s=ft(n);e[r]=s;let i=sr(t),a=sr(n);e[i]=a;let c=Fe(t),o=Fe(n);e[c]=o;let l=Fe(r),d=Fe(s);e[l]=d;let u=Fe(i),p=Fe(a);e[u]=p;}function mt(e,t,n){ir(e,t,n);let r=Js(t);r&&r!==t&&ir(e,r,n);}function tn(e,t){let n=t.startsWith("/")?t:`/${t}`,r=(e||"").replace(/\/$/,"");return !r||r==="."||r==="/"?n:`${r}${n}`}function ar(e,t){try{return new URL(e,t==="."?"https://relative.invalid":t).pathname}catch{return e.startsWith("/")?e:`/${e.replace(/^\.\//,"")}`}}function cr(e,t,n){if(!t)return n;let r=S.dirname(S.resolve(t)),s=S.resolve(e,n.replace(/^\/+/,"")),i=S.relative(r,s).replace(/\\/g,"/");return i?(i.startsWith(".")||(i=`./${i}`),i):"."}var Ys=["wp-content/","wp-includes/","wp-admin/","wp-json/","_next/"],Xs=new Set([".html",".htm"]),ur="WPSuite.io Static Publisher",ei=ur.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function ti(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ni(e){return e.startsWith("//")||e.startsWith("\\/\\/")||e.startsWith("\\\\/\\\\/")}function ri(e,t,n){return ni(t)?e.replace(new RegExp(`(?<!:)${ti(t)}`,"g"),n):e.split(t).join(n)}function si(e,t,n){if(e.wpsuite?.siteSettings?.subscriber===true||e.wpsuite?.subscriptionType==="PROFESSIONAL"||e.wpsuite?.subscriptionType==="AGENCY"||!n)return false;let s=S.extname(n).toLowerCase();return Xs.has(s)?/<head\b|<html\b|<!doctype html/i.test(t):false}function ii(e){if(new RegExp(`<meta\\b(?=[^>]*\\bname=(["'])generator\\1)(?=[^>]*\\bcontent=(["'])${ei}\\2)[^>]*\\/?>`,"i").test(e))return e;let t=`<meta name="generator" content="${ur}" />`;if(e.match(/(\r?\n)([ \t]*)<\/head>/i))return e.replace(/(\r?\n)([ \t]*)<\/head>/i,`$1$2${t}$1$2</head>`);let r=e.includes(`\r
|
|
1
|
+
import A from'fs/promises';import As from'http';import Nn from'https';import S from'path';import ur,{createHash}from'crypto';import {request,chromium}from'playwright';import {gunzipSync}from'zlib';import Zs from'fast-glob';import {availableParallelism}from'os';import {Worker}from'worker_threads';import {S3Client,ListObjectsV2Command,HeadObjectCommand,GetObjectCommand,DeleteObjectsCommand}from'@aws-sdk/client-s3';import {Upload}from'@aws-sdk/lib-storage';import pa from'mime-types';import {CloudFrontClient,waitUntilInvalidationCompleted,CreateInvalidationCommand}from'@aws-sdk/client-cloudfront';var Ps=new Set(["post-type","taxonomy","author","date","posts-page","listing"]);function Se(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))].sort()}function vs(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))]}function Cs(e){return new URL(e).pathname.split("/").filter(Boolean).some(n=>{try{return decodeURIComponent(n).endsWith("__trashed")}catch{return n.endsWith("__trashed")}})}function Bt(e){return Array.isArray(e)?e.map(Bt):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,Bt(n)])):e}function Rs(e){return JSON.stringify(Bt(e))}function le(e){return createHash("sha256").update(Rs(e)).digest("hex")}function Fn(e){return le({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 Wt(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 ie(e,t){xs(t);let n=new URL(Wt(e)),r=new URL(t,`${n.toString().replace(/\/$/,"")}/`);if(r.origin!==n.origin)throw new Error(`Content-sync URL is outside the source origin: ${t}`);let s=n.pathname.replace(/\/+$/,"");if(s&&r.pathname!==s&&!r.pathname.startsWith(`${s}/`))throw new Error(`Content-sync URL is outside the source site path: ${t}`);return r.hash="",r.toString()}function xs(e){let n=String(e).split(/[?#]/,1)[0];for(let s=0;s<3;s+=1)try{let i=decodeURIComponent(n);if(i===n)break;n=i;}catch{throw new Error(`Content-sync URL has malformed encoding: ${e}`)}if(n.includes("\0")||n.includes("\\"))throw new Error(`Content-sync URL has an unsafe path: ${e}`);if(n.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]*/i,"").split("/").some(s=>s==="."||s===".."))throw new Error(`Content-sync URL has an unsafe path: ${e}`)}function Je(e){let t=Se((e.postTypes??[]).map(r=>String(r).toLowerCase().replace(/[^a-z0-9_-]/g,"")));if(t.length===0)throw new Error("Content-sync requires at least one public post type.");let n=Se((e.listingPaths??[]).map(r=>{let s=String(r).trim();if(!s)return "";let i=new URL(s,"https://content-sync.invalid/");if(i.origin!=="https://content-sync.invalid"&&/^https?:\/\//i.test(s))throw new Error("Content-sync listing routes must be same-site paths.");let a=`/${i.pathname.replace(/^\/+|\/+$/g,"")}`;return a==="/"?"/":`${a}/`}));return {postTypes:t,listingPaths:n,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 Un(e,t,n){return le({schemaVersion:1,sourceOrigin:Wt(e),ruleId:t.trim(),scope:Je(n)})}function Ln(e){return le({schemaVersion:1,...e})}function jn(e){let t=String(e.siteId??"").trim()||String(e.accountId??"").trim()||Wt(e.sourceOrigin);return `content-sync:${le({siteIdentity:t,ruleId:e.ruleId.trim(),targetFingerprint:e.targetFingerprint}).slice(0,48)}`}function qn(e){let t=[...e].sort((s,i)=>s.sequence-i.sequence),n=new Map,r=-1;for(let s of t){if(!Number.isSafeInteger(s.sequence)||s.sequence<=r)throw new Error("Content-sync journal events are not strictly ordered.");if(r=s.sequence,!Number.isSafeInteger(s.blogId)||s.blogId<1)throw new Error("Content-sync journal event has an invalid multisite identity.");let i=`${s.blogId}:${s.postType}:${s.postId}`,a=n.get(i);if(!a){n.set(i,{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 [...n.values()].sort((s,i)=>s.fromSequence-i.fromSequence)}function On(e){return e?.status==="publish"&&!!e.url}function Is(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 Ht(e){let t=Je(e.scope),n=new Map;qn(e.events);for(let r of e.events)for(let s of [r.before,r.after])for(let i of s?.archiveFamilies??[]){if(!Ps.has(i.kind)||!Is(i.kind,t))continue;let a={...i,url:ie(e.sourceOrigin,i.url)};n.set(`${a.kind}|${a.url}`,a);}for(let r of t.listingPaths){let s=ie(e.sourceOrigin,r);n.set(`listing|${s}`,{kind:"listing",url:s});}return [...n.values()].sort((r,s)=>r.url.localeCompare(s.url))}function _n(e){let t=Je(e.scope),n=qn(e.events),r=new Set,s=new Set,i=new Map,a=new Map(Ht({events:e.events,scope:t,sourceOrigin:e.sourceOrigin}).map(p=>[`${p.kind}|${p.url}`,p]));for(let p of n){let y=p.before,m=p.after,h=On(y),w=On(m);w&&m.url&&r.add(ie(e.sourceOrigin,m.url)),h&&y.url&&(!w||y.url!==m.url)&&s.add(ie(e.sourceOrigin,y.url));}for(let p of [...e.events].sort((y,m)=>y.sequence-m.sequence)){for(let y of [p.before,p.after])for(let m of y?.resourceDeleteUrls??[])i.set(ie(e.sourceOrigin,m),"delete");for(let y of p.after?.resourceRenderUrls??[])i.set(ie(e.sourceOrigin,y),"render");}let c=[...i].filter(([,p])=>p==="render").map(([p])=>p),o=[...i].filter(([,p])=>p==="delete").map(([p])=>p),l=new Map(e.resolvedArchiveFamilies.map(p=>[`${p.kind}|${ie(e.sourceOrigin,p.url)}`,{...p,url:ie(e.sourceOrigin,p.url),pageUrls:Se(p.pageUrls.map(y=>ie(e.sourceOrigin,y)))}])),d=[...a.entries()].map(([p,y])=>{let m=l.get(p);if(!m)throw new Error(`WordPress did not resolve archive family ${p}.`);return {...y,...m}}).sort((p,y)=>p.url.localeCompare(y.url)),u=Se(d.flatMap(p=>p.pageUrls)),g=t.includeSitemapChain?vs(e.sitemapUrls.map(p=>ie(e.sourceOrigin,p))):[],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:n.length,directRenderUrls:Se([...r]),archiveFamilyUrls:u,sitemapUrls:g,deleteUrls:Se([...s]),resourceRenderUrls:Se(c),resourceDeleteUrls:Se(o),archiveFamilies:d};return {...f,impactHash:le(f)}}function Ve(e){let{impactHash:t,...n}=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(le(n)!==t)throw new Error("Content-sync impact plan hash mismatch.");for(let r of [...e.directRenderUrls,...e.deleteUrls,...e.resourceRenderUrls,...e.resourceDeleteUrls])if(Cs(r))throw new Error(`Content-sync impact contains a WordPress trash alias instead of the last public URL: ${r}`)}var Ts="wp-json/smartcloud-static-publisher/v1/content-sync/",ks=25*1024*1024,gt=class extends Error{status;code;constructor(t,n,r){super(r),this.name="ContentSyncApiError",this.status=t,this.code=n;}},ft=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,n="content-sync"){let r=this.options.sourceOrigin.replace(/\/+$/,"")+"/",s=n==="content-sync"?Ts:`wp-json/smartcloud-static-publisher/v1/${n}/`;return new URL(`${s}${t}`,r)}async post(t,n,r="content-sync"){let s=this.endpoint(t,r),i=Buffer.from(JSON.stringify(n),"utf8"),a=s.protocol==="https:"?Nn:As,c=s.protocol==="https:"?new Nn.Agent({rejectUnauthorized:!this.options.ignoreHttpsErrors}):void 0;return new Promise((o,l)=>{let d=a.request(s,{method:"POST",agent:c,headers:{"content-type":"application/json","content-length":String(i.byteLength),"x-static-publisher-token":this.options.runtimeToken},timeout:this.options.timeoutMs},u=>{let g=[],f=0;u.on("data",p=>{if(f+=p.byteLength,f>ks){u.destroy(new Error("Content-sync API response exceeded the size limit."));return}g.push(p);}),u.on("error",l),u.on("end",()=>{let p=Buffer.concat(g).toString("utf8"),y;try{y=p?JSON.parse(p):{};}catch{l(new gt(u.statusCode??500,"invalid-json","Content-sync API returned invalid JSON."));return}let m=u.statusCode??500;if(m<200||m>=300){l(new gt(m,String(y.code??"request-failed"),String(y.message??`Content-sync API request failed (${m}).`)));return}o(y);});});d.on("timeout",()=>d.destroy(new Error(`Content-sync API request timed out: ${t}`))),d.on("error",l),d.end(i);})}async head(t){return this.post("head",t)}async unboundHead(t,n){return this.post("head",{postTypes:t,includeSubsites:n})}async events(t){let n=[],r=t.afterSequence,s=new Set(t.postTypes);for(;r<t.throughSequence;){let i=await this.post("events",{...t,afterSequence:r,limit:250});if(i.fromSequence!==r||i.throughSequence!==t.throughSequence||i.nextSequence<r||i.nextSequence>t.throughSequence)throw new Error("Content-sync API returned an inconsistent event page.");if(!Array.isArray(i.items))throw new Error("Content-sync API returned a malformed event page.");let a=r;for(let c of i.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(i.items.length>0&&i.nextSequence!==a)throw new Error("Content-sync API event cursor does not match the final returned event.");if(n.push(...i.items),!i.hasMore)break;if(i.nextSequence===r)throw new Error("Content-sync API event pagination did not advance.");r=i.nextSequence;}if(t.throughSequence>t.afterSequence&&n.at(-1)?.sequence!==t.throughSequence)throw new Error("Content-sync API omitted the claimed journal high-water event.");return n}async resolveImpactFamilies(t,n){let r=await this.post("impact",{families:t,includeSubsites:n});return Array.isArray(r.families)?r.families:[]}async releaseFingerprint(t=false){let n=await this.post("fingerprint",{includeSubsites:t}),r=String(n.fingerprint||"").trim();if(!/^[a-f0-9]{64}$/.test(r))throw new Error("WordPress returned an invalid release fingerprint.");return r}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 mt(e){let t=S.resolve(e);return {state:S.join(t,"content-sync-state.json"),current:S.join(t,"content-sync-current.json"),impact:S.join(t,"content-sync-impact-plan.json"),checkpoint:S.join(t,"content-sync-checkpoint.json"),baseline:S.join(t,"content-sync-baseline.json"),activeRules:S.join(t,"content-sync-active-rules.json"),releaseCutoff:S.join(t,"content-sync-release-cutoff.json"),candidateManifest:S.join(t,"content-sync-candidate-manifest.json"),trustedManifest:S.join(t,"crawl-manifest.json"),invalidation:S.join(t,"content-sync-invalidation.json"),deployPlan:S.join(t,"deploy-plan.json")}}async function zt(e){let t=await Ke(e.releaseCutoff);if(t===null)return {schemaVersion:1,updatedAt:"",entries:{}};let n=t;if(n.schemaVersion!==1||typeof n.updatedAt!="string"||!n.entries||typeof n.entries!="object"||Array.isArray(n.entries))throw new Error("Invalid content-sync release-cutoff store.");return n}async function Bn(e,t){await Ee(e.releaseCutoff,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Ee(e,t){await A.mkdir(S.dirname(e),{recursive:true});let n=`${e}.${process.pid}.${Date.now()}.tmp`;await A.writeFile(n,JSON.stringify(t,null,2),"utf8"),await A.rename(n,e);}async function Ke(e){try{return JSON.parse(await A.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 Qt(e){let t=await Ke(e.baseline);if(t===null)return {schemaVersion:1,updatedAt:"",entries:{}};let n=t;if(n.schemaVersion!==1||typeof n.updatedAt!="string"||!n.entries||typeof n.entries!="object"||Array.isArray(n.entries))throw new Error("Invalid content-sync baseline store.");return n}async function Wn(e,t){await Ee(e.baseline,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Jt(e){let t=await Ke(e.current);if(t===null)return null;let n=t;if(n.schemaVersion!==1||typeof n.jobId!="string"||typeof n.phase!="string"||!Number.isSafeInteger(n.fromSequence)||!Number.isSafeInteger(n.toSequence))throw new Error("Invalid content-sync current-range state.");return n}async function Hn(e,t){await Ee(e.current,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function zn(e){let t=await Ke(e.impact);if(t===null)return null;let n=t;return Ve(n),n}async function Qn(e,t){Ve(t),await Ee(e.impact,t);}async function Jn(e,t){await Ee(e.checkpoint,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function ht(e){let t=await Ke(e.state);if(t===null)return {schemaVersion:1,updatedAt:"",rules:{}};let n=t;if(n.schemaVersion!==1||typeof n.updatedAt!="string"||!n.rules||typeof n.rules!="object"||Array.isArray(n.rules))throw new Error("Invalid content-sync state store.");return n}async function wt(e,t){await Ee(e.state,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Vt(e){await Promise.all([e.current,e.checkpoint].map(async t=>{try{await A.unlink(t);}catch(n){if(n.code!=="ENOENT")throw n}}));}async function Vn(e,t){let n=await Jt(e);return !n||n.coalesceKey!==t?false:(await Promise.all([e.current,e.checkpoint,e.impact,e.candidateManifest,e.invalidation,e.deployPlan].map(async r=>{try{await A.unlink(r);}catch(s){if(s.code!=="ENOENT")throw s}})),true)}var Kt=["/sitemap_index.xml","/wp-sitemap.xml","/sitemap.xml"];function Ge(e){let t=new Set;for(let n of [...e,...Kt]){let r=String(n||"").trim();r&&t.add(r);}return [...t]}function Gt(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function Kn(e){if(!e||!/^https?:\/\//i.test(e))return false;try{return Gt(new URL(e))}catch{return false}}function Zn(e){let t=e.trim();return t==="."?".":t.replace(/\/$/,"")}function Ds(e){let t=String(e??"").trim();if(!t)return "";let n=t;if(/^https?:\/\//i.test(n))try{n=new URL(n).pathname;}catch{return ""}if(n=n.split(/[?#]/,1)[0]?.replace(/\\/g,"/").trim()??"",!n)return "";let r=n.endsWith("/"),s=n.replace(/^\/+/,"").split("/").map(a=>a.replace(/[^A-Za-z0-9._-]/g,"")).filter(a=>a.length>0&&a!=="."&&a!=="..");if(s.length===0)return "";let i=`/${s.join("/")}`;return r&&S.extname(i)===""&&(i+="/"),i==="/"?"":i}function Zt(e){return !e||typeof e!="object"?{}:Object.fromEntries(Object.entries(e).map(([t,n])=>[t.trim(),String(n??"")]).filter(([t])=>t.length>0))}function Os(e){if(!e||typeof e!="object")return {};let t={};for(let[n,r]of Object.entries(e)){let s=n.trim();if(!s||!r||typeof r!="object")continue;let i=r,a={};if(typeof i.targetOrigin=="string"){let o=Zn(i.targetOrigin);o&&(a.targetOrigin=o);}let c=Zt(i.extraReplacements);if(Object.keys(c).length>0&&(a.extraReplacements=c),i.s3&&typeof i.s3=="object"){let o={},l=i.s3;typeof l.bucket=="string"&&(o.bucket=l.bucket.trim()),typeof l.prefix=="string"&&(o.prefix=l.prefix.trim()),typeof l.region=="string"&&(o.region=l.region.trim()),typeof l.htmlCacheControl=="string"&&(o.htmlCacheControl=l.htmlCacheControl.trim()),typeof l.assetCacheControl=="string"&&(o.assetCacheControl=l.assetCacheControl.trim()),Object.keys(o).length>0&&(a.s3=o);}if(i.cloudFront&&typeof i.cloudFront=="object"){let o={},l=i.cloudFront;typeof l.distributionId=="string"&&(o.distributionId=l.distributionId.trim()),Array.isArray(l.invalidationPaths)&&(o.invalidationPaths=l.invalidationPaths.map(d=>String(d??"").trim()).filter(d=>d.length>0)),Object.keys(o).length>0&&(a.cloudFront=o);}t[s]=a;}return t}function Xt(e){return e==="PROFESSIONAL"||e==="AGENCY"?e:void 0}function Fs(e,t){if(!e||typeof e!="object")return null;let n=e,r=n.command;if(r!=="publish"&&r!=="crawl"&&r!=="deploy"&&r!=="invalidate"&&r!=="retry-timeouts"&&r!=="url"&&r!=="content-sync")return null;let s=Number.parseInt(String(n.intervalMinutes??"0"),10);if(!Number.isFinite(s)||s<1)return null;let i=String(n.id??`${r}-${t+1}`).trim();if(!i)return null;let a=String(n.deploymentProfile??"").trim(),c=String(n.url??"").trim(),o=Array.isArray(n.postTypes)?[...new Set(n.postTypes.map(d=>String(d??"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"")).filter(Boolean))]:[],l=Array.isArray(n.listingPaths)?[...new Set(n.listingPaths.map(d=>String(d??"").trim()).filter(Boolean))]:[];return r==="content-sync"&&o.length===0?null:{id:i,enabled:n.enabled!==false,command:r,intervalMinutes:s,...r==="publish"||r==="crawl"?{crawlMode:n.crawlMode==="incremental"?"incremental":"full"}:{},...(r==="publish"||r==="deploy"||r==="invalidate"||r==="content-sync")&&a?{deploymentProfile:a}:{},...c?{url:c}:{},...o.length>0?{postTypes:o}:{},...l.length>0?{listingPaths:l}:{},...typeof n.includeSubsites=="boolean"?{includeSubsites:n.includeSubsites}:{},...typeof n.includePostTypeArchives=="boolean"?{includePostTypeArchives:n.includePostTypeArchives}:{},...typeof n.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:n.includeTaxonomyArchives}:{},...typeof n.includeAuthorArchives=="boolean"?{includeAuthorArchives:n.includeAuthorArchives}:{},...typeof n.includeDateArchives=="boolean"?{includeDateArchives:n.includeDateArchives}:{},...typeof n.includePostsPage=="boolean"?{includePostsPage:n.includePostsPage}:{},...typeof n.includeSitemapChain=="boolean"?{includeSitemapChain:n.includeSitemapChain}:{}}}function Yn(e){let t=e&&typeof e=="object"?e:{},n=Array.isArray(t.rules)?t.rules.map((r,s)=>Fs(r,s)).filter(r=>!!r):[];return {enabled:t.enabled===true,timezone:typeof t.timezone=="string"&&t.timezone.trim()!==""?t.timezone.trim():"UTC",rules:n}}function Us(e){if(!e||typeof e!="object")return;let t=e,n={};for(let s of ["accountId","siteId"]){let i=t[s];typeof i=="string"&&i.trim()!==""&&(n[s]=i.trim());}let r=Number(t.lastUpdate??0);return Number.isFinite(r)&&r>0&&(n.lastUpdate=Math.floor(r)),t.subscriber===true&&(n.subscriber=true),Object.keys(n).length>0?n:void 0}function en(e){let t=e&&typeof e=="object"?e:{},n=String(t.accountId??"").trim(),r=String(t.siteId??"").trim(),s=t.subscriber===true,i=Us(t.siteSettings),a={...i??{},...n?{accountId:i?.accountId??n}:{},...r?{siteId:i?.siteId??r}:{},...i?.subscriber===true||s?{subscriber:true}:{}},c={},o=String(t.apiBase??"").trim();o&&(c.apiBase=o);let l=String(t.runtimeToken??t.nonce??"").trim();l&&(c.runtimeToken=l);let d=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();d&&(c.virtualAssetBaseUrl=d),Object.keys(a).length>0&&(c.siteSettings=a);let u=Xt(t.subscriptionType);return u&&(c.subscriptionType=u),c}function Ls(e){try{let t=new URL(e);globalThis.location=t;}catch{}}function Xn(e){return typeof e=="string"?e:e instanceof URL?e.toString():e.url}function js(e,t){let n=new Headers(e instanceof Request?e.headers:void 0);if(t?.headers)for(let[r,s]of new Headers(t.headers).entries())n.set(r,s);return n}async function er(e,t,n=5){let r=new URL(Xn(e)),s=String(t?.method??(e instanceof Request?e.method:"GET")).toUpperCase(),i=r.protocol==="http:"?As:Nn,a=js(e,t);return await new Promise((c,o)=>{let l=i.request(r,{method:s,headers:Object.fromEntries(a.entries()),...r.protocol==="https:"?{rejectUnauthorized:false}:{}},d=>{let u=[];d.on("data",g=>{u.push(Buffer.isBuffer(g)?g:Buffer.from(g));}),d.on("error",o),d.on("end",()=>{let g=d.statusCode??0,f=d.headers.location;if(n>0&&f&&[301,302,303,307,308].includes(g)){c(er(new URL(f,r),{method:g===303?"GET":s},n-1));return}let p=new Headers;for(let[y,m]of Object.entries(d.headers))Array.isArray(m)?p.set(y,m.join(", ")):typeof m=="string"&&p.set(y,m);c(new Response(Buffer.concat(u),{status:g,statusText:d.statusMessage??"",headers:p}));});});l.on("error",o),l.end();})}function qs(e){let t=en(e.wpsuite),n={...t.siteSettings??{},...t.siteSettings?.subscriber===true||t.subscriptionType==="PROFESSIONAL"||t.subscriptionType==="AGENCY"?{subscriber:true}:{}},r=String(n.accountId??"").trim(),s=String(n.siteId??"").trim(),i=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();if(e.wpsuite={...t.apiBase?{apiBase:t.apiBase}:{},...t.runtimeToken?{runtimeToken:t.runtimeToken}:{},...i?{virtualAssetBaseUrl:i}:{},...Object.keys(n).length>0?{siteSettings:n}:{},...t.subscriptionType?{subscriptionType:t.subscriptionType}:{}},!r||!s||!i)return false;Ls(e.sourceOrigin);let a=globalThis,o={...a.WpSuite??{},siteSettings:n,uploadUrl:i};return t.apiBase&&(o.apiBase=t.apiBase),a.WpSuite=o,true}async function _s(e){let t=String(e.wpsuite?.virtualAssetBaseUrl??e.wpsuite?.uploadUrl??"").trim();if(!qs(e)){let s=e.wpsuite?.siteSettings,i=[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): ${i.join(", ")}.`,requests:[]}}}let n=globalThis.fetch,r=[];try{typeof n=="function"&&/^https?:\/\//i.test(t)&&(globalThis.fetch=(async(o,l)=>{let d=Xn(o);if(d.startsWith(t)){let u=(()=>{try{return new URL(d).pathname}catch{return d}})();try{let g=e.ignoreHttpsErrors&&d.startsWith("https://")?await er(o,l):await n(o,l);return r.push({path:u,status:g.status,ok:g.ok,error:null}),g}catch(g){throw r.push({path:u,status:null,ok:!1,error:g instanceof Error?g.message:String(g)}),g}}return n(o,l)}));let{getConfig:s}=await import('@smart-cloud/wpsuite-core'),i=await s("publisher"),a=i&&typeof i=="object"?i:null,c=Xt(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:r}}}catch(s){return {remote:null,diagnostic:{status:"unavailable",virtualAssetBaseUrl:t,subscriptionType:null,error:s instanceof Error?s.message:String(s),requests:r}}}finally{typeof n=="function"&&(globalThis.fetch=n);}}function Ns(e,t){let n=Os(t?.deploymentProfiles),r=String(t?.defaultDeploymentProfile??"").trim(),s=n[r]?r:"",i=Xt(t?.subscriptionType),a=en(e.wpsuite);return {...e,scheduler:Yn(t?.scheduler),deploymentProfiles:n,defaultDeploymentProfile:s,...i?{subscriptionType:i}:{},wpsuite:{...a,...a.siteSettings||i?{siteSettings:{...a.siteSettings??{},...a.siteSettings?.subscriber===true||i==="PROFESSIONAL"||i==="AGENCY"?{subscriber:true}:{}}}:{},...i?{subscriptionType:i}:{}}}}function Yt(e,t){let r=String(e||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!r)return t;let s=r.split("/").map(i=>i.trim()).filter(i=>i.length>0&&i!=="."&&i!=="..");return s.length>0?s.join("/"):t}function Bs(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?S.resolve(e):""}function Gn(e,t,n){let r=String(t||"").trim();return r&&S.isAbsolute(r)?S.resolve(r):S.resolve(e,Yt(r,n))}async function oe(e,t={}){let n=String(e??"").trim()||process.env.PUBLISHER_CONFIG||"publisher.config.json",r=await A.readFile(n,"utf8"),s=JSON.parse(r);s.sourceOrigin=s.sourceOrigin.replace(/\/$/,""),s.targetOrigin=Zn(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=Ds(s.generated404RequestPath),s.sitemapPaths||=[...Kt],s.allowedAssetHosts||=[],s.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],s.blockedPathPrefixes||=[],s.blockedSearchFragments||=[],s.concurrency||=1,s.maxPages||=0,s.extraReplacements=Zt(s.extraReplacements),s.postCrawlCopyMap=Zt(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=Number(s.assetDownloadConcurrency)>0?Number(s.assetDownloadConcurrency):s.concurrency,s.rewriteConcurrency=Number(s.rewriteConcurrency)>0?Number(s.rewriteConcurrency):s.assetDownloadConcurrency,s.wpsuite=en(s.wpsuite),s.scheduler=Yn(void 0),s.deploymentProfiles={},s.defaultDeploymentProfile="",s.deploymentTargetOverride=String(s.deploymentTargetOverride??"").trim();let i=await _s(s);t.onRemotePublisherConfigDiagnostic?.(i.diagnostic);let a=Ns(s,i.remote),c=Bs(),o=c?S.resolve(c,".."):"";return o?(a.outputDir=Gn(o,a.outputDir,"export"),a.logDir=Gn(o,a.logDir,"logs")):(S.isAbsolute(a.outputDir)||(a.outputDir=Yt(a.outputDir,"export")),S.isAbsolute(a.logDir)||(a.logDir=Yt(a.logDir,"logs"))),a}var Ws=".deploy-plan.json",Hs="deploy-plan.json",zs=".crawl-incomplete.json",Qs="crawl-incomplete.json";function tr(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?S.resolve(e):""}function nr(e){let t=String(e||"").replace(/\\/g,"/").replace(/^\/+/,"").trim(),n=S.posix.normalize(t);return !t||!n||n==="."||/^[a-zA-Z]:/.test(n)||n.startsWith("../")||n===".."?null:n}function Js(e){let t=String(e||"").trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("*")||t.includes("#"))return null;try{let n=new URL(t,"https://content-sync.invalid");return n.origin!=="https://content-sync.invalid"?null:`${S.posix.normalize(n.pathname)}${n.search}`}catch{return null}}function de(e){return [...new Set(e.map(nr).filter(t=>t!==null))]}function rr(e,t){let n={generatedAt:String(t.generatedAt||new Date().toISOString()),outputDir:S.resolve(e.outputDir),runMode:t.runMode,crawlMode:t.crawlMode,fullSyncRequired:!!t.fullSyncRequired,changedFiles:de(t.changedFiles||[]),deletedFiles:de(t.deletedFiles||[]),rewriteTargets:de(t.rewriteTargets||[])};return t.schemaVersion===2?{...n,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(r=>String(r||"").trim()).filter(r=>{try{let s=new URL(r);return s.protocol==="http:"||s.protocol==="https:"}catch{return false}}))],uploadGroups:{assets:de(t.uploadGroups?.assets||[]),content:de(t.uploadGroups?.content||[]),listings:de(t.uploadGroups?.listings||[]),resources:de(t.uploadGroups?.resources||[]),sitemapLeaves:de(t.uploadGroups?.sitemapLeaves||[]),sitemapIndexes:de(t.uploadGroups?.sitemapIndexes||[])},invalidationPaths:[...new Set((t.invalidationPaths||[]).map(Js).filter(r=>r!==null))].sort()}:{schemaVersion:1,...n,runMode:t.runMode}}function Vs(e){if(!e||typeof e!="object")return false;let t=e;if(t.schemaVersion===2){let n=t;return n.runMode==="content-sync"&&n.crawlMode==="incremental"&&n.fullSyncRequired===false&&typeof n.generatedAt=="string"&&typeof n.outputDir=="string"&&typeof n.consumerId=="string"&&n.consumerId.trim()!==""&&Number.isSafeInteger(n.fromSequence)&&Number.isSafeInteger(n.toSequence)&&Number(n.toSequence)>=Number(n.fromSequence)&&typeof n.impactHash=="string"&&/^[a-f0-9]{64}$/.test(n.impactHash)&&Array.isArray(n.resolvedSitemapUrls)&&Array.isArray(n.changedFiles)&&Array.isArray(n.deletedFiles)&&Array.isArray(n.rewriteTargets)&&!!n.uploadGroups&&Array.isArray(n.uploadGroups.assets)&&Array.isArray(n.uploadGroups.content)&&Array.isArray(n.uploadGroups.listings)&&Array.isArray(n.uploadGroups.resources)&&Array.isArray(n.uploadGroups.sitemapLeaves)&&Array.isArray(n.uploadGroups.sitemapIndexes)&&Array.isArray(n.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)}function tn(e){let t=S.join(S.resolve(e.outputDir),Ws),n=tr();return n?[S.join(n,Hs),t]:[t]}function nn(e){let t=S.join(S.resolve(e.outputDir),zs),n=tr();return n?[S.join(n,Qs),t]:[t]}function pe(e,t){let n=S.resolve(e),r=S.resolve(t),s=S.relative(n,r).replace(/\\/g,"/");return nr(s)}async function Me(e){let t=S.resolve(e.outputDir);for(let n of tn(e))try{let r=await A.readFile(n,"utf8"),s=JSON.parse(r);if(!Vs(s)||S.resolve(s.outputDir)!==t)continue;return rr(e,s)}catch{}return null}async function rn(e,t){let n=rr(e,t);for(let r of tn(e)){await A.mkdir(S.dirname(r),{recursive:true});let s=`${r}.${process.pid}.${Date.now()}.tmp`;await A.writeFile(s,JSON.stringify(n,null,2),"utf8"),await A.rename(s,r);}}async function De(e){for(let t of tn(e))try{await A.unlink(t);}catch(n){if(n.code!=="ENOENT")throw n}}async function sr(e,t){let n={schemaVersion:1,startedAt:String(t.startedAt||new Date().toISOString()),outputDir:S.resolve(e.outputDir)};for(let r of nn(e)){await A.mkdir(S.dirname(r),{recursive:true});let s=`${r}.${process.pid}.tmp`;await A.writeFile(s,JSON.stringify(n,null,2),"utf8"),await A.rename(s,r);}}async function ir(e){let t=S.resolve(e.outputDir);for(let n of nn(e)){let r;try{r=await A.readFile(n,"utf8");}catch(i){if(i.code==="ENOENT")continue;throw i}let s;try{s=JSON.parse(r);}catch{throw new Error(`Invalid incomplete crawl marker: ${n}`)}if(s.schemaVersion!==1||typeof s.startedAt!="string"||typeof s.outputDir!="string"||S.resolve(s.outputDir)!==t)throw new Error(`Invalid incomplete crawl marker: ${n}`);return {schemaVersion:1,startedAt:s.startedAt,outputDir:t}}return null}async function or(e){for(let t of nn(e))try{await A.unlink(t);}catch(n){if(n.code!=="ENOENT")throw n}}function Ye(e,t=10){return ur.createHash("sha1").update(e).digest("hex").slice(0,t)}async function Ks(e){await A.mkdir(S.dirname(e),{recursive:true});}async function Xe(e,t,n){await Ks(e);let r=S.join(S.dirname(e),`.${S.basename(e)}.${process.pid}.${Date.now()}.${ur.randomBytes(6).toString("hex")}.tmp`);try{typeof t=="string"?await A.writeFile(r,t,n??"utf8"):await A.writeFile(r,t),await A.rename(r,e);}catch(s){throw await A.unlink(r).catch(()=>{}),s}}function Pe(e){return [".html",".htm",".css",".js",".mjs",".json",".xml",".xsl",".txt",".svg",".map",".enc",".jws"].includes(S.extname(e).toLowerCase())}function fe(e){return e.replace(/"/g,'"').replace(/"/g,'"').replace(/'/g,"'").replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function Oe(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function yt(e){return e.replace(/\//g,"\\/")}function ar(e){return e.replace(/\//g,"\\\\/")}function Gs(e){try{let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")return null;let n=t.pathname==="/"&&!t.search&&!t.hash?"":`${t.pathname}${t.search}${t.hash}`;return `//${t.host}${n}`}catch{return null}}function cr(e,t,n){if(!t)return;e[t]=n;let r=yt(t),s=yt(n);e[r]=s;let i=ar(t),a=ar(n);e[i]=a;let c=Oe(t),o=Oe(n);e[c]=o;let l=Oe(r),d=Oe(s);e[l]=d;let u=Oe(i),g=Oe(a);e[u]=g;}function St(e,t,n){cr(e,t,n);let r=Gs(t);r&&r!==t&&cr(e,r,n);}function sn(e,t){let n=t.startsWith("/")?t:`/${t}`,r=(e||"").replace(/\/$/,"");return !r||r==="."||r==="/"?n:`${r}${n}`}function lr(e,t){try{return new URL(e,t==="."?"https://relative.invalid":t).pathname}catch{return e.startsWith("/")?e:`/${e.replace(/^\.\//,"")}`}}function dr(e,t,n){if(!t)return n;let r=S.dirname(S.resolve(t)),s=S.resolve(e,n.replace(/^\/+/,"")),i=S.relative(r,s).replace(/\\/g,"/");return i?(i.startsWith(".")||(i=`./${i}`),i):"."}var ti=["wp-content/","wp-includes/","wp-admin/","wp-json/","_next/"],ni=new Set([".html",".htm"]),pr="WPSuite.io Static Publisher",ri=pr.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function si(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ii(e){return e.startsWith("//")||e.startsWith("\\/\\/")||e.startsWith("\\\\/\\\\/")}function oi(e,t,n){return ii(t)?e.replace(new RegExp(`(?<!:)${si(t)}`,"g"),n):e.split(t).join(n)}function ai(e,t,n){if(e.wpsuite?.siteSettings?.subscriber===true||e.wpsuite?.subscriptionType==="PROFESSIONAL"||e.wpsuite?.subscriptionType==="AGENCY"||!n)return false;let s=S.extname(n).toLowerCase();return ni.has(s)?/<head\b|<html\b|<!doctype html/i.test(t):false}function ci(e){if(new RegExp(`<meta\\b(?=[^>]*\\bname=(["'])generator\\1)(?=[^>]*\\bcontent=(["'])${ri}\\2)[^>]*\\/?>`,"i").test(e))return e;let t=`<meta name="generator" content="${pr}" />`;if(e.match(/(\r?\n)([ \t]*)<\/head>/i))return e.replace(/(\r?\n)([ \t]*)<\/head>/i,`$1$2${t}$1$2</head>`);let r=e.includes(`\r
|
|
2
2
|
`)?`\r
|
|
3
3
|
`:`
|
|
4
|
-
`;return e.replace(/<head\b[^>]*>/i,s=>`${s}${r} ${t}`)}function
|
|
5
|
-
`,"utf8");}function
|
|
6
|
-
`,"utf8");});}enqueueJsonLine(t,n){this.enqueueTask(()=>
|
|
7
|
-
`,"utf8");});}enqueueJsonLine(t,n){this.enqueueTask(()=>
|
|
4
|
+
`;return e.replace(/<head\b[^>]*>/i,s=>`${s}${r} ${t}`)}function ui(e){let t=fe(e).trim();return t.startsWith("{")||t.startsWith("[")||t.includes("\\/")||/"@context"|"@type"/.test(t)}function li(e,t){let n=[...new Set(t)].filter(i=>i.includes("/")&&!/\\+\//.test(i)).map(i=>[i,yt(i)]).filter(([i,a])=>i!==a).sort((i,a)=>a[0].length-i[0].length);if(!n.length)return e;let r=i=>{let a=i;for(let[c,o]of n)a=a.split(c).join(o);return a},s=e.replace(/(<script\b[^>]*\btype=["']application\/(?:ld\+)?json["'][^>]*>)([\s\S]*?)(<\/script>)/gi,(i,a,c,o)=>`${a}${r(c)}${o}`);return s=s.replace(/(<meta\b[^>]*\bcontent=(['"]))([\s\S]*?)(\2[^>]*>)/gi,(i,a,c,o,l)=>ui(o)?`${a}${r(o)}${l}`:i),s}function di(e,t){if(!t)return null;let n=S.dirname(S.resolve(t)),r=S.resolve(e.outputDir),s=S.relative(n,r).replace(/\\/g,"/");return s?(s.startsWith(".")||(s=`./${s}`),s.endsWith("/")?s:`${s}/`):"./"}function pi(e,t,n){let r=di(t,n);if(!r)return e;let s=e;for(let i of ti){let a=i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=new RegExp(`(?:\\.{1,}/)+${a}`,"g"),o=new RegExp(`(?<!\\.)/${a}`,"g");s=s.replace(c,`${r}${i}`).replace(o,`${r}${i}`);let l=i.replace(/\//g,"\\/"),d=r.replace(/\//g,"\\/"),u=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),g=new RegExp(`(?:\\.{1,}\\\\/)+${u}`,"g"),f=new RegExp(`(?:\\.{1,}(?:\\\\/|\\\\))+${u}`,"g"),p=new RegExp(`(?<![\\.\\\\])\\/${u}`,"g");s=s.replace(g,`${d}${l}`).replace(f,`${d}${l}`).replace(p,`${d}${l}`);}return s}function an(e,t,n){if(e.urlRewriteMode==="absolute")return t;let r=(()=>{try{return new URL(t,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin)}catch{return null}})(),s=r?r.pathname:lr(t,e.targetOrigin),i=r?`${r.search}${r.hash}`:"";return e.urlRewriteMode==="root-relative"?`${s}${i}`:`${dr(e.outputDir,n,s)}${i}`}function on(e,t,n,r,s){St(e,n,an(t,r,s));}function gi(e,t,n,r,s){if(!n||n===r)return;St(e,n,r);let i=an(t,n,s),a=an(t,r,s);St(e,i,a);}function cn(e,t,n,r,s={}){let i=e,a={};on(a,t,t.sourceOrigin,t.targetOrigin,r);for(let[o,l]of Object.entries(t.extraReplacements))on(a,t,o,l,r);for(let[o,l]of Object.entries(n))on(a,t,o,l,r);for(let[o,l]of Object.entries(s)){let d=n[o];!d||d===l||gi(a,t,l,d,r);}let c=Object.entries(a).sort((o,l)=>l[0].length-o[0].length);for(let[o,l]of c)i=oi(i,o,l);return t.urlRewriteMode!=="absolute"&&(i=pi(i,t,r)),i=li(i,c.map(([,o])=>o)),ai(t,i,r)&&(i=ci(i)),i}async function fi(e,t,n,r){let s=S.join(e.outputDir,r),i=S.extname(s).toLowerCase(),a;try{a=await A.readFile(s,"utf8");}catch(l){if(l.code!=="ENOENT")throw l;return {changed:false}}let o=cn(a,e,t,i===".js"||i===".mjs"?void 0:s,n);return o!==a?(await Xe(s,o,"utf8"),{changed:true}):{changed:false}}async function mi(e,t){return await new Promise((n,r)=>{let s=o=>{if(c(),o?.error){r(new Error(o.error));return}n({changed:!!o?.changed});},i=o=>{c(),r(o);},a=o=>{c(),o!==0&&r(new Error(`Rewrite worker exited with code ${o}.`));},c=()=>{e.off("message",s),e.off("error",i),e.off("exit",a);};e.on("message",s),e.on("error",i),e.on("exit",a),e.postMessage({file:t});})}async function bt(e,t,n={}){let s=(n.files?[...new Set(n.files)].map(g=>S.resolve(g)).filter(g=>g.startsWith(S.resolve(e.outputDir))).map(g=>S.relative(e.outputDir,g).replace(/\\/g,"/")).filter(g=>g.length>0):await Zs(["**/*"],{cwd:e.outputDir,onlyFiles:true,dot:true})).filter(g=>g!=="asset-map.json"&&Pe(g)),i=0;if(s.length===0)return 0;let a=Math.max(1,Number(e.rewriteConcurrency||e.assetDownloadConcurrency||1)),c=Math.max(1,Math.min(a,s.length,availableParallelism()));await n.onStart?.({totalFiles:s.length,workerCount:c});let o=0,l=0,d=null;if(c===1){for(let g of s){let f=await fi(e,t,n.previousAssetMap??{},g);f.changed&&(i+=1),l+=1,await n.onProgress?.({index:l,totalFiles:s.length,changedTextFiles:i,file:g,changed:f.changed});}return i}let u=Array.from({length:c},async()=>{let g=new Worker(new URL("./rewrite-worker.js",import.meta.url),{workerData:{config:e,assetMap:t,previousAssetMap:n.previousAssetMap??{}}});try{for(;!d;){let f=o;if(f>=s.length)return;o+=1;let p=s[f],y=await mi(g,p);y.changed&&(i+=1),l+=1,await n.onProgress?.({index:l,totalFiles:s.length,changedTextFiles:i,file:p,changed:y.changed});}}catch(f){throw d=f instanceof Error?f:new Error(String(f)),d}finally{await g.terminate().catch(()=>{});}});return await Promise.all(u),i}var ue={error:0,warn:1,info:2,debug:3},hi=/^(?:authorization|proxyAuthorization|runtimeToken|siteKey|nonce|accessToken|refreshToken|accessKeyId|secretAccessKey|sessionToken|xStaticPublisherToken|xApiKey)$/i;function xe(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 vt(e){return typeof e=="string"?xe(e):Array.isArray(e)?e.map(t=>vt(t)):e instanceof Error?{name:e.name,message:xe(e.message),...e.stack?{stack:xe(e.stack)}:{}}:e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([t,n])=>[t,hi.test(t)?"[REDACTED]":vt(n)])):e}function Rt(e){return e?vt(e):void 0}var gr=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",Pt=gr?S.join(gr,"current-progress.json"):"",fr=Promise.resolve();function mr(e){return e.includes("crawl")?"crawl":e.includes("deploy")?"deploy":e.includes("invalidate")?"invalidate":e}function wi(e,t){let n={...e},r=new Set(["pagesQueued","pagesRendered","assetsQueued","sitemapsQueued","pagesDiscovered","assetsDiscovered","sitemapsDiscovered","pagesSaved","assetsSaved","donePages","doneAssets","doneSitemaps","changedTextFiles","uploaded","failed","index","totalFiles","pageQueue","assetQueue","sitemapQueue"]);for(let[s,i]of Object.entries(t)){let a=n[s];if(typeof a=="number"&&typeof i=="number"&&r.has(s)){n[s]=Math.max(a,i);continue}n[s]=i;}return n}function hr(e,t,n){Pt&&(fr=fr.then(async()=>{let r=new Date,s=r.toISOString();await A.mkdir(S.dirname(Pt),{recursive:true});let i=await A.readFile(Pt,"utf8").then(h=>JSON.parse(h)).catch(()=>null),a=i&&typeof i.details=="object"&&i.details?i.details:{},c=mr(e),o=i?.currentStep||mr(i?.source||""),l=i?.startedAt||s,d={...i?.stepDurationsSec??{}},u=i?.stepStartedAt||s;if(o&&o!==c&&i?.stepStartedAt){let h=Math.max(0,Math.round((r.getTime()-new Date(i.stepStartedAt).getTime())/1e3));d[o]=(d[o]??0)+h,u=s;}let g=Math.max(0,Math.round((r.getTime()-new Date(u).getTime())/1e3)),f=Math.max(0,Math.round((r.getTime()-new Date(l).getTime())/1e3)),p=xe(t),y=Rt(n)??{},m={checkedAt:s,source:e,message:p,details:wi(a,y),startedAt:l,currentStep:c,stepStartedAt:u,stepElapsedSec:g,totalElapsedSec:f,stepDurationsSec:d};await A.writeFile(Pt,JSON.stringify(m,null,2),"utf8");}).catch(()=>{}));}async function wr(e,t){await A.mkdir(S.dirname(e),{recursive:true}),await A.appendFile(e,`${JSON.stringify(vt(t))}
|
|
5
|
+
`,"utf8");}function yi(e,t){let n=typeof t?.phase=="string"?t.phase.trim():"";return n||(e==="page"?"render-pages":e==="asset"?"download-assets":e==="sitemap"?"discovery":e==="timing"&&typeof t?.name=="string"&&t.name.trim()||"crawl")}function Si(e,t,n){let r=Rt(n);return {checkedAt:new Date().toISOString(),currentStep:yi(e,r),level:e,message:xe(t),details:r??{}}}var Fe=class{constructor(t,n,r="info"){this.logDir=t;this.logFile=n;this.level=r;this.ensureLogFileReady();}logDir;logFile;level;startedAt=Date.now();marks=new Map;initPromise=null;writeQueue=Promise.resolve();writeError=null;get logPath(){return S.join(this.logDir,this.logFile)}artifactPath(t){return this.logFile.endsWith(".log.jsonl")?S.join(this.logDir,this.logFile.replace(/\.log\.jsonl$/u,`${t}.jsonl`)):S.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 A.mkdir(this.logDir,{recursive:true}),await A.writeFile(this.logPath,"","utf8");})()),this.initPromise}enqueueTask(t){this.writeQueue=this.writeQueue.then(t).catch(n=>{this.writeError=n instanceof Error?n:new Error(String(n));});}enqueueLine(t){this.enqueueTask(async()=>{await this.ensureLogFileReady(),await A.appendFile(this.logPath,`${t}
|
|
6
|
+
`,"utf8");});}enqueueJsonLine(t,n){this.enqueueTask(()=>wr(t,n));}accepts(t){return ue[t]<=ue[this.level]}push(t,n,r){if(!this.accepts(t))return;let s=xe(n),i=Rt(r),a=JSON.stringify({time:new Date().toISOString(),level:t,message:s,...i||{}});this.enqueueLine(a),t==="error"?console.error(`[ERROR] ${s}`,i?JSON.stringify(i):""):t==="warn"?console.warn(`[WARN] ${s}`,i?JSON.stringify(i):""):console.log(`[${t.toUpperCase().padEnd(5)}] ${s}`);}info(t,n){this.push("info",t,n);}progress(t,n){hr(this.logFile,t,n);}debug(t,n){this.push("debug",t,n);}warn(t,n){this.push("warn",t,n);}reject(t,n,r,s,i){let a={kind:t,url:n,reason:r,...s?{source:s}:{},...i||{}};this.enqueueJsonLine(this.rejectedPath,a),this.accepts("debug")&&this.push("debug",`Rejected ${t} ${n}: ${r}`,a);}error(t,n){this.enqueueJsonLine(this.errorsPath,{message:t,...n||{}}),this.push("error",t,n);}mark(t){this.marks.set(t,Date.now());}endMark(t,n){let r=this.marks.get(t);if(!r)return;let s=Date.now()-r,i=Number((s/1e3).toFixed(2));this.push("info",`Timing ${t}: ${i}s`,{name:t,ms:s,seconds:i,...n||{}});}async flush(){let t=Date.now()-this.startedAt,n=Number((t/1e3).toFixed(2));if(this.push("info",`Total time: ${n}s`,{name:"total",ms:t,seconds:n}),await this.writeQueue,this.writeError)throw this.writeError}},Ct=class{constructor(t,n="info"){this.logDir=t;this.level=typeof n=="boolean"?n?"debug":"info":n,this.ensureLogFileReady();}logDir;startedAt=Date.now();marks=new Map;initPromise=null;writeQueue=Promise.resolve();writeError=null;level;get logPath(){return S.join(this.logDir,"crawl.log.jsonl")}get currentEventPath(){return S.join(this.logDir,"current-crawl-event.json")}get rejectedPath(){return S.join(this.logDir,"rejected.jsonl")}get ignoredPath(){return S.join(this.logDir,"ignored.jsonl")}get skippedPath(){return S.join(this.logDir,"skipped-http.jsonl")}get errorsPath(){return S.join(this.logDir,"errors.jsonl")}get timingsPath(){return S.join(this.logDir,"timings.jsonl")}ensureLogFileReady(){return this.initPromise||(this.initPromise=(async()=>{await A.mkdir(this.logDir,{recursive:true}),await A.writeFile(this.logPath,"","utf8");})()),this.initPromise}enqueueTask(t){this.writeQueue=this.writeQueue.then(t).catch(n=>{this.writeError=n instanceof Error?n:new Error(String(n));});}enqueueLine(t){this.enqueueTask(async()=>{await this.ensureLogFileReady(),await A.appendFile(this.logPath,`${t}
|
|
7
|
+
`,"utf8");});}enqueueJsonLine(t,n){this.enqueueTask(()=>wr(t,n));}updateCurrentEvent(t,n,r){let s=Si(t,n,r);this.enqueueTask(async()=>{await A.mkdir(this.logDir,{recursive:true}),await A.writeFile(this.currentEventPath,JSON.stringify(s,null,2),"utf8");});}push(t,n,r){let s=xe(n),i=Rt(r),a=JSON.stringify({time:new Date().toISOString(),level:t,message:s,...i||{}});this.enqueueLine(a),this.updateCurrentEvent(t,s,i),t==="error"?console.error(s,i||""):t==="warn"?console.warn(s,i||""):(ue[this.level]>=ue.debug||["summary","page","sitemap","asset","timing"].includes(t))&&console.log(s);}info(t,n){this.push("info",t,n);}debug(t,n){ue[this.level]<ue.debug||this.push("debug",t,n);}progress(t,n){hr("crawl.log.jsonl",t,n),this.updateCurrentEvent("progress",t,n);}checkpoint(t,n){this.updateCurrentEvent("checkpoint",t,n);}page(t,n){this.push("page",t,n);}sitemap(t,n){this.push("sitemap",t,n);}asset(t,n){this.push("asset",t,n);}warn(t,n){this.push("warn",t,n);}error(t,n){this.enqueueJsonLine(this.errorsPath,{message:t,...n||{}}),this.push("error",t,n);}summary(t,n){this.push("summary",t,n);}mark(t){this.marks.set(t,Date.now());}endMark(t,n){let r=this.marks.get(t);if(!r)return;let s=Date.now()-r,i={name:t,ms:s,seconds:Number((s/1e3).toFixed(2)),...n||{}};this.enqueueJsonLine(this.timingsPath,i),this.push("timing",`Timing ${t}: ${i.seconds}s`,i);}reject(t,n,r,s){let i={kind:t,url:n,reason:r,source:s};this.enqueueJsonLine(this.rejectedPath,i),ue[this.level]>=ue.debug&&this.push("reject",`Rejected ${t} ${n}: ${r}`,i);}ignore(t,n,r,s){let i={kind:t,url:n,reason:r,source:s};this.enqueueJsonLine(this.ignoredPath,i),ue[this.level]>=ue.debug&&this.push("ignore",`Ignored ${t} ${n}: ${r}`,i);}skip(t,n,r,s){let i={kind:t,url:n,status:r,source:s};this.enqueueJsonLine(this.skippedPath,i),this.push("warn",`Skipped ${t} ${n}: HTTP ${r}`,i);}async flush(){let t=Date.now()-this.startedAt,n={name:"total",ms:t,seconds:Number((t/1e3).toFixed(2))};if(this.enqueueJsonLine(this.timingsPath,n),await this.writeQueue,this.writeError)throw this.writeError}};var yr="(?: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 br(e){let t=new RegExp(`(?:https?:)?//[^\\s'"<>\\);]+\\.${yr}(?:[?#][^\\s'"<>\\);]*)?(?=[\\s'"<>\\);]|$)|(?<![A-Za-z0-9._-])/[^\\s'"<>\\);]+\\.${yr}(?:[?#][^\\s'"<>\\);]*)?(?=[\\s'"<>\\);]|$)`,"gi");return [...e.matchAll(t)].map(n=>n[0])}function Sr(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 Pr(e){let t=new Set,n=[],r=/\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 i of e.matchAll(r))i[1]&&Sr(i[1])&&n.push({index:i.index??0,value:i[1]});for(let i of e.matchAll(s))i[1]&&Sr(i[1])&&n.push({index:i.index??0,value:i[1]});for(let i of n.sort((a,c)=>a.index-c.index))t.add(i.value);return [...t]}function vr(e,t){let n=S.relative(t,e);return n===""||!n.startsWith("..")&&!S.isAbsolute(n)}function Cr(e,t,n,r){let s=S.resolve(e),i=S.resolve(t),a=S.extname(s).toLowerCase();return !vr(s,i)||a!==".html"&&a!==".htm"||n.has(s)?false:!r.some(c=>vr(s,S.resolve(c)))}function Rr(e,t){return typeof e=="string"&&e.length>0&&t?.supported===true&&typeof t.token=="string"&&t.token.length>0&&e===t.token}function xr(e,t){try{let n=new URL(e),r=new URL(t,n);if(r.origin!==n.origin)return !1;let s=n.pathname.replace(/\/+$/,"");if(s&&r.pathname!==s&&!r.pathname.startsWith(`${s}/`))return !1;let i=s?r.pathname.slice(s.length)||"/":r.pathname;return ["/wp-includes/","/wp-content/plugins/","/wp-content/themes/","/wp-content/mu-plugins/"].some(a=>i.startsWith(a))}catch{return false}}function Ir(e){return e<1}function Ar(e){let t=String(e??"").toLowerCase();return t==="strict"?"Strict":t==="lax"?"Lax":t==="none"?"None":"Unspecified"}function Pi(e){let t=e.pathname||"/";if(!t.startsWith("/")||t==="/")return "/";let n=t.lastIndexOf("/");return n<=0?"/":t.slice(0,n)}function et(e){return `${e.name.toLowerCase()}
|
|
8
8
|
${e.domain.toLowerCase()}
|
|
9
|
-
${e.path}`}function
|
|
10
|
-
`,{encoding:"utf8",mode:384}),await A.rename(n,e);}var
|
|
11
|
-
${n}`,40),tokenSource:t.tokenSource?`${t.tokenSource}+site-subscriber`:"site-subscriber"}}async function
|
|
9
|
+
${e.path}`}function Tr(e,t){let n;try{n=new URL(t);}catch{return null}let r=e.split(";"),s=r.shift()?.trim()??"",i=s.indexOf("=");if(i<=0)return null;let a=s.slice(0,i).trim();if(!a||[...a].some(y=>y<=" "||"=;,".includes(y)))return null;let c=n.hostname.toLowerCase(),o=Pi(n),l=null,d=true,u=false,g=false,f="Unspecified",p=false;for(let y of r){let m=y.indexOf("="),h=(m<0?y:y.slice(0,m)).trim().toLowerCase(),w=m<0?"":y.slice(m+1).trim();if(h==="domain"&&w)c=w.toLowerCase();else if(h==="path"&&w.startsWith("/"))o=w;else if(h==="expires"){let P=Date.parse(w);Number.isFinite(P)&&(l=Math.floor(P/1e3),d=false);}else if(h==="max-age"&&/^-?\d+$/u.test(w)){let P=Number.parseInt(w,10);l=Math.floor(Date.now()/1e3)+P,d=false;}else h==="secure"?u=true:h==="httponly"?g=true:h==="samesite"?f=Ar(w):h==="partitioned"&&(p=true);}return {name:a,domain:c,path:o,expires:l,session:d,secure:u,httpOnly:g,sameSite:f,partitioned:p}}function vi(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:Ar(e.sameSite),partitioned:e.partitioned===true}}function kr(e,t){let n=new Map(e.map(r=>[et(r),r.value]));return t.filter(r=>n.get(et(r))!==r.value).map(vi)}function Ci(e,t){let n=e.session||t.session;return {...e,expires:n?null:Math.max(e.expires??0,t.expires??0)||null,session:n,secure:e.secure&&t.secure,httpOnly:e.httpOnly&&t.httpOnly,sameSite:e.sameSite===t.sameSite?e.sameSite:"Unspecified",partitioned:e.partitioned&&t.partitioned}}var xt=class{#e=new Map;add(t){if(!t)return;let n={...t,domain:t.domain.toLowerCase(),path:t.path||"/"},r=et(n),s=this.#e.get(r);this.#e.set(r,s?Ci(s,n):n);}addAll(t){for(let n of t)this.add(n);}artifact(){return {schemaVersion:1,observations:[...this.#e.values()].sort((t,n)=>et(t).localeCompare(et(n)))}}};async function It(e,t){await A.mkdir(S.dirname(e),{recursive:true});let n=`${e}.${process.pid}.tmp`;await A.writeFile(n,`${JSON.stringify(t,null,2)}
|
|
10
|
+
`,{encoding:"utf8",mode:384}),await A.rename(n,e);}function tt(e){let t=e;for(let r=0;r<3;r+=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(r=>r==="."||r==="..")?null:t}function nt(e,t){let n=tt(t);if(n===null)throw new Error(`Unsafe output URL pathname: ${t}`);let r=S.resolve(e),s=S.resolve(r,n.replace(/^\/+/,""));if(s!==r&&!s.startsWith(`${r}${S.sep}`))throw new Error(`Output path escapes configured root: ${t}`);return s}var Ai=["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"],Br=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"]),Wr=new Set(["",".html",".htm"]),Ti=new Set([".css",".xml",".xsl",".svg",".json",".html",".htm",".txt",".enc",".jws"]),ki=["/wp-content/","/wp-includes/","/wp-admin/","/static/","/assets/","/build/","/_next/"];function $i(e){let t=[],n="full",r="full",s=false,i=false,a="";for(let c=0;c<e.length;c++){let o=e[c];if(o==="--retry-timeouts")n="retry-timeouts",s=true;else if(o==="--resume")s=true;else if(o==="--resume-rewrite")s=true,i=true;else if(o==="--crawl-mode"){let l=e[++c];if(!l)throw new Error("--crawl-mode requires a value");r=l==="incremental"?"incremental":"full",s||=r==="incremental";}else if(o.startsWith("--crawl-mode="))r=o.slice(13)==="incremental"?"incremental":"full",s||=r==="incremental";else if(o==="--incremental")r="incremental",s=true;else if(o==="--url"){let l=e[++c];if(!l)throw new Error("--url requires a value");n="single-url",s=true,t.push(l);}else if(o.startsWith("--url="))n="single-url",s=true,t.push(o.slice(6));else if(o==="--urls"){let l=e[++c];if(!l)throw new Error("--urls requires a file path");n="single-url",s=true,t.push(`@${l}`);}else if(o==="--content-sync-plan"){let l=e[++c];if(!l)throw new Error("--content-sync-plan requires a file path");n="content-sync",r="incremental",s=true,a=S.resolve(l);}else o.startsWith("--content-sync-plan=")&&(n="content-sync",r="incremental",s=true,a=S.resolve(o.slice(20)));}return {mode:n,crawlMode:r,urls:t,preserveOutput:s,resumeRewrite:i,contentSyncPlanPath:a}}function Mt(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?S.resolve(e):""}function Ei(){let e=Mt();return e?S.join(e,"privacy","cookie-observations.json"):null}function Mi(){let e=Mt();return e?S.resolve(e,".."):""}function Di(){let e=process.env.STATIC_PUBLISHER_WP_ROOT||process.env.WPSUITE_STATIC_PUBLISHER_WP_ROOT||"";return e.trim()?S.resolve(e):""}function Oi(e){let t=e.trim(),n=[{alias:"@storage-root",root:Mi(),requiredEnv:"STATIC_PUBLISHER_RUNTIME_DIR or WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR"},{alias:"@runtime",root:Mt(),requiredEnv:"STATIC_PUBLISHER_RUNTIME_DIR or WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR"},{alias:"@wp-root",root:Di(),requiredEnv:"STATIC_PUBLISHER_WP_ROOT or WPSUITE_STATIC_PUBLISHER_WP_ROOT"}];for(let r of n){if(t!==r.alias&&!t.startsWith(`${r.alias}/`))continue;if(!r.root)return {resolvedPath:null,alias:r.alias,requiredEnv:r.requiredEnv};let s=t.slice(r.alias.length).replace(/^\/+/,"");return {resolvedPath:s?S.resolve(r.root,s):r.root,alias:r.alias}}return {resolvedPath:S.resolve(t)}}function Hr(e){let t=String(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH||"").trim();if(t)return S.resolve(t);let n=Mt();return n?S.join(n,"crawl-manifest.json"):S.join(e.outputDir,".crawl-manifest.json")}function zr(){return {schemaVersion:5,updatedAt:"",pages:{},assets:{}}}function Er(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 Fi(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,changeToken:typeof e.changeToken=="string"?e.changeToken:null,tokenSource:typeof e.tokenSource=="string"?e.tokenSource:null,discoveredAssets:Array.isArray(e.discoveredAssets)?e.discoveredAssets.map(n=>String(n)):[],lastCrawledAt:String(e.lastCrawledAt||""),lastSeenRunId:String(e.lastSeenRunId||""),unreferencedRuns:Math.max(0,Number(e.unreferencedRuns)||0),rewriteComplete:e.rewriteComplete===true||!t}}function pn(e){let t=e?.["content-type"]?.trim();return t||null}function Ui(){return {rewriteTargets:new Set,changedFiles:new Set,deletedFiles:new Set}}function te(e,t,n){let r=pe(t.outputDir,n);r&&(e.changedFiles.add(r),e.deletedFiles.delete(r));}function gn(e,t,n){let r=pe(t.outputDir,n);r&&(e.deletedFiles.add(r),e.changedFiles.delete(r));}function Ie(e,t){e.rewriteTargets.add(S.resolve(t));}async function Li(e){try{let t=await A.readFile(Hr(e),"utf8"),n=JSON.parse(t);if(n&&typeof n=="object"&&n.pages&&typeof n.pages=="object"){if((n.schemaVersion===2||n.schemaVersion===3||n.schemaVersion===4||n.schemaVersion===5)&&n.assets&&typeof n.assets=="object")return {schemaVersion:5,updatedAt:String(n.updatedAt||""),pages:Object.fromEntries(Object.entries(n.pages).map(([r,s])=>[r,Er(s)])),assets:Object.fromEntries(Object.entries(n.assets).map(([r,s])=>[r,Fi(s)]))};if(n.schemaVersion===1)return {schemaVersion:5,updatedAt:String(n.updatedAt||""),pages:Object.fromEntries(Object.entries(n.pages).map(([r,s])=>[r,Er(s)])),assets:{}}}}catch{}return zr()}function fn(e){return JSON.parse(JSON.stringify(e))}async function ji(e,t){let n=Hr(e);await A.mkdir(S.dirname(n),{recursive:true}),await A.writeFile(n,JSON.stringify(t,null,2),"utf8");}async function ve(e,t){if(!t.trackManifest)return;let n=async()=>{let r=fn(t.manifest);r.updatedAt=new Date().toISOString(),t.manifest.updatedAt=r.updatedAt,await ji(e,r);};t.manifestSaveChain=t.manifestSaveChain.then(n,n),await t.manifestSaveChain;}function it(e){if(!e)return null;let t=e.trim();return t||null}function qi(e,t){let n=new Set,r=new Set([...Object.keys(e),...Object.keys(t)]);for(let s of r){let i=e[s],a=t[s];!i||!a||i===a||n.add(s);}return n}async function Qr(e,t,n,r){let s=[...new Set(n.map(c=>c.trim()).filter(Boolean))],i=String(e.wpsuite?.runtimeToken||"").trim();if(s.length===0||!i)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":i},data:JSON.stringify({urls:s})});if(!c.ok())return r.warn(`Change token lookup failed with HTTP ${c.status()}`,{endpoint:a,status:c.status()}),new Map;let o=await c.json().catch(()=>null);if(!o||!Array.isArray(o.items))return new Map;let l=new Map;for(let d of o.items)!d||typeof d.url!="string"||l.set(d.url,d);return l}catch(c){return r.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 Tt(e,t,n,r,s){if(!n.enabled&&!n.trackManifest)return null;if(n.changeTokenCache.has(r))return n.changeTokenCache.get(r)??null;let a=(await Qr(e,t,[r],s)).get(r)??null;return bn(e,r)&&(!a||a.supported!==true||!a.token)&&(a=await Bi(e,t,r,s)),a=Jr(e,a),n.changeTokenCache.set(r,a),a}async function _i(e,t,n,r,s){if(!n.trackManifest)return;let i=[...new Set(r.map(a=>a.trim()).filter(Boolean))].filter(a=>!n.changeTokenCache.has(a));for(let a=0;a<i.length;a+=250){let c=i.slice(a,a+250),o=await Qr(e,t,c,s);for(let l of c)n.changeTokenCache.set(l,Jr(e,o.get(l)??null));}}function Ni(e){return `subscriber=${e.wpsuite?.siteSettings?.subscriber===true?"1":"0"}`}function Jr(e,t){if(!t?.supported||!t.token||t.tokenSource==="wp-media-file")return t;let n=Ni(e);return {...t,token:Ye(`${t.token}
|
|
11
|
+
${n}`,40),tokenSource:t.tokenSource?`${t.tokenSource}+site-subscriber`:"site-subscriber"}}async function Bi(e,t,n,r){try{let s=await t.get(n,{timeout:Math.min(e.navigationTimeoutMs,15e3),failOnStatusCode:!1});if(s.status()!==404)return r.warn(`Generated 404 fallback token skipped for ${n}`,{url:n,status:s.status(),requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),null;let i=await s.text().catch(()=>""),a=Ye(`${n}
|
|
12
12
|
404
|
|
13
|
-
${i}`,40);return r.info(`Using generated 404 fallback change token for ${n}`,{url:n,requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),{url:n,supported:!0,token:a,tokenSource:"generated-404-response-hash",postId:null,dependencyPostIds:[],reason:null}}catch(s){return r.warn(`Generated 404 fallback token lookup failed for ${n}`,{url:n,error:String(s),requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),null}}async function _i(e,t,n,r,s,i){let a=wn(e,s);if(!r.enabled)return {action:"render",changeToken:r.trackManifest?await xt(e,t,r,s,i):null};let c=r.manifest.pages[s];if(!c)return {action:"render",changeToken:await xt(e,t,r,s,i)};let o=await xt(e,t,r,s,i);if(o?.supported&&o.token)return c.changeToken===o.token?a&&!await Ni(e,t,s,i)?{action:"render",changeToken:o}:{action:"reuse",changeToken:o}:{action:"render",changeToken:o};let l=nt(n.sitemapLastmodByPage[s]);return l&&c.sitemapLastmod&&c.sitemapLastmod===l?{action:"reuse",changeToken:o}:{action:"render",changeToken:o}}async function Ni(e,t,n,r){try{let i=(await t.get(n,{timeout:Math.min(e.navigationTimeoutMs,15e3),failOnStatusCode:!1})).status();return i===404?!0:(r.warn(`Generated 404 request path no longer returns 404 for ${n}`,{url:n,status:i,requestPath:e.generated404RequestPath,source:"generated-404-status-probe"}),!1)}catch(s){return r.warn(`Generated 404 status probe failed for ${n}`,{url:n,error:String(s),requestPath:e.generated404RequestPath,source:"generated-404-status-probe"}),false}}async function Bi(e,t,n,r,s){let i=kr(n.previousManifest,void 0,r,"previous-manifest"),a=0;for(let[p,f]of Object.entries(n.manifest.pages))if(!n.seenPages.has(p)){un(s,e,f.outputPath);try{await A.unlink(f.outputPath);}catch(g){(g.code||"")!=="ENOENT"&&r.warn(`Failed to remove stale incremental page output for ${p}`,{url:p,outputPath:f.outputPath,error:String(g)});}delete n.manifest.pages[p],a++;}let c=kr(n.manifest,n.runId,r,"active-manifest"),o=new Set,l=new Set;for(let p of c){for(let y of rt(e,p))o.add(y);let f=n.manifest.assets[p]?.outputPath;f&&l.add(f);let g=qe(e,t.assetMap,p);g&&l.add(g);}for(let p of Object.keys(n.manifest.assets)){if(c.has(p)){n.manifest.assets[p].unreferencedRuns=0;continue}let f=n.manifest.assets[p];if(Cr(f.unreferencedRuns)){f.unreferencedRuns+=1,r.warn(`Deferred deletion of newly unreferenced incremental asset ${p}.`,{url:p,unreferencedRuns:f.unreferencedRuns,phase:"incremental-cleanup",source:"asset-deletion-grace"});continue}delete n.manifest.assets[p];}let d=0,u=0;for(let p of i){if(n.manifest.assets[p])continue;let f=new Set,g=n.previousManifest.assets[p]?.outputPath;g&&f.add(g);let y=qe(e,t.assetMap,p);if(!c.has(p)&&y)f.add(y);else if(!c.has(p)){let h=oo(e,p,r,"incremental-cleanup");h&&(f.add(h.originalFilePath),h.hashedFilePath&&f.add(h.hashedFilePath));}for(let h of f)if(!l.has(h)){un(s,e,h);try{await A.unlink(h),d++;}catch(m){(m.code||"")!=="ENOENT"&&r.warn(`Failed to remove stale incremental asset output for ${p}`,{url:p,outputPath:h,error:String(m)});}}for(let h of rt(e,p))o.has(h)||Object.prototype.hasOwnProperty.call(t.assetMap,h)&&(delete t.assetMap[h],u++);}(a>0||d>0||u>0)&&r.info(`Incremental cleanup removed ${a} stale pages, ${d} stale assets, ${u} stale asset mappings`,{removedPages:a,removedAssets:d,removedAssetMappings:u,phase:"incremental-cleanup"});}async function Wi(e,t,n,r){let s=new Set([...Object.values(t.manifest.pages),...Object.values(t.manifest.assets)].map(o=>String(o.outputPath||"").trim()).filter(Boolean).map(o=>S.resolve(o))),i=Object.values(e.postCrawlCopyMap||{}).map(o=>It(String(o||""))).filter(o=>!!o).map(o=>S.resolve(e.outputDir,o)),c=(await Vs(["**/*.html","**/*.htm"],{cwd:e.outputDir,onlyFiles:true,dot:true})).filter(o=>br(S.join(e.outputDir,o),e.outputDir,s,i));for(let o of c){let l=S.join(e.outputDir,o);un(r,e,l),await A.unlink(l);}c.length>0&&n.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 kr(e,t,n,r){let s=new Set,i=a=>{let c=a.trim();if(c){if(n){let o=ve(c,n,"asset",r??"manifest");if(!o)return;s.add(o.toString());return}s.add(c);}};for(let a of Object.values(e.pages))for(let c of a.discoveredAssets||[])i(c);for(let[a,c]of Object.entries(e.assets||{}))t&&c.lastSeenRunId!==t||i(a);return s}function $r(e,t,n){for(let r of t)for(let s of rt(e,r))if(n.has(s))return true;return false}function Hi(e,t,n,r,s){let i=new Set(n.rewriteTargets);for(let c of n.changedFiles)i.add(S.resolve(e.outputDir,c));for(let c of Object.values(t.manifest.pages))c.rewriteComplete||i.add(S.resolve(c.outputPath));for(let c of Object.values(t.manifest.assets))c.isText&&!c.rewriteComplete&&i.add(S.resolve(c.outputPath));let a=Ui(r,s);if(a.size===0)return [...i];for(let c of Object.values(t.manifest.pages))$r(e,c.discoveredAssets,a)&&i.add(S.resolve(c.outputPath));for(let[c,o]of Object.entries(t.manifest.assets)){o.isText&&$r(e,o.discoveredAssets,a)&&i.add(S.resolve(o.outputPath));for(let l of rt(e,c))if(a.has(l)){te(n,e,o.outputPath),o.isText&&i.add(S.resolve(o.outputPath));break}}return [...i]}function zi(e,t){let n=t?new Set(Array.from(t,s=>S.resolve(s))):null,r=s=>n===null||n.has(S.resolve(s));for(let s of Object.values(e.manifest.pages))r(s.outputPath)&&(s.rewriteComplete=true);for(let s of Object.values(e.manifest.assets)){if(!s.isText){s.rewriteComplete=true;continue}r(s.outputPath)&&(s.rewriteComplete=true);}}function Qi(e,t,n){let r=new Set,s=i=>{if(!i)return;let a=Se(e.outputDir,i);a&&r.add(a);};for(let i of t.donePages)s(ge(e,i));for(let i of Object.values(n.manifest.pages))i.lastSeenRunId===n.runId&&s(i.outputPath);for(let i of t.doneAssets)s(qe(e,t.assetMap,i));for(let i of Object.values(n.manifest.assets))i.lastSeenRunId===n.runId&&s(i.outputPath);return r}async function Ji(e,t,n,r,s){let i=[...r.deletedFiles].sort(),a=Qi(e,t,n),c=0;for(let d of [...a].sort()){try{if((await A.stat(S.join(e.outputDir,d))).isFile())continue}catch{}c++,s.warn(`Active output is missing after crawl: ${d}`,{phase:"deploy-plan",file:d,outputPath:S.join(e.outputDir,d)});}if(c>0&&s.warn(`Detected ${c} active output file(s) missing before deploy plan save.`,{phase:"deploy-plan",missingActiveOutputs:c}),i.length===0)return [];let o=[],l=0;for(let d of i){if(!a.has(d)){o.push(d);continue}l++;let u=S.join(e.outputDir,d),p;try{p=(await A.stat(u)).isFile();}catch{p=false;}s.warn(`Deploy plan protected active output from deletion: ${d}`,{phase:"deploy-plan",file:d,outputPath:u,exists:p});}return l>0&&s.info(`Deploy plan skipped ${l} active output deletion(s).`,{phase:"deploy-plan",protectedDeletes:l,deletedFiles:o.length}),o}function rt(e,t){let n=new Set([t]);try{let r=new URL(t),i=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{i.push(new URL(e.targetOrigin).origin);}catch{}for(let a of i)try{n.add(new URL(a).origin+r.pathname+r.search);}catch{}n.add(r.pathname+r.search),n.add(r.pathname);}catch{}return [...n]}function Vi(e,t){let n=new Set([t]);try{let r=new URL(t),i=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{i.push(new URL(e.targetOrigin).origin);}catch{}for(let a of i)try{n.add(new URL(a).origin+r.pathname+r.search);}catch{}n.add(r.pathname+r.search);}catch{}return [...n]}function zr(e,t){let n=e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/"?e.targetOrigin:"https://relative.invalid/";try{let r=new URL(t,n);return S.join(e.outputDir,hn(r.pathname))}catch{return null}}function Ki(e,t,n){for(let r of Vi(e,n)){let s=t[r];if(!s)continue;let i=zr(e,s);if(i)return {outputPath:i,publicUrl:s}}return null}function Gi(e,t,n){for(let r of rt(e,n)){let s=t[r];if(!s)continue;let i=zr(e,s);if(i)return i}return null}function qe(e,t,n){let r=Gi(e,t,n);if(r)return r;try{return $t(e,n).originalFilePath}catch{return null}}function Zi(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?S.join(S.resolve(e),"queue-runner-heartbeat.json"):""}async function Er(e){let t=Zi();if(t)try{let n=await A.readFile(t,"utf8"),r=JSON.parse(n);if(!r||typeof r!="object")return;await A.writeFile(t,JSON.stringify({...r,checkedAt:new Date().toISOString(),status:"running",currentStep:"rewrite",message:e},null,2),"utf8");}catch{}}function Yi(e,t){let n=new Set;for(let r of t.donePages)n.add(S.resolve(ge(e,r)));for(let r of t.doneAssets){let s=qe(e,t.assetMap,r);!s||!be(s)||n.add(S.resolve(s));}for(let r of t.doneSitemaps){let s=qe(e,t.assetMap,r);!s||!be(s)||n.add(S.resolve(s));}return [...n]}var At="re:",Ct=new Map;function Xi(e){if(!e.startsWith(At))return null;let t=Ct.get(e);if(t!==void 0)return t||null;let n=e.slice(At.length).trim();if(!n)return Ct.set(e,false),null;try{let r=new RegExp(n);return Ct.set(e,r),r}catch{return console.warn(`[crawl] Ignoring invalid path matcher regex: ${e}`),Ct.set(e,false),null}}function mn(e,t){let n=Xi(t);return n?n.test(e):t.startsWith(At)?false:e.startsWith(t)}function eo(e,t){return t.find(n=>mn(e,n))}function Qr(e,t){let n=eo(t.pathname,e.blockedPathPrefixes);if(n)return n.startsWith(At)?`blocked path regex: ${n}`:`blocked path prefix: ${n}`;let r=e.blockedSearchFragments.find(s=>t.search.includes(s));return r?`blocked search fragment: ${r}`:null}function to(e){let t=new URL(e.sourceOrigin),n=new Set([t.hostname,...e.allowedAssetHosts]);if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{n.add(new URL(e.targetOrigin).hostname);}catch{}for(let r of Object.keys(e.extraReplacements||{}))try{n.add(new URL(r).hostname);}catch{}return n}function no(e,t){return to(e).has(t.hostname)}function ro(e){let t=de(e.trim()).replace(/\\\//g,"/").replace(/^['"]|['"]$/g,"").trim();return t=t.replace(/[)]+$/g,"").trim(),t=t.replace(/;.*$/g,"").trim(),t}function dn(e){let t=de(e).replace(/\\\//g,"/");return /[{}]|\bwindow\.|\blocation\.|\bincludes\(|\?\?null|\+|%7B|%7D|%22|<|>|\s/.test(t)||/[()[\]'"]/.test(t)}function so(e){let t=de(e).replace(/\\\//g,"/").trim(),n=S.extname(t).toLowerCase();return qr.has(n)||_r.has(n)?false:/^(?:this|[A-Za-z_$][\w$]*)\.[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(t)}function _e(e){return Ii.some(t=>e.pathname.startsWith(t))}function J(e,t,n=e.sourceOrigin,r,s="url",i=false){let a=ro(t);if(!a||a.startsWith("data:")||a.startsWith("blob:")||a.startsWith("mailto:")||a.startsWith("tel:")||a.startsWith("#"))return r?.ignore(s,t,"empty or unsupported scheme",n),null;if(dn(a))return r?.ignore(s,t,"looks like JavaScript/code fragment",n),null;if(so(a))return r?.ignore(s,t,"looks like JavaScript property access",n),null;try{let c=new URL(a,n);if(Jr(c))return r?.reject(s,t,"malformed URL encoding",n),null;if(!["http:","https:"].includes(c.protocol))return r?.ignore(s,t,"unsupported protocol: ",n),null;if(!no(e,c))return r?.ignore(s,c.toString(),"host not allowed",n),null;let o=Qr(e,c);if(o&&!(i&&Jt(c)))return r?.reject(s,c.toString(),o,n),null;let l=new URL(e.sourceOrigin);return c.protocol=l.protocol,c.host=l.host,c.hash="",c}catch{return r?.reject(s,t,"invalid URL",n),null}}function Jr(e){try{return decodeURIComponent(e.pathname),decodeURIComponent(e.search),decodeURIComponent(e.hash),!1}catch{return true}}function ve(e,t,n,r){try{let s=new URL(e);return Jr(s)?(t.reject(n,e,"malformed URL encoding",r),null):s.protocol!=="http:"&&s.protocol!=="https:"?(t.reject(n,e,`unsupported protocol: ${s.protocol}`,r),null):s}catch{return t.reject(n,e,"invalid URL",r),null}}function Vr(e){return qr.has(S.extname(e.pathname).toLowerCase())}function Ce(e){return _e(e)?false:_r.has(S.extname(e.pathname).toLowerCase())}function Ne(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function W(e,t){return !!(Ne(t)||t.pathname==="/robots.txt"||t.pathname==="/llms.txt"||t.pathname.toLowerCase().endsWith(".xsl")||e.assetPathPrefixes.length>0&&e.assetPathPrefixes.some(n=>mn(t.pathname,n))||Vr(t)||!Ce(t)&&!_e(t))}function ge(e,t){let n=new URL(t),r=hn(n.pathname);return r.endsWith("/")?r+="index.html":S.extname(r)||(r+="/index.html"),S.join(e.outputDir,r)}function hn(e){try{return decodeURIComponent(e)}catch{return e}}function io(e){if(!e.generated404RequestPath)return null;try{let t=new URL(e.generated404RequestPath,e.sourceOrigin);return !t.pathname.endsWith("/")&&S.extname(t.pathname)===""&&(t.pathname+="/"),t.hash="",t.toString()}catch{return null}}function wn(e,t){let n=io(e);if(!n)return false;try{return new URL(t,e.sourceOrigin).toString()===n}catch{return false}}function $t(e,t){let n=new URL(t),r=hn(n.pathname);r.endsWith("/")&&(r+="index.html");let s=!!n.search,i=r,a=S.join(e.outputDir,i),c=tn(e.targetOrigin,i),o=`${c}${n.search}`;if(!s)return {originalPathname:i,originalFilePath:a,originalPublicUrl:c,originalPublicUrlWithSearch:o,preferQueryHashed:s};let l=S.extname(r),u=`${l?r.slice(0,-l.length):r}.${Ye(n.search)}${l||".bin"}`;return {originalPathname:i,originalFilePath:a,originalPublicUrl:c,originalPublicUrlWithSearch:o,preferQueryHashed:s,hashedPathname:u,hashedFilePath:S.join(e.outputDir,u),hashedPublicUrl:tn(e.targetOrigin,u)}}function oo(e,t,n,r){let s=ve(t,n,"asset",r);return s?$t(e,s.toString()):null}function ao(e,t,n,r,s){t[n]=r;try{let i=new URL(n),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 o of c)try{let l=new URL(o);t[l.origin+i.pathname+i.search]=r;}catch{}try{let o=(()=>{let l=new URL(r,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin);return `${l.pathname}${l.search}`})();t[i.pathname+i.search]=o;}catch{}try{let o=new URL(r,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[i.pathname]=o;}catch{}try{let o=new URL(s,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[i.pathname]=o;}catch{}}catch{}}async function Kr(e){try{return await A.readFile(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}async function je(e){try{return await A.stat(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}function co(e){let t=String(e["content-length"]||"").trim();if(!t)return null;let n=Number.parseInt(t,10);return Number.isFinite(n)&&n>=0?n:null}function Gr(e){let t=String(e["last-modified"]||"").trim();if(!t)return null;let n=Date.parse(t);return Number.isFinite(n)?n:null}function uo(e,t){let n=Gr(t),r=co(t),s=e?.mtime.getTime();return n!==null&&Math.abs((s??0)-n)>=1e3||r!==null&&e?.size!==r?false:n!==null||r!==null}async function lo(e,t){if(!t)return;let n=Gr(t);if(n===null)return;let r=await je(e);if(!r)return;let s=new Date(n);await A.utimes(e,r.atime,s).catch(()=>{});}function Mr(e,t){let n=S.extname(e.pathname).toLowerCase(),r=t["content-type"]||"";return xi.has(n)||Ri.some(s=>r.includes(s))&&!r.startsWith("image/")&&!r.includes("font")}function po(e){try{let t=S.extname(new URL(e).pathname).toLowerCase();return t===".js"||t===".mjs"}catch{return false}}function Le(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 go(e){return Ye(e.toString("base64"),40)}function fo(e,t,n){let r=e.assetVariantDigestsByOriginalPath.get(t);if(!r||r.size===0)return false;for(let s of r)if(s!==n)return true;return false}function mo(e,t,n){let r=e.assetVariantDigestsByOriginalPath.get(t);r||(r=new Set,e.assetVariantDigestsByOriginalPath.set(t,r)),r.add(n);}async function pn(e,t,n,r,s,i,a){let c=$t(e,n),o=go(r),l=c.originalFilePath,d=c.originalPublicUrlWithSearch;if(c.preferQueryHashed&&c.hashedFilePath&&c.hashedPublicUrl&&fo(s,c.originalFilePath,o)){let g=Ki(e,t,n);g?(l=g.outputPath,d=g.publicUrl):(l=c.hashedFilePath,d=c.hashedPublicUrl);}ao(e,t,n,d,c.originalPublicUrl);let u=be(l)?Buffer.from(sn(r.toString("utf8"),e,t,l),"utf8"):r,p=await Kr(l),f=false;return (p===null||!p.equals(u))&&(await Xe(l,u),f=true),i?.debug(`${f?"Saved":"Skipped unchanged"} asset output ${n}`,{phase:"download-assets",url:n,outputPath:l,bytes:u.length,wroteFile:f}),mo(s,c.originalFilePath,o),await lo(l,a),s.stats.assetsSaved++,i&&(s.stats.assetsSaved%50===0||s.stats.assetsSaved===1)&&i.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:l,publicUrl:d,wroteFile:f}}function st(e,t,n,r,s){let i=()=>{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 p=new URL(u);return Ne(p)?{discoveredFrom:u,discoveredFromType:"sitemap"}:W(e,p)?{discoveredFrom:u,discoveredFromType:"asset"}:Ce(p)&&!_e(p)?{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=J(e,n,a,r,"page");if(!c)return;if(!Ce(c)||Vr(c)){if(W(e,c)){r.info(`Seeded/non-page URL queued as asset: ${c.toString()}`,{url:c.toString(),source:s}),Q(e,t,c.toString(),r,s);return}r.reject("page",c.toString(),_e(c)?"asset/internal path cannot be page":"not page-like",s);return}let o=c.toString(),{discoveredFrom:l,discoveredFromType:d}=i();l&&!t.pageDiscoverySources.has(o)&&t.pageDiscoverySources.set(o,l),!t.donePages.has(o)&&!t.queuedPages.has(o)&&(t.queuedPages.add(o),t.pageQueue.push(o),t.stats.pagesQueued++,r.debug(`Queued discovered page ${o}`,{phase:"discovery",url:o,discoveredFrom:l,discoveredFromType:d,outputPath:ge(e,o)}),(t.stats.pagesQueued%25===0||t.stats.pagesQueued===1)&&r.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,n,r,s){let i=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,a=J(e,n,i,r,"asset");if(!a)return;if(!W(e,a)){r.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)&&r.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 Tt(e,t,n,r,s){let i=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,a=J(e,n,i,r,"sitemap",Qn(s));if(!a)return;if(!Ne(a)){r.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)&&r.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 ho(e){let t=de(e),n=[...t.matchAll(/<url>\s*([\s\S]*?)\s*<\/url>/gi)].map(r=>r[1]);return n.length>0?n.map(r=>{let s=r.match(/<loc>\s*([^<]+?)\s*<\/loc>/i);if(!s?.[1])return null;let i=r.match(/<lastmod>\s*([^<]+?)\s*<\/lastmod>/i);return {loc:s[1].trim(),lastmod:nt(i?.[1]??null)}}).filter(r=>!!r):[...t.matchAll(/<loc>\s*([^<]+?)\s*<\/loc>/gi)].map(r=>({loc:r[1].trim(),lastmod:null})).filter(r=>r.loc)}function wo(e){return e.split(",").map(t=>t.trim().split(/\s+/)[0]).filter(Boolean)}function yo(e){let t=[],n=/url\(\s*(?:"([^"]+)"|'([^']+)'|([^)]*?))\s*\)/gi;for(let r of e.matchAll(n)){let s=e.slice(Math.max(0,r.index-8),r.index);if(/\bnew\s+$/i.test(s))continue;let i=(r[1]||r[2]||r[3]||"").trim();i&&t.push(i);}return t}function So(e){return e.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>/gi,"")}function bo(e,t){if(t==="dom-style")return true;let n=(()=>{try{return S.extname(new URL(e).pathname).toLowerCase()}catch{return ""}})();return !(n===".js"||n===".mjs"||n===".map"||t.includes("javascript"))}function It(e){return e.trim().replace(/\\/g,"/").replace(/^https?:\/\/[^/]+/i,"").replace(/^\/+/,"")}async function Zr(e,t,n,r){let s=[];await A.mkdir(t,{recursive:true});let i=await A.readdir(e,{withFileTypes:true});for(let a of i){let c=S.join(e,a.name),o=S.join(t,a.name);if(a.isDirectory()){s.push(...await Zr(c,o,n,r));continue}await Yr(c,o,n,r)&&s.push(o);}return s}async function Po(e,t){try{let[n,r]=await Promise.all([A.stat(e),A.stat(t)]);if(n.size!==r.size)return !1;let[s,i]=await Promise.all([A.readFile(e),A.readFile(t)]);return s.equals(i)}catch{return false}}async function Yr(e,t,n,r){let s=S.resolve(t);return n.has(s)?(r.debug("Skipped post-crawl copy over crawled page output",{phase:"copy-extra-paths",sourcePath:e,targetPath:t}),false):await Po(e,t)?(r.debug("Skipped unchanged post-crawl copy target",{phase:"copy-extra-paths",sourcePath:e,targetPath:t}),false):(await A.mkdir(S.dirname(t),{recursive:true}),await A.copyFile(e,t),true)}async function vo(e,t,n){let r=Object.entries(e.postCrawlCopyMap||{}).map(([c,o])=>({sourcePath:c.trim(),prefix:String(o||"").trim()}));if(r.length===0)return [];let s=0,i=[],a=new Set([...t.donePages].map(c=>S.resolve(ge(e,c))));n.mark("copy-extra-paths");for(let c of r){let o=c.sourcePath,l=c.prefix;if(!o||!l){n.warn("Skipped post-crawl copy mapping with empty key/value",{sourcePath:o,prefixPath:l});continue}let d=Ei(o);if(!d.resolvedPath){n.warn("Skipped post-crawl copy source because alias root is not configured",{sourcePath:o,alias:d.alias||"",requiredEnv:d.requiredEnv||"",prefixPath:l});continue}let u=d.resolvedPath,p=It(l);if(!p){n.warn("Skipped post-crawl copy mapping with invalid export prefix",{sourcePath:o,prefixPath:l});continue}let f;try{f=await A.stat(u);}catch{n.warn("Skipped post-crawl copy source because it does not exist",{sourcePath:o,sourceAbs:u,prefixPath:l});continue}let g=S.resolve(e.outputDir,p);if(f.isDirectory()){let w=await Zr(u,g,a,n);i.push(...w),s+=w.length,w.length>0&&n.progress(`Copied static directory to export: ${u} -> /${p}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${p}`,copiedItems:s,changedFiles:w.length});continue}let y=S.basename(u),h=l.endsWith("/")?S.join(g,y):g;await Yr(u,h,a,n)&&(i.push(h),s++,n.progress(`Copied static file to export: ${u} -> /${It(l.endsWith("/")?`${l}${y}`:l)}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${It(l.endsWith("/")?`${l}${y}`:l)}`,copiedItems:s}));}return n.endMark("copy-extra-paths",{mappedSources:r.length,copiedItems:s}),i}function it(e,t,n,r,s){let i=new Set,a=de(n).replace(/\\\//g,"/"),c=s==="page-html"?So(a):a,o=bo(t,s);if(o){for(let l of yo(c)){let d=J(e,l,t,r,`${s}:css-url`);d&&W(e,d)&&i.add(d.toString());}for(let l of c.matchAll(/@import\s+(?:url\()?\s*['"]?([^'"\s;]+)['"]?\s*\)?/gi)){let d=J(e,l[1],t,r,`${s}:css-import`);d&&W(e,d)&&i.add(d.toString());}}if(o||s==="page-html")for(let l of c.matchAll(/<\?xml-stylesheet[^>]+href=["']([^"']+)["'][^>]*\?>/gi)){let d=J(e,l[1],t,r,`${s}:xml-stylesheet`);d&&W(e,d)&&i.add(d.toString());}if(s==="page-html")for(let l of wr(a)){let d=l.startsWith("//")?`${new URL(e.sourceOrigin).protocol}${l}`:l;if(dn(d)){r.ignore(`${s}:serialized-url`,d,"looks like JavaScript/code fragment",t);continue}let u=J(e,d,t,r,`${s}:serialized-url`);u&&W(e,u)?i.add(u.toString()):u&&r.ignore("asset",u.toString(),"serialized URL did not pass safe asset path filter",t);}if(s!=="page-html"&&po(t))for(let l of yr(a)){if(dn(l)||!/\.(?:js|mjs)(?:[?#]|$)/i.test(l))continue;let d=J(e,l,t,r,`${s}:relative-asset`);d&&W(e,d)&&i.add(d.toString());}return [...i]}function Co(e,t,n,r){let s=new Set,i=de(n);for(let a of i.matchAll(/href=["']([^"'#\s][^"']*?)["']/gi)){let c=a[1],o=J(e,c,t,r,"page-link");o&&(Qr(e,o)||Ce(o)&&!_e(o)&&!W(e,o)&&s.add(o.toString()));}return [...s]}async function Dr(e,t,n,r,s,i,a=false,c=[]){let o=new Set(c),l=0,d=new Map,u=(p,f)=>{let g=[f],y=new Set;for(;g.length>0;){let h=g.pop();if(h===p)return true;y.has(h)||(y.add(h),g.push(...d.get(h)??[]));}return false};for(;n.sitemapQueue.length>0;){let p=n.sitemapQueue.shift();n.queuedSitemaps.delete(p);let f=ve(p,r,"sitemap","sitemap-queue");if(!f)continue;let g=f.toString();if(n.doneSitemaps.has(g))continue;n.doneSitemaps.add(g),r.sitemap(`Fetching sitemap ${g}`,{url:g});let y=true;try{let h=await t.get(g,{timeout:6e4});if(y=!1,!h.ok()){if(r.skip("sitemap",g,h.status()),a&&!o.has(g))throw new Error(`Required child content-sync sitemap returned HTTP ${h.status()}: ${g}`);continue}let m=await h.body(),w=h.url()||g,P=ve(w,r,"sitemap-response",g);if(!P)continue;let x=P.toString();n.successfulSitemaps.add(g),n.successfulSitemaps.add(x),o.has(g)&&(n.resolvedSitemapRoots.add(x),l+=1);let j=await pn(e,n.assetMap,x,m,n,r);te(s,e,j.outputPath),xe(s,j.outputPath);let M=m.toString("utf8");/<sitemapindex(?:\s|>)/i.test(M)?n.sitemapIndexUrls.add(x):n.sitemapLeafUrls.add(x);let _=it(e,x,M,r,"sitemap");for(let $ of _)Q(e,n,$,r,x);let C=[];for(let $ of ho(M)){let R=J(e,$.loc,x,r,"sitemap-loc",!0);if(!R){if(a)throw new Error(`Content-sync sitemap contains an inadmissible location: ${$.loc}`);continue}if(Ne(R)){if(u(x,R.toString()))throw new Error(`Sitemap index cycle detected: ${x} -> ${R.toString()}`);if(d.has(x)||d.set(x,new Set),d.get(x).add(R.toString()),C.push(R.toString()),a&&n.doneSitemaps.has(R.toString())&&!n.successfulSitemaps.has(R.toString()))throw new Error(`Required child content-sync sitemap was not resolved: ${R.toString()}`);Tt(e,n,R.toString(),r,x);}else if(a){if(Ce(R)&&!W(e,R)){let D=i.requiredUrls.has(R.toString()),b=i.manifest.pages[R.toString()],T=!!b&&!!await je(b.outputPath);if(!D&&!T)throw new Error(`Content-sync sitemap coverage is incomplete for ${R.toString()}.`)}r.ignore("sitemap-loc",R.toString(),"content-sync sitemap-only traversal does not enqueue urlset locations",x);}else W(e,R)?Q(e,n,R.toString(),r,x):Ce(R)?($.lastmod&&(n.sitemapLastmodByPage[R.toString()]=$.lastmod),st(e,n,R.toString(),r,x)):r.reject("sitemap-loc",R.toString(),"not page/sitemap/asset-like",x);}i.trackManifest&&(i.manifest.assets[x]={url:x,outputPath:j.outputPath,isText:!0,contentType:h.headers()["content-type"]??"application/xml",changeToken:null,tokenSource:null,discoveredAssets:[...new Set([..._,...C])],lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,unreferencedRuns:0,rewriteComplete:!1},await Pe(e,i));}catch(h){r.error(`Failed sitemap ${g}`,{url:g,error:String(h)});let m=a&&o.has(g)&&y;if(a&&!m)throw h}}if(a&&o.size>0&&l===0)throw new Error(`None of the configured content-sync sitemap roots could be resolved: ${[...o].join(", ")}`)}async function Ro(e,t,n,r,s,i,a){let c=J(e,r,e.sourceOrigin,s,"asset-fetch");if(!c||!W(e,c))return;let o=c.toString();if(n.doneAssets.has(o))return;let l=i.enabled||i.strictTargeted?i.previousManifest.assets[o]:void 0,d=i.trackManifest?await xt(e,t,i,o,s):null,u=d?.token??null,p=Pr(l?.changeToken,d),f=i.strictTargeted&&(!d?.supported||!d.token)&&vr(e.sourceOrigin,o),g=i.strictTargeted?i.manifest.assets[o]:void 0;if(g?.lastSeenRunId===i.runId&&await je(g.outputPath)){n.doneAssets.add(o);for(let h of g.discoveredAssets||[])Q(e,n,h,s,o);te(a,e,g.outputPath),g.isText&&xe(a,g.outputPath),s.info(`Resumed completed content-sync asset ${o}`,{url:o,source:"content-sync-checkpoint"}),Le(n,s);return}if(l&&(p||f)&&await je(l.outputPath)){i.manifest.assets[o]={...l,changeToken:u,tokenSource:d?.tokenSource??l.tokenSource,discoveredAssets:[...l.discoveredAssets||[]],lastSeenRunId:i.runId,unreferencedRuns:0},delete i.manifest.pages[o],n.doneAssets.add(o);for(let h of l.discoveredAssets||[])Q(e,n,h,s,o);s.info(`Reused unchanged trusted asset ${o}.`,{url:o,tokenSource:d?.tokenSource??"unknown",phase:"download-assets",source:p?"asset-change-token-match":"content-sync-release-fingerprint"}),Le(n,s);return}let y=(h,m={})=>{if(!l||i.strictTargeted)return false;i.manifest.assets[o]={...l,discoveredAssets:[...l.discoveredAssets||[]],lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,unreferencedRuns:0},delete i.manifest.pages[o],n.doneAssets.add(o);for(let w of l.discoveredAssets||[])Q(e,n,w,s,o);return s.warn(`Keeping previous incremental asset ${o} after fetch issue.`,{url:o,reason:h,preservedFromPreviousManifest:true,...m,phase:"download-assets"}),Le(n,s),true};s.asset(`Fetching asset ${o}`,{url:o});try{let h=qe(e,n.assetMap,o),m=h?await je(h):null;if(h&&m)try{let D=await H(`fetch asset headers ${o}`,6e4,()=>t.head(o,{timeout:6e4})),b=D.headers();if(D.ok()&&uo(m,b)){let T=await Kr(h);if(T!==null){let U=D.url()||o,q=ve(U,s,"asset-response",o);if(!q)return;let v=q.toString(),E=await pn(e,n.assetMap,v,T,n,s,b);E.wroteFile&&(te(a,e,E.outputPath),be(E.outputPath)&&xe(a,E.outputPath)),n.doneAssets.add(o),s.info(`Reused existing asset ${o} based on response headers.`,{url:o,filePath:h,lastModified:b["last-modified"]||"",contentLength:b["content-length"]||"",phase:"download-assets"}),Le(n,s);let F=Mr(c,b),z=l?.discoveredAssets?[...l.discoveredAssets]:[];if(F||l?.isText){let ee=T.toString("utf8"),O=it(e,v,ee,s,"asset:cached");(O.length>0||!l)&&(z=O);for(let Ae of z)Q(e,n,Ae,s,v);}if(i.trackManifest){let ee=F||!!l?.isText;i.manifest.assets[o]={url:o,outputPath:E.outputPath,isText:ee,contentType:cn(b)||l?.contentType||null,changeToken:d?.supported?d.token:null,tokenSource:d?.supported?d.tokenSource??null:null,discoveredAssets:z,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,unreferencedRuns:0,rewriteComplete:!ee},delete i.manifest.pages[o],(i.enabled||i.strictTargeted)&&ee&&await Pe(e,i);}return}}}catch{}let w=await H(`fetch asset ${o}`,6e4,()=>t.get(o,{timeout:6e4}));if(!w.ok()){if(y(`http-${w.status()}`,{status:w.status()}))return;if(i.strictTargeted)throw new Error(`Required content-sync asset returned HTTP ${w.status()}: ${o}`);s.skip("asset",o,w.status());return}let P=await H(`read asset response ${o}`,6e4,()=>w.body()),x=w.url()||o,j=ve(x,s,"asset-response",o);if(!j)return;let M=j.toString(),_=w.headers(),C=await pn(e,n.assetMap,M,P,n,s,_);C.wroteFile&&(te(a,e,C.outputPath),be(C.outputPath)&&xe(a,C.outputPath)),n.doneAssets.add(o),Le(n,s);let $=Mr(c,_),R=[];if($){let D=P.toString("utf8");R=it(e,M,D,s,`asset:${S.extname(c.pathname).toLowerCase()||_["content-type"]||"unknown"}`);for(let b of R)Q(e,n,b,s,M);}i.trackManifest&&(i.manifest.assets[o]={url:o,outputPath:C.outputPath,isText:$,contentType:cn(_),changeToken:d?.supported?d.token:null,tokenSource:d?.supported?d.tokenSource??null:null,discoveredAssets:R,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,unreferencedRuns:0,rewriteComplete:!$},delete i.manifest.pages[o],(i.enabled||i.strictTargeted)&&$&&await Pe(e,i));}catch(h){if(y("fetch-error",{error:String(h)}))return;if(s.error(`Failed asset ${o}`,{url:o,error:String(h)}),i.strictTargeted)throw h}finally{n.doneAssets.has(o)||(n.doneAssets.add(o),Le(n,s));}}async function xo(e,t,n,r,s,i){let a=Math.max(1,Number(e.assetDownloadConcurrency||e.concurrency||1)),c=Array.from({length:a},async()=>{for(;n.assetQueue.length>0;){let o=n.assetQueue.shift();o&&(n.queuedAssets.delete(o),await Ro(e,t,n,o,r,s,i));}});await Promise.all(c);}function Io(e){let t=Math.ceil(e/1e3);return `${t} second${t===1?"":"s"}`}function pe(e){return Math.max(6e4,e.navigationTimeoutMs*2,e.readiness.timeoutMs+e.readiness.fallbackWaitMs+15e3)}function tt(e){return Math.max(15e3,Math.min(6e4,pe(e)))}function Ao(e){return Math.max(15e3,e.readiness.timeoutMs+e.readiness.fallbackWaitMs+1e4)}function yn(e){return e.stats.pagesCompleted}function gn(e){let n=e.options?.browserProcess;return {pid:typeof n?.process?.pid=="number"?n.process.pid:null,kill:typeof n?.kill=="function"?n.kill.bind(n):null}}async function an(e,t,n){let r=gn(e);try{if(r.kill){await r.kill(),t.warn(`Force-killed crawl worker browser after ${n}`,{browserPid:r.pid,reason:n});return}if(r.pid!==null){process.kill(r.pid,"SIGKILL"),t.warn(`Sent SIGKILL to crawl worker browser after ${n}`,{browserPid:r.pid,reason:n});return}t.warn(`Could not resolve crawl worker browser PID after ${n}`,{reason:n});}catch(s){t.error(`Failed to force-kill crawl worker browser after ${n}`,{browserPid:r.pid,reason:n,error:String(s)});}}async function H(e,t,n){let r;try{return await Promise.race([n(),new Promise((s,i)=>{r=globalThis.setTimeout(()=>{i(new ot(e,t));},t);})])}finally{r!==void 0&&globalThis.clearTimeout(r);}}var ot=class extends Error{constructor(n,r){super(`${n} timed out after ${Io(r)}.`);this.operation=n;this.timeoutMs=r;this.name="OperationTimeoutError";}operation;timeoutMs};async function To(e,t){let n=Ao(e);await t.evaluate(async r=>{await new Promise(s=>{let i=0,a=700,c=Date.now(),o=()=>{window.clearInterval(l),window.scrollTo(0,0),s();},l=window.setInterval(()=>{if(Date.now()-c>=r.maxDurationMs){o();return}window.scrollBy(0,a),i+=a;let d=document.body?.scrollHeight||0,u=document.documentElement?.scrollHeight||0,p=Math.max(d,u);i>=p+window.innerHeight&&o();},120);});},{maxDurationMs:n});}async function ko(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 To(e,t),await t.waitForTimeout(e.readiness.fallbackWaitMs);}async function $o(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 Eo(e,t){return e.noJavaScriptRenderPathPrefixes.some(n=>mn(t,n))}async function Mo(e,t,n,r,s=true){let i=new Set;if(s){let c=await t.evaluate(()=>{let o=new Set,l=["href","src","poster","data-src","data-lazy-src","data-original","data-bg","data-background","data-href"],d=new Set,u=["srcset","data-srcset","data-lazy-srcset"],p=f=>{f.querySelectorAll("*").forEach(g=>{for(let h of l){let m=g.getAttribute(h);m&&o.add(m);}for(let h of u){let m=g.getAttribute(h);m&&m.split(",").forEach(w=>{let P=w.trim().split(/\s+/)[0];P&&o.add(P);});}let y=g.getAttribute("style");y&&d.add(y),g.shadowRoot&&p(g.shadowRoot);});};return p(document),{attrs:[...o],styles:[...d]}});for(let o of c.attrs)for(let l of wo(o)){let d=J(e,l,n,r,"dom-attr");d&&W(e,d)&&i.add(d.toString());}for(let o of c.styles)for(let l of it(e,n,o,r,"dom-style"))i.add(l);}let a=await t.content();for(let c of it(e,n,a,r,"page-html"))i.add(c);return [...i]}async function Fr(e,t,n,r,s){let i=ge(e,t);await Xe(i,n,"utf8");let a=await A.stat(i);s?.debug(`Saved page output ${t}`,{phase:"save-pages",url:t,outputPath:i,bytes:a.size}),r.stats.pagesSaved++;let c=Math.min(r.stats.pagesQueued,yn(r)+1);s&&(r.stats.pagesSaved%10===0||r.stats.pagesSaved===1)&&s.progress(`Page progress: processed ${c}, rendered ${r.stats.pagesRendered}, saved ${r.stats.pagesSaved}, discovered ${r.stats.pagesQueued}.`,{donePages:c,claimedPages:r.donePages.size,pagesRendered:r.stats.pagesRendered,pagesSaved:r.stats.pagesSaved,pagesQueued:r.stats.pagesQueued,pageQueue:r.pageQueue.length,phase:"save-pages"});}function Do(e){let t=yn(e);return t%5===0||t===1||t===e.stats.pagesQueued}function Fo(e,t){let n=yn(e);t.progress(`Render progress: processed ${n}, rendered ${e.stats.pagesRendered}, saved ${e.stats.pagesSaved}, discovered ${e.stats.pagesQueued}.`,{donePages:n,claimedPages:e.donePages.size,pagesRendered:e.stats.pagesRendered,pagesSaved:e.stats.pagesSaved,pagesQueued:e.stats.pagesQueued,phase:"render-pages"});}async function Oo(e){await e.addInitScript(()=>{Object.defineProperty(window,"__WPSUITE_STATIC_EXPORT__",{value:true,writable:false,configurable:true});let t=n=>{if(n==null||String(n)==="")return true;try{let r=new URL(String(n),window.location.href),s=new URL(window.location.href);return r.hash="",s.hash="",r.href===s.href}catch{return false}};try{let n=window.location.assign.bind(window.location),r=window.location.replace.bind(window.location),s=window.location.reload.bind(window.location);Object.defineProperty(window.location,"assign",{configurable:!0,value:i=>{if(t(i)){console.warn("[smartcloud-static-publisher] blocked same-page location.assign",i??"");return}return n(i)}}),Object.defineProperty(window.location,"replace",{configurable:!0,value:i=>{if(t(i)){console.warn("[smartcloud-static-publisher] blocked same-page location.replace",i??"");return}return r(i)}}),Object.defineProperty(window.location,"reload",{configurable:!0,value:()=>{console.warn("[smartcloud-static-publisher] blocked location.reload");}});}catch{}});}async function Uo(e,t,n){let r=await e.newContext({viewport:t.viewport,userAgent:"WPSuiteStaticPublisher/0.8 Playwright SitemapOnly",ignoreHTTPSErrors:t.ignoreHttpsErrors,...n?{javaScriptEnabled:false}:{}});return n||await Oo(r),r}async function Lo(e,t,n,r,s,i,a,c){let o=await chromium.launch({headless:true}),l=gn(o);l.pid!==null&&n.debug(`Launched crawl worker browser PID ${l.pid}`,{browserPid:l.pid});try{for(;t.pageQueue.length>0;){o||(o=await chromium.launch({headless:!0}),l=gn(o),l.pid!==null&&n.debug(`Relaunched crawl worker browser PID ${l.pid}`,{browserPid:l.pid}));let d=o;if(e.maxPages>0&&t.donePages.size>=e.maxPages)break;let u=t.pageQueue.shift();if(!u)break;t.queuedPages.delete(u);let p=null,f=null,g=!1,y=[],h=new Set;try{let m=ve(u,n,"page","page-queue");if(!m)continue;let w=m.toString();if(u=w,t.queuedPages.delete(u),t.donePages.has(u))continue;t.donePages.add(u),i.enabled&&i.seenPages.add(u);let P=wn(e,u),x=Eo(e,m.pathname);if(!Ce(m)||W(e,m)||_e(m)){if(W(e,m)){n.info(`Worker redirected non-page URL to asset queue: ${u}`,{url:u,source:"worker-guard"}),Q(e,t,u,n,"worker-guard");continue}n.reject("page",u,"guard rejected non-page URL before rendering","worker");continue}let j=i.strictTargeted?i.manifest.pages[u]:void 0;if(j?.lastSeenRunId===i.runId&&await je(j.outputPath)){i.seenPages.add(u);for(let v of j.discoveredAssets||[])Q(e,t,v,n,u);te(a,e,j.outputPath),xe(a,j.outputPath),n.info(`Resumed completed content-sync page ${u}`,{url:u,source:"content-sync-checkpoint"});continue}let M=await _i(e,s,t,i,u,n);if(i.enabled&&r!=="single-url"&&r!=="content-sync"){let v=i.manifest.pages[u];if(M.action==="reuse"&&v){for(let E of v.discoveredAssets)Q(e,t,E,n,u);for(let E of v.discoveredPages)st(e,t,E,n,u);v.lastSeenRunId=i.runId,v.sitemapLastmod=nt(t.sitemapLastmodByPage[u])??v.sitemapLastmod,M.changeToken?.supported&&(v.changeToken=M.changeToken.token,v.tokenSource=M.changeToken.tokenSource??v.tokenSource),n.info(`Incremental reuse skipped unchanged page ${u}`,{url:u,mode:"incremental",reason:M.changeToken?.supported===!0?"change-token-match":"sitemap-lastmod-match"});continue}}p=await H(`create page context ${u}`,pe(e),()=>Uo(d,e,x)),f=await H(`create page ${u}`,pe(e),()=>p.newPage()),y=await p.cookies();let _=!1,C=new Set;await f.route("**/*",async v=>{let E=v.request();try{let F=J(e,E.url(),e.sourceOrigin,n,"network-request");F&&W(e,F)&&(C.add(F.toString()),Q(e,t,F.toString(),n,u));}catch{}if(E.isNavigationRequest()&&E.frame()===f.mainFrame())try{let F=new URL(E.url()),z=new URL(w);if(F.hash="",z.hash="",F.href===z.href){if(_){n.warn(`Blocked same-page navigation/reload for ${u}`,{url:u,requestUrl:E.url()});try{await v.abort("aborted");}catch(ee){n.debug(`Ignored canceled route while blocking reload for ${u}`,{url:u,error:String(ee)});}return}_=!0;}}catch{}try{await v.continue();}catch(F){n.debug(`Ignored canceled network route for ${u}`,{url:u,requestUrl:E.url(),error:String(F)});}}),f.on("response",v=>{try{let F=J(e,v.url(),e.sourceOrigin,n,"network-response");F&&W(e,F)&&(C.add(F.toString()),Q(e,t,F.toString(),n,u));}catch{}let E=v.headerValues("set-cookie").then(F=>{for(let z of F)c.add(xr(z,v.url()));}).catch(()=>{}).then(()=>{});h.add(E),E.finally(()=>h.delete(E));}),n.page(`Rendering ${u}`,{url:u});let $=null,R=null;try{if($=await f.goto(u,{waitUntil:"domcontentloaded",timeout:e.navigationTimeoutMs}),$&&$.ok())try{R=await H(`read response body ${u}`,pe(e),()=>$.text());}catch{R=null;}}catch(v){n.warn(`Navigation issue for ${u}; saving current DOM if available`,{url:u,error:String(v)});}if(r==="content-sync"&&$){let v=ve($.url(),n,"content-sync-final-response",u)?.toString();if(v&&v!==w){if(i.deleteOnMissingUrls.has(u)){await fn(e,i,a,u,i.deleteOnMissingUrls),n.info(`Removed stale content-sync archive route redirected to ${v}`,{url:u,finalResponseUrl:v,source:"content-sync-tombstone"});continue}throw new Error(`Required content-sync route redirected outside its planned URL: ${u} -> ${v}`)}}if(P){let v=$?.status()??null;if(v!==404){n.error(`Generated 404 request path returned unexpected status for ${u}`,{url:u,expectedStatus:404,status:v,requestPath:e.generated404RequestPath});continue}n.info(`Capturing rendered 404 page for ${u}`,{url:u,status:v,outputPath:ge(e,u)});}else if($&&!$.ok()){if(r==="content-sync"&&($.status()===404||$.status()===410)&&i.deleteOnMissingUrls.has(u)){await fn(e,i,a,u,i.deleteOnMissingUrls),n.info(`Removed stale content-sync archive page ${u}`,{url:u,status:$.status(),source:"content-sync-tombstone"}),await f.close();continue}if(r==="content-sync")throw new Error(`Required content-sync route returned HTTP ${$.status()}: ${u}`);n.skip("page",u,$.status(),t.pageDiscoverySources.get(u)),await f.close();continue}x?(n.info(`Rendering without JS execution for ${u}`,{url:u,mode:"no-js"}),await H(`wait for rendered page ${u}`,pe(e),()=>$o(e,f))):await H(`wait for rendered page ${u}`,pe(e),()=>ko(e,f)),t.stats.pagesRendered++;let D=await H(`extract rendered assets ${u}`,pe(e),()=>Mo(e,f,w,n,!x));for(let v of D)Q(e,t,v,n,u);let b=[...new Set([...D,...C])],T=R??await H(`capture rendered html ${u}`,pe(e),()=>f.content()),U=r!=="single-url"&&r!=="content-sync"&&!P?Co(e,u,T,n):[];if(r!=="single-url"&&r!=="content-sync"&&!P)for(let v of U)st(e,t,v,n,u);await Fr(e,u,T,t,n);let q=ge(e,u);if(te(a,e,q),xe(a,q),i.trackManifest){let v=$?.headers();i.manifest.pages[u]={url:u,outputPath:q,contentType:cn(v),changeToken:M.changeToken?.supported?M.changeToken.token:null,tokenSource:M.changeToken?.supported?M.changeToken.tokenSource??null:null,sitemapLastmod:nt(t.sitemapLastmodByPage[u])??null,discoveredPages:U,discoveredAssets:b,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,rewriteComplete:!1},(i.enabled||i.strictTargeted)&&await Pe(e,i);}}catch(m){if(g=m instanceof ot,i.strictTargeted)throw n.error(`Failed required content-sync page ${u}`,{url:u,error:String(m)}),m;if(g)n.warn(`Skipped partial DOM for timed-out page ${u}`,{url:u,error:String(m),recovery:"recycle-worker-browser"});else try{let w=f?await H(`capture partial html ${u}`,pe(e),()=>f.content()):"";if(w&&w.trim()){await Fr(e,u,w,t,n);let P=ge(e,u);if(te(a,e,P),xe(a,P),i.trackManifest){let x=i.manifest.pages[u]??i.previousManifest.pages[u];i.manifest.pages[u]={url:u,outputPath:P,contentType:x?.contentType??null,changeToken:null,tokenSource:null,sitemapLastmod:nt(t.sitemapLastmodByPage[u])??x?.sitemapLastmod??null,discoveredPages:x?.discoveredPages?[...x.discoveredPages]:[],discoveredAssets:x?.discoveredAssets?[...x.discoveredAssets]:[],lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,rewriteComplete:!1},(i.enabled||i.strictTargeted)&&await Pe(e,i);}n.warn(`Saved partial DOM for ${u}`,{url:u,error:String(m)});}}catch(w){w instanceof ot&&(g=!0),n.error(`Could not save partial DOM for ${u}`,{url:u,error:String(w)});}n.error(`Failed page ${u}`,{url:u,error:String(m)});}finally{if(!g&&f&&await H(`drain network routes ${u}`,tt(e),()=>f.unrouteAll({behavior:"wait"})).catch(m=>{g=!0,n.warn(`Could not drain network routes for ${u}`,{url:u,browserPid:l.pid,error:String(m),recovery:"recycle-worker-browser"});}),g&&(o=null,await an(d,n,`page operation timeout for ${u}`),await d.close().catch(()=>{})),h.size>0&&await Promise.allSettled([...h]),!g&&p)try{let m=await p.cookies();c.addAll(Ir(y,m));}catch{}t.stats.pagesCompleted++,Do(t)&&Fo(t,n),!g&&f&&await H(`close page ${u}`,tt(e),()=>f.close()).catch(m=>{g=!0,n.warn(`Timed out while closing page ${u}`,{url:u,browserPid:l.pid,error:String(m),recovery:"recycle-worker-browser"});}),!g&&p&&await H(`close page context ${u}`,tt(e),()=>p.close()).catch(m=>{g=!0,n.warn(`Timed out while closing page context for ${u}`,{url:u,browserPid:l.pid,error:String(m),recovery:"recycle-worker-browser"});}),g&&o===d&&(o=null,await an(d,n,`page cleanup timeout for ${u}`),await d.close().catch(()=>{}));}}}finally{if(o){let d=o;await H("close worker browser",tt(e),()=>d.close()).catch(u=>(n.warn("Timed out while closing crawl worker browser",{browserPid:l.pid,error:String(u)}),an(d,n,"browser.close timeout")));}}}async function jo(e){try{let t=await A.readFile(e),r=(e.endsWith(".gz")?gunzipSync(t):t).toString("utf8").trim();if(!r)return [];try{let s=JSON.parse(r);if(Array.isArray(s))return s;if(s&&typeof s=="object")return [s]}catch{return r.split(/\r?\n/).map(s=>s.trim()).filter(Boolean).map(s=>{try{let i=JSON.parse(s);return i&&typeof i=="object"?i:null}catch{return null}}).filter(s=>s!==null)}return []}catch{return []}}function Or(e){let t=String(e||"").toLowerCase();return t.includes("timeout")||t.includes("timed out")||t.includes("navigation timeout")}function qo(e){let t=String(e?.job?.command||"").trim(),n=String(e?.job?.crawlMode||"full").trim();return t!=="publish"&&t!=="crawl"?false:n!=="incremental"}function _o(e){let t=[e?.archivedAt,e?.job?.endedAt,e?.job?.startedAt];for(let n of t){let r=Date.parse(String(n||""));if(Number.isFinite(r))return r}return 0}async function Xr(e){try{let t=await A.readFile(e,"utf8"),n=JSON.parse(t);return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}function Ur(e){let t=String(e.originalFileName||"").toLowerCase();return t.endsWith("errors.jsonl")?0:t.endsWith("errors.json")?1:2}function No(e,t){let n=Array.isArray(t?.artifacts)?t.artifacts.filter(r=>String(r?.role||"").trim()==="errors"&&String(r?.storedFileName||"").trim()!=="").sort((r,s)=>Ur(r)-Ur(s)).map(r=>S.join(e,String(r.storedFileName))):[];return [...new Set([...n,S.join(e,"errors.jsonl"),S.join(e,"errors.json"),S.join(e,"errors.jsonl.gz"),S.join(e,"errors.json.gz")])]}async function Lr(e){let t=await Xr(S.join(e,"job.json"));for(let n of No(e,t)){let r=await jo(n);if(r.length>0)return r}return []}async function Bo(e){let t=S.join(e.logDir,"archive"),n;try{n=await A.readdir(t);}catch{return ""}let r="",s=0;for(let i of n){let a=S.join(t,i);if(!(await A.stat(a).catch(()=>null))?.isDirectory())continue;let o=await Xr(S.join(a,"job.json"));if(!qo(o))continue;let l=_o(o);l>=s&&(s=l,r=a);}return r}async function Wo(e){let t=await Bo(e),n=t!==""?await Lr(t):await Lr(e.logDir),r=new Set;for(let s of n)if(Or(s.error)||Or(s.message)){let i=s.url;typeof i=="string"&&i&&r.add(i);}return [...r]}async function Ho(e){let t=[];for(let n of e)if(n.startsWith("@")){let r=n.slice(1),s=await A.readFile(r,"utf8");t.push(...s.split(/\r?\n/).map(i=>i.trim()).filter(i=>i&&!i.startsWith("#")));}else t.push(n);return t}async function zo(e){if(!e)throw new Error("Content-sync crawl requires an immutable impact plan.");let t=JSON.parse(await A.readFile(e,"utf8"));return Ve(t),t}function Qo(e,t){let n;try{n=new URL(e);}catch{return false}return t.archiveFamilies.some(r=>{let s=new URL(r.url);if(n.origin!==s.origin)return false;if(n.toString()===s.toString())return true;if(n.searchParams.has("paged")&&n.pathname===s.pathname)return /^\d+$/.test(n.searchParams.get("paged")||"");let i=s.pathname.replace(/\/+$/,""),a=n.pathname.slice(i.length).replace(/^\/+/,""),c=String(r.paginationBase||"page").replace(/^\/+|\/+$/g,"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return n.pathname.startsWith(`${i}/`)&&new RegExp(`^${c}/\\d+/?$`).test(a)})}function Rt(e,t,n){let r=n==="page"?ge(e,t):$t(e,t).originalFilePath;return Se(e.outputDir,r)}async function fn(e,t,n,r,s){let i=t.manifest.pages[r];if(!i)return;let a=Se(e.outputDir,i.outputPath);if(!a)throw new Error(`Manifest-owned page path escaped output root: ${r}`);let c=S.resolve(i.outputPath);Object.entries(t.manifest.pages).some(([l,d])=>l!==r&&!s.has(l)&&S.resolve(d.outputPath)===c)||(await A.rm(i.outputPath,{force:true}),n.deletedFiles.add(a)),delete t.manifest.pages[r];}function Jo(e,t){let n=new Set,r=[...t];for(;r.length>0;){let s=r.shift();if(n.has(s))continue;n.add(s);let i=e.assets[s];for(let a of i?.discoveredAssets??[])try{Ne(new URL(a))&&r.push(a);}catch{}}return n}async function Vo(e,t,n,r,s){let i=Jo(n.previousManifest,s);for(let a of i){if(t.successfulSitemaps.has(a))continue;let c=n.previousManifest.assets[a];if(!c)continue;let o=Se(e.outputDir,c.outputPath);if(!o)throw new Error(`Manifest-owned sitemap path escaped output root: ${a}`);await A.rm(c.outputPath,{force:true}),r.deletedFiles.add(o),delete n.manifest.assets[a];}await Pe(e,n);}async function Ko(e){try{let t=await A.readFile(S.join(e.outputDir,"asset-map.json"),"utf8");return JSON.parse(t)}catch{return {}}}async function Go(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 A.mkdir(e,{recursive:true}),await Promise.all(t.map(async n=>{try{await A.unlink(S.join(e,n));}catch(r){if(r.code!=="ENOENT")throw r}}));}function jr(e,t,n,r,s){let i=J(e,n,e.sourceOrigin,r,"manual-url");i&&(Ne(i)?Tt(e,t,i.toString(),r,s):W(e,i)?Q(e,t,i.toString(),r,s):Ce(i)?st(e,t,i.toString(),r,s):r.reject("manual-url",i.toString(),"not page/sitemap/asset-like",s));}async function es(e=process.argv.slice(2)){let t=[],n=await ie(void 0,{onRemotePublisherConfigDiagnostic:b=>{t.push(b);}}),r=Ge(n.sitemapPaths),s=t.at(-1)??null,i=Ai(e),a=i.mode==="content-sync"?await zo(i.contentSyncPlanPath):null;if(i.resumeRewrite&&i.mode!=="full")throw new Error("--resume-rewrite is only supported for full crawl/publish jobs.");let c=[];i.mode==="retry-timeouts"&&(c=await Wo(n)),i.mode==="single-url"&&(c=await Ho(i.urls)),a&&(c=[...a.directRenderUrls,...a.archiveFamilyUrls]);let o=i.crawlMode==="incremental"&&i.mode==="full",l=o&&typeof n.subscriptionType=="string"&&n.subscriptionType.trim()!=="";if(a&&n.subscriptionType!=="PROFESSIONAL"&&n.subscriptionType!=="AGENCY")throw new Error("Content-sync requires an active Professional or Agency subscription.");let d=(i.mode==="full"||i.mode==="single-url"||i.mode==="content-sync")&&!i.resumeRewrite,u=i.mode!=="full"||i.resumeRewrite||l,p=u?await Ko(n):{},f=l||i.mode==="single-url"||i.mode==="content-sync"?await Fi(n):Br(),g=new Set(c),y=new Set;if(a){for(let b of a.archiveFamilies)if(b.foundPosts===0)for(let T of b.pageUrls)y.add(T);for(let b of Object.keys(f.pages))Qo(b,a)&&!g.has(b)&&(c.push(b),y.add(b));}let h={enabled:l,trackManifest:d,manifest:ln(f),previousManifest:ln(f),runId:a?.jobId??`${Date.now()}`,seenPages:new Set,changeTokenCache:new Map,manifestSaveChain:Promise.resolve(),strictTargeted:!!a,requiredUrls:g,deleteOnMissingUrls:y};await Go(n.logDir);let m=new St(n.logDir,n.logLevel);if(s){let b={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?m.info("Loaded remote WP Suite publisher configuration.",b):m.warn("Remote WP Suite publisher configuration is unavailable or has no active subscription type.",b);}if(o&&!l){let b="Incremental crawl requires an active remote publisher subscription; refusing to fall back to a destructive full crawl.";throw m.error(b,{requestedMode:i.crawlMode,subscriptionType:n.subscriptionType??null,source:"incremental-subscription-guard"}),await m.flush(),new Error(b)}let w={pageQueue:[],queuedPages:new Set,donePages: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:{...p},assetVariantDigestsByOriginalPath:new Map,stats:{pagesQueued:0,pagesRendered:0,pagesCompleted:0,assetsQueued:0,sitemapsQueued:0,assetsSaved:0,pagesSaved:0}},P=Di(),x=new Pt,j=Ti();if(j&&!i.resumeRewrite&&await vt(j,x.artifact()),await De(n),await tr(n,{startedAt:new Date().toISOString(),outputDir:S.resolve(n.outputDir)}),u||await A.rm(n.outputDir,{recursive:true,force:true}),await A.mkdir(n.outputDir,{recursive:true}),a){let b=new Set([...a.deleteUrls,...h.deleteOnMissingUrls]);for(let T of a.deleteUrls)await fn(n,h,P,T,b);}if(i.resumeRewrite)m.info("Resuming final rewrite from existing output.",{phase:"rewrite-text",mode:i.mode,crawlMode:i.crawlMode});else {let b=await request.newContext({ignoreHTTPSErrors:n.ignoreHttpsErrors});try{if(m.mark("discovery"),i.mode==="full"?(r.forEach(U=>Tt(n,w,U,m)),await Dr(n,b,w,m,P,h),n.seedPaths.forEach(U=>jr(n,w,U,m,"seed-path")),n.generated404RequestPath&&st(n,w,n.generated404RequestPath,m,"generated-404-request-path")):(c.forEach(U=>jr(n,w,U,m,"cli")),a?.sitemapUrls.forEach(U=>Tt(n,w,U,m,"content-sync-impact")),await Dr(n,b,w,m,P,h,i.mode==="content-sync",a?.sitemapUrls??[]),a&&await Vo(n,w,h,P,a.sitemapUrls)),m.endMark("discovery",{pages:w.pageQueue.length,assets:w.assetQueue.length,sitemaps:w.sitemapQueue.length}),m.summary(`Queued ${w.pageQueue.length} pages, ${w.assetQueue.length} assets, ${w.sitemapQueue.length} sitemaps.`,{mode:i.mode,crawlMode:i.crawlMode,queuedPages:w.pageQueue.length,queuedAssets:w.assetQueue.length,queuedSitemaps:w.sitemapQueue.length}),i.mode==="retry-timeouts"&&w.pageQueue.length===0&&w.assetQueue.length===0&&w.sitemapQueue.length===0){m.summary("No timed-out URLs were queued. Skipping retry crawl.",{mode:i.mode,crawlMode:i.crawlMode,queuedPages:0,queuedAssets:0,queuedSitemaps:0}),await m.flush(),j&&await vt(j,x.artifact());return}m.mark("render-pages");let T=Array.from({length:Math.max(1,n.concurrency)},()=>Lo(n,w,m,i.mode,b,h,P,x));if(await Promise.all(T),j&&await vt(j,x.artifact()),m.endMark("render-pages",{pages:w.stats.pagesCompleted}),m.mark("download-assets"),m.progress("Asset download phase started.",{phase:"download-assets",doneAssets:w.doneAssets.size,assetsQueued:w.stats.assetsQueued,assetQueue:w.assetQueue.length}),await Li(n,b,h,[...w.assetQueue],m),await xo(n,b,w,m,h,P),m.endMark("download-assets",{assets:w.doneAssets.size}),h.enabled&&n.maxPages===0&&(await Bi(n,w,h,m,P),i.mode==="full"&&await Wi(n,h,m,P)),i.mode==="full"){let U=await vo(n,w,m);for(let q of U)te(P,n,q);}}finally{await H("dispose crawl request context",tt(n),()=>b.dispose()).catch(T=>{m.warn("Timed out while disposing crawl request context",{error:String(T)});});}}h.trackManifest&&await Pe(n,h),await A.writeFile(S.join(n.outputDir,"asset-map.json"),JSON.stringify(w.assetMap,null,2),"utf8"),JSON.stringify(p,null,2)!==JSON.stringify(w.assetMap,null,2)&&te(P,n,S.join(n.outputDir,"asset-map.json"));let M=i.mode==="single-url"||i.mode==="content-sync"?Yi(n,w):h.enabled&&!i.resumeRewrite?Hi(n,h,P,p,w.assetMap):void 0;m.mark("rewrite-text");let _=i.mode==="single-url"||i.mode==="content-sync"?`Rewriting text files touched by URL crawl: 0/${M?.length??0}`:"Rewriting text files...";m.progress(_,{phase:"rewrite-text",index:0,totalFiles:M?.length,changedTextFiles:0}),await Er(_);let C=Date.now(),$=await ht(n,w.assetMap,{files:M,previousAssetMap:p,onStart:({totalFiles:b,workerCount:T})=>{m.info(`Rewrite phase scanning ${b} text files.`,{phase:"rewrite-text",totalFiles:b,workerCount:T});},onProgress:async({index:b,totalFiles:T,changedTextFiles:U,file:q,changed:v})=>{v&&te(P,n,S.join(n.outputDir,q)),m.checkpoint(`Rewriting text file ${b}/${T}`,{phase:"rewrite-text",index:b,totalFiles:T,changedTextFiles:U,file:q}),m.debug(`${v?"Rewrote":"Checked unchanged"} text file ${b}/${T}: ${q}`,{phase:"rewrite-text",index:b,totalFiles:T,changedTextFiles:U,file:q,changed:v});let E=Date.now();if(!(b===1||b===T||b%50===0||E-C>=5e3))return;C=E;let z=`Rewriting text files: ${b}/${T}`;m.progress(z,{phase:"rewrite-text",index:b,totalFiles:T,changedTextFiles:U,file:q}),await Er(z);}});h.trackManifest&&(zi(h,M),await Pe(n,h)),m.endMark("rewrite-text",{changedTextFiles:$});let R=a?[...P.deletedFiles].sort():h.enabled&&!i.resumeRewrite?await Ji(n,w,h,P,m):[],D=[...new Set((M||[]).map(b=>Se(n.outputDir,S.isAbsolute(b)?b:S.join(n.outputDir,b))).filter(b=>b!==null))].sort();if(a){let b=[...P.changedFiles].sort(),T=new Set(b),U=new Set(a.directRenderUrls.map(O=>Rt(n,O,"page")).filter(O=>!!O&&T.has(O))),q=new Set(a.archiveFamilyUrls.map(O=>Rt(n,O,"page")).filter(O=>!!O&&T.has(O))),v=new Set([...w.sitemapLeafUrls].map(O=>Rt(n,O,"asset")).filter(O=>!!O&&T.has(O))),E=new Set([...w.sitemapIndexUrls].map(O=>Rt(n,O,"asset")).filter(O=>!!O&&T.has(O))),F=new Set([...U,...q,...v,...E]),z=b.filter(O=>!F.has(O)),ee=[...new Set([...a.directRenderUrls,...a.archiveFamilyUrls,...w.resolvedSitemapRoots,...w.sitemapLeafUrls,...w.sitemapIndexUrls,...a.deleteUrls].map(O=>{let Ae=new URL(O);return `${Ae.pathname}${Ae.search}`}))].sort();await en(n,{schemaVersion:2,generatedAt:new Date().toISOString(),outputDir:S.resolve(n.outputDir),runMode:"content-sync",crawlMode:"incremental",fullSyncRequired:false,changedFiles:b,deletedFiles:R,rewriteTargets:D,consumerId:a.consumerId,fromSequence:a.fromSequence,toSequence:a.toSequence,impactHash:a.impactHash,resolvedSitemapUrls:[...w.resolvedSitemapRoots],uploadGroups:{assets:z,content:[...U].sort(),listings:[...q].sort(),sitemapLeaves:[...v].sort(),sitemapIndexes:[...E].reverse()},invalidationPaths:ee});}else await en(n,{schemaVersion:1,generatedAt:new Date().toISOString(),outputDir:S.resolve(n.outputDir),runMode:i.mode,crawlMode:i.crawlMode,fullSyncRequired:!(h.enabled&&!i.resumeRewrite),changedFiles:h.enabled&&!i.resumeRewrite?[...P.changedFiles].sort():[],deletedFiles:h.enabled&&!i.resumeRewrite?R:[],rewriteTargets:h.enabled&&!i.resumeRewrite?D:[]});await rr(n),m.summary(i.resumeRewrite?`Done. Resumed final rewrite over existing output and changed ${$} text files.`:`Done. Rendered ${w.stats.pagesRendered} pages, processed ${w.doneSitemaps.size} sitemaps and ${w.doneAssets.size} assets.`,{mode:i.mode,crawlMode:i.crawlMode,resumeRewrite:i.resumeRewrite,...w.stats,pagesRendered:w.stats.pagesRendered,donePages:w.stats.pagesCompleted,claimedPages:w.donePages.size,doneSitemaps:w.doneSitemaps.size,doneAssets:w.doneAssets.size,changedTextFiles:$}),await m.flush();}function Zo(e){let t=e/6e4;if(Number.isInteger(t)&&t>=1)return `${t} minute${t===1?"":"s"}`;let n=Math.ceil(e/1e3);return `${n} second${n===1?"":"s"}`}async function ne(e,t,n){let r=new AbortController,s=globalThis.setTimeout(()=>{r.abort(new Error(`${e} timed out after ${Zo(t)}.`));},t);try{return await n({abortController:r,httpOptions:{abortSignal:r.signal,requestTimeout:t}})}finally{globalThis.clearTimeout(s);}}function Yo(e){return typeof e.subscriptionType=="string"&&e.subscriptionType.trim()!==""}function Et(e){let t="";for(let r=0;r<e.length;r++){let s=e[r];if(s==="--profile"){let i=(e[r+1]||"").trim();if(!i)throw new Error("Missing value for --profile.");t=i,r+=1;}else if(s.startsWith("--profile=")){let i=s.slice(10).trim();if(!i)throw new Error("Missing value for --profile.");t=i;}}let n=String(process.env.PUBLISHER_DEPLOY_PROFILE||process.env.PUBLISHER_DEPLOYMENT_PROFILE||"").trim();return t||n||null}function Xo(e,t){return {...e,...t??{}}}function ea(e,t){return {...e,...t??{},invalidationPaths:[...(t?.invalidationPaths??e.invalidationPaths)||[]]}}function Be(e,t){let n=String(t??e.deploymentTargetOverride??"").trim();if(!Yo(e)){if(n)throw new Error(`Deployment target "${n}" requires an active WPSuite subscription and remote publisher config.`);return {name:null,profile:null,config:e}}let r=String(n||e.defaultDeploymentProfile||"").trim();if(!r)return {name:null,profile:null,config:e};let s=e.deploymentProfiles?.[r];if(!s)throw new Error(`Unknown deployment profile "${r}". Check the linked WPSuite publisher configuration.`);return {name:r,profile:s,config:{...e,targetOrigin:s.targetOrigin??e.targetOrigin,s3:Xo(e.s3,s.s3),cloudFront:ea(e.cloudFront,s.cloudFront)}}}var ss="wpsuite-sha256",is="wpsuite-normalized-sha256",ua=/(?:^|[-_:.])(id|uid|nonce|token|hash|instance)(?:$|[-_:.])/i,Rn=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,la=["SIGINT","SIGTERM"],Ft=new Set,Mt=new Map,ts=null;function da(e){Ft.add(e);let t=false;return ()=>{t||(t=true,Ft.delete(e));}}async function pa(){let e=[...Ft];e.length!==0&&await Promise.allSettled(e.map(async t=>{Ft.delete(t),await A.rm(t,{recursive:true,force:true});}));}function ga(){if(!(Mt.size>0))for(let e of la){let t=()=>{ts||(ts=pa().finally(()=>{for(let[n,r]of Mt)process.off(n,r);Mt.clear(),process.exit(1);}));};Mt.set(e,t),process.on(e,t);}}ga();function fa(e,t){let n=String(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH||"").trim();if(n)return S.resolve(n);let r=t.trim();return r?S.join(S.resolve(r),"crawl-manifest.json"):S.join(S.resolve(e),".crawl-manifest.json")}function os(e){return S.normalize(e).split(S.sep).join("/")}function ns(e,t){let n=S.relative(S.resolve(e),S.resolve(t));return !n||n.startsWith("..")||S.isAbsolute(n)?null:os(n)}async function ma(e,t,n){let r=fa(e.outputDir,t),s;try{s=await A.readFile(r,"utf8");}catch(d){return d.code==="ENOENT"?(n.warn("Deploy rewrite guard disabled because the crawl manifest is missing.",{manifestPath:r,source:"deploy-guard"}),null):(n.warn("Deploy rewrite guard disabled because the crawl manifest could not be read.",{manifestPath:r,error:d instanceof Error?d.message:String(d),source:"deploy-guard"}),null)}let i;try{i=JSON.parse(s);}catch(d){return n.warn("Deploy rewrite guard disabled because the crawl manifest is invalid JSON.",{manifestPath:r,error:d instanceof Error?d.message:String(d),source:"deploy-guard"}),null}let a=new Map,c=new Map,o=0,l=0;for(let[d,u]of Object.entries(i.pages||{})){let p=String(u?.outputPath||"").trim(),f=p?ns(e.outputDir,p):null;if(f){let g=typeof u?.contentType=="string"&&u.contentType?u.contentType:null;g&&c.set(f,g);}!p||u?.rewriteComplete===true||f&&(o++,a.has(f)||a.set(f,{kind:"page",sourceUrl:d,outputPath:S.resolve(p),relativePath:f}));}for(let[d,u]of Object.entries(i.assets||{})){let p=String(u?.outputPath||"").trim(),f=u?.isText===true,g=p?ns(e.outputDir,p):null;if(g){let y=typeof u?.contentType=="string"&&u.contentType?u.contentType:null;y&&c.set(g,y);}!p||!f||u?.rewriteComplete===true||g&&(l++,a.has(g)||a.set(g,{kind:"asset",sourceUrl:d,outputPath:S.resolve(p),relativePath:g}));}return {manifestPath:r,byRelativePath:a,contentTypeByRelativePath:c,pendingPages:o,pendingTextAssets:l}}function ha(e){return e&&(Rn.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 bn(e){return e.split(/([_:.\-/=?&#]+)/g).map((t,n)=>n%2===1?t:ha(t)).join("")}function wa(e){return e.split(/([_:.\-/=?&#]+)/g).map((t,n)=>n%2===1?t:Rn.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 Ot(e,t){return Array.isArray(e)?e.map(n=>Ot(n,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Ot(r,n)])):typeof e!="string"?e:t&&ua.test(t)?wa(e):Rn.test(e)?"__uuid__":/^[0-9a-f]{6,}$/i.test(e)||/^[0-9]{8,}$/.test(e)?bn(e):e}function ya(e){return e.replace(/((?:https?:\/\/[^"'\s>]+|\/)(?:wp-content|wp-includes)\/[^"'\s>?]+)\?ver=[A-Za-z0-9._-]+(?=$|[#"'])/gi,"$1")}function Sa(e,t){let n=t.trim();if((n.startsWith("{")||n.startsWith("[")||n.startsWith('"'))&&e.startsWith("data-"))try{let s=JSON.parse(n);return JSON.stringify(Ot(s))}catch{}if(e.startsWith("data-")&&/^[A-Za-z0-9+/=]+$/.test(n))try{let s=Buffer.from(n,"base64").toString("utf8"),i=JSON.parse(s),a=JSON.stringify(Ot(i));return Buffer.from(a,"utf8").toString("base64")}catch{}return t}function ba(e,t){let n=e.toLowerCase();return n==="class"?t.split(/(\s+)/).map((r,s)=>s%2===1?r:bn(r)).join(""):n==="id"||n==="for"||n==="aria-controls"||n==="aria-labelledby"||n==="aria-describedby"||n==="aria-owns"||n==="aria-activedescendant"||n==="name"?bn(t):n==="href"||n==="src"?ya(t):Sa(n,t)}function Pa(e){return e.replace(/<([a-z][^\s/>]*)([^<>]*?)>/gi,(t,n,r)=>{if(n.startsWith("/"))return t;let s=r.replace(/\s([:@a-zA-Z_][-:.a-zA-Z0-9_]*?)=(['"])([\s\S]*?)\2/g,(i,a,c,o)=>{let l=ba(a,o);return ` ${a}=${c}${l}${c}`});return `<${n}${s}>`})}function Sn(e){let t=S.extname(e).toLowerCase();return [".html",".htm",".xml",".xsl",".txt"].includes(t)||["robots.txt","sitemap.xml"].includes(S.basename(e))}function Dt(e,t){return [e.replace(/^\/+|\/+$/g,""),t.replace(/^\/+/,"")].filter(Boolean).join("/")}async function va(e,t,n,r){let s=new Map,i,a=0;do{a++;let c=await ne(`S3 list objects page ${a} for s3://${t}/${n||""}`,3e5,({httpOptions:o})=>e.send(new ListObjectsV2Command({Bucket:t,Prefix:n||void 0,ContinuationToken:i}),o));for(let o of c.Contents||[]){if(!o.Key)continue;let l=(o.ETag||"").replace(/^"|"$/g,"").toLowerCase(),d=Number(o.Size??0);s.set(o.Key,{etag:l,size:d});}i=c.NextContinuationToken,r.debug(`Listed S3 keys page ${a}: ${s.size} keys so far`);}while(i);return s}async function Ca(e,t,n,r){if(r.has(n))return r.get(n)??null;try{let s=await ne(`S3 head object ${n}`,3e5,({httpOptions:a})=>e.send(new HeadObjectCommand({Bucket:t,Key:n}),a)),i={etag:(s.ETag||"").replace(/^"|"$/g,"").toLowerCase(),size:Number(s.ContentLength??0)};return r.set(n,i),i}catch{return r.set(n,null),null}}async function Ra(e,t,n,r){let s=[...new Set(Array.from(n).filter(Boolean))];if(s.length===0)return r.info("No explicitly tombstoned S3 objects to delete."),[];r.info(`Deleting ${s.length} explicitly tombstoned S3 object(s)\u2026`);for(let i=0;i<s.length;i+=1e3){let a=s.slice(i,i+1e3);if(a.length===0)continue;let c=await ne(`S3 delete objects batch ${Math.floor(i/1e3)+1}`,3e5,({httpOptions:o})=>e.send(new DeleteObjectsCommand({Bucket:t,Delete:{Objects:a.map(l=>({Key:l}))}}),o));if(c.Errors&&c.Errors.length>0){let o=c.Errors.map(l=>`${l.Key||"(unknown)"}: ${l.Code||"DeleteFailed"}`);throw new Error(`S3 reported ${o.length} object deletion error(s): ${o.join(", ")}`)}r.info(`Deleted batch of ${a.length} object(s).`);for(let o of a)r.debug(` deleted: ${o}`);}return s}function xa(e){return createHash("md5").update(e).digest("hex")}function rs(e){return createHash("sha256").update(e).digest("hex")}function Pn(e){return createHash("sha256").update(Pa(e.toString("utf8"))).digest("hex")}async function Ia(e,t,n,r){if(r.has(n))return r.get(n)??null;try{let a=((await ne(`S3 head object metadata ${n}`,3e5,({httpOptions:c})=>e.send(new HeadObjectCommand({Bucket:t,Key:n}),c))).Metadata?.[ss]||"").trim().toLowerCase()||null;return r.set(n,a),a}catch{return r.set(n,null),null}}async function Aa(e,t,n,r,s){if(r.has(n))return r.get(n)??null;try{let a=((await ne(`S3 head object normalized metadata ${n}`,3e5,({httpOptions:c})=>e.send(new HeadObjectCommand({Bucket:t,Key:n}),c))).Metadata?.[is]||"").trim().toLowerCase();if(a)return r.set(n,a),a}catch{return r.set(n,null),null}if(s.has(n)){let i=s.get(n)??null;return r.set(n,i),i}try{let a=await(await ne(`S3 get object ${n}`,3e5,({httpOptions:o})=>e.send(new GetObjectCommand({Bucket:t,Key:n}),o))).Body?.transformToByteArray(),c=a?Pn(Buffer.from(a)):null;return s.set(n,c),r.set(n,c),c}catch{return s.set(n,null),r.set(n,null),null}}function Ta(e){return e.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"profile"}function ka(e,t){let n=e,r=Object.entries(t).sort((s,i)=>i[0].length-s[0].length);for(let[s,i]of r)s&&(n=n.split(s).join(i));return n}async function $a(e,t,n,r){let s=S.join(e,"asset-map.json"),i;try{i=await A.readFile(s,"utf8");}catch(o){if(o.code==="ENOENT")return;throw o}let a=JSON.parse(i);if(!a||typeof a!="object")return;let c=Object.fromEntries(Object.entries(a).map(([o,l])=>{let d=String(l??"");return t.urlRewriteMode==="absolute"&&t.targetOrigin&&n.targetOrigin&&t.targetOrigin!==n.targetOrigin&&(d=d.split(t.targetOrigin).join(n.targetOrigin)),d=ka(d,r),[o,d]}));await A.writeFile(s,JSON.stringify(c,null,2),"utf8");}async function Ea(e,t,n,r,s,i){let a=e.targetOrigin!==t.targetOrigin,c=Object.keys(r).length>0;if(!n||!a&&!c)return {outputDir:e.outputDir,cleanup:async()=>{}};if(a&&e.urlRewriteMode!=="absolute")throw new Error(`Deployment profile "${n}" changes targetOrigin, but the base crawl output must use urlRewriteMode "absolute" for multi-target redeploys.`);let o=S.join(S.dirname(e.outputDir),`.deploy-profile-${Ta(n)}-${Date.now()}`),l=da(o);s.info(`Preparing deployment profile "${n}" from existing crawl output to ${o}...`);try{if(await A.rm(o,{recursive:!0,force:!0}),i){await A.mkdir(o,{recursive:!0});for(let f of i){let g=S.join(e.outputDir,f),y=S.join(o,f);await A.mkdir(S.dirname(y),{recursive:!0}),await A.copyFile(g,y);}}else await A.cp(e.outputDir,o,{recursive:!0});let d={...e,sourceOrigin:e.targetOrigin,targetOrigin:t.targetOrigin,extraReplacements:r,outputDir:o},u=1;s.info(`Rewriting text files for deployment profile "${n}"...`);let p=await ht(d,{},{files:i,onStart:({totalFiles:f,workerCount:g})=>{u=g,s.info(`Rewriting ${f} text file(s) for deployment profile "${n}" with ${g} worker(s).`);},onProgress:({index:f,totalFiles:g,changedTextFiles:y,file:h,changed:m})=>{let P=`Rewriting [${f}/${g}] ${h} (${m?"rewrote":"checked"}; ${y} changed so far)`;g<=200||f<=5||f%10===0||f===g?(s.progress(P,{file:h,index:f,totalFiles:g,changed:m,changedTextFiles:y,workerCount:u}),s.info(P)):s.debug(P);}});return await $a(o,e,t,r),s.info(`Prepared deployment profile "${n}" in ${o} (${p} rewritten text file(s)).`),{outputDir:o,cleanup:async()=>{l(),await A.rm(o,{recursive:!0,force:!0});}}}catch(d){throw s.error(`Failed to prepare deployment profile "${n}" temporary output.`,{tempDir:o,outputDir:e.outputDir,error:d instanceof Error?d.message:String(d),...d instanceof Error&&d.stack?{stack:d.stack}:{}}),await A.rm(o,{recursive:true,force:true}).catch(()=>{}),l(),await s.flush().catch(()=>{}),d}}async function as(e=process.argv.slice(2)){let t=await ie(),n=Et(e),r=Be(t,n),s=S.resolve(r.config.logDir||"logs"),i=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",a=i?S.join(S.resolve(i),"deploy-diff.json"):"",c=new Oe(s,"deploy.log.jsonl",r.config.logLevel??"info"),o=r.profile?.extraReplacements??{},l=async()=>{};try{let d=await Me(t);if(e.includes("--content-sync")&&d?.schemaVersion!==2)throw new Error("Content-sync deployment requires a valid schema-2 targeted deploy plan.");let p=await nr(t);if(p)throw new Error(`Deployment blocked: the crawl started at ${p.startedAt} did not complete its final rewrite. Run a successful crawl or resume the rewrite before deploying.`);let f=await Ea(t,r.config,r.name,o,c,d?.schemaVersion===2?d.changedFiles:void 0);l=f.cleanup;let g={...r.config,outputDir:f.outputDir},y=g.s3SyncMode??"sdk-upload-delete";if(d?.schemaVersion===2&&d.deletedFiles.length>0&&y!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let h=d?.schemaVersion!==2&&f.outputDir!==t.outputDir&&(t.targetOrigin!==r.config.targetOrigin||Object.keys(o).length>0),m=!!d&&!d.fullSyncRequired&&!h;if(d?.schemaVersion===2&&!m)throw new Error("Content-sync deployment cannot widen into a full-output deployment.");r.name&&c.info(`Using deployment profile: ${r.name}`),c.info(`Starting deploy \u2014 s3://${g.s3.bucket}/${g.s3.prefix||""} (region: ${g.s3.region})`),c.info(`S3 sync mode: ${y}`),d&&d.fullSyncRequired?c.info("Deploy plan requests a full sync; scanning the whole output tree."):d&&h?c.info("Ignoring incremental deploy plan because deployment-profile rewrites require a full sync."):m&&c.info(`Using incremental deploy plan: ${d.changedFiles.length} changed file(s), ${d.deletedFiles.length} deleted file(s).`),c.mark("deploy");let w=new S3Client({region:g.s3.region}),P=f.outputDir===t.outputDir?await ma(t,i,c):null,x=d?.schemaVersion===2?[...d.uploadGroups.assets,...d.uploadGroups.content,...d.uploadGroups.listings,...d.uploadGroups.sitemapLeaves,...d.uploadGroups.sitemapIndexes]:d?.changedFiles??[];if(d?.schemaVersion===2){let k=[...new Set(x)],K=[...new Set(d.changedFiles)];if(k.length!==K.length||K.some(I=>!k.includes(I)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let j=m?(await Promise.all(x.map(async k=>{try{return (await A.stat(S.join(g.outputDir,k))).isFile()?k:null}catch{if(d?.schemaVersion===2)throw new Error(`Content-sync planned upload is missing: ${k}`);return null}}))).filter(k=>k!==null):await Vs(["**/*"],{cwd:g.outputDir,onlyFiles:!0,dot:!0}),M=[],_=[],C=j.filter(k=>{let K=P?.byRelativePath.get(os(k));if(!K)return !0;let I=Dt(g.s3.prefix,k);return M.push(k),_.push(I),c.reject(K.kind,K.sourceUrl||k,"rewrite not completed; deploy upload blocked","deploy-guard",{file:k,key:I,outputPath:K.outputPath,manifestPath:P?.manifestPath}),!1}),$=new Set((m?C:j).map(k=>Dt(g.s3.prefix,k)));P&&(P.pendingPages>0||P.pendingTextAssets>0)&&c.info(`Deploy rewrite guard loaded ${P.pendingPages} pending page(s) and ${P.pendingTextAssets} pending text asset(s) from crawl manifest.`,{manifestPath:P.manifestPath,pendingPages:P.pendingPages,pendingTextAssets:P.pendingTextAssets,source:"deploy-guard"}),M.length>0&&c.warn(`Deploy rewrite guard blocked ${M.length} file(s) from upload because final crawl rewrite is incomplete.`,{rejected:M.length,manifestPath:P?.manifestPath,source:"deploy-guard"}),m?c.info(`Using ${C.length} eligible planned changed file(s) from deploy plan for upload${M.length>0?` (${M.length} blocked by deploy rewrite guard)`:""}.`):c.info(`Found ${j.length} file(s) in output directory "${g.outputDir}"${M.length>0?`; ${C.length} remain eligible for upload after deploy rewrite guard filtering`:""}.`),c.progress("Deploy preflight: comparing local output with remote S3 state.",{phase:"deploy",mode:y,totalFiles:C.length,scannedFiles:j.length,rejected:M.length,deploymentProfile:r.name||"",s3Bucket:g.s3.bucket,s3Prefix:g.s3.prefix||"",targetedPlan:m,deployGuardEnabled:f.outputDir===t.outputDir});let R=0,D=0,b=0,T=[],U=[],q=[],v=[],E=[],F=new Map,z=new Map,ee=new Map,O=new Map,Ae=new Map;m||(c.info("Listing existing S3 objects to detect unchanged files..."),F=await va(w,g.s3.bucket,g.s3.prefix,c),c.info(`Found ${F.size} existing key(s) in S3.`));let ms=async k=>F.has(k)?F.get(k)??null:m?Ca(w,g.s3.bucket,k,z):null;for(let k of C){let K=S.join(g.outputDir,k),I=Dt(g.s3.prefix,k),re=P?.contentTypeByRelativePath.get(k),He=re&&re!=="application/octet-stream"?re:ca.lookup(k)||re||"application/octet-stream",hs=Sn(k)?g.s3.htmlCacheControl:g.s3.assetCacheControl,B=R+D+b+1;C.length<=200||B<=5||B%10===0||B===C.length?(c.progress(`Uploading [${B}/${C.length}] ${I} (${He})`,{file:k,key:I,index:B,totalFiles:C.length,contentType:He,mode:y}),c.info(`Uploading [${B}/${C.length}] ${I} (${He})`)):c.debug(`Uploading [${B}/${C.length}] ${I} (${He})`);try{let se=await A.readFile(K),ze=await ms(I),Qe=null,Te=null;if(ze){let jt=se.byteLength;if(ze.size===jt){let ct=ze.etag.includes("-");if(ze.etag!==""&&!ct){let ws=xa(se);if(ze.etag===ws){D++,C.length<=200||D<=5||D%25===0?(c.progress(`Skipped unchanged [${B}/${C.length}] ${I}`,{file:k,key:I,index:B,totalFiles:C.length,uploaded:R,skipped:D,failed:b,mode:y,reason:"etag-md5-match"}),c.info(`Skipped unchanged [${B}/${C.length}] ${I}`)):c.debug(`Skipped unchanged [${B}/${C.length}] ${I}`),U.push(I);continue}}Qe=rs(se);let $n=await Ia(w,g.s3.bucket,I,ee);if($n&&$n===Qe){D++,C.length<=200||D<=5||D%25===0?(c.progress(`Skipped unchanged [${B}/${C.length}] ${I}`,{file:k,key:I,index:B,totalFiles:C.length,uploaded:R,skipped:D,failed:b,mode:y,reason:"metadata-sha256-match"}),c.info(`Skipped unchanged [${B}/${C.length}] ${I}`)):c.debug(`Skipped unchanged [${B}/${C.length}] ${I}`),U.push(I);continue}}if(Sn(k)){Te=Pn(se);let ct=await Aa(w,g.s3.bucket,I,O,Ae);if(ct&&ct===Te){D++,C.length<=200||D<=5||D%25===0?(c.progress(`Skipped semantically unchanged [${B}/${C.length}] ${I}`,{file:k,key:I,index:B,totalFiles:C.length,uploaded:R,skipped:D,failed:b,mode:y,reason:"normalized-html-match"}),c.info(`Skipped semantically unchanged [${B}/${C.length}] ${I}`)):c.debug(`Skipped semantically unchanged [${B}/${C.length}] ${I}`),U.push(I);continue}}}Qe=Qe??rs(se),Te=Te??(Sn(k)?Pn(se):null),await ne(`S3 upload ${I}`,9e5,({abortController:jt})=>new Upload({client:w,abortController:jt,params:{Bucket:g.s3.bucket,Key:I,Body:se,ContentType:He,CacheControl:hs,Metadata:{[ss]:Qe,...Te?{[is]:Te}:{}}}}).done()),R++,T.push(I),(R%25===0||R===C.length)&&(c.progress(`Uploaded ${R}/${C.length} file(s)\u2026`,{uploaded:R,skipped:D,failed:b,totalFiles:C.length,mode:y}),c.info(`Uploaded ${R}/${C.length} file(s)\u2026`));}catch(se){b++,q.push(I),c.error(`Failed to upload ${I}: ${se.message}`,{key:I,error:String(se)});}}if(c.info(`Upload complete: ${R} uploaded, ${D} skipped unchanged, ${_.length} rejected by guard, ${b} failed.`),q.length>0||_.length>0)throw new Error(`Deployment stopped before deletion because ${q.length} upload(s) failed and ${_.length} upload(s) were rejected.`);if(y==="sdk-upload-delete"){let k=new Set((d?.deletedFiles??[]).map(I=>Dt(g.s3.prefix,I))),K=[...k].filter(I=>!$.has(I));if(!m&&(E=[...F.keys()].filter(re=>!$.has(re)).filter(re=>!k.has(re)),E.length>0)){c.warn(`Protected ${E.length} remote-only S3 object(s) from deletion because the crawl did not provide explicit tombstones.`,{protected:E.length,source:"deploy-delete-guard"});for(let re of E)c.debug(` protected remote-only object: ${re}`);}v=await Ra(w,g.s3.bucket,m?K:K.filter(I=>F.has(I)),c);}else c.info("Sync mode is sdk-upload-only \u2014 skipping stale object deletion.");a&&(await A.mkdir(S.dirname(a),{recursive:!0}),await A.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:y,summary:{totalFiles:j.length,eligibleFiles:C.length,uploaded:T.length,skipped:U.length,rejected:_.length,failed:q.length,deleted:v.length,protected:E.length,...r.name?{profile:r.name}:{}},uploadedKeys:T,skippedKeys:U,rejectedKeys:_,failedKeys:q,deletedKeys:v,protectedRemoteOnlyKeys:E},null,2),"utf8")),d?.schemaVersion!==2&&await De(t),c.endMark("deploy"),await c.flush();}finally{await l().catch(()=>{});}}function Da(e){let t=e;return t.endsWith("/")?t+="index.html":S.posix.basename(t).includes(".")||(t+="/index.html"),t}function Fa(e,t){let n=t.trim().replace(/^\/+|\/+$/g,"");if(!n)return null;let r=`/${n}`;return e===r||e.startsWith(`${r}/`)?e:`${r}${e.startsWith("/")?e:`/${e}`}`}function cs(e,t){let n=new Set;for(let r of e){let s=new URL(r,"https://content-sync.invalid");if(s.origin!=="https://content-sync.invalid")continue;let i=`${s.pathname}${s.search}`,a=Da(s.pathname);n.add(i),n.add(`${a}${s.search}`);let c=Fa(a,t);c&&n.add(`${c}${s.search}`);}return [...n].sort()}function ja(){let e=String(process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"").trim();return e?S.join(S.resolve(e),"content-sync-invalidation.json"):""}async function xn(e,t){if(!e)return;await A.mkdir(S.dirname(e),{recursive:true});let n=`${e}.${process.pid}.${Date.now()}.tmp`;await A.writeFile(n,JSON.stringify({...t,updatedAt:new Date().toISOString()},null,2),"utf8"),await A.rename(n,e);}async function qa(e,t,n,r){if(!e)return null;try{let s=JSON.parse(await A.readFile(e,"utf8"));if(s.schemaVersion!==1||s.distributionId!==t||s.impactHash!==n||!Array.isArray(s.batches))throw new Error("Content-sync invalidation state does not match the deploy plan.");let i=s.batches.flatMap(a=>a.paths);return i.length!==r.length||i.some((a,c)=>a!==r[c])?null:s}catch(s){if(s.code==="ENOENT")return null;throw s}}function _a(e,t=3e3){let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}async function ls(e=process.argv.slice(2)){let t=await ie(),n=Et(e),r=Be(t,n),s=r.config,i=new Oe(s.logDir||"logs","invalidate.log.jsonl",s.logLevel??"info"),a=e.includes("--content-sync"),c=await Me(t);if(a&&c?.schemaVersion!==2)throw new Error("Content-sync invalidation requires a valid schema-2 targeted deploy plan.");if(r.name&&i.info(`Using deployment profile: ${r.name}`),!s.cloudFront.distributionId){i.info("No CloudFront distributionId configured; skipping invalidation."),await i.flush();return}let o=c?.schemaVersion===2?c.invalidationPaths:s.cloudFront.invalidationPaths.length>0?s.cloudFront.invalidationPaths:["/*"],l=c?.schemaVersion===2?cs(o,s.s3.prefix||""):o;if(c?.schemaVersion===2&&l.some(g=>g==="/*"))throw new Error("Content-sync cannot use a whole-distribution invalidation.");if(l.length===0){i.info("The targeted deploy plan has no CloudFront paths to invalidate."),await i.flush();return}let d=s.cloudFront.distributionId,u=new CloudFrontClient({region:"us-east-1",maxAttempts:5});if(i.mark("invalidate"),c?.schemaVersion!==2){let g=`smartcloud-static-publisher-${Date.now()}`;await ne(`CloudFront invalidation for distribution ${d}`,3e5,({httpOptions:y})=>u.send(new CreateInvalidationCommand({DistributionId:d,InvalidationBatch:{CallerReference:g,Paths:{Quantity:l.length,Items:l}}}),y)),i.endMark("invalidate"),await i.flush();return}let p=ja(),f=await qa(p,d,c.impactHash,l);if(!f){let g=createHash("sha256").update(JSON.stringify(l)).digest("hex");f={schemaVersion:1,distributionId:d,impactHash:c.impactHash,updatedAt:new Date().toISOString(),batches:_a(l).map((y,h)=>({index:h,callerReference:`wpsuite-content-sync-${c.impactHash.slice(0,24)}-${g.slice(0,24)}-${h}`,paths:y,invalidationId:null,status:"pending"}))},await xn(p,f);}for(let g of f.batches){if(!g.invalidationId){let y=await ne(`CloudFront targeted invalidation batch ${g.index+1}`,3e5,({httpOptions:m})=>u.send(new CreateInvalidationCommand({DistributionId:d,InvalidationBatch:{CallerReference:g.callerReference,Paths:{Quantity:g.paths.length,Items:g.paths}}}),m)),h=String(y.Invalidation?.Id||"").trim();if(!h)throw new Error("CloudFront did not return an invalidation ID.");g.invalidationId=h,g.status="created",await xn(p,f);}await waitUntilInvalidationCompleted({client:u,maxWaitTime:900,minDelay:2,maxDelay:15},{DistributionId:d,Id:g.invalidationId}),g.status="completed",await xn(p,f),i.info(`CloudFront invalidation batch ${g.index+1}/${f.batches.length} completed.`,{invalidationId:g.invalidationId,pathCount:g.paths.length});}i.endMark("invalidate"),await i.flush();}function Lt(e){let t=new URL(e);return t.hash="",t.href}function ds(e,t,n){let r=new Set([...t].map(o=>Lt(o))),s=new Map,i=new Map,a=o=>{s.set(Lt(o),o);},c=o=>{if(!o)return;let l=Lt(o);s.has(l)||i.set(l,o);};for(let o of e.deleteUrls)a(o);for(let o of e.archiveFamilies)if(o.foundPosts===0)for(let l of o.pageUrls)r.has(Lt(l))||a(l);c(e.directRenderUrls[0]);for(let o of e.archiveFamilies)c(o.pageUrls[0]),c(o.pageUrls.at(-1));for(let o of n)c(o);return {expectedAvailable:[...i.values()],expectedMissing:[...s.values()]}}var gs=["claimed","impact-planned","rendered","deployed","invalidated","verified","acknowledged"];function Tn(){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 S.resolve(e)}function We(e,t){return gs.indexOf(e)>=gs.indexOf(t)}async function me(e,t,n,r,s={}){let i={timestamp:new Date().toISOString(),eventType:t,status:t.endsWith("failed")?"failed":"success",actorSource:"content-sync",jobId:n.id||"",command:"content-sync",message:r,details:s};await A.mkdir(e,{recursive:true}),await A.appendFile(S.join(e,"audit-events.jsonl"),`${JSON.stringify(i)}
|
|
14
|
-
`,"utf8");}function Ba(e){return Je({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 Wa(e,t){let n=(e.scheduler?.rules??[]).find(r=>r.command==="content-sync"&&r.id===t);if(!n)throw new Error(`Content-sync scheduler rule not found: ${t}`);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 n=Ba(t),r=Be(e,t.deploymentProfile),s=r.name||"",i=Dn(e.sourceOrigin,String(t.id||""),n),a=Fn({sourceOrigin:e.sourceOrigin,targetOrigin:r.config.targetOrigin,deploymentProfile:s,s3Bucket:r.config.s3.bucket,s3Prefix:r.config.s3.prefix,cloudFrontDistributionId:r.config.cloudFront.distributionId,urlRewriteMode:r.config.urlRewriteMode,extraReplacements:r.profile?.extraReplacements??{}}),c=On({siteId:e.wpsuite?.siteSettings?.siteId,accountId:e.wpsuite?.siteSettings?.accountId,sourceOrigin:e.sourceOrigin,ruleId:String(t.id||""),targetFingerprint:a}),o=`content-sync:${String(t.id||"")}:${ue({scopeFingerprint:i,targetFingerprint:a}).slice(0,32)}`,l=new lt({sourceOrigin:e.sourceOrigin,runtimeToken:String(e.wpsuite?.runtimeToken||""),ignoreHttpsErrors:e.ignoreHttpsErrors}),d=await l.releaseFingerprint(n.includeSubsites),u=Mn({wordpressFingerprint:d,targetFingerprint:a,sourceOrigin:e.sourceOrigin,sitemapPaths:Ge(e.sitemapPaths),blockedPathPrefixes:e.blockedPathPrefixes,assetPathPrefixes:e.assetPathPrefixes,noJavaScriptRenderPathPrefixes:e.noJavaScriptRenderPathPrefixes,urlRewriteMode:e.urlRewriteMode});return {rule:t,scope:n,deployment:r,deploymentProfile:s,scopeFingerprint:i,targetFingerprint:a,consumerId:c,coalesceKey:o,client:l,releaseFingerprint:u}}async function Ha(e){let t=Tn(),n=dt(t),r=await ie(),s=(r.scheduler?.rules??[]).filter(l=>l.command==="content-sync"&&l.enabled!==false);if(s.length===0)return 0;let i=await Wt(n),a=await pt(n),c=await Bt(n),o=0;for(let l of s){let d=await kn(r,l),u=c.entries[d.coalesceKey];if(!u||u.releaseJobId!==e||u.scopeFingerprint!==d.scopeFingerprint||u.targetFingerprint!==d.targetFingerprint||u.releaseFingerprint!==d.releaseFingerprint)throw new Error(`The normal release has no matching pre-crawl content-sync cutoff for rule ${String(l.id||"")}.`);let p=ue({releaseJobId:e,releaseFingerprint:d.releaseFingerprint,scopeFingerprint:d.scopeFingerprint,targetFingerprint:d.targetFingerprint,sequence:u.sequence}),f=await d.client.establishBaseline({consumerId:d.consumerId,scopeFingerprint:d.scopeFingerprint,baselineId:p,postTypes:d.scope.postTypes,includeSubsites:d.scope.includeSubsites,sequence:u.sequence}),g={schemaVersion:1,ruleId:String(l.id||""),consumerId:d.consumerId,coalesceKey:d.coalesceKey,scopeFingerprint:d.scopeFingerprint,targetFingerprint:d.targetFingerprint,releaseFingerprint:d.releaseFingerprint,baselineId:p,deploymentProfile:d.deploymentProfile,committedSequence:f.committedSequence,releaseJobId:e,verifiedAt:new Date().toISOString()};i.entries[d.coalesceKey]=g;let y=a.rules[d.coalesceKey];a.rules[d.coalesceKey]={ruleId:String(l.id||""),consumerId:d.consumerId,coalesceKey:d.coalesceKey,committedSequence:f.committedSequence,observedHeadSequence:f.headSequence,lag:Math.max(0,f.headSequence-f.committedSequence),lastSuccessfulJobId:y?.lastSuccessfulJobId||e,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:f.headSequence>f.committedSequence,retryAttempt:0,nextRetryAt:null,lastError:null,baselineStatus:"ready",baselineReason:null};let h=await zn(n,d.coalesceKey);await me(t,"content-sync-baseline-established",{id:e},"A normal release established a verified content-sync baseline.",{ruleId:l.id,consumerId:d.consumerId,committedSequence:f.committedSequence,supersededCurrent:h}),o++;}return await _n(n,i),await gt(n,a),await A.rm(n.releaseCutoff,{force:true}),o}async function za(e){let t=Tn(),n=dt(t),r=await ie(),s=(r.scheduler?.rules??[]).filter(c=>c.command==="content-sync"&&c.enabled!==false);if(s.length===0)return 0;let i=await Bt(n),a=0;for(let c of s){let o=await kn(r,c),l=Object.values(i.entries).find(p=>p.releaseJobId===e&&p.ruleId===String(c.id||""));if(l){if(l.coalesceKey===o.coalesceKey&&l.scopeFingerprint===o.scopeFingerprint&&l.targetFingerprint===o.targetFingerprint&&l.releaseFingerprint===o.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 d=await o.client.unboundHead(o.scope.postTypes,o.scope.includeSubsites),u={schemaVersion:1,releaseJobId:e,ruleId:String(c.id||""),coalesceKey:o.coalesceKey,scopeFingerprint:o.scopeFingerprint,targetFingerprint:o.targetFingerprint,releaseFingerprint:o.releaseFingerprint,sequence:d.headSequence,capturedAt:new Date().toISOString()};i.entries[o.coalesceKey]=u,await me(t,"content-sync-release-cutoff-captured",{id:e},"A normal release captured its pre-crawl content-sync journal cutoff.",{ruleId:c.id,consumerId:o.consumerId,sequence:d.headSequence}),a++;}return await qn(n,i),a}async function Qa(e,t){let n=JSON.parse(await A.readFile(S.join(e,"current-run.json"),"utf8"));if(n.id!==t||n.command!=="content-sync"||!String(n.ruleId||"").trim())throw new Error("The active queue job is not the requested content-sync job.");return n}async function An(e,t,n=0){let r=e.protocol==="https:"?jn:Rs,s=e.protocol==="https:"?new jn.Agent({rejectUnauthorized:!t}):void 0;return new Promise((i,a)=>{let c=r.get(e,{agent:s,timeout:3e4,headers:{"user-agent":"WP-Suite-Content-Sync/1"}},o=>{let l=o.statusCode??500,d=o.headers.location;if(l>=300&&l<400&&d&&n<5){o.resume(),An(new URL(d,e),t,n+1).then(i,a);return}let u=[],p=0;o.on("data",f=>{p+=f.byteLength,p<=1048576&&u.push(f);}),o.on("error",a),o.on("end",()=>i({status:l,body:Buffer.concat(u).toString("utf8")}));});c.on("timeout",()=>c.destroy(new Error(`Verification timed out: ${e}`))),c.on("error",a);})}async function Ja(e,t,n,r){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 i=JSON.parse(await A.readFile(r,"utf8")),a=new Set;for(let[l,d]of Object.entries(i.pages??{}))a.add(l),typeof d.url=="string"&&a.add(d.url);let c=await Me(e);if(c?.schemaVersion!==2||c.impactHash!==n.impactHash)throw new Error("Content-sync verification requires the matching targeted deploy plan.");let o=ds(n,a,c.resolvedSitemapUrls);for(let l of o.expectedAvailable){let d=new URL(l),u=new URL(`${d.pathname}${d.search}`,s),p=await An(u,e.ignoreHttpsErrors);if(p.status<200||p.status>=400)throw new Error(`Content-sync verification failed (${p.status}): ${u}`)}for(let l of o.expectedMissing.slice(0,10)){let d=new URL(l),u=new URL(`${d.pathname}${d.search}`,s),p=await An(u,e.ignoreHttpsErrors);if(p.status>=200&&p.status<300)throw new Error(`Deleted content is still publicly available: ${u}`)}}async function Va(e){let t=await A.readFile(e.candidateManifest,"utf8");JSON.parse(t);let n=`${e.trustedManifest}.${process.pid}.tmp`;await A.writeFile(n,t,"utf8"),await A.rename(n,e.trustedManifest);}async function Ka(e,t){try{let n=JSON.parse(await A.readFile(e.candidateManifest,"utf8"));if([...Object.values(n.pages??{}),...Object.values(n.assets??{})].some(s=>s?.lastSeenRunId===t))return "resumed"}catch(n){if(n.code!=="ENOENT")throw new Error(`The content-sync candidate manifest is invalid: ${n instanceof Error?n.message:String(n)}`,{cause:n})}return await A.copyFile(e.trustedManifest,e.candidateManifest).catch(n=>{throw new Error(`A trusted crawl manifest is required before content-sync: ${n instanceof Error?n.message:String(n)}`,{cause:n})}),"initialized"}async function Ie(e,t,n,r,s={},i=0,a=async()=>{}){t.phase=n,await Nn(e,t),await Hn(e,{schemaVersion:1,jobId:t.jobId,phase:n,completedItems:r,totalItems:r,attempt:i,updatedAt:new Date().toISOString(),details:s}),await me(S.dirname(e.state),"content-sync-checkpoint",{id:t.jobId},`Content-sync checkpoint completed: ${n}.`,{phase:n,completedItems:r,totalItems:r,attempt:i,...s}),await a(n,t);}async function Ga(e,t={}){let n={loadConfig:ie,resolveRuleContext:kn,runCrawl:es,runDeploy:as,runInvalidate:ls,verifyDeployment:Ja,promoteCandidateManifest:Va,clearDeployPlan:De,afterCheckpoint:async()=>{},...t},r=Tn(),s=dt(r),i=await Qa(r,e),a=await n.loadConfig(),c=Wa(a,String(i.ruleId)),o=await n.resolveRuleContext(a,c);if(i.coalesceKey&&i.coalesceKey!==o.coalesceKey)throw new Error("Queued content-sync demand no longer matches the active rule scope.");let d=(await Wt(s)).entries[o.coalesceKey];if(!d||d.scopeFingerprint!==o.scopeFingerprint||d.targetFingerprint!==o.targetFingerprint||d.releaseFingerprint!==o.releaseFingerprint)throw await me(r,"content-sync-baseline-rejected",i,"Content-sync requires a new verified full or incremental release baseline.",{ruleId:c.id,reason:d?"mismatch":"missing"}),new Error("Content-sync baseline is missing or stale. Run a successful normal publish first.");let u=await Ht(s),p=await o.client.head({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites});if(u&&u.jobId!==i.id)throw new Error("Another immutable content-sync range is still active.");if(u||(u={schemaVersion:1,jobId:i.id,ruleId:String(c.id||""),consumerId:o.consumerId,coalesceKey:o.coalesceKey,scopeFingerprint:o.scopeFingerprint,targetFingerprint:o.targetFingerprint,baselineId:d.baselineId,fromSequence:p.committedSequence,toSequence:p.headSequence,phase:"claimed",impactHash:null,startedAt:new Date().toISOString(),updatedAt:new Date().toISOString()},await Ie(s,u,"claimed",0,{fromSequence:u.fromSequence,toSequence:u.toSequence},0,n.afterCheckpoint),await me(r,"content-sync-range-claimed",i,"Content-sync claimed a closed journal range.",{fromSequence:u.fromSequence,toSequence:u.toSequence})),u.fromSequence===u.toSequence){let m=await pt(s);m.rules[o.coalesceKey]={ruleId:String(c.id||""),consumerId:o.consumerId,coalesceKey:o.coalesceKey,committedSequence:u.toSequence,observedHeadSequence:p.headSequence,lag:Math.max(0,p.headSequence-u.toSequence),lastSuccessfulJobId:i.id,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:false,retryAttempt:0,nextRetryAt:null,lastError:null},await gt(s,m),await zt(s);return}let f=await Bn(s);if(!We(u.phase,"impact-planned")){let m=await o.client.events({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites,afterSequence:u.fromSequence,throughSequence:u.toSequence}),w=Nt({events:m,scope:o.scope,sourceOrigin:a.sourceOrigin}),P=await o.client.resolveImpactFamilies(w,o.scope.includeSubsites);f=Ln({jobId:i.id,ruleId:String(c.id||""),consumerId:o.consumerId,coalesceKey:o.coalesceKey,scopeFingerprint:o.scopeFingerprint,targetFingerprint:o.targetFingerprint,baselineId:d.baselineId,sourceOrigin:a.sourceOrigin,scope:o.scope,fromSequence:u.fromSequence,toSequence:u.toSequence,events:m,resolvedArchiveFamilies:P,sitemapUrls:Ge(a.sitemapPaths)}),await Wn(s,f),u.impactHash=f.impactHash,await Ie(s,u,"impact-planned",m.length,{eventCount:m.length,foldedCount:f.foldedCount,impactHash:f.impactHash},0,n.afterCheckpoint),await me(r,"content-sync-impact-planned",i,"Content-sync persisted an immutable impact plan.",{impactHash:f.impactHash,eventCount:m.length});}if(!f||f.jobId!==i.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,!We(u.phase,"rendered")){let m=await Ka(s,i.id);await me(r,m==="resumed"?"content-sync-render-resumed":"content-sync-render-initialized",i,m==="resumed"?"Content-sync resumed its candidate crawl manifest.":"Content-sync initialized a candidate crawl manifest.",{impactHash:f.impactHash}),await n.runCrawl(["--content-sync-plan",s.impact]),await Ie(s,u,"rendered",f.directRenderUrls.length+f.archiveFamilyUrls.length,{impactHash:f.impactHash},i.attempt??0,n.afterCheckpoint);}let g=o.deploymentProfile?["--profile",o.deploymentProfile]:[];if(We(u.phase,"deployed")||(await n.runDeploy([...g,"--content-sync"]),await Ie(s,u,"deployed",1,{impactHash:f.impactHash},0,n.afterCheckpoint),await me(r,"content-sync-deployed",i,"Content-sync targeted deployment completed.",{impactHash:f.impactHash})),We(u.phase,"invalidated")?We(u.phase,"verified")||await n.runInvalidate([...g,"--content-sync"]):(await n.runInvalidate([...g,"--content-sync"]),await Ie(s,u,"invalidated",1,{impactHash:f.impactHash},0,n.afterCheckpoint)),We(u.phase,"verified")||(await n.verifyDeployment(a,o,f,s.candidateManifest),await n.promoteCandidateManifest(s),await Ie(s,u,"verified",1,{impactHash:f.impactHash},0,n.afterCheckpoint)),p=await o.client.head({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites}),p.committedSequence===u.fromSequence)await o.client.acknowledge({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,expectedSequence:u.fromSequence,sequence:u.toSequence,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites});else if(p.committedSequence!==u.toSequence)throw new Error("Content-sync acknowledgement cursor is in an unexpected state.");await Ie(s,u,"acknowledged",1,{sequence:u.toSequence},0,n.afterCheckpoint),await me(r,"content-sync-cursor-acknowledged",i,"Content-sync committed its journal cursor after verification.",{sequence:u.toSequence});let y=await o.client.head({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites}),h=await pt(s);h.rules[o.coalesceKey]={ruleId:String(c.id||""),consumerId:o.consumerId,coalesceKey:o.coalesceKey,committedSequence:u.toSequence,observedHeadSequence:y.headSequence,lag:Math.max(0,y.headSequence-u.toSequence),lastSuccessfulJobId:i.id,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:y.headSequence>u.toSequence,retryAttempt:0,nextRetryAt:null,lastError:null},await gt(s,h),await n.clearDeployPlan(a),await A.rm(S.join(r,"content-sync-invalidation.json"),{force:true}),await A.rm(s.candidateManifest,{force:true}),await zt(s);}async function fs(e=process.argv.slice(2)){let n=e.indexOf("--capture-baseline-cutoffs");if(n>=0){let a=String(e[n+1]||"").trim();if(!a)throw new Error("--capture-baseline-cutoffs requires a release job ID.");await za(a);return}let r=e.indexOf("--establish-baselines");if(r>=0){let a=String(e[r+1]||"").trim();if(!a)throw new Error("--establish-baselines requires a release job ID.");await Ha(a);return}let s=e.indexOf("--job-id"),i=s>=0?String(e[s+1]||"").trim():"";if(!i)throw new Error("Content-sync requires --job-id.");await Ga(i);}fs().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exit(1);});
|
|
13
|
+
${i}`,40);return r.info(`Using generated 404 fallback change token for ${n}`,{url:n,requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),{url:n,supported:!0,token:a,tokenSource:"generated-404-response-hash",postId:null,dependencyPostIds:[],reason:null}}catch(s){return r.warn(`Generated 404 fallback token lookup failed for ${n}`,{url:n,error:String(s),requestPath:e.generated404RequestPath,source:"generated-404-change-token-fallback"}),null}}async function Wi(e,t,n,r,s,i){let a=bn(e,s);if(!r.enabled)return {action:"render",changeToken:r.trackManifest?await Tt(e,t,r,s,i):null};let c=r.manifest.pages[s];if(!c)return {action:"render",changeToken:await Tt(e,t,r,s,i)};let o=await Tt(e,t,r,s,i);if(o?.supported&&o.token)return c.changeToken===o.token?a&&!await Hi(e,t,s,i)?{action:"render",changeToken:o}:{action:"reuse",changeToken:o}:{action:"render",changeToken:o};let l=it(n.sitemapLastmodByPage[s]);return l&&c.sitemapLastmod&&c.sitemapLastmod===l?{action:"reuse",changeToken:o}:{action:"render",changeToken:o}}async function Hi(e,t,n,r){try{let i=(await t.get(n,{timeout:Math.min(e.navigationTimeoutMs,15e3),failOnStatusCode:!1})).status();return i===404?!0:(r.warn(`Generated 404 request path no longer returns 404 for ${n}`,{url:n,status:i,requestPath:e.generated404RequestPath,source:"generated-404-status-probe"}),!1)}catch(s){return r.warn(`Generated 404 status probe failed for ${n}`,{url:n,error:String(s),requestPath:e.generated404RequestPath,source:"generated-404-status-probe"}),false}}async function zi(e,t,n,r,s){let i=Mr(n.previousManifest,void 0,r,"previous-manifest"),a=0;for(let[g,f]of Object.entries(n.manifest.pages))if(!n.seenPages.has(g)){gn(s,e,f.outputPath);try{await A.unlink(f.outputPath);}catch(p){(p.code||"")!=="ENOENT"&&r.warn(`Failed to remove stale incremental page output for ${g}`,{url:g,outputPath:f.outputPath,error:String(p)});}delete n.manifest.pages[g],a++;}let c=Mr(n.manifest,n.runId,r,"active-manifest"),o=new Set,l=new Set;for(let g of c){for(let y of ot(e,g))o.add(y);let f=n.manifest.assets[g]?.outputPath;f&&l.add(f);let p=qe(e,t.assetMap,g);p&&l.add(p);}for(let g of Object.keys(n.manifest.assets)){if(c.has(g)){n.manifest.assets[g].unreferencedRuns=0;continue}let f=n.manifest.assets[g];if(Ir(f.unreferencedRuns)){f.unreferencedRuns+=1,r.warn(`Deferred deletion of newly unreferenced incremental asset ${g}.`,{url:g,unreferencedRuns:f.unreferencedRuns,phase:"incremental-cleanup",source:"asset-deletion-grace"});continue}delete n.manifest.assets[g];}let d=0,u=0;for(let g of i){if(n.manifest.assets[g])continue;let f=new Set,p=n.previousManifest.assets[g]?.outputPath;p&&f.add(p);let y=qe(e,t.assetMap,g);if(!c.has(g)&&y)f.add(y);else if(!c.has(g)){let m=uo(e,g,r,"incremental-cleanup");m&&(f.add(m.originalFilePath),m.hashedFilePath&&f.add(m.hashedFilePath));}for(let m of f)if(!l.has(m)){gn(s,e,m);try{await A.unlink(m),d++;}catch(h){(h.code||"")!=="ENOENT"&&r.warn(`Failed to remove stale incremental asset output for ${g}`,{url:g,outputPath:m,error:String(h)});}}for(let m of ot(e,g))o.has(m)||Object.prototype.hasOwnProperty.call(t.assetMap,m)&&(delete t.assetMap[m],u++);}(a>0||d>0||u>0)&&r.info(`Incremental cleanup removed ${a} stale pages, ${d} stale assets, ${u} stale asset mappings`,{removedPages:a,removedAssets:d,removedAssetMappings:u,phase:"incremental-cleanup"});}async function Qi(e,t,n,r){let s=new Set([...Object.values(t.manifest.pages),...Object.values(t.manifest.assets)].map(o=>String(o.outputPath||"").trim()).filter(Boolean).map(o=>S.resolve(o))),i=Object.values(e.postCrawlCopyMap||{}).map(o=>kt(String(o||""))).filter(o=>!!o).map(o=>S.resolve(e.outputDir,o)),c=(await Zs(["**/*.html","**/*.htm"],{cwd:e.outputDir,onlyFiles:true,dot:true})).filter(o=>Cr(S.join(e.outputDir,o),e.outputDir,s,i));for(let o of c){let l=S.join(e.outputDir,o);gn(r,e,l),await A.unlink(l);}c.length>0&&n.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 Mr(e,t,n,r){let s=new Set,i=a=>{let c=a.trim();if(c){if(n){let o=Ce(c,n,"asset",r??"manifest");if(!o)return;s.add(o.toString());return}s.add(c);}};for(let a of Object.values(e.pages))for(let c of a.discoveredAssets||[])i(c);for(let[a,c]of Object.entries(e.assets||{}))t&&c.lastSeenRunId!==t||i(a);return s}function Dr(e,t,n){for(let r of t)for(let s of ot(e,r))if(n.has(s))return true;return false}function Ji(e,t,n,r,s){let i=new Set(n.rewriteTargets);for(let c of n.changedFiles)i.add(S.resolve(e.outputDir,c));for(let c of Object.values(t.manifest.pages))c.rewriteComplete||i.add(S.resolve(c.outputPath));for(let c of Object.values(t.manifest.assets))c.isText&&!c.rewriteComplete&&i.add(S.resolve(c.outputPath));let a=qi(r,s);if(a.size===0)return [...i];for(let c of Object.values(t.manifest.pages))Dr(e,c.discoveredAssets,a)&&i.add(S.resolve(c.outputPath));for(let[c,o]of Object.entries(t.manifest.assets)){o.isText&&Dr(e,o.discoveredAssets,a)&&i.add(S.resolve(o.outputPath));for(let l of ot(e,c))if(a.has(l)){te(n,e,o.outputPath),o.isText&&i.add(S.resolve(o.outputPath));break}}return [...i]}function Vi(e,t){let n=t?new Set(Array.from(t,s=>S.resolve(s))):null,r=s=>n===null||n.has(S.resolve(s));for(let s of Object.values(e.manifest.pages))r(s.outputPath)&&(s.rewriteComplete=true);for(let s of Object.values(e.manifest.assets)){if(!s.isText){s.rewriteComplete=true;continue}r(s.outputPath)&&(s.rewriteComplete=true);}}function Ki(e,t,n){let r=new Set,s=i=>{if(!i)return;let a=pe(e.outputDir,i);a&&r.add(a);};for(let i of t.donePages)s(he(e,i));for(let i of Object.values(n.manifest.pages))i.lastSeenRunId===n.runId&&s(i.outputPath);for(let i of t.doneAssets)s(qe(e,t.assetMap,i));for(let i of Object.values(n.manifest.assets))i.lastSeenRunId===n.runId&&s(i.outputPath);return r}async function Gi(e,t,n,r,s){let i=[...r.deletedFiles].sort(),a=Ki(e,t,n),c=0;for(let d of [...a].sort()){try{if((await A.stat(S.join(e.outputDir,d))).isFile())continue}catch{}c++,s.warn(`Active output is missing after crawl: ${d}`,{phase:"deploy-plan",file:d,outputPath:S.join(e.outputDir,d)});}if(c>0&&s.warn(`Detected ${c} active output file(s) missing before deploy plan save.`,{phase:"deploy-plan",missingActiveOutputs:c}),i.length===0)return [];let o=[],l=0;for(let d of i){if(!a.has(d)){o.push(d);continue}l++;let u=S.join(e.outputDir,d),g;try{g=(await A.stat(u)).isFile();}catch{g=false;}s.warn(`Deploy plan protected active output from deletion: ${d}`,{phase:"deploy-plan",file:d,outputPath:u,exists:g});}return l>0&&s.info(`Deploy plan skipped ${l} active output deletion(s).`,{phase:"deploy-plan",protectedDeletes:l,deletedFiles:o.length}),o}function ot(e,t){let n=new Set([t]);try{let r=new URL(t),i=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{i.push(new URL(e.targetOrigin).origin);}catch{}for(let a of i)try{n.add(new URL(a).origin+r.pathname+r.search);}catch{}n.add(r.pathname+r.search),n.add(r.pathname);}catch{}return [...n]}function Zi(e,t){let n=new Set([t]);try{let r=new URL(t),i=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{i.push(new URL(e.targetOrigin).origin);}catch{}for(let a of i)try{n.add(new URL(a).origin+r.pathname+r.search);}catch{}n.add(r.pathname+r.search);}catch{}return [...n]}function Vr(e,t){let n=e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/"?e.targetOrigin:"https://relative.invalid/";try{let r=new URL(t,n);return nt(e.outputDir,r.pathname)}catch{return null}}function Yi(e,t,n){for(let r of Zi(e,n)){let s=t[r];if(!s)continue;let i=Vr(e,s);if(i)return {outputPath:i,publicUrl:s}}return null}function Xi(e,t,n){for(let r of ot(e,n)){let s=t[r];if(!s)continue;let i=Vr(e,s);if(i)return i}return null}function qe(e,t,n){let r=Xi(e,t,n);if(r)return r;try{return Dt(e,n).originalFilePath}catch{return null}}function eo(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?S.join(S.resolve(e),"queue-runner-heartbeat.json"):""}async function Or(e){let t=eo();if(t)try{let n=await A.readFile(t,"utf8"),r=JSON.parse(n);if(!r||typeof r!="object")return;await A.writeFile(t,JSON.stringify({...r,checkedAt:new Date().toISOString(),status:"running",currentStep:"rewrite",message:e},null,2),"utf8");}catch{}}function to(e,t){let n=new Set;for(let r of t.donePages)n.add(S.resolve(he(e,r)));for(let r of t.doneAssets){let s=qe(e,t.assetMap,r);!s||!Pe(s)||n.add(S.resolve(s));}for(let r of t.doneSitemaps){let s=qe(e,t.assetMap,r);!s||!Pe(s)||n.add(S.resolve(s));}return [...n]}var $t="re:",At=new Map;function no(e){if(!e.startsWith($t))return null;let t=At.get(e);if(t!==void 0)return t||null;let n=e.slice($t.length).trim();if(!n)return At.set(e,false),null;try{let r=new RegExp(n);return At.set(e,r),r}catch{return console.warn(`[crawl] Ignoring invalid path matcher regex: ${e}`),At.set(e,false),null}}function Sn(e,t){let n=no(t);return n?n.test(e):t.startsWith($t)?false:e.startsWith(t)}function ro(e,t){return t.find(n=>Sn(e,n))}function Kr(e,t){let n=ro(t.pathname,e.blockedPathPrefixes);if(n)return n.startsWith($t)?`blocked path regex: ${n}`:`blocked path prefix: ${n}`;let r=e.blockedSearchFragments.find(s=>t.search.includes(s));return r?`blocked search fragment: ${r}`:null}function so(e){let t=new URL(e.sourceOrigin),n=new Set([t.hostname,...e.allowedAssetHosts]);if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{n.add(new URL(e.targetOrigin).hostname);}catch{}for(let r of Object.keys(e.extraReplacements||{}))try{n.add(new URL(r).hostname);}catch{}return n}function io(e,t){return so(e).has(t.hostname)}function oo(e){let t=fe(e.trim()).replace(/\\\//g,"/").replace(/^['"]|['"]$/g,"").trim();return t=t.replace(/[)]+$/g,"").trim(),t=t.replace(/;.*$/g,"").trim(),t}function mn(e){let t=fe(e).replace(/\\\//g,"/");return /[{}]|\bwindow\.|\blocation\.|\bincludes\(|\?\?null|\+|%7B|%7D|%22|<|>|\s/.test(t)||/[()[\]'"]/.test(t)}function ao(e){let t=fe(e).replace(/\\\//g,"/").trim(),n=S.extname(t).toLowerCase();return Br.has(n)||Wr.has(n)?false:/^(?:this|[A-Za-z_$][\w$]*)\.[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(t)}function _e(e){return ki.some(t=>e.pathname.startsWith(t))}function J(e,t,n=e.sourceOrigin,r,s="url",i=false){let a=oo(t);if(!a||a.startsWith("data:")||a.startsWith("blob:")||a.startsWith("mailto:")||a.startsWith("tel:")||a.startsWith("#"))return r?.ignore(s,t,"empty or unsupported scheme",n),null;if(mn(a))return r?.ignore(s,t,"looks like JavaScript/code fragment",n),null;if(ao(a))return r?.ignore(s,t,"looks like JavaScript property access",n),null;try{let c=new URL(a,n);if(Gr(c))return r?.reject(s,t,"malformed URL encoding",n),null;if(!["http:","https:"].includes(c.protocol))return r?.ignore(s,t,"unsupported protocol: ",n),null;if(!io(e,c))return r?.ignore(s,c.toString(),"host not allowed",n),null;let o=Kr(e,c);if(o&&!(i&&Gt(c)))return r?.reject(s,c.toString(),o,n),null;let l=new URL(e.sourceOrigin);return c.protocol=l.protocol,c.host=l.host,c.hash="",c}catch{return r?.reject(s,t,"invalid URL",n),null}}function Gr(e){try{return decodeURIComponent(e.pathname),decodeURIComponent(e.search),decodeURIComponent(e.hash),!1}catch{return true}}function Ce(e,t,n,r){try{let s=new URL(e);return Gr(s)?(t.reject(n,e,"malformed URL encoding",r),null):tt(s.pathname)===null?(t.reject(n,e,"unsafe URL pathname",r),null):s.protocol!=="http:"&&s.protocol!=="https:"?(t.reject(n,e,`unsupported protocol: ${s.protocol}`,r),null):s}catch{return t.reject(n,e,"invalid URL",r),null}}function Zr(e){return Br.has(S.extname(e.pathname).toLowerCase())}function Re(e){return _e(e)?false:Wr.has(S.extname(e.pathname).toLowerCase())}function Ne(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function W(e,t){return !!(Ne(t)||t.pathname==="/robots.txt"||t.pathname==="/llms.txt"||t.pathname.toLowerCase().endsWith(".xsl")||e.assetPathPrefixes.length>0&&e.assetPathPrefixes.some(n=>Sn(t.pathname,n))||Zr(t)||!Re(t)&&!_e(t))}function he(e,t){let n=new URL(t),r=tt(n.pathname);if(r===null)throw new Error(`Unsafe page URL pathname: ${n.pathname}`);return r.endsWith("/")?r+="index.html":S.extname(r)||(r+="/index.html"),nt(e.outputDir,r)}function co(e){if(!e.generated404RequestPath)return null;try{let t=new URL(e.generated404RequestPath,e.sourceOrigin);return !t.pathname.endsWith("/")&&S.extname(t.pathname)===""&&(t.pathname+="/"),t.hash="",t.toString()}catch{return null}}function bn(e,t){let n=co(e);if(!n)return false;try{return new URL(t,e.sourceOrigin).toString()===n}catch{return false}}function Dt(e,t){let n=new URL(t),r=tt(n.pathname);if(r===null)throw new Error(`Unsafe asset URL pathname: ${n.pathname}`);r.endsWith("/")&&(r+="index.html");let s=!!n.search,i=r,a=nt(e.outputDir,i),c=sn(e.targetOrigin,i),o=`${c}${n.search}`;if(!s)return {originalPathname:i,originalFilePath:a,originalPublicUrl:c,originalPublicUrlWithSearch:o,preferQueryHashed:s};let l=S.extname(r),u=`${l?r.slice(0,-l.length):r}.${Ye(n.search)}${l||".bin"}`;return {originalPathname:i,originalFilePath:a,originalPublicUrl:c,originalPublicUrlWithSearch:o,preferQueryHashed:s,hashedPathname:u,hashedFilePath:nt(e.outputDir,u),hashedPublicUrl:sn(e.targetOrigin,u)}}function uo(e,t,n,r){let s=Ce(t,n,"asset",r);return s?Dt(e,s.toString()):null}function lo(e,t,n,r,s){t[n]=r;try{let i=new URL(n),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 o of c)try{let l=new URL(o);t[l.origin+i.pathname+i.search]=r;}catch{}try{let o=(()=>{let l=new URL(r,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin);return `${l.pathname}${l.search}`})();t[i.pathname+i.search]=o;}catch{}try{let o=new URL(r,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[i.pathname]=o;}catch{}try{let o=new URL(s,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[i.pathname]=o;}catch{}}catch{}}async function Yr(e){try{return await A.readFile(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}async function je(e){try{return await A.stat(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}function po(e){let t=String(e["content-length"]||"").trim();if(!t)return null;let n=Number.parseInt(t,10);return Number.isFinite(n)&&n>=0?n:null}function Xr(e){let t=String(e["last-modified"]||"").trim();if(!t)return null;let n=Date.parse(t);return Number.isFinite(n)?n:null}function go(e,t){let n=Xr(t),r=po(t),s=e?.mtime.getTime();return n!==null&&Math.abs((s??0)-n)>=1e3||r!==null&&e?.size!==r?false:n!==null||r!==null}async function fo(e,t){if(!t)return;let n=Xr(t);if(n===null)return;let r=await je(e);if(!r)return;let s=new Date(n);await A.utimes(e,r.atime,s).catch(()=>{});}function Fr(e,t){let n=S.extname(e.pathname).toLowerCase(),r=t["content-type"]||"";return Ti.has(n)||Ai.some(s=>r.includes(s))&&!r.startsWith("image/")&&!r.includes("font")}function mo(e){try{let t=S.extname(new URL(e).pathname).toLowerCase();return t===".js"||t===".mjs"}catch{return false}}function Le(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 ho(e){return Ye(e.toString("base64"),40)}function wo(e,t,n){let r=e.assetVariantDigestsByOriginalPath.get(t);if(!r||r.size===0)return false;for(let s of r)if(s!==n)return true;return false}function yo(e,t,n){let r=e.assetVariantDigestsByOriginalPath.get(t);r||(r=new Set,e.assetVariantDigestsByOriginalPath.set(t,r)),r.add(n);}async function hn(e,t,n,r,s,i,a){let c=Dt(e,n),o=ho(r),l=c.originalFilePath,d=c.originalPublicUrlWithSearch;if(c.preferQueryHashed&&c.hashedFilePath&&c.hashedPublicUrl&&wo(s,c.originalFilePath,o)){let p=Yi(e,t,n);p?(l=p.outputPath,d=p.publicUrl):(l=c.hashedFilePath,d=c.hashedPublicUrl);}lo(e,t,n,d,c.originalPublicUrl);let u=Pe(l)?Buffer.from(cn(r.toString("utf8"),e,t,l),"utf8"):r,g=await Yr(l),f=false;return (g===null||!g.equals(u))&&(await Xe(l,u),f=true),i?.debug(`${f?"Saved":"Skipped unchanged"} asset output ${n}`,{phase:"download-assets",url:n,outputPath:l,bytes:u.length,wroteFile:f}),yo(s,c.originalFilePath,o),await fo(l,a),s.stats.assetsSaved++,i&&(s.stats.assetsSaved%50===0||s.stats.assetsSaved===1)&&i.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:l,publicUrl:d,wroteFile:f}}function at(e,t,n,r,s){let i=()=>{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 Ne(g)?{discoveredFrom:u,discoveredFromType:"sitemap"}:W(e,g)?{discoveredFrom:u,discoveredFromType:"asset"}:Re(g)&&!_e(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=J(e,n,a,r,"page");if(!c)return;if(!Re(c)||Zr(c)){if(W(e,c)){r.info(`Seeded/non-page URL queued as asset: ${c.toString()}`,{url:c.toString(),source:s}),Q(e,t,c.toString(),r,s);return}r.reject("page",c.toString(),_e(c)?"asset/internal path cannot be page":"not page-like",s);return}let o=c.toString(),{discoveredFrom:l,discoveredFromType:d}=i();l&&!t.pageDiscoverySources.has(o)&&t.pageDiscoverySources.set(o,l),!t.donePages.has(o)&&!t.queuedPages.has(o)&&(t.queuedPages.add(o),t.pageQueue.push(o),t.stats.pagesQueued++,r.debug(`Queued discovered page ${o}`,{phase:"discovery",url:o,discoveredFrom:l,discoveredFromType:d,outputPath:he(e,o)}),(t.stats.pagesQueued%25===0||t.stats.pagesQueued===1)&&r.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,n,r,s){let i=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,a=J(e,n,i,r,"asset");if(!a)return;if(!W(e,a)){r.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)&&r.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 Et(e,t,n,r,s){let i=s&&/^https?:\/\//i.test(s)?s:e.sourceOrigin,a=J(e,n,i,r,"sitemap",Kn(s));if(!a)return;if(!Ne(a)){r.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)&&r.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 So(e){let t=fe(e),n=[...t.matchAll(/<url>\s*([\s\S]*?)\s*<\/url>/gi)].map(r=>r[1]);return n.length>0?n.map(r=>{let s=r.match(/<loc>\s*([^<]+?)\s*<\/loc>/i);if(!s?.[1])return null;let i=r.match(/<lastmod>\s*([^<]+?)\s*<\/lastmod>/i);return {loc:s[1].trim(),lastmod:it(i?.[1]??null)}}).filter(r=>!!r):[...t.matchAll(/<loc>\s*([^<]+?)\s*<\/loc>/gi)].map(r=>({loc:r[1].trim(),lastmod:null})).filter(r=>r.loc)}function bo(e){return e.split(",").map(t=>t.trim().split(/\s+/)[0]).filter(Boolean)}function Po(e){let t=[],n=/url\(\s*(?:"([^"]+)"|'([^']+)'|([^)]*?))\s*\)/gi;for(let r of e.matchAll(n)){let s=e.slice(Math.max(0,r.index-8),r.index);if(/\bnew\s+$/i.test(s))continue;let i=(r[1]||r[2]||r[3]||"").trim();i&&t.push(i);}return t}function vo(e){return e.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>/gi,"")}function Co(e,t){if(t==="dom-style")return true;let n=(()=>{try{return S.extname(new URL(e).pathname).toLowerCase()}catch{return ""}})();return !(n===".js"||n===".mjs"||n===".map"||t.includes("javascript"))}function kt(e){return e.trim().replace(/\\/g,"/").replace(/^https?:\/\/[^/]+/i,"").replace(/^\/+/,"")}async function es(e,t,n,r){let s=[];await A.mkdir(t,{recursive:true});let i=await A.readdir(e,{withFileTypes:true});for(let a of i){let c=S.join(e,a.name),o=S.join(t,a.name);if(a.isDirectory()){s.push(...await es(c,o,n,r));continue}await ts(c,o,n,r)&&s.push(o);}return s}async function Ro(e,t){try{let[n,r]=await Promise.all([A.stat(e),A.stat(t)]);if(n.size!==r.size)return !1;let[s,i]=await Promise.all([A.readFile(e),A.readFile(t)]);return s.equals(i)}catch{return false}}async function ts(e,t,n,r){let s=S.resolve(t);return n.has(s)?(r.debug("Skipped post-crawl copy over crawled page output",{phase:"copy-extra-paths",sourcePath:e,targetPath:t}),false):await Ro(e,t)?(r.debug("Skipped unchanged post-crawl copy target",{phase:"copy-extra-paths",sourcePath:e,targetPath:t}),false):(await A.mkdir(S.dirname(t),{recursive:true}),await A.copyFile(e,t),true)}async function xo(e,t,n){let r=Object.entries(e.postCrawlCopyMap||{}).map(([c,o])=>({sourcePath:c.trim(),prefix:String(o||"").trim()}));if(r.length===0)return [];let s=0,i=[],a=new Set([...t.donePages].map(c=>S.resolve(he(e,c))));n.mark("copy-extra-paths");for(let c of r){let o=c.sourcePath,l=c.prefix;if(!o||!l){n.warn("Skipped post-crawl copy mapping with empty key/value",{sourcePath:o,prefixPath:l});continue}let d=Oi(o);if(!d.resolvedPath){n.warn("Skipped post-crawl copy source because alias root is not configured",{sourcePath:o,alias:d.alias||"",requiredEnv:d.requiredEnv||"",prefixPath:l});continue}let u=d.resolvedPath,g=kt(l);if(!g){n.warn("Skipped post-crawl copy mapping with invalid export prefix",{sourcePath:o,prefixPath:l});continue}let f;try{f=await A.stat(u);}catch{n.warn("Skipped post-crawl copy source because it does not exist",{sourcePath:o,sourceAbs:u,prefixPath:l});continue}let p=S.resolve(e.outputDir,g);if(f.isDirectory()){let w=await es(u,p,a,n);i.push(...w),s+=w.length,w.length>0&&n.progress(`Copied static directory to export: ${u} -> /${g}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${g}`,copiedItems:s,changedFiles:w.length});continue}let y=S.basename(u),m=l.endsWith("/")?S.join(p,y):p;await ts(u,m,a,n)&&(i.push(m),s++,n.progress(`Copied static file to export: ${u} -> /${kt(l.endsWith("/")?`${l}${y}`:l)}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${kt(l.endsWith("/")?`${l}${y}`:l)}`,copiedItems:s}));}return n.endMark("copy-extra-paths",{mappedSources:r.length,copiedItems:s}),i}function ct(e,t,n,r,s){let i=new Set,a=fe(n).replace(/\\\//g,"/"),c=s==="page-html"?vo(a):a,o=Co(t,s);if(o){for(let l of Po(c)){let d=J(e,l,t,r,`${s}:css-url`);d&&W(e,d)&&i.add(d.toString());}for(let l of c.matchAll(/@import\s+(?:url\()?\s*['"]?([^'"\s;]+)['"]?\s*\)?/gi)){let d=J(e,l[1],t,r,`${s}:css-import`);d&&W(e,d)&&i.add(d.toString());}}if(o||s==="page-html")for(let l of c.matchAll(/<\?xml-stylesheet[^>]+href=["']([^"']+)["'][^>]*\?>/gi)){let d=J(e,l[1],t,r,`${s}:xml-stylesheet`);d&&W(e,d)&&i.add(d.toString());}if(s==="page-html")for(let l of br(a)){let d=l.startsWith("//")?`${new URL(e.sourceOrigin).protocol}${l}`:l;if(mn(d)){r.ignore(`${s}:serialized-url`,d,"looks like JavaScript/code fragment",t);continue}let u=J(e,d,t,r,`${s}:serialized-url`);u&&W(e,u)?i.add(u.toString()):u&&r.ignore("asset",u.toString(),"serialized URL did not pass safe asset path filter",t);}if(s!=="page-html"&&mo(t))for(let l of Pr(a)){if(mn(l)||!/\.(?:js|mjs)(?:[?#]|$)/i.test(l))continue;let d=J(e,l,t,r,`${s}:relative-asset`);d&&W(e,d)&&i.add(d.toString());}return [...i]}function Io(e,t,n,r){let s=new Set,i=fe(n);for(let a of i.matchAll(/href=["']([^"'#\s][^"']*?)["']/gi)){let c=a[1],o=J(e,c,t,r,"page-link");o&&(Kr(e,o)||Re(o)&&!_e(o)&&!W(e,o)&&s.add(o.toString()));}return [...s]}async function Ur(e,t,n,r,s,i,a=false,c=[]){let o=new Set(c),l=0,d=new Map,u=(g,f)=>{let p=[f],y=new Set;for(;p.length>0;){let m=p.pop();if(m===g)return true;y.has(m)||(y.add(m),p.push(...d.get(m)??[]));}return false};for(;n.sitemapQueue.length>0;){let g=n.sitemapQueue.shift();n.queuedSitemaps.delete(g);let f=Ce(g,r,"sitemap","sitemap-queue");if(!f)continue;let p=f.toString();if(n.doneSitemaps.has(p))continue;n.doneSitemaps.add(p),r.sitemap(`Fetching sitemap ${p}`,{url:p});let y=true;try{let m=await t.get(p,{timeout:6e4});if(y=!1,!m.ok()){if(r.skip("sitemap",p,m.status()),a&&!o.has(p))throw new Error(`Required child content-sync sitemap returned HTTP ${m.status()}: ${p}`);continue}let h=await m.body(),w=m.url()||p,P=Ce(w,r,"sitemap-response",p);if(!P)continue;let x=P.toString();n.successfulSitemaps.add(p),n.successfulSitemaps.add(x),o.has(p)&&(n.resolvedSitemapRoots.add(x),l+=1);let j=await hn(e,n.assetMap,x,h,n,r);te(s,e,j.outputPath),Ie(s,j.outputPath);let M=h.toString("utf8");/<sitemapindex(?:\s|>)/i.test(M)?n.sitemapIndexUrls.add(x):n.sitemapLeafUrls.add(x);let _=ct(e,x,M,r,"sitemap");for(let $ of _)Q(e,n,$,r,x);let C=[];for(let $ of So(M)){let R=J(e,$.loc,x,r,"sitemap-loc",!0);if(!R){if(a)throw new Error(`Content-sync sitemap contains an inadmissible location: ${$.loc}`);continue}if(Ne(R)){if(u(x,R.toString()))throw new Error(`Sitemap index cycle detected: ${x} -> ${R.toString()}`);if(d.has(x)||d.set(x,new Set),d.get(x).add(R.toString()),C.push(R.toString()),a&&n.doneSitemaps.has(R.toString())&&!n.successfulSitemaps.has(R.toString()))throw new Error(`Required child content-sync sitemap was not resolved: ${R.toString()}`);Et(e,n,R.toString(),r,x);}else if(a){if(Re(R)&&!W(e,R)){let U=i.requiredUrls.has(R.toString()),b=i.manifest.pages[R.toString()],T=!!b&&!!await je(b.outputPath);if(!U&&!T)throw new Error(`Content-sync sitemap coverage is incomplete for ${R.toString()}.`)}r.ignore("sitemap-loc",R.toString(),"content-sync sitemap-only traversal does not enqueue urlset locations",x);}else W(e,R)?Q(e,n,R.toString(),r,x):Re(R)?($.lastmod&&(n.sitemapLastmodByPage[R.toString()]=$.lastmod),at(e,n,R.toString(),r,x)):r.reject("sitemap-loc",R.toString(),"not page/sitemap/asset-like",x);}i.trackManifest&&(i.manifest.assets[x]={url:x,outputPath:j.outputPath,isText:!0,contentType:m.headers()["content-type"]??"application/xml",changeToken:null,tokenSource:null,discoveredAssets:[...new Set([..._,...C])],lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,unreferencedRuns:0,rewriteComplete:!1},await ve(e,i));}catch(m){r.error(`Failed sitemap ${p}`,{url:p,error:String(m)});let h=a&&o.has(p)&&y;if(a&&!h)throw m}}if(a&&o.size>0&&l===0)throw new Error(`None of the configured content-sync sitemap roots could be resolved: ${[...o].join(", ")}`)}async function Ao(e,t,n,r,s,i,a){let c=J(e,r,e.sourceOrigin,s,"asset-fetch");if(!c||!W(e,c))return;let o=c.toString();if(n.doneAssets.has(o))return;let l=i.enabled||i.strictTargeted?i.previousManifest.assets[o]:void 0,d=i.trackManifest?await Tt(e,t,i,o,s):null,u=d?.token??null,g=Rr(l?.changeToken,d),f=i.strictTargeted&&(!d?.supported||!d.token)&&xr(e.sourceOrigin,o),p=i.strictTargeted?i.manifest.assets[o]:void 0;if(p?.lastSeenRunId===i.runId&&await je(p.outputPath)){n.doneAssets.add(o);for(let m of p.discoveredAssets||[])Q(e,n,m,s,o);te(a,e,p.outputPath),p.isText&&Ie(a,p.outputPath),s.info(`Resumed completed content-sync asset ${o}`,{url:o,source:"content-sync-checkpoint"}),Le(n,s);return}if(l&&(g||f)&&await je(l.outputPath)){i.manifest.assets[o]={...l,changeToken:u,tokenSource:d?.tokenSource??l.tokenSource,discoveredAssets:[...l.discoveredAssets||[]],lastSeenRunId:i.runId,unreferencedRuns:0},delete i.manifest.pages[o],n.doneAssets.add(o);for(let m of l.discoveredAssets||[])Q(e,n,m,s,o);s.info(`Reused unchanged trusted asset ${o}.`,{url:o,tokenSource:d?.tokenSource??"unknown",phase:"download-assets",source:g?"asset-change-token-match":"content-sync-release-fingerprint"}),Le(n,s);return}let y=(m,h={})=>{if(!l||i.strictTargeted)return false;i.manifest.assets[o]={...l,discoveredAssets:[...l.discoveredAssets||[]],lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,unreferencedRuns:0},delete i.manifest.pages[o],n.doneAssets.add(o);for(let w of l.discoveredAssets||[])Q(e,n,w,s,o);return s.warn(`Keeping previous incremental asset ${o} after fetch issue.`,{url:o,reason:m,preservedFromPreviousManifest:true,...h,phase:"download-assets"}),Le(n,s),true};s.asset(`Fetching asset ${o}`,{url:o});try{let m=qe(e,n.assetMap,o),h=m?await je(m):null;if(m&&h)try{let U=await H(`fetch asset headers ${o}`,6e4,()=>t.head(o,{timeout:6e4})),b=U.headers();if(U.ok()&&go(h,b)){let T=await Yr(m);if(T!==null){let O=U.url()||o,q=Ce(O,s,"asset-response",o);if(!q)return;let v=q.toString(),E=await hn(e,n.assetMap,v,T,n,s,b);E.wroteFile&&(te(a,e,E.outputPath),Pe(E.outputPath)&&Ie(a,E.outputPath)),n.doneAssets.add(o),s.info(`Reused existing asset ${o} based on response headers.`,{url:o,filePath:m,lastModified:b["last-modified"]||"",contentLength:b["content-length"]||"",phase:"download-assets"}),Le(n,s);let F=Fr(c,b),z=l?.discoveredAssets?[...l.discoveredAssets]:[];if(F||l?.isText){let ee=T.toString("utf8"),Te=ct(e,v,ee,s,"asset:cached");(Te.length>0||!l)&&(z=Te);for(let D of z)Q(e,n,D,s,v);}if(i.trackManifest){let ee=F||!!l?.isText;i.manifest.assets[o]={url:o,outputPath:E.outputPath,isText:ee,contentType:pn(b)||l?.contentType||null,changeToken:d?.supported?d.token:null,tokenSource:d?.supported?d.tokenSource??null:null,discoveredAssets:z,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,unreferencedRuns:0,rewriteComplete:!ee},delete i.manifest.pages[o],(i.enabled||i.strictTargeted)&&ee&&await ve(e,i);}return}}}catch{}let w=await H(`fetch asset ${o}`,6e4,()=>t.get(o,{timeout:6e4}));if(!w.ok()){if(y(`http-${w.status()}`,{status:w.status()}))return;if(i.strictTargeted)throw new Error(`Required content-sync asset returned HTTP ${w.status()}: ${o}`);s.skip("asset",o,w.status());return}let P=await H(`read asset response ${o}`,6e4,()=>w.body()),x=w.url()||o,j=Ce(x,s,"asset-response",o);if(!j)return;let M=j.toString(),_=w.headers(),C=await hn(e,n.assetMap,M,P,n,s,_);C.wroteFile&&(te(a,e,C.outputPath),Pe(C.outputPath)&&Ie(a,C.outputPath)),n.doneAssets.add(o),Le(n,s);let $=Fr(c,_),R=[];if($){let U=P.toString("utf8");R=ct(e,M,U,s,`asset:${S.extname(c.pathname).toLowerCase()||_["content-type"]||"unknown"}`);for(let b of R)Q(e,n,b,s,M);}i.trackManifest&&(i.manifest.assets[o]={url:o,outputPath:C.outputPath,isText:$,contentType:pn(_),changeToken:d?.supported?d.token:null,tokenSource:d?.supported?d.tokenSource??null:null,discoveredAssets:R,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,unreferencedRuns:0,rewriteComplete:!$},delete i.manifest.pages[o],(i.enabled||i.strictTargeted)&&$&&await ve(e,i));}catch(m){if(y("fetch-error",{error:String(m)}))return;if(s.error(`Failed asset ${o}`,{url:o,error:String(m)}),i.strictTargeted)throw m}finally{n.doneAssets.has(o)||(n.doneAssets.add(o),Le(n,s));}}async function To(e,t,n,r,s,i){let a=Math.max(1,Number(e.assetDownloadConcurrency||e.concurrency||1)),c=Array.from({length:a},async()=>{for(;n.assetQueue.length>0;){let o=n.assetQueue.shift();o&&(n.queuedAssets.delete(o),await Ao(e,t,n,o,r,s,i));}});await Promise.all(c);}function ko(e){let t=Math.ceil(e/1e3);return `${t} second${t===1?"":"s"}`}function me(e){return Math.max(6e4,e.navigationTimeoutMs*2,e.readiness.timeoutMs+e.readiness.fallbackWaitMs+15e3)}function st(e){return Math.max(15e3,Math.min(6e4,me(e)))}function $o(e){return Math.max(15e3,e.readiness.timeoutMs+e.readiness.fallbackWaitMs+1e4)}function Pn(e){return e.stats.pagesCompleted}function wn(e){let n=e.options?.browserProcess;return {pid:typeof n?.process?.pid=="number"?n.process.pid:null,kill:typeof n?.kill=="function"?n.kill.bind(n):null}}async function dn(e,t,n){let r=wn(e);try{if(r.kill){await r.kill(),t.warn(`Force-killed crawl worker browser after ${n}`,{browserPid:r.pid,reason:n});return}if(r.pid!==null){process.kill(r.pid,"SIGKILL"),t.warn(`Sent SIGKILL to crawl worker browser after ${n}`,{browserPid:r.pid,reason:n});return}t.warn(`Could not resolve crawl worker browser PID after ${n}`,{reason:n});}catch(s){t.error(`Failed to force-kill crawl worker browser after ${n}`,{browserPid:r.pid,reason:n,error:String(s)});}}async function H(e,t,n){let r;try{return await Promise.race([n(),new Promise((s,i)=>{r=globalThis.setTimeout(()=>{i(new ut(e,t));},t);})])}finally{r!==void 0&&globalThis.clearTimeout(r);}}var ut=class extends Error{constructor(n,r){super(`${n} timed out after ${ko(r)}.`);this.operation=n;this.timeoutMs=r;this.name="OperationTimeoutError";}operation;timeoutMs};async function Eo(e,t){let n=$o(e);await t.evaluate(async r=>{await new Promise(s=>{let i=0,a=700,c=Date.now(),o=()=>{window.clearInterval(l),window.scrollTo(0,0),s();},l=window.setInterval(()=>{if(Date.now()-c>=r.maxDurationMs){o();return}window.scrollBy(0,a),i+=a;let d=document.body?.scrollHeight||0,u=document.documentElement?.scrollHeight||0,g=Math.max(d,u);i>=g+window.innerHeight&&o();},120);});},{maxDurationMs:n});}async function Mo(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 Eo(e,t),await t.waitForTimeout(e.readiness.fallbackWaitMs);}async function Do(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 Oo(e,t){return e.noJavaScriptRenderPathPrefixes.some(n=>Sn(t,n))}async function Fo(e,t,n,r,s=true){let i=new Set;if(s){let c=await t.evaluate(()=>{let o=new Set,l=["href","src","poster","data-src","data-lazy-src","data-original","data-bg","data-background","data-href","data-resource-url"],d=new Set,u=["srcset","data-srcset","data-lazy-srcset"],g=f=>{f.querySelectorAll("*").forEach(p=>{for(let m of l){let h=p.getAttribute(m);h&&o.add(h);}for(let m of u){let h=p.getAttribute(m);h&&h.split(",").forEach(w=>{let P=w.trim().split(/\s+/)[0];P&&o.add(P);});}let y=p.getAttribute("style");y&&d.add(y),p.shadowRoot&&g(p.shadowRoot);});};return g(document),{attrs:[...o],styles:[...d]}});for(let o of c.attrs)for(let l of bo(o)){let d=J(e,l,n,r,"dom-attr");d&&W(e,d)&&i.add(d.toString());}for(let o of c.styles)for(let l of ct(e,n,o,r,"dom-style"))i.add(l);}let a=await t.content();for(let c of ct(e,n,a,r,"page-html"))i.add(c);return [...i]}async function Lr(e,t,n,r,s){let i=he(e,t);await Xe(i,n,"utf8");let a=await A.stat(i);s?.debug(`Saved page output ${t}`,{phase:"save-pages",url:t,outputPath:i,bytes:a.size}),r.stats.pagesSaved++;let c=Math.min(r.stats.pagesQueued,Pn(r)+1);s&&(r.stats.pagesSaved%10===0||r.stats.pagesSaved===1)&&s.progress(`Page progress: processed ${c}, rendered ${r.stats.pagesRendered}, saved ${r.stats.pagesSaved}, discovered ${r.stats.pagesQueued}.`,{donePages:c,claimedPages:r.donePages.size,pagesRendered:r.stats.pagesRendered,pagesSaved:r.stats.pagesSaved,pagesQueued:r.stats.pagesQueued,pageQueue:r.pageQueue.length,phase:"save-pages"});}function Uo(e){let t=Pn(e);return t%5===0||t===1||t===e.stats.pagesQueued}function Lo(e,t){let n=Pn(e);t.progress(`Render progress: processed ${n}, rendered ${e.stats.pagesRendered}, saved ${e.stats.pagesSaved}, discovered ${e.stats.pagesQueued}.`,{donePages:n,claimedPages:e.donePages.size,pagesRendered:e.stats.pagesRendered,pagesSaved:e.stats.pagesSaved,pagesQueued:e.stats.pagesQueued,phase:"render-pages"});}async function jo(e){await e.addInitScript(()=>{Object.defineProperty(window,"__WPSUITE_STATIC_EXPORT__",{value:true,writable:false,configurable:true});let t=n=>{if(n==null||String(n)==="")return true;try{let r=new URL(String(n),window.location.href),s=new URL(window.location.href);return r.hash="",s.hash="",r.href===s.href}catch{return false}};try{let n=window.location.assign.bind(window.location),r=window.location.replace.bind(window.location),s=window.location.reload.bind(window.location);Object.defineProperty(window.location,"assign",{configurable:!0,value:i=>{if(t(i)){console.warn("[smartcloud-static-publisher] blocked same-page location.assign",i??"");return}return n(i)}}),Object.defineProperty(window.location,"replace",{configurable:!0,value:i=>{if(t(i)){console.warn("[smartcloud-static-publisher] blocked same-page location.replace",i??"");return}return r(i)}}),Object.defineProperty(window.location,"reload",{configurable:!0,value:()=>{console.warn("[smartcloud-static-publisher] blocked location.reload");}});}catch{}});}async function qo(e,t,n){let r=await e.newContext({viewport:t.viewport,userAgent:"WPSuiteStaticPublisher/0.8 Playwright SitemapOnly",ignoreHTTPSErrors:t.ignoreHttpsErrors,...n?{javaScriptEnabled:false}:{}});return n||await jo(r),r}async function _o(e,t,n,r,s,i,a,c){let o=await chromium.launch({headless:true}),l=wn(o);l.pid!==null&&n.debug(`Launched crawl worker browser PID ${l.pid}`,{browserPid:l.pid});try{for(;t.pageQueue.length>0;){o||(o=await chromium.launch({headless:!0}),l=wn(o),l.pid!==null&&n.debug(`Relaunched crawl worker browser PID ${l.pid}`,{browserPid:l.pid}));let d=o;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,p=!1,y=[],m=new Set;try{let h=Ce(u,n,"page","page-queue");if(!h)continue;let w=h.toString();if(u=w,t.queuedPages.delete(u),t.donePages.has(u))continue;t.donePages.add(u),i.enabled&&i.seenPages.add(u);let P=bn(e,u),x=Oo(e,h.pathname);if(!Re(h)||W(e,h)||_e(h)){if(W(e,h)){n.info(`Worker redirected non-page URL to asset queue: ${u}`,{url:u,source:"worker-guard"}),Q(e,t,u,n,"worker-guard");continue}n.reject("page",u,"guard rejected non-page URL before rendering","worker");continue}let j=i.strictTargeted?i.manifest.pages[u]:void 0;if(j?.lastSeenRunId===i.runId&&await je(j.outputPath)){i.seenPages.add(u);for(let v of j.discoveredAssets||[])Q(e,t,v,n,u);te(a,e,j.outputPath),Ie(a,j.outputPath),n.info(`Resumed completed content-sync page ${u}`,{url:u,source:"content-sync-checkpoint"});continue}let M=await Wi(e,s,t,i,u,n);if(i.enabled&&r!=="single-url"&&r!=="content-sync"){let v=i.manifest.pages[u];if(M.action==="reuse"&&v){for(let E of v.discoveredAssets)Q(e,t,E,n,u);for(let E of v.discoveredPages)at(e,t,E,n,u);v.lastSeenRunId=i.runId,v.sitemapLastmod=it(t.sitemapLastmodByPage[u])??v.sitemapLastmod,M.changeToken?.supported&&(v.changeToken=M.changeToken.token,v.tokenSource=M.changeToken.tokenSource??v.tokenSource),n.info(`Incremental reuse skipped unchanged page ${u}`,{url:u,mode:"incremental",reason:M.changeToken?.supported===!0?"change-token-match":"sitemap-lastmod-match"});continue}}g=await H(`create page context ${u}`,me(e),()=>qo(d,e,x)),f=await H(`create page ${u}`,me(e),()=>g.newPage()),y=await g.cookies();let _=!1,C=new Set;await f.route("**/*",async v=>{let E=v.request();try{let F=J(e,E.url(),e.sourceOrigin,n,"network-request");F&&W(e,F)&&(C.add(F.toString()),Q(e,t,F.toString(),n,u));}catch{}if(E.isNavigationRequest()&&E.frame()===f.mainFrame())try{let F=new URL(E.url()),z=new URL(w);if(F.hash="",z.hash="",F.href===z.href){if(_){n.warn(`Blocked same-page navigation/reload for ${u}`,{url:u,requestUrl:E.url()});try{await v.abort("aborted");}catch(ee){n.debug(`Ignored canceled route while blocking reload for ${u}`,{url:u,error:String(ee)});}return}_=!0;}}catch{}try{await v.continue();}catch(F){n.debug(`Ignored canceled network route for ${u}`,{url:u,requestUrl:E.url(),error:String(F)});}}),f.on("response",v=>{try{let F=J(e,v.url(),e.sourceOrigin,n,"network-response");F&&W(e,F)&&(C.add(F.toString()),Q(e,t,F.toString(),n,u));}catch{}let E=v.headerValues("set-cookie").then(F=>{for(let z of F)c.add(Tr(z,v.url()));}).catch(()=>{}).then(()=>{});m.add(E),E.finally(()=>m.delete(E));}),n.page(`Rendering ${u}`,{url:u});let $=null,R=null;try{if($=await f.goto(u,{waitUntil:"domcontentloaded",timeout:e.navigationTimeoutMs}),$&&$.ok())try{R=await H(`read response body ${u}`,me(e),()=>$.text());}catch{R=null;}}catch(v){n.warn(`Navigation issue for ${u}; saving current DOM if available`,{url:u,error:String(v)});}if(r==="content-sync"&&$){let v=Ce($.url(),n,"content-sync-final-response",u)?.toString();if(v&&v!==w){if(i.deleteOnMissingUrls.has(u)){await yn(e,i,a,u,i.deleteOnMissingUrls),n.info(`Removed stale content-sync archive route redirected to ${v}`,{url:u,finalResponseUrl:v,source:"content-sync-tombstone"});continue}throw new Error(`Required content-sync route redirected outside its planned URL: ${u} -> ${v}`)}}if(P){let v=$?.status()??null;if(v!==404){n.error(`Generated 404 request path returned unexpected status for ${u}`,{url:u,expectedStatus:404,status:v,requestPath:e.generated404RequestPath});continue}n.info(`Capturing rendered 404 page for ${u}`,{url:u,status:v,outputPath:he(e,u)});}else if($&&!$.ok()){if(r==="content-sync"&&($.status()===404||$.status()===410)&&i.deleteOnMissingUrls.has(u)){await yn(e,i,a,u,i.deleteOnMissingUrls),n.info(`Removed stale content-sync archive page ${u}`,{url:u,status:$.status(),source:"content-sync-tombstone"}),await f.close();continue}if(r==="content-sync")throw new Error(`Required content-sync route returned HTTP ${$.status()}: ${u}`);n.skip("page",u,$.status(),t.pageDiscoverySources.get(u)),await f.close();continue}x?(n.info(`Rendering without JS execution for ${u}`,{url:u,mode:"no-js"}),await H(`wait for rendered page ${u}`,me(e),()=>Do(e,f))):await H(`wait for rendered page ${u}`,me(e),()=>Mo(e,f)),t.stats.pagesRendered++;let U=await H(`extract rendered assets ${u}`,me(e),()=>Fo(e,f,w,n,!x));for(let v of U)Q(e,t,v,n,u);let b=[...new Set([...U,...C])],T=R??await H(`capture rendered html ${u}`,me(e),()=>f.content()),O=r!=="single-url"&&r!=="content-sync"&&!P?Io(e,u,T,n):[];if(r!=="single-url"&&r!=="content-sync"&&!P)for(let v of O)at(e,t,v,n,u);await Lr(e,u,T,t,n);let q=he(e,u);if(te(a,e,q),Ie(a,q),i.trackManifest){let v=$?.headers();i.manifest.pages[u]={url:u,outputPath:q,contentType:pn(v),changeToken:M.changeToken?.supported?M.changeToken.token:null,tokenSource:M.changeToken?.supported?M.changeToken.tokenSource??null:null,sitemapLastmod:it(t.sitemapLastmodByPage[u])??null,discoveredPages:O,discoveredAssets:b,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,rewriteComplete:!1},(i.enabled||i.strictTargeted)&&await ve(e,i);}}catch(h){if(p=h instanceof ut,i.strictTargeted)throw n.error(`Failed required content-sync page ${u}`,{url:u,error:String(h)}),h;if(p)n.warn(`Skipped partial DOM for timed-out page ${u}`,{url:u,error:String(h),recovery:"recycle-worker-browser"});else try{let w=f?await H(`capture partial html ${u}`,me(e),()=>f.content()):"";if(w&&w.trim()){await Lr(e,u,w,t,n);let P=he(e,u);if(te(a,e,P),Ie(a,P),i.trackManifest){let x=i.manifest.pages[u]??i.previousManifest.pages[u];i.manifest.pages[u]={url:u,outputPath:P,contentType:x?.contentType??null,changeToken:null,tokenSource:null,sitemapLastmod:it(t.sitemapLastmodByPage[u])??x?.sitemapLastmod??null,discoveredPages:x?.discoveredPages?[...x.discoveredPages]:[],discoveredAssets:x?.discoveredAssets?[...x.discoveredAssets]:[],lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId,rewriteComplete:!1},(i.enabled||i.strictTargeted)&&await ve(e,i);}n.warn(`Saved partial DOM for ${u}`,{url:u,error:String(h)});}}catch(w){w instanceof ut&&(p=!0),n.error(`Could not save partial DOM for ${u}`,{url:u,error:String(w)});}n.error(`Failed page ${u}`,{url:u,error:String(h)});}finally{if(!p&&f&&await H(`drain network routes ${u}`,st(e),()=>f.unrouteAll({behavior:"wait"})).catch(h=>{p=!0,n.warn(`Could not drain network routes for ${u}`,{url:u,browserPid:l.pid,error:String(h),recovery:"recycle-worker-browser"});}),p&&(o=null,await dn(d,n,`page operation timeout for ${u}`),await d.close().catch(()=>{})),m.size>0&&await Promise.allSettled([...m]),!p&&g)try{let h=await g.cookies();c.addAll(kr(y,h));}catch{}t.stats.pagesCompleted++,Uo(t)&&Lo(t,n),!p&&f&&await H(`close page ${u}`,st(e),()=>f.close()).catch(h=>{p=!0,n.warn(`Timed out while closing page ${u}`,{url:u,browserPid:l.pid,error:String(h),recovery:"recycle-worker-browser"});}),!p&&g&&await H(`close page context ${u}`,st(e),()=>g.close()).catch(h=>{p=!0,n.warn(`Timed out while closing page context for ${u}`,{url:u,browserPid:l.pid,error:String(h),recovery:"recycle-worker-browser"});}),p&&o===d&&(o=null,await dn(d,n,`page cleanup timeout for ${u}`),await d.close().catch(()=>{}));}}}finally{if(o){let d=o;await H("close worker browser",st(e),()=>d.close()).catch(u=>(n.warn("Timed out while closing crawl worker browser",{browserPid:l.pid,error:String(u)}),dn(d,n,"browser.close timeout")));}}}async function No(e){try{let t=await A.readFile(e),r=(e.endsWith(".gz")?gunzipSync(t):t).toString("utf8").trim();if(!r)return [];try{let s=JSON.parse(r);if(Array.isArray(s))return s;if(s&&typeof s=="object")return [s]}catch{return r.split(/\r?\n/).map(s=>s.trim()).filter(Boolean).map(s=>{try{let i=JSON.parse(s);return i&&typeof i=="object"?i:null}catch{return null}}).filter(s=>s!==null)}return []}catch{return []}}function jr(e){let t=String(e||"").toLowerCase();return t.includes("timeout")||t.includes("timed out")||t.includes("navigation timeout")}function Bo(e){let t=String(e?.job?.command||"").trim(),n=String(e?.job?.crawlMode||"full").trim();return t!=="publish"&&t!=="crawl"?false:n!=="incremental"}function Wo(e){let t=[e?.archivedAt,e?.job?.endedAt,e?.job?.startedAt];for(let n of t){let r=Date.parse(String(n||""));if(Number.isFinite(r))return r}return 0}async function ns(e){try{let t=await A.readFile(e,"utf8"),n=JSON.parse(t);return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}function qr(e){let t=String(e.originalFileName||"").toLowerCase();return t.endsWith("errors.jsonl")?0:t.endsWith("errors.json")?1:2}function Ho(e,t){let n=Array.isArray(t?.artifacts)?t.artifacts.filter(r=>String(r?.role||"").trim()==="errors"&&String(r?.storedFileName||"").trim()!=="").sort((r,s)=>qr(r)-qr(s)).map(r=>S.join(e,String(r.storedFileName))):[];return [...new Set([...n,S.join(e,"errors.jsonl"),S.join(e,"errors.json"),S.join(e,"errors.jsonl.gz"),S.join(e,"errors.json.gz")])]}async function _r(e){let t=await ns(S.join(e,"job.json"));for(let n of Ho(e,t)){let r=await No(n);if(r.length>0)return r}return []}async function zo(e){let t=S.join(e.logDir,"archive"),n;try{n=await A.readdir(t);}catch{return ""}let r="",s=0;for(let i of n){let a=S.join(t,i);if(!(await A.stat(a).catch(()=>null))?.isDirectory())continue;let o=await ns(S.join(a,"job.json"));if(!Bo(o))continue;let l=Wo(o);l>=s&&(s=l,r=a);}return r}async function Qo(e){let t=await zo(e),n=t!==""?await _r(t):await _r(e.logDir),r=new Set;for(let s of n)if(jr(s.error)||jr(s.message)){let i=s.url;typeof i=="string"&&i&&r.add(i);}return [...r]}async function Jo(e){let t=[];for(let n of e)if(n.startsWith("@")){let r=n.slice(1),s=await A.readFile(r,"utf8");t.push(...s.split(/\r?\n/).map(i=>i.trim()).filter(i=>i&&!i.startsWith("#")));}else t.push(n);return t}async function Vo(e){if(!e)throw new Error("Content-sync crawl requires an immutable impact plan.");let t=JSON.parse(await A.readFile(e,"utf8"));return Ve(t),t}function Ko(e,t){let n;try{n=new URL(e);}catch{return false}return t.archiveFamilies.some(r=>{let s=new URL(r.url);if(n.origin!==s.origin)return false;if(n.toString()===s.toString())return true;if(n.searchParams.has("paged")&&n.pathname===s.pathname)return /^\d+$/.test(n.searchParams.get("paged")||"");let i=s.pathname.replace(/\/+$/,""),a=n.pathname.slice(i.length).replace(/^\/+/,""),c=String(r.paginationBase||"page").replace(/^\/+|\/+$/g,"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return n.pathname.startsWith(`${i}/`)&&new RegExp(`^${c}/\\d+/?$`).test(a)})}function rt(e,t,n){let r=n==="page"?he(e,t):Dt(e,t).originalFilePath;return pe(e.outputDir,r)}async function yn(e,t,n,r,s){let i=t.manifest.pages[r];if(!i)return;let a=pe(e.outputDir,i.outputPath);if(!a)throw new Error(`Manifest-owned page path escaped output root: ${r}`);let c=S.resolve(i.outputPath);Object.entries(t.manifest.pages).some(([l,d])=>l!==r&&!s.has(l)&&S.resolve(d.outputPath)===c)||(await A.rm(i.outputPath,{force:true}),n.deletedFiles.add(a)),delete t.manifest.pages[r];}async function Go(e,t,n,r,s){let i=t.manifest.assets[r];if(!i)return;let a=pe(e.outputDir,i.outputPath);if(!a)throw new Error(`Manifest-owned resource path escaped output root: ${r}`);let c=S.resolve(i.outputPath);Object.entries(t.manifest.assets).some(([l,d])=>l!==r&&!s.has(l)&&S.resolve(d.outputPath)===c)||(await A.rm(i.outputPath,{force:true}),n.deletedFiles.add(a)),delete t.manifest.assets[r];}function Zo(e,t){let n=new Set,r=[...t];for(;r.length>0;){let s=r.shift();if(n.has(s))continue;n.add(s);let i=e.assets[s];for(let a of i?.discoveredAssets??[])try{Ne(new URL(a))&&r.push(a);}catch{}}return n}async function Yo(e,t,n,r,s){let i=Zo(n.previousManifest,s);for(let a of i){if(t.successfulSitemaps.has(a))continue;let c=n.previousManifest.assets[a];if(!c)continue;let o=pe(e.outputDir,c.outputPath);if(!o)throw new Error(`Manifest-owned sitemap path escaped output root: ${a}`);await A.rm(c.outputPath,{force:true}),r.deletedFiles.add(o),delete n.manifest.assets[a];}await ve(e,n);}async function Xo(e){try{let t=await A.readFile(S.join(e.outputDir,"asset-map.json"),"utf8");return JSON.parse(t)}catch{return {}}}async function ea(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 A.mkdir(e,{recursive:true}),await Promise.all(t.map(async n=>{try{await A.unlink(S.join(e,n));}catch(r){if(r.code!=="ENOENT")throw r}}));}function Nr(e,t,n,r,s){let i=J(e,n,e.sourceOrigin,r,"manual-url");i&&(Ne(i)?Et(e,t,i.toString(),r,s):W(e,i)?Q(e,t,i.toString(),r,s):Re(i)?at(e,t,i.toString(),r,s):r.reject("manual-url",i.toString(),"not page/sitemap/asset-like",s));}async function rs(e=process.argv.slice(2)){let t=[],n=await oe(void 0,{onRemotePublisherConfigDiagnostic:b=>{t.push(b);}}),r=Ge(n.sitemapPaths),s=t.at(-1)??null,i=$i(e),a=i.mode==="content-sync"?await Vo(i.contentSyncPlanPath):null;if(i.resumeRewrite&&i.mode!=="full")throw new Error("--resume-rewrite is only supported for full crawl/publish jobs.");let c=[];i.mode==="retry-timeouts"&&(c=await Qo(n)),i.mode==="single-url"&&(c=await Jo(i.urls)),a&&(c=[...a.directRenderUrls,...a.archiveFamilyUrls,...a.resourceRenderUrls]);let o=i.crawlMode==="incremental"&&i.mode==="full",l=o&&typeof n.subscriptionType=="string"&&n.subscriptionType.trim()!=="";if(a&&n.subscriptionType!=="PROFESSIONAL"&&n.subscriptionType!=="AGENCY")throw new Error("Content-sync requires an active Professional or Agency subscription.");let d=(i.mode==="full"||i.mode==="single-url"||i.mode==="content-sync")&&!i.resumeRewrite,u=i.mode!=="full"||i.resumeRewrite||l,g=u?await Xo(n):{},f=l||i.mode==="single-url"||i.mode==="content-sync"?await Li(n):zr(),p=new Set(c),y=new Set;if(a){for(let b of a.archiveFamilies)if(b.foundPosts===0)for(let T of b.pageUrls)y.add(T);for(let b of Object.keys(f.pages))Ko(b,a)&&!p.has(b)&&(c.push(b),y.add(b));}let m={enabled:l,trackManifest:d,manifest:fn(f),previousManifest:fn(f),runId:a?.jobId??`${Date.now()}`,seenPages:new Set,changeTokenCache:new Map,manifestSaveChain:Promise.resolve(),strictTargeted:!!a,requiredUrls:p,deleteOnMissingUrls:y};await ea(n.logDir);let h=new Ct(n.logDir,n.logLevel);if(s){let b={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.",b):h.warn("Remote WP Suite publisher configuration is unavailable or has no active subscription type.",b);}if(o&&!l){let b="Incremental crawl requires an active remote publisher subscription; refusing to fall back to a destructive full crawl.";throw h.error(b,{requestedMode:i.crawlMode,subscriptionType:n.subscriptionType??null,source:"incremental-subscription-guard"}),await h.flush(),new Error(b)}let w={pageQueue:[],queuedPages:new Set,donePages: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}},P=Ui(),x=new xt,j=Ei();if(j&&!i.resumeRewrite&&await It(j,x.artifact()),await De(n),await sr(n,{startedAt:new Date().toISOString(),outputDir:S.resolve(n.outputDir)}),u||await A.rm(n.outputDir,{recursive:true,force:true}),await A.mkdir(n.outputDir,{recursive:true}),a){let b=new Set([...a.deleteUrls,...m.deleteOnMissingUrls]);for(let O of a.deleteUrls)await yn(n,m,P,O,b);let T=new Set(a.resourceDeleteUrls);for(let O of a.resourceDeleteUrls)await Go(n,m,P,O,T);}if(i.resumeRewrite)h.info("Resuming final rewrite from existing output.",{phase:"rewrite-text",mode:i.mode,crawlMode:i.crawlMode});else {let b=await request.newContext({ignoreHTTPSErrors:n.ignoreHttpsErrors});try{if(h.mark("discovery"),i.mode==="full"?(r.forEach(O=>Et(n,w,O,h)),await Ur(n,b,w,h,P,m),n.seedPaths.forEach(O=>Nr(n,w,O,h,"seed-path")),n.generated404RequestPath&&at(n,w,n.generated404RequestPath,h,"generated-404-request-path")):(c.forEach(O=>Nr(n,w,O,h,"cli")),a?.sitemapUrls.forEach(O=>Et(n,w,O,h,"content-sync-impact")),await Ur(n,b,w,h,P,m,i.mode==="content-sync",a?.sitemapUrls??[]),a&&await Yo(n,w,m,P,a.sitemapUrls)),h.endMark("discovery",{pages:w.pageQueue.length,assets:w.assetQueue.length,sitemaps:w.sitemapQueue.length}),h.summary(`Queued ${w.pageQueue.length} pages, ${w.assetQueue.length} assets, ${w.sitemapQueue.length} sitemaps.`,{mode:i.mode,crawlMode:i.crawlMode,queuedPages:w.pageQueue.length,queuedAssets:w.assetQueue.length,queuedSitemaps:w.sitemapQueue.length}),i.mode==="retry-timeouts"&&w.pageQueue.length===0&&w.assetQueue.length===0&&w.sitemapQueue.length===0){h.summary("No timed-out URLs were queued. Skipping retry crawl.",{mode:i.mode,crawlMode:i.crawlMode,queuedPages:0,queuedAssets:0,queuedSitemaps:0}),await h.flush(),j&&await It(j,x.artifact());return}h.mark("render-pages");let T=Array.from({length:Math.max(1,n.concurrency)},()=>_o(n,w,h,i.mode,b,m,P,x));if(await Promise.all(T),j&&await It(j,x.artifact()),h.endMark("render-pages",{pages:w.stats.pagesCompleted}),h.mark("download-assets"),h.progress("Asset download phase started.",{phase:"download-assets",doneAssets:w.doneAssets.size,assetsQueued:w.stats.assetsQueued,assetQueue:w.assetQueue.length}),await _i(n,b,m,[...w.assetQueue],h),await To(n,b,w,h,m,P),h.endMark("download-assets",{assets:w.doneAssets.size}),m.enabled&&n.maxPages===0&&(await zi(n,w,m,h,P),i.mode==="full"&&await Qi(n,m,h,P)),i.mode==="full"){let O=await xo(n,w,h);for(let q of O)te(P,n,q);}}finally{await H("dispose crawl request context",st(n),()=>b.dispose()).catch(T=>{h.warn("Timed out while disposing crawl request context",{error:String(T)});});}}m.trackManifest&&await ve(n,m),await A.writeFile(S.join(n.outputDir,"asset-map.json"),JSON.stringify(w.assetMap,null,2),"utf8"),JSON.stringify(g,null,2)!==JSON.stringify(w.assetMap,null,2)&&te(P,n,S.join(n.outputDir,"asset-map.json"));let M=i.mode==="single-url"||i.mode==="content-sync"?to(n,w):m.enabled&&!i.resumeRewrite?Ji(n,m,P,g,w.assetMap):void 0;h.mark("rewrite-text");let _=i.mode==="single-url"||i.mode==="content-sync"?`Rewriting text files touched by URL crawl: 0/${M?.length??0}`:"Rewriting text files...";h.progress(_,{phase:"rewrite-text",index:0,totalFiles:M?.length,changedTextFiles:0}),await Or(_);let C=Date.now(),$=await bt(n,w.assetMap,{files:M,previousAssetMap:g,onStart:({totalFiles:b,workerCount:T})=>{h.info(`Rewrite phase scanning ${b} text files.`,{phase:"rewrite-text",totalFiles:b,workerCount:T});},onProgress:async({index:b,totalFiles:T,changedTextFiles:O,file:q,changed:v})=>{v&&te(P,n,S.join(n.outputDir,q)),h.checkpoint(`Rewriting text file ${b}/${T}`,{phase:"rewrite-text",index:b,totalFiles:T,changedTextFiles:O,file:q}),h.debug(`${v?"Rewrote":"Checked unchanged"} text file ${b}/${T}: ${q}`,{phase:"rewrite-text",index:b,totalFiles:T,changedTextFiles:O,file:q,changed:v});let E=Date.now();if(!(b===1||b===T||b%50===0||E-C>=5e3))return;C=E;let z=`Rewriting text files: ${b}/${T}`;h.progress(z,{phase:"rewrite-text",index:b,totalFiles:T,changedTextFiles:O,file:q}),await Or(z);}});m.trackManifest&&(Vi(m,M),await ve(n,m)),h.endMark("rewrite-text",{changedTextFiles:$});let R=a?[...P.deletedFiles].sort():m.enabled&&!i.resumeRewrite?await Gi(n,w,m,P,h):[],U=[...new Set((M||[]).map(b=>pe(n.outputDir,S.isAbsolute(b)?b:S.join(n.outputDir,b))).filter(b=>b!==null))].sort();if(a){let b=[...P.changedFiles].sort(),T=new Set(b),O=new Set(a.directRenderUrls.map(D=>rt(n,D,"page")).filter(D=>!!D&&T.has(D))),q=new Set(a.archiveFamilyUrls.map(D=>rt(n,D,"page")).filter(D=>!!D&&T.has(D))),v=new Set(a.resourceRenderUrls.map(D=>rt(n,D,"asset")).filter(D=>!!D&&T.has(D))),E=new Set([...w.sitemapLeafUrls].map(D=>rt(n,D,"asset")).filter(D=>!!D&&T.has(D))),F=new Set([...w.sitemapIndexUrls].map(D=>rt(n,D,"asset")).filter(D=>!!D&&T.has(D))),z=new Set([...O,...q,...v,...E,...F]),ee=b.filter(D=>!z.has(D)),Te=[...new Set([...a.directRenderUrls,...a.archiveFamilyUrls,...w.resolvedSitemapRoots,...w.sitemapLeafUrls,...w.sitemapIndexUrls,...a.deleteUrls,...a.resourceRenderUrls,...a.resourceDeleteUrls].map(D=>{let dt=new URL(D);return `${dt.pathname}${dt.search}`}))].sort();await rn(n,{schemaVersion:2,generatedAt:new Date().toISOString(),outputDir:S.resolve(n.outputDir),runMode:"content-sync",crawlMode:"incremental",fullSyncRequired:false,changedFiles:b,deletedFiles:R,rewriteTargets:U,consumerId:a.consumerId,fromSequence:a.fromSequence,toSequence:a.toSequence,impactHash:a.impactHash,resolvedSitemapUrls:[...w.resolvedSitemapRoots],uploadGroups:{assets:ee,content:[...O].sort(),listings:[...q].sort(),resources:[...v].sort(),sitemapLeaves:[...E].sort(),sitemapIndexes:[...F].reverse()},invalidationPaths:Te});}else await rn(n,{schemaVersion:1,generatedAt:new Date().toISOString(),outputDir:S.resolve(n.outputDir),runMode:i.mode,crawlMode:i.crawlMode,fullSyncRequired:!(m.enabled&&!i.resumeRewrite),changedFiles:m.enabled&&!i.resumeRewrite?[...P.changedFiles].sort():[],deletedFiles:m.enabled&&!i.resumeRewrite?R:[],rewriteTargets:m.enabled&&!i.resumeRewrite?U:[]});await or(n),h.summary(i.resumeRewrite?`Done. Resumed final rewrite over existing output and changed ${$} text files.`:`Done. Rendered ${w.stats.pagesRendered} pages, processed ${w.doneSitemaps.size} sitemaps and ${w.doneAssets.size} assets.`,{mode:i.mode,crawlMode:i.crawlMode,resumeRewrite:i.resumeRewrite,...w.stats,pagesRendered:w.stats.pagesRendered,donePages:w.stats.pagesCompleted,claimedPages:w.donePages.size,doneSitemaps:w.doneSitemaps.size,doneAssets:w.doneAssets.size,changedTextFiles:$}),await h.flush();}function ta(e){let t=e/6e4;if(Number.isInteger(t)&&t>=1)return `${t} minute${t===1?"":"s"}`;let n=Math.ceil(e/1e3);return `${n} second${n===1?"":"s"}`}async function ne(e,t,n){let r=new AbortController,s=globalThis.setTimeout(()=>{r.abort(new Error(`${e} timed out after ${ta(t)}.`));},t);try{return await n({abortController:r,httpOptions:{abortSignal:r.signal,requestTimeout:t}})}finally{globalThis.clearTimeout(s);}}function na(e){return typeof e.subscriptionType=="string"&&e.subscriptionType.trim()!==""}function Ot(e){let t="";for(let r=0;r<e.length;r++){let s=e[r];if(s==="--profile"){let i=(e[r+1]||"").trim();if(!i)throw new Error("Missing value for --profile.");t=i,r+=1;}else if(s.startsWith("--profile=")){let i=s.slice(10).trim();if(!i)throw new Error("Missing value for --profile.");t=i;}}let n=String(process.env.PUBLISHER_DEPLOY_PROFILE||process.env.PUBLISHER_DEPLOYMENT_PROFILE||"").trim();return t||n||null}function ra(e,t){return {...e,...t??{}}}function sa(e,t){return {...e,...t??{},invalidationPaths:[...(t?.invalidationPaths??e.invalidationPaths)||[]]}}function Be(e,t){let n=String(t??e.deploymentTargetOverride??"").trim();if(!na(e)){if(n)throw new Error(`Deployment target "${n}" requires an active WPSuite subscription and remote publisher config.`);return {name:null,profile:null,config:e}}let r=String(n||e.defaultDeploymentProfile||"").trim();if(!r)return {name:null,profile:null,config:e};let s=e.deploymentProfiles?.[r];if(!s)throw new Error(`Unknown deployment profile "${r}". Check the linked WPSuite publisher configuration.`);return {name:r,profile:s,config:{...e,targetOrigin:s.targetOrigin??e.targetOrigin,s3:ra(e.s3,s.s3),cloudFront:sa(e.cloudFront,s.cloudFront)}}}var as="wpsuite-sha256",cs="wpsuite-normalized-sha256",ga=/(?:^|[-_:.])(id|uid|nonce|token|hash|instance)(?:$|[-_:.])/i,An=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,fa=["SIGINT","SIGTERM"],Lt=new Set,Ft=new Map,ss=null;function ma(e){Lt.add(e);let t=false;return ()=>{t||(t=true,Lt.delete(e));}}async function ha(){let e=[...Lt];e.length!==0&&await Promise.allSettled(e.map(async t=>{Lt.delete(t),await A.rm(t,{recursive:true,force:true});}));}function wa(){if(!(Ft.size>0))for(let e of fa){let t=()=>{ss||(ss=ha().finally(()=>{for(let[n,r]of Ft)process.off(n,r);Ft.clear(),process.exit(1);}));};Ft.set(e,t),process.on(e,t);}}wa();function ya(e,t){let n=String(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH||"").trim();if(n)return S.resolve(n);let r=t.trim();return r?S.join(S.resolve(r),"crawl-manifest.json"):S.join(S.resolve(e),".crawl-manifest.json")}function us(e){return S.normalize(e).split(S.sep).join("/")}function is(e,t){let n=S.relative(S.resolve(e),S.resolve(t));return !n||n.startsWith("..")||S.isAbsolute(n)?null:us(n)}async function Sa(e,t,n){let r=ya(e.outputDir,t),s;try{s=await A.readFile(r,"utf8");}catch(d){return d.code==="ENOENT"?(n.warn("Deploy rewrite guard disabled because the crawl manifest is missing.",{manifestPath:r,source:"deploy-guard"}),null):(n.warn("Deploy rewrite guard disabled because the crawl manifest could not be read.",{manifestPath:r,error:d instanceof Error?d.message:String(d),source:"deploy-guard"}),null)}let i;try{i=JSON.parse(s);}catch(d){return n.warn("Deploy rewrite guard disabled because the crawl manifest is invalid JSON.",{manifestPath:r,error:d instanceof Error?d.message:String(d),source:"deploy-guard"}),null}let a=new Map,c=new Map,o=0,l=0;for(let[d,u]of Object.entries(i.pages||{})){let g=String(u?.outputPath||"").trim(),f=g?is(e.outputDir,g):null;if(f){let p=typeof u?.contentType=="string"&&u.contentType?u.contentType:null;p&&c.set(f,p);}!g||u?.rewriteComplete===true||f&&(o++,a.has(f)||a.set(f,{kind:"page",sourceUrl:d,outputPath:S.resolve(g),relativePath:f}));}for(let[d,u]of Object.entries(i.assets||{})){let g=String(u?.outputPath||"").trim(),f=u?.isText===true,p=g?is(e.outputDir,g):null;if(p){let y=typeof u?.contentType=="string"&&u.contentType?u.contentType:null;y&&c.set(p,y);}!g||!f||u?.rewriteComplete===true||p&&(l++,a.has(p)||a.set(p,{kind:"asset",sourceUrl:d,outputPath:S.resolve(g),relativePath:p}));}return {manifestPath:r,byRelativePath:a,contentTypeByRelativePath:c,pendingPages:o,pendingTextAssets:l}}function ba(e){return e&&(An.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 Cn(e){return e.split(/([_:.\-/=?&#]+)/g).map((t,n)=>n%2===1?t:ba(t)).join("")}function Pa(e){return e.split(/([_:.\-/=?&#]+)/g).map((t,n)=>n%2===1?t:An.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 jt(e,t){return Array.isArray(e)?e.map(n=>jt(n,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,jt(r,n)])):typeof e!="string"?e:t&&ga.test(t)?Pa(e):An.test(e)?"__uuid__":/^[0-9a-f]{6,}$/i.test(e)||/^[0-9]{8,}$/.test(e)?Cn(e):e}function va(e){return e.replace(/((?:https?:\/\/[^"'\s>]+|\/)(?:wp-content|wp-includes)\/[^"'\s>?]+)\?ver=[A-Za-z0-9._-]+(?=$|[#"'])/gi,"$1")}function Ca(e,t){let n=t.trim();if((n.startsWith("{")||n.startsWith("[")||n.startsWith('"'))&&e.startsWith("data-"))try{let s=JSON.parse(n);return JSON.stringify(jt(s))}catch{}if(e.startsWith("data-")&&/^[A-Za-z0-9+/=]+$/.test(n))try{let s=Buffer.from(n,"base64").toString("utf8"),i=JSON.parse(s),a=JSON.stringify(jt(i));return Buffer.from(a,"utf8").toString("base64")}catch{}return t}function Ra(e,t){let n=e.toLowerCase();return n==="class"?t.split(/(\s+)/).map((r,s)=>s%2===1?r:Cn(r)).join(""):n==="id"||n==="for"||n==="aria-controls"||n==="aria-labelledby"||n==="aria-describedby"||n==="aria-owns"||n==="aria-activedescendant"||n==="name"?Cn(t):n==="href"||n==="src"?va(t):Ca(n,t)}function xa(e){return e.replace(/<([a-z][^\s/>]*)([^<>]*?)>/gi,(t,n,r)=>{if(n.startsWith("/"))return t;let s=r.replace(/\s([:@a-zA-Z_][-:.a-zA-Z0-9_]*?)=(['"])([\s\S]*?)\2/g,(i,a,c,o)=>{let l=Ra(a,o);return ` ${a}=${c}${l}${c}`});return `<${n}${s}>`})}function vn(e){let t=S.extname(e).toLowerCase();return [".html",".htm",".xml",".xsl",".txt"].includes(t)||["robots.txt","sitemap.xml"].includes(S.basename(e))}function Ut(e,t){return [e.replace(/^\/+|\/+$/g,""),t.replace(/^\/+/,"")].filter(Boolean).join("/")}async function Ia(e,t,n,r){let s=new Map,i,a=0;do{a++;let c=await ne(`S3 list objects page ${a} for s3://${t}/${n||""}`,3e5,({httpOptions:o})=>e.send(new ListObjectsV2Command({Bucket:t,Prefix:n||void 0,ContinuationToken:i}),o));for(let o of c.Contents||[]){if(!o.Key)continue;let l=(o.ETag||"").replace(/^"|"$/g,"").toLowerCase(),d=Number(o.Size??0);s.set(o.Key,{etag:l,size:d});}i=c.NextContinuationToken,r.debug(`Listed S3 keys page ${a}: ${s.size} keys so far`);}while(i);return s}async function Aa(e,t,n,r){if(r.has(n))return r.get(n)??null;try{let s=await ne(`S3 head object ${n}`,3e5,({httpOptions:a})=>e.send(new HeadObjectCommand({Bucket:t,Key:n}),a)),i={etag:(s.ETag||"").replace(/^"|"$/g,"").toLowerCase(),size:Number(s.ContentLength??0)};return r.set(n,i),i}catch{return r.set(n,null),null}}async function Ta(e,t,n,r){let s=[...new Set(Array.from(n).filter(Boolean))];if(s.length===0)return r.info("No explicitly tombstoned S3 objects to delete."),[];r.info(`Deleting ${s.length} explicitly tombstoned S3 object(s)\u2026`);for(let i=0;i<s.length;i+=1e3){let a=s.slice(i,i+1e3);if(a.length===0)continue;let c=await ne(`S3 delete objects batch ${Math.floor(i/1e3)+1}`,3e5,({httpOptions:o})=>e.send(new DeleteObjectsCommand({Bucket:t,Delete:{Objects:a.map(l=>({Key:l}))}}),o));if(c.Errors&&c.Errors.length>0){let o=c.Errors.map(l=>`${l.Key||"(unknown)"}: ${l.Code||"DeleteFailed"}`);throw new Error(`S3 reported ${o.length} object deletion error(s): ${o.join(", ")}`)}r.info(`Deleted batch of ${a.length} object(s).`);for(let o of a)r.debug(` deleted: ${o}`);}return s}function ka(e){return createHash("md5").update(e).digest("hex")}function os(e){return createHash("sha256").update(e).digest("hex")}function Rn(e){return createHash("sha256").update(xa(e.toString("utf8"))).digest("hex")}async function $a(e,t,n,r){if(r.has(n))return r.get(n)??null;try{let a=((await ne(`S3 head object metadata ${n}`,3e5,({httpOptions:c})=>e.send(new HeadObjectCommand({Bucket:t,Key:n}),c))).Metadata?.[as]||"").trim().toLowerCase()||null;return r.set(n,a),a}catch{return r.set(n,null),null}}async function Ea(e,t,n,r,s){if(r.has(n))return r.get(n)??null;try{let a=((await ne(`S3 head object normalized metadata ${n}`,3e5,({httpOptions:c})=>e.send(new HeadObjectCommand({Bucket:t,Key:n}),c))).Metadata?.[cs]||"").trim().toLowerCase();if(a)return r.set(n,a),a}catch{return r.set(n,null),null}if(s.has(n)){let i=s.get(n)??null;return r.set(n,i),i}try{let a=await(await ne(`S3 get object ${n}`,3e5,({httpOptions:o})=>e.send(new GetObjectCommand({Bucket:t,Key:n}),o))).Body?.transformToByteArray(),c=a?Rn(Buffer.from(a)):null;return s.set(n,c),r.set(n,c),c}catch{return s.set(n,null),r.set(n,null),null}}function Ma(e){return e.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"profile"}function Da(e,t){let n=e,r=Object.entries(t).sort((s,i)=>i[0].length-s[0].length);for(let[s,i]of r)s&&(n=n.split(s).join(i));return n}async function Oa(e,t,n,r){let s=S.join(e,"asset-map.json"),i;try{i=await A.readFile(s,"utf8");}catch(o){if(o.code==="ENOENT")return;throw o}let a=JSON.parse(i);if(!a||typeof a!="object")return;let c=Object.fromEntries(Object.entries(a).map(([o,l])=>{let d=String(l??"");return t.urlRewriteMode==="absolute"&&t.targetOrigin&&n.targetOrigin&&t.targetOrigin!==n.targetOrigin&&(d=d.split(t.targetOrigin).join(n.targetOrigin)),d=Da(d,r),[o,d]}));await A.writeFile(s,JSON.stringify(c,null,2),"utf8");}async function Fa(e,t,n,r,s,i){let a=e.targetOrigin!==t.targetOrigin,c=Object.keys(r).length>0;if(!n||!a&&!c)return {outputDir:e.outputDir,cleanup:async()=>{}};if(a&&e.urlRewriteMode!=="absolute")throw new Error(`Deployment profile "${n}" changes targetOrigin, but the base crawl output must use urlRewriteMode "absolute" for multi-target redeploys.`);let o=S.join(S.dirname(e.outputDir),`.deploy-profile-${Ma(n)}-${Date.now()}`),l=ma(o);s.info(`Preparing deployment profile "${n}" from existing crawl output to ${o}...`);try{if(await A.rm(o,{recursive:!0,force:!0}),i){await A.mkdir(o,{recursive:!0});for(let f of i){let p=S.join(e.outputDir,f),y=S.join(o,f);await A.mkdir(S.dirname(y),{recursive:!0}),await A.copyFile(p,y);}}else await A.cp(e.outputDir,o,{recursive:!0});let d={...e,sourceOrigin:e.targetOrigin,targetOrigin:t.targetOrigin,extraReplacements:r,outputDir:o},u=1;s.info(`Rewriting text files for deployment profile "${n}"...`);let g=await bt(d,{},{files:i,onStart:({totalFiles:f,workerCount:p})=>{u=p,s.info(`Rewriting ${f} text file(s) for deployment profile "${n}" with ${p} worker(s).`);},onProgress:({index:f,totalFiles:p,changedTextFiles:y,file:m,changed:h})=>{let P=`Rewriting [${f}/${p}] ${m} (${h?"rewrote":"checked"}; ${y} changed so far)`;p<=200||f<=5||f%10===0||f===p?(s.progress(P,{file:m,index:f,totalFiles:p,changed:h,changedTextFiles:y,workerCount:u}),s.info(P)):s.debug(P);}});return await Oa(o,e,t,r),s.info(`Prepared deployment profile "${n}" in ${o} (${g} rewritten text file(s)).`),{outputDir:o,cleanup:async()=>{l(),await A.rm(o,{recursive:!0,force:!0});}}}catch(d){throw s.error(`Failed to prepare deployment profile "${n}" temporary output.`,{tempDir:o,outputDir:e.outputDir,error:d instanceof Error?d.message:String(d),...d instanceof Error&&d.stack?{stack:d.stack}:{}}),await A.rm(o,{recursive:true,force:true}).catch(()=>{}),l(),await s.flush().catch(()=>{}),d}}async function ls(e=process.argv.slice(2)){let t=await oe(),n=Ot(e),r=Be(t,n),s=S.resolve(r.config.logDir||"logs"),i=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",a=i?S.join(S.resolve(i),"deploy-diff.json"):"",c=new Fe(s,"deploy.log.jsonl",r.config.logLevel??"info"),o=r.profile?.extraReplacements??{},l=async()=>{};try{let d=await Me(t);if(e.includes("--content-sync")&&d?.schemaVersion!==2)throw new Error("Content-sync deployment requires a valid schema-2 targeted deploy plan.");let g=await ir(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=await Fa(t,r.config,r.name,o,c,d?.schemaVersion===2?d.changedFiles:void 0);l=f.cleanup;let p={...r.config,outputDir:f.outputDir},y=p.s3SyncMode??"sdk-upload-delete";if(d?.schemaVersion===2&&d.deletedFiles.length>0&&y!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let m=d?.schemaVersion!==2&&f.outputDir!==t.outputDir&&(t.targetOrigin!==r.config.targetOrigin||Object.keys(o).length>0),h=!!d&&!d.fullSyncRequired&&!m;if(d?.schemaVersion===2&&!h)throw new Error("Content-sync deployment cannot widen into a full-output deployment.");r.name&&c.info(`Using deployment profile: ${r.name}`),c.info(`Starting deploy \u2014 s3://${p.s3.bucket}/${p.s3.prefix||""} (region: ${p.s3.region})`),c.info(`S3 sync mode: ${y}`),d&&d.fullSyncRequired?c.info("Deploy plan requests a full sync; scanning the whole output tree."):d&&m?c.info("Ignoring incremental deploy plan because deployment-profile rewrites require a full sync."):h&&c.info(`Using incremental deploy plan: ${d.changedFiles.length} changed file(s), ${d.deletedFiles.length} deleted file(s).`),c.mark("deploy");let w=new S3Client({region:p.s3.region}),P=f.outputDir===t.outputDir?await Sa(t,i,c):null,x=d?.schemaVersion===2?[...d.uploadGroups.assets,...d.uploadGroups.content,...d.uploadGroups.listings,...d.uploadGroups.resources,...d.uploadGroups.sitemapLeaves,...d.uploadGroups.sitemapIndexes]:d?.changedFiles??[];if(d?.schemaVersion===2){let k=[...new Set(x)],K=[...new Set(d.changedFiles)];if(k.length!==K.length||K.some(I=>!k.includes(I)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let j=h?(await Promise.all(x.map(async k=>{try{return (await A.stat(S.join(p.outputDir,k))).isFile()?k:null}catch{if(d?.schemaVersion===2)throw new Error(`Content-sync planned upload is missing: ${k}`);return null}}))).filter(k=>k!==null):await Zs(["**/*"],{cwd:p.outputDir,onlyFiles:!0,dot:!0}),M=[],_=[],C=j.filter(k=>{let K=P?.byRelativePath.get(us(k));if(!K)return !0;let I=Ut(p.s3.prefix,k);return M.push(k),_.push(I),c.reject(K.kind,K.sourceUrl||k,"rewrite not completed; deploy upload blocked","deploy-guard",{file:k,key:I,outputPath:K.outputPath,manifestPath:P?.manifestPath}),!1}),$=new Set((h?C:j).map(k=>Ut(p.s3.prefix,k)));P&&(P.pendingPages>0||P.pendingTextAssets>0)&&c.info(`Deploy rewrite guard loaded ${P.pendingPages} pending page(s) and ${P.pendingTextAssets} pending text asset(s) from crawl manifest.`,{manifestPath:P.manifestPath,pendingPages:P.pendingPages,pendingTextAssets:P.pendingTextAssets,source:"deploy-guard"}),M.length>0&&c.warn(`Deploy rewrite guard blocked ${M.length} file(s) from upload because final crawl rewrite is incomplete.`,{rejected:M.length,manifestPath:P?.manifestPath,source:"deploy-guard"}),h?c.info(`Using ${C.length} eligible planned changed file(s) from deploy plan for upload${M.length>0?` (${M.length} blocked by deploy rewrite guard)`:""}.`):c.info(`Found ${j.length} file(s) in output directory "${p.outputDir}"${M.length>0?`; ${C.length} remain eligible for upload after deploy rewrite guard filtering`:""}.`),c.progress("Deploy preflight: comparing local output with remote S3 state.",{phase:"deploy",mode:y,totalFiles:C.length,scannedFiles:j.length,rejected:M.length,deploymentProfile:r.name||"",s3Bucket:p.s3.bucket,s3Prefix:p.s3.prefix||"",targetedPlan:h,deployGuardEnabled:f.outputDir===t.outputDir});let R=0,U=0,b=0,T=[],O=[],q=[],v=[],E=[],F=new Map,z=new Map,ee=new Map,Te=new Map,D=new Map;h||(c.info("Listing existing S3 objects to detect unchanged files..."),F=await Ia(w,p.s3.bucket,p.s3.prefix,c),c.info(`Found ${F.size} existing key(s) in S3.`));let dt=async k=>F.has(k)?F.get(k)??null:h?Aa(w,p.s3.bucket,k,z):null;for(let k of C){let K=S.join(p.outputDir,k),I=Ut(p.s3.prefix,k),re=P?.contentTypeByRelativePath.get(k),He=re&&re!=="application/octet-stream"?re:pa.lookup(k)||re||"application/octet-stream",ys=vn(k)?p.s3.htmlCacheControl:p.s3.assetCacheControl,B=R+U+b+1;C.length<=200||B<=5||B%10===0||B===C.length?(c.progress(`Uploading [${B}/${C.length}] ${I} (${He})`,{file:k,key:I,index:B,totalFiles:C.length,contentType:He,mode:y}),c.info(`Uploading [${B}/${C.length}] ${I} (${He})`)):c.debug(`Uploading [${B}/${C.length}] ${I} (${He})`);try{let se=await A.readFile(K),ze=await dt(I),Qe=null,ke=null;if(ze){let Nt=se.byteLength;if(ze.size===Nt){let pt=ze.etag.includes("-");if(ze.etag!==""&&!pt){let Ss=ka(se);if(ze.etag===Ss){U++,C.length<=200||U<=5||U%25===0?(c.progress(`Skipped unchanged [${B}/${C.length}] ${I}`,{file:k,key:I,index:B,totalFiles:C.length,uploaded:R,skipped:U,failed:b,mode:y,reason:"etag-md5-match"}),c.info(`Skipped unchanged [${B}/${C.length}] ${I}`)):c.debug(`Skipped unchanged [${B}/${C.length}] ${I}`),O.push(I);continue}}Qe=os(se);let Dn=await $a(w,p.s3.bucket,I,ee);if(Dn&&Dn===Qe){U++,C.length<=200||U<=5||U%25===0?(c.progress(`Skipped unchanged [${B}/${C.length}] ${I}`,{file:k,key:I,index:B,totalFiles:C.length,uploaded:R,skipped:U,failed:b,mode:y,reason:"metadata-sha256-match"}),c.info(`Skipped unchanged [${B}/${C.length}] ${I}`)):c.debug(`Skipped unchanged [${B}/${C.length}] ${I}`),O.push(I);continue}}if(vn(k)){ke=Rn(se);let pt=await Ea(w,p.s3.bucket,I,Te,D);if(pt&&pt===ke){U++,C.length<=200||U<=5||U%25===0?(c.progress(`Skipped semantically unchanged [${B}/${C.length}] ${I}`,{file:k,key:I,index:B,totalFiles:C.length,uploaded:R,skipped:U,failed:b,mode:y,reason:"normalized-html-match"}),c.info(`Skipped semantically unchanged [${B}/${C.length}] ${I}`)):c.debug(`Skipped semantically unchanged [${B}/${C.length}] ${I}`),O.push(I);continue}}}Qe=Qe??os(se),ke=ke??(vn(k)?Rn(se):null),await ne(`S3 upload ${I}`,9e5,({abortController:Nt})=>new Upload({client:w,abortController:Nt,params:{Bucket:p.s3.bucket,Key:I,Body:se,ContentType:He,CacheControl:ys,Metadata:{[as]:Qe,...ke?{[cs]:ke}:{}}}}).done()),R++,T.push(I),(R%25===0||R===C.length)&&(c.progress(`Uploaded ${R}/${C.length} file(s)\u2026`,{uploaded:R,skipped:U,failed:b,totalFiles:C.length,mode:y}),c.info(`Uploaded ${R}/${C.length} file(s)\u2026`));}catch(se){b++,q.push(I),c.error(`Failed to upload ${I}: ${se.message}`,{key:I,error:String(se)});}}if(c.info(`Upload complete: ${R} uploaded, ${U} skipped unchanged, ${_.length} rejected by guard, ${b} failed.`),q.length>0||_.length>0)throw new Error(`Deployment stopped before deletion because ${q.length} upload(s) failed and ${_.length} upload(s) were rejected.`);if(y==="sdk-upload-delete"){let k=new Set((d?.deletedFiles??[]).map(I=>Ut(p.s3.prefix,I))),K=[...k].filter(I=>!$.has(I));if(!h&&(E=[...F.keys()].filter(re=>!$.has(re)).filter(re=>!k.has(re)),E.length>0)){c.warn(`Protected ${E.length} remote-only S3 object(s) from deletion because the crawl did not provide explicit tombstones.`,{protected:E.length,source:"deploy-delete-guard"});for(let re of E)c.debug(` protected remote-only object: ${re}`);}v=await Ta(w,p.s3.bucket,h?K:K.filter(I=>F.has(I)),c);}else c.info("Sync mode is sdk-upload-only \u2014 skipping stale object deletion.");a&&(await A.mkdir(S.dirname(a),{recursive:!0}),await A.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:y,summary:{totalFiles:j.length,eligibleFiles:C.length,uploaded:T.length,skipped:O.length,rejected:_.length,failed:q.length,deleted:v.length,protected:E.length,...r.name?{profile:r.name}:{}},uploadedKeys:T,skippedKeys:O,rejectedKeys:_,failedKeys:q,deletedKeys:v,protectedRemoteOnlyKeys:E},null,2),"utf8")),d?.schemaVersion!==2&&await De(t),c.endMark("deploy"),await c.flush();}finally{await l().catch(()=>{});}}function La(e){let t=e;return t.endsWith("/")?t+="index.html":S.posix.basename(t).includes(".")||(t+="/index.html"),t}function ja(e,t){let n=t.trim().replace(/^\/+|\/+$/g,"");if(!n)return null;let r=`/${n}`;return e===r||e.startsWith(`${r}/`)?e:`${r}${e.startsWith("/")?e:`/${e}`}`}function ds(e,t){let n=new Set;for(let r of e){let s=new URL(r,"https://content-sync.invalid");if(s.origin!=="https://content-sync.invalid")continue;let i=`${s.pathname}${s.search}`,a=La(s.pathname);n.add(i),n.add(`${a}${s.search}`);let c=ja(a,t);c&&n.add(`${c}${s.search}`);}return [...n].sort()}function Ba(){let e=String(process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"").trim();return e?S.join(S.resolve(e),"content-sync-invalidation.json"):""}async function Tn(e,t){if(!e)return;await A.mkdir(S.dirname(e),{recursive:true});let n=`${e}.${process.pid}.${Date.now()}.tmp`;await A.writeFile(n,JSON.stringify({...t,updatedAt:new Date().toISOString()},null,2),"utf8"),await A.rename(n,e);}async function Wa(e,t,n,r){if(!e)return null;try{let s=JSON.parse(await A.readFile(e,"utf8"));if(s.schemaVersion!==1||s.distributionId!==t||s.impactHash!==n||!Array.isArray(s.batches))throw new Error("Content-sync invalidation state does not match the deploy plan.");let i=s.batches.flatMap(a=>a.paths);return i.length!==r.length||i.some((a,c)=>a!==r[c])?null:s}catch(s){if(s.code==="ENOENT")return null;throw s}}function Ha(e,t=3e3){let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}async function gs(e=process.argv.slice(2)){let t=await oe(),n=Ot(e),r=Be(t,n),s=r.config,i=new Fe(s.logDir||"logs","invalidate.log.jsonl",s.logLevel??"info"),a=e.includes("--content-sync"),c=await Me(t);if(a&&c?.schemaVersion!==2)throw new Error("Content-sync invalidation requires a valid schema-2 targeted deploy plan.");if(r.name&&i.info(`Using deployment profile: ${r.name}`),!s.cloudFront.distributionId){i.info("No CloudFront distributionId configured; skipping invalidation."),await i.flush();return}let o=c?.schemaVersion===2?c.invalidationPaths:s.cloudFront.invalidationPaths.length>0?s.cloudFront.invalidationPaths:["/*"],l=c?.schemaVersion===2?ds(o,s.s3.prefix||""):o;if(c?.schemaVersion===2&&l.some(p=>p==="/*"))throw new Error("Content-sync cannot use a whole-distribution invalidation.");if(l.length===0){i.info("The targeted deploy plan has no CloudFront paths to invalidate."),await i.flush();return}let d=s.cloudFront.distributionId,u=new CloudFrontClient({region:"us-east-1",maxAttempts:5});if(i.mark("invalidate"),c?.schemaVersion!==2){let p=`smartcloud-static-publisher-${Date.now()}`;await ne(`CloudFront invalidation for distribution ${d}`,3e5,({httpOptions:y})=>u.send(new CreateInvalidationCommand({DistributionId:d,InvalidationBatch:{CallerReference:p,Paths:{Quantity:l.length,Items:l}}}),y)),i.endMark("invalidate"),await i.flush();return}let g=Ba(),f=await Wa(g,d,c.impactHash,l);if(!f){let p=createHash("sha256").update(JSON.stringify(l)).digest("hex");f={schemaVersion:1,distributionId:d,impactHash:c.impactHash,updatedAt:new Date().toISOString(),batches:Ha(l).map((y,m)=>({index:m,callerReference:`wpsuite-content-sync-${c.impactHash.slice(0,24)}-${p.slice(0,24)}-${m}`,paths:y,invalidationId:null,status:"pending"}))},await Tn(g,f);}for(let p of f.batches){if(!p.invalidationId){let y=await ne(`CloudFront targeted invalidation batch ${p.index+1}`,3e5,({httpOptions:h})=>u.send(new CreateInvalidationCommand({DistributionId:d,InvalidationBatch:{CallerReference:p.callerReference,Paths:{Quantity:p.paths.length,Items:p.paths}}}),h)),m=String(y.Invalidation?.Id||"").trim();if(!m)throw new Error("CloudFront did not return an invalidation ID.");p.invalidationId=m,p.status="created",await Tn(g,f);}await waitUntilInvalidationCompleted({client:u,maxWaitTime:900,minDelay:2,maxDelay:15},{DistributionId:d,Id:p.invalidationId}),p.status="completed",await Tn(g,f),i.info(`CloudFront invalidation batch ${p.index+1}/${f.batches.length} completed.`,{invalidationId:p.invalidationId,pathCount:p.paths.length});}i.endMark("invalidate"),await i.flush();}function _t(e){let t=new URL(e);return t.hash="",t.href}function fs(e,t,n){let r=new Set([...t].map(o=>_t(o))),s=new Map,i=new Map,a=o=>{s.set(_t(o),o);},c=o=>{if(!o)return;let l=_t(o);s.has(l)||i.set(l,o);};for(let o of e.deleteUrls)a(o);for(let o of e.resourceDeleteUrls)a(o);for(let o of e.archiveFamilies)if(o.foundPosts===0)for(let l of o.pageUrls)r.has(_t(l))||a(l);for(let o of e.directRenderUrls)c(o);for(let o of e.resourceRenderUrls)c(o);for(let o of e.archiveFamilies)c(o.pageUrls[0]),c(o.pageUrls.at(-1));for(let o of n)c(o);return {expectedAvailable:[...i.values()],expectedMissing:[...s.values()]}}var hs=["claimed","impact-planned","rendered","deployed","invalidated","verified","acknowledged"];function En(){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 S.resolve(e)}function We(e,t){return hs.indexOf(e)>=hs.indexOf(t)}async function ye(e,t,n,r,s={}){let i={timestamp:new Date().toISOString(),eventType:t,status:t.endsWith("failed")?"failed":"success",actorSource:"content-sync",jobId:n.id||"",command:"content-sync",message:r,details:s};await A.mkdir(e,{recursive:true}),await A.appendFile(S.join(e,"audit-events.jsonl"),`${JSON.stringify(i)}
|
|
14
|
+
`,"utf8");}function Qa(e){return Je({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 Ja(e,t){let n=(e.scheduler?.rules??[]).find(r=>r.command==="content-sync"&&r.id===t);if(!n)throw new Error(`Content-sync scheduler rule not found: ${t}`);if(n.enabled===false)throw new Error(`Content-sync scheduler rule is disabled: ${t}`);return n}async function Mn(e,t){if(e.subscriptionType!=="PROFESSIONAL"&&e.subscriptionType!=="AGENCY")throw new Error("Content-sync requires an active Professional or Agency subscription.");let n=Qa(t),r=Be(e,t.deploymentProfile),s=r.name||"",i=Un(e.sourceOrigin,String(t.id||""),n),a=Ln({sourceOrigin:e.sourceOrigin,targetOrigin:r.config.targetOrigin,deploymentProfile:s,s3Bucket:r.config.s3.bucket,s3Prefix:r.config.s3.prefix,cloudFrontDistributionId:r.config.cloudFront.distributionId,urlRewriteMode:r.config.urlRewriteMode,extraReplacements:r.profile?.extraReplacements??{}}),c=jn({siteId:e.wpsuite?.siteSettings?.siteId,accountId:e.wpsuite?.siteSettings?.accountId,sourceOrigin:e.sourceOrigin,ruleId:String(t.id||""),targetFingerprint:a}),o=`content-sync:${String(t.id||"")}:${le({scopeFingerprint:i,targetFingerprint:a}).slice(0,32)}`,l=new ft({sourceOrigin:e.sourceOrigin,runtimeToken:String(e.wpsuite?.runtimeToken||""),ignoreHttpsErrors:e.ignoreHttpsErrors}),d=await l.releaseFingerprint(n.includeSubsites),u=Fn({wordpressFingerprint:d,targetFingerprint:a,sourceOrigin:e.sourceOrigin,sitemapPaths:Ge(e.sitemapPaths),blockedPathPrefixes:e.blockedPathPrefixes,assetPathPrefixes:e.assetPathPrefixes,noJavaScriptRenderPathPrefixes:e.noJavaScriptRenderPathPrefixes,urlRewriteMode:e.urlRewriteMode});return {rule:t,scope:n,deployment:r,deploymentProfile:s,scopeFingerprint:i,targetFingerprint:a,consumerId:c,coalesceKey:o,client:l,releaseFingerprint:u}}async function Va(e){let t=En(),n=mt(t),r=await oe(),s=(r.scheduler?.rules??[]).filter(l=>l.command==="content-sync"&&l.enabled!==false);if(s.length===0)return 0;let i=await Qt(n),a=await ht(n),c=await zt(n),o=0;for(let l of s){let d=await Mn(r,l),u=c.entries[d.coalesceKey];if(!u||u.releaseJobId!==e||u.scopeFingerprint!==d.scopeFingerprint||u.targetFingerprint!==d.targetFingerprint||u.releaseFingerprint!==d.releaseFingerprint)throw new Error(`The normal release has no matching pre-crawl content-sync cutoff for rule ${String(l.id||"")}.`);let g=le({releaseJobId:e,releaseFingerprint:d.releaseFingerprint,scopeFingerprint:d.scopeFingerprint,targetFingerprint:d.targetFingerprint,sequence:u.sequence}),f=await d.client.establishBaseline({consumerId:d.consumerId,scopeFingerprint:d.scopeFingerprint,baselineId:g,postTypes:d.scope.postTypes,includeSubsites:d.scope.includeSubsites,sequence:u.sequence}),p={schemaVersion:1,ruleId:String(l.id||""),consumerId:d.consumerId,coalesceKey:d.coalesceKey,scopeFingerprint:d.scopeFingerprint,targetFingerprint:d.targetFingerprint,releaseFingerprint:d.releaseFingerprint,baselineId:g,deploymentProfile:d.deploymentProfile,committedSequence:f.committedSequence,releaseJobId:e,verifiedAt:new Date().toISOString()};i.entries[d.coalesceKey]=p;let y=a.rules[d.coalesceKey];a.rules[d.coalesceKey]={ruleId:String(l.id||""),consumerId:d.consumerId,coalesceKey:d.coalesceKey,committedSequence:f.committedSequence,observedHeadSequence:f.headSequence,lag:Math.max(0,f.headSequence-f.committedSequence),lastSuccessfulJobId:y?.lastSuccessfulJobId||e,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:f.headSequence>f.committedSequence,retryAttempt:0,nextRetryAt:null,lastError:null,baselineStatus:"ready",baselineReason:null};let m=await Vn(n,d.coalesceKey);await ye(t,"content-sync-baseline-established",{id:e},"A normal release established a verified content-sync baseline.",{ruleId:l.id,consumerId:d.consumerId,committedSequence:f.committedSequence,supersededCurrent:m}),o++;}return await Wn(n,i),await wt(n,a),await A.rm(n.releaseCutoff,{force:true}),o}async function Ka(e){let t=En(),n=mt(t),r=await oe(),s=(r.scheduler?.rules??[]).filter(c=>c.command==="content-sync"&&c.enabled!==false);if(s.length===0)return 0;let i=await zt(n),a=0;for(let c of s){let o=await Mn(r,c),l=Object.values(i.entries).find(g=>g.releaseJobId===e&&g.ruleId===String(c.id||""));if(l){if(l.coalesceKey===o.coalesceKey&&l.scopeFingerprint===o.scopeFingerprint&&l.targetFingerprint===o.targetFingerprint&&l.releaseFingerprint===o.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 d=await o.client.unboundHead(o.scope.postTypes,o.scope.includeSubsites),u={schemaVersion:1,releaseJobId:e,ruleId:String(c.id||""),coalesceKey:o.coalesceKey,scopeFingerprint:o.scopeFingerprint,targetFingerprint:o.targetFingerprint,releaseFingerprint:o.releaseFingerprint,sequence:d.headSequence,capturedAt:new Date().toISOString()};i.entries[o.coalesceKey]=u,await ye(t,"content-sync-release-cutoff-captured",{id:e},"A normal release captured its pre-crawl content-sync journal cutoff.",{ruleId:c.id,consumerId:o.consumerId,sequence:d.headSequence}),a++;}return await Bn(n,i),a}async function Ga(e,t){let n=JSON.parse(await A.readFile(S.join(e,"current-run.json"),"utf8"));if(n.id!==t||n.command!=="content-sync"||!String(n.ruleId||"").trim())throw new Error("The active queue job is not the requested content-sync job.");return n}async function $n(e,t,n=0){let r=e.protocol==="https:"?Nn:As,s=e.protocol==="https:"?new Nn.Agent({rejectUnauthorized:!t}):void 0;return new Promise((i,a)=>{let c=r.get(e,{agent:s,timeout:3e4,headers:{"user-agent":"WP-Suite-Content-Sync/1"}},o=>{let l=o.statusCode??500,d=o.headers.location;if(l>=300&&l<400&&d&&n<5){o.resume(),$n(new URL(d,e),t,n+1).then(i,a);return}let u=[],g=0;o.on("data",f=>{g+=f.byteLength,g<=1048576&&u.push(f);}),o.on("error",a),o.on("end",()=>i({status:l,body:Buffer.concat(u).toString("utf8"),contentType:String(o.headers["content-type"]||"")}));});c.on("timeout",()=>c.destroy(new Error(`Verification timed out: ${e}`))),c.on("error",a);})}async function Za(e,t,n,r){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 i=JSON.parse(await A.readFile(r,"utf8")),a=new Set;for(let[d,u]of Object.entries(i.pages??{}))a.add(d),typeof u.url=="string"&&a.add(u.url);let c=await Me(e);if(c?.schemaVersion!==2||c.impactHash!==n.impactHash)throw new Error("Content-sync verification requires the matching targeted deploy plan.");let o=fs(n,a,c.resolvedSitemapUrls),l=new Set(n.resourceRenderUrls.map(d=>{let u=new URL(d);return u.hash="",u.href}));for(let d of o.expectedAvailable){let u=new URL(d),g=new URL(`${u.pathname}${u.search}`,s),f=await $n(g,e.ignoreHttpsErrors);if(f.status<200||f.status>=400)throw new Error(`Content-sync verification failed (${f.status}): ${g}`);let p=new URL(d);if(p.hash="",l.has(p.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 d of o.expectedMissing){let u=new URL(d),g=new URL(`${u.pathname}${u.search}`,s),f=await $n(g,e.ignoreHttpsErrors);if(f.status>=200&&f.status<300)throw new Error(`Deleted content is still publicly available: ${g}`)}}async function Ya(e){let t=await A.readFile(e.candidateManifest,"utf8");JSON.parse(t);let n=`${e.trustedManifest}.${process.pid}.tmp`;await A.writeFile(n,t,"utf8"),await A.rename(n,e.trustedManifest);}async function Xa(e,t){try{let n=JSON.parse(await A.readFile(e.candidateManifest,"utf8"));if([...Object.values(n.pages??{}),...Object.values(n.assets??{})].some(s=>s?.lastSeenRunId===t))return "resumed"}catch(n){if(n.code!=="ENOENT")throw new Error(`The content-sync candidate manifest is invalid: ${n instanceof Error?n.message:String(n)}`,{cause:n})}return await A.copyFile(e.trustedManifest,e.candidateManifest).catch(n=>{throw new Error(`A trusted crawl manifest is required before content-sync: ${n instanceof Error?n.message:String(n)}`,{cause:n})}),"initialized"}async function Ae(e,t,n,r,s={},i=0,a=async()=>{}){t.phase=n,await Hn(e,t),await Jn(e,{schemaVersion:1,jobId:t.jobId,phase:n,completedItems:r,totalItems:r,attempt:i,updatedAt:new Date().toISOString(),details:s}),await ye(S.dirname(e.state),"content-sync-checkpoint",{id:t.jobId},`Content-sync checkpoint completed: ${n}.`,{phase:n,completedItems:r,totalItems:r,attempt:i,...s}),await a(n,t);}async function ec(e,t={}){let n={loadConfig:oe,resolveRuleContext:Mn,runCrawl:rs,runDeploy:ls,runInvalidate:gs,verifyDeployment:Za,promoteCandidateManifest:Ya,clearDeployPlan:De,afterCheckpoint:async()=>{},...t},r=En(),s=mt(r),i=await Ga(r,e),a=await n.loadConfig(),c=Ja(a,String(i.ruleId)),o=await n.resolveRuleContext(a,c);if(i.coalesceKey&&i.coalesceKey!==o.coalesceKey)throw new Error("Queued content-sync demand no longer matches the active rule scope.");let d=(await Qt(s)).entries[o.coalesceKey];if(!d||d.scopeFingerprint!==o.scopeFingerprint||d.targetFingerprint!==o.targetFingerprint||d.releaseFingerprint!==o.releaseFingerprint)throw await ye(r,"content-sync-baseline-rejected",i,"Content-sync requires a new verified full or incremental release baseline.",{ruleId:c.id,reason:d?"mismatch":"missing"}),new Error("Content-sync baseline is missing or stale. Run a successful normal publish first.");let u=await Jt(s),g=await o.client.head({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites});if(u&&u.jobId!==i.id)throw new Error("Another immutable content-sync range is still active.");if(u||(u={schemaVersion:1,jobId:i.id,ruleId:String(c.id||""),consumerId:o.consumerId,coalesceKey:o.coalesceKey,scopeFingerprint:o.scopeFingerprint,targetFingerprint:o.targetFingerprint,baselineId:d.baselineId,fromSequence:g.committedSequence,toSequence:g.headSequence,phase:"claimed",impactHash:null,startedAt:new Date().toISOString(),updatedAt:new Date().toISOString()},await Ae(s,u,"claimed",0,{fromSequence:u.fromSequence,toSequence:u.toSequence},0,n.afterCheckpoint),await ye(r,"content-sync-range-claimed",i,"Content-sync claimed a closed journal range.",{fromSequence:u.fromSequence,toSequence:u.toSequence})),u.fromSequence===u.toSequence){let h=await ht(s);h.rules[o.coalesceKey]={ruleId:String(c.id||""),consumerId:o.consumerId,coalesceKey:o.coalesceKey,committedSequence:u.toSequence,observedHeadSequence:g.headSequence,lag:Math.max(0,g.headSequence-u.toSequence),lastSuccessfulJobId:i.id,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:false,retryAttempt:0,nextRetryAt:null,lastError:null},await wt(s,h),await Vt(s);return}let f=await zn(s);if(!We(u.phase,"impact-planned")){let h=await o.client.events({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites,afterSequence:u.fromSequence,throughSequence:u.toSequence}),w=Ht({events:h,scope:o.scope,sourceOrigin:a.sourceOrigin}),P=await o.client.resolveImpactFamilies(w,o.scope.includeSubsites);f=_n({jobId:i.id,ruleId:String(c.id||""),consumerId:o.consumerId,coalesceKey:o.coalesceKey,scopeFingerprint:o.scopeFingerprint,targetFingerprint:o.targetFingerprint,baselineId:d.baselineId,sourceOrigin:a.sourceOrigin,scope:o.scope,fromSequence:u.fromSequence,toSequence:u.toSequence,events:h,resolvedArchiveFamilies:P,sitemapUrls:Ge(a.sitemapPaths)}),await Qn(s,f),u.impactHash=f.impactHash,await Ae(s,u,"impact-planned",h.length,{eventCount:h.length,foldedCount:f.foldedCount,impactHash:f.impactHash},0,n.afterCheckpoint),await ye(r,"content-sync-impact-planned",i,"Content-sync persisted an immutable impact plan.",{impactHash:f.impactHash,eventCount:h.length});}if(!f||f.jobId!==i.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,!We(u.phase,"rendered")){let h=await Xa(s,i.id);await ye(r,h==="resumed"?"content-sync-render-resumed":"content-sync-render-initialized",i,h==="resumed"?"Content-sync resumed its candidate crawl manifest.":"Content-sync initialized a candidate crawl manifest.",{impactHash:f.impactHash}),await n.runCrawl(["--content-sync-plan",s.impact]),await Ae(s,u,"rendered",f.directRenderUrls.length+f.archiveFamilyUrls.length+f.resourceRenderUrls.length,{impactHash:f.impactHash},i.attempt??0,n.afterCheckpoint);}let p=o.deploymentProfile?["--profile",o.deploymentProfile]:[];if(We(u.phase,"deployed")||(await n.runDeploy([...p,"--content-sync"]),await Ae(s,u,"deployed",1,{impactHash:f.impactHash},0,n.afterCheckpoint),await ye(r,"content-sync-deployed",i,"Content-sync targeted deployment completed.",{impactHash:f.impactHash})),We(u.phase,"invalidated")?We(u.phase,"verified")||await n.runInvalidate([...p,"--content-sync"]):(await n.runInvalidate([...p,"--content-sync"]),await Ae(s,u,"invalidated",1,{impactHash:f.impactHash},0,n.afterCheckpoint)),We(u.phase,"verified")||(await n.verifyDeployment(a,o,f,s.candidateManifest),await n.promoteCandidateManifest(s),await Ae(s,u,"verified",1,{impactHash:f.impactHash},0,n.afterCheckpoint)),g=await o.client.head({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites}),g.committedSequence===u.fromSequence)await o.client.acknowledge({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,expectedSequence:u.fromSequence,sequence:u.toSequence,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites});else if(g.committedSequence!==u.toSequence)throw new Error("Content-sync acknowledgement cursor is in an unexpected state.");await Ae(s,u,"acknowledged",1,{sequence:u.toSequence},0,n.afterCheckpoint),await ye(r,"content-sync-cursor-acknowledged",i,"Content-sync committed its journal cursor after verification.",{sequence:u.toSequence});let y=await o.client.head({consumerId:o.consumerId,scopeFingerprint:o.scopeFingerprint,baselineId:d.baselineId,postTypes:o.scope.postTypes,includeSubsites:o.scope.includeSubsites}),m=await ht(s);m.rules[o.coalesceKey]={ruleId:String(c.id||""),consumerId:o.consumerId,coalesceKey:o.coalesceKey,committedSequence:u.toSequence,observedHeadSequence:y.headSequence,lag:Math.max(0,y.headSequence-u.toSequence),lastSuccessfulJobId:i.id,lastSuccessfulAt:new Date().toISOString(),trailingWorkDetected:y.headSequence>u.toSequence,retryAttempt:0,nextRetryAt:null,lastError:null},await wt(s,m),await n.clearDeployPlan(a),await A.rm(S.join(r,"content-sync-invalidation.json"),{force:true}),await A.rm(s.candidateManifest,{force:true}),await Vt(s);}async function ws(e=process.argv.slice(2)){let n=e.indexOf("--capture-baseline-cutoffs");if(n>=0){let a=String(e[n+1]||"").trim();if(!a)throw new Error("--capture-baseline-cutoffs requires a release job ID.");await Ka(a);return}let r=e.indexOf("--establish-baselines");if(r>=0){let a=String(e[r+1]||"").trim();if(!a)throw new Error("--establish-baselines requires a release job ID.");await Va(a);return}let s=e.indexOf("--job-id"),i=s>=0?String(e[s+1]||"").trim():"";if(!i)throw new Error("Content-sync requires --job-id.");await ec(i);}ws().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exit(1);});
|