@smart-cloud/publisher-exporter 1.1.76 → 1.1.78
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 +16 -0
- package/dist/content-sync.js +15 -15
- package/dist/crawl.js +13 -13
- package/dist/deploy.js +6 -6
- package/dist/remote-worker.js +5 -5
- package/package.json +1 -1
package/dist/deploy.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import M,{readFile}from'fs/promises';import sr from'http';import ir from'https';import v from'path';import {S3Client,GetObjectCommand,PutObjectCommand,CopyObjectCommand,HeadObjectCommand,DeleteObjectsCommand,ListObjectsV2Command}from'@aws-sdk/client-s3';import {Upload}from'@aws-sdk/lib-storage';import Dr,{createHash}from'crypto';import Fr from'fast-glob';import Tt from'mime-types';import {availableParallelism}from'os';import {Worker}from'worker_threads';import {LambdaClient,InvokeCommand}from'@aws-sdk/client-lambda';import {DynamoDBClient,GetItemCommand}from'@aws-sdk/client-dynamodb';import {fromTemporaryCredentials}from'@aws-sdk/credential-providers';var nt=["/sitemap_index.xml","/wp-sitemap.xml","/sitemap.xml"];function st(t){let e=t.trim();return e==="."?".":e.replace(/\/$/,"")}function ar(t){let e=String(t??"").trim();if(!e)return "";let r=e;if(/^https?:\/\//i.test(r))try{r=new URL(r).pathname;}catch{return ""}if(r=r.split(/[?#]/,1)[0]?.replace(/\\/g,"/").trim()??"",!r)return "";let n=r.endsWith("/"),o=r.replace(/^\/+/,"").split("/").map(a=>a.replace(/[^A-Za-z0-9._-]/g,"")).filter(a=>a.length>0&&a!=="."&&a!=="..");if(o.length===0)return "";let s=`/${o.join("/")}`;return n&&v.extname(s)===""&&(s+="/"),s==="/"?"":s}function Ne(t){return !t||typeof t!="object"?{}:Object.fromEntries(Object.entries(t).map(([e,r])=>[e.trim(),String(r??"")]).filter(([e])=>e.length>0))}function lr(t){if(!t||typeof t!="object")return {};let e={};for(let[r,n]of Object.entries(t)){let o=r.trim();if(!o||!n||typeof n!="object")continue;let s=n,a={};if(typeof s.targetOrigin=="string"){let l=st(s.targetOrigin);l&&(a.targetOrigin=l);}let i=Ne(s.extraReplacements);if(Object.keys(i).length>0&&(a.extraReplacements=i),s.s3&&typeof s.s3=="object"){let l={},u=s.s3;typeof u.bucket=="string"&&(l.bucket=u.bucket.trim()),typeof u.prefix=="string"&&(l.prefix=u.prefix.trim()),typeof u.region=="string"&&(l.region=u.region.trim()),typeof u.htmlCacheControl=="string"&&(l.htmlCacheControl=u.htmlCacheControl.trim()),typeof u.assetCacheControl=="string"&&(l.assetCacheControl=u.assetCacheControl.trim()),Object.keys(l).length>0&&(a.s3=l);}if(s.cloudFront&&typeof s.cloudFront=="object"){let l={},u=s.cloudFront;typeof u.distributionId=="string"&&(l.distributionId=u.distributionId.trim()),Array.isArray(u.invalidationPaths)&&(l.invalidationPaths=u.invalidationPaths.map(c=>String(c??"").trim()).filter(c=>c.length>0)),Object.keys(l).length>0&&(a.cloudFront=l);}e[o]=a;}return e}function Ue(t){return t==="PROFESSIONAL"||t==="AGENCY"?t:void 0}function cr(t,e){if(!t||typeof t!="object")return null;let r=t,n=r.command;if(n!=="publish"&&n!=="crawl"&&n!=="deploy"&&n!=="invalidate"&&n!=="retry-timeouts"&&n!=="url"&&n!=="content-sync")return null;let o=Number.parseInt(String(r.intervalMinutes??"0"),10);if(!Number.isFinite(o)||o<1)return null;let s=String(r.id??`${n}-${e+1}`).trim();if(!s)return null;let a=String(r.deploymentProfile??"").trim(),i=String(r.url??"").trim(),l=Array.isArray(r.postTypes)?[...new Set(r.postTypes.map(c=>String(c??"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"")).filter(Boolean))]:[],u=Array.isArray(r.listingPaths)?[...new Set(r.listingPaths.map(c=>String(c??"").trim()).filter(Boolean))]:[];return n==="content-sync"&&l.length===0?null:{id:s,enabled:r.enabled!==false,command:n,intervalMinutes:o,...n==="publish"||n==="crawl"?{crawlMode:r.crawlMode==="incremental"?"incremental":"full"}:{},...(n==="publish"||n==="deploy"||n==="invalidate"||n==="content-sync")&&a?{deploymentProfile:a}:{},...i?{url:i}:{},...l.length>0?{postTypes:l}:{},...u.length>0?{listingPaths:u}:{},...typeof r.includeSubsites=="boolean"?{includeSubsites:r.includeSubsites}:{},...typeof r.includePostTypeArchives=="boolean"?{includePostTypeArchives:r.includePostTypeArchives}:{},...typeof r.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:r.includeTaxonomyArchives}:{},...typeof r.includeAuthorArchives=="boolean"?{includeAuthorArchives:r.includeAuthorArchives}:{},...typeof r.includeDateArchives=="boolean"?{includeDateArchives:r.includeDateArchives}:{},...typeof r.includePostsPage=="boolean"?{includePostsPage:r.includePostsPage}:{},...typeof r.includeSitemapChain=="boolean"?{includeSitemapChain:r.includeSitemapChain}:{}}}function it(t){let e=t&&typeof t=="object"?t:{},r=Array.isArray(e.rules)?e.rules.map((n,o)=>cr(n,o)).filter(n=>!!n):[];return {enabled:e.enabled===true,timezone:typeof e.timezone=="string"&&e.timezone.trim()!==""?e.timezone.trim():"UTC",rules:r}}function ur(t){let e=t&&typeof t=="object"?t:{},r=e.render&&typeof e.render=="object"?e.render:{},n=Number(r.concurrency??0),o=Number(r.batchSize??0),s=Number(r.maxAttempts??0),a=e.rewrite&&typeof e.rewrite=="object"?e.rewrite:{},i=e.deploy&&typeof e.deploy=="object"?e.deploy:{},l=(u,c)=>({enabled:typeof u.enabled=="boolean"?u.enabled:r.enabled===true,concurrency:Math.min(100,Math.max(1,Number(u.concurrency||c.concurrency))),batchSize:Math.min(500,Math.max(1,Number(u.batchSize||c.batchSize))),maxAttempts:Math.min(5,Math.max(1,Number(u.maxAttempts||2)))});return {render:{enabled:r.enabled===true,...Number.isInteger(n)&&n>0?{concurrency:n}:{},batchSize:Number.isInteger(o)&&o>0?Math.min(20,o):5,...Number.isInteger(s)&&s>0?{maxAttempts:Math.min(5,s)}:{}},rewrite:l(a,{concurrency:8,batchSize:25}),deploy:l(i,{concurrency:8,batchSize:50})}}function pr(t){if(!t||typeof t!="object")return;let e=t,r={};for(let o of ["accountId","siteId"]){let s=e[o];typeof s=="string"&&s.trim()!==""&&(r[o]=s.trim());}let n=Number(e.lastUpdate??0);return Number.isFinite(n)&&n>0&&(r.lastUpdate=Math.floor(n)),e.subscriber===true&&(r.subscriber=true),Object.keys(r).length>0?r:void 0}function Ve(t){let e=t&&typeof t=="object"?t:{},r=String(e.accountId??"").trim(),n=String(e.siteId??"").trim(),o=e.subscriber===true,s=pr(e.siteSettings),a={...s??{},...r?{accountId:s?.accountId??r}:{},...n?{siteId:s?.siteId??n}:{},...s?.subscriber===true||o?{subscriber:true}:{}},i={},l=String(e.apiBase??"").trim();l&&(i.apiBase=l);let u=String(e.runtimeToken??e.nonce??"").trim();u&&(i.runtimeToken=u);let c=String(e.virtualAssetBaseUrl??e.uploadUrl??"").trim();c&&(i.virtualAssetBaseUrl=c),Object.keys(a).length>0&&(i.siteSettings=a);let p=Ue(e.subscriptionType);return p&&(i.subscriptionType=p),i}function dr(t){try{let e=new URL(t);globalThis.location=e;}catch{}}function at(t){return typeof t=="string"?t:t instanceof URL?t.toString():t.url}function gr(t,e){let r=new Headers(t instanceof Request?t.headers:void 0);if(e?.headers)for(let[n,o]of new Headers(e.headers).entries())r.set(n,o);return r}async function lt(t,e,r=5){let n=new URL(at(t)),o=String(e?.method??(t instanceof Request?t.method:"GET")).toUpperCase(),s=n.protocol==="http:"?sr:ir,a=gr(t,e);return await new Promise((i,l)=>{let u=s.request(n,{method:o,headers:Object.fromEntries(a.entries()),...n.protocol==="https:"?{rejectUnauthorized:false}:{}},c=>{let p=[];c.on("data",d=>{p.push(Buffer.isBuffer(d)?d:Buffer.from(d));}),c.on("error",l),c.on("end",()=>{let d=c.statusCode??0,m=c.headers.location;if(r>0&&m&&[301,302,303,307,308].includes(d)){i(lt(new URL(m,n),{method:d===303?"GET":o},r-1));return}let R=new Headers;for(let[w,y]of Object.entries(c.headers))Array.isArray(y)?R.set(w,y.join(", ")):typeof y=="string"&&R.set(w,y);i(new Response(Buffer.concat(p),{status:d,statusText:c.statusMessage??"",headers:R}));});});u.on("error",l),u.end();})}function mr(t){let e=Ve(t.wpsuite),r={...e.siteSettings??{},...e.siteSettings?.subscriber===true||e.subscriptionType==="PROFESSIONAL"||e.subscriptionType==="AGENCY"?{subscriber:true}:{}},n=String(r.accountId??"").trim(),o=String(r.siteId??"").trim(),s=String(e.virtualAssetBaseUrl??e.uploadUrl??"").trim();if(t.wpsuite={...e.apiBase?{apiBase:e.apiBase}:{},...e.runtimeToken?{runtimeToken:e.runtimeToken}:{},...s?{virtualAssetBaseUrl:s}:{},...Object.keys(r).length>0?{siteSettings:r}:{},...e.subscriptionType?{subscriptionType:e.subscriptionType}:{}},!n||!o||!s)return false;dr(t.sourceOrigin);let a=globalThis,l={...a.WpSuite??{},siteSettings:r,uploadUrl:s};return e.apiBase&&(l.apiBase=e.apiBase),a.WpSuite=l,true}async function fr(t){let e=String(t.wpsuite?.virtualAssetBaseUrl??t.wpsuite?.uploadUrl??"").trim();if(!mr(t)){let o=t.wpsuite?.siteSettings,s=[String(o?.accountId??"").trim()?"":"accountId",String(o?.siteId??"").trim()?"":"siteId",e?"":"virtualAssetBaseUrl"].filter(Boolean);return {remote:null,diagnostic:{status:"invalid-runtime",virtualAssetBaseUrl:e,subscriptionType:null,error:`Missing WP Suite runtime field(s): ${s.join(", ")}.`,requests:[]}}}let r=globalThis.fetch,n=[];try{typeof r=="function"&&/^https?:\/\//i.test(e)&&(globalThis.fetch=(async(l,u)=>{let c=at(l);if(c.startsWith(e)){let p=(()=>{try{return new URL(c).pathname}catch{return c}})();try{let d=t.ignoreHttpsErrors&&c.startsWith("https://")?await lt(l,u):await r(l,u);return n.push({path:p,status:d.status,ok:d.ok,error:null}),d}catch(d){throw n.push({path:p,status:null,ok:!1,error:d instanceof Error?d.message:String(d)}),d}}return r(l,u)}));let{getConfig:o}=await import('@smart-cloud/wpsuite-core'),s=await o("publisher"),a=s&&typeof s=="object"?s:null,i=Ue(a?.subscriptionType);return {remote:a,diagnostic:{status:a?"loaded":"unavailable",virtualAssetBaseUrl:e,subscriptionType:i??null,error:a?null:"WP Suite publisher config loader returned no configuration.",requests:n}}}catch(o){return {remote:null,diagnostic:{status:"unavailable",virtualAssetBaseUrl:e,subscriptionType:null,error:o instanceof Error?o.message:String(o),requests:n}}}finally{typeof r=="function"&&(globalThis.fetch=r);}}function hr(t,e){let r=lr(e?.deploymentProfiles),n=String(e?.defaultDeploymentProfile??"").trim(),o=r[n]?n:"",s=Ue(e?.subscriptionType),a=Ve(t.wpsuite);return {...t,scheduler:it(e?.scheduler),deploymentProfiles:r,defaultDeploymentProfile:o,...s?{subscriptionType:s}:{},wpsuite:{...a,...a.siteSettings||s?{siteSettings:{...a.siteSettings??{},...a.siteSettings?.subscriber===true||s==="PROFESSIONAL"||s==="AGENCY"?{subscriber:true}:{}}}:{},...s?{subscriptionType:s}:{}}}}function Ke(t,e){let n=String(t||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!n)return e;let o=n.split("/").map(s=>s.trim()).filter(s=>s.length>0&&s!=="."&&s!=="..");return o.length>0?o.join("/"):e}function yr(){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return t.trim()?v.resolve(t):""}function ot(t,e,r){let n=String(e||"").trim();return n&&v.isAbsolute(n)?v.resolve(n):v.resolve(t,Ke(n,r))}async function ve(t,e={}){let r=String("").trim()||process.env.PUBLISHER_CONFIG||"publisher.config.json",n=await M.readFile(r,"utf8"),o=JSON.parse(n);o.sourceOrigin=o.sourceOrigin.replace(/\/$/,""),o.targetOrigin=st(o.targetOrigin),o.ignoreHttpsErrors??=false,o.outputDir=String(o.outputDir||"export").trim()||"export",o.urlRewriteMode||=o.targetOrigin==="."?"relative":"absolute",o.noJavaScriptRenderPathPrefixes||=[],o.seedPaths||=[],o.generated404RequestPath=ar(o.generated404RequestPath),o.sitemapPaths||=[...nt],o.allowedAssetHosts||=[],o.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],o.blockedPathPrefixes||=[],o.blockedSearchFragments||=[],o.pageCache={purgeBeforeCrawl:o.pageCache?.purgeBeforeCrawl===true};let s=Number(o.processingConcurrency)>0?Math.min(100,Math.max(1,Number(o.processingConcurrency))):null;o.concurrency=s??o.concurrency??1,o.maxPages||=0,o.extraReplacements=Ne(o.extraReplacements),o.postCrawlCopyMap=Ne(o.postCrawlCopyMap),o.logDir=String(o.logDir||"logs").trim()||"logs",o.verbose??=false,o.logLevel||=o.verbose?"debug":"info",o.s3SyncMode||="sdk-upload-delete",o.readiness||={waitForSelector:null,waitForFunction:null,timeoutMs:1500,fallbackWaitMs:1500},o.readiness.timeoutMs??=1500,o.readiness.fallbackWaitMs??=1500,o.viewport||={width:1440,height:1200},o.navigationTimeoutMs||=3e4,o.assetDownloadConcurrency=s??(Number(o.assetDownloadConcurrency)>0?Number(o.assetDownloadConcurrency):o.concurrency),o.rewriteConcurrency=s??(Number(o.rewriteConcurrency)>0?Number(o.rewriteConcurrency):o.assetDownloadConcurrency),o.wpsuite=Ve(o.wpsuite),o.scheduler=it(void 0),o.remoteWorkers=ur(o.remoteWorkers),typeof o.lambdaDelegationEnabled=="boolean"&&(o.remoteWorkers.render??={},o.remoteWorkers.rewrite??={},o.remoteWorkers.deploy??={},o.remoteWorkers.render.enabled=o.lambdaDelegationEnabled,o.remoteWorkers.rewrite.enabled=o.lambdaDelegationEnabled,o.remoteWorkers.deploy.enabled=o.lambdaDelegationEnabled),s!==null&&(o.processingConcurrency=s,o.remoteWorkers.render??={},o.remoteWorkers.rewrite??={},o.remoteWorkers.deploy??={},o.remoteWorkers.render.concurrency=s,o.remoteWorkers.rewrite.concurrency=s,o.remoteWorkers.deploy.concurrency=s),o.deploymentProfiles={},o.defaultDeploymentProfile="",o.deploymentTargetOverride=String(o.deploymentTargetOverride??"").trim();let a=await fr(o);e.onRemotePublisherConfigDiagnostic?.(a.diagnostic);let i=hr(o,a.remote),l=yr(),u=l?v.resolve(l,".."):"";return u?(i.outputDir=ot(u,i.outputDir,"export"),i.logDir=ot(u,i.logDir,"logs")):(v.isAbsolute(i.outputDir)||(i.outputDir=Ke(i.outputDir,"export")),v.isAbsolute(i.logDir)||(i.logDir=Ke(i.logDir,"logs"))),i}function wr(t){let e=t/6e4;if(Number.isInteger(e)&&e>=1)return `${e} minute${e===1?"":"s"}`;let r=Math.ceil(t/1e3);return `${r} second${r===1?"":"s"}`}async function Y(t,e,r){let n=new AbortController,o=globalThis.setTimeout(()=>{n.abort(new Error(`${t} timed out after ${wr(e)}.`));},e);try{return await r({abortController:n,httpOptions:{abortSignal:n.signal,requestTimeout:e}})}finally{globalThis.clearTimeout(o);}}var br=".deploy-plan.json",Rr="deploy-plan.json",kr=".crawl-incomplete.json",Sr="crawl-incomplete.json";function ct(){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return t.trim()?v.resolve(t):""}function Pr(t){let e=String(t||"").replace(/\\/g,"/").replace(/^\/+/,"").trim(),r=v.posix.normalize(e);return !e||!r||r==="."||/^[a-zA-Z]:/.test(r)||r.startsWith("../")||r===".."?null:r}function xr(t){let e=String(t||"").trim();if(!e.startsWith("/")||e.startsWith("//")||e.includes("*")||e.includes("#"))return null;try{let r=new URL(e,"https://content-sync.invalid");return r.origin!=="https://content-sync.invalid"?null:`${v.posix.normalize(r.pathname)}${r.search}`}catch{return null}}function J(t){return [...new Set(t.map(Pr).filter(e=>e!==null))]}function vr(t,e){let r={generatedAt:String(e.generatedAt||new Date().toISOString()),outputDir:v.resolve(t.outputDir),runMode:e.runMode,crawlMode:e.crawlMode,fullSyncRequired:!!e.fullSyncRequired,changedFiles:J(e.changedFiles||[]),deletedFiles:J(e.deletedFiles||[]),rewriteTargets:J(e.rewriteTargets||[]),revalidateFiles:J(e.revalidateFiles||[])};return e.schemaVersion===2?{...r,schemaVersion:2,runMode:"content-sync",crawlMode:"incremental",fullSyncRequired:false,consumerId:String(e.consumerId||"").trim(),fromSequence:Math.max(0,Number(e.fromSequence)||0),toSequence:Math.max(0,Number(e.toSequence)||0),impactHash:String(e.impactHash||"").trim(),resolvedSitemapUrls:[...new Set((e.resolvedSitemapUrls||[]).map(n=>String(n||"").trim()).filter(n=>{try{let o=new URL(n);return o.protocol==="http:"||o.protocol==="https:"}catch{return false}}))],uploadGroups:{assets:J(e.uploadGroups?.assets||[]),content:J(e.uploadGroups?.content||[]),listings:J(e.uploadGroups?.listings||[]),resources:J(e.uploadGroups?.resources||[]),sitemapLeaves:J(e.uploadGroups?.sitemapLeaves||[]),sitemapIndexes:J(e.uploadGroups?.sitemapIndexes||[])},invalidationPaths:[...new Set((e.invalidationPaths||[]).map(xr).filter(n=>n!==null))].sort()}:{schemaVersion:1,...r,runMode:e.runMode}}function Er(t){if(!t||typeof t!="object")return false;let e=t;if(e.schemaVersion===2){let r=e;return r.runMode==="content-sync"&&r.crawlMode==="incremental"&&r.fullSyncRequired===false&&typeof r.generatedAt=="string"&&typeof r.outputDir=="string"&&typeof r.consumerId=="string"&&r.consumerId.trim()!==""&&Number.isSafeInteger(r.fromSequence)&&Number.isSafeInteger(r.toSequence)&&Number(r.toSequence)>=Number(r.fromSequence)&&typeof r.impactHash=="string"&&/^[a-f0-9]{64}$/.test(r.impactHash)&&Array.isArray(r.resolvedSitemapUrls)&&Array.isArray(r.changedFiles)&&Array.isArray(r.deletedFiles)&&Array.isArray(r.rewriteTargets)&&(r.revalidateFiles===void 0||Array.isArray(r.revalidateFiles))&&!!r.uploadGroups&&Array.isArray(r.uploadGroups.assets)&&Array.isArray(r.uploadGroups.content)&&Array.isArray(r.uploadGroups.listings)&&Array.isArray(r.uploadGroups.resources)&&Array.isArray(r.uploadGroups.sitemapLeaves)&&Array.isArray(r.uploadGroups.sitemapIndexes)&&Array.isArray(r.invalidationPaths)}return e.schemaVersion===1&&typeof e.generatedAt=="string"&&typeof e.outputDir=="string"&&(e.runMode==="full"||e.runMode==="retry-timeouts"||e.runMode==="single-url")&&(e.crawlMode==="full"||e.crawlMode==="incremental")&&typeof e.fullSyncRequired=="boolean"&&Array.isArray(e.changedFiles)&&Array.isArray(e.deletedFiles)&&Array.isArray(e.rewriteTargets)&&(e.revalidateFiles===void 0||Array.isArray(e.revalidateFiles))}function ut(t){let e=v.join(v.resolve(t.outputDir),br),r=ct();return r?[v.join(r,Rr),e]:[e]}function Cr(t){let e=v.join(v.resolve(t.outputDir),kr),r=ct();return r?[v.join(r,Sr),e]:[e]}async function pt(t){let e=v.resolve(t.outputDir);for(let r of ut(t))try{let n=await M.readFile(r,"utf8"),o=JSON.parse(n);if(!Er(o)||v.resolve(o.outputDir)!==e)continue;return vr(t,o)}catch{}return null}async function Ee(t){for(let e of ut(t))try{await M.unlink(e);}catch(r){if(r.code!=="ENOENT")throw r}}async function dt(t){let e=v.resolve(t.outputDir);for(let r of Cr(t)){let n;try{n=await M.readFile(r,"utf8");}catch(s){if(s.code==="ENOENT")continue;throw s}let o;try{o=JSON.parse(n);}catch{throw new Error(`Invalid incomplete crawl marker: ${r}`)}if(o.schemaVersion!==1||typeof o.startedAt!="string"||typeof o.outputDir!="string"||v.resolve(o.outputDir)!==e)throw new Error(`Invalid incomplete crawl marker: ${r}`);return {schemaVersion:1,startedAt:o.startedAt,outputDir:e}}return null}function Ir(t){return typeof t.subscriptionType=="string"&&t.subscriptionType.trim()!==""}function gt(t){let e="";for(let n=0;n<t.length;n++){let o=t[n];if(o==="--profile"){let s=(t[n+1]||"").trim();if(!s)throw new Error("Missing value for --profile.");e=s,n+=1;}else if(o.startsWith("--profile=")){let s=o.slice(10).trim();if(!s)throw new Error("Missing value for --profile.");e=s;}}let r=String(process.env.PUBLISHER_DEPLOY_PROFILE||process.env.PUBLISHER_DEPLOYMENT_PROFILE||"").trim();return e||r||null}function $r(t,e){return {...t,...e??{}}}function Tr(t,e){return {...t,...e??{},invalidationPaths:[...(e?.invalidationPaths??t.invalidationPaths)||[]]}}function mt(t,e){let r=String(e??t.deploymentTargetOverride??"").trim();if(!Ir(t)){if(r)throw new Error(`Deployment target "${r}" requires an active WPSuite subscription and remote publisher config.`);return {name:null,profile:null,config:t}}let n=String(r||t.defaultDeploymentProfile||"").trim();if(!n)return {name:null,profile:null,config:t};let o=t.deploymentProfiles?.[n];if(!o)throw new Error(`Unknown deployment profile "${n}". Check the linked WPSuite publisher configuration.`);return {name:n,profile:o,config:{...t,targetOrigin:o.targetOrigin??t.targetOrigin,s3:$r(t.s3,o.s3),cloudFront:Tr(t.cloudFront,o.cloudFront)}}}var ft={error:0,warn:1,info:2,debug:3},jr=/^(?:authorization|proxyAuthorization|runtimeToken|siteKey|nonce|accessToken|refreshToken|accessKeyId|secretAccessKey|sessionToken|xStaticPublisherToken|xApiKey)$/i;function ke(t){return t.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 Ie(t){return typeof t=="string"?ke(t):Array.isArray(t)?t.map(e=>Ie(e)):t instanceof Error?{name:t.name,message:ke(t.message),...t.stack?{stack:ke(t.stack)}:{}}:t&&typeof t=="object"?Object.fromEntries(Object.entries(t).map(([e,r])=>[e,jr.test(e)?"[REDACTED]":Ie(r)])):t}function bt(t){return t?Ie(t):void 0}var ht=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",Ce=ht?v.join(ht,"current-progress.json"):"",yt=Promise.resolve();function wt(t){return t.includes("crawl")?"crawl":t.includes("deploy")?"deploy":t.includes("invalidate")?"invalidate":t}function Or(t,e){let r={...t},n=typeof t.phase=="string"?t.phase.trim():"",o=typeof e.phase=="string"?e.phase.trim():"";if(o!==""&&(o==="deploy"||o.startsWith("deploy-"))&&n!==o)for(let i of ["index","totalFiles","staged","uploaded","skipped","failed","deleted","workerCount","completedBatches","totalBatches"])delete r[i];let a=new Set(["pagesQueued","pagesRendered","assetsQueued","sitemapsQueued","pagesDiscovered","assetsDiscovered","sitemapsDiscovered","pagesSaved","assetsSaved","donePages","doneAssets","doneSitemaps","changedTextFiles","uploaded","failed","index","totalFiles","completedBatches","totalBatches","pageQueue","assetQueue","sitemapQueue"]);for(let[i,l]of Object.entries(e)){let u=r[i];if(typeof u=="number"&&typeof l=="number"&&a.has(i)){r[i]=Math.max(u,l);continue}r[i]=l;}return r}function Mr(t,e,r){Ce&&(yt=yt.then(async()=>{let n=new Date,o=n.toISOString();await M.mkdir(v.dirname(Ce),{recursive:true});let s=await M.readFile(Ce,"utf8").then(P=>JSON.parse(P)).catch(()=>null),a=s&&typeof s.details=="object"&&s.details?s.details:{},i=wt(t),l=s?.currentStep||wt(s?.source||""),u=s?.startedAt||o,c={...s?.stepDurationsSec??{}},p=s?.stepStartedAt||o;if(l&&l!==i&&s?.stepStartedAt){let P=Math.max(0,Math.round((n.getTime()-new Date(s.stepStartedAt).getTime())/1e3));c[l]=(c[l]??0)+P,p=o;}let d=Math.max(0,Math.round((n.getTime()-new Date(p).getTime())/1e3)),m=Math.max(0,Math.round((n.getTime()-new Date(u).getTime())/1e3)),R=ke(e),w=bt(r)??{},y={checkedAt:o,source:t,message:R,details:Or(a,w),startedAt:u,currentStep:i,stepStartedAt:p,stepElapsedSec:d,totalElapsedSec:m,stepDurationsSec:c};await M.writeFile(Ce,JSON.stringify(y,null,2),"utf8");}).catch(()=>{}));}async function Ar(t,e){await M.mkdir(v.dirname(t),{recursive:true}),await M.appendFile(t,`${JSON.stringify(Ie(e))}
|
|
2
|
-
`,"utf8");}var we=class{constructor(e,r,n="info"){this.logDir=e;this.logFile=r;this.level=n;this.ensureLogFileReady();}logDir;logFile;level;startedAt=Date.now();marks=new Map;initPromise=null;writeQueue=Promise.resolve();writeError=null;get logPath(){return
|
|
3
|
-
`,"utf8");});}enqueueJsonLine(e,r){this.enqueueTask(()=>Ar(e,r));}accepts(e){return
|
|
1
|
+
import O,{readFile}from'fs/promises';import sr from'http';import ir from'https';import I from'path';import {S3Client,GetObjectCommand,PutObjectCommand,CopyObjectCommand,HeadObjectCommand,DeleteObjectsCommand,ListObjectsV2Command}from'@aws-sdk/client-s3';import {Upload}from'@aws-sdk/lib-storage';import Dr,{createHash}from'crypto';import Fr from'fast-glob';import Ot from'mime-types';import {availableParallelism}from'os';import {Worker}from'worker_threads';import {LambdaClient,InvokeCommand}from'@aws-sdk/client-lambda';import {DynamoDBClient,GetItemCommand}from'@aws-sdk/client-dynamodb';import {fromTemporaryCredentials}from'@aws-sdk/credential-providers';var st=["/sitemap_index.xml","/wp-sitemap.xml","/sitemap.xml"];function at(t){let e=t.trim();return e==="."?".":e.replace(/\/$/,"")}function ar(t){let e=String(t??"").trim();if(!e)return "";let r=e;if(/^https?:\/\//i.test(r))try{r=new URL(r).pathname;}catch{return ""}if(r=r.split(/[?#]/,1)[0]?.replace(/\\/g,"/").trim()??"",!r)return "";let n=r.endsWith("/"),o=r.replace(/^\/+/,"").split("/").map(a=>a.replace(/[^A-Za-z0-9._-]/g,"")).filter(a=>a.length>0&&a!=="."&&a!=="..");if(o.length===0)return "";let s=`/${o.join("/")}`;return n&&I.extname(s)===""&&(s+="/"),s==="/"?"":s}function Ue(t){return !t||typeof t!="object"?{}:Object.fromEntries(Object.entries(t).map(([e,r])=>[e.trim(),String(r??"")]).filter(([e])=>e.length>0))}function lr(t){if(!t||typeof t!="object")return {};let e={};for(let[r,n]of Object.entries(t)){let o=r.trim();if(!o||!n||typeof n!="object")continue;let s=n,a={};if(typeof s.targetOrigin=="string"){let l=at(s.targetOrigin);l&&(a.targetOrigin=l);}let i=Ue(s.extraReplacements);if(Object.keys(i).length>0&&(a.extraReplacements=i),s.s3&&typeof s.s3=="object"){let l={},u=s.s3;typeof u.bucket=="string"&&(l.bucket=u.bucket.trim()),typeof u.prefix=="string"&&(l.prefix=u.prefix.trim()),typeof u.region=="string"&&(l.region=u.region.trim()),typeof u.htmlCacheControl=="string"&&(l.htmlCacheControl=u.htmlCacheControl.trim()),typeof u.assetCacheControl=="string"&&(l.assetCacheControl=u.assetCacheControl.trim()),Object.keys(l).length>0&&(a.s3=l);}if(s.cloudFront&&typeof s.cloudFront=="object"){let l={},u=s.cloudFront;typeof u.distributionId=="string"&&(l.distributionId=u.distributionId.trim()),Array.isArray(u.invalidationPaths)&&(l.invalidationPaths=u.invalidationPaths.map(c=>String(c??"").trim()).filter(c=>c.length>0)),Object.keys(l).length>0&&(a.cloudFront=l);}e[o]=a;}return e}function Be(t){return t==="PROFESSIONAL"||t==="AGENCY"?t:void 0}function cr(t,e){if(!t||typeof t!="object")return null;let r=t,n=r.command;if(n!=="publish"&&n!=="crawl"&&n!=="deploy"&&n!=="invalidate"&&n!=="retry-timeouts"&&n!=="url"&&n!=="content-sync")return null;let o=Number.parseInt(String(r.intervalMinutes??"0"),10);if(!Number.isFinite(o)||o<1)return null;let s=String(r.id??`${n}-${e+1}`).trim();if(!s)return null;let a=String(r.deploymentProfile??"").trim(),i=String(r.url??"").trim(),l=Array.isArray(r.postTypes)?[...new Set(r.postTypes.map(c=>String(c??"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"")).filter(Boolean))]:[],u=Array.isArray(r.listingPaths)?[...new Set(r.listingPaths.map(c=>String(c??"").trim()).filter(Boolean))]:[];return n==="content-sync"&&l.length===0?null:{id:s,enabled:r.enabled!==false,command:n,intervalMinutes:o,...n==="publish"||n==="crawl"?{crawlMode:r.crawlMode==="incremental"?"incremental":"full"}:{},...(n==="publish"||n==="deploy"||n==="invalidate"||n==="content-sync")&&a?{deploymentProfile:a}:{},...i?{url:i}:{},...l.length>0?{postTypes:l}:{},...u.length>0?{listingPaths:u}:{},...typeof r.includeSubsites=="boolean"?{includeSubsites:r.includeSubsites}:{},...typeof r.includePostTypeArchives=="boolean"?{includePostTypeArchives:r.includePostTypeArchives}:{},...typeof r.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:r.includeTaxonomyArchives}:{},...typeof r.includeAuthorArchives=="boolean"?{includeAuthorArchives:r.includeAuthorArchives}:{},...typeof r.includeDateArchives=="boolean"?{includeDateArchives:r.includeDateArchives}:{},...typeof r.includePostsPage=="boolean"?{includePostsPage:r.includePostsPage}:{},...typeof r.includeSitemapChain=="boolean"?{includeSitemapChain:r.includeSitemapChain}:{}}}function lt(t){let e=t&&typeof t=="object"?t:{},r=Array.isArray(e.rules)?e.rules.map((n,o)=>cr(n,o)).filter(n=>!!n):[];return {enabled:e.enabled===true,timezone:typeof e.timezone=="string"&&e.timezone.trim()!==""?e.timezone.trim():"UTC",rules:r}}function ur(t){let e=t&&typeof t=="object"?t:{},r=e.render&&typeof e.render=="object"?e.render:{},n=Number(r.concurrency??0),o=Number(r.batchSize??0),s=Number(r.maxAttempts??0),a=e.rewrite&&typeof e.rewrite=="object"?e.rewrite:{},i=e.deploy&&typeof e.deploy=="object"?e.deploy:{},l=(u,c)=>({enabled:typeof u.enabled=="boolean"?u.enabled:r.enabled===true,concurrency:Math.min(100,Math.max(1,Number(u.concurrency||c.concurrency))),batchSize:Math.min(500,Math.max(1,Number(u.batchSize||c.batchSize))),maxAttempts:Math.min(5,Math.max(1,Number(u.maxAttempts||2)))});return {render:{enabled:r.enabled===true,...Number.isInteger(n)&&n>0?{concurrency:n}:{},batchSize:Number.isInteger(o)&&o>0?Math.min(20,o):5,...Number.isInteger(s)&&s>0?{maxAttempts:Math.min(5,s)}:{}},rewrite:l(a,{concurrency:8,batchSize:25}),deploy:l(i,{concurrency:8,batchSize:50})}}function pr(t){if(!t||typeof t!="object")return;let e=t,r={};for(let o of ["accountId","siteId"]){let s=e[o];typeof s=="string"&&s.trim()!==""&&(r[o]=s.trim());}let n=Number(e.lastUpdate??0);return Number.isFinite(n)&&n>0&&(r.lastUpdate=Math.floor(n)),e.subscriber===true&&(r.subscriber=true),Object.keys(r).length>0?r:void 0}function ze(t){let e=t&&typeof t=="object"?t:{},r=String(e.accountId??"").trim(),n=String(e.siteId??"").trim(),o=e.subscriber===true,s=pr(e.siteSettings),a={...s??{},...r?{accountId:s?.accountId??r}:{},...n?{siteId:s?.siteId??n}:{},...s?.subscriber===true||o?{subscriber:true}:{}},i={},l=String(e.apiBase??"").trim();l&&(i.apiBase=l);let u=String(e.runtimeToken??e.nonce??"").trim();u&&(i.runtimeToken=u);let c=String(e.virtualAssetBaseUrl??e.uploadUrl??"").trim();c&&(i.virtualAssetBaseUrl=c),Object.keys(a).length>0&&(i.siteSettings=a);let d=Be(e.subscriptionType);return d&&(i.subscriptionType=d),i}function dr(t){try{let e=new URL(t);globalThis.location=e;}catch{}}function ct(t){return typeof t=="string"?t:t instanceof URL?t.toString():t.url}function gr(t,e){let r=new Headers(t instanceof Request?t.headers:void 0);if(e?.headers)for(let[n,o]of new Headers(e.headers).entries())r.set(n,o);return r}async function ut(t,e,r=5){let n=new URL(ct(t)),o=String(e?.method??(t instanceof Request?t.method:"GET")).toUpperCase(),s=n.protocol==="http:"?sr:ir,a=gr(t,e);return await new Promise((i,l)=>{let u=s.request(n,{method:o,headers:Object.fromEntries(a.entries()),...n.protocol==="https:"?{rejectUnauthorized:false}:{}},c=>{let d=[];c.on("data",g=>{d.push(Buffer.isBuffer(g)?g:Buffer.from(g));}),c.on("error",l),c.on("end",()=>{let g=c.statusCode??0,f=c.headers.location;if(r>0&&f&&[301,302,303,307,308].includes(g)){i(ut(new URL(f,n),{method:g===303?"GET":o},r-1));return}let b=new Headers;for(let[y,R]of Object.entries(c.headers))Array.isArray(R)?b.set(y,R.join(", ")):typeof R=="string"&&b.set(y,R);i(new Response(Buffer.concat(d),{status:g,statusText:c.statusMessage??"",headers:b}));});});u.on("error",l),u.end();})}function mr(t){let e=ze(t.wpsuite),r={...e.siteSettings??{},...e.siteSettings?.subscriber===true||e.subscriptionType==="PROFESSIONAL"||e.subscriptionType==="AGENCY"?{subscriber:true}:{}},n=String(r.accountId??"").trim(),o=String(r.siteId??"").trim(),s=String(e.virtualAssetBaseUrl??e.uploadUrl??"").trim();if(t.wpsuite={...e.apiBase?{apiBase:e.apiBase}:{},...e.runtimeToken?{runtimeToken:e.runtimeToken}:{},...s?{virtualAssetBaseUrl:s}:{},...Object.keys(r).length>0?{siteSettings:r}:{},...e.subscriptionType?{subscriptionType:e.subscriptionType}:{}},!n||!o||!s)return false;dr(t.sourceOrigin);let a=globalThis,l={...a.WpSuite??{},siteSettings:r,uploadUrl:s};return e.apiBase&&(l.apiBase=e.apiBase),a.WpSuite=l,true}async function fr(t){let e=String(t.wpsuite?.virtualAssetBaseUrl??t.wpsuite?.uploadUrl??"").trim();if(!mr(t)){let o=t.wpsuite?.siteSettings,s=[String(o?.accountId??"").trim()?"":"accountId",String(o?.siteId??"").trim()?"":"siteId",e?"":"virtualAssetBaseUrl"].filter(Boolean);return {remote:null,diagnostic:{status:"invalid-runtime",virtualAssetBaseUrl:e,subscriptionType:null,error:`Missing WP Suite runtime field(s): ${s.join(", ")}.`,requests:[]}}}let r=globalThis.fetch,n=[];try{typeof r=="function"&&/^https?:\/\//i.test(e)&&(globalThis.fetch=(async(l,u)=>{let c=ct(l);if(c.startsWith(e)){let d=(()=>{try{return new URL(c).pathname}catch{return c}})();try{let g=t.ignoreHttpsErrors&&c.startsWith("https://")?await ut(l,u):await r(l,u);return n.push({path:d,status:g.status,ok:g.ok,error:null}),g}catch(g){throw n.push({path:d,status:null,ok:!1,error:g instanceof Error?g.message:String(g)}),g}}return r(l,u)}));let{getConfig:o}=await import('@smart-cloud/wpsuite-core'),s=await o("publisher"),a=s&&typeof s=="object"?s:null,i=Be(a?.subscriptionType);return {remote:a,diagnostic:{status:a?"loaded":"unavailable",virtualAssetBaseUrl:e,subscriptionType:i??null,error:a?null:"WP Suite publisher config loader returned no configuration.",requests:n}}}catch(o){return {remote:null,diagnostic:{status:"unavailable",virtualAssetBaseUrl:e,subscriptionType:null,error:o instanceof Error?o.message:String(o),requests:n}}}finally{typeof r=="function"&&(globalThis.fetch=r);}}function hr(t,e){let r=lr(e?.deploymentProfiles),n=String(e?.defaultDeploymentProfile??"").trim(),o=r[n]?n:"",s=Be(e?.subscriptionType),a=ze(t.wpsuite);return {...t,scheduler:lt(e?.scheduler),deploymentProfiles:r,defaultDeploymentProfile:o,...s?{subscriptionType:s}:{},wpsuite:{...a,...a.siteSettings||s?{siteSettings:{...a.siteSettings??{},...a.siteSettings?.subscriber===true||s==="PROFESSIONAL"||s==="AGENCY"?{subscriber:true}:{}}}:{},...s?{subscriptionType:s}:{}}}}function Ve(t,e){let n=String(t||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!n)return e;let o=n.split("/").map(s=>s.trim()).filter(s=>s.length>0&&s!=="."&&s!=="..");return o.length>0?o.join("/"):e}function yr(){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return t.trim()?I.resolve(t):""}function it(t,e,r){let n=String(e||"").trim();return n&&I.isAbsolute(n)?I.resolve(n):I.resolve(t,Ve(n,r))}async function Ee(t,e={}){let r=String("").trim()||process.env.PUBLISHER_CONFIG||"publisher.config.json",n=await O.readFile(r,"utf8"),o=JSON.parse(n);o.sourceOrigin=o.sourceOrigin.replace(/\/$/,""),o.targetOrigin=at(o.targetOrigin),o.ignoreHttpsErrors??=false,o.outputDir=String(o.outputDir||"export").trim()||"export",o.urlRewriteMode||=o.targetOrigin==="."?"relative":"absolute",o.noJavaScriptRenderPathPrefixes||=[],o.seedPaths||=[],o.generated404RequestPath=ar(o.generated404RequestPath),o.sitemapPaths||=[...st],o.allowedAssetHosts||=[],o.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],o.blockedPathPrefixes||=[],o.blockedSearchFragments||=[],o.pageCache={purgeBeforeCrawl:o.pageCache?.purgeBeforeCrawl===true};let s=Number(o.processingConcurrency)>0?Math.min(100,Math.max(1,Number(o.processingConcurrency))):null;o.concurrency=s??o.concurrency??1,o.maxPages||=0,o.extraReplacements=Ue(o.extraReplacements),o.postCrawlCopyMap=Ue(o.postCrawlCopyMap),o.logDir=String(o.logDir||"logs").trim()||"logs",o.verbose??=false,o.logLevel||=o.verbose?"debug":"info",o.s3SyncMode||="sdk-upload-delete",o.readiness||={waitForSelector:null,waitForFunction:null,timeoutMs:1500,fallbackWaitMs:1500},o.readiness.timeoutMs??=1500,o.readiness.fallbackWaitMs??=1500,o.viewport||={width:1440,height:1200},o.navigationTimeoutMs||=3e4,o.assetDownloadConcurrency=s??(Number(o.assetDownloadConcurrency)>0?Number(o.assetDownloadConcurrency):o.concurrency),o.rewriteConcurrency=s??(Number(o.rewriteConcurrency)>0?Number(o.rewriteConcurrency):o.assetDownloadConcurrency),o.wpsuite=ze(o.wpsuite),o.scheduler=lt(void 0),o.remoteWorkers=ur(o.remoteWorkers),typeof o.lambdaDelegationEnabled=="boolean"&&(o.remoteWorkers.render??={},o.remoteWorkers.rewrite??={},o.remoteWorkers.deploy??={},o.remoteWorkers.render.enabled=o.lambdaDelegationEnabled,o.remoteWorkers.rewrite.enabled=o.lambdaDelegationEnabled,o.remoteWorkers.deploy.enabled=o.lambdaDelegationEnabled),s!==null&&(o.processingConcurrency=s,o.remoteWorkers.render??={},o.remoteWorkers.rewrite??={},o.remoteWorkers.deploy??={},o.remoteWorkers.render.concurrency=s,o.remoteWorkers.rewrite.concurrency=s,o.remoteWorkers.deploy.concurrency=s),o.deploymentProfiles={},o.defaultDeploymentProfile="",o.deploymentTargetOverride=String(o.deploymentTargetOverride??"").trim();let a=await fr(o);e.onRemotePublisherConfigDiagnostic?.(a.diagnostic);let i=hr(o,a.remote),l=yr(),u=l?I.resolve(l,".."):"";return u?(i.outputDir=it(u,i.outputDir,"export"),i.logDir=it(u,i.logDir,"logs")):(I.isAbsolute(i.outputDir)||(i.outputDir=Ve(i.outputDir,"export")),I.isAbsolute(i.logDir)||(i.logDir=Ve(i.logDir,"logs"))),i}function wr(t){let e=t/6e4;if(Number.isInteger(e)&&e>=1)return `${e} minute${e===1?"":"s"}`;let r=Math.ceil(t/1e3);return `${r} second${r===1?"":"s"}`}async function Z(t,e,r){let n=new AbortController,o=globalThis.setTimeout(()=>{n.abort(new Error(`${t} timed out after ${wr(e)}.`));},e);try{return await r({abortController:n,httpOptions:{abortSignal:n.signal,requestTimeout:e}})}finally{globalThis.clearTimeout(o);}}var br=".deploy-plan.json",Rr="deploy-plan.json",kr=".crawl-incomplete.json",Pr="crawl-incomplete.json";function pt(){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return t.trim()?I.resolve(t):""}function Sr(t){let e=String(t||"").replace(/\\/g,"/").replace(/^\/+/,"").trim(),r=I.posix.normalize(e);return !e||!r||r==="."||/^[a-zA-Z]:/.test(r)||r.startsWith("../")||r===".."?null:r}function xr(t){let e=String(t||"").trim();if(!e.startsWith("/")||e.startsWith("//")||e.includes("*")||e.includes("#"))return null;try{let r=new URL(e,"https://content-sync.invalid");return r.origin!=="https://content-sync.invalid"?null:`${I.posix.normalize(r.pathname)}${r.search}`}catch{return null}}function G(t){return [...new Set(t.map(Sr).filter(e=>e!==null))]}function vr(t,e){let r={generatedAt:String(e.generatedAt||new Date().toISOString()),outputDir:I.resolve(t.outputDir),runMode:e.runMode,crawlMode:e.crawlMode,fullSyncRequired:!!e.fullSyncRequired,changedFiles:G(e.changedFiles||[]),deletedFiles:G(e.deletedFiles||[]),rewriteTargets:G(e.rewriteTargets||[]),revalidateFiles:G(e.revalidateFiles||[])};return e.schemaVersion===2?{...r,schemaVersion:2,runMode:"content-sync",crawlMode:"incremental",fullSyncRequired:false,consumerId:String(e.consumerId||"").trim(),fromSequence:Math.max(0,Number(e.fromSequence)||0),toSequence:Math.max(0,Number(e.toSequence)||0),impactHash:String(e.impactHash||"").trim(),resolvedSitemapUrls:[...new Set((e.resolvedSitemapUrls||[]).map(n=>String(n||"").trim()).filter(n=>{try{let o=new URL(n);return o.protocol==="http:"||o.protocol==="https:"}catch{return false}}))],uploadGroups:{assets:G(e.uploadGroups?.assets||[]),content:G(e.uploadGroups?.content||[]),listings:G(e.uploadGroups?.listings||[]),resources:G(e.uploadGroups?.resources||[]),sitemapLeaves:G(e.uploadGroups?.sitemapLeaves||[]),sitemapIndexes:G(e.uploadGroups?.sitemapIndexes||[])},invalidationPaths:[...new Set((e.invalidationPaths||[]).map(xr).filter(n=>n!==null))].sort()}:{schemaVersion:1,...r,runMode:e.runMode}}function Er(t){if(!t||typeof t!="object")return false;let e=t;if(e.schemaVersion===2){let r=e;return r.runMode==="content-sync"&&r.crawlMode==="incremental"&&r.fullSyncRequired===false&&typeof r.generatedAt=="string"&&typeof r.outputDir=="string"&&typeof r.consumerId=="string"&&r.consumerId.trim()!==""&&Number.isSafeInteger(r.fromSequence)&&Number.isSafeInteger(r.toSequence)&&Number(r.toSequence)>=Number(r.fromSequence)&&typeof r.impactHash=="string"&&/^[a-f0-9]{64}$/.test(r.impactHash)&&Array.isArray(r.resolvedSitemapUrls)&&Array.isArray(r.changedFiles)&&Array.isArray(r.deletedFiles)&&Array.isArray(r.rewriteTargets)&&(r.revalidateFiles===void 0||Array.isArray(r.revalidateFiles))&&!!r.uploadGroups&&Array.isArray(r.uploadGroups.assets)&&Array.isArray(r.uploadGroups.content)&&Array.isArray(r.uploadGroups.listings)&&Array.isArray(r.uploadGroups.resources)&&Array.isArray(r.uploadGroups.sitemapLeaves)&&Array.isArray(r.uploadGroups.sitemapIndexes)&&Array.isArray(r.invalidationPaths)}return e.schemaVersion===1&&typeof e.generatedAt=="string"&&typeof e.outputDir=="string"&&(e.runMode==="full"||e.runMode==="retry-timeouts"||e.runMode==="single-url")&&(e.crawlMode==="full"||e.crawlMode==="incremental")&&typeof e.fullSyncRequired=="boolean"&&Array.isArray(e.changedFiles)&&Array.isArray(e.deletedFiles)&&Array.isArray(e.rewriteTargets)&&(e.revalidateFiles===void 0||Array.isArray(e.revalidateFiles))}function dt(t){let e=I.join(I.resolve(t.outputDir),br),r=pt();return r?[I.join(r,Rr),e]:[e]}function Ir(t){let e=I.join(I.resolve(t.outputDir),kr),r=pt();return r?[I.join(r,Pr),e]:[e]}async function gt(t){let e=I.resolve(t.outputDir);for(let r of dt(t))try{let n=await O.readFile(r,"utf8"),o=JSON.parse(n);if(!Er(o)||I.resolve(o.outputDir)!==e)continue;return vr(t,o)}catch{}return null}async function Ie(t){for(let e of dt(t))try{await O.unlink(e);}catch(r){if(r.code!=="ENOENT")throw r}}async function mt(t){let e=I.resolve(t.outputDir);for(let r of Ir(t)){let n;try{n=await O.readFile(r,"utf8");}catch(s){if(s.code==="ENOENT")continue;throw s}let o;try{o=JSON.parse(n);}catch{throw new Error(`Invalid incomplete crawl marker: ${r}`)}if(o.schemaVersion!==1||typeof o.startedAt!="string"||typeof o.outputDir!="string"||I.resolve(o.outputDir)!==e)throw new Error(`Invalid incomplete crawl marker: ${r}`);return {schemaVersion:1,startedAt:o.startedAt,outputDir:e}}return null}function Cr(t){return typeof t.subscriptionType=="string"&&t.subscriptionType.trim()!==""}function ft(t){let e="";for(let n=0;n<t.length;n++){let o=t[n];if(o==="--profile"){let s=(t[n+1]||"").trim();if(!s)throw new Error("Missing value for --profile.");e=s,n+=1;}else if(o.startsWith("--profile=")){let s=o.slice(10).trim();if(!s)throw new Error("Missing value for --profile.");e=s;}}let r=String(process.env.PUBLISHER_DEPLOY_PROFILE||process.env.PUBLISHER_DEPLOYMENT_PROFILE||"").trim();return e||r||null}function $r(t,e){return {...t,...e??{}}}function Tr(t,e){return {...t,...e??{},invalidationPaths:[...(e?.invalidationPaths??t.invalidationPaths)||[]]}}function ht(t,e){let r=String(e??t.deploymentTargetOverride??"").trim();if(!Cr(t)){if(r)throw new Error(`Deployment target "${r}" requires an active WPSuite subscription and remote publisher config.`);return {name:null,profile:null,config:t}}let n=String(r||t.defaultDeploymentProfile||"").trim();if(!n)return {name:null,profile:null,config:t};let o=t.deploymentProfiles?.[n];if(!o)throw new Error(`Unknown deployment profile "${n}". Check the linked WPSuite publisher configuration.`);return {name:n,profile:o,config:{...t,targetOrigin:o.targetOrigin??t.targetOrigin,s3:$r(t.s3,o.s3),cloudFront:Tr(t.cloudFront,o.cloudFront)}}}var yt={error:0,warn:1,info:2,debug:3},jr=/^(?:authorization|proxyAuthorization|runtimeToken|siteKey|nonce|accessToken|refreshToken|accessKeyId|secretAccessKey|sessionToken|xStaticPublisherToken|xApiKey)$/i;function ke(t){return t.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 $e(t){return typeof t=="string"?ke(t):Array.isArray(t)?t.map(e=>$e(e)):t instanceof Error?{name:t.name,message:ke(t.message),...t.stack?{stack:ke(t.stack)}:{}}:t&&typeof t=="object"?Object.fromEntries(Object.entries(t).map(([e,r])=>[e,jr.test(e)?"[REDACTED]":$e(r)])):t}function kt(t){return t?$e(t):void 0}var wt=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",Ce=wt?I.join(wt,"current-progress.json"):"",bt=Promise.resolve();function Rt(t){return t.includes("crawl")?"crawl":t.includes("deploy")?"deploy":t.includes("invalidate")?"invalidate":t}function Or(t,e){let r={...t},n=typeof t.phase=="string"?t.phase.trim():"",o=typeof e.phase=="string"?e.phase.trim():"";if(o!==""&&(o==="deploy"||o.startsWith("deploy-"))&&n!==o)for(let i of ["index","totalFiles","staged","uploaded","skipped","failed","deleted","workerCount","completedBatches","totalBatches"])delete r[i];let a=new Set(["pagesQueued","pagesRendered","assetsQueued","sitemapsQueued","pagesDiscovered","assetsDiscovered","sitemapsDiscovered","pagesSaved","assetsSaved","donePages","doneAssets","doneSitemaps","changedTextFiles","uploaded","failed","index","totalFiles","completedBatches","totalBatches","pageQueue","assetQueue","sitemapQueue"]);for(let[i,l]of Object.entries(e)){let u=r[i];if(typeof u=="number"&&typeof l=="number"&&a.has(i)){r[i]=Math.max(u,l);continue}r[i]=l;}return r}function Mr(t,e,r){Ce&&(bt=bt.then(async()=>{let n=new Date,o=n.toISOString();await O.mkdir(I.dirname(Ce),{recursive:true});let s=await O.readFile(Ce,"utf8").then(S=>JSON.parse(S)).catch(()=>null),a=s&&typeof s.details=="object"&&s.details?s.details:{},i=Rt(t),l=s?.currentStep||Rt(s?.source||""),u=s?.startedAt||o,c={...s?.stepDurationsSec??{}},d=s?.stepStartedAt||o;if(l&&l!==i&&s?.stepStartedAt){let S=Math.max(0,Math.round((n.getTime()-new Date(s.stepStartedAt).getTime())/1e3));c[l]=(c[l]??0)+S,d=o;}let g=Math.max(0,Math.round((n.getTime()-new Date(d).getTime())/1e3)),f=Math.max(0,Math.round((n.getTime()-new Date(u).getTime())/1e3)),b=ke(e),y=kt(r)??{},R={checkedAt:o,source:t,message:b,details:Or(a,y),startedAt:u,currentStep:i,stepStartedAt:d,stepElapsedSec:g,totalElapsedSec:f,stepDurationsSec:c};await O.writeFile(Ce,JSON.stringify(R,null,2),"utf8");}).catch(()=>{}));}async function Ar(t,e){await O.mkdir(I.dirname(t),{recursive:true}),await O.appendFile(t,`${JSON.stringify($e(e))}
|
|
2
|
+
`,"utf8");}var we=class{constructor(e,r,n="info"){this.logDir=e;this.logFile=r;this.level=n;this.ensureLogFileReady();}logDir;logFile;level;startedAt=Date.now();marks=new Map;initPromise=null;writeQueue=Promise.resolve();writeError=null;get logPath(){return I.join(this.logDir,this.logFile)}artifactPath(e){return this.logFile.endsWith(".log.jsonl")?I.join(this.logDir,this.logFile.replace(/\.log\.jsonl$/u,`${e}.jsonl`)):I.join(this.logDir,`${this.logFile}${e}.jsonl`)}get errorsPath(){return this.artifactPath(".errors")}get rejectedPath(){return this.artifactPath(".rejected")}ensureLogFileReady(){return this.initPromise||(this.initPromise=(async()=>{await O.mkdir(this.logDir,{recursive:true}),await O.writeFile(this.logPath,"","utf8");})()),this.initPromise}enqueueTask(e){this.writeQueue=this.writeQueue.then(e).catch(r=>{this.writeError=r instanceof Error?r:new Error(String(r));});}enqueueLine(e){this.enqueueTask(async()=>{await this.ensureLogFileReady(),await O.appendFile(this.logPath,`${e}
|
|
3
|
+
`,"utf8");});}enqueueJsonLine(e,r){this.enqueueTask(()=>Ar(e,r));}accepts(e){return yt[e]<=yt[this.level]}push(e,r,n){if(!this.accepts(e))return;let o=ke(r),s=kt(n),a=JSON.stringify({time:new Date().toISOString(),level:e,message:o,...s||{}});this.enqueueLine(a),e==="error"?console.error(`[ERROR] ${o}`,s?JSON.stringify(s):""):e==="warn"?console.warn(`[WARN] ${o}`,s?JSON.stringify(s):""):console.log(`[${e.toUpperCase().padEnd(5)}] ${o}`);}info(e,r){this.push("info",e,r);}progress(e,r){Mr(this.logFile,e,r);}debug(e,r){this.push("debug",e,r);}warn(e,r){this.push("warn",e,r);}reject(e,r,n,o,s){let a={kind:e,url:r,reason:n,...o?{source:o}:{},...s||{}};this.enqueueJsonLine(this.rejectedPath,a),this.accepts("debug")&&this.push("debug",`Rejected ${e} ${r}: ${n}`,a);}error(e,r){this.enqueueJsonLine(this.errorsPath,{message:e,...r||{}}),this.push("error",e,r);}mark(e){this.marks.set(e,Date.now());}endMark(e,r){let n=this.marks.get(e);if(!n)return;let o=Date.now()-n,s=Number((o/1e3).toFixed(2));this.push("info",`Timing ${e}: ${s}s`,{name:e,ms:o,seconds:s,...r||{}});}async flush(){let e=Date.now()-this.startedAt,r=Number((e/1e3).toFixed(2));if(this.push("info",`Total time: ${r}s`,{name:"total",ms:e,seconds:r}),await this.writeQueue,this.writeError)throw this.writeError}};async function Wr(t){await O.mkdir(I.dirname(t),{recursive:true});}async function Se(t,e,r){await Wr(t);let n=I.join(I.dirname(t),`.${I.basename(t)}.${process.pid}.${Date.now()}.${Dr.randomBytes(6).toString("hex")}.tmp`);try{typeof e=="string"?await O.writeFile(n,e,r??"utf8"):await O.writeFile(n,e),await O.rename(n,t);}catch(o){throw await O.unlink(n).catch(()=>{}),o}}function xt(t){return [".html",".htm",".css",".js",".mjs",".json",".xml",".xsl",".txt",".svg",".map",".enc",".jws"].includes(I.extname(t).toLowerCase())}function vt(t){return t.replace(/"/g,'"').replace(/"/g,'"').replace(/'/g,"'").replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function be(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function Te(t){return t.replace(/\//g,"\\/")}function Pt(t){return t.replace(/\//g,"\\\\/")}function Lr(t){try{let e=new URL(t);if(e.protocol!=="http:"&&e.protocol!=="https:")return null;let r=e.pathname==="/"&&!e.search&&!e.hash?"":`${e.pathname}${e.search}${e.hash}`;return `//${e.host}${r}`}catch{return null}}function St(t,e,r){if(!e)return;t[e]=r;let n=Te(e),o=Te(r);t[n]=o;let s=Pt(e),a=Pt(r);t[s]=a;let i=be(e),l=be(r);t[i]=l;let u=be(n),c=be(o);t[u]=c;let d=be(s),g=be(a);t[d]=g;}function je(t,e,r){St(t,e,r);let n=Lr(e);n&&n!==e&&St(t,n,r);}function Et(t,e){try{return new URL(t,e==="."?"https://relative.invalid":e).pathname}catch{return t.startsWith("/")?t:`/${t.replace(/^\.\//,"")}`}}function It(t,e,r){if(!e)return r;let n=I.dirname(I.resolve(e)),o=I.resolve(t,r.replace(/^\/+/,"")),s=I.relative(n,o).replace(/\\/g,"/");return s?(s.startsWith(".")||(s=`./${s}`),s):"."}async function Ge(t,e){return (e?[...new Set(e)].map(n=>I.resolve(n)).filter(n=>n.startsWith(I.resolve(t.outputDir))).map(n=>I.relative(t.outputDir,n).replace(/\\/g,"/")).filter(n=>n.length>0):await Fr(["**/*"],{cwd:t.outputDir,onlyFiles:true,dot:true})).filter(n=>n!=="asset-map.json"&&xt(n))}var Ur=["wp-content/","wp-includes/","wp-admin/","wp-json/","_next/"],Vr=new Set([".html",".htm"]),Ct="WPSuite.io Static Publisher",Br=Ct.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function zr(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function qr(t){return t.startsWith("//")||t.startsWith("\\/\\/")||t.startsWith("\\\\/\\\\/")}function Hr(t,e,r){return qr(e)?t.replace(new RegExp(`(?<!:)${zr(e)}`,"g"),r):t.split(e).join(r)}function Jr(t,e,r){if(t.wpsuite?.siteSettings?.subscriber===true||t.wpsuite?.subscriptionType==="PROFESSIONAL"||t.wpsuite?.subscriptionType==="AGENCY"||!r)return false;let o=I.extname(r).toLowerCase();return Vr.has(o)?/<head\b|<html\b|<!doctype html/i.test(e):false}function Gr(t){if(new RegExp(`<meta\\b(?=[^>]*\\bname=(["'])generator\\1)(?=[^>]*\\bcontent=(["'])${Br}\\2)[^>]*\\/?>`,"i").test(t))return t;let e=`<meta name="generator" content="${Ct}" />`;if(t.match(/(\r?\n)([ \t]*)<\/head>/i))return t.replace(/(\r?\n)([ \t]*)<\/head>/i,`$1$2${e}$1$2</head>`);let n=t.includes(`\r
|
|
4
4
|
`)?`\r
|
|
5
5
|
`:`
|
|
6
|
-
`;return t.replace(/<head\b[^>]*>/i,o=>`${o}${n} ${e}`)}function Qr(t){let e=
|
|
7
|
-
`)).slice(0,16)}`,"taskId"),
|
|
8
|
-
`)).slice(0,16)}`,"taskId");try{let S=await n.client.invoke({schemaVersion:K,operation:"rewrite",jobId:a,taskId:C,configKey:l,assetMapKey:u,items:P.map(I=>({inputKey:I.object.key,outputKey:I.object.key,relativePath:I.relativePath,contentType:I.contentType||I.object.contentType}))});k=Mt(await n.client.readResult(S),S);break}catch(S){f=S;}}if(!k)throw new Error(`Remote object rewrite batch ${y+1}/${p.length} failed: ${f instanceof Error?f.message:String(f)}`,{cause:f});for(let b of P){let C=k.detail.objects.find(S=>S.outputKey===b.object.key);if(!C)throw new Error(`Remote rewrite result omitted ${b.relativePath}.`);b.object=C.output,C.changed&&(w+=1),R+=1,await n.onProgress?.({index:R,totalFiles:s.length,changedTextFiles:w,file:b.relativePath,changed:C.changed});}}})),e.assetMap={...r},e.generatedAt=new Date().toISOString(),w}function W(t,e,{optional:r=false}={}){if(!(r&&(t==null||t===""))){if(typeof t!="string"||!t.trim())throw new Error(`${e} must be a non-empty string.`);return t.trim()}}function yn(t){if(!t||typeof t!="object")throw new Error("Remote worker config must be a JSON object.");let e=t;if(e.schemaVersion!==1)throw new Error(`Unsupported remote worker config version: ${String(e.schemaVersion)}.`);if(e.protocolVersion!==K)throw new Error(`Remote worker protocol mismatch: expected ${K}, received ${String(e.protocolVersion)}.`);let r=e.workspace,n=e.functions;if(!r||!n)throw new Error("Remote worker config requires workspace and functions objects.");return {schemaVersion:1,region:W(e.region,"region"),...W(e.roleArn,"roleArn",{optional:true})?{roleArn:W(e.roleArn,"roleArn")}:{},...W(e.roleSessionName,"roleSessionName",{optional:true})?{roleSessionName:W(e.roleSessionName,"roleSessionName")}:{},workspace:{bucket:W(r.bucket,"workspace.bucket"),prefix:String(r.prefix??"")},...e.status&&typeof e.status=="object"?{status:{tableName:W(e.status.tableName,"status.tableName")}}:{},functions:{render:W(n.render,"functions.render"),...W(n.asset,"functions.asset",{optional:true})?{asset:W(n.asset,"functions.asset")}:{},rewrite:W(n.rewrite,"functions.rewrite"),"deploy-copy":W(n["deploy-copy"],"functions.deploy-copy")},targets:Array.isArray(e.targets)?e.targets.map((o,s)=>{if(!o||typeof o!="object")throw new Error(`targets[${s}] must be an object.`);let a=o;return {id:W(a.id,`targets[${s}].id`),bucketName:W(a.bucketName,`targets[${s}].bucketName`),prefix:String(a.prefix??""),region:W(a.region,`targets[${s}].region`)}}):[],protocolVersion:K}}async function Ft(t){let e=v.resolve(t);try{return yn(JSON.parse(await readFile(e,"utf8")))}catch(r){throw new Error(`Unable to load remote worker config ${e}: ${r instanceof Error?r.message:String(r)}`,{cause:r})}}var je=class{config;lambda;s3;dynamodb;#e;constructor(e,r={},n={}){this.config=e;let o=e.roleArn?fromTemporaryCredentials({params:{RoleArn:e.roleArn,RoleSessionName:e.roleSessionName??"publisher-exporter-remote-worker"},clientConfig:{region:e.region}}):void 0;this.lambda=new LambdaClient({region:e.region,...o?{credentials:o}:{},...r}),this.s3=new S3Client({region:e.region,...o?{credentials:o}:{}}),this.dynamodb=e.status?new DynamoDBClient({region:e.region,...o?{credentials:o}:{}}):null,this.#e=n;}async#t(e){if(!this.dynamodb||!this.config.status)return null;let n=(await this.dynamodb.send(new GetItemCommand({TableName:this.config.status.tableName,ConsistentRead:true,Key:{jobId:{S:e.jobId},taskId:{S:e.taskId}}}))).Item;if(!n)return null;let o=n.operation?.S,s=n.status?.S;return !o||!["render","asset","rewrite","deploy-copy"].includes(o)||!s||!["running","succeeded","partial","failed"].includes(s)?null:{jobId:n.jobId?.S??e.jobId,taskId:n.taskId?.S??e.taskId,operation:o,status:s,completedItems:Number(n.completedItems?.N??0),failedItems:Number(n.failedItems?.N??0),totalItems:Number(n.totalItems?.N??0),sequence:Number(n.sequence?.N??0),updatedAt:n.updatedAt?.S??new Date(0).toISOString(),requestId:n.requestId?.S??null}}async#r(e,r){let n=this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify(e),"utf8")}));if(e.operation==="health"||!this.dynamodb||!this.#e.onProgress)return await n;let o=false,s=n.finally(()=>{o=true;}),a=Math.max(500,Math.min(3e4,this.#e.progressPollIntervalMs??2e3)),i=-1;for(;!o;){await Promise.race([s.then(()=>{},()=>{}),new Promise(l=>setTimeout(l,a))]);try{let l=await this.#t(e);l&&l.sequence>i&&(i=l.sequence,await this.#e.onProgress(l));}catch(l){await this.#e.onProgressError?.(l instanceof Error?l:new Error(String(l)));}}return await s}async invoke(e){let r=e.operation==="health"?this.config.functions.render:this.config.functions[e.operation];if(!r)throw new Error(`Remote worker configuration does not provide a ${e.operation} function. Redeploy the Lambda workers and reinstall remote-workers.json.`);let n=await this.#r(e,r),o=n.Payload?JSON.parse(new TextDecoder().decode(n.Payload)):null;if(n.FunctionError)throw new Error(`Remote ${e.operation} worker failed (${n.FunctionError}): ${JSON.stringify(o)}`);if(!o||typeof o!="object")throw new Error(`Remote ${e.operation} worker returned no JSON response.`);let s=o;if(s.schemaVersion!==K||s.operation!==e.operation||s.jobId!==e.jobId||s.taskId!==e.taskId)throw new Error(`Remote ${e.operation} worker returned a mismatched response.`);return s}async readResult(e){if(!e.resultKey)throw new Error(`Remote ${e.operation} response does not contain a resultKey.`);let r=oe(e.resultKey,this.config.workspace.prefix),n=await this.s3.send(new GetObjectCommand({Bucket:this.config.workspace.bucket,Key:r}));if(!n.Body)throw new Error(`Remote worker result has no body: ${r}`);return JSON.parse(await n.Body.transformToString("utf8"))}async readObject(e){if(e.bucket!==this.config.workspace.bucket)throw new Error(`Remote worker object bucket mismatch: ${e.bucket}.`);let r=oe(e.key,this.config.workspace.prefix),n=await this.s3.send(new GetObjectCommand({Bucket:this.config.workspace.bucket,Key:r,...e.versionId?{VersionId:e.versionId}:{}}));if(!n.Body)throw new Error(`Remote worker object has no body: ${r}`);let o=await n.Body.transformToByteArray();if(o.byteLength!==e.bytes)throw new Error(`Remote worker object length mismatch for ${r}: expected ${e.bytes}, received ${o.byteLength}.`);if(pe(o)!==e.sha256)throw new Error(`Remote worker object checksum mismatch for ${r}.`);return o}async readObjectText(e){return new TextDecoder("utf8",{fatal:true}).decode(await this.readObject(e))}async health(e){let r=this.config.functions[e];if(!r)throw new Error(`Remote worker configuration does not provide a ${e} function.`);let n=`${e}-${Date.now()}`,o=await this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify({schemaVersion:K,operation:"health",jobId:"health",taskId:n}),"utf8")})),s=o.Payload?JSON.parse(new TextDecoder().decode(o.Payload)):null;if(o.FunctionError||!s||typeof s!="object")throw new Error(`Remote ${e} health check failed: ${JSON.stringify(s)}`);return s}async writeWorkspaceObject(e){let r=oe(e.key,this.config.workspace.prefix),n=typeof e.body=="string"?Buffer.from(e.body,"utf8"):e.body,o=pe(n),s=await this.s3.send(new PutObjectCommand({Bucket:this.config.workspace.bucket,Key:r,Body:n,ContentType:e.contentType,...e.cacheControl?{CacheControl:e.cacheControl}:{},Metadata:{sha256:o,...e.metadata??{}}}));return {bucket:this.config.workspace.bucket,key:r,sha256:o,bytes:n.byteLength,contentType:e.contentType,...s.ETag?{etag:s.ETag}:{},...s.VersionId?{versionId:s.VersionId}:{}}}async copyWorkspaceObject(e,r){if(e.bucket!==this.config.workspace.bucket)throw new Error(`Remote worker object bucket mismatch: ${e.bucket}.`);let n=oe(e.key,this.config.workspace.prefix),o=oe(r,this.config.workspace.prefix),s=`${e.bucket}/${n.split("/").map(i=>encodeURIComponent(i)).join("/")}`,a=await this.s3.send(new CopyObjectCommand({Bucket:e.bucket,Key:o,CopySource:s,MetadataDirective:"COPY"}));return {...e,key:o,...a.CopyObjectResult?.ETag?{etag:a.CopyObjectResult.ETag}:{},...a.VersionId?{versionId:a.VersionId}:{}}}};var wn="remote-workers.json";function _t(t={}){let e=String(t.explicitPath??"").trim();if(e)return v.resolve(e);let r=String(t.runtimeDir??process.env.STATIC_PUBLISHER_RUNTIME_DIR??process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR??"").trim();return r?v.join(v.resolve(r),wn):""}function Rn(){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return t.trim()?v.resolve(t):""}function kn(t){let e=String(process.env.STATIC_PUBLISHER_REMOTE_EXPORT_MANIFEST_PATH||"").trim();if(e)return v.resolve(e);let r=Rn();if(r)return v.join(r,"remote-export-manifest.json");let n=v.resolve(t.outputDir);return v.join(v.dirname(n),`.${v.basename(n)}-remote-export-manifest.json`)}function Sn(t){let e=v.posix.normalize(String(t||"").replace(/\\/g,"/").replace(/^\/+/,""));if(!e||e==="."||e===".."||e.startsWith("../")||/^[A-Za-z]:/.test(e))throw new Error(`Invalid remote export relative path: ${t}`);return e}async function Nt(t){try{let e=JSON.parse(await M.readFile(kn(t),"utf8"));if(e.schemaVersion!==1||typeof e.jobId!="string"||!e.workspace||typeof e.workspace.bucket!="string"||typeof e.workspace.prefix!="string"||!e.objects||typeof e.objects!="object"||!e.assetMap||typeof e.assetMap!="object")return null;let r=e;for(let[n,o]of Object.entries(r.objects)){if(Sn(n),!o||o.relativePath!==n||o.object?.bucket!==r.workspace.bucket)return null;oe(o.object.key,r.workspace.prefix);}return r}catch{return null}}function Ge(t){return String(t??"").split(";").map(e=>e.trim().toLowerCase()).filter(Boolean).join(";")}var Bt="wpsuite-sha256",qt="wpsuite-normalized-sha256",Ze="public, max-age=0, must-revalidate",Tn=/(?:^|[-_:.])(id|uid|nonce|token|hash|instance)(?:$|[-_:.])/i,Xe=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,jn=["SIGINT","SIGTERM"],Ae=new Set,Oe=new Map,Kt=null;function On(t){Ae.add(t);let e=false;return ()=>{e||(e=true,Ae.delete(t));}}async function Mn(){let t=[...Ae];t.length!==0&&await Promise.allSettled(t.map(async e=>{Ae.delete(e),await M.rm(e,{recursive:true,force:true});}));}function An(){if(!(Oe.size>0))for(let t of jn){let e=()=>{Kt||(Kt=Mn().finally(()=>{for(let[r,n]of Oe)process.off(r,n);Oe.clear(),process.exit(1);}));};Oe.set(t,e),process.on(t,e);}}An();function Dn(t,e){let r=String(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH||"").trim();if(r)return v.resolve(r);let n=e.trim();return n?v.join(v.resolve(n),"crawl-manifest.json"):v.join(v.resolve(t),".crawl-manifest.json")}function ie(t){return v.normalize(t).split(v.sep).join("/")}function Ut(t,e){let r=v.relative(v.resolve(t),v.resolve(e));return !r||r.startsWith("..")||v.isAbsolute(r)?null:ie(r)}async function Ln(t,e,r){let n=Dn(t.outputDir,e),o;try{o=await M.readFile(n,"utf8");}catch(c){return c.code==="ENOENT"?(r.warn("Deploy rewrite guard disabled because the crawl manifest is missing.",{manifestPath:n,source:"deploy-guard"}),null):(r.warn("Deploy rewrite guard disabled because the crawl manifest could not be read.",{manifestPath:n,error:c instanceof Error?c.message:String(c),source:"deploy-guard"}),null)}let s;try{s=JSON.parse(o);}catch(c){return r.warn("Deploy rewrite guard disabled because the crawl manifest is invalid JSON.",{manifestPath:n,error:c instanceof Error?c.message:String(c),source:"deploy-guard"}),null}let a=new Map,i=new Map,l=0,u=0;for(let[c,p]of Object.entries(s.pages||{})){let d=String(p?.outputPath||"").trim(),m=d?Ut(t.outputDir,d):null;if(m){let R=typeof p?.contentType=="string"&&p.contentType?p.contentType:null;R&&i.set(m,R);}!d||p?.rewriteComplete===true||m&&(l++,a.has(m)||a.set(m,{kind:"page",sourceUrl:c,outputPath:v.resolve(d),relativePath:m}));}for(let[c,p]of Object.entries(s.assets||{})){let d=String(p?.outputPath||"").trim(),m=p?.isText===true,R=d?Ut(t.outputDir,d):null;if(R){let w=typeof p?.contentType=="string"&&p.contentType?p.contentType:null;w&&i.set(R,w);}!d||!m||p?.rewriteComplete===true||R&&(u++,a.has(R)||a.set(R,{kind:"asset",sourceUrl:c,outputPath:v.resolve(d),relativePath:R}));}return {manifestPath:n,byRelativePath:a,contentTypeByRelativePath:i,pendingPages:l,pendingTextAssets:u}}function Wn(t){return t&&(Xe.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)?"__hex__":/^[0-9]{8,}$/.test(t)?"__num__":/^(?=.*[a-z])(?=.*\d)[a-z0-9]{8,}$/i.test(t)?"__alnum__":t)}function Qe(t){return t.split(/([_:.\-/=?&#]+)/g).map((e,r)=>r%2===1?e:Wn(e)).join("")}function Fn(t){return t.split(/([_:.\-/=?&#]+)/g).map((e,r)=>r%2===1?e:Xe.test(e)?"__uuid__":/^[0-9a-f]{6,}$/i.test(e)?"__hex__":/^[0-9]{6,}$/.test(e)?"__num__":/^[a-z0-9_-]{6,}$/i.test(e)?"__id__":e).join("")}function De(t,e){return Array.isArray(t)?t.map(r=>De(r,e)):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).map(([r,n])=>[r,De(n,r)])):typeof t!="string"?t:e&&Tn.test(e)?Fn(t):Xe.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)||/^[0-9]{8,}$/.test(t)?Qe(t):t}function _n(t){return t.replace(/((?:https?:\/\/[^"'\s>]+|\/)(?:wp-content|wp-includes)\/[^"'\s>?]+)\?ver=[A-Za-z0-9._-]+(?=$|[#"'])/gi,"$1")}function Nn(t,e){let r=e.trim();if((r.startsWith("{")||r.startsWith("[")||r.startsWith('"'))&&t.startsWith("data-"))try{let o=JSON.parse(r);return JSON.stringify(De(o))}catch{}if(t.startsWith("data-")&&/^[A-Za-z0-9+/=]+$/.test(r))try{let o=Buffer.from(r,"base64").toString("utf8"),s=JSON.parse(o),a=JSON.stringify(De(s));return Buffer.from(a,"utf8").toString("base64")}catch{}return e}function Kn(t,e){let r=t.toLowerCase();return r==="class"?e.split(/(\s+)/).map((n,o)=>o%2===1?n:Qe(n)).join(""):r==="id"||r==="for"||r==="aria-controls"||r==="aria-labelledby"||r==="aria-describedby"||r==="aria-owns"||r==="aria-activedescendant"||r==="name"?Qe(e):r==="href"||r==="src"?_n(e):Nn(r,e)}function Un(t){return t.replace(/<([a-z][^\s/>]*)([^<>]*?)>/gi,(e,r,n)=>{if(r.startsWith("/"))return e;let o=n.replace(/\s([:@a-zA-Z_][-:.a-zA-Z0-9_]*?)=(['"])([\s\S]*?)\2/g,(s,a,i,l)=>{let u=Kn(a,l);return ` ${a}=${i}${u}${i}`});return `<${r}${o}>`})}function Re(t){let e=v.extname(t).toLowerCase();return [".html",".htm",".xml",".xsl",".txt"].includes(e)||["robots.txt","sitemap.xml"].includes(v.basename(t))}function Me(t,e){return [t.replace(/^\/+|\/+$/g,""),e.replace(/^\/+/,"")].filter(Boolean).join("/")}async function Vn(t,e,r,n){let o=new Map,s,a=0;do{a++;let i=await Y(`S3 list objects page ${a} for s3://${e}/${r||""}`,3e5,({httpOptions:l})=>t.send(new ListObjectsV2Command({Bucket:e,Prefix:r||void 0,ContinuationToken:s}),l));for(let l of i.Contents||[]){if(!l.Key)continue;let u=(l.ETag||"").replace(/^"|"$/g,"").toLowerCase(),c=Number(l.Size??0);o.set(l.Key,{etag:u,size:c,cacheControl:void 0,contentType:void 0});}s=i.NextContinuationToken,n.debug(`Listed S3 keys page ${a}: ${o.size} keys so far`);}while(s);return o}async function zn(t,e,r,n){if(n.has(r))return n.get(r)??null;try{let o=await Y(`S3 head object ${r}`,3e5,({httpOptions:a})=>t.send(new HeadObjectCommand({Bucket:e,Key:r}),a)),s={etag:(o.ETag||"").replace(/^"|"$/g,"").toLowerCase(),size:Number(o.ContentLength??0),cacheControl:o.CacheControl?.trim()||null,contentType:o.ContentType?.trim()||null};return n.set(r,s),s}catch{return n.set(r,null),null}}async function Bn(t,e,r,n){if(n.cacheControl!==void 0&&n.contentType!==void 0)return {cacheControl:n.cacheControl,contentType:n.contentType};try{let o=await Y(`S3 head cache metadata ${r}`,3e5,({httpOptions:s})=>t.send(new HeadObjectCommand({Bucket:e,Key:r}),s));n.cacheControl=o.CacheControl?.trim()||null,n.contentType=o.ContentType?.trim()||null;}catch{n.cacheControl=null,n.contentType=null;}return {cacheControl:n.cacheControl,contentType:n.contentType}}function Vt(t){return String(t||"").split(",").map(e=>e.trim().toLowerCase()).filter(Boolean).sort().join(",")}async function qn(t,e,r,n){let o=[...new Set(Array.from(r).filter(Boolean))];if(o.length===0)return n.info("No explicitly tombstoned S3 objects to delete."),[];n.info(`Deleting ${o.length} explicitly tombstoned S3 object(s)\u2026`);for(let s=0;s<o.length;s+=1e3){let a=o.slice(s,s+1e3);if(a.length===0)continue;let i=await Y(`S3 delete objects batch ${Math.floor(s/1e3)+1}`,3e5,({httpOptions:l})=>t.send(new DeleteObjectsCommand({Bucket:e,Delete:{Objects:a.map(u=>({Key:u}))}}),l));if(i.Errors&&i.Errors.length>0){let l=i.Errors.map(u=>`${u.Key||"(unknown)"}: ${u.Code||"DeleteFailed"}`);throw new Error(`S3 reported ${l.length} object deletion error(s): ${l.join(", ")}`)}n.info(`Deleted batch of ${a.length} object(s).`);for(let l of a)n.debug(` deleted: ${l}`);}return o}function Hn(t){return createHash("md5").update(t).digest("hex")}function ae(t){return createHash("sha256").update(t).digest("hex")}function Le(t){return createHash("sha256").update(Un(t.toString("utf8"))).digest("hex")}async function Jn(t,e,r,n){if(n.has(r))return n.get(r)??null;try{let a=((await Y(`S3 head object metadata ${r}`,3e5,({httpOptions:i})=>t.send(new HeadObjectCommand({Bucket:e,Key:r}),i))).Metadata?.[Bt]||"").trim().toLowerCase()||null;return n.set(r,a),a}catch{return n.set(r,null),null}}async function Gn(t,e,r,n,o){if(n.has(r))return n.get(r)??null;try{let a=((await Y(`S3 head object normalized metadata ${r}`,3e5,({httpOptions:i})=>t.send(new HeadObjectCommand({Bucket:e,Key:r}),i))).Metadata?.[qt]||"").trim().toLowerCase();if(a)return n.set(r,a),a}catch{return n.set(r,null),null}if(o.has(r)){let s=o.get(r)??null;return n.set(r,s),s}try{let a=await(await Y(`S3 get object ${r}`,3e5,({httpOptions:l})=>t.send(new GetObjectCommand({Bucket:e,Key:r}),l))).Body?.transformToByteArray(),i=a?Le(Buffer.from(a)):null;return o.set(r,i),n.set(r,i),i}catch{return o.set(r,null),n.set(r,null),null}}function Qn(t){return t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"profile"}function Yn(t,e){let r=t,n=Object.entries(e).sort((o,s)=>s[0].length-o[0].length);for(let[o,s]of n)o&&(r=r.split(o).join(s));return r}async function Zn(t,e,r,n){let o=v.join(t,"asset-map.json"),s;try{s=await M.readFile(o,"utf8");}catch(l){if(l.code==="ENOENT")return;throw l}let a=JSON.parse(s);if(!a||typeof a!="object")return;let i=Object.fromEntries(Object.entries(a).map(([l,u])=>{let c=String(u??"");return e.urlRewriteMode==="absolute"&&e.targetOrigin&&r.targetOrigin&&e.targetOrigin!==r.targetOrigin&&(c=c.split(e.targetOrigin).join(r.targetOrigin)),c=Yn(c,n),[l,c]}));await M.writeFile(o,JSON.stringify(i,null,2),"utf8");}async function Xn(t,e,r,n,o,s,a){let i=t.targetOrigin!==e.targetOrigin,l=Object.keys(n).length>0;if(!r||!i&&!l)return {outputDir:t.outputDir,cleanup:async()=>{}};if(i&&t.urlRewriteMode!=="absolute")throw new Error(`Deployment profile "${r}" changes targetOrigin, but the base crawl output must use urlRewriteMode "absolute" for multi-target redeploys.`);let u=v.join(v.dirname(t.outputDir),`.deploy-profile-${Qn(r)}-${Date.now()}`),c=On(u);o.info(`Preparing deployment profile "${r}" from existing crawl output to ${u}...`);try{if(await M.rm(u,{recursive:!0,force:!0}),s){await M.mkdir(u,{recursive:!0});for(let w of s){let y=v.join(t.outputDir,w),P=v.join(u,w);await M.mkdir(v.dirname(P),{recursive:!0}),await M.copyFile(y,P);}}else await M.cp(t.outputDir,u,{recursive:!0});let p={...t,sourceOrigin:t.targetOrigin,targetOrigin:e.targetOrigin,extraReplacements:n,outputDir:u},d=1;o.info(`Rewriting text files for deployment profile "${r}"...`);let m={files:s,onStart:({totalFiles:w,workerCount:y})=>{d=y,o.info(`Rewriting ${w} text file(s) for deployment profile "${r}" with ${y} worker(s).`);},onProgress:({index:w,totalFiles:y,changedTextFiles:P,file:k,changed:f})=>{let C=`Rewriting [${w}/${y}] ${k} (${f?"rewrote":"checked"}; ${P} changed so far)`;y<=200||w<=5||w%10===0||w===y?(o.progress(C,{file:k,index:w,totalFiles:y,changed:f,changedTextFiles:P,workerCount:d}),o.info(C)):o.debug(C);}},R=a?await At(p,{},{...a,options:m}):await Ct(p,{},m);return await Zn(u,t,e,n),o.info(`Prepared deployment profile "${r}" in ${u} (${R} rewritten text file(s)).`),{outputDir:u,cleanup:async()=>{c(),await M.rm(u,{recursive:!0,force:!0});}}}catch(p){throw o.error(`Failed to prepare deployment profile "${r}" temporary output.`,{tempDir:u,outputDir:t.outputDir,error:p instanceof Error?p.message:String(p),...p instanceof Error&&p.stack?{stack:p.stack}:{}}),await M.rm(u,{recursive:true,force:true}).catch(()=>{}),c(),await o.flush().catch(()=>{}),p}}function Ht(t,e){let r=o=>o.replace(/^\/+|\/+$/g,""),n=t.targets.find(o=>o.bucketName===e.s3.bucket&&r(o.prefix)===r(e.s3.prefix)&&o.region===e.s3.region);if(!n)throw new Error(`No CDK Lambda deployment target matches s3://${e.s3.bucket}/${e.s3.prefix||""} in ${e.s3.region}. Redeploy the CDK with this target and reinstall remote-workers.json.`);return n}function eo(t,e){if(!t||typeof t!="object")throw new Error("Remote deploy result must be a JSON object.");let r=t;if(r.schemaVersion!==K||r.response?.operation!=="deploy-copy"||r.response.jobId!==e.jobId||r.response.taskId!==e.taskId||!r.detail||!Array.isArray(r.detail.objects)||!Array.isArray(r.detail.deletedKeys)||!Array.isArray(r.detail.deleteErrors))throw new Error("Remote deploy result has an invalid envelope.");return r}async function We(t){let e=null;for(let r=1;r<=Math.max(1,Math.min(5,t.maxAttempts));r+=1){let n=B(`deploy-${t.batchIndex}-a${r}-${Date.now()}`,"taskId");try{let o=await t.client.invoke({schemaVersion:K,operation:"deploy-copy",jobId:t.jobId,taskId:n,targetId:t.targetId,items:t.items,...t.deleteRelativeKeys?{deleteRelativeKeys:t.deleteRelativeKeys}:{}}),s=eo(await t.client.readResult(o),o);if(s.response.status==="partial")throw new Error(`Worker reported ${s.response.failedItems} failed item(s).`);return s}catch(o){e=o;}}throw new Error(`Remote deploy task failed after ${t.maxAttempts} attempt(s): ${e instanceof Error?e.message:String(e)}`,{cause:e})}async function to(t){let e=Ht(t.remoteConfig,t.config),r=B(`deploy-${Date.now()}-${ae(Buffer.from(`${e.id}:${t.config.outputDir}`)).slice(0,12)}`,"jobId"),n=ue(t.remoteConfig.workspace.prefix,"jobs",r,"deploy-inputs");t.log.progress(`Staging export for Lambda deploy: 0/${t.files.length}`,{phase:"deploy-stage",index:0,totalFiles:t.files.length,uploaded:0,skipped:0,failed:0,mode:"lambda-s3-copy"});let o=0,s=[],a=Math.max(1,Math.min(16,t.concurrency*2)),i=0;await Promise.all(Array.from({length:Math.min(a,t.files.length)},async()=>{for(;;){let k=i;if(k>=t.files.length)return;i+=1;let f=t.files[k],b=await M.readFile(v.join(t.config.outputDir,f)),C=t.contentTypeByRelativePath?.get(f)||Tt.lookup(f)||"application/octet-stream",S=t.revalidateFiles.has(ie(f))?Ze:Re(f)?t.config.s3.htmlCacheControl:t.config.s3.assetCacheControl,I=ae(b),$=Re(f)?Le(b):void 0,E=`${n}/files/${ae(Buffer.from(f))}-${v.basename(f)}`.replace(/\/+/g,"/");await t.client.writeWorkspaceObject({key:E,body:b,contentType:String(C),cacheControl:S,metadata:{"wpsuite-sha256":I,...$?{"wpsuite-normalized-sha256":$}:{}}}),s[k]={sourceKey:E,targetRelativeKey:f,sha256:I,...$?{normalizedSha256:$}:{},bytes:b.byteLength,contentType:String(C),cacheControl:S},o+=1,(o===t.files.length||o<=5||o%25===0)&&t.log.progress(`Staging export for Lambda deploy: ${o}/${t.files.length}`,{phase:"deploy-stage",index:o,totalFiles:t.files.length,staged:o,mode:"lambda-s3-copy"});}}));let l=[],u=Math.max(1,Math.min(500,t.batchSize));for(let k=0;k<s.length;k+=u)l.push(s.slice(k,k+u));let c=[],p=[],d=[],m=0,R=0,w=0,y=Math.max(1,Math.min(Math.max(1,t.concurrency),l.length));if(t.log.progress(`Lambda deploy: 0/${t.files.length}`,{phase:"deploy-copy",index:0,totalFiles:t.files.length,uploaded:0,skipped:0,failed:0,mode:"lambda-s3-copy",workerCount:y,completedBatches:0,totalBatches:l.length}),await Promise.all(Array.from({length:y},async()=>{for(;;){let k=w;if(k>=l.length)return;w+=1;let f=Date.now(),b=await We({client:t.client,jobId:r,targetId:e.id,batchIndex:k+1,items:l[k],maxAttempts:t.maxAttempts}),C=0,S=0,I=0;for(let E of b.detail.objects)m+=1,E.status==="copied"?(c.push(E.targetKey),C+=1):E.status==="skipped"?(p.push(E.targetKey),S+=1):(d.push(E.targetKey),I+=1),t.log.debug(`Lambda deploy ${E.status}: ${E.targetKey}`,{phase:"deploy-copy",batch:k+1,sourceKey:E.sourceKey,targetKey:E.targetKey,status:E.status,...E.error?{error:E.error}:{}});R+=1;let $=Date.now()-f;t.log.info(`Lambda deploy batch ${k+1}/${l.length} completed: ${C} copied, ${S} skipped unchanged, ${I} failed.`,{phase:"deploy-copy",batch:k+1,totalBatches:l.length,items:b.detail.objects.length,copied:C,skipped:S,failed:I,elapsedMs:$,elapsedSeconds:Math.round($/10)/100,workerExporterVersion:b.response.exporterVersion,...b.requestId?{lambdaRequestId:b.requestId}:{},...b.completedAt?{workerCompletedAt:b.completedAt}:{}}),t.log.progress(`Lambda deploy: ${m}/${t.files.length}`,{phase:"deploy-copy",index:m,totalFiles:t.files.length,uploaded:c.length,skipped:p.length,failed:d.length,mode:"lambda-s3-copy",workerCount:y,completedBatches:R,totalBatches:l.length});}})),d.length>0)throw new Error(`Remote deployment failed for ${d.length} object(s).`);let P=[];for(let k=0;k<t.deletedFiles.length;k+=1e3){let f=t.deletedFiles.slice(k,k+1e3);if(f.length===0)continue;let b=await We({client:t.client,jobId:r,targetId:e.id,batchIndex:l.length+Math.floor(k/1e3)+1,items:[],deleteRelativeKeys:f,maxAttempts:t.maxAttempts});P.push(...b.detail.deletedKeys),t.log.progress(`Lambda deploy deletions: ${P.length}/${t.deletedFiles.length}`,{phase:"deploy-delete",index:P.length,totalFiles:t.deletedFiles.length,deleted:P.length,mode:"lambda-s3-copy"});}return {uploadedKeys:c,skippedKeys:p,failedKeys:d,deletedKeys:P}}async function ro(t){let e=Ht(t.remoteConfig,t.config),r=B(`deploy-manifest-${Date.now()}-${ae(Buffer.from(e.id)).slice(0,12)}`,"jobId"),n=t.objects.map(m=>({sourceKey:m.object.key,targetRelativeKey:m.relativePath,sha256:m.object.sha256,bytes:m.object.bytes,contentType:m.contentType||"application/octet-stream",cacheControl:t.revalidateFiles.has(ie(m.relativePath))?Ze:Re(m.relativePath)?t.config.s3.htmlCacheControl:t.config.s3.assetCacheControl})),o=[],s=Math.max(1,Math.min(500,t.batchSize));for(let m=0;m<n.length;m+=s)o.push(n.slice(m,m+s));let a=[],i=[],l=[],u=0,c=0,p=Math.max(1,Math.min(Math.max(1,t.concurrency),Math.max(1,o.length)));if(t.log.progress(`Lambda deploy: 0/${n.length}`,{phase:"deploy-copy",index:0,totalFiles:n.length,mode:"lambda-s3-native",workerCount:p}),await Promise.all(Array.from({length:o.length===0?0:p},async()=>{for(;;){let m=u;if(m>=o.length)return;u+=1;let R=await We({client:t.client,jobId:r,targetId:e.id,batchIndex:m+1,items:o[m],maxAttempts:t.maxAttempts});for(let w of R.detail.objects)c+=1,w.status==="copied"?a.push(w.targetKey):w.status==="skipped"?i.push(w.targetKey):l.push(w.targetKey);t.log.progress(`Lambda deploy: ${c}/${n.length}`,{phase:"deploy-copy",index:c,totalFiles:n.length,uploaded:a.length,skipped:i.length,failed:l.length,mode:"lambda-s3-native",workerCount:p});}})),l.length>0)throw new Error(`Remote deployment failed for ${l.length} object(s).`);let d=[];for(let m=0;m<t.deletedFiles.length;m+=1e3){let R=t.deletedFiles.slice(m,m+1e3);if(R.length===0)continue;let w=await We({client:t.client,jobId:r,targetId:e.id,batchIndex:o.length+Math.floor(m/1e3)+1,items:[],deleteRelativeKeys:R,maxAttempts:t.maxAttempts});d.push(...w.detail.deletedKeys);}return {uploadedKeys:a,skippedKeys:i,failedKeys:l,deletedKeys:d}}async function no(t,e,r,n,o){let s={...e,jobId:B(`profile-${ae(Buffer.from(n)).slice(0,16)}-${Date.now()}`,"jobId"),objects:{},assetMap:{...e.assetMap},generatedAt:new Date().toISOString()},a=0,i=Math.max(1,Math.min(Math.max(1,o),Math.max(1,r.length)));return await Promise.all(Array.from({length:r.length===0?0:i},async()=>{for(;;){let l=a;if(l>=r.length)return;a+=1;let u=r[l],c=ue(t.config.workspace.prefix,"jobs",s.jobId,"profile",ae(Buffer.from(u.relativePath)),v.basename(u.relativePath));s.objects[u.relativePath]={...u,object:await t.copyWorkspaceObject(u.object,c)};}})),s}async function Jt(t=process.argv.slice(2)){let e=await ve(),r=gt(t),n=mt(e,r),o=v.resolve(n.config.logDir||"logs"),s=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",a=s?v.join(v.resolve(s),"deploy-diff.json"):"",i=new we(o,"deploy.log.jsonl",n.config.logLevel??"info"),l=n.profile?.extraReplacements??{},u=async()=>{};try{let c=await pt(e);if(t.includes("--content-sync")&&c?.schemaVersion!==2)throw new Error("Content-sync deployment requires a valid schema-2 targeted deploy plan.");let d=await dt(e);if(d)throw new Error(`Deployment blocked: the crawl started at ${d.startedAt} did not complete its final rewrite. Run a successful crawl or resume the rewrite before deploying.`);let m=e.remoteWorkers?.rewrite?.enabled===!0,R=e.remoteWorkers?.deploy?.enabled===!0,w=null,y=null;if(m||R){let h=_t({runtimeDir:s});if(!h)throw new Error("Remote Lambda workers are enabled, but the runtime directory is unknown.");w=await Ft(h);let j=!1;y=new je(w,{},{onProgress:g=>{i.progress(`Lambda ${g.operation} batch: ${g.completedItems+g.failedItems}/${g.totalItems}`,{remoteWorkerOperation:g.operation,remoteWorkerTaskId:g.taskId,remoteWorkerStatus:g.status,remoteWorkerCompletedItems:g.completedItems,remoteWorkerFailedItems:g.failedItems,remoteWorkerTotalItems:g.totalItems,remoteWorkerUpdatedAt:g.updatedAt});},onProgressError:g=>{j||(j=!0,i.warn("Lambda progress status could not be read; task execution continues.",{error:g.message}));}});}let P=R&&m&&e.remoteWorkers?.render?.enabled===!0&&y&&w?.functions.asset?await Nt(e):null;if(P&&y&&w){if(P.workspace.bucket!==w.workspace.bucket||P.workspace.prefix!==w.workspace.prefix)throw new Error("Remote export manifest workspace does not match remote-workers.json.");let h=n.config,j=h.s3SyncMode??"sdk-upload-delete";if(c?.schemaVersion===2&&c.deletedFiles.length>0&&j!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let g=c?.schemaVersion===2?[...c.uploadGroups.assets,...c.uploadGroups.content,...c.uploadGroups.listings,...c.uploadGroups.resources,...c.uploadGroups.sitemapLeaves,...c.uploadGroups.sitemapIndexes]:c?.changedFiles??[];if(c?.schemaVersion===2){let _=[...new Set(g)],Q=[...new Set(c.changedFiles)];if(_.length!==Q.length||Q.some(he=>!_.includes(he)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let H=!!c&&!c.fullSyncRequired?[...new Set(g.map(ie))]:Object.keys(P.objects).sort(),fe=H.filter(_=>!P.objects[_]);if(fe.length>0)throw new Error(`Remote export manifest is missing ${fe.length} planned object(s): ${fe.slice(0,10).join(", ")}`);let te=P,T=H.map(_=>P.objects[_]);n.name&&(e.targetOrigin!==h.targetOrigin||Object.keys(l).length>0)&&(te=await no(y,P,T,n.name||"default",e.concurrency),await Dt(h,te,te.assetMap,{client:y,jobId:te.jobId,concurrency:e.concurrency,batchSize:25,maxAttempts:2}),T=H.map(_=>te.objects[_])),n.name&&i.info(`Using deployment profile: ${n.name}`),i.info(`Starting S3-native Lambda deploy - s3://${h.s3.bucket}/${h.s3.prefix||""} (${h.s3.region}).`),i.mark("deploy");let L=await ro({client:y,remoteConfig:w,config:h,objects:T,deletedFiles:j==="sdk-upload-delete"?c?.deletedFiles??[]:[],revalidateFiles:new Set((c?.revalidateFiles??[]).map(ie)),concurrency:e.concurrency,batchSize:50,maxAttempts:2,log:i});a&&(await M.mkdir(v.dirname(a),{recursive:!0}),await M.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:"lambda-s3-native",summary:{totalFiles:T.length,eligibleFiles:T.length,uploaded:L.uploadedKeys.length,skipped:L.skippedKeys.length,rejected:0,failed:L.failedKeys.length,deleted:L.deletedKeys.length,protected:0,...n.name?{profile:n.name}:{}},uploadedKeys:L.uploadedKeys,skippedKeys:L.skippedKeys,rejectedKeys:[],failedKeys:L.failedKeys,deletedKeys:L.deletedKeys,protectedRemoteOnlyKeys:[]},null,2),"utf8")),c?.schemaVersion!==2&&await Ee(e),i.endMark("deploy"),await i.flush();return}let k=await Xn(e,n.config,n.name,l,i,c?.schemaVersion===2?c.changedFiles:void 0,m&&y?{client:y,jobId:`profile-${Date.now()}`,concurrency:e.remoteWorkers?.rewrite?.concurrency??e.rewriteConcurrency,batchSize:e.remoteWorkers?.rewrite?.batchSize??25,maxAttempts:e.remoteWorkers?.rewrite?.maxAttempts??2,onStageProgress:({index:h,totalFiles:j,file:g})=>{(h===1||h===j||h%25===0)&&i.progress(`Staging deployment-profile rewrite: ${h}/${j}`,{phase:"rewrite-stage",index:h,totalFiles:j,file:g,execution:"lambda"});}}:void 0);u=k.cleanup;let f={...n.config,outputDir:k.outputDir},b=f.s3SyncMode??"sdk-upload-delete";if(c?.schemaVersion===2&&c.deletedFiles.length>0&&b!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let C=c?.schemaVersion!==2&&k.outputDir!==e.outputDir&&(e.targetOrigin!==n.config.targetOrigin||Object.keys(l).length>0),S=!!c&&!c.fullSyncRequired&&!C;if(c?.schemaVersion===2&&!S)throw new Error("Content-sync deployment cannot widen into a full-output deployment.");n.name&&i.info(`Using deployment profile: ${n.name}`),i.info(`Starting deploy \u2014 s3://${f.s3.bucket}/${f.s3.prefix||""} (region: ${f.s3.region})`),i.info(`S3 sync mode: ${b}`),c&&c.fullSyncRequired?i.info("Deploy plan requests a full sync; scanning the whole output tree."):c&&C?i.info("Ignoring incremental deploy plan because deployment-profile rewrites require a full sync."):S&&i.info(`Using incremental deploy plan: ${c.changedFiles.length} changed file(s), ${c.deletedFiles.length} deleted file(s).`),i.mark("deploy");let I=new S3Client({region:f.s3.region}),$=k.outputDir===e.outputDir?await Ln(e,s,i):null,E=c?.schemaVersion===2?[...c.uploadGroups.assets,...c.uploadGroups.content,...c.uploadGroups.listings,...c.uploadGroups.resources,...c.uploadGroups.sitemapLeaves,...c.uploadGroups.sitemapIndexes]:c?.changedFiles??[];if(c?.schemaVersion===2){let h=[...new Set(E)],j=[...new Set(c.changedFiles)];if(h.length!==j.length||j.some(g=>!h.includes(g)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let D=S?(await Promise.all(E.map(async h=>{try{return (await M.stat(v.join(f.outputDir,h))).isFile()?h:null}catch{if(c?.schemaVersion===2)throw new Error(`Content-sync planned upload is missing: ${h}`);return null}}))).filter(h=>h!==null):await Fr(["**/*"],{cwd:f.outputDir,onlyFiles:!0,dot:!0}),U=[],O=[],x=D.filter(h=>{let j=$?.byRelativePath.get(ie(h));if(!j)return !0;let g=Me(f.s3.prefix,h);return U.push(h),O.push(g),i.reject(j.kind,j.sourceUrl||h,"rewrite not completed; deploy upload blocked","deploy-guard",{file:h,key:g,outputPath:j.outputPath,manifestPath:$?.manifestPath}),!1}),et=new Set((c?.revalidateFiles||[]).map(ie)),tt=new Set((S?x:D).map(h=>Me(f.s3.prefix,h)));$&&($.pendingPages>0||$.pendingTextAssets>0)&&i.info(`Deploy rewrite guard loaded ${$.pendingPages} pending page(s) and ${$.pendingTextAssets} pending text asset(s) from crawl manifest.`,{manifestPath:$.manifestPath,pendingPages:$.pendingPages,pendingTextAssets:$.pendingTextAssets,source:"deploy-guard"}),U.length>0&&i.warn(`Deploy rewrite guard blocked ${U.length} file(s) from upload because final crawl rewrite is incomplete.`,{rejected:U.length,manifestPath:$?.manifestPath,source:"deploy-guard"}),S?i.info(`Using ${x.length} eligible planned changed file(s) from deploy plan for upload${U.length>0?` (${U.length} blocked by deploy rewrite guard)`:""}.`):i.info(`Found ${D.length} file(s) in output directory "${f.outputDir}"${U.length>0?`; ${x.length} remain eligible for upload after deploy rewrite guard filtering`:""}.`),i.progress("Deploy preflight: comparing local output with remote S3 state.",{phase:"deploy",mode:b,totalFiles:x.length,scannedFiles:D.length,rejected:U.length,deploymentProfile:n.name||"",s3Bucket:f.s3.bucket,s3Prefix:f.s3.prefix||"",targetedPlan:S,deployGuardEnabled:k.outputDir===e.outputDir});let F=0,A=0,q=0,ge=[],X=[],ee=[],le=[],ce=[],me=new Map,Gt=new Map,Qt=new Map,Yt=new Map,Zt=new Map;if(R){if(!y||!w)throw new Error("Remote deploy worker client was not initialized.");if(b!=="sdk-upload-delete"&&b!=="sdk-upload-only")throw new Error(`Unsupported remote deploy mode: ${b}`);let h=await to({client:y,remoteConfig:w,config:f,files:x,deletedFiles:b==="sdk-upload-delete"?c?.deletedFiles??[]:[],revalidateFiles:et,contentTypeByRelativePath:$?.contentTypeByRelativePath,concurrency:f.remoteWorkers?.deploy?.concurrency??f.assetDownloadConcurrency,batchSize:f.remoteWorkers?.deploy?.batchSize??50,maxAttempts:f.remoteWorkers?.deploy?.maxAttempts??2,log:i});ge.push(...h.uploadedKeys),X.push(...h.skippedKeys),ee.push(...h.failedKeys),le=h.deletedKeys,F=ge.length,A=X.length,q=ee.length,i.info(`Lambda deploy complete: ${F} copied, ${A} skipped unchanged, ${le.length} deleted, ${q} failed.`),a&&(await M.mkdir(v.dirname(a),{recursive:!0}),await M.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:"lambda-s3-copy",summary:{totalFiles:D.length,eligibleFiles:x.length,uploaded:F,skipped:A,rejected:O.length,failed:q,deleted:le.length,protected:0,...n.name?{profile:n.name}:{}},uploadedKeys:ge,skippedKeys:X,rejectedKeys:O,failedKeys:ee,deletedKeys:le,protectedRemoteOnlyKeys:[]},null,2),"utf8")),c?.schemaVersion!==2&&await Ee(e),i.endMark("deploy"),await i.flush();return}S||(i.info("Listing existing S3 objects to detect unchanged files..."),me=await Vn(I,f.s3.bucket,f.s3.prefix,i),i.info(`Found ${me.size} existing key(s) in S3.`));let Xt=async h=>me.has(h)?me.get(h)??null:S?zn(I,f.s3.bucket,h,Gt):null;for(let h of x){let j=v.join(f.outputDir,h),g=Me(f.s3.prefix,h),V=$?.contentTypeByRelativePath.get(h),H=V&&V!=="application/octet-stream"?V:Tt.lookup(h)||V||"application/octet-stream",fe=et.has(ie(h)),te=fe?Ze:Re(h)?f.s3.htmlCacheControl:f.s3.assetCacheControl,T=F+A+q+1;x.length<=200||T<=5||T%10===0||T===x.length?(i.progress(`Uploading [${T}/${x.length}] ${g} (${H})`,{file:h,key:g,index:T,totalFiles:x.length,contentType:H,mode:b}),i.info(`Uploading [${T}/${x.length}] ${g} (${H})`)):i.debug(`Uploading [${T}/${x.length}] ${g} (${H})`);try{let z=await M.readFile(j),L=await Xt(g),_=null,Q=null;if(L){let he=await Bn(I,f.s3.bucket,g,L),er=!fe||Vt(he.cacheControl)===Vt(te),tr=Ge(he.contentType)===Ge(String(H)),_e=er&&tr,rr=z.byteLength;if(L.size===rr){let xe=L.etag.includes("-");if(L.etag!==""&&!xe){let nr=Hn(z);if(L.etag===nr&&_e){A++,x.length<=200||A<=5||A%25===0?(i.progress(`Skipped unchanged [${T}/${x.length}] ${g}`,{file:h,key:g,index:T,totalFiles:x.length,uploaded:F,skipped:A,failed:q,mode:b,reason:"etag-md5-match"}),i.info(`Skipped unchanged [${T}/${x.length}] ${g}`)):i.debug(`Skipped unchanged [${T}/${x.length}] ${g}`),X.push(g);continue}}_=ae(z);let rt=await Jn(I,f.s3.bucket,g,Qt);if(rt&&rt===_&&_e){A++,x.length<=200||A<=5||A%25===0?(i.progress(`Skipped unchanged [${T}/${x.length}] ${g}`,{file:h,key:g,index:T,totalFiles:x.length,uploaded:F,skipped:A,failed:q,mode:b,reason:"metadata-sha256-match"}),i.info(`Skipped unchanged [${T}/${x.length}] ${g}`)):i.debug(`Skipped unchanged [${T}/${x.length}] ${g}`),X.push(g);continue}}if(Re(h)){Q=Le(z);let xe=await Gn(I,f.s3.bucket,g,Yt,Zt);if(xe&&xe===Q&&_e){A++,x.length<=200||A<=5||A%25===0?(i.progress(`Skipped semantically unchanged [${T}/${x.length}] ${g}`,{file:h,key:g,index:T,totalFiles:x.length,uploaded:F,skipped:A,failed:q,mode:b,reason:"normalized-html-match"}),i.info(`Skipped semantically unchanged [${T}/${x.length}] ${g}`)):i.debug(`Skipped semantically unchanged [${T}/${x.length}] ${g}`),X.push(g);continue}}}_=_??ae(z),Q=Q??(Re(h)?Le(z):null),await Y(`S3 upload ${g}`,9e5,({abortController:he})=>new Upload({client:I,abortController:he,params:{Bucket:f.s3.bucket,Key:g,Body:z,ContentType:H,CacheControl:te,Metadata:{[Bt]:_,...Q?{[qt]:Q}:{}}}}).done()),F++,ge.push(g),(F%25===0||F===x.length)&&(i.progress(`Uploaded ${F}/${x.length} file(s)\u2026`,{uploaded:F,skipped:A,failed:q,totalFiles:x.length,mode:b}),i.info(`Uploaded ${F}/${x.length} file(s)\u2026`));}catch(z){q++,ee.push(g),i.error(`Failed to upload ${g}: ${z.message}`,{key:g,error:String(z)});}}if(i.info(`Upload complete: ${F} uploaded, ${A} skipped unchanged, ${O.length} rejected by guard, ${q} failed.`),ee.length>0||O.length>0)throw new Error(`Deployment stopped before deletion because ${ee.length} upload(s) failed and ${O.length} upload(s) were rejected.`);if(b==="sdk-upload-delete"){let h=new Set((c?.deletedFiles??[]).map(g=>Me(f.s3.prefix,g))),j=[...h].filter(g=>!tt.has(g));if(!S&&(ce=[...me.keys()].filter(V=>!tt.has(V)).filter(V=>!h.has(V)),ce.length>0)){i.warn(`Protected ${ce.length} remote-only S3 object(s) from deletion because the crawl did not provide explicit tombstones.`,{protected:ce.length,source:"deploy-delete-guard"});for(let V of ce)i.debug(` protected remote-only object: ${V}`);}le=await qn(I,f.s3.bucket,S?j:j.filter(g=>me.has(g)),i);}else i.info("Sync mode is sdk-upload-only \u2014 skipping stale object deletion.");a&&(await M.mkdir(v.dirname(a),{recursive:!0}),await M.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:b,summary:{totalFiles:D.length,eligibleFiles:x.length,uploaded:ge.length,skipped:X.length,rejected:O.length,failed:ee.length,deleted:le.length,protected:ce.length,...n.name?{profile:n.name}:{}},uploadedKeys:ge,skippedKeys:X,rejectedKeys:O,failedKeys:ee,deletedKeys:le,protectedRemoteOnlyKeys:ce},null,2),"utf8")),c?.schemaVersion!==2&&await Ee(e),i.endMark("deploy"),await i.flush();}finally{await u().catch(()=>{});}}Jt().catch(async t=>{console.error(t);try{let r=(await ve().catch(()=>null))?.logDir??"logs",n=new we(r,"deploy.log.jsonl","debug");n.error(`Unhandled error: ${t instanceof Error?t.message:String(t)}`,t instanceof Error?{stack:t.stack}:void 0),await n.flush();}catch{}process.exit(1);});
|
|
6
|
+
`;return t.replace(/<head\b[^>]*>/i,o=>`${o}${n} ${e}`)}function Qr(t){let e=vt(t).trim();return e.startsWith("{")||e.startsWith("[")||e.includes("\\/")||/"@context"|"@type"/.test(e)}function Yr(t,e){let r=[...new Set(e)].filter(s=>s.includes("/")&&!/\\+\//.test(s)).map(s=>[s,Te(s)]).filter(([s,a])=>s!==a).sort((s,a)=>a[0].length-s[0].length);if(!r.length)return t;let n=s=>{let a=s;for(let[i,l]of r)a=a.split(i).join(l);return a},o=t.replace(/(<script\b[^>]*\btype=["']application\/(?:ld\+)?json["'][^>]*>)([\s\S]*?)(<\/script>)/gi,(s,a,i,l)=>`${a}${n(i)}${l}`);return o=o.replace(/(<meta\b[^>]*\bcontent=(['"]))([\s\S]*?)(\2[^>]*>)/gi,(s,a,i,l,u)=>Qr(l)?`${a}${n(l)}${u}`:s),o}function Zr(t,e){if(!e)return null;let r=I.dirname(I.resolve(e)),n=I.resolve(t.outputDir),o=I.relative(r,n).replace(/\\/g,"/");return o?(o.startsWith(".")||(o=`./${o}`),o.endsWith("/")?o:`${o}/`):"./"}function Xr(t,e,r){let n=Zr(e,r);if(!n)return t;let o=t;for(let s of Ur){let a=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=new RegExp(`(?:\\.{1,}/)+${a}`,"g"),l=new RegExp(`(?<!\\.)/${a}`,"g");o=o.replace(i,`${n}${s}`).replace(l,`${n}${s}`);let u=s.replace(/\//g,"\\/"),c=n.replace(/\//g,"\\/"),d=u.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),g=new RegExp(`(?:\\.{1,}\\\\/)+${d}`,"g"),f=new RegExp(`(?:\\.{1,}(?:\\\\/|\\\\))+${d}`,"g"),b=new RegExp(`(?<![\\.\\\\])\\/${d}`,"g");o=o.replace(g,`${c}${u}`).replace(f,`${c}${u}`).replace(b,`${c}${u}`);}return o}function Je(t,e,r){if(t.urlRewriteMode==="absolute")return e;let n=(()=>{try{return new URL(e,t.targetOrigin==="."?"https://relative.invalid":t.targetOrigin)}catch{return null}})(),o=n?n.pathname:Et(e,t.targetOrigin),s=n?`${n.search}${n.hash}`:"";return t.urlRewriteMode==="root-relative"?`${o}${s}`:`${It(t.outputDir,r,o)}${s}`}function He(t,e,r,n,o){je(t,r,Je(e,n,o));}function en(t,e,r,n,o){if(!r||r===n)return;je(t,r,n);let s=Je(e,r,o),a=Je(e,n,o);je(t,s,a);}function tn(t,e,r,n,o={}){let s=t,a={};He(a,e,e.sourceOrigin,e.targetOrigin,n);for(let[l,u]of Object.entries(e.extraReplacements))He(a,e,l,u,n);for(let[l,u]of Object.entries(r))He(a,e,l,u,n);for(let[l,u]of Object.entries(o)){let c=r[l];!c||c===u||en(a,e,u,c,n);}let i=Object.entries(a).sort((l,u)=>u[0].length-l[0].length);for(let[l,u]of i)s=Hr(s,l,u);return e.urlRewriteMode!=="absolute"&&(s=Xr(s,e,n)),s=Yr(s,i.map(([,l])=>l)),Jr(e,s,n)&&(s=Gr(s)),s}async function rn(t,e,r,n){let o=I.join(t.outputDir,n),s=I.extname(o).toLowerCase(),a;try{a=await O.readFile(o,"utf8");}catch(u){if(u.code!=="ENOENT")throw u;return {changed:false}}let l=tn(a,t,e,s===".js"||s===".mjs"?void 0:o,r);return l!==a?(await Se(o,l,"utf8"),{changed:true}):{changed:false}}async function nn(t,e){return await new Promise((r,n)=>{let o=l=>{if(i(),l?.error){n(new Error(l.error));return}r({changed:!!l?.changed});},s=l=>{i(),n(l);},a=l=>{i(),l!==0&&n(new Error(`Rewrite worker exited with code ${l}.`));},i=()=>{t.off("message",o),t.off("error",s),t.off("exit",a);};t.on("message",o),t.on("error",s),t.on("exit",a),t.postMessage({file:e});})}async function $t(t,e,r={}){let n=await Ge(t,r.files),o=0;if(n.length===0)return 0;let s=Math.max(1,Number(t.rewriteConcurrency||t.assetDownloadConcurrency||1)),a=Math.max(1,Math.min(s,n.length,availableParallelism()));await r.onStart?.({totalFiles:n.length,workerCount:a});let i=0,l=0,u=null;if(a===1){for(let d of n){let g=await rn(t,e,r.previousAssetMap??{},d);g.changed&&(o+=1),l+=1,await r.onProgress?.({index:l,totalFiles:n.length,changedTextFiles:o,file:d,changed:g.changed});}return o}let c=Array.from({length:a},async()=>{let d=new Worker(new URL("./rewrite-worker.js",import.meta.url),{workerData:{config:t,assetMap:e,previousAssetMap:r.previousAssetMap??{}}});try{for(;!u;){let g=i;if(g>=n.length)return;i+=1;let f=n[g],b=await nn(d,f);b.changed&&(o+=1),l+=1,await r.onProgress?.({index:l,totalFiles:n.length,changedTextFiles:o,file:f,changed:b.changed});}}catch(g){throw u=g instanceof Error?g:new Error(String(g)),u}finally{await d.terminate().catch(()=>{});}});return await Promise.all(c),o}var U=1,Tt=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function H(t,e){let r=String(t??"").trim();if(!Tt.test(r))throw new Error(`${e} must match ${Tt.source} and be at most 128 characters.`);return r}function jt(t){let e=String(t??"").trim().replace(/^\/+|\/+$/g,"");if(!e)return "";let r=e.split("/").filter(Boolean);if(r.some(n=>n==="."||n===".."))throw new Error("S3 prefix contains an unsafe dot path segment.");return `${r.join("/")}/`}function pe(t,...e){let r=jt(t),n=e.map((o,s)=>{let a=String(o??"").replace(/^\/+|\/+$/g,"");if(!a||a.split("/").some(i=>i==="."||i===".."))throw new Error(`Unsafe S3 key segment at index ${s}.`);return a});return `${r}${n.join("/")}`}function de(t){return createHash("sha256").update(t).digest("hex")}function se(t,e){let r=String(t??"").replace(/^\/+/,""),n=jt(e);if(!r||r.includes("\0"))throw new Error("S3 object key is empty or invalid.");if(n&&!r.startsWith(n))throw new Error(`S3 object key is outside the configured workspace prefix: ${r}`);if(r.split("/").some(o=>o===".."))throw new Error("S3 object key contains an unsafe parent segment.");return r}function Mt(t,e){let r=[];for(let n=0;n<t.length;n+=e)r.push(t.slice(n,n+e));return r}function At(t){return {sourceOrigin:t.sourceOrigin,targetOrigin:t.targetOrigin,urlRewriteMode:t.urlRewriteMode,outputDir:"/workspace",extraReplacements:t.extraReplacements,wpsuite:{...t.wpsuite?.subscriptionType?{subscriptionType:t.wpsuite.subscriptionType}:{},...t.wpsuite?.siteSettings?{siteSettings:{subscriber:t.wpsuite.siteSettings.subscriber===true}}:{}}}}function Dt(t,e){if(!t||typeof t!="object")throw new Error("Remote rewrite result must be a JSON object.");let r=t;if(r.schemaVersion!==U||r.response?.operation!=="rewrite"||r.response.jobId!==e.jobId||r.response.taskId!==e.taskId||!r.detail||!Array.isArray(r.detail.objects))throw new Error("Remote rewrite result has an invalid envelope.");return r}async function Wt(t,e,r){let n=r.options??{},o=await Ge(t,n.files);if(o.length===0)return 0;let s=H(r.jobId,"jobId"),a=pe(r.client.config.workspace.prefix,"jobs",s,"rewrite-inputs"),i=`${a}/config.json`.replace(/\/+/g,"/"),l=`${a}/asset-map.json`.replace(/\/+/g,"/"),u=`${a}/previous-asset-map.json`.replace(/\/+/g,"/");await Promise.all([r.client.writeWorkspaceObject({key:i,body:JSON.stringify(At(t)),contentType:"application/json; charset=utf-8"}),r.client.writeWorkspaceObject({key:l,body:JSON.stringify(e),contentType:"application/json; charset=utf-8"}),r.client.writeWorkspaceObject({key:u,body:JSON.stringify(n.previousAssetMap??{}),contentType:"application/json; charset=utf-8"})]);let c=Math.max(1,Math.min(500,r.batchSize)),d=Math.ceil(o.length/c),g=Math.max(1,Math.min(Math.max(1,r.concurrency),d));await n.onStart?.({totalFiles:o.length,workerCount:g});let f=[],b=0,y=0;await Promise.all(Array.from({length:Math.min(16,o.length)},async()=>{for(;;){let v=b;if(v>=o.length)return;b+=1;let E=o[v],x=I.join(t.outputDir,E),C=Ot.lookup(E),M=C?Ot.contentType(C)||C:"text/plain; charset=utf-8",A=`${a}/files/${de(E)}.txt`.replace(/\/+/g,"/");await r.client.writeWorkspaceObject({key:A,body:await O.readFile(x),contentType:M}),f[v]={relativePath:E,key:A,fullPath:x,contentType:M},y+=1,await r.onStageProgress?.({index:y,totalFiles:o.length,file:E});}}));let R=Mt(f,c),S=0,P=0,h=0,k=0,j=Array.from({length:g},async()=>{for(;;){let v=S;if(v>=R.length)return;S+=1;let E=R[v],x=null,C=null;for(let M=1;M<=Math.max(1,Math.min(5,r.maxAttempts));M+=1){let A=H(`rewrite-${v+1}-a${M}-${de(E.map(w=>w.relativePath).join(`
|
|
7
|
+
`)).slice(0,16)}`,"taskId"),V={schemaVersion:U,operation:"rewrite",jobId:s,taskId:A,configKey:i,assetMapKey:l,previousAssetMapKey:u,items:E.map(w=>({inputKey:w.key,outputKey:w.key,relativePath:w.relativePath,contentType:w.contentType}))};try{let w=await r.client.invoke(V);C=Dt(await r.client.readResult(w),w);break}catch(w){x=w;}}if(!C)throw new Error(`Remote rewrite batch ${v+1}/${R.length} failed: ${x instanceof Error?x.message:String(x)}`,{cause:x});for(let M of E){let A=C.detail.objects.find(V=>V.outputKey===M.key);if(!A)throw new Error(`Remote rewrite result omitted ${M.relativePath}.`);await Se(M.fullPath,Buffer.from(await r.client.readObject(A.output))),A.changed&&(k+=1),P+=1,await n.onProgress?.({index:P,totalFiles:o.length,changedTextFiles:k,file:M.relativePath,changed:A.changed});}h+=1,await r.onBatchProgress?.({completedItems:P,totalItems:o.length,completedBatches:h,totalBatches:R.length,changedTextFiles:k});}});return await Promise.all(j),k}async function Lt(t,e,r,n){let o=n.relativePaths?new Set([...n.relativePaths].map(S=>S.replace(/\\/g,"/"))):null,s=Object.values(e.objects).filter(S=>S.isText&&(!o||o.has(S.relativePath))).sort((S,P)=>S.relativePath.localeCompare(P.relativePath));if(s.length===0)return 0;let a=H(n.jobId,"jobId"),i=pe(n.client.config.workspace.prefix,"jobs",a,"rewrite-config"),l=`${i}/config.json`.replace(/\/+/g,"/"),u=`${i}/asset-map.json`.replace(/\/+/g,"/");await Promise.all([n.client.writeWorkspaceObject({key:l,body:JSON.stringify(At(t)),contentType:"application/json; charset=utf-8"}),n.client.writeWorkspaceObject({key:u,body:JSON.stringify(r),contentType:"application/json; charset=utf-8"})]);let c=Math.max(1,Math.min(500,n.batchSize)),d=Mt(s,c),g=Math.max(1,Math.min(Math.max(1,n.concurrency),d.length)),f=0,b=0,y=0,R=0;return await Promise.all(Array.from({length:g},async()=>{for(;;){let S=f;if(S>=d.length)return;f+=1;let P=d[S],h=null,k=null;for(let j=1;j<=Math.max(1,Math.min(5,n.maxAttempts));j+=1){let v=H(`rewrite-object-${S+1}-a${j}-${de(P.map(E=>E.relativePath).join(`
|
|
8
|
+
`)).slice(0,16)}`,"taskId");try{let E=await n.client.invoke({schemaVersion:U,operation:"rewrite",jobId:a,taskId:v,configKey:l,assetMapKey:u,items:P.map(x=>({inputKey:x.object.key,outputKey:x.object.key,relativePath:x.relativePath,contentType:x.contentType||x.object.contentType}))});h=Dt(await n.client.readResult(E),E);break}catch(E){k=E;}}if(!h)throw new Error(`Remote object rewrite batch ${S+1}/${d.length} failed: ${k instanceof Error?k.message:String(k)}`,{cause:k});for(let j of P){let v=h.detail.objects.find(E=>E.outputKey===j.object.key);if(!v)throw new Error(`Remote rewrite result omitted ${j.relativePath}.`);j.object=v.output,v.changed&&(R+=1),b+=1,await n.onProgress?.({index:b,totalFiles:s.length,changedTextFiles:R,file:j.relativePath,changed:v.changed});}y+=1,await n.onBatchProgress?.({completedItems:b,totalItems:s.length,completedBatches:y,totalBatches:d.length,changedTextFiles:R});}})),e.assetMap={...r},e.generatedAt=new Date().toISOString(),R}function F(t,e,{optional:r=false}={}){if(!(r&&(t==null||t===""))){if(typeof t!="string"||!t.trim())throw new Error(`${e} must be a non-empty string.`);return t.trim()}}function yn(t){if(!t||typeof t!="object")throw new Error("Remote worker config must be a JSON object.");let e=t;if(e.schemaVersion!==1)throw new Error(`Unsupported remote worker config version: ${String(e.schemaVersion)}.`);if(e.protocolVersion!==U)throw new Error(`Remote worker protocol mismatch: expected ${U}, received ${String(e.protocolVersion)}.`);let r=e.workspace,n=e.functions;if(!r||!n)throw new Error("Remote worker config requires workspace and functions objects.");return {schemaVersion:1,region:F(e.region,"region"),...F(e.roleArn,"roleArn",{optional:true})?{roleArn:F(e.roleArn,"roleArn")}:{},...F(e.roleSessionName,"roleSessionName",{optional:true})?{roleSessionName:F(e.roleSessionName,"roleSessionName")}:{},workspace:{bucket:F(r.bucket,"workspace.bucket"),prefix:String(r.prefix??"")},...e.status&&typeof e.status=="object"?{status:{tableName:F(e.status.tableName,"status.tableName")}}:{},functions:{render:F(n.render,"functions.render"),...F(n.asset,"functions.asset",{optional:true})?{asset:F(n.asset,"functions.asset")}:{},rewrite:F(n.rewrite,"functions.rewrite"),"deploy-copy":F(n["deploy-copy"],"functions.deploy-copy")},targets:Array.isArray(e.targets)?e.targets.map((o,s)=>{if(!o||typeof o!="object")throw new Error(`targets[${s}] must be an object.`);let a=o;return {id:F(a.id,`targets[${s}].id`),bucketName:F(a.bucketName,`targets[${s}].bucketName`),prefix:String(a.prefix??""),region:F(a.region,`targets[${s}].region`)}}):[],protocolVersion:U}}async function Nt(t){let e=I.resolve(t);try{return yn(JSON.parse(await readFile(e,"utf8")))}catch(r){throw new Error(`Unable to load remote worker config ${e}: ${r instanceof Error?r.message:String(r)}`,{cause:r})}}var Oe=class{config;lambda;s3;dynamodb;#e;constructor(e,r={},n={}){this.config=e;let o=e.roleArn?fromTemporaryCredentials({params:{RoleArn:e.roleArn,RoleSessionName:e.roleSessionName??"publisher-exporter-remote-worker"},clientConfig:{region:e.region}}):void 0;this.lambda=new LambdaClient({region:e.region,...o?{credentials:o}:{},...r}),this.s3=new S3Client({region:e.region,...o?{credentials:o}:{}}),this.dynamodb=e.status?new DynamoDBClient({region:e.region,...o?{credentials:o}:{}}):null,this.#e=n;}async#t(e){if(!this.dynamodb||!this.config.status)return null;let n=(await this.dynamodb.send(new GetItemCommand({TableName:this.config.status.tableName,ConsistentRead:true,Key:{jobId:{S:e.jobId},taskId:{S:e.taskId}}}))).Item;if(!n)return null;let o=n.operation?.S,s=n.status?.S;return !o||!["render","asset","rewrite","deploy-copy"].includes(o)||!s||!["running","succeeded","partial","failed"].includes(s)?null:{jobId:n.jobId?.S??e.jobId,taskId:n.taskId?.S??e.taskId,operation:o,status:s,completedItems:Number(n.completedItems?.N??0),failedItems:Number(n.failedItems?.N??0),totalItems:Number(n.totalItems?.N??0),sequence:Number(n.sequence?.N??0),updatedAt:n.updatedAt?.S??new Date(0).toISOString(),requestId:n.requestId?.S??null}}async#r(e,r){let n=this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify(e),"utf8")}));if(e.operation==="health"||!this.dynamodb||!this.#e.onProgress)return await n;let o=false,s=n.finally(()=>{o=true;}),a=Math.max(500,Math.min(3e4,this.#e.progressPollIntervalMs??2e3)),i=-1;for(;!o;){await Promise.race([s.then(()=>{},()=>{}),new Promise(l=>setTimeout(l,a))]);try{let l=await this.#t(e);l&&l.sequence>i&&(i=l.sequence,await this.#e.onProgress(l));}catch(l){await this.#e.onProgressError?.(l instanceof Error?l:new Error(String(l)));}}return await s}async invoke(e){let r=e.operation==="health"?this.config.functions.render:this.config.functions[e.operation];if(!r)throw new Error(`Remote worker configuration does not provide a ${e.operation} function. Redeploy the Lambda workers and reinstall remote-workers.json.`);let n=await this.#r(e,r),o=n.Payload?JSON.parse(new TextDecoder().decode(n.Payload)):null;if(n.FunctionError)throw new Error(`Remote ${e.operation} worker failed (${n.FunctionError}): ${JSON.stringify(o)}`);if(!o||typeof o!="object")throw new Error(`Remote ${e.operation} worker returned no JSON response.`);let s=o;if(s.schemaVersion!==U||s.operation!==e.operation||s.jobId!==e.jobId||s.taskId!==e.taskId)throw new Error(`Remote ${e.operation} worker returned a mismatched response.`);return s}async readResult(e){if(!e.resultKey)throw new Error(`Remote ${e.operation} response does not contain a resultKey.`);let r=se(e.resultKey,this.config.workspace.prefix),n=await this.s3.send(new GetObjectCommand({Bucket:this.config.workspace.bucket,Key:r}));if(!n.Body)throw new Error(`Remote worker result has no body: ${r}`);return JSON.parse(await n.Body.transformToString("utf8"))}async readObject(e){if(e.bucket!==this.config.workspace.bucket)throw new Error(`Remote worker object bucket mismatch: ${e.bucket}.`);let r=se(e.key,this.config.workspace.prefix),n=await this.s3.send(new GetObjectCommand({Bucket:this.config.workspace.bucket,Key:r,...e.versionId?{VersionId:e.versionId}:{}}));if(!n.Body)throw new Error(`Remote worker object has no body: ${r}`);let o=await n.Body.transformToByteArray();if(o.byteLength!==e.bytes)throw new Error(`Remote worker object length mismatch for ${r}: expected ${e.bytes}, received ${o.byteLength}.`);if(de(o)!==e.sha256)throw new Error(`Remote worker object checksum mismatch for ${r}.`);return o}async readObjectText(e){return new TextDecoder("utf8",{fatal:true}).decode(await this.readObject(e))}async health(e){let r=this.config.functions[e];if(!r)throw new Error(`Remote worker configuration does not provide a ${e} function.`);let n=`${e}-${Date.now()}`,o=await this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify({schemaVersion:U,operation:"health",jobId:"health",taskId:n}),"utf8")})),s=o.Payload?JSON.parse(new TextDecoder().decode(o.Payload)):null;if(o.FunctionError||!s||typeof s!="object")throw new Error(`Remote ${e} health check failed: ${JSON.stringify(s)}`);return s}async writeWorkspaceObject(e){let r=se(e.key,this.config.workspace.prefix),n=typeof e.body=="string"?Buffer.from(e.body,"utf8"):e.body,o=de(n),s=await this.s3.send(new PutObjectCommand({Bucket:this.config.workspace.bucket,Key:r,Body:n,ContentType:e.contentType,...e.cacheControl?{CacheControl:e.cacheControl}:{},Metadata:{sha256:o,...e.metadata??{}}}));return {bucket:this.config.workspace.bucket,key:r,sha256:o,bytes:n.byteLength,contentType:e.contentType,...s.ETag?{etag:s.ETag}:{},...s.VersionId?{versionId:s.VersionId}:{}}}async copyWorkspaceObject(e,r){if(e.bucket!==this.config.workspace.bucket)throw new Error(`Remote worker object bucket mismatch: ${e.bucket}.`);let n=se(e.key,this.config.workspace.prefix),o=se(r,this.config.workspace.prefix),s=`${e.bucket}/${n.split("/").map(i=>encodeURIComponent(i)).join("/")}`,a=await this.s3.send(new CopyObjectCommand({Bucket:e.bucket,Key:o,CopySource:s,MetadataDirective:"COPY"}));return {...e,key:o,...a.CopyObjectResult?.ETag?{etag:a.CopyObjectResult.ETag}:{},...a.VersionId?{versionId:a.VersionId}:{}}}};var wn="remote-workers.json";function Kt(t={}){let e=String(t.explicitPath??"").trim();if(e)return I.resolve(e);let r=String(t.runtimeDir??process.env.STATIC_PUBLISHER_RUNTIME_DIR??process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR??"").trim();return r?I.join(I.resolve(r),wn):""}function Rn(){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return t.trim()?I.resolve(t):""}function kn(t){let e=String(process.env.STATIC_PUBLISHER_REMOTE_EXPORT_MANIFEST_PATH||"").trim();if(e)return I.resolve(e);let r=Rn();if(r)return I.join(r,"remote-export-manifest.json");let n=I.resolve(t.outputDir);return I.join(I.dirname(n),`.${I.basename(n)}-remote-export-manifest.json`)}function Pn(t){let e=I.posix.normalize(String(t||"").replace(/\\/g,"/").replace(/^\/+/,""));if(!e||e==="."||e===".."||e.startsWith("../")||/^[A-Za-z]:/.test(e))throw new Error(`Invalid remote export relative path: ${t}`);return e}async function Ut(t){try{let e=JSON.parse(await O.readFile(kn(t),"utf8"));if(e.schemaVersion!==1||typeof e.jobId!="string"||!e.workspace||typeof e.workspace.bucket!="string"||typeof e.workspace.prefix!="string"||!e.objects||typeof e.objects!="object"||!e.assetMap||typeof e.assetMap!="object")return null;let r=e;for(let[n,o]of Object.entries(r.objects)){if(Pn(n),!o||o.relativePath!==n||o.object?.bucket!==r.workspace.bucket)return null;se(o.object.key,r.workspace.prefix);}return r}catch{return null}}function Ye(t){return String(t??"").split(";").map(e=>e.trim().toLowerCase()).filter(Boolean).join(";")}var Ht="wpsuite-sha256",Jt="wpsuite-normalized-sha256",et="public, max-age=0, must-revalidate",Tn=/(?:^|[-_:.])(id|uid|nonce|token|hash|instance)(?:$|[-_:.])/i,tt=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,jn=["SIGINT","SIGTERM"],De=new Set,Me=new Map,Vt=null;function On(t){De.add(t);let e=false;return ()=>{e||(e=true,De.delete(t));}}async function Mn(){let t=[...De];t.length!==0&&await Promise.allSettled(t.map(async e=>{De.delete(e),await O.rm(e,{recursive:true,force:true});}));}function An(){if(!(Me.size>0))for(let t of jn){let e=()=>{Vt||(Vt=Mn().finally(()=>{for(let[r,n]of Me)process.off(r,n);Me.clear(),process.exit(1);}));};Me.set(t,e),process.on(t,e);}}An();function Dn(t,e){let r=String(process.env.STATIC_PUBLISHER_CRAWL_MANIFEST_PATH||"").trim();if(r)return I.resolve(r);let n=e.trim();return n?I.join(I.resolve(n),"crawl-manifest.json"):I.join(I.resolve(t),".crawl-manifest.json")}function ae(t){return I.normalize(t).split(I.sep).join("/")}function Bt(t,e){let r=I.relative(I.resolve(t),I.resolve(e));return !r||r.startsWith("..")||I.isAbsolute(r)?null:ae(r)}async function Wn(t,e,r){let n=Dn(t.outputDir,e),o;try{o=await O.readFile(n,"utf8");}catch(c){return c.code==="ENOENT"?(r.warn("Deploy rewrite guard disabled because the crawl manifest is missing.",{manifestPath:n,source:"deploy-guard"}),null):(r.warn("Deploy rewrite guard disabled because the crawl manifest could not be read.",{manifestPath:n,error:c instanceof Error?c.message:String(c),source:"deploy-guard"}),null)}let s;try{s=JSON.parse(o);}catch(c){return r.warn("Deploy rewrite guard disabled because the crawl manifest is invalid JSON.",{manifestPath:n,error:c instanceof Error?c.message:String(c),source:"deploy-guard"}),null}let a=new Map,i=new Map,l=0,u=0;for(let[c,d]of Object.entries(s.pages||{})){let g=String(d?.outputPath||"").trim(),f=g?Bt(t.outputDir,g):null;if(f){let b=typeof d?.contentType=="string"&&d.contentType?d.contentType:null;b&&i.set(f,b);}!g||d?.rewriteComplete===true||f&&(l++,a.has(f)||a.set(f,{kind:"page",sourceUrl:c,outputPath:I.resolve(g),relativePath:f}));}for(let[c,d]of Object.entries(s.assets||{})){let g=String(d?.outputPath||"").trim(),f=d?.isText===true,b=g?Bt(t.outputDir,g):null;if(b){let y=typeof d?.contentType=="string"&&d.contentType?d.contentType:null;y&&i.set(b,y);}!g||!f||d?.rewriteComplete===true||b&&(u++,a.has(b)||a.set(b,{kind:"asset",sourceUrl:c,outputPath:I.resolve(g),relativePath:b}));}return {manifestPath:n,byRelativePath:a,contentTypeByRelativePath:i,pendingPages:l,pendingTextAssets:u}}function Ln(t){return t&&(tt.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)?"__hex__":/^[0-9]{8,}$/.test(t)?"__num__":/^(?=.*[a-z])(?=.*\d)[a-z0-9]{8,}$/i.test(t)?"__alnum__":t)}function Ze(t){return t.split(/([_:.\-/=?&#]+)/g).map((e,r)=>r%2===1?e:Ln(e)).join("")}function Fn(t){return t.split(/([_:.\-/=?&#]+)/g).map((e,r)=>r%2===1?e:tt.test(e)?"__uuid__":/^[0-9a-f]{6,}$/i.test(e)?"__hex__":/^[0-9]{6,}$/.test(e)?"__num__":/^[a-z0-9_-]{6,}$/i.test(e)?"__id__":e).join("")}function We(t,e){return Array.isArray(t)?t.map(r=>We(r,e)):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).map(([r,n])=>[r,We(n,r)])):typeof t!="string"?t:e&&Tn.test(e)?Fn(t):tt.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)||/^[0-9]{8,}$/.test(t)?Ze(t):t}function _n(t){return t.replace(/((?:https?:\/\/[^"'\s>]+|\/)(?:wp-content|wp-includes)\/[^"'\s>?]+)\?ver=[A-Za-z0-9._-]+(?=$|[#"'])/gi,"$1")}function Nn(t,e){let r=e.trim();if((r.startsWith("{")||r.startsWith("[")||r.startsWith('"'))&&t.startsWith("data-"))try{let o=JSON.parse(r);return JSON.stringify(We(o))}catch{}if(t.startsWith("data-")&&/^[A-Za-z0-9+/=]+$/.test(r))try{let o=Buffer.from(r,"base64").toString("utf8"),s=JSON.parse(o),a=JSON.stringify(We(s));return Buffer.from(a,"utf8").toString("base64")}catch{}return e}function Kn(t,e){let r=t.toLowerCase();return r==="class"?e.split(/(\s+)/).map((n,o)=>o%2===1?n:Ze(n)).join(""):r==="id"||r==="for"||r==="aria-controls"||r==="aria-labelledby"||r==="aria-describedby"||r==="aria-owns"||r==="aria-activedescendant"||r==="name"?Ze(e):r==="href"||r==="src"?_n(e):Nn(r,e)}function Un(t){return t.replace(/<([a-z][^\s/>]*)([^<>]*?)>/gi,(e,r,n)=>{if(r.startsWith("/"))return e;let o=n.replace(/\s([:@a-zA-Z_][-:.a-zA-Z0-9_]*?)=(['"])([\s\S]*?)\2/g,(s,a,i,l)=>{let u=Kn(a,l);return ` ${a}=${i}${u}${i}`});return `<${r}${o}>`})}function Re(t){let e=I.extname(t).toLowerCase();return [".html",".htm",".xml",".xsl",".txt"].includes(e)||["robots.txt","sitemap.xml"].includes(I.basename(t))}function Ae(t,e){return [t.replace(/^\/+|\/+$/g,""),e.replace(/^\/+/,"")].filter(Boolean).join("/")}async function Vn(t,e,r,n){let o=new Map,s,a=0;do{a++;let i=await Z(`S3 list objects page ${a} for s3://${e}/${r||""}`,3e5,({httpOptions:l})=>t.send(new ListObjectsV2Command({Bucket:e,Prefix:r||void 0,ContinuationToken:s}),l));for(let l of i.Contents||[]){if(!l.Key)continue;let u=(l.ETag||"").replace(/^"|"$/g,"").toLowerCase(),c=Number(l.Size??0);o.set(l.Key,{etag:u,size:c,cacheControl:void 0,contentType:void 0});}s=i.NextContinuationToken,n.debug(`Listed S3 keys page ${a}: ${o.size} keys so far`);}while(s);return o}async function Bn(t,e,r,n){if(n.has(r))return n.get(r)??null;try{let o=await Z(`S3 head object ${r}`,3e5,({httpOptions:a})=>t.send(new HeadObjectCommand({Bucket:e,Key:r}),a)),s={etag:(o.ETag||"").replace(/^"|"$/g,"").toLowerCase(),size:Number(o.ContentLength??0),cacheControl:o.CacheControl?.trim()||null,contentType:o.ContentType?.trim()||null};return n.set(r,s),s}catch{return n.set(r,null),null}}async function zn(t,e,r,n){if(n.cacheControl!==void 0&&n.contentType!==void 0)return {cacheControl:n.cacheControl,contentType:n.contentType};try{let o=await Z(`S3 head cache metadata ${r}`,3e5,({httpOptions:s})=>t.send(new HeadObjectCommand({Bucket:e,Key:r}),s));n.cacheControl=o.CacheControl?.trim()||null,n.contentType=o.ContentType?.trim()||null;}catch{n.cacheControl=null,n.contentType=null;}return {cacheControl:n.cacheControl,contentType:n.contentType}}function zt(t){return String(t||"").split(",").map(e=>e.trim().toLowerCase()).filter(Boolean).sort().join(",")}async function qn(t,e,r,n){let o=[...new Set(Array.from(r).filter(Boolean))];if(o.length===0)return n.info("No explicitly tombstoned S3 objects to delete."),[];n.info(`Deleting ${o.length} explicitly tombstoned S3 object(s)\u2026`);for(let s=0;s<o.length;s+=1e3){let a=o.slice(s,s+1e3);if(a.length===0)continue;let i=await Z(`S3 delete objects batch ${Math.floor(s/1e3)+1}`,3e5,({httpOptions:l})=>t.send(new DeleteObjectsCommand({Bucket:e,Delete:{Objects:a.map(u=>({Key:u}))}}),l));if(i.Errors&&i.Errors.length>0){let l=i.Errors.map(u=>`${u.Key||"(unknown)"}: ${u.Code||"DeleteFailed"}`);throw new Error(`S3 reported ${l.length} object deletion error(s): ${l.join(", ")}`)}n.info(`Deleted batch of ${a.length} object(s).`);for(let l of a)n.debug(` deleted: ${l}`);}return o}function Hn(t){return createHash("md5").update(t).digest("hex")}function le(t){return createHash("sha256").update(t).digest("hex")}function Le(t){return createHash("sha256").update(Un(t.toString("utf8"))).digest("hex")}async function Jn(t,e,r,n){if(n.has(r))return n.get(r)??null;try{let a=((await Z(`S3 head object metadata ${r}`,3e5,({httpOptions:i})=>t.send(new HeadObjectCommand({Bucket:e,Key:r}),i))).Metadata?.[Ht]||"").trim().toLowerCase()||null;return n.set(r,a),a}catch{return n.set(r,null),null}}async function Gn(t,e,r,n,o){if(n.has(r))return n.get(r)??null;try{let a=((await Z(`S3 head object normalized metadata ${r}`,3e5,({httpOptions:i})=>t.send(new HeadObjectCommand({Bucket:e,Key:r}),i))).Metadata?.[Jt]||"").trim().toLowerCase();if(a)return n.set(r,a),a}catch{return n.set(r,null),null}if(o.has(r)){let s=o.get(r)??null;return n.set(r,s),s}try{let a=await(await Z(`S3 get object ${r}`,3e5,({httpOptions:l})=>t.send(new GetObjectCommand({Bucket:e,Key:r}),l))).Body?.transformToByteArray(),i=a?Le(Buffer.from(a)):null;return o.set(r,i),n.set(r,i),i}catch{return o.set(r,null),n.set(r,null),null}}function Qn(t){return t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"profile"}function Yn(t,e){let r=t,n=Object.entries(e).sort((o,s)=>s[0].length-o[0].length);for(let[o,s]of n)o&&(r=r.split(o).join(s));return r}async function Zn(t,e,r,n){let o=I.join(t,"asset-map.json"),s;try{s=await O.readFile(o,"utf8");}catch(l){if(l.code==="ENOENT")return;throw l}let a=JSON.parse(s);if(!a||typeof a!="object")return;let i=Object.fromEntries(Object.entries(a).map(([l,u])=>{let c=String(u??"");return e.urlRewriteMode==="absolute"&&e.targetOrigin&&r.targetOrigin&&e.targetOrigin!==r.targetOrigin&&(c=c.split(e.targetOrigin).join(r.targetOrigin)),c=Yn(c,n),[l,c]}));await O.writeFile(o,JSON.stringify(i,null,2),"utf8");}async function Xn(t,e,r,n,o,s,a){let i=t.targetOrigin!==e.targetOrigin,l=Object.keys(n).length>0;if(!r||!i&&!l)return {outputDir:t.outputDir,cleanup:async()=>{}};if(i&&t.urlRewriteMode!=="absolute")throw new Error(`Deployment profile "${r}" changes targetOrigin, but the base crawl output must use urlRewriteMode "absolute" for multi-target redeploys.`);let u=I.join(I.dirname(t.outputDir),`.deploy-profile-${Qn(r)}-${Date.now()}`),c=On(u);o.info(`Preparing deployment profile "${r}" from existing crawl output to ${u}...`);try{if(await O.rm(u,{recursive:!0,force:!0}),s){await O.mkdir(u,{recursive:!0});for(let y of s){let R=I.join(t.outputDir,y),S=I.join(u,y);await O.mkdir(I.dirname(S),{recursive:!0}),await O.copyFile(R,S);}}else await O.cp(t.outputDir,u,{recursive:!0});let d={...t,sourceOrigin:t.targetOrigin,targetOrigin:e.targetOrigin,extraReplacements:n,outputDir:u},g=1;o.info(`Rewriting text files for deployment profile "${r}"...`);let f={files:s,onStart:({totalFiles:y,workerCount:R})=>{g=R,o.info(`Rewriting ${y} text file(s) for deployment profile "${r}" with ${R} worker(s).`);},onProgress:({index:y,totalFiles:R,changedTextFiles:S,file:P,changed:h})=>{let j=`Rewriting [${y}/${R}] ${P} (${h?"rewrote":"checked"}; ${S} changed so far)`;R<=200||y<=5||y%10===0||y===R?(o.progress(j,{file:P,index:y,totalFiles:R,changed:h,changedTextFiles:S,workerCount:g}),o.info(j)):o.debug(j);}},b=a?await Wt(d,{},{...a,options:f}):await $t(d,{},f);return await Zn(u,t,e,n),o.info(`Prepared deployment profile "${r}" in ${u} (${b} rewritten text file(s)).`),{outputDir:u,cleanup:async()=>{c(),await O.rm(u,{recursive:!0,force:!0});}}}catch(d){throw o.error(`Failed to prepare deployment profile "${r}" temporary output.`,{tempDir:u,outputDir:t.outputDir,error:d instanceof Error?d.message:String(d),...d instanceof Error&&d.stack?{stack:d.stack}:{}}),await O.rm(u,{recursive:true,force:true}).catch(()=>{}),c(),await o.flush().catch(()=>{}),d}}function Gt(t,e){let r=o=>o.replace(/^\/+|\/+$/g,""),n=t.targets.find(o=>o.bucketName===e.s3.bucket&&r(o.prefix)===r(e.s3.prefix)&&o.region===e.s3.region);if(!n)throw new Error(`No CDK Lambda deployment target matches s3://${e.s3.bucket}/${e.s3.prefix||""} in ${e.s3.region}. Redeploy the CDK with this target and reinstall remote-workers.json.`);return n}function eo(t,e){if(!t||typeof t!="object")throw new Error("Remote deploy result must be a JSON object.");let r=t;if(r.schemaVersion!==U||r.response?.operation!=="deploy-copy"||r.response.jobId!==e.jobId||r.response.taskId!==e.taskId||!r.detail||!Array.isArray(r.detail.objects)||!Array.isArray(r.detail.deletedKeys)||!Array.isArray(r.detail.deleteErrors))throw new Error("Remote deploy result has an invalid envelope.");return r}async function Fe(t){let e=null;for(let r=1;r<=Math.max(1,Math.min(5,t.maxAttempts));r+=1){let n=H(`deploy-${t.batchIndex}-a${r}-${Date.now()}`,"taskId");try{let o=await t.client.invoke({schemaVersion:U,operation:"deploy-copy",jobId:t.jobId,taskId:n,targetId:t.targetId,items:t.items,...t.deleteRelativeKeys?{deleteRelativeKeys:t.deleteRelativeKeys}:{}}),s=eo(await t.client.readResult(o),o);if(s.response.status==="partial")throw new Error(`Worker reported ${s.response.failedItems} failed item(s).`);return s}catch(o){e=o;}}throw new Error(`Remote deploy task failed after ${t.maxAttempts} attempt(s): ${e instanceof Error?e.message:String(e)}`,{cause:e})}async function to(t){let e=Gt(t.remoteConfig,t.config),r=H(`deploy-${Date.now()}-${le(Buffer.from(`${e.id}:${t.config.outputDir}`)).slice(0,12)}`,"jobId"),n=pe(t.remoteConfig.workspace.prefix,"jobs",r,"deploy-inputs");t.log.progress(`Staging export for Lambda deploy: 0/${t.files.length}`,{phase:"deploy-stage",index:0,totalFiles:t.files.length,uploaded:0,skipped:0,failed:0,mode:"lambda-s3-copy"});let o=0,s=[],a=Math.max(1,Math.min(16,t.concurrency*2)),i=0;await Promise.all(Array.from({length:Math.min(a,t.files.length)},async()=>{for(;;){let P=i;if(P>=t.files.length)return;i+=1;let h=t.files[P],k=await O.readFile(I.join(t.config.outputDir,h)),j=t.contentTypeByRelativePath?.get(h)||Ot.lookup(h)||"application/octet-stream",v=t.revalidateFiles.has(ae(h))?et:Re(h)?t.config.s3.htmlCacheControl:t.config.s3.assetCacheControl,E=le(k),x=Re(h)?Le(k):void 0,C=`${n}/files/${le(Buffer.from(h))}-${I.basename(h)}`.replace(/\/+/g,"/");await t.client.writeWorkspaceObject({key:C,body:k,contentType:String(j),cacheControl:v,metadata:{"wpsuite-sha256":E,...x?{"wpsuite-normalized-sha256":x}:{}}}),s[P]={sourceKey:C,targetRelativeKey:h,sha256:E,...x?{normalizedSha256:x}:{},bytes:k.byteLength,contentType:String(j),cacheControl:v},o+=1,(o===t.files.length||o<=5||o%25===0)&&t.log.progress(`Staging export for Lambda deploy: ${o}/${t.files.length}`,{phase:"deploy-stage",index:o,totalFiles:t.files.length,staged:o,mode:"lambda-s3-copy"});}}));let l=[],u=Math.max(1,Math.min(500,t.batchSize));for(let P=0;P<s.length;P+=u)l.push(s.slice(P,P+u));let c=[],d=[],g=[],f=0,b=0,y=0,R=Math.max(1,Math.min(Math.max(1,t.concurrency),l.length));if(t.log.progress(`Lambda deploy: 0/${t.files.length}`,{phase:"deploy-copy",index:0,totalFiles:t.files.length,uploaded:0,skipped:0,failed:0,mode:"lambda-s3-copy",workerCount:R,completedBatches:0,totalBatches:l.length}),await Promise.all(Array.from({length:R},async()=>{for(;;){let P=y;if(P>=l.length)return;y+=1;let h=Date.now(),k=await Fe({client:t.client,jobId:r,targetId:e.id,batchIndex:P+1,items:l[P],maxAttempts:t.maxAttempts}),j=0,v=0,E=0;for(let C of k.detail.objects)f+=1,C.status==="copied"?(c.push(C.targetKey),j+=1):C.status==="skipped"?(d.push(C.targetKey),v+=1):(g.push(C.targetKey),E+=1),t.log.debug(`Lambda deploy ${C.status}: ${C.targetKey}`,{phase:"deploy-copy",batch:P+1,sourceKey:C.sourceKey,targetKey:C.targetKey,status:C.status,...C.error?{error:C.error}:{}});b+=1;let x=Date.now()-h;t.log.info(`Lambda deploy batch ${P+1}/${l.length} completed: ${j} copied, ${v} skipped unchanged, ${E} failed.`,{phase:"deploy-copy",batch:P+1,totalBatches:l.length,items:k.detail.objects.length,copied:j,skipped:v,failed:E,elapsedMs:x,elapsedSeconds:Math.round(x/10)/100,workerExporterVersion:k.response.exporterVersion,...k.requestId?{lambdaRequestId:k.requestId}:{},...k.completedAt?{workerCompletedAt:k.completedAt}:{}}),t.log.progress(`Lambda deploy: ${f}/${t.files.length}`,{phase:"deploy-copy",index:f,totalFiles:t.files.length,uploaded:c.length,skipped:d.length,failed:g.length,mode:"lambda-s3-copy",workerCount:R,completedBatches:b,totalBatches:l.length});}})),g.length>0)throw new Error(`Remote deployment failed for ${g.length} object(s).`);let S=[];for(let P=0;P<t.deletedFiles.length;P+=1e3){let h=t.deletedFiles.slice(P,P+1e3);if(h.length===0)continue;let k=await Fe({client:t.client,jobId:r,targetId:e.id,batchIndex:l.length+Math.floor(P/1e3)+1,items:[],deleteRelativeKeys:h,maxAttempts:t.maxAttempts});S.push(...k.detail.deletedKeys),t.log.progress(`Lambda deploy deletions: ${S.length}/${t.deletedFiles.length}`,{phase:"deploy-delete",index:S.length,totalFiles:t.deletedFiles.length,deleted:S.length,mode:"lambda-s3-copy"});}return {uploadedKeys:c,skippedKeys:d,failedKeys:g,deletedKeys:S}}async function ro(t){let e=Gt(t.remoteConfig,t.config),r=H(`deploy-manifest-${Date.now()}-${le(Buffer.from(e.id)).slice(0,12)}`,"jobId"),n=t.objects.map(f=>({sourceKey:f.object.key,targetRelativeKey:f.relativePath,sha256:f.object.sha256,bytes:f.object.bytes,contentType:f.contentType||"application/octet-stream",cacheControl:t.revalidateFiles.has(ae(f.relativePath))?et:Re(f.relativePath)?t.config.s3.htmlCacheControl:t.config.s3.assetCacheControl})),o=[],s=Math.max(1,Math.min(500,t.batchSize));for(let f=0;f<n.length;f+=s)o.push(n.slice(f,f+s));let a=[],i=[],l=[],u=0,c=0,d=Math.max(1,Math.min(Math.max(1,t.concurrency),Math.max(1,o.length)));if(t.log.progress(`Lambda deploy: 0/${n.length}`,{phase:"deploy-copy",index:0,totalFiles:n.length,mode:"lambda-s3-native",workerCount:d}),await Promise.all(Array.from({length:o.length===0?0:d},async()=>{for(;;){let f=u;if(f>=o.length)return;u+=1;let b=await Fe({client:t.client,jobId:r,targetId:e.id,batchIndex:f+1,items:o[f],maxAttempts:t.maxAttempts});for(let y of b.detail.objects)c+=1,y.status==="copied"?a.push(y.targetKey):y.status==="skipped"?i.push(y.targetKey):l.push(y.targetKey);t.log.progress(`Lambda deploy: ${c}/${n.length}`,{phase:"deploy-copy",index:c,totalFiles:n.length,uploaded:a.length,skipped:i.length,failed:l.length,mode:"lambda-s3-native",workerCount:d});}})),l.length>0)throw new Error(`Remote deployment failed for ${l.length} object(s).`);let g=[];for(let f=0;f<t.deletedFiles.length;f+=1e3){let b=t.deletedFiles.slice(f,f+1e3);if(b.length===0)continue;let y=await Fe({client:t.client,jobId:r,targetId:e.id,batchIndex:o.length+Math.floor(f/1e3)+1,items:[],deleteRelativeKeys:b,maxAttempts:t.maxAttempts});g.push(...y.detail.deletedKeys);}return {uploadedKeys:a,skippedKeys:i,failedKeys:l,deletedKeys:g}}async function no(t,e,r,n,o){let s={...e,jobId:H(`profile-${le(Buffer.from(n)).slice(0,16)}-${Date.now()}`,"jobId"),objects:{},assetMap:{...e.assetMap},generatedAt:new Date().toISOString()},a=0,i=Math.max(1,Math.min(Math.max(1,o),Math.max(1,r.length)));return await Promise.all(Array.from({length:r.length===0?0:i},async()=>{for(;;){let l=a;if(l>=r.length)return;a+=1;let u=r[l],c=pe(t.config.workspace.prefix,"jobs",s.jobId,"profile",le(Buffer.from(u.relativePath)),I.basename(u.relativePath));s.objects[u.relativePath]={...u,object:await t.copyWorkspaceObject(u.object,c)};}})),s}async function Qt(t=process.argv.slice(2)){let e=await Ee(),r=ft(t),n=ht(e,r),o=I.resolve(n.config.logDir||"logs"),s=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",a=s?I.join(I.resolve(s),"deploy-diff.json"):"",i=new we(o,"deploy.log.jsonl",n.config.logLevel??"info"),l=n.profile?.extraReplacements??{},u=async()=>{};try{let c=await gt(e);if(t.includes("--content-sync")&&c?.schemaVersion!==2)throw new Error("Content-sync deployment requires a valid schema-2 targeted deploy plan.");let g=await mt(e);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=e.remoteWorkers?.rewrite?.enabled===!0,b=e.remoteWorkers?.deploy?.enabled===!0,y=null,R=null;if(f||b){let m=Kt({runtimeDir:s});if(!m)throw new Error("Remote Lambda workers are enabled, but the runtime directory is unknown.");y=await Nt(m);let $=!1;R=new Oe(y,{},{onProgress:p=>{if(p.operation==="rewrite"){i.debug("Lambda rewrite task progress.",{remoteWorkerOperation:p.operation,remoteWorkerTaskId:p.taskId,remoteWorkerStatus:p.status,remoteWorkerCompletedItems:p.completedItems,remoteWorkerFailedItems:p.failedItems,remoteWorkerTotalItems:p.totalItems,remoteWorkerUpdatedAt:p.updatedAt});return}i.progress(`Lambda ${p.operation} batch: ${p.completedItems+p.failedItems}/${p.totalItems}`,{remoteWorkerOperation:p.operation,remoteWorkerTaskId:p.taskId,remoteWorkerStatus:p.status,remoteWorkerCompletedItems:p.completedItems,remoteWorkerFailedItems:p.failedItems,remoteWorkerTotalItems:p.totalItems,remoteWorkerUpdatedAt:p.updatedAt});},onProgressError:p=>{$||($=!0,i.warn("Lambda progress status could not be read; task execution continues.",{error:p.message}));}});}let S=b&&f&&e.remoteWorkers?.render?.enabled===!0&&R&&y?.functions.asset?await Ut(e):null;if(S&&R&&y){if(S.workspace.bucket!==y.workspace.bucket||S.workspace.prefix!==y.workspace.prefix)throw new Error("Remote export manifest workspace does not match remote-workers.json.");let m=n.config,$=m.s3SyncMode??"sdk-upload-delete";if(c?.schemaVersion===2&&c.deletedFiles.length>0&&$!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let p=c?.schemaVersion===2?[...c.uploadGroups.assets,...c.uploadGroups.content,...c.uploadGroups.listings,...c.uploadGroups.resources,...c.uploadGroups.sitemapLeaves,...c.uploadGroups.sitemapIndexes]:c?.changedFiles??[];if(c?.schemaVersion===2){let W=[...new Set(p)],z=[...new Set(c.changedFiles)];if(W.length!==z.length||z.some(Y=>!W.includes(Y)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let B=!!c&&!c.fullSyncRequired?[...new Set(p.map(ae))]:Object.keys(S.objects).sort(),he=B.filter(W=>!S.objects[W]);if(he.length>0)throw new Error(`Remote export manifest is missing ${he.length} planned object(s): ${he.slice(0,10).join(", ")}`);let re=S,T=B.map(W=>S.objects[W]);n.name&&(e.targetOrigin!==m.targetOrigin||Object.keys(l).length>0)&&(re=await no(R,S,T,n.name||"default",e.concurrency),await Lt(m,re,re.assetMap,{client:R,jobId:re.jobId,concurrency:e.concurrency,batchSize:25,maxAttempts:2,onBatchProgress:({completedItems:W,totalItems:z,completedBatches:Y,totalBatches:xe,changedTextFiles:Ne})=>{i.progress(`Lambda deployment-profile rewrite: ${W}/${z} files; ${Y}/${xe} batches completed`,{phase:"rewrite-text",execution:"lambda",index:W,totalFiles:z,completedBatches:Y,totalBatches:xe,changedTextFiles:Ne});}}),T=B.map(W=>re.objects[W])),n.name&&i.info(`Using deployment profile: ${n.name}`),i.info(`Starting S3-native Lambda deploy - s3://${m.s3.bucket}/${m.s3.prefix||""} (${m.s3.region}).`),i.mark("deploy");let L=await ro({client:R,remoteConfig:y,config:m,objects:T,deletedFiles:$==="sdk-upload-delete"?c?.deletedFiles??[]:[],revalidateFiles:new Set((c?.revalidateFiles??[]).map(ae)),concurrency:e.concurrency,batchSize:50,maxAttempts:2,log:i});a&&(await O.mkdir(I.dirname(a),{recursive:!0}),await O.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:"lambda-s3-native",summary:{totalFiles:T.length,eligibleFiles:T.length,uploaded:L.uploadedKeys.length,skipped:L.skippedKeys.length,rejected:0,failed:L.failedKeys.length,deleted:L.deletedKeys.length,protected:0,...n.name?{profile:n.name}:{}},uploadedKeys:L.uploadedKeys,skippedKeys:L.skippedKeys,rejectedKeys:[],failedKeys:L.failedKeys,deletedKeys:L.deletedKeys,protectedRemoteOnlyKeys:[]},null,2),"utf8")),c?.schemaVersion!==2&&await Ie(e),i.endMark("deploy"),await i.flush();return}let P=await Xn(e,n.config,n.name,l,i,c?.schemaVersion===2?c.changedFiles:void 0,f&&R?{client:R,jobId:`profile-${Date.now()}`,concurrency:e.remoteWorkers?.rewrite?.concurrency??e.rewriteConcurrency,batchSize:e.remoteWorkers?.rewrite?.batchSize??25,maxAttempts:e.remoteWorkers?.rewrite?.maxAttempts??2,onStageProgress:({index:m,totalFiles:$,file:p})=>{(m===1||m===$||m%25===0)&&i.progress(`Staging deployment-profile rewrite: ${m}/${$}`,{phase:"rewrite-stage",index:m,totalFiles:$,file:p,execution:"lambda"});},onBatchProgress:({completedItems:m,totalItems:$,completedBatches:p,totalBatches:N,changedTextFiles:B})=>{i.progress(`Lambda deployment-profile rewrite: ${m}/${$} files; ${p}/${N} batches completed`,{phase:"rewrite-text",execution:"lambda",index:m,totalFiles:$,completedBatches:p,totalBatches:N,changedTextFiles:B});}}:void 0);u=P.cleanup;let h={...n.config,outputDir:P.outputDir},k=h.s3SyncMode??"sdk-upload-delete";if(c?.schemaVersion===2&&c.deletedFiles.length>0&&k!=="sdk-upload-delete")throw new Error("Content-sync tombstones require the sdk-upload-delete S3 sync mode.");let j=c?.schemaVersion!==2&&P.outputDir!==e.outputDir&&(e.targetOrigin!==n.config.targetOrigin||Object.keys(l).length>0),v=!!c&&!c.fullSyncRequired&&!j;if(c?.schemaVersion===2&&!v)throw new Error("Content-sync deployment cannot widen into a full-output deployment.");n.name&&i.info(`Using deployment profile: ${n.name}`),i.info(`Starting deploy \u2014 s3://${h.s3.bucket}/${h.s3.prefix||""} (region: ${h.s3.region})`),i.info(`S3 sync mode: ${k}`),c&&c.fullSyncRequired?i.info("Deploy plan requests a full sync; scanning the whole output tree."):c&&j?i.info("Ignoring incremental deploy plan because deployment-profile rewrites require a full sync."):v&&i.info(`Using incremental deploy plan: ${c.changedFiles.length} changed file(s), ${c.deletedFiles.length} deleted file(s).`),i.mark("deploy");let E=new S3Client({region:h.s3.region}),x=P.outputDir===e.outputDir?await Wn(e,s,i):null,C=c?.schemaVersion===2?[...c.uploadGroups.assets,...c.uploadGroups.content,...c.uploadGroups.listings,...c.uploadGroups.resources,...c.uploadGroups.sitemapLeaves,...c.uploadGroups.sitemapIndexes]:c?.changedFiles??[];if(c?.schemaVersion===2){let m=[...new Set(C)],$=[...new Set(c.changedFiles)];if(m.length!==$.length||$.some(p=>!m.includes(p)))throw new Error("Content-sync deploy-plan upload groups do not cover the exact changed-file set.")}let M=v?(await Promise.all(C.map(async m=>{try{return (await O.stat(I.join(h.outputDir,m))).isFile()?m:null}catch{if(c?.schemaVersion===2)throw new Error(`Content-sync planned upload is missing: ${m}`);return null}}))).filter(m=>m!==null):await Fr(["**/*"],{cwd:h.outputDir,onlyFiles:!0,dot:!0}),A=[],V=[],w=M.filter(m=>{let $=x?.byRelativePath.get(ae(m));if(!$)return !0;let p=Ae(h.s3.prefix,m);return A.push(m),V.push(p),i.reject($.kind,$.sourceUrl||m,"rewrite not completed; deploy upload blocked","deploy-guard",{file:m,key:p,outputPath:$.outputPath,manifestPath:x?.manifestPath}),!1}),rt=new Set((c?.revalidateFiles||[]).map(ae)),nt=new Set((v?w:M).map(m=>Ae(h.s3.prefix,m)));x&&(x.pendingPages>0||x.pendingTextAssets>0)&&i.info(`Deploy rewrite guard loaded ${x.pendingPages} pending page(s) and ${x.pendingTextAssets} pending text asset(s) from crawl manifest.`,{manifestPath:x.manifestPath,pendingPages:x.pendingPages,pendingTextAssets:x.pendingTextAssets,source:"deploy-guard"}),A.length>0&&i.warn(`Deploy rewrite guard blocked ${A.length} file(s) from upload because final crawl rewrite is incomplete.`,{rejected:A.length,manifestPath:x?.manifestPath,source:"deploy-guard"}),v?i.info(`Using ${w.length} eligible planned changed file(s) from deploy plan for upload${A.length>0?` (${A.length} blocked by deploy rewrite guard)`:""}.`):i.info(`Found ${M.length} file(s) in output directory "${h.outputDir}"${A.length>0?`; ${w.length} remain eligible for upload after deploy rewrite guard filtering`:""}.`),i.progress("Deploy preflight: comparing local output with remote S3 state.",{phase:"deploy",mode:k,totalFiles:w.length,scannedFiles:M.length,rejected:A.length,deploymentProfile:n.name||"",s3Bucket:h.s3.bucket,s3Prefix:h.s3.prefix||"",targetedPlan:v,deployGuardEnabled:P.outputDir===e.outputDir});let _=0,D=0,J=0,me=[],ee=[],te=[],ce=[],ue=[],fe=new Map,Yt=new Map,Zt=new Map,Xt=new Map,er=new Map;if(b){if(!R||!y)throw new Error("Remote deploy worker client was not initialized.");if(k!=="sdk-upload-delete"&&k!=="sdk-upload-only")throw new Error(`Unsupported remote deploy mode: ${k}`);let m=await to({client:R,remoteConfig:y,config:h,files:w,deletedFiles:k==="sdk-upload-delete"?c?.deletedFiles??[]:[],revalidateFiles:rt,contentTypeByRelativePath:x?.contentTypeByRelativePath,concurrency:h.remoteWorkers?.deploy?.concurrency??h.assetDownloadConcurrency,batchSize:h.remoteWorkers?.deploy?.batchSize??50,maxAttempts:h.remoteWorkers?.deploy?.maxAttempts??2,log:i});me.push(...m.uploadedKeys),ee.push(...m.skippedKeys),te.push(...m.failedKeys),ce=m.deletedKeys,_=me.length,D=ee.length,J=te.length,i.info(`Lambda deploy complete: ${_} copied, ${D} skipped unchanged, ${ce.length} deleted, ${J} failed.`),a&&(await O.mkdir(I.dirname(a),{recursive:!0}),await O.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:"lambda-s3-copy",summary:{totalFiles:M.length,eligibleFiles:w.length,uploaded:_,skipped:D,rejected:V.length,failed:J,deleted:ce.length,protected:0,...n.name?{profile:n.name}:{}},uploadedKeys:me,skippedKeys:ee,rejectedKeys:V,failedKeys:te,deletedKeys:ce,protectedRemoteOnlyKeys:[]},null,2),"utf8")),c?.schemaVersion!==2&&await Ie(e),i.endMark("deploy"),await i.flush();return}v||(i.info("Listing existing S3 objects to detect unchanged files..."),fe=await Vn(E,h.s3.bucket,h.s3.prefix,i),i.info(`Found ${fe.size} existing key(s) in S3.`));let tr=async m=>fe.has(m)?fe.get(m)??null:v?Bn(E,h.s3.bucket,m,Yt):null;for(let m of w){let $=I.join(h.outputDir,m),p=Ae(h.s3.prefix,m),N=x?.contentTypeByRelativePath.get(m),B=N&&N!=="application/octet-stream"?N:Ot.lookup(m)||N||"application/octet-stream",he=rt.has(ae(m)),re=he?et:Re(m)?h.s3.htmlCacheControl:h.s3.assetCacheControl,T=_+D+J+1;w.length<=200||T<=5||T%10===0||T===w.length?(i.progress(`Uploading [${T}/${w.length}] ${p} (${B})`,{file:m,key:p,index:T,totalFiles:w.length,contentType:B,mode:k}),i.info(`Uploading [${T}/${w.length}] ${p} (${B})`)):i.debug(`Uploading [${T}/${w.length}] ${p} (${B})`);try{let q=await O.readFile($),L=await tr(p),W=null,z=null;if(L){let Y=await zn(E,h.s3.bucket,p,L),xe=!he||zt(Y.cacheControl)===zt(re),Ne=Ye(Y.contentType)===Ye(String(B)),Ke=xe&&Ne,rr=q.byteLength;if(L.size===rr){let ve=L.etag.includes("-");if(L.etag!==""&&!ve){let nr=Hn(q);if(L.etag===nr&&Ke){D++,w.length<=200||D<=5||D%25===0?(i.progress(`Skipped unchanged [${T}/${w.length}] ${p}`,{file:m,key:p,index:T,totalFiles:w.length,uploaded:_,skipped:D,failed:J,mode:k,reason:"etag-md5-match"}),i.info(`Skipped unchanged [${T}/${w.length}] ${p}`)):i.debug(`Skipped unchanged [${T}/${w.length}] ${p}`),ee.push(p);continue}}W=le(q);let ot=await Jn(E,h.s3.bucket,p,Zt);if(ot&&ot===W&&Ke){D++,w.length<=200||D<=5||D%25===0?(i.progress(`Skipped unchanged [${T}/${w.length}] ${p}`,{file:m,key:p,index:T,totalFiles:w.length,uploaded:_,skipped:D,failed:J,mode:k,reason:"metadata-sha256-match"}),i.info(`Skipped unchanged [${T}/${w.length}] ${p}`)):i.debug(`Skipped unchanged [${T}/${w.length}] ${p}`),ee.push(p);continue}}if(Re(m)){z=Le(q);let ve=await Gn(E,h.s3.bucket,p,Xt,er);if(ve&&ve===z&&Ke){D++,w.length<=200||D<=5||D%25===0?(i.progress(`Skipped semantically unchanged [${T}/${w.length}] ${p}`,{file:m,key:p,index:T,totalFiles:w.length,uploaded:_,skipped:D,failed:J,mode:k,reason:"normalized-html-match"}),i.info(`Skipped semantically unchanged [${T}/${w.length}] ${p}`)):i.debug(`Skipped semantically unchanged [${T}/${w.length}] ${p}`),ee.push(p);continue}}}W=W??le(q),z=z??(Re(m)?Le(q):null),await Z(`S3 upload ${p}`,9e5,({abortController:Y})=>new Upload({client:E,abortController:Y,params:{Bucket:h.s3.bucket,Key:p,Body:q,ContentType:B,CacheControl:re,Metadata:{[Ht]:W,...z?{[Jt]:z}:{}}}}).done()),_++,me.push(p),(_%25===0||_===w.length)&&(i.progress(`Uploaded ${_}/${w.length} file(s)\u2026`,{uploaded:_,skipped:D,failed:J,totalFiles:w.length,mode:k}),i.info(`Uploaded ${_}/${w.length} file(s)\u2026`));}catch(q){J++,te.push(p),i.error(`Failed to upload ${p}: ${q.message}`,{key:p,error:String(q)});}}if(i.info(`Upload complete: ${_} uploaded, ${D} skipped unchanged, ${V.length} rejected by guard, ${J} failed.`),te.length>0||V.length>0)throw new Error(`Deployment stopped before deletion because ${te.length} upload(s) failed and ${V.length} upload(s) were rejected.`);if(k==="sdk-upload-delete"){let m=new Set((c?.deletedFiles??[]).map(p=>Ae(h.s3.prefix,p))),$=[...m].filter(p=>!nt.has(p));if(!v&&(ue=[...fe.keys()].filter(N=>!nt.has(N)).filter(N=>!m.has(N)),ue.length>0)){i.warn(`Protected ${ue.length} remote-only S3 object(s) from deletion because the crawl did not provide explicit tombstones.`,{protected:ue.length,source:"deploy-delete-guard"});for(let N of ue)i.debug(` protected remote-only object: ${N}`);}ce=await qn(E,h.s3.bucket,v?$:$.filter(p=>fe.has(p)),i);}else i.info("Sync mode is sdk-upload-only \u2014 skipping stale object deletion.");a&&(await O.mkdir(I.dirname(a),{recursive:!0}),await O.writeFile(a,JSON.stringify({generatedAt:new Date().toISOString(),mode:k,summary:{totalFiles:M.length,eligibleFiles:w.length,uploaded:me.length,skipped:ee.length,rejected:V.length,failed:te.length,deleted:ce.length,protected:ue.length,...n.name?{profile:n.name}:{}},uploadedKeys:me,skippedKeys:ee,rejectedKeys:V,failedKeys:te,deletedKeys:ce,protectedRemoteOnlyKeys:ue},null,2),"utf8")),c?.schemaVersion!==2&&await Ie(e),i.endMark("deploy"),await i.flush();}finally{await u().catch(()=>{});}}Qt().catch(async t=>{console.error(t);try{let r=(await Ee().catch(()=>null))?.logDir??"logs",n=new we(r,"deploy.log.jsonl","debug");n.error(`Unhandled error: ${t instanceof Error?t.message:String(t)}`,t instanceof Error?{stack:t.stack}:void 0),await n.flush();}catch{}process.exit(1);});
|