@smart-cloud/publisher-exporter 1.1.59 → 1.1.61

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.
@@ -1,3 +1,3 @@
1
- import {pathToFileURL}from'url';import P from'fs/promises';import {existsSync,createReadStream,createWriteStream}from'fs';import m from'path';import {spawn}from'child_process';import {randomUUID,createHash}from'crypto';import Ge from'http';import be from'https';import {pipeline}from'stream/promises';import {createGzip}from'zlib';function he(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))].sort()}function G(e){return Array.isArray(e)?e.map(G):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,G(n)])):e}function ze(e){return JSON.stringify(G(e))}function J(e){return createHash("sha256").update(ze(e)).digest("hex")}function fe(e){return J({schemaVersion:1,wordpressFingerprint:e.wordpressFingerprint,targetFingerprint:e.targetFingerprint,sourceOrigin:e.sourceOrigin,sitemapPaths:[...e.sitemapPaths].sort(),blockedPathPrefixes:[...e.blockedPathPrefixes].sort(),assetPathPrefixes:[...e.assetPathPrefixes].sort(),noJavaScriptRenderPathPrefixes:[...e.noJavaScriptRenderPathPrefixes].sort(),urlRewriteMode:e.urlRewriteMode})}function He(e){let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error(`Unsupported source origin protocol: ${t.protocol}`);return t.hash="",t.search="",t.pathname=t.pathname.replace(/\/+$/,""),t.toString().replace(/\/$/,"")}function N(e){let t=he((e.postTypes??[]).map(r=>String(r).toLowerCase().replace(/[^a-z0-9_-]/g,"")));if(t.length===0)throw new Error("Content-sync requires at least one public post type.");let n=he((e.listingPaths??[]).map(r=>{let i=String(r).trim();if(!i)return "";let a=new URL(i,"https://content-sync.invalid/");if(a.origin!=="https://content-sync.invalid"&&/^https?:\/\//i.test(i))throw new Error("Content-sync listing routes must be same-site paths.");let s=`/${a.pathname.replace(/^\/+|\/+$/g,"")}`;return s==="/"?"/":`${s}/`}));return {postTypes:t,listingPaths:n,includeSubsites:e.includeSubsites===true,includePostTypeArchives:e.includePostTypeArchives!==false,includeTaxonomyArchives:e.includeTaxonomyArchives!==false,includeAuthorArchives:e.includeAuthorArchives===true,includeDateArchives:e.includeDateArchives===true,includePostsPage:e.includePostsPage!==false,includeSitemapChain:e.includeSitemapChain!==false}}function Y(e,t,n){return J({schemaVersion:1,sourceOrigin:He(e),ruleId:t.trim(),scope:N(n)})}function Z(e){return J({schemaVersion:1,...e})}function Se(e){return e.replace(/((?:x-static-publisher-token|authorization|proxy-authorization|x-api-key|aws-access-key-id|aws-secret-access-key|aws-session-token)\s*:\s*)[^\r\n]+/gi,"$1[REDACTED]").replace(/\b(Basic|Bearer)\s+[^\s]+/gi,"$1 [REDACTED]").replace(/([?&](?:token|access_token|refresh_token|api_key|key|nonce)=)[^&\s]+/gi,"$1[REDACTED]").replace(/((?:"|')?(?:runtimeToken|siteKey|nonce|accessToken|refreshToken|accessKeyId|secretAccessKey|sessionToken)(?:"|')?\s*[:=]\s*(?:"|'))[^"']+/gi,"$1[REDACTED]")}var ye=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";ye?m.join(ye,"current-progress.json"):"";Promise.resolve();var Ye="wp-json/smartcloud-static-publisher/v1/content-sync/",Ze=25*1024*1024,T=class extends Error{status;code;constructor(t,n,r){super(r),this.name="ContentSyncApiError",this.status=t,this.code=n;}},L=class{options;constructor(t){if(!t.runtimeToken.trim())throw new Error("Content-sync requires a WordPress runtime token.");this.options={...t,timeoutMs:t.timeoutMs??6e4};}endpoint(t,n="content-sync"){let r=this.options.sourceOrigin.replace(/\/+$/,"")+"/",i=n==="content-sync"?Ye:`wp-json/smartcloud-static-publisher/v1/${n}/`;return new URL(`${i}${t}`,r)}async post(t,n,r="content-sync"){let i=this.endpoint(t,r),a=Buffer.from(JSON.stringify(n),"utf8"),s=i.protocol==="https:"?be:Ge,o=i.protocol==="https:"?new be.Agent({rejectUnauthorized:!this.options.ignoreHttpsErrors}):void 0;return new Promise((c,u)=>{let g=s.request(i,{method:"POST",agent:o,headers:{"content-type":"application/json","content-length":String(a.byteLength),"x-static-publisher-token":this.options.runtimeToken},timeout:this.options.timeoutMs},d=>{let p=[],h=0;d.on("data",S=>{if(h+=S.byteLength,h>Ze){d.destroy(new Error("Content-sync API response exceeded the size limit."));return}p.push(S);}),d.on("error",u),d.on("end",()=>{let S=Buffer.concat(p).toString("utf8"),l;try{l=S?JSON.parse(S):{};}catch{u(new T(d.statusCode??500,"invalid-json","Content-sync API returned invalid JSON."));return}let y=d.statusCode??500;if(y<200||y>=300){u(new T(y,String(l.code??"request-failed"),String(l.message??`Content-sync API request failed (${y}).`)));return}c(l);});});g.on("timeout",()=>g.destroy(new Error(`Content-sync API request timed out: ${t}`))),g.on("error",u),g.end(a);})}async head(t){return this.post("head",t)}async unboundHead(t,n){return this.post("head",{postTypes:t,includeSubsites:n})}async events(t){let n=[],r=t.afterSequence,i=new Set(t.postTypes);for(;r<t.throughSequence;){let a=await this.post("events",{...t,afterSequence:r,limit:250});if(a.fromSequence!==r||a.throughSequence!==t.throughSequence||a.nextSequence<r||a.nextSequence>t.throughSequence)throw new Error("Content-sync API returned an inconsistent event page.");if(!Array.isArray(a.items))throw new Error("Content-sync API returned a malformed event page.");let s=r;for(let o of a.items){if(!Number.isSafeInteger(o.sequence)||o.sequence<=s||o.sequence>t.throughSequence||!Number.isSafeInteger(o.postId)||o.postId<=0||!Number.isSafeInteger(o.blogId)||o.blogId<=0||!i.has(o.postType)||typeof o.operation!="string"||!o.operation)throw new Error("Content-sync API returned an invalid or out-of-scope journal event.");s=o.sequence;}if(a.items.length>0&&a.nextSequence!==s)throw new Error("Content-sync API event cursor does not match the final returned event.");if(n.push(...a.items),!a.hasMore)break;if(a.nextSequence===r)throw new Error("Content-sync API event pagination did not advance.");r=a.nextSequence;}if(t.throughSequence>t.afterSequence&&n.at(-1)?.sequence!==t.throughSequence)throw new Error("Content-sync API omitted the claimed journal high-water event.");return n}async resolveImpactFamilies(t,n){let r=await this.post("impact",{families:t,includeSubsites:n});return Array.isArray(r.families)?r.families:[]}async releaseFingerprint(t=false){let n=await this.post("fingerprint",{includeSubsites:t}),r=String(n.fingerprint||"").trim();if(!/^[a-f0-9]{64}$/.test(r))throw new Error("WordPress returned an invalid release fingerprint.");return r}async establishBaseline(t){return this.post("baseline",t)}async acknowledge(t){return this.post("ack",t)}async importCookieObservations(t){return this.post("cookie-observations",t,"privacy")}};function Xe(e){return typeof e.subscriptionType=="string"&&e.subscriptionType.trim()!==""}function et(e,t){return {...e,...t??{}}}function tt(e,t){return {...e,...t??{},invalidationPaths:[...(t?.invalidationPaths??e.invalidationPaths)||[]]}}function X(e,t){let n=String(t??e.deploymentTargetOverride??"").trim();if(!Xe(e)){if(n)throw new Error(`Deployment target "${n}" requires an active WPSuite subscription and remote publisher config.`);return {name:null,profile:null,config:e}}let r=String(n||e.defaultDeploymentProfile||"").trim();if(!r)return {name:null,profile:null,config:e};let i=e.deploymentProfiles?.[r];if(!i)throw new Error(`Unknown deployment profile "${r}". Check the linked WPSuite publisher configuration.`);return {name:r,profile:i,config:{...e,targetOrigin:i.targetOrigin??e.targetOrigin,s3:et(e.s3,i.s3),cloudFront:tt(e.cloudFront,i.cloudFront)}}}var ee=["/sitemap_index.xml","/wp-sitemap.xml","/sitemap.xml"];function we(e){let t=new Set;for(let n of [...e,...ee]){let r=String(n||"").trim();r&&t.add(r);}return [...t]}function Pe(e){let t=e.trim();return t==="."?".":t.replace(/\/$/,"")}function st(e){let t=String(e??"").trim();if(!t)return "";let n=t;if(/^https?:\/\//i.test(n))try{n=new URL(n).pathname;}catch{return ""}if(n=n.split(/[?#]/,1)[0]?.replace(/\\/g,"/").trim()??"",!n)return "";let r=n.endsWith("/"),i=n.replace(/^\/+/,"").split("/").map(s=>s.replace(/[^A-Za-z0-9._-]/g,"")).filter(s=>s.length>0&&s!=="."&&s!=="..");if(i.length===0)return "";let a=`/${i.join("/")}`;return r&&m.extname(a)===""&&(a+="/"),a==="/"?"":a}function te(e){return !e||typeof e!="object"?{}:Object.fromEntries(Object.entries(e).map(([t,n])=>[t.trim(),String(n??"")]).filter(([t])=>t.length>0))}function ot(e){if(!e||typeof e!="object")return {};let t={};for(let[n,r]of Object.entries(e)){let i=n.trim();if(!i||!r||typeof r!="object")continue;let a=r,s={};if(typeof a.targetOrigin=="string"){let c=Pe(a.targetOrigin);c&&(s.targetOrigin=c);}let o=te(a.extraReplacements);if(Object.keys(o).length>0&&(s.extraReplacements=o),a.s3&&typeof a.s3=="object"){let c={},u=a.s3;typeof u.bucket=="string"&&(c.bucket=u.bucket.trim()),typeof u.prefix=="string"&&(c.prefix=u.prefix.trim()),typeof u.region=="string"&&(c.region=u.region.trim()),typeof u.htmlCacheControl=="string"&&(c.htmlCacheControl=u.htmlCacheControl.trim()),typeof u.assetCacheControl=="string"&&(c.assetCacheControl=u.assetCacheControl.trim()),Object.keys(c).length>0&&(s.s3=c);}if(a.cloudFront&&typeof a.cloudFront=="object"){let c={},u=a.cloudFront;typeof u.distributionId=="string"&&(c.distributionId=u.distributionId.trim()),Array.isArray(u.invalidationPaths)&&(c.invalidationPaths=u.invalidationPaths.map(g=>String(g??"").trim()).filter(g=>g.length>0)),Object.keys(c).length>0&&(s.cloudFront=c);}t[i]=s;}return t}function re(e){return e==="PROFESSIONAL"||e==="AGENCY"?e:void 0}function at(e,t){if(!e||typeof e!="object")return null;let n=e,r=n.command;if(r!=="publish"&&r!=="crawl"&&r!=="deploy"&&r!=="invalidate"&&r!=="retry-timeouts"&&r!=="url"&&r!=="content-sync")return null;let i=Number.parseInt(String(n.intervalMinutes??"0"),10);if(!Number.isFinite(i)||i<1)return null;let a=String(n.id??`${r}-${t+1}`).trim();if(!a)return null;let s=String(n.deploymentProfile??"").trim(),o=String(n.url??"").trim(),c=Array.isArray(n.postTypes)?[...new Set(n.postTypes.map(g=>String(g??"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"")).filter(Boolean))]:[],u=Array.isArray(n.listingPaths)?[...new Set(n.listingPaths.map(g=>String(g??"").trim()).filter(Boolean))]:[];return r==="content-sync"&&c.length===0?null:{id:a,enabled:n.enabled!==false,command:r,intervalMinutes:i,...r==="publish"||r==="crawl"?{crawlMode:n.crawlMode==="incremental"?"incremental":"full"}:{},...(r==="publish"||r==="deploy"||r==="invalidate"||r==="content-sync")&&s?{deploymentProfile:s}:{},...o?{url:o}:{},...c.length>0?{postTypes:c}:{},...u.length>0?{listingPaths:u}:{},...typeof n.includeSubsites=="boolean"?{includeSubsites:n.includeSubsites}:{},...typeof n.includePostTypeArchives=="boolean"?{includePostTypeArchives:n.includePostTypeArchives}:{},...typeof n.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:n.includeTaxonomyArchives}:{},...typeof n.includeAuthorArchives=="boolean"?{includeAuthorArchives:n.includeAuthorArchives}:{},...typeof n.includeDateArchives=="boolean"?{includeDateArchives:n.includeDateArchives}:{},...typeof n.includePostsPage=="boolean"?{includePostsPage:n.includePostsPage}:{},...typeof n.includeSitemapChain=="boolean"?{includeSitemapChain:n.includeSitemapChain}:{}}}function Ce(e){let t=e&&typeof e=="object"?e:{},n=Array.isArray(t.rules)?t.rules.map((r,i)=>at(r,i)).filter(r=>!!r):[];return {enabled:t.enabled===true,timezone:typeof t.timezone=="string"&&t.timezone.trim()!==""?t.timezone.trim():"UTC",rules:n}}function ct(e){if(!e||typeof e!="object")return;let t=e,n={};for(let i of ["accountId","siteId"]){let a=t[i];typeof a=="string"&&a.trim()!==""&&(n[i]=a.trim());}let r=Number(t.lastUpdate??0);return Number.isFinite(r)&&r>0&&(n.lastUpdate=Math.floor(r)),t.subscriber===true&&(n.subscriber=true),Object.keys(n).length>0?n:void 0}function ie(e){let t=e&&typeof e=="object"?e:{},n=String(t.accountId??"").trim(),r=String(t.siteId??"").trim(),i=t.subscriber===true,a=ct(t.siteSettings),s={...a??{},...n?{accountId:a?.accountId??n}:{},...r?{siteId:a?.siteId??r}:{},...a?.subscriber===true||i?{subscriber:true}:{}},o={},c=String(t.apiBase??"").trim();c&&(o.apiBase=c);let u=String(t.runtimeToken??t.nonce??"").trim();u&&(o.runtimeToken=u);let g=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();g&&(o.virtualAssetBaseUrl=g),Object.keys(s).length>0&&(o.siteSettings=s);let d=re(t.subscriptionType);return d&&(o.subscriptionType=d),o}function ut(e){try{let t=new URL(e);globalThis.location=t;}catch{}}function Ae(e){return typeof e=="string"?e:e instanceof URL?e.toString():e.url}function lt(e,t){let n=new Headers(e instanceof Request?e.headers:void 0);if(t?.headers)for(let[r,i]of new Headers(t.headers).entries())n.set(r,i);return n}async function Ie(e,t,n=5){let r=new URL(Ae(e)),i=String(t?.method??(e instanceof Request?e.method:"GET")).toUpperCase(),a=r.protocol==="http:"?Ge:be,s=lt(e,t);return await new Promise((o,c)=>{let u=a.request(r,{method:i,headers:Object.fromEntries(s.entries()),...r.protocol==="https:"?{rejectUnauthorized:false}:{}},g=>{let d=[];g.on("data",p=>{d.push(Buffer.isBuffer(p)?p:Buffer.from(p));}),g.on("error",c),g.on("end",()=>{let p=g.statusCode??0,h=g.headers.location;if(n>0&&h&&[301,302,303,307,308].includes(p)){o(Ie(new URL(h,r),{method:p===303?"GET":i},n-1));return}let S=new Headers;for(let[l,y]of Object.entries(g.headers))Array.isArray(y)?S.set(l,y.join(", ")):typeof y=="string"&&S.set(l,y);o(new Response(Buffer.concat(d),{status:p,statusText:g.statusMessage??"",headers:S}));});});u.on("error",c),u.end();})}function dt(e){let t=ie(e.wpsuite),n={...t.siteSettings??{},...t.siteSettings?.subscriber===true||t.subscriptionType==="PROFESSIONAL"||t.subscriptionType==="AGENCY"?{subscriber:true}:{}},r=String(n.accountId??"").trim(),i=String(n.siteId??"").trim(),a=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();if(e.wpsuite={...t.apiBase?{apiBase:t.apiBase}:{},...t.runtimeToken?{runtimeToken:t.runtimeToken}:{},...a?{virtualAssetBaseUrl:a}:{},...Object.keys(n).length>0?{siteSettings:n}:{},...t.subscriptionType?{subscriptionType:t.subscriptionType}:{}},!r||!i||!a)return false;ut(e.sourceOrigin);let s=globalThis,c={...s.WpSuite??{},siteSettings:n,uploadUrl:a};return t.apiBase&&(c.apiBase=t.apiBase),s.WpSuite=c,true}async function gt(e){let t=String(e.wpsuite?.virtualAssetBaseUrl??e.wpsuite?.uploadUrl??"").trim();if(!dt(e)){let i=e.wpsuite?.siteSettings,a=[String(i?.accountId??"").trim()?"":"accountId",String(i?.siteId??"").trim()?"":"siteId",t?"":"virtualAssetBaseUrl"].filter(Boolean);return {remote:null,diagnostic:{status:"invalid-runtime",virtualAssetBaseUrl:t,subscriptionType:null,error:`Missing WP Suite runtime field(s): ${a.join(", ")}.`,requests:[]}}}let n=globalThis.fetch,r=[];try{typeof n=="function"&&/^https?:\/\//i.test(t)&&(globalThis.fetch=(async(c,u)=>{let g=Ae(c);if(g.startsWith(t)){let d=(()=>{try{return new URL(g).pathname}catch{return g}})();try{let p=e.ignoreHttpsErrors&&g.startsWith("https://")?await Ie(c,u):await n(c,u);return r.push({path:d,status:p.status,ok:p.ok,error:null}),p}catch(p){throw r.push({path:d,status:null,ok:!1,error:p instanceof Error?p.message:String(p)}),p}}return n(c,u)}));let{getConfig:i}=await import('@smart-cloud/wpsuite-core'),a=await i("publisher"),s=a&&typeof a=="object"?a:null,o=re(s?.subscriptionType);return {remote:s,diagnostic:{status:s?"loaded":"unavailable",virtualAssetBaseUrl:t,subscriptionType:o??null,error:s?null:"WP Suite publisher config loader returned no configuration.",requests:r}}}catch(i){return {remote:null,diagnostic:{status:"unavailable",virtualAssetBaseUrl:t,subscriptionType:null,error:i instanceof Error?i.message:String(i),requests:r}}}finally{typeof n=="function"&&(globalThis.fetch=n);}}function pt(e,t){let n=ot(t?.deploymentProfiles),r=String(t?.defaultDeploymentProfile??"").trim(),i=n[r]?r:"",a=re(t?.subscriptionType),s=ie(e.wpsuite);return {...e,scheduler:Ce(t?.scheduler),deploymentProfiles:n,defaultDeploymentProfile:i,...a?{subscriptionType:a}:{},wpsuite:{...s,...s.siteSettings||a?{siteSettings:{...s.siteSettings??{},...s.siteSettings?.subscriber===true||a==="PROFESSIONAL"||a==="AGENCY"?{subscriber:true}:{}}}:{},...a?{subscriptionType:a}:{}}}}function ne(e,t){let r=String(e||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!r)return t;let i=r.split("/").map(a=>a.trim()).filter(a=>a.length>0&&a!=="."&&a!=="..");return i.length>0?i.join("/"):t}function mt(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?m.resolve(e):""}function ve(e,t,n){let r=String(t||"").trim();return r&&m.isAbsolute(r)?m.resolve(r):m.resolve(e,ne(r,n))}async function W(e,t={}){let n=String(e??"").trim()||process.env.PUBLISHER_CONFIG||"publisher.config.json",r=await P.readFile(n,"utf8"),i=JSON.parse(r);i.sourceOrigin=i.sourceOrigin.replace(/\/$/,""),i.targetOrigin=Pe(i.targetOrigin),i.ignoreHttpsErrors??=false,i.outputDir=String(i.outputDir||"export").trim()||"export",i.urlRewriteMode||=i.targetOrigin==="."?"relative":"absolute",i.noJavaScriptRenderPathPrefixes||=[],i.seedPaths||=[],i.generated404RequestPath=st(i.generated404RequestPath),i.sitemapPaths||=[...ee],i.allowedAssetHosts||=[],i.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],i.blockedPathPrefixes||=[],i.blockedSearchFragments||=[],i.concurrency||=1,i.maxPages||=0,i.extraReplacements=te(i.extraReplacements),i.postCrawlCopyMap=te(i.postCrawlCopyMap),i.logDir=String(i.logDir||"logs").trim()||"logs",i.verbose??=false,i.logLevel||=i.verbose?"debug":"info",i.s3SyncMode||="sdk-upload-delete",i.readiness||={waitForSelector:null,waitForFunction:null,timeoutMs:1500,fallbackWaitMs:1500},i.readiness.timeoutMs??=1500,i.readiness.fallbackWaitMs??=1500,i.viewport||={width:1440,height:1200},i.navigationTimeoutMs||=3e4,i.assetDownloadConcurrency=Number(i.assetDownloadConcurrency)>0?Number(i.assetDownloadConcurrency):i.concurrency,i.rewriteConcurrency=Number(i.rewriteConcurrency)>0?Number(i.rewriteConcurrency):i.assetDownloadConcurrency,i.wpsuite=ie(i.wpsuite),i.scheduler=Ce(void 0),i.deploymentProfiles={},i.defaultDeploymentProfile="",i.deploymentTargetOverride=String(i.deploymentTargetOverride??"").trim();let a=await gt(i);t.onRemotePublisherConfigDiagnostic?.(a.diagnostic);let s=pt(i,a.remote),o=mt(),c=o?m.resolve(o,".."):"";return c?(s.outputDir=ve(c,s.outputDir,"export"),s.logDir=ve(c,s.logDir,"logs")):(m.isAbsolute(s.outputDir)||(s.outputDir=ne(s.outputDir,"export")),m.isAbsolute(s.logDir)||(s.logDir=ne(s.logDir,"logs"))),s}function Re(e){let t=e.split(/\r?\n/).map(r=>r.trim()).filter(Boolean),n=[...t].reverse().find(r=>/^(?:Error|[A-Za-z][A-Za-z0-9]*Error):\s/.test(r));return n||(t.find(r=>!r.startsWith("at "))??"")}function se(e){let t=m.resolve(e);return {state:m.join(t,"content-sync-state.json"),current:m.join(t,"content-sync-current.json"),impact:m.join(t,"content-sync-impact-plan.json"),checkpoint:m.join(t,"content-sync-checkpoint.json"),baseline:m.join(t,"content-sync-baseline.json"),activeRules:m.join(t,"content-sync-active-rules.json"),releaseCutoff:m.join(t,"content-sync-release-cutoff.json"),candidateManifest:m.join(t,"content-sync-candidate-manifest.json"),trustedManifest:m.join(t,"crawl-manifest.json"),invalidation:m.join(t,"content-sync-invalidation.json"),deployPlan:m.join(t,"deploy-plan.json")}}async function oe(e,t){await qe(e.activeRules,{contractVersion:1,evaluatedAt:new Date().toISOString(),entries:t});}async function qe(e,t){await P.mkdir(m.dirname(e),{recursive:true});let n=`${e}.${process.pid}.${Date.now()}.tmp`;await P.writeFile(n,JSON.stringify(t,null,2),"utf8"),await P.rename(n,e);}async function xe(e){try{return JSON.parse(await P.readFile(e,"utf8"))}catch(t){if(t.code==="ENOENT")return null;throw new Error(`Invalid or unreadable content-sync state file ${e}: ${t instanceof Error?t.message:String(t)}`,{cause:t})}}async function ht(e){let t=await xe(e.current);if(t===null)return null;let n=t;if(n.schemaVersion!==1||typeof n.jobId!="string"||typeof n.phase!="string"||!Number.isSafeInteger(n.fromSequence)||!Number.isSafeInteger(n.toSequence))throw new Error("Invalid content-sync current-range state.");return n}async function De(e){let t=await xe(e.state);if(t===null)return {schemaVersion:1,updatedAt:"",rules:{}};let n=t;if(n.schemaVersion!==1||typeof n.updatedAt!="string"||!n.rules||typeof n.rules!="object"||Array.isArray(n.rules))throw new Error("Invalid content-sync state store.");return n}async function ke(e,t){await qe(e.state,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Te(e,t){let n=await ht(e);return !n||n.coalesceKey!==t?false:(await Promise.all([e.current,e.checkpoint,e.impact,e.candidateManifest,e.invalidation,e.deployPlan].map(async r=>{try{await P.unlink(r);}catch(i){if(i.code!=="ENOENT")throw i}})),true)}function Le(e){let t=String(e.command??"").trim();return (t==="publish"||t==="crawl")&&e.crawlMode==="incremental"||t==="content-sync"}var ae=new Map;async function Ee(e){let t=m.resolve(e),n=ae.get(t);if(n!==void 0)return n;try{let r=JSON.parse(await P.readFile(t,"utf8")),i=String(r.version??"").trim();return ae.set(t,i),i}catch{return ae.set(t,""),""}}var $=class extends Error{request;step;constructor(t,n){super(`Stop requested during ${n}.`),this.name="StopRequestedError",this.request=t,this.step=n;}},vt="queue-mutation.lock",Pt=5e3,Ct=3e4;function At(e){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",n=process.env.STATIC_PUBLISHER_EXPORTER_DIR||process.cwd(),r=process.env.PUBLISHER_CONFIG||"",i=1;for(let o=0;o<e.length;o++){let c=e[o];c==="--runtime-dir"?t=e[++o]||"":c.startsWith("--runtime-dir=")?t=c.slice(14):c==="--exporter-dir"?n=e[++o]||n:c.startsWith("--exporter-dir=")?n=c.slice(15):c==="--config"?r=e[++o]||"":c.startsWith("--config=")?r=c.slice(9):c==="--max-jobs"?i=Number.parseInt(e[++o]||"1",10):c.startsWith("--max-jobs=")&&(i=Number.parseInt(c.slice(11),10));}if(!t)throw new Error("Missing runtime dir. Use --runtime-dir or STATIC_PUBLISHER_RUNTIME_DIR.");let a=m.resolve(t),s=r?m.resolve(r):m.join(a,"config.json");return {runtimeDir:a,exporterDir:m.resolve(n),configPath:s,maxJobs:Number.isFinite(i)&&i>0?i:1}}async function w(e,t){try{let n=await P.readFile(e,"utf8");return JSON.parse(n)}catch(n){if((n&&typeof n=="object"&&"code"in n?String(n.code||""):"")!=="ENOENT"){let i=n instanceof Error?n.message:String(n);console.warn(`[queue-runner] failed to read JSON ${e}: ${i}`);}return t}}async function v(e,t){await P.mkdir(m.dirname(e),{recursive:true}),await P.writeFile(e,JSON.stringify(t,null,2),"utf8");}function Be(e){return m.join(e,vt)}async function It(e){await new Promise(t=>setTimeout(t,e));}async function Rt(e){let t=Be(e),n=Date.now()+Pt;for(;;)try{await P.mkdir(m.dirname(t),{recursive:!0}),await P.writeFile(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()},null,2),{encoding:"utf8",flag:"wx"});return}catch(r){if((r&&typeof r=="object"&&"code"in r?String(r.code||""):"")!=="EEXIST")throw r;let a=await P.stat(t).catch(()=>null);if(a&&Date.now()-a.mtimeMs>Ct){await P.unlink(t).catch(()=>{});continue}if(Date.now()>=n)throw new Error("Timed out acquiring queue mutation lock.",{cause:r});await It(50);}}async function qt(e){await P.unlink(Be(e)).catch(()=>{});}async function F(e,t){await Rt(e);try{return await t()}finally{await qt(e);}}function Me(e){return m.join(e,"queue-runner-heartbeat.json")}function ge(e){return m.join(e,"current-progress.json")}function ce(e){return m.join(e,"scheduler-state.json")}function xt(e,t){let r=String(e||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!r)return t;let i=r.split("/").map(a=>a.trim()).filter(a=>a.length>0&&a!=="."&&a!=="..");return i.length>0?i.join("/"):t}async function Ue(e){let t=await w(e.configPath||"",null),n=m.resolve(e.runtimeDir,".."),i=(typeof t?.logDir=="string"?t.logDir:"").trim();return i&&m.isAbsolute(i)?m.resolve(i):m.resolve(n,xt(i,"logs"))}function ue(e,t){return String(e||"").trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||t}function Dt(e){let t=e?new Date(e):new Date;return (Number.isNaN(t.getTime())?new Date:t).toISOString().replace(/[-:]/g,"").replace(/\.\d{3}Z$/,"Z")}function kt(e){return [Dt(e.endedAt||e.startedAt),ue(e.command||"job","job"),ue(e.id||"job","job"),ue(e.status||"finished","finished")].join("-")}function Tt(e){return e.endsWith(".log.jsonl")||e.endsWith(".errors.jsonl")||e.endsWith(".rejected.jsonl")?true:["current-crawl-event.json","rejected.jsonl","ignored.jsonl","skipped-http.jsonl","errors.jsonl","timings.jsonl","rejected.json","ignored.json","skipped-http.json","errors.json","timings.json"].includes(e)}function Et(e){return e==="errors.json"||e==="errors.jsonl"||e.endsWith(".errors.jsonl")?"errors":e==="ignored.json"||e==="ignored.jsonl"?"ignored":e==="rejected.json"||e==="rejected.jsonl"||e.endsWith(".rejected.jsonl")?"rejected":e==="skipped-http.json"||e==="skipped-http.jsonl"?"skipped-http":e==="timings.json"||e==="timings.jsonl"?"timings":e==="current-progress.json"?"current-progress":e==="current-crawl-event.json"?"current-crawl-event":e.endsWith(".log.jsonl")?e.replace(/\.log\.jsonl$/i,"-log"):e.replace(/\.[^.]+$/u,"")||"artifact"}function Ft(e){return e.endsWith(".gz")?"application/gzip":e.endsWith(".jsonl")?"application/x-ndjson":e.endsWith(".json")?"application/json":"text/plain"}async function Q(e,t,n){let r=`${n}.gz`,i=m.join(t,r);await pipeline(createReadStream(e),createGzip({level:9}),createWriteStream(i));let[a,s]=await Promise.all([P.stat(e),P.stat(i)]);return {role:Et(n),originalFileName:n,storedFileName:r,compressed:true,compression:"gzip",contentType:Ft(r),originalSize:a.size,storedSize:s.size}}async function K(e,t){let n=await Ue(t),r=new Date().toISOString(),i=kt(e),a=m.join(n,"archive",i),s=[],o=[];await P.mkdir(a,{recursive:true});try{let d=await P.readdir(n,{withFileTypes:!0});for(let p of d){if(!p.isFile()||!Tt(p.name))continue;let h=await Q(m.join(n,p.name),a,p.name);o.push(h),s.push(h.storedFileName);}}catch(d){if((d&&typeof d=="object"&&"code"in d?String(d.code||""):"")!=="ENOENT")throw d}let c=ge(t.runtimeDir);if(existsSync(c)){let d=await Q(c,a,"current-progress.json");o.push(d),s.push(d.storedFileName);}if(e.command==="content-sync")for(let d of ["content-sync-current.json","content-sync-impact-plan.json","content-sync-checkpoint.json","content-sync-state.json","content-sync-invalidation.json","deploy-plan.json"]){let p=m.join(t.runtimeDir,d);if(!existsSync(p))continue;let h=await Q(p,a,d);o.push(h),s.push(h.storedFileName);}let u=m.join(t.runtimeDir,"privacy","cookie-observations.json");if(existsSync(u)){let d=await Q(u,a,"cookie-observations.json");o.push(d),s.push(d.storedFileName);}let g=[...s,"job.json"];return await v(m.join(a,"job.json"),{manifestVersion:1,archivedAt:r,archiveKey:i,archiveDir:a,logDir:n,runtimeDir:t.runtimeDir,exporterDir:t.exporterDir,configPath:t.configPath||"",archivedFiles:g,artifacts:o,job:e}),{archiveKey:i,archiveDir:a,archiveCreatedAt:r,archivedFiles:g,artifacts:o}}function jt(e){return m.join(e,"audit-events.jsonl")}function le(e){return m.join(e,"stop-request.json")}async function $e(e){try{let t=await P.readFile(le(e),"utf8"),n=JSON.parse(t);return n&&typeof n=="object"?n:null}catch{return null}}async function Fe(e,t){let n=await $e(e);if(!n)return null;let r=String(n.targetJobId||"").trim();return r&&r!==t?null:n}async function U(e,t){if(!t){await P.unlink(le(e)).catch(()=>{});return}let n=await $e(e);if(!n)return;let r=String(n.targetJobId||"").trim();(!r||r===t)&&await P.unlink(le(e)).catch(()=>{});}async function R(e,t){try{let n={occurredAt:t.occurredAt||new Date().toISOString(),status:t.status||"info",actorSource:t.actorSource||"queue-runner",...t};await P.mkdir(e,{recursive:!0}),await P.appendFile(jt(e),`${JSON.stringify(n)}
2
- `,"utf8");}catch{}}async function C(e,t,n){let[r,i]=await Promise.all([Ee(m.join(e.exporterDir,"package.json")),Ee(m.join(e.exporterDir,"node_modules","@smart-cloud","wpsuite-core","package.json"))]),a={checkedAt:new Date().toISOString(),status:t,pid:process.pid,nodePath:process.execPath,nodeVersion:process.version,exporterVersion:r,wpsuiteCoreVersion:i,runtimeDir:e.runtimeDir,exporterDir:e.exporterDir,...n??{}};try{await v(Me(e.runtimeDir),a);}catch{}}async function E(e){try{await P.unlink(ge(e));}catch{}}function Ot(e,t){let n=e.command;if(n!=="publish"&&n!=="crawl"&&n!=="deploy"&&n!=="invalidate"&&n!=="retry-timeouts"&&n!=="url"&&n!=="content-sync")return null;let r=Number.parseInt(String(e.intervalMinutes??"0"),10);if(!Number.isFinite(r)||r<1)return null;let i=(e.id||`${n}-${t+1}`).trim();if(!i)return null;let a=e.enabled!==false,s=typeof e.url=="string"?e.url.trim():"",o=typeof e.deploymentProfile=="string"?e.deploymentProfile.trim():"",c=Array.isArray(e.postTypes)?[...new Set(e.postTypes.map(d=>String(d).trim()).filter(Boolean))]:[],u=Array.isArray(e.listingPaths)?[...new Set(e.listingPaths.map(d=>String(d).trim()).filter(Boolean))]:[],g=(n==="publish"||n==="crawl")&&e.crawlMode==="incremental"?"incremental":"full";return n==="url"&&!s||n==="content-sync"&&c.length===0?null:{id:i,enabled:a,command:n,intervalMinutes:r,...n==="publish"||n==="crawl"?{crawlMode:g}:{},...(n==="publish"||n==="deploy"||n==="invalidate"||n==="content-sync")&&o?{deploymentProfile:o}:{},...s?{url:s}:{},...c.length>0?{postTypes:c}:{},...u.length>0?{listingPaths:u}:{},...typeof e.includeSubsites=="boolean"?{includeSubsites:e.includeSubsites}:{},...typeof e.includePostTypeArchives=="boolean"?{includePostTypeArchives:e.includePostTypeArchives}:{},...typeof e.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:e.includeTaxonomyArchives}:{},...typeof e.includeAuthorArchives=="boolean"?{includeAuthorArchives:e.includeAuthorArchives}:{},...typeof e.includeDateArchives=="boolean"?{includeDateArchives:e.includeDateArchives}:{},...typeof e.includePostsPage=="boolean"?{includePostsPage:e.includePostsPage}:{},...typeof e.includeSitemapChain=="boolean"?{includeSitemapChain:e.includeSitemapChain}:{}}}async function Jt(e){let t=await W(e.configPath).catch(()=>null),n=t?.scheduler,r=Array.isArray(n?.rules)?n.rules.map((i,a)=>Ot(i,a)).filter(i=>!!i):[];return {enabled:!!n?.enabled,timezone:typeof n?.timezone=="string"&&n.timezone.trim()?n.timezone.trim():"UTC",rules:r,wpsuite:t?.wpsuite,publisherConfig:t}}function z(e,t){if(!t)throw new Error("Content-sync scheduler requires a valid publisher config.");let n=N({postTypes:e.postTypes??[],listingPaths:e.listingPaths??[],includeSubsites:e.includeSubsites,includePostTypeArchives:e.includePostTypeArchives,includeTaxonomyArchives:e.includeTaxonomyArchives,includeAuthorArchives:e.includeAuthorArchives,includeDateArchives:e.includeDateArchives,includePostsPage:e.includePostsPage,includeSitemapChain:e.includeSitemapChain}),r=Y(t.sourceOrigin,e.id,n),i=X(t,e.deploymentProfile),a=Z({sourceOrigin:t.sourceOrigin,targetOrigin:i.config.targetOrigin,deploymentProfile:i.name||"",s3Bucket:i.config.s3.bucket,s3Prefix:i.config.s3.prefix,cloudFrontDistributionId:i.config.cloudFront.distributionId,urlRewriteMode:i.config.urlRewriteMode,extraReplacements:i.profile?.extraReplacements??{}});return `content-sync:${e.id}:${J({scopeFingerprint:r,targetFingerprint:a}).slice(0,32)}`}function Lt(e,t,n,r){let i=[n[t],r[t]].filter(s=>!!s).filter(s=>s.coalesceKey===t&&s.ruleId===e.id).map(s=>String(s.consumerId??"").trim()).filter(Boolean),a=[...new Set(i)];return a.length===1?a[0]:""}async function je(e,t){let n=se(e.runtimeDir);if(await oe(n,[]),!t?.enabled||!t.publisherConfig)return;let r=t.rules.filter(u=>u.enabled&&u.command==="content-sync");if(r.length===0)return;let[i,a]=await Promise.all([w(n.state,{}),w(n.baseline,{})]),s=i.rules??{},o=a.entries??{},c=[];for(let u of r){let g=z(u,t.publisherConfig),d=Lt(u,g,s,o);d&&c.push({ruleId:u.id,coalesceKey:g,consumerId:d});}await oe(n,c);}async function Bt(e,t,n,r,i){let s=(await w(m.join(e.runtimeDir,"content-sync-baseline.json"),{})).entries?.[r];if(!s?.consumerId||!s.scopeFingerprint||!s.baselineId)return {status:"baseline-required",reason:"No verified normal-release baseline exists for this rule scope."};try{let o=t.publisherConfig;if(!o)throw new Error("Publisher configuration is unavailable.");let c=N({postTypes:n.postTypes??[],listingPaths:n.listingPaths??[],includeSubsites:n.includeSubsites,includePostTypeArchives:n.includePostTypeArchives,includeTaxonomyArchives:n.includeTaxonomyArchives,includeAuthorArchives:n.includeAuthorArchives,includeDateArchives:n.includeDateArchives,includePostsPage:n.includePostsPage,includeSitemapChain:n.includeSitemapChain}),u=Y(o.sourceOrigin,n.id,c),g=X(o,n.deploymentProfile),d=Z({sourceOrigin:o.sourceOrigin,targetOrigin:g.config.targetOrigin,deploymentProfile:g.name||"",s3Bucket:g.config.s3.bucket,s3Prefix:g.config.s3.prefix,cloudFrontDistributionId:g.config.cloudFront.distributionId,urlRewriteMode:g.config.urlRewriteMode,extraReplacements:g.profile?.extraReplacements??{}});if(s.scopeFingerprint!==u||s.targetFingerprint!==d||!s.releaseFingerprint)return {status:"baseline-required",reason:"The verified content-sync baseline does not match the active scope or deployment target. Run a successful full or incremental publish to establish a new baseline."};let p=new L({sourceOrigin:o.sourceOrigin,runtimeToken:String(o.wpsuite?.runtimeToken||""),ignoreHttpsErrors:o.ignoreHttpsErrors}),h=await p.releaseFingerprint(c.includeSubsites),S=fe({wordpressFingerprint:h,targetFingerprint:d,sourceOrigin:o.sourceOrigin,sitemapPaths:we(o.sitemapPaths),blockedPathPrefixes:o.blockedPathPrefixes,assetPathPrefixes:o.assetPathPrefixes,noJavaScriptRenderPathPrefixes:o.noJavaScriptRenderPathPrefixes,urlRewriteMode:o.urlRewriteMode});if(s.releaseFingerprint!==S)return {status:"baseline-required",reason:"The installed WordPress release changed after the last verified content-sync baseline. Run a successful full or incremental publish to establish a new baseline."};let l=await p.head({consumerId:s.consumerId,scopeFingerprint:s.scopeFingerprint,baselineId:s.baselineId,postTypes:c.postTypes,includeSubsites:c.includeSubsites}),y=l.committedSequence;if(i?.command==="content-sync"&&i.coalesceKey===r){let b=await w(m.join(e.runtimeDir,"content-sync-current.json"),null);b?.coalesceKey===r&&Number.isSafeInteger(b.toSequence)&&(y=Math.max(y,Number(b.toSequence)));}return {status:l.headSequence>y?"pending":"current",headSequence:l.headSequence,committedSequence:l.committedSequence}}catch(o){return o instanceof T&&o.code==="baseline-required"?{status:"baseline-required",reason:o.message}:{status:"unavailable",reason:o instanceof Error?o.message:String(o)}}}async function Ne(e,t,n,r,i,a){let s=m.join(e.runtimeDir,"content-sync-state.json"),c=(await w(s,{})).rules??{},u=c[n]??{};c[n]={...u,ruleId:t,coalesceKey:n,...Number.isSafeInteger(i)?{observedHeadSequence:i}:{},...Number.isSafeInteger(a)?{committedSequence:a}:{},retryAttempt:0,nextRetryAt:null,lastError:r,baselineStatus:"required",baselineReason:r,trailingWorkDetected:Number.isSafeInteger(i)&&Number.isSafeInteger(a)?Number(i)>Number(a):!!u.trailingWorkDetected},await v(s,{schemaVersion:1,updatedAt:new Date().toISOString(),rules:c});}function de(e,t){let n=(t.url||"").trim(),r=t.crawlMode||"full",i=(t.deploymentProfile||"").trim(),a=(t.coalesceKey||"").trim();return e.some(s=>s.command===t.command&&(t.command!=="content-sync"||(s.coalesceKey||"").trim()===a)&&(s.url||"").trim()===n&&(s.crawlMode||"full")===r&&(s.deploymentProfile||"").trim()===i&&(s.status===void 0||s.status==="queued"||s.status==="retry-wait"||s.status==="running"))}async function Mt(e,t,n){if(!t.allowSchedulerAutoEnqueue)return await je(e,null),0;let r=await Jt(e);if(await je(e,r),!r.enabled||r.rules.length===0)return 0;if(t.assertActiveSubscriptionForIdentity)try{await t.assertActiveSubscriptionForIdentity(r.wpsuite??null);}catch(l){let y=l instanceof Error?l.message:String(l);return console.warn(`[queue-runner] scheduler auto-enqueue skipped: ${y}`),0}let i=m.join(e.runtimeDir,"queue.json"),a=m.join(e.runtimeDir,"current-run.json"),s=Date.now(),o=0,c=[],u=[],g=[],d=new Map,[p,h,S]=await Promise.all([w(i,[]),w(a,null),w(ce(e.runtimeDir),{lastEnqueuedBucketByRuleId:{},lastEvaluatedBucketByRuleId:{},lastCreatedBucketByRuleId:{},coalescedCountByRuleId:{}})]);for(let l of r.rules){if(!l.enabled||l.command!=="content-sync")continue;let y=Math.floor(s/(l.intervalMinutes*60*1e3)),b=S.lastEvaluatedBucketByRuleId?.[l.id]??S.lastEnqueuedBucketByRuleId?.[l.id]??-1;if(y<=b)continue;let D=z(l,r.publisherConfig);de(p,{command:l.command,deploymentProfile:l.deploymentProfile,coalesceKey:D})||d.set(l.id,await Bt(e,r,l,D,h));}await F(e.runtimeDir,async()=>{let l=await w(i,[]),y=await w(a,null),b=await w(ce(e.runtimeDir),{lastEnqueuedBucketByRuleId:{},lastEvaluatedBucketByRuleId:{},lastCreatedBucketByRuleId:{},coalescedCountByRuleId:{}});b.lastEnqueuedBucketByRuleId??={},b.lastEvaluatedBucketByRuleId??={...b.lastEnqueuedBucketByRuleId},b.lastCreatedBucketByRuleId??={...b.lastEnqueuedBucketByRuleId},b.coalescedCountByRuleId??={};let D=[...l];y&&y.status==="running"&&D.unshift(y);for(let f of r.rules){if(!f.enabled)continue;let A=f.intervalMinutes*60*1e3,x=Math.floor(s/A),j=b.lastEvaluatedBucketByRuleId[f.id]??b.lastEnqueuedBucketByRuleId[f.id]??-1;if(x<=j)continue;let O=f.command==="content-sync"?z(f,r.publisherConfig):"";b.lastEvaluatedBucketByRuleId[f.id]=x;let Ke=f.command==="content-sync"?l:D;if(de(Ke,{command:f.command,url:f.url,crawlMode:f.crawlMode,deploymentProfile:f.deploymentProfile,coalesceKey:O})){b.coalescedCountByRuleId[f.id]=(b.coalescedCountByRuleId[f.id]??0)+1,u.push(f);continue}if(f.command==="content-sync"){let V=d.get(f.id);if(!V||V.status!=="pending"){let me=V??{status:"unavailable",reason:"Content-sync demand was not checked."};me.status!=="current"&&g.push({rule:f,check:me});continue}}let H={id:randomUUID(),command:f.command,...f.command==="content-sync"?{ruleId:f.id,coalesceKey:O,attempt:0}:{},...(f.command==="publish"||f.command==="crawl")&&f.crawlMode?{crawlMode:f.crawlMode}:{},...(f.command==="publish"||f.command==="deploy"||f.command==="invalidate"||f.command==="content-sync")&&f.deploymentProfile?{deploymentProfile:f.deploymentProfile}:{},...f.url?{url:f.url}:{},enqueueSource:"scheduler",...r.wpsuite?{wpsuite:r.wpsuite}:{},status:"queued",createdAt:new Date().toISOString(),createdBy:0};l.push(H),D.push(H),c.push({job:H,rule:f}),b.lastEnqueuedBucketByRuleId[f.id]=x,b.lastCreatedBucketByRuleId[f.id]=x,o+=1;}o>0&&await v(i,l),await v(ce(e.runtimeDir),b);});for(let l of c){if(l.rule.command==="content-sync"){let y=d.get(l.rule.id);await R(e.runtimeDir,{eventType:"content-sync-demand-detected",status:"queued",actorSource:"queue-runner-scheduler",jobId:l.job.id,command:l.job.command,message:"Pending journal changes require a content-sync job.",details:{ruleId:l.rule.id,headSequence:y?.headSequence??0,committedSequence:y?.committedSequence??0}});}await R(e.runtimeDir,{eventType:"job-created",status:"queued",actorSource:"queue-runner-scheduler",jobId:l.job.id,command:l.job.command,message:"Scheduler auto-enqueued a job.",details:{ruleId:l.rule.id,intervalMinutes:l.rule.intervalMinutes,timezone:r.timezone,deploymentProfile:l.rule.deploymentProfile||"",url:l.rule.url||""}});}for(let l of u)await R(e.runtimeDir,{eventType:"content-sync-coalesced",status:"queued",actorSource:"queue-runner-scheduler",command:l.command,message:"Scheduler demand was coalesced into an existing content-sync job.",details:{ruleId:l.id}});for(let l of g){if(l.check.status==="baseline-required"){let y=z(l.rule,r.publisherConfig);await Ne(e,l.rule.id,y,l.check.reason||"A successful full or incremental publish must establish a new content-sync baseline.",l.check.headSequence,l.check.committedSequence);}await R(e.runtimeDir,{eventType:l.check.status==="baseline-required"?"content-sync-baseline-required":"content-sync-demand-check-failed",status:l.check.status==="unavailable"?"failed":"info",actorSource:"queue-runner-scheduler",command:"content-sync",message:l.check.reason||"The content-sync consumer is already at the current journal head.",details:{ruleId:l.rule.id,headSequence:l.check.headSequence??0,committedSequence:l.check.committedSequence??0}});}return o}async function Ut(e){let t={pid:process.pid,startedAt:new Date().toISOString()};await P.writeFile(e,JSON.stringify(t,null,2),{encoding:"utf8",flag:"wx"});}async function $t(e){try{await P.unlink(e);}catch{}}function Nt(e,t){let n=[m.join(e,"dist",`${t}.js`),m.join(e,`${t}.js`)];for(let r of n)if(existsSync(r))return r;throw new Error(`Cannot find ${t}.js in ${m.join(e,"dist")} or ${e}`)}async function q(e,t,n,r,i,a,s){if(s){let u=await Fe(t,s);if(u)throw new $(u,n)}let o=Nt(e,n),c={...process.env,...a??{}};return c.STATIC_PUBLISHER_RUNTIME_DIR=t,i&&(c.PUBLISHER_CONFIG=i),await new Promise((u,g)=>{let d=null,p=null,h=null,S=null,l=false,y="",b=spawn(process.execPath,[o,...r],{cwd:e,env:c,stdio:["inherit","inherit","pipe"]});b.stderr?.on("data",A=>{y+=A.toString("utf8");});let D=()=>{p&&clearInterval(p),h&&clearInterval(h),S&&clearTimeout(S);},f=async()=>{if(!(!s||d||l)){l=true;try{let A=await Fe(t,s);if(!A)return;d=A,b.kill("SIGTERM"),S=setTimeout(()=>{b.kill("SIGKILL");},1e4);}finally{l=false;}}};s&&(p=setInterval(()=>{f();},1e3),h=setInterval(()=>{(async()=>{let A=Me(t),x=await w(A,{});await v(A,{...x,checkedAt:new Date().toISOString(),status:"running",currentJobId:s||x.currentJobId||"",currentStep:n});})().catch(()=>{});},15e3)),b.on("error",A=>{D(),g(A);}),b.on("close",(A,x)=>{D();let j=Se(y).trim();if(j&&process.stderr.write(`${j}
3
- `),d){g(new $(d,n));return}if(A===0)u();else {let O=Re(j);g(new Error(`${n} exited with code ${A??-1}${x?` (signal ${x})`:""}${O?`: ${O}`:""}`));}});}),0}function Wt(e){let t=e.awsTempCreds;if(!t)return {};let n={};return typeof t.accessKeyId=="string"&&t.accessKeyId.trim()!==""&&(n.AWS_ACCESS_KEY_ID=t.accessKeyId.trim()),typeof t.secretAccessKey=="string"&&t.secretAccessKey.trim()!==""&&(n.AWS_SECRET_ACCESS_KEY=t.secretAccessKey.trim()),typeof t.sessionToken=="string"&&t.sessionToken.trim()!==""&&(n.AWS_SESSION_TOKEN=t.sessionToken.trim()),n}async function Qt(e,t){let n=s=>{if(!s||typeof s!="object")return null;let o=s,c={...o.siteSettings??{},...String(o.accountId??"").trim()&&!o.siteSettings?.accountId?{accountId:String(o.accountId).trim()}:{},...String(o.siteId??"").trim()&&!o.siteSettings?.siteId?{siteId:String(o.siteId).trim()}:{},...o.siteSettings?.subscriber===true||o.subscriber===true?{subscriber:true}:{}},u={...String(o.apiBase??"").trim()?{apiBase:String(o.apiBase).trim()}:{},...String(o.runtimeToken??o.nonce??"").trim()?{runtimeToken:String(o.runtimeToken??o.nonce).trim()}:{},...String(o.virtualAssetBaseUrl??o.uploadUrl??"").trim()?{virtualAssetBaseUrl:String(o.virtualAssetBaseUrl??o.uploadUrl).trim()}:{},...Object.keys(c).length>0?{siteSettings:c}:{},...o.subscriptionType?{subscriptionType:o.subscriptionType}:{}};return Object.keys(u).length>0?u:null},r=await W(t.configPath).catch(()=>null),i=n(r?.wpsuite);if(i)return i;let a=n(e.wpsuite);return a||null}async function Kt(e,t){return await Qt(e,t)}function pe(e){let t={...e,status:"queued"};return delete t.startedAt,delete t.endedAt,delete t.exitCode,delete t.error,delete t.stopRequestedAt,delete t.stopRequestedByUserId,delete t.stopRequestedByLogin,delete t.stopMode,delete t.stoppedStep,t}async function _t(e,t){let n=await w(ge(e.runtimeDir),null),r=n&&n.details&&typeof n.details.phase=="string"?n.details.phase.trim():"";if(r)return r;let i=n&&typeof n.currentStep=="string"?n.currentStep.trim():"";if(i)return i;let a=await Ue(e).catch(()=>"");if(a){let s=await w(m.join(a,"current-crawl-event.json"),null),o=s&&typeof s.currentStep=="string"?s.currentStep.trim():"";if(o)return o}return t}function zt(e,t){if((e.command==="publish"||e.command==="crawl")&&t==="rewrite-text")return "rewrite-text"}async function Ht(e){let t=m.join(e.runtimeDir,"queue.json"),n=m.join(e.runtimeDir,"current-run.json"),r=await F(e.runtimeDir,async()=>{let i=await w(n,null);if(!i||i.status!=="running"&&i.status!=="queued")return null;let a=await w(t,[]),s=Array.isArray(a)?a.filter(c=>c?.id!==i.id):[],o=pe(i);return await v(t,[o,...s]),await v(n,null),o});r&&(await U(e.runtimeDir,r.id),await R(e.runtimeDir,{eventType:"job-recovered",status:"queued",actorSource:"queue-runner",jobId:r.id,command:r.command,message:"Recovered stale current-run entry back into queue."}));}async function M(e,t){if(e.resumeFromStep==="rewrite-text")return;let n=m.join(t.runtimeDir,"privacy","cookie-observations.json"),r;try{let o=await P.stat(n);if(!o.isFile()||o.size>5*1024*1024)throw new Error("Cookie observation artifact is missing or exceeds 5 MiB.");r=JSON.parse(await P.readFile(n,"utf8"));}catch(o){if((o&&typeof o=="object"&&"code"in o?String(o.code||""):"")==="ENOENT")return;throw o}let i=await W(t.configPath),a=String(i.wpsuite?.runtimeToken||"").trim();if(!a)return;await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"consent-cookie-observations"}),await new L({sourceOrigin:i.sourceOrigin,runtimeToken:a,ignoreHttpsErrors:!!i.ignoreHttpsErrors}).importCookieObservations(r);}async function Vt(e,t,n){try{if((n.shouldEnforceSubscriptionOnJobExecution?.(e)??n.enforceSubscriptionOnJobExecution)&&n.assertActiveSubscriptionForIdentity){let o=await Kt(e,t);await n.assertActiveSubscriptionForIdentity(o);}let i=Wt(e),a=e.resumeFromStep==="rewrite-text"?["--resume-rewrite"]:e.crawlMode==="incremental"?["--crawl-mode","incremental"]:[],s=e.deploymentProfile?["--profile",e.deploymentProfile]:[];if(e.command==="publish")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"content-sync-release-cutoff"}),await q(t.exporterDir,t.runtimeDir,"content-sync",["--capture-baseline-cutoffs",e.id],t.configPath,i,e.id),await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:e.resumeFromStep==="rewrite-text"?"rewrite-text":"crawl"}),await q(t.exporterDir,t.runtimeDir,"crawl",a,t.configPath,i,e.id),await M(e,t),await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"deploy"}),await q(t.exporterDir,t.runtimeDir,"deploy",s,t.configPath,i,e.id),await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"invalidate"}),await q(t.exporterDir,t.runtimeDir,"invalidate",s,t.configPath,i,e.id),await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"content-sync-baseline"}),await q(t.exporterDir,t.runtimeDir,"content-sync",["--establish-baselines",e.id],t.configPath,i,e.id),{exitCode:0};if(e.command==="crawl")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:e.resumeFromStep==="rewrite-text"?"rewrite-text":"crawl"}),await q(t.exporterDir,t.runtimeDir,"crawl",a,t.configPath,i,e.id),await M(e,t),{exitCode:0};if(e.command==="deploy")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"deploy"}),await q(t.exporterDir,t.runtimeDir,"deploy",s,t.configPath,i,e.id),{exitCode:0};if(e.command==="invalidate")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"invalidate"}),await q(t.exporterDir,t.runtimeDir,"invalidate",s,t.configPath,i,e.id),{exitCode:0};if(e.command==="retry-timeouts")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"retry-timeouts"}),await q(t.exporterDir,t.runtimeDir,"crawl",["--retry-timeouts"],t.configPath,i,e.id),await M(e,t),{exitCode:0};if(e.command==="url"){let o=(e.url||"").trim();return o?(await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"url"}),await q(t.exporterDir,t.runtimeDir,"crawl",["--url",o],t.configPath,i,e.id),await M(e,t),{exitCode:0}):{exitCode:2,error:"Missing url for command 'url'"}}return e.command==="content-sync"?!e.ruleId||!e.coalesceKey?{exitCode:2,error:"Content-sync queue jobs require ruleId and coalesceKey."}:(await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"content-sync"}),await q(t.exporterDir,t.runtimeDir,"content-sync",["--job-id",e.id],t.configPath,i,e.id),await M(e,t),{exitCode:0}):{exitCode:2,error:`Unsupported command: ${e.command}`}}catch(r){return r instanceof $?{exitCode:130,error:"Job stop requested.",stopped:true,stopRequest:r.request,stoppedStep:r.step}:{exitCode:1,error:r instanceof Error?r.message:String(r)}}}function We(e){return async function(n=process.argv.slice(2)){let r=At(n),i=m.join(r.runtimeDir,"export.lock"),a=m.join(r.runtimeDir,"last-run.json");await E(r.runtimeDir),await C(r,"starting",{message:"queue-runner starting"});try{await Ut(i);}catch(s){if((s&&typeof s=="object"&&"code"in s?String(s.code||""):"")!=="EEXIST")throw s;console.log("[queue-runner] lock active, skipping"),await C(r,"lock-active",{message:"lock active, skipped this cron tick"});return}try{await Ht(r);let s=await Mt(r,e),o=0;for(let c=0;c<r.maxJobs;c++){let u=await Xt(r,e);if(u==="none"||(o+=1,u==="stopped"))break}if(o===0)await E(r.runtimeDir),await C(r,"idle",{processedJobs:o,schedulerEnqueued:s,message:"no queued jobs"});else {await E(r.runtimeDir);let c=await w(a,null),u=String(c?.status||"").trim();await C(r,u==="success"?"job-success":u==="stopped"?"job-stopped":"job-failed",{processedJobs:o,schedulerEnqueued:s,lastJobId:c?.id,lastJobCommand:c?.command,lastJobStatus:c?.status,lastJobExitCode:c?.exitCode,lastJobError:c?.error,...u==="stopped"?{currentStep:c?.stoppedStep,stopRequestedAt:c?.stopRequestedAt,stopRequestedByLogin:c?.stopRequestedByLogin,stopRequestedMode:c?.stopMode,lastStoppedStep:c?.stoppedStep,message:c?.stopMode==="requeue"?`Job stopped during ${c?.stoppedStep||c?.command||"active step"} and requeued.`:`Job stopped during ${c?.stoppedStep||c?.command||"active step"} and left out of queue.`}:{}});}}catch(s){let o=s instanceof Error?s.message:String(s);throw await C(r,"error",{message:o}),await R(r.runtimeDir,{eventType:"queue-runner-error",status:"failed",actorSource:"queue-runner",message:"Unhandled queue-runner error.",details:{error:o}}),s}finally{await $t(i);}}}async function Oe(e,t){if(t.command!=="content-sync"||!t.coalesceKey)return false;let n=se(e.runtimeDir),r=await Te(n,t.coalesceKey),i=await De(n),a=i.rules[t.coalesceKey];return a&&(i.rules[t.coalesceKey]={...a,trailingWorkDetected:true,retryAttempt:0,nextRetryAt:null,lastError:null},await ke(n,i)),r}async function Gt(e,t,n){let r=m.join(e.runtimeDir,"queue.json"),i=m.join(e.runtimeDir,"current-run.json");await F(e.runtimeDir,async()=>{let a=await w(r,[]),s=Array.isArray(a)?a.filter(u=>u?.id!==t.id):[],o=pe(t),c=zt(t,n);c?o.resumeFromStep=c:delete o.resumeFromStep,await v(r,[o,...s]),await v(i,null);});}async function Yt(e,t,n){let r=Math.max(0,t.attempt??0)+1,i=Math.min(3600*1e3,6e4*2**(r-1)),a=Math.floor(i*.2*Math.random()),s=new Date(Date.now()+i+a).toISOString(),o={...pe(t),status:"retry-wait",attempt:r,nextAttemptAt:s,error:n};if(await F(e.runtimeDir,async()=>{let c=m.join(e.runtimeDir,"queue.json"),u=m.join(e.runtimeDir,"current-run.json"),d=(await w(c,[])).filter(p=>p.id!==t.id);await v(c,[o,...d]),await v(u,null);}),t.coalesceKey){let c=m.join(e.runtimeDir,"content-sync-state.json"),g=(await w(c,{})).rules??{};g[t.coalesceKey]={...g[t.coalesceKey]??{},ruleId:t.ruleId||"",coalesceKey:t.coalesceKey,retryAttempt:r,nextRetryAt:s,lastError:n,trailingWorkDetected:true},await v(c,{schemaVersion:1,updatedAt:new Date().toISOString(),rules:g});}return o}async function Zt(e,t){if(!t.coalesceKey||!t.ruleId||!(await w(m.join(e.runtimeDir,"content-sync-state.json"),null))?.rules?.[t.coalesceKey]?.trailingWorkDetected)return null;let r=null;await F(e.runtimeDir,async()=>{let a=m.join(e.runtimeDir,"queue.json"),s=await w(a,[]);de(s,{command:"content-sync",coalesceKey:t.coalesceKey,deploymentProfile:t.deploymentProfile})||(r={id:randomUUID(),command:"content-sync",ruleId:t.ruleId,coalesceKey:t.coalesceKey,deploymentProfile:t.deploymentProfile,enqueueSource:"scheduler",wpsuite:t.wpsuite,status:"queued",attempt:0,createdAt:new Date().toISOString(),createdBy:0},await v(a,[...s,r]));});let i=r;return i&&await R(e.runtimeDir,{eventType:"content-sync-trailing-job-created",status:"queued",actorSource:"queue-runner",jobId:i.id,command:i.command,message:"Content changes after the stable cutoff created one trailing job.",details:{predecessorJobId:t.id,ruleId:t.ruleId,coalesceKey:t.coalesceKey}}),i}async function Xt(e,t){let n=m.join(e.runtimeDir,"queue.json"),r=m.join(e.runtimeDir,"current-run.json"),i=m.join(e.runtimeDir,"last-run.json"),a=new Date().toISOString(),s=await F(e.runtimeDir,async()=>{let d=await w(n,[]);if(!Array.isArray(d)||d.length===0)return null;let p=Date.parse(String(d[0]?.nextAttemptAt||""));if(Number.isFinite(p)&&p>Date.now())return null;let h={...d[0],status:"running",startedAt:a};return delete h.nextAttemptAt,await v(n,d.slice(1)),await v(r,h),h});if(!s)return "none";await E(e.runtimeDir),await R(e.runtimeDir,{eventType:"job-run-started",status:"running",actorSource:"queue-runner",jobId:s.id,command:s.command,message:"Job execution started.",details:{createdAt:s.createdAt||"",startedAt:a,createdBy:s.createdBy??null,deploymentProfile:s.deploymentProfile||"",queuedWithTempAwsCreds:!!s.awsTempCreds}}),await C(e,"running",{currentJobId:s.id,currentJobCommand:s.command,currentStep:s.command});let o=await Vt(s,e,t),c=new Date().toISOString();if(o.stopped){let d=await _t(e,o.stoppedStep||s.command),p=o.stopRequest?.mode==="requeue"?"requeue":"stop",h={...s,status:"stopped",endedAt:c,exitCode:o.exitCode,...o.error?{error:o.error}:{},stopRequestedAt:o.stopRequest?.requestedAt||"",stopRequestedByUserId:typeof o.stopRequest?.requestedByUserId=="number"?o.stopRequest.requestedByUserId:null,stopRequestedByLogin:o.stopRequest?.requestedByLogin||"",stopMode:p,stoppedStep:d},S=false;p==="requeue"?await Gt(e,s,d):(await v(r,null),S=await Oe(e,s));try{let l=await K(h,e);h.logArchiveDir=l.archiveDir,h.logArchiveCreatedAt=l.archiveCreatedAt,h.logArchiveFileCount=l.archivedFiles.length;}catch(l){h.logArchiveError=l instanceof Error?l.message:String(l);}return await v(i,h),await U(e.runtimeDir,s.id),await E(e.runtimeDir),await R(e.runtimeDir,{eventType:"job-run-stopped",status:"stopped",actorSource:"queue-runner",jobId:s.id,command:s.command,message:p==="requeue"?"Job stop requested and requeued.":"Job stop requested and removed from active execution without requeue.",details:{startedAt:s.startedAt||"",endedAt:c,deploymentProfile:s.deploymentProfile||"",stopMode:p,stopRequestedAt:o.stopRequest?.requestedAt||"",stopRequestedByLogin:o.stopRequest?.requestedByLogin||"",stopRequestedByUserId:typeof o.stopRequest?.requestedByUserId=="number"?o.stopRequest.requestedByUserId:null,stoppedStep:d,logArchiveKey:h.logArchiveError||!h.logArchiveDir?"":m.basename(h.logArchiveDir),logArchiveDir:h.logArchiveDir||"",logArchiveCreatedAt:h.logArchiveCreatedAt||"",logArchiveFileCount:h.logArchiveFileCount??0,logArchiveError:h.logArchiveError||"",contentSyncAbandoned:S,journalCursorPreserved:S}}),"stopped"}if(s.command==="content-sync"&&o.exitCode!==0){if(/baseline (?:is missing or stale|required)|verified content-sync baseline|new baseline/i.test(o.error||"")){let S="The installed release no longer matches the verified content-sync baseline. Run a successful full or incremental publish to establish a new baseline.";s.ruleId&&s.coalesceKey&&await Ne(e,s.ruleId,s.coalesceKey,S);let l={...s,status:"failed",endedAt:c,exitCode:o.exitCode,error:S};await v(r,null),await E(e.runtimeDir),await Oe(e,s);try{let y=await K(l,e);l.logArchiveDir=y.archiveDir,l.logArchiveCreatedAt=y.archiveCreatedAt,l.logArchiveFileCount=y.archivedFiles.length;}catch(y){l.logArchiveError=y instanceof Error?y.message:String(y);}return await v(i,l),await U(e.runtimeDir,s.id),await R(e.runtimeDir,{eventType:"content-sync-baseline-required",status:"failed",actorSource:"queue-runner",jobId:s.id,command:s.command,message:S,details:{ruleId:s.ruleId||"",retryScheduled:false}}),"processed"}await R(e.runtimeDir,{eventType:"content-sync-failed",status:"failed",actorSource:"queue-runner",jobId:s.id,command:s.command,message:"Content-sync execution failed before cursor acknowledgement.",details:{attempt:s.attempt??0,error:o.error||"Content-sync execution failed."}});let p=await Yt(e,s,o.error||"Content-sync execution failed."),h={...s,status:"retry-wait",endedAt:c,exitCode:o.exitCode,error:p.error,attempt:p.attempt,nextAttemptAt:p.nextAttemptAt};try{let S=await K(h,e);h.logArchiveDir=S.archiveDir,h.logArchiveCreatedAt=S.archiveCreatedAt,h.logArchiveFileCount=S.archivedFiles.length;}catch(S){h.logArchiveError=S instanceof Error?S.message:String(S);}return await v(i,h),await U(e.runtimeDir,s.id),await R(e.runtimeDir,{eventType:"content-sync-retry-scheduled",status:"retry-wait",actorSource:"queue-runner",jobId:s.id,command:s.command,message:"Content-sync retry was scheduled with bounded backoff.",details:{attempt:p.attempt??0,nextAttemptAt:p.nextAttemptAt||"",error:p.error||""}}),"processed"}let u={...s,status:o.exitCode===0?"success":"failed",endedAt:c,exitCode:o.exitCode,...o.error?{error:o.error}:{}};await v(r,null),u.status==="success"&&u.command==="content-sync"&&await Zt(e,u),await U(e.runtimeDir,s.id);try{let d=await K(u,e);u.logArchiveDir=d.archiveDir,u.logArchiveCreatedAt=d.archiveCreatedAt,u.logArchiveFileCount=d.archivedFiles.length;}catch(d){u.logArchiveError=d instanceof Error?d.message:String(d);}await v(i,u);let g=s.startedAt&&u.endedAt?Math.max(0,Math.round((new Date(u.endedAt).getTime()-new Date(s.startedAt).getTime())/1e3)):void 0;return await R(e.runtimeDir,{eventType:"job-run-finished",status:u.status==="success"?"success":"failed",actorSource:"queue-runner",jobId:u.id,command:u.command,message:u.status==="success"?"Job execution finished successfully.":"Job execution finished with failure.",details:{startedAt:s.startedAt||"",endedAt:u.endedAt||"",durationSec:g,deploymentProfile:u.deploymentProfile||"",exitCode:u.exitCode??null,error:u.error||"",logArchiveKey:u.logArchiveError||!u.logArchiveDir?"":m.basename(u.logArchiveDir),logArchiveDir:u.logArchiveDir||"",logArchiveCreatedAt:u.logArchiveCreatedAt||"",logArchiveFileCount:u.logArchiveFileCount??0,logArchiveError:u.logArchiveError||""}}),"processed"}async function tn(e){if(!e)throw new Error("Missing remote WPSuite publisher state. Refresh the runtime config before running subscription-gated jobs.");if(e.subscriptionType!=="PROFESSIONAL"&&e.subscriptionType!=="AGENCY")throw new Error("This job requires an active WPSuite publisher subscription in the remote site configuration.")}var nn={allowSchedulerAutoEnqueue:true,enforceSubscriptionOnJobExecution:false,shouldEnforceSubscriptionOnJobExecution:e=>Le(e)||e.enqueueSource==="scheduler"||e.createdBy===0,assertActiveSubscriptionForIdentity:tn},Qe=We(nn),rn=Qe,Hn=Qe;process.argv[1]&&import.meta.url===pathToFileURL(process.argv[1]).href&&rn().catch(e=>{console.error(e),process.exit(1);});export{Hn as default,rn as main,Qe as runQueueRunner};
1
+ import {pathToFileURL}from'url';import P from'fs/promises';import {existsSync,createReadStream,createWriteStream}from'fs';import m from'path';import {spawn}from'child_process';import {randomUUID,createHash}from'crypto';import Ge from'http';import be from'https';import {pipeline}from'stream/promises';import {createGzip}from'zlib';function he(e){return [...new Set(e.map(t=>t.trim()).filter(Boolean))].sort()}function G(e){return Array.isArray(e)?e.map(G):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,G(n)])):e}function ze(e){return JSON.stringify(G(e))}function J(e){return createHash("sha256").update(ze(e)).digest("hex")}function fe(e){return J({schemaVersion:1,wordpressFingerprint:e.wordpressFingerprint,targetFingerprint:e.targetFingerprint,sourceOrigin:e.sourceOrigin,sitemapPaths:[...e.sitemapPaths].sort(),blockedPathPrefixes:[...e.blockedPathPrefixes].sort(),assetPathPrefixes:[...e.assetPathPrefixes].sort(),noJavaScriptRenderPathPrefixes:[...e.noJavaScriptRenderPathPrefixes].sort(),urlRewriteMode:e.urlRewriteMode})}function He(e){let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error(`Unsupported source origin protocol: ${t.protocol}`);return t.hash="",t.search="",t.pathname=t.pathname.replace(/\/+$/,""),t.toString().replace(/\/$/,"")}function N(e){let t=he((e.postTypes??[]).map(r=>String(r).toLowerCase().replace(/[^a-z0-9_-]/g,"")));if(t.length===0)throw new Error("Content-sync requires at least one public post type.");let n=he((e.listingPaths??[]).map(r=>{let i=String(r).trim();if(!i)return "";let a=new URL(i,"https://content-sync.invalid/");if(a.origin!=="https://content-sync.invalid"&&/^https?:\/\//i.test(i))throw new Error("Content-sync listing routes must be same-site paths.");let s=`/${a.pathname.replace(/^\/+|\/+$/g,"")}`;return s==="/"?"/":`${s}/`}));return {postTypes:t,listingPaths:n,includeSubsites:e.includeSubsites===true,includePostTypeArchives:e.includePostTypeArchives!==false,includeTaxonomyArchives:e.includeTaxonomyArchives!==false,includeAuthorArchives:e.includeAuthorArchives===true,includeDateArchives:e.includeDateArchives===true,includePostsPage:e.includePostsPage!==false,includeSitemapChain:e.includeSitemapChain!==false}}function Y(e,t,n){return J({schemaVersion:1,sourceOrigin:He(e),ruleId:t.trim(),scope:N(n)})}function Z(e){return J({schemaVersion:1,...e})}function Se(e){return e.replace(/((?:x-static-publisher-token|authorization|proxy-authorization|x-api-key|aws-access-key-id|aws-secret-access-key|aws-session-token)\s*:\s*)[^\r\n]+/gi,"$1[REDACTED]").replace(/\b(Basic|Bearer)\s+[^\s]+/gi,"$1 [REDACTED]").replace(/([?&](?:token|access_token|refresh_token|api_key|key|nonce)=)[^&\s]+/gi,"$1[REDACTED]").replace(/((?:"|')?(?:runtimeToken|siteKey|nonce|accessToken|refreshToken|accessKeyId|secretAccessKey|sessionToken)(?:"|')?\s*[:=]\s*(?:"|'))[^"']+/gi,"$1[REDACTED]")}var ye=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";ye?m.join(ye,"current-progress.json"):"";Promise.resolve();var Ye="wp-json/smartcloud-static-publisher/v1/content-sync/",Ze=25*1024*1024,T=class extends Error{status;code;constructor(t,n,r){super(r),this.name="ContentSyncApiError",this.status=t,this.code=n;}},L=class{options;constructor(t){if(!t.runtimeToken.trim())throw new Error("Content-sync requires a WordPress runtime token.");this.options={...t,timeoutMs:t.timeoutMs??6e4};}endpoint(t,n="content-sync"){let r=this.options.sourceOrigin.replace(/\/+$/,"")+"/",i=n==="content-sync"?Ye:`wp-json/smartcloud-static-publisher/v1/${n}/`;return new URL(`${i}${t}`,r)}async post(t,n,r="content-sync"){let i=this.endpoint(t,r),a=Buffer.from(JSON.stringify(n),"utf8"),s=i.protocol==="https:"?be:Ge,o=i.protocol==="https:"?new be.Agent({rejectUnauthorized:!this.options.ignoreHttpsErrors}):void 0;return new Promise((c,u)=>{let g=s.request(i,{method:"POST",agent:o,headers:{"content-type":"application/json","content-length":String(a.byteLength),"x-static-publisher-token":this.options.runtimeToken},timeout:this.options.timeoutMs},d=>{let p=[],h=0;d.on("data",S=>{if(h+=S.byteLength,h>Ze){d.destroy(new Error("Content-sync API response exceeded the size limit."));return}p.push(S);}),d.on("error",u),d.on("end",()=>{let S=Buffer.concat(p).toString("utf8"),l;try{l=S?JSON.parse(S):{};}catch{u(new T(d.statusCode??500,"invalid-json","Content-sync API returned invalid JSON."));return}let y=d.statusCode??500;if(y<200||y>=300){u(new T(y,String(l.code??"request-failed"),String(l.message??`Content-sync API request failed (${y}).`)));return}c(l);});});g.on("timeout",()=>g.destroy(new Error(`Content-sync API request timed out: ${t}`))),g.on("error",u),g.end(a);})}async head(t){return this.post("head",t)}async unboundHead(t,n){return this.post("head",{postTypes:t,includeSubsites:n})}async events(t){let n=[],r=t.afterSequence,i=new Set(t.postTypes);for(;r<t.throughSequence;){let a=await this.post("events",{...t,afterSequence:r,limit:250});if(a.fromSequence!==r||a.throughSequence!==t.throughSequence||a.nextSequence<r||a.nextSequence>t.throughSequence)throw new Error("Content-sync API returned an inconsistent event page.");if(!Array.isArray(a.items))throw new Error("Content-sync API returned a malformed event page.");let s=r;for(let o of a.items){if(!Number.isSafeInteger(o.sequence)||o.sequence<=s||o.sequence>t.throughSequence||!Number.isSafeInteger(o.postId)||o.postId<=0||!Number.isSafeInteger(o.blogId)||o.blogId<=0||!i.has(o.postType)||typeof o.operation!="string"||!o.operation)throw new Error("Content-sync API returned an invalid or out-of-scope journal event.");s=o.sequence;}if(a.items.length>0&&a.nextSequence!==s)throw new Error("Content-sync API event cursor does not match the final returned event.");if(n.push(...a.items),!a.hasMore)break;if(a.nextSequence===r)throw new Error("Content-sync API event pagination did not advance.");r=a.nextSequence;}if(t.throughSequence>t.afterSequence&&n.at(-1)?.sequence!==t.throughSequence)throw new Error("Content-sync API omitted the claimed journal high-water event.");return n}async resolveImpactFamilies(t,n){let r=await this.post("impact",{families:t,includeSubsites:n});return Array.isArray(r.families)?r.families:[]}async releaseFingerprint(t=false){let n=await this.post("fingerprint",{includeSubsites:t}),r=String(n.fingerprint||"").trim();if(!/^[a-f0-9]{64}$/.test(r))throw new Error("WordPress returned an invalid release fingerprint.");return r}async establishBaseline(t){return this.post("baseline",t)}async acknowledge(t){return this.post("ack",t)}async importCookieObservations(t){return this.post("cookie-observations",t,"privacy")}};function Xe(e){return typeof e.subscriptionType=="string"&&e.subscriptionType.trim()!==""}function et(e,t){return {...e,...t??{}}}function tt(e,t){return {...e,...t??{},invalidationPaths:[...(t?.invalidationPaths??e.invalidationPaths)||[]]}}function X(e,t){let n=String(t??e.deploymentTargetOverride??"").trim();if(!Xe(e)){if(n)throw new Error(`Deployment target "${n}" requires an active WPSuite subscription and remote publisher config.`);return {name:null,profile:null,config:e}}let r=String(n||e.defaultDeploymentProfile||"").trim();if(!r)return {name:null,profile:null,config:e};let i=e.deploymentProfiles?.[r];if(!i)throw new Error(`Unknown deployment profile "${r}". Check the linked WPSuite publisher configuration.`);return {name:r,profile:i,config:{...e,targetOrigin:i.targetOrigin??e.targetOrigin,s3:et(e.s3,i.s3),cloudFront:tt(e.cloudFront,i.cloudFront)}}}var ee=["/sitemap_index.xml","/wp-sitemap.xml","/sitemap.xml"];function we(e){let t=new Set;for(let n of [...e,...ee]){let r=String(n||"").trim();r&&t.add(r);}return [...t]}function Pe(e){let t=e.trim();return t==="."?".":t.replace(/\/$/,"")}function st(e){let t=String(e??"").trim();if(!t)return "";let n=t;if(/^https?:\/\//i.test(n))try{n=new URL(n).pathname;}catch{return ""}if(n=n.split(/[?#]/,1)[0]?.replace(/\\/g,"/").trim()??"",!n)return "";let r=n.endsWith("/"),i=n.replace(/^\/+/,"").split("/").map(s=>s.replace(/[^A-Za-z0-9._-]/g,"")).filter(s=>s.length>0&&s!=="."&&s!=="..");if(i.length===0)return "";let a=`/${i.join("/")}`;return r&&m.extname(a)===""&&(a+="/"),a==="/"?"":a}function te(e){return !e||typeof e!="object"?{}:Object.fromEntries(Object.entries(e).map(([t,n])=>[t.trim(),String(n??"")]).filter(([t])=>t.length>0))}function ot(e){if(!e||typeof e!="object")return {};let t={};for(let[n,r]of Object.entries(e)){let i=n.trim();if(!i||!r||typeof r!="object")continue;let a=r,s={};if(typeof a.targetOrigin=="string"){let c=Pe(a.targetOrigin);c&&(s.targetOrigin=c);}let o=te(a.extraReplacements);if(Object.keys(o).length>0&&(s.extraReplacements=o),a.s3&&typeof a.s3=="object"){let c={},u=a.s3;typeof u.bucket=="string"&&(c.bucket=u.bucket.trim()),typeof u.prefix=="string"&&(c.prefix=u.prefix.trim()),typeof u.region=="string"&&(c.region=u.region.trim()),typeof u.htmlCacheControl=="string"&&(c.htmlCacheControl=u.htmlCacheControl.trim()),typeof u.assetCacheControl=="string"&&(c.assetCacheControl=u.assetCacheControl.trim()),Object.keys(c).length>0&&(s.s3=c);}if(a.cloudFront&&typeof a.cloudFront=="object"){let c={},u=a.cloudFront;typeof u.distributionId=="string"&&(c.distributionId=u.distributionId.trim()),Array.isArray(u.invalidationPaths)&&(c.invalidationPaths=u.invalidationPaths.map(g=>String(g??"").trim()).filter(g=>g.length>0)),Object.keys(c).length>0&&(s.cloudFront=c);}t[i]=s;}return t}function re(e){return e==="PROFESSIONAL"||e==="AGENCY"?e:void 0}function at(e,t){if(!e||typeof e!="object")return null;let n=e,r=n.command;if(r!=="publish"&&r!=="crawl"&&r!=="deploy"&&r!=="invalidate"&&r!=="retry-timeouts"&&r!=="url"&&r!=="content-sync")return null;let i=Number.parseInt(String(n.intervalMinutes??"0"),10);if(!Number.isFinite(i)||i<1)return null;let a=String(n.id??`${r}-${t+1}`).trim();if(!a)return null;let s=String(n.deploymentProfile??"").trim(),o=String(n.url??"").trim(),c=Array.isArray(n.postTypes)?[...new Set(n.postTypes.map(g=>String(g??"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"")).filter(Boolean))]:[],u=Array.isArray(n.listingPaths)?[...new Set(n.listingPaths.map(g=>String(g??"").trim()).filter(Boolean))]:[];return r==="content-sync"&&c.length===0?null:{id:a,enabled:n.enabled!==false,command:r,intervalMinutes:i,...r==="publish"||r==="crawl"?{crawlMode:n.crawlMode==="incremental"?"incremental":"full"}:{},...(r==="publish"||r==="deploy"||r==="invalidate"||r==="content-sync")&&s?{deploymentProfile:s}:{},...o?{url:o}:{},...c.length>0?{postTypes:c}:{},...u.length>0?{listingPaths:u}:{},...typeof n.includeSubsites=="boolean"?{includeSubsites:n.includeSubsites}:{},...typeof n.includePostTypeArchives=="boolean"?{includePostTypeArchives:n.includePostTypeArchives}:{},...typeof n.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:n.includeTaxonomyArchives}:{},...typeof n.includeAuthorArchives=="boolean"?{includeAuthorArchives:n.includeAuthorArchives}:{},...typeof n.includeDateArchives=="boolean"?{includeDateArchives:n.includeDateArchives}:{},...typeof n.includePostsPage=="boolean"?{includePostsPage:n.includePostsPage}:{},...typeof n.includeSitemapChain=="boolean"?{includeSitemapChain:n.includeSitemapChain}:{}}}function Ce(e){let t=e&&typeof e=="object"?e:{},n=Array.isArray(t.rules)?t.rules.map((r,i)=>at(r,i)).filter(r=>!!r):[];return {enabled:t.enabled===true,timezone:typeof t.timezone=="string"&&t.timezone.trim()!==""?t.timezone.trim():"UTC",rules:n}}function ct(e){if(!e||typeof e!="object")return;let t=e,n={};for(let i of ["accountId","siteId"]){let a=t[i];typeof a=="string"&&a.trim()!==""&&(n[i]=a.trim());}let r=Number(t.lastUpdate??0);return Number.isFinite(r)&&r>0&&(n.lastUpdate=Math.floor(r)),t.subscriber===true&&(n.subscriber=true),Object.keys(n).length>0?n:void 0}function ie(e){let t=e&&typeof e=="object"?e:{},n=String(t.accountId??"").trim(),r=String(t.siteId??"").trim(),i=t.subscriber===true,a=ct(t.siteSettings),s={...a??{},...n?{accountId:a?.accountId??n}:{},...r?{siteId:a?.siteId??r}:{},...a?.subscriber===true||i?{subscriber:true}:{}},o={},c=String(t.apiBase??"").trim();c&&(o.apiBase=c);let u=String(t.runtimeToken??t.nonce??"").trim();u&&(o.runtimeToken=u);let g=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();g&&(o.virtualAssetBaseUrl=g),Object.keys(s).length>0&&(o.siteSettings=s);let d=re(t.subscriptionType);return d&&(o.subscriptionType=d),o}function ut(e){try{let t=new URL(e);globalThis.location=t;}catch{}}function Ae(e){return typeof e=="string"?e:e instanceof URL?e.toString():e.url}function lt(e,t){let n=new Headers(e instanceof Request?e.headers:void 0);if(t?.headers)for(let[r,i]of new Headers(t.headers).entries())n.set(r,i);return n}async function Ie(e,t,n=5){let r=new URL(Ae(e)),i=String(t?.method??(e instanceof Request?e.method:"GET")).toUpperCase(),a=r.protocol==="http:"?Ge:be,s=lt(e,t);return await new Promise((o,c)=>{let u=a.request(r,{method:i,headers:Object.fromEntries(s.entries()),...r.protocol==="https:"?{rejectUnauthorized:false}:{}},g=>{let d=[];g.on("data",p=>{d.push(Buffer.isBuffer(p)?p:Buffer.from(p));}),g.on("error",c),g.on("end",()=>{let p=g.statusCode??0,h=g.headers.location;if(n>0&&h&&[301,302,303,307,308].includes(p)){o(Ie(new URL(h,r),{method:p===303?"GET":i},n-1));return}let S=new Headers;for(let[l,y]of Object.entries(g.headers))Array.isArray(y)?S.set(l,y.join(", ")):typeof y=="string"&&S.set(l,y);o(new Response(Buffer.concat(d),{status:p,statusText:g.statusMessage??"",headers:S}));});});u.on("error",c),u.end();})}function dt(e){let t=ie(e.wpsuite),n={...t.siteSettings??{},...t.siteSettings?.subscriber===true||t.subscriptionType==="PROFESSIONAL"||t.subscriptionType==="AGENCY"?{subscriber:true}:{}},r=String(n.accountId??"").trim(),i=String(n.siteId??"").trim(),a=String(t.virtualAssetBaseUrl??t.uploadUrl??"").trim();if(e.wpsuite={...t.apiBase?{apiBase:t.apiBase}:{},...t.runtimeToken?{runtimeToken:t.runtimeToken}:{},...a?{virtualAssetBaseUrl:a}:{},...Object.keys(n).length>0?{siteSettings:n}:{},...t.subscriptionType?{subscriptionType:t.subscriptionType}:{}},!r||!i||!a)return false;ut(e.sourceOrigin);let s=globalThis,c={...s.WpSuite??{},siteSettings:n,uploadUrl:a};return t.apiBase&&(c.apiBase=t.apiBase),s.WpSuite=c,true}async function gt(e){let t=String(e.wpsuite?.virtualAssetBaseUrl??e.wpsuite?.uploadUrl??"").trim();if(!dt(e)){let i=e.wpsuite?.siteSettings,a=[String(i?.accountId??"").trim()?"":"accountId",String(i?.siteId??"").trim()?"":"siteId",t?"":"virtualAssetBaseUrl"].filter(Boolean);return {remote:null,diagnostic:{status:"invalid-runtime",virtualAssetBaseUrl:t,subscriptionType:null,error:`Missing WP Suite runtime field(s): ${a.join(", ")}.`,requests:[]}}}let n=globalThis.fetch,r=[];try{typeof n=="function"&&/^https?:\/\//i.test(t)&&(globalThis.fetch=(async(c,u)=>{let g=Ae(c);if(g.startsWith(t)){let d=(()=>{try{return new URL(g).pathname}catch{return g}})();try{let p=e.ignoreHttpsErrors&&g.startsWith("https://")?await Ie(c,u):await n(c,u);return r.push({path:d,status:p.status,ok:p.ok,error:null}),p}catch(p){throw r.push({path:d,status:null,ok:!1,error:p instanceof Error?p.message:String(p)}),p}}return n(c,u)}));let{getConfig:i}=await import('@smart-cloud/wpsuite-core'),a=await i("publisher"),s=a&&typeof a=="object"?a:null,o=re(s?.subscriptionType);return {remote:s,diagnostic:{status:s?"loaded":"unavailable",virtualAssetBaseUrl:t,subscriptionType:o??null,error:s?null:"WP Suite publisher config loader returned no configuration.",requests:r}}}catch(i){return {remote:null,diagnostic:{status:"unavailable",virtualAssetBaseUrl:t,subscriptionType:null,error:i instanceof Error?i.message:String(i),requests:r}}}finally{typeof n=="function"&&(globalThis.fetch=n);}}function pt(e,t){let n=ot(t?.deploymentProfiles),r=String(t?.defaultDeploymentProfile??"").trim(),i=n[r]?r:"",a=re(t?.subscriptionType),s=ie(e.wpsuite);return {...e,scheduler:Ce(t?.scheduler),deploymentProfiles:n,defaultDeploymentProfile:i,...a?{subscriptionType:a}:{},wpsuite:{...s,...s.siteSettings||a?{siteSettings:{...s.siteSettings??{},...s.siteSettings?.subscriber===true||a==="PROFESSIONAL"||a==="AGENCY"?{subscriber:true}:{}}}:{},...a?{subscriptionType:a}:{}}}}function ne(e,t){let r=String(e||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!r)return t;let i=r.split("/").map(a=>a.trim()).filter(a=>a.length>0&&a!=="."&&a!=="..");return i.length>0?i.join("/"):t}function mt(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?m.resolve(e):""}function ve(e,t,n){let r=String(t||"").trim();return r&&m.isAbsolute(r)?m.resolve(r):m.resolve(e,ne(r,n))}async function Q(e,t={}){let n=String(e??"").trim()||process.env.PUBLISHER_CONFIG||"publisher.config.json",r=await P.readFile(n,"utf8"),i=JSON.parse(r);i.sourceOrigin=i.sourceOrigin.replace(/\/$/,""),i.targetOrigin=Pe(i.targetOrigin),i.ignoreHttpsErrors??=false,i.outputDir=String(i.outputDir||"export").trim()||"export",i.urlRewriteMode||=i.targetOrigin==="."?"relative":"absolute",i.noJavaScriptRenderPathPrefixes||=[],i.seedPaths||=[],i.generated404RequestPath=st(i.generated404RequestPath),i.sitemapPaths||=[...ee],i.allowedAssetHosts||=[],i.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],i.blockedPathPrefixes||=[],i.blockedSearchFragments||=[],i.concurrency||=1,i.maxPages||=0,i.extraReplacements=te(i.extraReplacements),i.postCrawlCopyMap=te(i.postCrawlCopyMap),i.logDir=String(i.logDir||"logs").trim()||"logs",i.verbose??=false,i.logLevel||=i.verbose?"debug":"info",i.s3SyncMode||="sdk-upload-delete",i.readiness||={waitForSelector:null,waitForFunction:null,timeoutMs:1500,fallbackWaitMs:1500},i.readiness.timeoutMs??=1500,i.readiness.fallbackWaitMs??=1500,i.viewport||={width:1440,height:1200},i.navigationTimeoutMs||=3e4,i.assetDownloadConcurrency=Number(i.assetDownloadConcurrency)>0?Number(i.assetDownloadConcurrency):i.concurrency,i.rewriteConcurrency=Number(i.rewriteConcurrency)>0?Number(i.rewriteConcurrency):i.assetDownloadConcurrency,i.wpsuite=ie(i.wpsuite),i.scheduler=Ce(void 0),i.deploymentProfiles={},i.defaultDeploymentProfile="",i.deploymentTargetOverride=String(i.deploymentTargetOverride??"").trim();let a=await gt(i);t.onRemotePublisherConfigDiagnostic?.(a.diagnostic);let s=pt(i,a.remote),o=mt(),c=o?m.resolve(o,".."):"";return c?(s.outputDir=ve(c,s.outputDir,"export"),s.logDir=ve(c,s.logDir,"logs")):(m.isAbsolute(s.outputDir)||(s.outputDir=ne(s.outputDir,"export")),m.isAbsolute(s.logDir)||(s.logDir=ne(s.logDir,"logs"))),s}function Re(e){let t=e.split(/\r?\n/).map(r=>r.trim()).filter(Boolean),n=[...t].reverse().find(r=>/^(?:Error|[A-Za-z][A-Za-z0-9]*Error):\s/.test(r));return n||(t.find(r=>!r.startsWith("at "))??"")}function se(e){let t=m.resolve(e);return {state:m.join(t,"content-sync-state.json"),current:m.join(t,"content-sync-current.json"),impact:m.join(t,"content-sync-impact-plan.json"),checkpoint:m.join(t,"content-sync-checkpoint.json"),baseline:m.join(t,"content-sync-baseline.json"),activeRules:m.join(t,"content-sync-active-rules.json"),releaseCutoff:m.join(t,"content-sync-release-cutoff.json"),candidateManifest:m.join(t,"content-sync-candidate-manifest.json"),trustedManifest:m.join(t,"crawl-manifest.json"),invalidation:m.join(t,"content-sync-invalidation.json"),deployPlan:m.join(t,"deploy-plan.json")}}async function oe(e,t){await qe(e.activeRules,{contractVersion:1,evaluatedAt:new Date().toISOString(),entries:t});}async function qe(e,t){await P.mkdir(m.dirname(e),{recursive:true});let n=`${e}.${process.pid}.${Date.now()}.tmp`;await P.writeFile(n,JSON.stringify(t,null,2),"utf8"),await P.rename(n,e);}async function xe(e){try{return JSON.parse(await P.readFile(e,"utf8"))}catch(t){if(t.code==="ENOENT")return null;throw new Error(`Invalid or unreadable content-sync state file ${e}: ${t instanceof Error?t.message:String(t)}`,{cause:t})}}async function ht(e){let t=await xe(e.current);if(t===null)return null;let n=t;if(n.schemaVersion!==1||typeof n.jobId!="string"||typeof n.phase!="string"||!Number.isSafeInteger(n.fromSequence)||!Number.isSafeInteger(n.toSequence))throw new Error("Invalid content-sync current-range state.");return n}async function De(e){let t=await xe(e.state);if(t===null)return {schemaVersion:1,updatedAt:"",rules:{}};let n=t;if(n.schemaVersion!==1||typeof n.updatedAt!="string"||!n.rules||typeof n.rules!="object"||Array.isArray(n.rules))throw new Error("Invalid content-sync state store.");return n}async function ke(e,t){await qe(e.state,{...t,schemaVersion:1,updatedAt:new Date().toISOString()});}async function Te(e,t){let n=await ht(e);return !n||n.coalesceKey!==t?false:(await Promise.all([e.current,e.checkpoint,e.impact,e.candidateManifest,e.invalidation,e.deployPlan].map(async r=>{try{await P.unlink(r);}catch(i){if(i.code!=="ENOENT")throw i}})),true)}function Le(e){let t=String(e.command??"").trim();return (t==="publish"||t==="crawl")&&e.crawlMode==="incremental"||t==="content-sync"}var ae=new Map;async function Ee(e){let t=m.resolve(e),n=ae.get(t);if(n!==void 0)return n;try{let r=JSON.parse(await P.readFile(t,"utf8")),i=String(r.version??"").trim();return ae.set(t,i),i}catch{return ae.set(t,""),""}}var $=class extends Error{request;step;constructor(t,n){super(`Stop requested during ${n}.`),this.name="StopRequestedError",this.request=t,this.step=n;}},vt="queue-mutation.lock",Pt=5e3,Ct=3e4;function At(e){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",n=process.env.STATIC_PUBLISHER_EXPORTER_DIR||process.cwd(),r=process.env.PUBLISHER_CONFIG||"",i=1;for(let o=0;o<e.length;o++){let c=e[o];c==="--runtime-dir"?t=e[++o]||"":c.startsWith("--runtime-dir=")?t=c.slice(14):c==="--exporter-dir"?n=e[++o]||n:c.startsWith("--exporter-dir=")?n=c.slice(15):c==="--config"?r=e[++o]||"":c.startsWith("--config=")?r=c.slice(9):c==="--max-jobs"?i=Number.parseInt(e[++o]||"1",10):c.startsWith("--max-jobs=")&&(i=Number.parseInt(c.slice(11),10));}if(!t)throw new Error("Missing runtime dir. Use --runtime-dir or STATIC_PUBLISHER_RUNTIME_DIR.");let a=m.resolve(t),s=r?m.resolve(r):m.join(a,"config.json");return {runtimeDir:a,exporterDir:m.resolve(n),configPath:s,maxJobs:Number.isFinite(i)&&i>0?i:1}}async function w(e,t){try{let n=await P.readFile(e,"utf8");return JSON.parse(n)}catch(n){if((n&&typeof n=="object"&&"code"in n?String(n.code||""):"")!=="ENOENT"){let i=n instanceof Error?n.message:String(n);console.warn(`[queue-runner] failed to read JSON ${e}: ${i}`);}return t}}async function v(e,t){await P.mkdir(m.dirname(e),{recursive:true}),await P.writeFile(e,JSON.stringify(t,null,2),"utf8");}function Be(e){return m.join(e,vt)}async function It(e){await new Promise(t=>setTimeout(t,e));}async function Rt(e){let t=Be(e),n=Date.now()+Pt;for(;;)try{await P.mkdir(m.dirname(t),{recursive:!0}),await P.writeFile(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()},null,2),{encoding:"utf8",flag:"wx"});return}catch(r){if((r&&typeof r=="object"&&"code"in r?String(r.code||""):"")!=="EEXIST")throw r;let a=await P.stat(t).catch(()=>null);if(a&&Date.now()-a.mtimeMs>Ct){await P.unlink(t).catch(()=>{});continue}if(Date.now()>=n)throw new Error("Timed out acquiring queue mutation lock.",{cause:r});await It(50);}}async function qt(e){await P.unlink(Be(e)).catch(()=>{});}async function F(e,t){await Rt(e);try{return await t()}finally{await qt(e);}}function Me(e){return m.join(e,"queue-runner-heartbeat.json")}function ge(e){return m.join(e,"current-progress.json")}function ce(e){return m.join(e,"scheduler-state.json")}function xt(e,t){let r=String(e||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!r)return t;let i=r.split("/").map(a=>a.trim()).filter(a=>a.length>0&&a!=="."&&a!=="..");return i.length>0?i.join("/"):t}async function Ue(e){let t=await w(e.configPath||"",null),n=m.resolve(e.runtimeDir,".."),i=(typeof t?.logDir=="string"?t.logDir:"").trim();return i&&m.isAbsolute(i)?m.resolve(i):m.resolve(n,xt(i,"logs"))}function ue(e,t){return String(e||"").trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||t}function Dt(e){let t=e?new Date(e):new Date;return (Number.isNaN(t.getTime())?new Date:t).toISOString().replace(/[-:]/g,"").replace(/\.\d{3}Z$/,"Z")}function kt(e){return [Dt(e.endedAt||e.startedAt),ue(e.command||"job","job"),ue(e.id||"job","job"),ue(e.status||"finished","finished")].join("-")}function Tt(e){return e.endsWith(".log.jsonl")||e.endsWith(".errors.jsonl")||e.endsWith(".rejected.jsonl")?true:["current-crawl-event.json","rejected.jsonl","ignored.jsonl","skipped-http.jsonl","errors.jsonl","timings.jsonl","rejected.json","ignored.json","skipped-http.json","errors.json","timings.json"].includes(e)}function Et(e){return e==="errors.json"||e==="errors.jsonl"||e.endsWith(".errors.jsonl")?"errors":e==="ignored.json"||e==="ignored.jsonl"?"ignored":e==="rejected.json"||e==="rejected.jsonl"||e.endsWith(".rejected.jsonl")?"rejected":e==="skipped-http.json"||e==="skipped-http.jsonl"?"skipped-http":e==="timings.json"||e==="timings.jsonl"?"timings":e==="current-progress.json"?"current-progress":e==="current-crawl-event.json"?"current-crawl-event":e.endsWith(".log.jsonl")?e.replace(/\.log\.jsonl$/i,"-log"):e.replace(/\.[^.]+$/u,"")||"artifact"}function Ft(e){return e.endsWith(".gz")?"application/gzip":e.endsWith(".jsonl")?"application/x-ndjson":e.endsWith(".json")?"application/json":"text/plain"}async function W(e,t,n){let r=`${n}.gz`,i=m.join(t,r);await pipeline(createReadStream(e),createGzip({level:9}),createWriteStream(i));let[a,s]=await Promise.all([P.stat(e),P.stat(i)]);return {role:Et(n),originalFileName:n,storedFileName:r,compressed:true,compression:"gzip",contentType:Ft(r),originalSize:a.size,storedSize:s.size}}async function K(e,t){let n=await Ue(t),r=new Date().toISOString(),i=kt(e),a=m.join(n,"archive",i),s=[],o=[];await P.mkdir(a,{recursive:true});try{let d=await P.readdir(n,{withFileTypes:!0});for(let p of d){if(!p.isFile()||!Tt(p.name))continue;let h=await W(m.join(n,p.name),a,p.name);o.push(h),s.push(h.storedFileName);}}catch(d){if((d&&typeof d=="object"&&"code"in d?String(d.code||""):"")!=="ENOENT")throw d}let c=ge(t.runtimeDir);if(existsSync(c)){let d=await W(c,a,"current-progress.json");o.push(d),s.push(d.storedFileName);}if(e.command==="content-sync")for(let d of ["content-sync-current.json","content-sync-impact-plan.json","content-sync-checkpoint.json","content-sync-state.json","content-sync-invalidation.json","deploy-plan.json"]){let p=m.join(t.runtimeDir,d);if(!existsSync(p))continue;let h=await W(p,a,d);o.push(h),s.push(h.storedFileName);}let u=m.join(t.runtimeDir,"privacy","cookie-observations.json");if(existsSync(u)){let d=await W(u,a,"cookie-observations.json");o.push(d),s.push(d.storedFileName);}let g=[...s,"job.json"];return await v(m.join(a,"job.json"),{manifestVersion:1,archivedAt:r,archiveKey:i,archiveDir:a,logDir:n,runtimeDir:t.runtimeDir,exporterDir:t.exporterDir,configPath:t.configPath||"",archivedFiles:g,artifacts:o,job:e}),{archiveKey:i,archiveDir:a,archiveCreatedAt:r,archivedFiles:g,artifacts:o}}function jt(e){return m.join(e,"audit-events.jsonl")}function le(e){return m.join(e,"stop-request.json")}async function $e(e){try{let t=await P.readFile(le(e),"utf8"),n=JSON.parse(t);return n&&typeof n=="object"?n:null}catch{return null}}async function Fe(e,t){let n=await $e(e);if(!n)return null;let r=String(n.targetJobId||"").trim();return r&&r!==t?null:n}async function U(e,t){if(!t){await P.unlink(le(e)).catch(()=>{});return}let n=await $e(e);if(!n)return;let r=String(n.targetJobId||"").trim();(!r||r===t)&&await P.unlink(le(e)).catch(()=>{});}async function R(e,t){try{let n={occurredAt:t.occurredAt||new Date().toISOString(),status:t.status||"info",actorSource:t.actorSource||"queue-runner",...t};await P.mkdir(e,{recursive:!0}),await P.appendFile(jt(e),`${JSON.stringify(n)}
2
+ `,"utf8");}catch{}}async function C(e,t,n){let[r,i]=await Promise.all([Ee(m.join(e.exporterDir,"package.json")),Ee(m.join(e.exporterDir,"node_modules","@smart-cloud","wpsuite-core","package.json"))]),a={checkedAt:new Date().toISOString(),status:t,pid:process.pid,nodePath:process.execPath,nodeVersion:process.version,exporterVersion:r,wpsuiteCoreVersion:i,runtimeDir:e.runtimeDir,exporterDir:e.exporterDir,...n??{}};try{await v(Me(e.runtimeDir),a);}catch{}}async function E(e){try{await P.unlink(ge(e));}catch{}}function Ot(e,t){let n=e.command;if(n!=="publish"&&n!=="crawl"&&n!=="deploy"&&n!=="invalidate"&&n!=="retry-timeouts"&&n!=="url"&&n!=="content-sync")return null;let r=Number.parseInt(String(e.intervalMinutes??"0"),10);if(!Number.isFinite(r)||r<1)return null;let i=(e.id||`${n}-${t+1}`).trim();if(!i)return null;let a=e.enabled!==false,s=typeof e.url=="string"?e.url.trim():"",o=typeof e.deploymentProfile=="string"?e.deploymentProfile.trim():"",c=Array.isArray(e.postTypes)?[...new Set(e.postTypes.map(d=>String(d).trim()).filter(Boolean))]:[],u=Array.isArray(e.listingPaths)?[...new Set(e.listingPaths.map(d=>String(d).trim()).filter(Boolean))]:[],g=(n==="publish"||n==="crawl")&&e.crawlMode==="incremental"?"incremental":"full";return n==="url"&&!s||n==="content-sync"&&c.length===0?null:{id:i,enabled:a,command:n,intervalMinutes:r,...n==="publish"||n==="crawl"?{crawlMode:g}:{},...(n==="publish"||n==="deploy"||n==="invalidate"||n==="content-sync")&&o?{deploymentProfile:o}:{},...s?{url:s}:{},...c.length>0?{postTypes:c}:{},...u.length>0?{listingPaths:u}:{},...typeof e.includeSubsites=="boolean"?{includeSubsites:e.includeSubsites}:{},...typeof e.includePostTypeArchives=="boolean"?{includePostTypeArchives:e.includePostTypeArchives}:{},...typeof e.includeTaxonomyArchives=="boolean"?{includeTaxonomyArchives:e.includeTaxonomyArchives}:{},...typeof e.includeAuthorArchives=="boolean"?{includeAuthorArchives:e.includeAuthorArchives}:{},...typeof e.includeDateArchives=="boolean"?{includeDateArchives:e.includeDateArchives}:{},...typeof e.includePostsPage=="boolean"?{includePostsPage:e.includePostsPage}:{},...typeof e.includeSitemapChain=="boolean"?{includeSitemapChain:e.includeSitemapChain}:{}}}async function Jt(e){let t=await Q(e.configPath).catch(()=>null),n=t?.scheduler,r=Array.isArray(n?.rules)?n.rules.map((i,a)=>Ot(i,a)).filter(i=>!!i):[];return {enabled:!!n?.enabled,timezone:typeof n?.timezone=="string"&&n.timezone.trim()?n.timezone.trim():"UTC",rules:r,wpsuite:t?.wpsuite,publisherConfig:t}}function z(e,t){if(!t)throw new Error("Content-sync scheduler requires a valid publisher config.");let n=N({postTypes:e.postTypes??[],listingPaths:e.listingPaths??[],includeSubsites:e.includeSubsites,includePostTypeArchives:e.includePostTypeArchives,includeTaxonomyArchives:e.includeTaxonomyArchives,includeAuthorArchives:e.includeAuthorArchives,includeDateArchives:e.includeDateArchives,includePostsPage:e.includePostsPage,includeSitemapChain:e.includeSitemapChain}),r=Y(t.sourceOrigin,e.id,n),i=X(t,e.deploymentProfile),a=Z({sourceOrigin:t.sourceOrigin,targetOrigin:i.config.targetOrigin,deploymentProfile:i.name||"",s3Bucket:i.config.s3.bucket,s3Prefix:i.config.s3.prefix,cloudFrontDistributionId:i.config.cloudFront.distributionId,urlRewriteMode:i.config.urlRewriteMode,extraReplacements:i.profile?.extraReplacements??{}});return `content-sync:${e.id}:${J({scopeFingerprint:r,targetFingerprint:a}).slice(0,32)}`}function Lt(e,t,n,r){let i=[n[t],r[t]].filter(s=>!!s).filter(s=>s.coalesceKey===t&&s.ruleId===e.id).map(s=>String(s.consumerId??"").trim()).filter(Boolean),a=[...new Set(i)];return a.length===1?a[0]:""}async function je(e,t){let n=se(e.runtimeDir);if(await oe(n,[]),!t?.enabled||!t.publisherConfig)return;let r=t.rules.filter(u=>u.enabled&&u.command==="content-sync");if(r.length===0)return;let[i,a]=await Promise.all([w(n.state,{}),w(n.baseline,{})]),s=i.rules??{},o=a.entries??{},c=[];for(let u of r){let g=z(u,t.publisherConfig),d=Lt(u,g,s,o);d&&c.push({ruleId:u.id,coalesceKey:g,consumerId:d});}await oe(n,c);}async function Bt(e,t,n,r,i){let s=(await w(m.join(e.runtimeDir,"content-sync-baseline.json"),{})).entries?.[r];if(!s?.consumerId||!s.scopeFingerprint||!s.baselineId)return {status:"baseline-required",reason:"No verified normal-release baseline exists for this rule scope."};try{let o=t.publisherConfig;if(!o)throw new Error("Publisher configuration is unavailable.");let c=N({postTypes:n.postTypes??[],listingPaths:n.listingPaths??[],includeSubsites:n.includeSubsites,includePostTypeArchives:n.includePostTypeArchives,includeTaxonomyArchives:n.includeTaxonomyArchives,includeAuthorArchives:n.includeAuthorArchives,includeDateArchives:n.includeDateArchives,includePostsPage:n.includePostsPage,includeSitemapChain:n.includeSitemapChain}),u=Y(o.sourceOrigin,n.id,c),g=X(o,n.deploymentProfile),d=Z({sourceOrigin:o.sourceOrigin,targetOrigin:g.config.targetOrigin,deploymentProfile:g.name||"",s3Bucket:g.config.s3.bucket,s3Prefix:g.config.s3.prefix,cloudFrontDistributionId:g.config.cloudFront.distributionId,urlRewriteMode:g.config.urlRewriteMode,extraReplacements:g.profile?.extraReplacements??{}});if(s.scopeFingerprint!==u||s.targetFingerprint!==d||!s.releaseFingerprint)return {status:"baseline-required",reason:"The verified content-sync baseline does not match the active scope or deployment target. Run a successful full or incremental publish to establish a new baseline."};let p=new L({sourceOrigin:o.sourceOrigin,runtimeToken:String(o.wpsuite?.runtimeToken||""),ignoreHttpsErrors:o.ignoreHttpsErrors}),h=await p.releaseFingerprint(c.includeSubsites),S=fe({wordpressFingerprint:h,targetFingerprint:d,sourceOrigin:o.sourceOrigin,sitemapPaths:we(o.sitemapPaths),blockedPathPrefixes:o.blockedPathPrefixes,assetPathPrefixes:o.assetPathPrefixes,noJavaScriptRenderPathPrefixes:o.noJavaScriptRenderPathPrefixes,urlRewriteMode:o.urlRewriteMode});if(s.releaseFingerprint!==S)return {status:"baseline-required",reason:"The installed WordPress release changed after the last verified content-sync baseline. Run a successful full or incremental publish to establish a new baseline."};let l=await p.head({consumerId:s.consumerId,scopeFingerprint:s.scopeFingerprint,baselineId:s.baselineId,postTypes:c.postTypes,includeSubsites:c.includeSubsites}),y=l.committedSequence;if(i?.command==="content-sync"&&i.coalesceKey===r){let b=await w(m.join(e.runtimeDir,"content-sync-current.json"),null);b?.coalesceKey===r&&Number.isSafeInteger(b.toSequence)&&(y=Math.max(y,Number(b.toSequence)));}return {status:l.headSequence>y?"pending":"current",headSequence:l.headSequence,committedSequence:l.committedSequence}}catch(o){return o instanceof T&&o.code==="baseline-required"?{status:"baseline-required",reason:o.message}:{status:"unavailable",reason:o instanceof Error?o.message:String(o)}}}async function Ne(e,t,n,r,i,a){let s=m.join(e.runtimeDir,"content-sync-state.json"),c=(await w(s,{})).rules??{},u=c[n]??{};c[n]={...u,ruleId:t,coalesceKey:n,...Number.isSafeInteger(i)?{observedHeadSequence:i}:{},...Number.isSafeInteger(a)?{committedSequence:a}:{},retryAttempt:0,nextRetryAt:null,lastError:r,baselineStatus:"required",baselineReason:r,trailingWorkDetected:Number.isSafeInteger(i)&&Number.isSafeInteger(a)?Number(i)>Number(a):!!u.trailingWorkDetected},await v(s,{schemaVersion:1,updatedAt:new Date().toISOString(),rules:c});}function de(e,t){let n=(t.url||"").trim(),r=t.crawlMode||"full",i=(t.deploymentProfile||"").trim(),a=(t.coalesceKey||"").trim();return e.some(s=>s.command===t.command&&(t.command!=="content-sync"||(s.coalesceKey||"").trim()===a)&&(s.url||"").trim()===n&&(s.crawlMode||"full")===r&&(s.deploymentProfile||"").trim()===i&&(s.status===void 0||s.status==="queued"||s.status==="retry-wait"||s.status==="running"))}async function Mt(e,t,n){if(!t.allowSchedulerAutoEnqueue)return await je(e,null),0;let r=await Jt(e);if(await je(e,r),!r.enabled||r.rules.length===0)return 0;if(t.assertActiveSubscriptionForIdentity)try{await t.assertActiveSubscriptionForIdentity(r.wpsuite??null);}catch(l){let y=l instanceof Error?l.message:String(l);return console.warn(`[queue-runner] scheduler auto-enqueue skipped: ${y}`),0}let i=m.join(e.runtimeDir,"queue.json"),a=m.join(e.runtimeDir,"current-run.json"),s=Date.now(),o=0,c=[],u=[],g=[],d=new Map,[p,h,S]=await Promise.all([w(i,[]),w(a,null),w(ce(e.runtimeDir),{lastEnqueuedBucketByRuleId:{},lastEvaluatedBucketByRuleId:{},lastCreatedBucketByRuleId:{},coalescedCountByRuleId:{}})]);for(let l of r.rules){if(!l.enabled||l.command!=="content-sync")continue;let y=Math.floor(s/(l.intervalMinutes*60*1e3)),b=S.lastEvaluatedBucketByRuleId?.[l.id]??S.lastEnqueuedBucketByRuleId?.[l.id]??-1;if(y<=b)continue;let D=z(l,r.publisherConfig);de(p,{command:l.command,deploymentProfile:l.deploymentProfile,coalesceKey:D})||d.set(l.id,await Bt(e,r,l,D,h));}await F(e.runtimeDir,async()=>{let l=await w(i,[]),y=await w(a,null),b=await w(ce(e.runtimeDir),{lastEnqueuedBucketByRuleId:{},lastEvaluatedBucketByRuleId:{},lastCreatedBucketByRuleId:{},coalescedCountByRuleId:{}});b.lastEnqueuedBucketByRuleId??={},b.lastEvaluatedBucketByRuleId??={...b.lastEnqueuedBucketByRuleId},b.lastCreatedBucketByRuleId??={...b.lastEnqueuedBucketByRuleId},b.coalescedCountByRuleId??={};let D=[...l];y&&y.status==="running"&&D.unshift(y);for(let f of r.rules){if(!f.enabled)continue;let A=f.intervalMinutes*60*1e3,x=Math.floor(s/A),j=b.lastEvaluatedBucketByRuleId[f.id]??b.lastEnqueuedBucketByRuleId[f.id]??-1;if(x<=j)continue;let O=f.command==="content-sync"?z(f,r.publisherConfig):"";b.lastEvaluatedBucketByRuleId[f.id]=x;let Ke=f.command==="content-sync"?l:D;if(de(Ke,{command:f.command,url:f.url,crawlMode:f.crawlMode,deploymentProfile:f.deploymentProfile,coalesceKey:O})){b.coalescedCountByRuleId[f.id]=(b.coalescedCountByRuleId[f.id]??0)+1,u.push(f);continue}if(f.command==="content-sync"){let V=d.get(f.id);if(!V||V.status!=="pending"){let me=V??{status:"unavailable",reason:"Content-sync demand was not checked."};me.status!=="current"&&g.push({rule:f,check:me});continue}}let H={id:randomUUID(),command:f.command,...f.command==="content-sync"?{ruleId:f.id,coalesceKey:O,attempt:0}:{},...(f.command==="publish"||f.command==="crawl")&&f.crawlMode?{crawlMode:f.crawlMode}:{},...(f.command==="publish"||f.command==="deploy"||f.command==="invalidate"||f.command==="content-sync")&&f.deploymentProfile?{deploymentProfile:f.deploymentProfile}:{},...f.url?{url:f.url}:{},enqueueSource:"scheduler",...r.wpsuite?{wpsuite:r.wpsuite}:{},status:"queued",createdAt:new Date().toISOString(),createdBy:0};l.push(H),D.push(H),c.push({job:H,rule:f}),b.lastEnqueuedBucketByRuleId[f.id]=x,b.lastCreatedBucketByRuleId[f.id]=x,o+=1;}o>0&&await v(i,l),await v(ce(e.runtimeDir),b);});for(let l of c){if(l.rule.command==="content-sync"){let y=d.get(l.rule.id);await R(e.runtimeDir,{eventType:"content-sync-demand-detected",status:"queued",actorSource:"queue-runner-scheduler",jobId:l.job.id,command:l.job.command,message:"Pending journal changes require a content-sync job.",details:{ruleId:l.rule.id,headSequence:y?.headSequence??0,committedSequence:y?.committedSequence??0}});}await R(e.runtimeDir,{eventType:"job-created",status:"queued",actorSource:"queue-runner-scheduler",jobId:l.job.id,command:l.job.command,message:"Scheduler auto-enqueued a job.",details:{ruleId:l.rule.id,intervalMinutes:l.rule.intervalMinutes,timezone:r.timezone,deploymentProfile:l.rule.deploymentProfile||"",url:l.rule.url||""}});}for(let l of u)await R(e.runtimeDir,{eventType:"content-sync-coalesced",status:"queued",actorSource:"queue-runner-scheduler",command:l.command,message:"Scheduler demand was coalesced into an existing content-sync job.",details:{ruleId:l.id}});for(let l of g){if(l.check.status==="baseline-required"){let y=z(l.rule,r.publisherConfig);await Ne(e,l.rule.id,y,l.check.reason||"A successful full or incremental publish must establish a new content-sync baseline.",l.check.headSequence,l.check.committedSequence);}await R(e.runtimeDir,{eventType:l.check.status==="baseline-required"?"content-sync-baseline-required":"content-sync-demand-check-failed",status:l.check.status==="unavailable"?"failed":"info",actorSource:"queue-runner-scheduler",command:"content-sync",message:l.check.reason||"The content-sync consumer is already at the current journal head.",details:{ruleId:l.rule.id,headSequence:l.check.headSequence??0,committedSequence:l.check.committedSequence??0}});}return o}async function Ut(e){let t={pid:process.pid,startedAt:new Date().toISOString()};await P.writeFile(e,JSON.stringify(t,null,2),{encoding:"utf8",flag:"wx"});}async function $t(e){try{await P.unlink(e);}catch{}}function Nt(e,t){let n=[m.join(e,"dist",`${t}.js`),m.join(e,`${t}.js`)];for(let r of n)if(existsSync(r))return r;throw new Error(`Cannot find ${t}.js in ${m.join(e,"dist")} or ${e}`)}async function q(e,t,n,r,i,a,s){if(s){let u=await Fe(t,s);if(u)throw new $(u,n)}let o=Nt(e,n),c={...process.env,...a??{}};return c.STATIC_PUBLISHER_RUNTIME_DIR=t,i&&(c.PUBLISHER_CONFIG=i),await new Promise((u,g)=>{let d=null,p=null,h=null,S=null,l=false,y="",b=spawn(process.execPath,[o,...r],{cwd:e,env:c,stdio:["inherit","inherit","pipe"]});b.stderr?.on("data",A=>{y+=A.toString("utf8");});let D=()=>{p&&clearInterval(p),h&&clearInterval(h),S&&clearTimeout(S);},f=async()=>{if(!(!s||d||l)){l=true;try{let A=await Fe(t,s);if(!A)return;d=A,b.kill("SIGTERM"),S=setTimeout(()=>{b.kill("SIGKILL");},1e4);}finally{l=false;}}};s&&(p=setInterval(()=>{f();},1e3),h=setInterval(()=>{(async()=>{let A=Me(t),x=await w(A,{});await v(A,{...x,checkedAt:new Date().toISOString(),status:"running",currentJobId:s||x.currentJobId||"",currentStep:n});})().catch(()=>{});},15e3)),b.on("error",A=>{D(),g(A);}),b.on("close",(A,x)=>{D();let j=Se(y).trim();if(j&&process.stderr.write(`${j}
3
+ `),d){g(new $(d,n));return}if(A===0)u();else {let O=Re(j);g(new Error(`${n} exited with code ${A??-1}${x?` (signal ${x})`:""}${O?`: ${O}`:""}`));}});}),0}function Qt(e){let t=e.awsTempCreds;if(!t)return {};let n={};return typeof t.accessKeyId=="string"&&t.accessKeyId.trim()!==""&&(n.AWS_ACCESS_KEY_ID=t.accessKeyId.trim()),typeof t.secretAccessKey=="string"&&t.secretAccessKey.trim()!==""&&(n.AWS_SECRET_ACCESS_KEY=t.secretAccessKey.trim()),typeof t.sessionToken=="string"&&t.sessionToken.trim()!==""&&(n.AWS_SESSION_TOKEN=t.sessionToken.trim()),n}async function Wt(e,t){let n=s=>{if(!s||typeof s!="object")return null;let o=s,c={...o.siteSettings??{},...String(o.accountId??"").trim()&&!o.siteSettings?.accountId?{accountId:String(o.accountId).trim()}:{},...String(o.siteId??"").trim()&&!o.siteSettings?.siteId?{siteId:String(o.siteId).trim()}:{},...o.siteSettings?.subscriber===true||o.subscriber===true?{subscriber:true}:{}},u={...String(o.apiBase??"").trim()?{apiBase:String(o.apiBase).trim()}:{},...String(o.runtimeToken??o.nonce??"").trim()?{runtimeToken:String(o.runtimeToken??o.nonce).trim()}:{},...String(o.virtualAssetBaseUrl??o.uploadUrl??"").trim()?{virtualAssetBaseUrl:String(o.virtualAssetBaseUrl??o.uploadUrl).trim()}:{},...Object.keys(c).length>0?{siteSettings:c}:{},...o.subscriptionType?{subscriptionType:o.subscriptionType}:{}};return Object.keys(u).length>0?u:null},r=await Q(t.configPath).catch(()=>null),i=n(r?.wpsuite);if(i)return i;let a=n(e.wpsuite);return a||null}async function Kt(e,t){return await Wt(e,t)}function pe(e){let t={...e,status:"queued"};return delete t.startedAt,delete t.endedAt,delete t.exitCode,delete t.error,delete t.stopRequestedAt,delete t.stopRequestedByUserId,delete t.stopRequestedByLogin,delete t.stopMode,delete t.stoppedStep,t}async function _t(e,t){let n=await w(ge(e.runtimeDir),null),r=n&&n.details&&typeof n.details.phase=="string"?n.details.phase.trim():"";if(r)return r;let i=n&&typeof n.currentStep=="string"?n.currentStep.trim():"";if(i)return i;let a=await Ue(e).catch(()=>"");if(a){let s=await w(m.join(a,"current-crawl-event.json"),null),o=s&&typeof s.currentStep=="string"?s.currentStep.trim():"";if(o)return o}return t}function zt(e,t){if((e.command==="publish"||e.command==="crawl")&&t==="rewrite-text")return "rewrite-text"}async function Ht(e){let t=m.join(e.runtimeDir,"queue.json"),n=m.join(e.runtimeDir,"current-run.json"),r=await F(e.runtimeDir,async()=>{let i=await w(n,null);if(!i||i.status!=="running"&&i.status!=="queued")return null;let a=await w(t,[]),s=Array.isArray(a)?a.filter(c=>c?.id!==i.id):[],o=pe(i);return await v(t,[o,...s]),await v(n,null),o});r&&(await U(e.runtimeDir,r.id),await R(e.runtimeDir,{eventType:"job-recovered",status:"queued",actorSource:"queue-runner",jobId:r.id,command:r.command,message:"Recovered stale current-run entry back into queue."}));}async function M(e,t){if(e.resumeFromStep==="rewrite-text")return;let n=m.join(t.runtimeDir,"privacy","cookie-observations.json"),r;try{let o=await P.stat(n);if(!o.isFile()||o.size>5*1024*1024)throw new Error("Cookie observation artifact is missing or exceeds 5 MiB.");r=JSON.parse(await P.readFile(n,"utf8"));}catch(o){if((o&&typeof o=="object"&&"code"in o?String(o.code||""):"")==="ENOENT")return;throw o}let i=await Q(t.configPath),a=String(i.wpsuite?.runtimeToken||"").trim();if(!a)return;await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"consent-cookie-observations"}),await new L({sourceOrigin:i.sourceOrigin,runtimeToken:a,ignoreHttpsErrors:!!i.ignoreHttpsErrors}).importCookieObservations(r);}async function Vt(e,t,n){try{if((n.shouldEnforceSubscriptionOnJobExecution?.(e)??n.enforceSubscriptionOnJobExecution)&&n.assertActiveSubscriptionForIdentity){let o=await Kt(e,t);await n.assertActiveSubscriptionForIdentity(o);}let i=Qt(e),a=e.resumeFromStep==="rewrite-text"?["--resume-rewrite"]:e.crawlMode==="incremental"?["--crawl-mode","incremental"]:[],s=e.deploymentProfile?["--profile",e.deploymentProfile]:[];if(e.command==="publish")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"content-sync-release-cutoff"}),await q(t.exporterDir,t.runtimeDir,"content-sync",["--capture-baseline-cutoffs",e.id],t.configPath,i,e.id),await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:e.resumeFromStep==="rewrite-text"?"rewrite-text":"crawl"}),await q(t.exporterDir,t.runtimeDir,"crawl",a,t.configPath,i,e.id),await M(e,t),await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"deploy"}),await q(t.exporterDir,t.runtimeDir,"deploy",s,t.configPath,i,e.id),await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"invalidate"}),await q(t.exporterDir,t.runtimeDir,"invalidate",s,t.configPath,i,e.id),await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"content-sync-baseline"}),await q(t.exporterDir,t.runtimeDir,"content-sync",["--establish-baselines",e.id],t.configPath,i,e.id),{exitCode:0};if(e.command==="crawl")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:e.resumeFromStep==="rewrite-text"?"rewrite-text":"crawl"}),await q(t.exporterDir,t.runtimeDir,"crawl",a,t.configPath,i,e.id),await M(e,t),{exitCode:0};if(e.command==="deploy")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"deploy"}),await q(t.exporterDir,t.runtimeDir,"deploy",s,t.configPath,i,e.id),{exitCode:0};if(e.command==="invalidate")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"invalidate"}),await q(t.exporterDir,t.runtimeDir,"invalidate",s,t.configPath,i,e.id),{exitCode:0};if(e.command==="retry-timeouts")return await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"retry-timeouts"}),await q(t.exporterDir,t.runtimeDir,"crawl",["--retry-timeouts"],t.configPath,i,e.id),await M(e,t),{exitCode:0};if(e.command==="url"){let o=(e.url||"").trim();return o?(await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"url"}),await q(t.exporterDir,t.runtimeDir,"crawl",["--url",o],t.configPath,i,e.id),await M(e,t),{exitCode:0}):{exitCode:2,error:"Missing url for command 'url'"}}return e.command==="content-sync"?!e.ruleId||!e.coalesceKey?{exitCode:2,error:"Content-sync queue jobs require ruleId and coalesceKey."}:(await C(t,"running",{currentJobId:e.id,currentJobCommand:e.command,currentStep:"content-sync"}),await q(t.exporterDir,t.runtimeDir,"content-sync",["--job-id",e.id],t.configPath,i,e.id),await M(e,t),{exitCode:0}):{exitCode:2,error:`Unsupported command: ${e.command}`}}catch(r){return r instanceof $?{exitCode:130,error:"Job stop requested.",stopped:true,stopRequest:r.request,stoppedStep:r.step}:{exitCode:1,error:r instanceof Error?r.message:String(r)}}}function Qe(e){return async function(n=process.argv.slice(2)){let r=At(n),i=m.join(r.runtimeDir,"export.lock"),a=m.join(r.runtimeDir,"last-run.json");await E(r.runtimeDir),await C(r,"starting",{message:"queue-runner starting"});try{await Ut(i);}catch(s){if((s&&typeof s=="object"&&"code"in s?String(s.code||""):"")!=="EEXIST")throw s;console.log("[queue-runner] lock active, skipping"),await C(r,"lock-active",{message:"lock active, skipped this cron tick"});return}try{await Ht(r);let s=await Mt(r,e),o=0;for(let c=0;c<r.maxJobs;c++){let u=await Xt(r,e);if(u==="none"||(o+=1,u==="stopped"))break}if(o===0)await E(r.runtimeDir),await C(r,"idle",{processedJobs:o,schedulerEnqueued:s,message:"no queued jobs"});else {await E(r.runtimeDir);let c=await w(a,null),u=String(c?.status||"").trim();await C(r,u==="success"?"job-success":u==="stopped"?"job-stopped":"job-failed",{processedJobs:o,schedulerEnqueued:s,lastJobId:c?.id,lastJobCommand:c?.command,lastJobStatus:c?.status,lastJobExitCode:c?.exitCode,lastJobError:c?.error,...u==="stopped"?{currentStep:c?.stoppedStep,stopRequestedAt:c?.stopRequestedAt,stopRequestedByLogin:c?.stopRequestedByLogin,stopRequestedMode:c?.stopMode,lastStoppedStep:c?.stoppedStep,message:c?.stopMode==="requeue"?`Job stopped during ${c?.stoppedStep||c?.command||"active step"} and requeued.`:`Job stopped during ${c?.stoppedStep||c?.command||"active step"} and left out of queue.`}:{}});}}catch(s){let o=s instanceof Error?s.message:String(s);throw await C(r,"error",{message:o}),await R(r.runtimeDir,{eventType:"queue-runner-error",status:"failed",actorSource:"queue-runner",message:"Unhandled queue-runner error.",details:{error:o}}),s}finally{await $t(i);}}}async function Oe(e,t){if(t.command!=="content-sync"||!t.coalesceKey)return false;let n=se(e.runtimeDir),r=await Te(n,t.coalesceKey),i=await De(n),a=i.rules[t.coalesceKey];return a&&(i.rules[t.coalesceKey]={...a,trailingWorkDetected:true,retryAttempt:0,nextRetryAt:null,lastError:null},await ke(n,i)),r}async function Gt(e,t,n){let r=m.join(e.runtimeDir,"queue.json"),i=m.join(e.runtimeDir,"current-run.json");await F(e.runtimeDir,async()=>{let a=await w(r,[]),s=Array.isArray(a)?a.filter(u=>u?.id!==t.id):[],o=pe(t),c=zt(t,n);c?o.resumeFromStep=c:delete o.resumeFromStep,await v(r,[o,...s]),await v(i,null);});}async function Yt(e,t,n){let r=Math.max(0,t.attempt??0)+1,i=Math.min(3600*1e3,6e4*2**(r-1)),a=Math.floor(i*.2*Math.random()),s=new Date(Date.now()+i+a).toISOString(),o={...pe(t),status:"retry-wait",attempt:r,nextAttemptAt:s,error:n};if(await F(e.runtimeDir,async()=>{let c=m.join(e.runtimeDir,"queue.json"),u=m.join(e.runtimeDir,"current-run.json"),d=(await w(c,[])).filter(p=>p.id!==t.id);await v(c,[o,...d]),await v(u,null);}),t.coalesceKey){let c=m.join(e.runtimeDir,"content-sync-state.json"),g=(await w(c,{})).rules??{};g[t.coalesceKey]={...g[t.coalesceKey]??{},ruleId:t.ruleId||"",coalesceKey:t.coalesceKey,retryAttempt:r,nextRetryAt:s,lastError:n,trailingWorkDetected:true},await v(c,{schemaVersion:1,updatedAt:new Date().toISOString(),rules:g});}return o}async function Zt(e,t){if(!t.coalesceKey||!t.ruleId||!(await w(m.join(e.runtimeDir,"content-sync-state.json"),null))?.rules?.[t.coalesceKey]?.trailingWorkDetected)return null;let r=null;await F(e.runtimeDir,async()=>{let a=m.join(e.runtimeDir,"queue.json"),s=await w(a,[]);de(s,{command:"content-sync",coalesceKey:t.coalesceKey,deploymentProfile:t.deploymentProfile})||(r={id:randomUUID(),command:"content-sync",ruleId:t.ruleId,coalesceKey:t.coalesceKey,deploymentProfile:t.deploymentProfile,enqueueSource:"scheduler",wpsuite:t.wpsuite,status:"queued",attempt:0,createdAt:new Date().toISOString(),createdBy:0},await v(a,[...s,r]));});let i=r;return i&&await R(e.runtimeDir,{eventType:"content-sync-trailing-job-created",status:"queued",actorSource:"queue-runner",jobId:i.id,command:i.command,message:"Content changes after the stable cutoff created one trailing job.",details:{predecessorJobId:t.id,ruleId:t.ruleId,coalesceKey:t.coalesceKey}}),i}async function Xt(e,t){let n=m.join(e.runtimeDir,"queue.json"),r=m.join(e.runtimeDir,"current-run.json"),i=m.join(e.runtimeDir,"last-run.json"),a=new Date().toISOString(),s=await F(e.runtimeDir,async()=>{let d=await w(n,[]);if(!Array.isArray(d)||d.length===0)return null;let p=Date.parse(String(d[0]?.nextAttemptAt||""));if(Number.isFinite(p)&&p>Date.now())return null;let h={...d[0],status:"running",startedAt:a};return delete h.nextAttemptAt,await v(n,d.slice(1)),await v(r,h),h});if(!s)return "none";await E(e.runtimeDir),await R(e.runtimeDir,{eventType:"job-run-started",status:"running",actorSource:"queue-runner",jobId:s.id,command:s.command,message:"Job execution started.",details:{createdAt:s.createdAt||"",startedAt:a,createdBy:s.createdBy??null,deploymentProfile:s.deploymentProfile||"",queuedWithTempAwsCreds:!!s.awsTempCreds}}),await C(e,"running",{currentJobId:s.id,currentJobCommand:s.command,currentStep:s.command});let o=await Vt(s,e,t),c=new Date().toISOString();if(o.stopped){let d=await _t(e,o.stoppedStep||s.command),p=o.stopRequest?.mode==="requeue"?"requeue":"stop",h={...s,status:"stopped",endedAt:c,exitCode:o.exitCode,...o.error?{error:o.error}:{},stopRequestedAt:o.stopRequest?.requestedAt||"",stopRequestedByUserId:typeof o.stopRequest?.requestedByUserId=="number"?o.stopRequest.requestedByUserId:null,stopRequestedByLogin:o.stopRequest?.requestedByLogin||"",stopMode:p,stoppedStep:d},S=false;p==="requeue"?await Gt(e,s,d):(await v(r,null),S=await Oe(e,s));try{let l=await K(h,e);h.logArchiveDir=l.archiveDir,h.logArchiveCreatedAt=l.archiveCreatedAt,h.logArchiveFileCount=l.archivedFiles.length;}catch(l){h.logArchiveError=l instanceof Error?l.message:String(l);}return await v(i,h),await U(e.runtimeDir,s.id),await E(e.runtimeDir),await R(e.runtimeDir,{eventType:"job-run-stopped",status:"stopped",actorSource:"queue-runner",jobId:s.id,command:s.command,message:p==="requeue"?"Job stop requested and requeued.":"Job stop requested and removed from active execution without requeue.",details:{startedAt:s.startedAt||"",endedAt:c,deploymentProfile:s.deploymentProfile||"",stopMode:p,stopRequestedAt:o.stopRequest?.requestedAt||"",stopRequestedByLogin:o.stopRequest?.requestedByLogin||"",stopRequestedByUserId:typeof o.stopRequest?.requestedByUserId=="number"?o.stopRequest.requestedByUserId:null,stoppedStep:d,logArchiveKey:h.logArchiveError||!h.logArchiveDir?"":m.basename(h.logArchiveDir),logArchiveDir:h.logArchiveDir||"",logArchiveCreatedAt:h.logArchiveCreatedAt||"",logArchiveFileCount:h.logArchiveFileCount??0,logArchiveError:h.logArchiveError||"",contentSyncAbandoned:S,journalCursorPreserved:S}}),"stopped"}if(s.command==="content-sync"&&o.exitCode!==0){if(/baseline (?:is missing or stale|required)|verified content-sync baseline|new baseline/i.test(o.error||"")){let S="The installed release no longer matches the verified content-sync baseline. Run a successful full or incremental publish to establish a new baseline.";s.ruleId&&s.coalesceKey&&await Ne(e,s.ruleId,s.coalesceKey,S);let l={...s,status:"failed",endedAt:c,exitCode:o.exitCode,error:S};await v(r,null),await E(e.runtimeDir),await Oe(e,s);try{let y=await K(l,e);l.logArchiveDir=y.archiveDir,l.logArchiveCreatedAt=y.archiveCreatedAt,l.logArchiveFileCount=y.archivedFiles.length;}catch(y){l.logArchiveError=y instanceof Error?y.message:String(y);}return await v(i,l),await U(e.runtimeDir,s.id),await R(e.runtimeDir,{eventType:"content-sync-baseline-required",status:"failed",actorSource:"queue-runner",jobId:s.id,command:s.command,message:S,details:{ruleId:s.ruleId||"",retryScheduled:false}}),"processed"}await R(e.runtimeDir,{eventType:"content-sync-failed",status:"failed",actorSource:"queue-runner",jobId:s.id,command:s.command,message:"Content-sync execution failed before cursor acknowledgement.",details:{attempt:s.attempt??0,error:o.error||"Content-sync execution failed."}});let p=await Yt(e,s,o.error||"Content-sync execution failed."),h={...s,status:"retry-wait",endedAt:c,exitCode:o.exitCode,error:p.error,attempt:p.attempt,nextAttemptAt:p.nextAttemptAt};try{let S=await K(h,e);h.logArchiveDir=S.archiveDir,h.logArchiveCreatedAt=S.archiveCreatedAt,h.logArchiveFileCount=S.archivedFiles.length;}catch(S){h.logArchiveError=S instanceof Error?S.message:String(S);}return await v(i,h),await U(e.runtimeDir,s.id),await R(e.runtimeDir,{eventType:"content-sync-retry-scheduled",status:"retry-wait",actorSource:"queue-runner",jobId:s.id,command:s.command,message:"Content-sync retry was scheduled with bounded backoff.",details:{attempt:p.attempt??0,nextAttemptAt:p.nextAttemptAt||"",error:p.error||""}}),"processed"}let u={...s,status:o.exitCode===0?"success":"failed",endedAt:c,exitCode:o.exitCode,...o.error?{error:o.error}:{}};await v(r,null),u.status==="success"&&u.command==="content-sync"&&await Zt(e,u),await U(e.runtimeDir,s.id);try{let d=await K(u,e);u.logArchiveDir=d.archiveDir,u.logArchiveCreatedAt=d.archiveCreatedAt,u.logArchiveFileCount=d.archivedFiles.length;}catch(d){u.logArchiveError=d instanceof Error?d.message:String(d);}await v(i,u);let g=s.startedAt&&u.endedAt?Math.max(0,Math.round((new Date(u.endedAt).getTime()-new Date(s.startedAt).getTime())/1e3)):void 0;return await R(e.runtimeDir,{eventType:"job-run-finished",status:u.status==="success"?"success":"failed",actorSource:"queue-runner",jobId:u.id,command:u.command,message:u.status==="success"?"Job execution finished successfully.":"Job execution finished with failure.",details:{startedAt:s.startedAt||"",endedAt:u.endedAt||"",durationSec:g,deploymentProfile:u.deploymentProfile||"",exitCode:u.exitCode??null,error:u.error||"",logArchiveKey:u.logArchiveError||!u.logArchiveDir?"":m.basename(u.logArchiveDir),logArchiveDir:u.logArchiveDir||"",logArchiveCreatedAt:u.logArchiveCreatedAt||"",logArchiveFileCount:u.logArchiveFileCount??0,logArchiveError:u.logArchiveError||""}}),"processed"}async function tn(e){if(!e)throw new Error("Missing remote WPSuite publisher state. Refresh the runtime config before running subscription-gated jobs.");if(e.subscriptionType!=="PROFESSIONAL"&&e.subscriptionType!=="AGENCY")throw new Error("This job requires an active WPSuite publisher subscription in the remote site configuration.")}var nn={allowSchedulerAutoEnqueue:true,enforceSubscriptionOnJobExecution:false,shouldEnforceSubscriptionOnJobExecution:e=>Le(e)||e.enqueueSource==="scheduler"||e.createdBy===0,assertActiveSubscriptionForIdentity:tn},We=Qe(nn),rn=We,Hn=We;process.argv[1]&&import.meta.url===pathToFileURL(process.argv[1]).href&&rn().catch(e=>{console.error(e),process.exit(1);});export{Hn as default,rn as main,We as runQueueRunner};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import u from'path';import {readFile}from'fs/promises';import {LambdaClient,InvokeCommand}from'@aws-sdk/client-lambda';import {S3Client,GetObjectCommand}from'@aws-sdk/client-s3';import {fromTemporaryCredentials}from'@aws-sdk/credential-providers';import'crypto';var a=1;function d(t){let e=String(t??"").trim().replace(/^\/+|\/+$/g,"");if(!e)return "";let r=e.split("/").filter(Boolean);if(r.some(o=>o==="."||o===".."))throw new Error("S3 prefix contains an unsafe dot path segment.");return `${r.join("/")}/`}function p(t,e){let r=String(t??"").replace(/^\/+/,""),o=d(e);if(!r||r.includes("\0"))throw new Error("S3 object key is empty or invalid.");if(o&&!r.startsWith(o))throw new Error(`S3 object key is outside the configured workspace prefix: ${r}`);if(r.split("/").some(n=>n===".."))throw new Error("S3 object key contains an unsafe parent segment.");return r}function i(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 k(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!==a)throw new Error(`Remote worker protocol mismatch: expected ${a}, received ${String(e.protocolVersion)}.`);let r=e.workspace,o=e.functions;if(!r||!o)throw new Error("Remote worker config requires workspace and functions objects.");return {schemaVersion:1,region:i(e.region,"region"),...i(e.roleArn,"roleArn",{optional:true})?{roleArn:i(e.roleArn,"roleArn")}:{},...i(e.roleSessionName,"roleSessionName",{optional:true})?{roleSessionName:i(e.roleSessionName,"roleSessionName")}:{},workspace:{bucket:i(r.bucket,"workspace.bucket"),prefix:String(r.prefix??"")},functions:{render:i(o.render,"functions.render"),rewrite:i(o.rewrite,"functions.rewrite"),"deploy-copy":i(o["deploy-copy"],"functions.deploy-copy")},protocolVersion:a}}async function l(t){let e=u.resolve(t);try{return k(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 c=class{config;lambda;s3;constructor(e,r={}){this.config=e;let o=e.roleArn?fromTemporaryCredentials({params:{RoleArn:e.roleArn,RoleSessionName:e.roleSessionName??"publisher-exporter-remote-worker"}}):void 0;this.lambda=new LambdaClient({region:e.region,...o?{credentials:o}:{},...r}),this.s3=new S3Client({region:e.region,...o?{credentials:o}:{}});}async invoke(e){let r=e.operation==="health"?this.config.functions.render:this.config.functions[e.operation],o=await this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify(e),"utf8")})),n=o.Payload?JSON.parse(new TextDecoder().decode(o.Payload)):null;if(o.FunctionError)throw new Error(`Remote ${e.operation} worker failed (${o.FunctionError}): ${JSON.stringify(n)}`);if(!n||typeof n!="object")throw new Error(`Remote ${e.operation} worker returned no JSON response.`);let s=n;if(s.schemaVersion!==a||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=p(e.resultKey,this.config.workspace.prefix),o=await this.s3.send(new GetObjectCommand({Bucket:this.config.workspace.bucket,Key:r}));if(!o.Body)throw new Error(`Remote worker result has no body: ${r}`);return JSON.parse(await o.Body.transformToString("utf8"))}async health(e){let r=this.config.functions[e],o=`${e}-${Date.now()}`,n=await this.lambda.send(new InvokeCommand({FunctionName:r,InvocationType:"RequestResponse",Payload:Buffer.from(JSON.stringify({schemaVersion:a,operation:"health",jobId:"health",taskId:o}),"utf8")})),s=n.Payload?JSON.parse(new TextDecoder().decode(n.Payload)):null;if(n.FunctionError||!s||typeof s!="object")throw new Error(`Remote ${e} health check failed: ${JSON.stringify(s)}`);return s}};function E(t){let e=t.findIndex(n=>n==="--config"||n==="-c"),o=t.find(n=>n.startsWith("--config="))?.slice(9)??(e>=0?t[e+1]:void 0)??process.env.PUBLISHER_REMOTE_WORKER_CONFIG;if(!o)throw new Error("Pass --config <path> or set PUBLISHER_REMOTE_WORKER_CONFIG.");return u.resolve(o)}async function O(){let t=await l(E(process.argv.slice(2))),e=new c(t),r=await Promise.all(["render","rewrite","deploy-copy"].map(async o=>({operation:o,response:await e.health(o)})));console.log(JSON.stringify({ok:true,results:r},null,2));}O().catch(t=>{console.error(t instanceof Error?t.message:String(t)),process.exit(1);});
@@ -0,0 +1,5 @@
1
+ import {S3Client,CopyObjectCommand,PutObjectCommand,GetObjectCommand}from'@aws-sdk/client-s3';import {chromium}from'playwright';import {createHash}from'crypto';import'fast-glob';import'fs/promises';import'os';import k from'path';import'worker_threads';var h=1,z=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function S(e,t){let r=String(e??"").trim();if(!z.test(r))throw new Error(`${t} must match ${z.source} and be at most 128 characters.`);return r}function x(e){let t=String(e??"").trim().replace(/^\/+|\/+$/g,"");if(!t)return "";let r=t.split("/").filter(Boolean);if(r.some(s=>s==="."||s===".."))throw new Error("S3 prefix contains an unsafe dot path segment.");return `${r.join("/")}/`}function E(e,...t){let r=x(e),s=t.map((o,n)=>{let i=String(o??"").replace(/^\/+|\/+$/g,"");if(!i||i.split("/").some(a=>a==="."||a===".."))throw new Error(`Unsafe S3 key segment at index ${n}.`);return i});return `${r}${s.join("/")}`}function L(e,t,r){return `${E(e,"jobs",S(t,"jobId"),"tasks",S(r,"taskId"))}/`}function P(e){return createHash("sha256").update(e).digest("hex")}function w(e,t){let r=String(e??"").replace(/^\/+/,""),s=x(t);if(!r||r.includes("\0"))throw new Error("S3 object key is empty or invalid.");if(s&&!r.startsWith(s))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 J(e){if(!e||typeof e!="object")throw new Error("Worker event must be a JSON object.");let t=e;if(t.schemaVersion!==h)throw new Error(`Unsupported worker protocol version: ${String(t.schemaVersion)}.`);let r=t.operation;if(r!=="render"&&r!=="rewrite"&&r!=="deploy-copy"&&r!=="health")throw new Error(`Unsupported worker operation: ${String(r)}.`);return S(String(t.jobId??""),"jobId"),S(String(t.taskId??""),"taskId"),e}function Y(e){return e.replace(/&quot;/g,'"').replace(/&#34;/g,'"').replace(/&apos;/g,"'").replace(/&#39;/g,"'").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">")}function R(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&#39;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function I(e){return e.replace(/\//g,"\\/")}function G(e){return e.replace(/\//g,"\\\\/")}function pe(e){try{let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")return null;let r=t.pathname==="/"&&!t.search&&!t.hash?"":`${t.pathname}${t.search}${t.hash}`;return `//${t.host}${r}`}catch{return null}}function X(e,t,r){if(!t)return;e[t]=r;let s=I(t),o=I(r);e[s]=o;let n=G(t),i=G(r);e[n]=i;let a=R(t),c=R(r);e[a]=c;let l=R(s),u=R(o);e[l]=u;let d=R(n),m=R(i);e[d]=m;}function $(e,t,r){X(e,t,r);let s=pe(t);s&&s!==t&&X(e,s,r);}function Z(e,t){try{return new URL(e,t==="."?"https://relative.invalid":t).pathname}catch{return e.startsWith("/")?e:`/${e.replace(/^\.\//,"")}`}}function Q(e,t,r){if(!t)return r;let s=k.dirname(k.resolve(t)),o=k.resolve(e,r.replace(/^\/+/,"")),n=k.relative(s,o).replace(/\\/g,"/");return n?(n.startsWith(".")||(n=`./${n}`),n):"."}var de=["wp-content/","wp-includes/","wp-admin/","wp-json/","_next/"],ge=new Set([".html",".htm"]),ee="WPSuite.io Static Publisher",me=ee.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function fe(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function he(e){return e.startsWith("//")||e.startsWith("\\/\\/")||e.startsWith("\\\\/\\\\/")}function we(e,t,r){return he(t)?e.replace(new RegExp(`(?<!:)${fe(t)}`,"g"),r):e.split(t).join(r)}function Re(e,t,r){if(e.wpsuite?.siteSettings?.subscriber===true||e.wpsuite?.subscriptionType==="PROFESSIONAL"||e.wpsuite?.subscriptionType==="AGENCY"||!r)return false;let o=k.extname(r).toLowerCase();return ge.has(o)?/<head\b|<html\b|<!doctype html/i.test(t):false}function ye(e){if(new RegExp(`<meta\\b(?=[^>]*\\bname=(["'])generator\\1)(?=[^>]*\\bcontent=(["'])${me}\\2)[^>]*\\/?>`,"i").test(e))return e;let t=`<meta name="generator" content="${ee}" />`;if(e.match(/(\r?\n)([ \t]*)<\/head>/i))return e.replace(/(\r?\n)([ \t]*)<\/head>/i,`$1$2${t}$1$2</head>`);let s=e.includes(`\r
2
+ `)?`\r
3
+ `:`
4
+ `;return e.replace(/<head\b[^>]*>/i,o=>`${o}${s} ${t}`)}function be(e){let t=Y(e).trim();return t.startsWith("{")||t.startsWith("[")||t.includes("\\/")||/"@context"|"@type"/.test(t)}function xe(e,t){let r=[...new Set(t)].filter(n=>n.includes("/")&&!/\\+\//.test(n)).map(n=>[n,I(n)]).filter(([n,i])=>n!==i).sort((n,i)=>i[0].length-n[0].length);if(!r.length)return e;let s=n=>{let i=n;for(let[a,c]of r)i=i.split(a).join(c);return i},o=e.replace(/(<script\b[^>]*\btype=["']application\/(?:ld\+)?json["'][^>]*>)([\s\S]*?)(<\/script>)/gi,(n,i,a,c)=>`${i}${s(a)}${c}`);return o=o.replace(/(<meta\b[^>]*\bcontent=(['"]))([\s\S]*?)(\2[^>]*>)/gi,(n,i,a,c,l)=>be(c)?`${i}${s(c)}${l}`:n),o}function Ee(e,t){if(!t)return null;let r=k.dirname(k.resolve(t)),s=k.resolve(e.outputDir),o=k.relative(r,s).replace(/\\/g,"/");return o?(o.startsWith(".")||(o=`./${o}`),o.endsWith("/")?o:`${o}/`):"./"}function ke(e,t,r){let s=Ee(t,r);if(!s)return e;let o=e;for(let n of de){let i=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=new RegExp(`(?:\\.{1,}/)+${i}`,"g"),c=new RegExp(`(?<!\\.)/${i}`,"g");o=o.replace(a,`${s}${n}`).replace(c,`${s}${n}`);let l=n.replace(/\//g,"\\/"),u=s.replace(/\//g,"\\/"),d=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),m=new RegExp(`(?:\\.{1,}\\\\/)+${d}`,"g"),v=new RegExp(`(?:\\.{1,}(?:\\\\/|\\\\))+${d}`,"g"),A=new RegExp(`(?<![\\.\\\\])\\/${d}`,"g");o=o.replace(m,`${u}${l}`).replace(v,`${u}${l}`).replace(A,`${u}${l}`);}return o}function _(e,t,r){if(e.urlRewriteMode==="absolute")return t;let s=(()=>{try{return new URL(t,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin)}catch{return null}})(),o=s?s.pathname:Z(t,e.targetOrigin),n=s?`${s.search}${s.hash}`:"";return e.urlRewriteMode==="root-relative"?`${o}${n}`:`${Q(e.outputDir,r,o)}${n}`}function F(e,t,r,s,o){$(e,r,_(t,s,o));}function Se(e,t,r,s,o){if(!r||r===s)return;$(e,r,s);let n=_(t,r,o),i=_(t,s,o);$(e,n,i);}function te(e,t,r,s,o={}){let n=e,i={};F(i,t,t.sourceOrigin,t.targetOrigin,s);for(let[c,l]of Object.entries(t.extraReplacements))F(i,t,c,l,s);for(let[c,l]of Object.entries(r))F(i,t,c,l,s);for(let[c,l]of Object.entries(o)){let u=r[c];!u||u===l||Se(i,t,l,u,s);}let a=Object.entries(i).sort((c,l)=>l[0].length-c[0].length);for(let[c,l]of a)n=we(n,c,l);return t.urlRewriteMode!=="absolute"&&(n=ke(n,t,s)),n=xe(n,a.map(([,c])=>c)),Re(t,n,s)&&(n=ye(n)),n}var y=String(process.env.PUBLISHER_WORKSPACE_BUCKET??"").trim(),g=x(process.env.PUBLISHER_WORKSPACE_PREFIX??""),W=String(process.env.PUBLISHER_ALLOWED_OPERATION??"").trim(),V=String(process.env.PUBLISHER_EXPORTER_VERSION??"unknown").trim(),B=String(process.env.PUBLISHER_PROXY_URL??"").trim(),We=Te(process.env.PUBLISHER_ALLOWED_TARGETS??"[]"),oe=new S3Client({}),re=new Map,T=null;function Te(e){try{let t=JSON.parse(e);return Array.isArray(t)?t.filter(r=>{if(!r||typeof r!="object")return !1;let s=r;return ["id","bucketName","prefix","region"].every(o=>typeof s[o]=="string")}).map(r=>({...r,prefix:x(r.prefix)})):[]}catch{return []}}function D(){if(!y)throw new Error("PUBLISHER_WORKSPACE_BUCKET is required.")}async function je(){if(T){let e=await T.catch(()=>null);if(e?.isConnected())return e}return T=chromium.launch({headless:true,args:["--no-sandbox","--disable-setuid-sandbox"],...B?{proxy:{server:B}}:{}}),T}async function ie(e){D();let t=w(e,g),r=await oe.send(new GetObjectCommand({Bucket:y,Key:t}));if(!r.Body)throw new Error(`S3 object has no body: ${t}`);return await r.Body.transformToString("utf8")}async function C(e){return JSON.parse(await ie(e))}async function H(e,t,r){D();let s=w(e,g),o=typeof t=="string"?Buffer.from(t,"utf8"):t,n=await oe.send(new PutObjectCommand({Bucket:y,Key:s,Body:o,ContentType:r,Metadata:{sha256:P(o)}}));return {bucket:y,key:s,sha256:P(o),bytes:o.byteLength,contentType:r,...n.ETag?{etag:n.ETag}:{},...n.VersionId?{versionId:n.VersionId}:{}}}async function Ce(e,t){return await H(e,`${JSON.stringify(t,null,2)}
5
+ `,"application/json; charset=utf-8")}async function Ve(e){try{let t=await C(e);return t.response??t}catch(t){if(t.name==="NoSuchKey"||t.$metadata?.httpStatusCode===404)return null;throw t}}function j(e){return [...new Set(e)].filter(t=>{try{let r=new URL(t);return r.protocol==="http:"||r.protocol==="https:"}catch{return false}}).sort()}async function ve(e,t,r){let o=await(await je()).newContext({viewport:e.options.viewport,ignoreHTTPSErrors:e.options.ignoreHttpsErrors,javaScriptEnabled:e.options.javaScriptEnabled,userAgent:"WPSuiteStaticPublisher/remote-worker-v1"}),n=await o.newPage(),i=new Set;n.on("request",a=>i.add(a.url()));try{let a=await n.goto(t,{waitUntil:"domcontentloaded",timeout:e.options.navigationTimeoutMs});e.options.readiness.waitForSelector&&await n.waitForSelector(e.options.readiness.waitForSelector,{timeout:e.options.readiness.timeoutMs}).catch(()=>{}),e.options.readiness.waitForFunction&&await n.waitForFunction(e.options.readiness.waitForFunction,void 0,{timeout:e.options.readiness.timeoutMs}).catch(()=>{}),e.options.readiness.fallbackWaitMs>0&&await n.waitForTimeout(e.options.readiness.fallbackWaitMs);let c=await n.evaluate(()=>{let p=(f,ae)=>{let M=[];for(let ce of document.querySelectorAll(f))for(let N of ae){let K=ce.getAttribute(N);if(K)if(N.includes("srcset"))for(let le of K.split(",")){let q=le.trim().split(/\s+/,1)[0];q&&M.push(q);}else M.push(K);}return M},b=f=>{try{return new URL(f,document.baseURI).href}catch{return null}};return {links:p("a[href]",["href"]).map(b).filter(f=>f!==null),assets:p("img,script,link,source,video,audio,iframe,[data-src],[data-href],[data-resource-url]",["src","href","srcset","data-src","data-srcset","data-href","data-resource-url","poster"]).map(b).filter(f=>f!==null)}}),l=await n.content(),u=new URL(t),d=j(c.links).filter(p=>{let b=new URL(p);return b.hash="",b.origin===u.origin}),m=E(L(g,e.jobId,e.taskId),"pages",`${String(r).padStart(4,"0")}-${P(t).slice(0,24)}.html`),v=await H(m,l,"text/html; charset=utf-8"),A=(await o.cookies()).map(p=>({name:p.name,domain:p.domain,path:p.path,expires:p.expires,httpOnly:p.httpOnly,secure:p.secure,sameSite:p.sameSite})),U=a?.status()??null;return {requestedUrl:t,finalUrl:n.url()||null,outcome:U!==null&&U>=400?"http-error":"rendered",httpStatus:U,contentType:a?.headers()["content-type"]??null,html:v,discoveredPages:d,discoveredAssets:j(c.assets),networkUrls:j([...i]),cookies:A}}catch(a){return {requestedUrl:t,finalUrl:n.url()||null,outcome:"failed",httpStatus:null,contentType:null,html:null,discoveredPages:[],discoveredAssets:[],networkUrls:j([...i]),cookies:[],error:a instanceof Error?a.message:String(a)}}finally{await o.close().catch(()=>{});}}async function Ae(e,t){if(!Array.isArray(e.urls)||e.urls.length<1||e.urls.length>20)throw new Error("Render tasks require between 1 and 20 URLs.");let r=new URL(e.sourceOrigin).origin,s=[];for(let n=0;n<e.urls.length;n+=1){let i=e.urls[n];if(!i)continue;let a=t.getRemainingTimeInMillis?.();if(a!==void 0&&a<6e4){s.push({requestedUrl:i,finalUrl:null,outcome:"deferred",httpStatus:null,contentType:null,html:null,discoveredPages:[],discoveredAssets:[],networkUrls:[],cookies:[],error:"Worker stopped accepting URLs because less than 60 seconds remained."});continue}let c=new URL(i);if(c.origin!==r)throw new Error(`Primary render URL is outside sourceOrigin: ${i}`);s.push(await ve(e,c.toString(),n));}let o=s.filter(n=>n.outcome==="failed"||n.outcome==="deferred").length;return {response:{schemaVersion:h,operation:"render",jobId:e.jobId,taskId:e.taskId,status:o>0?"partial":"succeeded",completedItems:s.length-o,failedItems:o,exporterVersion:V},detail:{pages:s}}}async function Ue(e){if(!Array.isArray(e.items)||e.items.length<1||e.items.length>500)throw new Error("Rewrite tasks require between 1 and 500 objects.");let r={...await C(e.configKey),outputDir:"/workspace"},s=await C(e.assetMapKey),o=e.previousAssetMapKey?await C(e.previousAssetMapKey):{},n=[];for(let i of e.items){let a=w(i.inputKey,g),c=w(i.outputKey,g),l=await ie(a),u=`/workspace/${i.relativePath.replace(/^\/+/,"")}`,d=te(l,r,s,u,o),m=await H(c,d,"text/plain; charset=utf-8");n.push({inputKey:a,outputKey:c,changed:d!==l,output:m});}return {response:{schemaVersion:h,operation:"rewrite",jobId:e.jobId,taskId:e.taskId,status:"succeeded",completedItems:n.length,failedItems:0,exporterVersion:V},detail:{objects:n}}}function Me(e,t){return `${e}/${t.split("/").map(r=>encodeURIComponent(r)).join("/")}`}async function Ke(e){if(!Array.isArray(e.items)||e.items.length<1||e.items.length>1e3)throw new Error("Deploy copy tasks require between 1 and 1000 objects.");let t=We.find(o=>o.id===e.targetId);if(!t)throw new Error(`Unknown deployment target: ${e.targetId}`);let r=re.get(t.region);r||(r=new S3Client({region:t.region}),re.set(t.region,r));let s=[];for(let o of e.items){let n=w(o.sourceKey,g),i=E(t.prefix,o.targetRelativeKey),a=await r.send(new CopyObjectCommand({Bucket:t.bucketName,Key:i,CopySource:Me(y,n)}));s.push({sourceKey:n,targetKey:i,...a.CopyObjectResult?.ETag?{etag:a.CopyObjectResult.ETag}:{}});}return {response:{schemaVersion:h,operation:"deploy-copy",jobId:e.jobId,taskId:e.taskId,status:"succeeded",completedItems:s.length,failedItems:0,exporterVersion:V},detail:{objects:s,targetId:t.id}}}async function ne(e,t){if(e.operation==="health")return {response:{schemaVersion:h,operation:"health",jobId:e.jobId,taskId:e.taskId,status:"succeeded",completedItems:1,failedItems:0,exporterVersion:V},detail:{allowedOperation:W,workspaceBucket:y,workspacePrefix:g,proxyConfigured:!!B}};if(W&&W!==e.operation)throw new Error(`Function is configured for ${W}, not ${e.operation}.`);return e.operation==="render"?await Ae(e,t):e.operation==="rewrite"?await Ue(e):await Ke(e)}async function ut(e,t={}){let r=J(e);if(r.operation==="health")return (await ne(r,t)).response;D();let s=E(L(g,r.jobId,r.taskId),"result.json"),o=await Ve(s);if(o)return o;let n=await ne(r,t),i={...n.response,resultKey:s};return await Ce(s,{schemaVersion:h,response:i,detail:n.detail,completedAt:new Date().toISOString(),requestId:t.awsRequestId??null}),i}export{ut as handler};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smart-cloud/publisher-exporter",
3
- "version": "1.1.59",
3
+ "version": "1.1.61",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Headless Playwright static publisher for WordPress/Elementor sites with sitemap-only page discovery, strict asset capture, escaped URL rewrite, structured logs, and targeted retry modes.",
@@ -10,6 +10,7 @@
10
10
  "files": [
11
11
  "dist",
12
12
  "publisher.config.example.json",
13
+ "remote-workers.example.json",
13
14
  "README.md",
14
15
  "package.json"
15
16
  ],
@@ -35,6 +36,7 @@
35
36
  "deploy": "node dist/deploy.js",
36
37
  "invalidate": "node dist/invalidate.js",
37
38
  "logs:prune": "node dist/prune-logs.js",
39
+ "remote-workers:health": "node dist/remote-worker-health.js",
38
40
  "queue:run": "node dist/queue-runner.js",
39
41
  "queue:drain": "node dist/queue-runner.js --max-jobs=100",
40
42
  "publish:site": "npm run build && npm run crawl && npm run deploy && npm run invalidate",
@@ -44,7 +46,9 @@
44
46
  },
45
47
  "dependencies": {
46
48
  "@aws-sdk/client-cloudfront": "^3.1127.0",
49
+ "@aws-sdk/client-lambda": "^3.1127.0",
47
50
  "@aws-sdk/client-s3": "^3.1127.0",
51
+ "@aws-sdk/credential-providers": "^3.1127.0",
48
52
  "@aws-sdk/lib-storage": "^3.1127.0",
49
53
  "@smart-cloud/publisher-core": "^1.1.10",
50
54
  "@smart-cloud/wpsuite-core": "^2.4.1",
@@ -0,0 +1,16 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "region": "eu-central-1",
4
+ "roleArn": "arn:aws:iam::123456789012:role/WpSuiteStaticPublisherWorkers-ExporterAccessRole",
5
+ "roleSessionName": "wpsuite-static-publisher",
6
+ "workspace": {
7
+ "bucket": "existing-workspace-bucket",
8
+ "prefix": "static-publisher/dev/"
9
+ },
10
+ "functions": {
11
+ "render": "arn:aws:lambda:eu-central-1:123456789012:function:render-worker:live",
12
+ "rewrite": "arn:aws:lambda:eu-central-1:123456789012:function:rewrite-worker:live",
13
+ "deploy-copy": "arn:aws:lambda:eu-central-1:123456789012:function:deploy-worker:live"
14
+ },
15
+ "protocolVersion": 1
16
+ }