sample-aws-pricing-calculator-mcp 1.3.6 → 1.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp-server.js +5 -5
- package/package.json +1 -1
package/dist/mcp-server.js
CHANGED
|
@@ -96,7 +96,7 @@ ${w.join(`
|
|
|
96
96
|
Use get_service_fields to discover valid values.`,correctedConfig:t,corrections:[]};let I=await nle(c,u),k=[];for(let ne of I){if(ne.type!=="columnFormIPM"||!ne.selectorValues)continue;let fe=t[ne.id];if(!(!fe||!fe.value||!Array.isArray(fe.value)))for(let pe of fe.value)for(let[Ye,gt]of Object.entries(ne.selectorValues)){if(!gt||gt.length===0)continue;let pr=pe[Ye];if(!pr)continue;let Xr=typeof pr=="object"&&pr.value!==void 0?pr.value:pr;if(typeof Xr=="string"&&!gt.includes(Xr)){let fn=Eu(Xr,gt),dl=fn.length?` Did you mean: ${fn.map(gc=>`"${gc}"`).join(", ")}?`:"";k.push(` Field "${ne.id}", selector "${Ye}": "${Xr}" is not valid.${dl}
|
|
97
97
|
Allowed: ${gt.slice(0,10).join(", ")}${gt.length>10?` ... (${gt.length} total)`:""}`)}}}if(k.length>0)return{error:`Invalid selector values for ${s.key}:
|
|
98
98
|
${k.join(`
|
|
99
|
-
`)}`,correctedConfig:t,corrections:[]};let T=i&&typeof i.get=="function"?ule(i,s.key):void 0,W=(typeof n=="string"&&n.trim()?n.trim():null)||T?.templateId||(typeof c.templates?.[0]=="object"?c.templates[0]?.id:null),re=W?cle(c,W):null,xe=mle({template:re,catalogEntry:T,configKeys:new Set(a)});return{error:null,correctedConfig:m,corrections:g,...$?{truncated:!0}:{},...xe.length>0?{missingRequired:xe}:{}}}catch{return{error:null,correctedConfig:t,corrections:[]}}}function mle({template:e,catalogEntry:t,configKeys:r}){return e?sle(e,t,{},{skipMathWalk:!0}).filter(n=>!r.has(n)):[]}Hk.exports={META_KEYS:Bk,levenshtein:P_,suggestMatch:Eu,validateConfigKeys:ple,validateFieldValue:Vk}});var Xk=_((Mxe,Wk)=>{var{canRehydrate:hle}=x_();function Gk(e){let t=new Set;for(let r of Kk(e))r.serviceCode&&t.add(r.serviceCode);return t}function*Kk(e){let t=Object.values(e.services||{});for(let r of Object.values(e.groups||{}))t.push(...Object.values(r.services||{}));for(let r of t){yield r;for(let i of r.subServices||[])yield i}}function gle(e){let t=null,r=i=>{if(!(t||!i||typeof i!="object")){if(i.subType==="columnFormIPM"&&i.mappingDefinitionName){t=i;return}for(let n of Object.values(i))n&&typeof n=="object"&&r(n)}};return r(e),t}async function vle({savedBlob:e,partition:t="aws",catalog:r}={}){if(!e||typeof e!="object")throw new TypeError("canRehydrateFetch requires a savedBlob object");let i=Fs(),n=await i.loadManifest(t),a=Gk(e),o=new Map;for(let l of a)try{let d=await i.fetchServiceDefinition(n,l,t);d&&o.set(l,d)}catch{}let s=null;try{s=await i.loadRegionList(t)}catch{}let c=new Map,u=new Map;try{for(let l of Kk(e)){if(!l.serviceCode||c.has(l.serviceCode))continue;let d=o.get(l.serviceCode);if(!d)continue;let f=gle(d);if(!f)continue;let p=l.region;if(p)try{let m=await i.loadSelectorAggregations(d,f,p);m&&c.set(l.serviceCode,m);let g=await i.loadSelectorDefaults(d,f);g&&u.set(l.serviceCode,g)}catch{}}}catch{}return hle({savedBlob:e,manifest:n,perServiceDefinitions:o,catalog:r,regionList:s,aggregations:c,selectorDefaults:u})}Wk.exports={canRehydrateFetch:vle,collectServiceCodes:Gk}});var iC=_((Nxe,nC)=>{"use strict";var{PARTITIONS:Yk,loadManifest:_m,fetchServiceDefinition:Qk,extractInputFields:yle,enrichFieldsWithMetadata:ble,findService:I_}=Fs(),{validateConfigKeys:_le}=Jk(),{canRehydrateFetch:wle}=Xk(),{nextStepFor:Sle,notFoundHintFor:$le,allFieldsAreSyntheticSlots:xle,findCatalogEntry:Ole,partialEntryHintFor:Ple}=bm(),{getEntry:j_}=gm(),{synthesizeAgentFields:Ile}=S_(),wm=Pu();function eC(e){return{content:[{type:"text",text:e}]}}function Sm(e){return{content:[{type:"text",text:e}],isError:!0}}function jle(e){return eC(JSON.stringify(e,null,2))}function Ele(e,{requireExplicit:t=!1}={}){return!e&&!t||Yk[e]?null:Sm(`Unknown partition '${e}'. Valid partitions: ${Object.keys(Yk).join(", ")}`)}function Tle(e){try{let t=JSON.parse(e);return Array.isArray(t)||(t=[t]),{entries:t}}catch{return{error:Sm("Invalid JSON in services parameter.")}}}function tC(e,t){let r=t?.defaultFields;if(!r||typeof r!="object")return e;let i=null;for(let[n,a]of Object.entries(r))n in e||(i===null&&(i={...e}),i[n]=a);return i===null?e:i}function C_(e){return(e&&Array.isArray(e.templates)?e.templates:[]).map(r=>typeof r=="string"?r:r&&r.id).filter(Boolean)}function E_(e){let t=C_(e),r=t.find(n=>/withoutfreetier/i.test(n)),i=t.find(n=>/withfreetier/i.test(n)&&!/withoutfreetier/i.test(n));return i&&r?{includeFreeTier:i,excludeFreeTier:r}:null}var kle=/^amazon(rds|aurora)/i,Cle=/backup|outposts/i;function T_(e){return typeof e=="string"&&kle.test(e)&&!Cle.test(e)}var k_=`AWS Database Savings Plans are only available on Gen 7+ instance families (e.g. m7g/r7g, m8g/r8g, m9g). T-class instances (t3, t4g) and anything Gen 6 or older (m5, r5, m6, r6, ...) are NOT eligible at all \u2014 on any RDS engine.
|
|
99
|
+
`)}`,correctedConfig:t,corrections:[]};let T=i&&typeof i.get=="function"?ule(i,s.key):void 0,W=(typeof n=="string"&&n.trim()?n.trim():null)||T?.templateId||(typeof c.templates?.[0]=="object"?c.templates[0]?.id:null),re=W?cle(c,W):null,xe=mle({template:re,catalogEntry:T,configKeys:new Set(a)});return{error:null,correctedConfig:m,corrections:g,...$?{truncated:!0}:{},...xe.length>0?{missingRequired:xe}:{}}}catch{return{error:null,correctedConfig:t,corrections:[]}}}function mle({template:e,catalogEntry:t,configKeys:r}){return e?sle(e,t,{},{skipMathWalk:!0}).filter(n=>!r.has(n)):[]}Hk.exports={META_KEYS:Bk,levenshtein:P_,suggestMatch:Eu,validateConfigKeys:ple,validateFieldValue:Vk}});var Xk=_((Mxe,Wk)=>{var{canRehydrate:hle}=x_();function Gk(e){let t=new Set;for(let r of Kk(e))r.serviceCode&&t.add(r.serviceCode);return t}function*Kk(e){let t=Object.values(e.services||{});for(let r of Object.values(e.groups||{}))t.push(...Object.values(r.services||{}));for(let r of t){yield r;for(let i of r.subServices||[])yield i}}function gle(e){let t=null,r=i=>{if(!(t||!i||typeof i!="object")){if(i.subType==="columnFormIPM"&&i.mappingDefinitionName){t=i;return}for(let n of Object.values(i))n&&typeof n=="object"&&r(n)}};return r(e),t}async function vle({savedBlob:e,partition:t="aws",catalog:r}={}){if(!e||typeof e!="object")throw new TypeError("canRehydrateFetch requires a savedBlob object");let i=Fs(),n=await i.loadManifest(t),a=Gk(e),o=new Map;for(let l of a)try{let d=await i.fetchServiceDefinition(n,l,t);d&&o.set(l,d)}catch{}let s=null;try{s=await i.loadRegionList(t)}catch{}let c=new Map,u=new Map;try{for(let l of Kk(e)){if(!l.serviceCode||c.has(l.serviceCode))continue;let d=o.get(l.serviceCode);if(!d)continue;let f=gle(d);if(!f)continue;let p=l.region;if(p)try{let m=await i.loadSelectorAggregations(d,f,p);m&&c.set(l.serviceCode,m);let g=await i.loadSelectorDefaults(d,f);g&&u.set(l.serviceCode,g)}catch{}}}catch{}return hle({savedBlob:e,manifest:n,perServiceDefinitions:o,catalog:r,regionList:s,aggregations:c,selectorDefaults:u})}Wk.exports={canRehydrateFetch:vle,collectServiceCodes:Gk}});var iC=_((Nxe,nC)=>{"use strict";var{PARTITIONS:Yk,loadManifest:_m,fetchServiceDefinition:Qk,extractInputFields:yle,enrichFieldsWithMetadata:ble,findService:I_}=Fs(),{validateConfigKeys:_le}=Jk(),{canRehydrateFetch:wle}=Xk(),{nextStepFor:Sle,notFoundHintFor:$le,allFieldsAreSyntheticSlots:xle,findCatalogEntry:Ole,partialEntryHintFor:Ple}=bm(),{getEntry:j_}=gm(),{synthesizeAgentFields:Ile}=S_(),wm=Pu();function eC(e){return{content:[{type:"text",text:e}]}}function Sm(e){return{content:[{type:"text",text:e}],isError:!0}}function jle(e){return eC(JSON.stringify(e,null,2))}function Ele(e,{requireExplicit:t=!1}={}){return!e&&!t||Yk[e]?null:Sm(`Unknown partition '${e}'. Valid partitions: ${Object.keys(Yk).join(", ")}`)}function Tle(e){try{let t=JSON.parse(e);return Array.isArray(t)||(t=[t]),{entries:t}}catch{return{error:Sm("Invalid JSON in services parameter.")}}}function tC(e,t){let r=t?.defaultFields;if(!r||typeof r!="object")return e;let i=null;for(let[n,a]of Object.entries(r))n in e||(i===null&&(i={...e}),i[n]=a);return i===null?e:i}function C_(e){return(e&&Array.isArray(e.templates)?e.templates:[]).map(r=>typeof r=="string"?r:r&&r.id).filter(Boolean)}function E_(e){let t=C_(e),r=t.find(n=>/withoutfreetier/i.test(n)),i=t.find(n=>/withfreetier/i.test(n)&&!/withoutfreetier/i.test(n));return i&&r?{includeFreeTier:i,excludeFreeTier:r}:null}var kle=/^amazon(rds|aurora)/i,Cle=/backup|outposts/i;function T_(e){return typeof e=="string"&&kle.test(e)&&!Cle.test(e)}var k_=`AWS Database Savings Plans are only available on Gen 7+ instance families (e.g. m7g/r7g, m8g/r8g, m9g). T-class instances (t3, t4g) and anything Gen 6 or older (m5, r5, m6, r6, ...) are NOT eligible at all \u2014 on any RDS engine. They are also only sold as a 1-year term (LeaseContractLength "1yr") \u2014 there is no 3-year Database Savings Plan. Neither constraint is enforced by the save-time lint, so picking "Database Savings Plans" as TermType on an ineligible instance, or with a 3-year LeaseContractLength, saves and rehydrates without error but silently misprices. Confirm the instance family's generation and use a 1-year term with the user before setting TermType to "Database Savings Plans".`;function rC(e){try{return JSON.stringify(e).toLowerCase().includes("database savings plans")}catch{return!1}}function Ale(e,t,r,i){if(typeof r!="string"||!r)return null;let n=i||null,a=n?(e.groups||{})[n]?.services:e.services;if(!a)return null;for(let[o,s]of Object.entries(a))if(o.split(":")[0]===t&&s&&s.description===r)return{service:t,description:r,group:n};return null}function Dle({catalog:e}){async function t(d,f){let p=[];for(let m of f){let{service:g,instance:w,group:$}=m,O=m.config;if(!g||!O){p.push({error:'Missing "service" or "config" in entry',entry:m});continue}if(typeof O=="string")try{O=JSON.parse(O)}catch{p.push({error:"Invalid JSON in config",service:g});continue}let I=w?`${g}:${w}`:g,k=await _le(g,O,d.partition,e,m.estimateFor);if(k.error){p.push({error:k.error,service:I});continue}O=k.correctedConfig;let T=j_(e,g);O=tC(O,T);let N=null;try{let pe=await _m(d.partition||"aws"),Ye=I_(pe,g);Ye&&(N=await Qk(pe,Ye.key,d.partition||"aws"))}catch{}let W=E_(N),re=typeof m.estimateFor=="string"&&m.estimateFor.trim()?m.estimateFor.trim():null;if(re&&N){let pe=C_(N);if(pe.length>0&&!pe.includes(re)){p.push({error:`estimateFor "${re}" is not a valid template for ${g}. Valid templates: ${pe.join(", ")}.`,service:I});continue}}let xe=re||T?.templateId||void 0;!re&&xe&&T.status==="unverified"&&wm.templateHint.unverified({serviceCode:g,templateId:xe,estimateId:d.id});let ne=Ale(d,g,O.description,$);d.addService(I,O,{group:$,templateIdHint:xe});let fe={success:!0,service:I,group:$||"(ungrouped)"};T_(g)&&rC(O)&&(fe.pricing_model_hint=k_),W&&!re&&(fe.free_tier_choice={applied:W.includeFreeTier,includeFreeTier:W.includeFreeTier,excludeFreeTier:W.excludeFreeTier,action_required:`${g} offers an AWS Free Tier choice and DEFAULTED to include it (${W.includeFreeTier}). Free Tier allowances are subtracted, which understates production/steady-state cost. Ask the user whether to include or exclude the Free Tier; to exclude it, re-add this service with estimateFor: "${W.excludeFreeTier}".`}),ne&&(fe.existing_entry=ne,fe.warning=`An entry with service="${g}" and description="${O.description}" already exists in this estimate (group: "${ne.group||"(ungrouped)"}"). add_service has appended a duplicate row \u2014 this inflates the cost. If you intended to replace the previous attempt (e.g. retrying after an error), call create_estimate to start fresh instead.`),k.corrections.length>0&&(fe.corrections=k.corrections,k.truncated&&(fe.truncated=!0)),k.missingRequired&&k.missingRequired.length>0&&(fe.partial=!0,fe.missing_required_fields=k.missingRequired,fe.next_step=Ple({serviceKey:g,missingFields:k.missingRequired,catalog:e})),p.push(fe)}return p}async function r(d){let f=await d.toAWSPayload(),p=await wle({savedBlob:f,partition:d.partition||void 0,catalog:e});return{blob:f,lintResult:p}}function i(d){return Sm(`Estimate "${d}" not found.
|
|
100
100
|
|
|
101
101
|
Next step: ${$le(d)}`)}function n(d,f){let p=d.status,m=p==="required-input"?k=>k.severity==="required-only":()=>!0,g=d.services.map(k=>k.failures.filter(m).map(T=>T.message).join("; ")).filter(Boolean).join(" | "),w=d.services.flatMap(k=>k.failures.filter(m).map(T=>T.predicate)).filter((k,T,N)=>N.indexOf(k)===T).join(", "),$=Sle(d,e),O=$?`
|
|
102
102
|
|
|
@@ -104,7 +104,7 @@ Next step: ${$}`:"";return`${f} ${p==="required-input"?"the saved estimate is mi
|
|
|
104
104
|
|
|
105
105
|
Predicate names: ${w}.`}async function a(d){let{lintResult:f}=await r(d);if(wm.lint({verdict:f.status,services:f.services,estimateId:d.id}),f.status==="read-only"||f.status==="required-input")return{isError:!0,text:n(f,"Export refused \u2014")};let p=await d.export();return{isError:!1,sharable_url:p.shareableUrl,aws_estimate_id:p.estimateId}}async function o(d,f){let p=await _m(f),m=await Qk(p,d.key,f);if(!m)return null;let g=yle(m),w=await ble(m,g),$=Ile(d.key,w),O={serviceCode:d.key,serviceName:d.name,fields:$},I=E_(m);if(I){let T=j_(e,d.key);O.freeTierChoice={includeFreeTier:I.includeFreeTier,excludeFreeTier:I.excludeFreeTier,default:T?.templateId||I.includeFreeTier,note:"This service exposes an AWS Free Tier template choice. ASK THE USER whether to include or exclude the Free Tier, then set estimateFor on the add_service/build_estimate entry to includeFreeTier or excludeFreeTier above. If unspecified it defaults to including the Free Tier, which understates steady-state/production cost."}}let k=j_(e,d.key);return k&&(O.catalog={status:k.status,templateId:k.templateId,required:k.required,traps:k.traps,subServices:k.subServices,minimalConfig:k.minimalConfig,lastVerifiedAt:k.lastVerifiedAt}),T_(d.key)&&(O.pricingModelHint=k_),O}let s=new Map;if(e)for(let d of e.values())for(let f of d.subServices||[])for(let p of f.productCodes||[])p&&s.set(p,{parentEntry:d,providerCode:f.serviceCode});async function c({svc:d,partition:f}){let p=s.get(d.key);if(!p)return null;let{parentEntry:m,providerCode:g}=p,w=null,$=await _m(f),O=I_($,g);if(O)try{w=await o(O,f)}catch{}return wm.getServiceFields.redirectToParent({serviceCode:d.key,redirectTo:g,childCodes:[g],previewServiceCode:w?.serviceCode||null}),{serviceCode:d.key,serviceName:d.name,status:"redirect_to_provider",next_step:`Service "${d.key}" is a product under the "${g}" provider in ${m.serviceCode}. ${m.serviceCode} is structured per-provider, not per-product \u2014 the calculator does not accept "${d.key}" as a top-level service. Use service code "${g}" with add_service / build_estimate; select the specific model via modelSelection in the provider's field set (previewed below).`,redirect_to:g,parent_service_code:m.serviceCode,catalog:{status:m.status,traps:m.traps},...w?{preview_fields_for:w}:{}}}function u(d){if(!s.size)return d;let f=m=>{let g=s.get(m.key);return g?{...m,redirect_to:g.providerCode,note:`Product under "${g.providerCode}" provider in ${g.parentEntry.serviceCode}; use service code "${g.providerCode}" in add_service / build_estimate.`}:m};if(Array.isArray(d))return d.map(f);let p={};for(let[m,g]of Object.entries(d))p[m]=Array.isArray(g)?g.map(f):g;return p}async function l({svc:d,fields:f,partition:p}){let m=f.map(T=>T.id),g=d.isActive==="false",w=xle(m);if(!g||!w)return null;let $=Ole(e,d.key);if(!$||$.serviceCode===d.key)return null;let O=($.subServices||[]).map(T=>T.serviceCode).filter(Boolean),I=null;if(O[0]){let T=await _m(p),N=I_(T,O[0]);if(N)try{I=await o(N,p)}catch{}}wm.getServiceFields.redirectToParent({serviceCode:d.key,redirectTo:$.serviceCode,childCodes:O,previewServiceCode:I?.serviceCode||null});let k={serviceCode:d.key,serviceName:d.name,status:"redirect_to_parent",next_step:`Service "${d.key}" is a deprecated parent envelope with no real input fields. Use one of the verified child service codes instead: ${O.join(", ")}. `+(O.length>1?`Pick the one matching the user's intent \u2014 fields for "${O[0]}" are previewed below; if a different child fits better, call get_service_fields with that code.`:`Fields for "${O[0]}" are previewed below; use that code in add_service.`),redirect_to:$.serviceCode,child_service_codes:O,catalog:{status:$.status,traps:$.traps,subServices:$.subServices}};return I&&(k.preview_fields_for=I),k}return{addEntries:t,lintEstimate:r,estimateNotFoundResult:i,formatLintRefusal:n,exportWithLint:a,buildFieldsResult:o,maybeBuildRedirectResult:l,maybeBuildProductRedirect:c,annotateSearchResults:u}}nC.exports={createHandlerHelpers:Dle,mcpTextOk:eC,mcpTextErr:Sm,mcpJsonOk:jle,checkPartition:Ele,parseServicesArg:Tle,applyDefaultFields:tC,detectFreeTierChoice:E_,templateIdList:C_,isRdsFamilyService:T_,configMentionsDatabaseSavingsPlans:rC,DATABASE_SAVINGS_PLANS_HINT:k_}});var uC=_((zxe,cC)=>{var Do;try{Do=require("playwright").chromium}catch{Do=null}var Rle=require("node:fs"),aC=6e4,D_=3e4,Mle=2e4,Nle=250,zle=2e4,Zle=1e4,qle=2e4,Ule=['button:has-text("Export")','button:has-text("Export estimate")','a:has-text("Export")','[data-testid*="export"]','[aria-label*="Export"]'];function oC(e,t){if(!e)return{available:!1,reason:"playwright-missing",message:"The Playwright library is not installed. It is an on-demand dependency used only to render calculator-computed costs.",install:["npm install playwright","npx playwright install chromium","npx playwright install-deps chromium"]};let r=null;try{r=e.executablePath()}catch{r=null}return!r||!t(r)?{available:!1,reason:"chromium-missing",message:"Playwright is installed but the Chromium browser binary is not. It is an on-demand ~150MB download.",install:["npx playwright install chromium"]}:{available:!0}}function Lle(){return oC(Do,Rle.existsSync)}async function Fle(e){if(!Do)throw new Error("Playwright is not installed. Run: npm install --save-dev playwright && npx playwright install chromium");let t=await Do.launch({headless:!0});try{let r=await t.newContext({viewport:{width:1440,height:900}});try{let i=await r.newPage();await i.goto(e,{waitUntil:"networkidle",timeout:aC});let n=await Vle(i,Ule,D_);if(!n)throw new Error("Export button not found on page");if(!await Hle(i,n))throw new Error("rehydration failed: calculator disabled the Export button (estimate is in Read-only mode)");let o=await i.locator("text=/USD/").all(),s=await Promise.all(o.map(g=>g.innerText())),c=s.length>=2?R_(s[1]):null,u=await i.locator('tr, [role="row"]').all(),l=[];for(let g of u){let w=await g.locator('td, [role="cell"]').all().catch(()=>[]);w.length<6||l.push(await Promise.all(w.map($=>$.innerText().catch(()=>""))))}let d=sC(l),f=new Map,p=new Map;for(let{service:g,monthly:w,config:$}of d)f.set(g,w),p.set(g,$);let m=d.length?d.reduce((g,w)=>g+w.monthly,0):null;return{monthlyCost:c,monthlyByService:f,configByService:p,rows:d,rowsTotal:m}}finally{await r.close()}}finally{await t.close()}}async function A_(e,t){let r=Date.now()+t;for(;Date.now()<r;){if(await e.isVisible().catch(()=>!1)&&!await e.isDisabled().catch(()=>!0))return!0;await new Promise(n=>setTimeout(n,250))}return!1}async function Ble(e,{update:t=!0}={}){if(!Do)throw new Error("Playwright is not installed. Run: npm install --save-dev playwright && npx playwright install chromium");let r=await Do.launch({headless:!0});try{let i=await r.newContext({viewport:{width:1440,height:900}});try{let n=await i.newPage();await n.goto(e,{waitUntil:"networkidle",timeout:aC});let a=n.getByRole("button",{name:/Accept all cookies/i}).first();await a.isVisible().catch(()=>!1)&&(await a.click().catch(()=>{}),await n.waitForTimeout(500));let o=n.getByRole("button",{name:"Export"}).first();if(!await A_(o,D_))throw new Error("rehydration failed: the estimate never became ready (it may be read-only or broken)");let s=n.getByRole("button",{name:"Share"}).first();if(t){let f=n.getByRole("button",{name:/Update estimate/}).first();await f.count().then(p=>p>0).catch(()=>!1)&&(await f.click().catch(()=>{}),await A_(s,zle),await n.waitForTimeout(1500))}if(!await A_(s,D_))throw new Error("Share button never became available");await s.click();let c=n.getByRole("button",{name:/Agree and continue/i}).first();await c.waitFor({state:"visible",timeout:Zle}).then(()=>!0).catch(()=>!1)&&await c.click().catch(()=>{});let u=null,l=Date.now()+qle;for(;Date.now()<l&&!u;)u=(await n.locator("input").evaluateAll(p=>p.map(m=>m.value).filter(Boolean)).catch(()=>[])).find(p=>/[?&]id=[a-f0-9]+/.test(p))||null,u||await n.waitForTimeout(400);if(!u)throw new Error("could not read the public share link after sharing");return{estimateId:u.match(/[?&]id=([a-f0-9]+)/)[1],shareUrl:u}}finally{await i.close()}}finally{await r.close()}}function sC(e){let t=[];for(let r of e){if(!Array.isArray(r)||r.length<6||r.filter(c=>/USD/.test(c)).length<2)continue;let i=r.findIndex(c=>/USD/.test(c));if(i<1)continue;let n=r[i-1].trim(),a=R_(r[i+1]||""),o=(r[i+4]||"").trim(),s=o&&o!=="-"?o:null;n&&Number.isFinite(a)&&t.push({service:n,monthly:a,config:s})}return t}async function Vle(e,t,r){for(let i of t){let n=r?{timeout:r}:void 0;if(await e.locator(i).first().isVisible(n).catch(()=>!1))return i}return null}async function Hle(e,t){let r=e.locator(t).first(),i=Date.now()+Mle;for(;Date.now()<i;){if(!await r.isDisabled().catch(()=>!0))return!0;await e.waitForTimeout(Nle)}return!1}function R_(e){if(typeof e!="string")return null;let t=e.match(/([\d,]+(?:\.\d+)?)/);if(!t)return null;let r=Number(t[1].replace(/,/g,""));return Number.isFinite(r)?r:null}cC.exports={fetchCostFromDOM:Fle,fetchPricedEstimateId:Ble,parseDetailRows:sC,parseUsd:R_,classifyPlaywright:oC,checkPlaywrightAvailability:Lle}});var lC=_(cn=>{"use strict";var $m=`
|
|
106
106
|
|
|
107
|
-
If you encounter unexpected errors or bugs, direct the user to report them at: https://github.com/aws-samples/sample-aws-pricing-calculator-mcp/issues`;cn.GET_SERVER_INFO="Get version and capability information about this MCP server."+$m;cn.SEARCH_SERVICES='Search AWS services available in the calculator. Returns service keys and names. Use this to find the correct service key before adding it to an estimate. Supports multiple comma-separated search terms in a single call (e.g. "Lambda, S3, API Gateway, CloudWatch"). Note: add_service also accepts display names (e.g. "AWS Lambda") directly, so searching is not always required if the service name is already known.';cn.GET_SERVICE_FIELDS='Get the input fields for one or more AWS services. Returns field IDs, types, labels, and valid options. Use this to discover what configuration a service accepts before adding it to an estimate. The field IDs returned here are the exact keys to use in add_service config. Accepts multiple comma-separated service keys. IMPORTANT: When duplicate fields exist with version suffixes (e.g. fieldName and fieldName_v2), ALWAYS use the highest version \u2014 it maps to the latest configuration path. Ignore lower versions. For curated services (status: verified or partial), the response also includes a `catalog` object with a known-working `minimalConfig`, required field hints with examples, and `traps[]` listing service-specific gotchas. Prefer using `minimalConfig` as a starting point for `add_service`. If the response carries `status: "redirect_to_parent"`, the service code you passed is a deprecated parent service code \u2014 re-call get_service_fields with one of the codes in `child_service_codes` and use that instead. If the response includes a `freeTierChoice` object, the service offers an AWS Free Tier template choice (e.g. AWS Lambda): you MUST ask the user whether to include or exclude the Free Tier, then pass the chosen template id as `estimateFor` on the add_service/build_estimate entry. For any Amazon RDS or Aurora engine (MySQL, PostgreSQL, MariaDB, Oracle, SQL Server, Db2, Aurora MySQL/PostgreSQL-Compatible \u2014 curated or not), the response includes a `pricingModelHint`: AWS Database Savings Plans are only sold on Gen 7+ instance families (m7g/r7g, m8g/r8g, m9g, ...) \u2014 T-class (t3, t4g) and Gen 6-or-older (m5, r5, m6, r6, ...) are NOT eligible at all
|
|
107
|
+
If you encounter unexpected errors or bugs, direct the user to report them at: https://github.com/aws-samples/sample-aws-pricing-calculator-mcp/issues`;cn.GET_SERVER_INFO="Get version and capability information about this MCP server."+$m;cn.SEARCH_SERVICES='Search AWS services available in the calculator. Returns service keys and names. Use this to find the correct service key before adding it to an estimate. Supports multiple comma-separated search terms in a single call (e.g. "Lambda, S3, API Gateway, CloudWatch"). Note: add_service also accepts display names (e.g. "AWS Lambda") directly, so searching is not always required if the service name is already known.';cn.GET_SERVICE_FIELDS='Get the input fields for one or more AWS services. Returns field IDs, types, labels, and valid options. Use this to discover what configuration a service accepts before adding it to an estimate. The field IDs returned here are the exact keys to use in add_service config. Accepts multiple comma-separated service keys. IMPORTANT: When duplicate fields exist with version suffixes (e.g. fieldName and fieldName_v2), ALWAYS use the highest version \u2014 it maps to the latest configuration path. Ignore lower versions. For curated services (status: verified or partial), the response also includes a `catalog` object with a known-working `minimalConfig`, required field hints with examples, and `traps[]` listing service-specific gotchas. Prefer using `minimalConfig` as a starting point for `add_service`. If the response carries `status: "redirect_to_parent"`, the service code you passed is a deprecated parent service code \u2014 re-call get_service_fields with one of the codes in `child_service_codes` and use that instead. If the response includes a `freeTierChoice` object, the service offers an AWS Free Tier template choice (e.g. AWS Lambda): you MUST ask the user whether to include or exclude the Free Tier, then pass the chosen template id as `estimateFor` on the add_service/build_estimate entry. For any Amazon RDS or Aurora engine (MySQL, PostgreSQL, MariaDB, Oracle, SQL Server, Db2, Aurora MySQL/PostgreSQL-Compatible \u2014 curated or not), the response includes a `pricingModelHint`: AWS Database Savings Plans are only sold on Gen 7+ instance families (m7g/r7g, m8g/r8g, m9g, ...) \u2014 T-class (t3, t4g) and Gen 6-or-older (m5, r5, m6, r6, ...) are NOT eligible at all \u2014 and only as a 1-year term (no 3-year option). The calculator does not refuse an ineligible instance or a 3-year term at save time. Pass this along to the user before setting TermType to "Database Savings Plans".';cn.CREATE_ESTIMATE="Create a new empty estimate. Returns an estimate ID to use with add_service and export_estimate.";cn.ADD_SERVICE=`Add one or more AWS services to an estimate. Accepts a single service or a JSON array of services in the "services" parameter.
|
|
108
108
|
|
|
109
109
|
TEMPLATE / FREE TIER: Each entry may set an optional "estimateFor" template id to pick a specific pricing template. This is how you control the AWS Free Tier: services like AWS Lambda expose an include/exclude Free Tier template pair (surfaced as freeTierChoice by get_service_fields). When a service offers that choice you MUST ask the user whether to include or exclude the Free Tier and set "estimateFor" to the chosen template id \u2014 if you don't, it defaults to INCLUDING the Free Tier, which understates steady-state/production cost. When that default is applied the per-entry result carries a free_tier_choice object with the includeFreeTier/excludeFreeTier template ids so you can re-add with the user's choice.
|
|
110
110
|
|
|
@@ -138,7 +138,7 @@ For multi-service estimates, prefer build_estimate over create_estimate + add_se
|
|
|
138
138
|
|
|
139
139
|
RETRY SEMANTICS: add_service ALWAYS APPENDS \u2014 it never replaces an existing entry. If a previous attempt already added a service to this estimate (e.g. you are rebuilding after a validation issue, or the user reported a problem with an earlier save), DO NOT call add_service again on the same estimate_id with the same configuration; that produces a duplicate row and inflates the cost. Instead, call create_estimate to start fresh, then add the corrected services. As a defense, the response surfaces an "existing_entry" field when (service, description) already matches a stored entry \u2014 if you see that field, you are about to create a duplicate; back out and use create_estimate.
|
|
140
140
|
|
|
141
|
-
DATABASE SAVINGS PLANS: for any Amazon RDS/Aurora entry whose config sets a columnFormIPM TermType to "Database Savings Plans", the per-entry result carries a "pricing_model_hint" \u2014 Database Savings Plans are only sold on Gen 7+ instance families (m7g/r7g, m8g/r8g, m9g, ...); T-class (t3, t4g) and Gen 6-or-older (m5, r5, m6, r6, ...) are NOT eligible at all
|
|
141
|
+
DATABASE SAVINGS PLANS: for any Amazon RDS/Aurora entry whose config sets a columnFormIPM TermType to "Database Savings Plans", the per-entry result carries a "pricing_model_hint" \u2014 Database Savings Plans are only sold on Gen 7+ instance families (m7g/r7g, m8g/r8g, m9g, ...); T-class (t3, t4g) and Gen 6-or-older (m5, r5, m6, r6, ...) are NOT eligible at all. They are also only sold as a 1-year term (LeaseContractLength "1yr") \u2014 there is no 3-year Database Savings Plan. The save does not get refused for picking an ineligible instance or a 3-year term. Relay this to the user rather than trusting the save succeeded cleanly.`+$m;cn.VALIDATE_ESTIMATE="Dry-run preflight: builds the would-be saved payload and runs a static check \u2014 WITHOUT calling the AWS save API. Use this to verify an estimate will render correctly (editable, not frozen) before saving. Returns {lint_verdict, next_step, lint_services, would_be_payload}. If it passes, call export_estimate to save and get the shareable URL.";cn.EXPORT_ESTIMATE="Export an estimate to calculator.aws and get a shareable URL. The link will show the full estimate with AWS-calculated pricing. Before saving, runs a static check against the payload. If the check detects the estimate would be broken, the export is refused with details explaining what to fix. After a successful export, return the shareable URL to the user and stop \u2014 do NOT automatically call get_estimate_cost to read computed costs. That tool has an optional Playwright/Chromium dependency and must only run on an explicit user request for the actual cost.";cn.BUILD_ESTIMATE=`One-shot: create an estimate, add services, lint-preflight, save, and return the calculator URL. Replaces three separate calls (create_estimate + add_service + export_estimate). Returns {sharable_url, aws_estimate_id, services} on success.
|
|
142
142
|
|
|
143
143
|
TEMPLATE / FREE TIER: Each entry may set an optional "estimateFor" template id to pick a specific pricing template. Services like AWS Lambda expose an include/exclude Free Tier template pair (surfaced as freeTierChoice by get_service_fields). When a service offers that choice you MUST ask the user whether to include or exclude the Free Tier BEFORE building and set "estimateFor" accordingly \u2014 otherwise it defaults to INCLUDING the Free Tier, which understates steady-state/production cost. When the default is applied, the service's result carries a free_tier_choice object with the includeFreeTier/excludeFreeTier template ids.
|
|
144
144
|
|
|
@@ -154,7 +154,7 @@ Use "description" to label what each service entry represents. Be careful, descr
|
|
|
154
154
|
|
|
155
155
|
If any service fails validation, returns a structured needs_field_grounding redirect pointing you at get_service_fields for the affected services (isError:false; not a hard failure \u2014 call get_service_fields and retry). If the pre-save check detects the estimate would be broken, the save is refused and an error is returned with per-service details explaining what to fix.
|
|
156
156
|
|
|
157
|
-
DATABASE SAVINGS PLANS: for any Amazon RDS/Aurora entry whose config sets a columnFormIPM TermType to "Database Savings Plans", the per-service result carries a "pricing_model_hint" \u2014 Database Savings Plans are only sold on Gen 7+ instance families (m7g/r7g, m8g/r8g, m9g, ...); T-class (t3, t4g) and Gen 6-or-older (m5, r5, m6, r6, ...) are NOT eligible at all
|
|
157
|
+
DATABASE SAVINGS PLANS: for any Amazon RDS/Aurora entry whose config sets a columnFormIPM TermType to "Database Savings Plans", the per-service result carries a "pricing_model_hint" \u2014 Database Savings Plans are only sold on Gen 7+ instance families (m7g/r7g, m8g/r8g, m9g, ...); T-class (t3, t4g) and Gen 6-or-older (m5, r5, m6, r6, ...) are NOT eligible at all. They are also only sold as a 1-year term (LeaseContractLength "1yr") \u2014 there is no 3-year Database Savings Plan. The save does not get refused for picking an ineligible instance or a 3-year term. Relay this to the user rather than trusting the save succeeded cleanly.
|
|
158
158
|
|
|
159
159
|
The estimate is kept in the in-memory store, so the returned aws_estimate_id can be passed to add_service/export_estimate to extend it.
|
|
160
160
|
|
|
@@ -166,7 +166,7 @@ Returns upfront_cost, monthly_cost, total_12_months_cost (derived as upfront + 1
|
|
|
166
166
|
|
|
167
167
|
SIDE EFFECT: pressing Update+Share saves a FRESH copy of the estimate under a NEW id, returned as priced_estimate_url. The original id is unchanged. (This is why the tool is not marked read-only.)
|
|
168
168
|
|
|
169
|
-
ON-DEMAND DEPENDENCY: this tool requires Playwright AND the Chromium browser binary, which are NOT installed by default (Chromium is a ~150MB download). The tool checks for them first and, when either is missing, returns cost_available:false with reason and the exact install_commands instead of failing. Do NOT install them silently \u2014 surface the commands and ask the user to confirm before running them, then retry.`+$m});var dC=_((qxe,Jle)=>{Jle.exports={name:"sample-aws-pricing-calculator-mcp",version:"1.3.6",bin:"dist/mcp-server.js",files:["dist/mcp-server.js","catalog/schema.json","catalog/services/*.json"],description:"MCP server for creating, reading, updating AWS Pricing Calculator estimates through natural language.",license:"MIT-0",main:"mcp-server.js",scripts:{test:"npm run validate-catalog && SKIP_NETWORK=1 node --test test/*.test.js","test:network":"npm run validate-catalog && node --test test/*.test.js","test:roundtrip":"node --test test/catalog-roundtrip.test.js",mcp:"node mcp-server.js","validate-catalog":"node scripts/validate-catalog.js","validate-catalog:cost":"node scripts/validate-verified-catalog.js",build:"esbuild mcp-server.js --bundle --platform=node --outfile=dist/mcp-server.js --format=cjs --minify --external:@aws-sdk/client-dynamodb --external:@aws-sdk/lib-dynamodb --external:playwright --external:playwright-core && node scripts/emit-bundle-contract.js && rm -f dist/aws-calculator.zip && zip dist/aws-calculator.zip mcp-server.js lib/aws/aws-client.js lib/aws/fetch-resilience.js lib/aws/estimate-builder.js lib/aws/ec2.js lib/dom-cost.js package.json"},dependencies:{"@modelcontextprotocol/sdk":"1.32.1",express:"5.2.1"},peerDependencies:{"@aws-sdk/client-dynamodb":">=3.700.0","@aws-sdk/lib-dynamodb":">=3.700.0"},peerDependenciesMeta:{"@aws-sdk/client-dynamodb":{optional:!0},"@aws-sdk/lib-dynamodb":{optional:!0}},devDependencies:{"@aws-sdk/client-dynamodb":"3.1046.0","@aws-sdk/lib-dynamodb":"3.1046.0",ajv:"8.20.0","ajv-formats":"3.0.1",esbuild:"0.28.2",playwright:"1.63.0"}}});var pC=_(fC=>{var Gle="x-hono-already-sent";Object.defineProperty(fC,"X_ALREADY_SENT",{enumerable:!0,get:function(){return Gle}})});var mC=_(Tu=>{Object.defineProperty(Tu,Symbol.toStringTag,{value:"Module"});var Kle=class{#e;constructor(e){this.#e=e,this.raw=e.raw,this.url=e.url?new URL(e.url):null,this.protocol=e.protocol??null}send(e,t){this.#e.send(e,t??{})}raw;binaryType="arraybuffer";get readyState(){return this.#e.readyState}url;protocol;close(e,t){this.#e.close(e,t)}},Wle=e=>new MessageEvent("message",{data:e}),Xle=e=>((...t)=>{if(typeof t[0]=="function"){let[r,i]=t;return async function(a,o){let s=await e(a,await r(a),i);if(s)return s;await o()}}else{let[r,i,n]=t;return(async()=>{let a=await e(r,i,n);if(!a)throw new Error("Failed to upgrade WebSocket");return a})()}});Tu.WSContext=Kle;Tu.createWSMessageEvent=Wle;Tu.defineWebSocketHelper=Xle});var BC=_(Mo=>{Object.defineProperty(Mo,Symbol.toStringTag,{value:"Module"});var Yle=pC(),B_=require("node:http"),Ei=require("node:http2"),hC=require("node:stream"),Qle=mC(),wr=class extends Error{constructor(e,t){super(e,t),this.name="RequestError"}},ede=new Set(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","server","user-agent"]),tde=/^[!#$%&'*+\-.^_`|~\dA-Za-z]+$/,xm=e=>e===9||e===10||e===13||e===32,gC=e=>{if(!xm(e.charCodeAt(0))&&!xm(e.charCodeAt(e.length-1)))return e;let t=0,r=e.length;for(;t<r&&xm(e.charCodeAt(t));)t++;for(;r>t&&xm(e.charCodeAt(r-1));)r--;return e.slice(t,r)},vC=/[\0\r\n]/,V_=globalThis.Headers,OC=(e,t=V_)=>{let r=new t;for(let i=0;i<e.length;i+=2){let n=e[i];n.startsWith(":")||r.append(n,e[i+1])}return r},H_=class{#e;#t;#n;#i;constructor(e){this.#e=e,e instanceof Ei.Http2ServerRequest&&(this.#t=e.rawHeaders.slice())}get#a(){return this.#t??=this.#e.rawHeaders.slice()}get#r(){return this.#n||(this.#n=OC(this.#a),this.#t=void 0),this.#n}#o(e){if(typeof e=="string"){if(!tde.test(e))throw new TypeError(`Invalid header name: ${e}`);return e.toLowerCase()}}#s(e){let t=this.#e instanceof Ei.Http2ServerRequest?void 0:this.#e.headers;if(!t||ede.has(e)||e==="set-cookie"||e==="__proto__")return;if(!Object.hasOwn(t,e))return null;let r=t[e];if(typeof r=="string"){let i=gC(r);return vC.test(i)?void 0:i}}#c(e,t){let r=t==="cookie"?"; ":", ",i=null;for(let n=0;n<e.length;n+=2){let a=e[n];if(a.length===t.length&&a.toLowerCase()===t){let o=gC(e[n+1]);if(vC.test(o)){this.#i=!0;return}i=i===null?o:i+r+o}}return i}append(e,t){this.#r.append(e,t)}delete(e){this.#r.delete(e)}get(e){let t=this.#o(e);if(t&&!this.#n&&!this.#i){let r=this.#s(t);if(r!==void 0)return r;let i=this.#c(this.#a,t);if(i!==void 0)return i}return this.#r.get(e)}has(e){let t=this.#o(e);if(t&&!this.#n&&!this.#i){let r=this.#s(t);if(r!==void 0)return r!==null;let i=this.#c(this.#a,t);if(i!==void 0)return i!==null}return this.#r.has(e)}set(e,t){this.#r.set(e,t)}getSetCookie(){return this.#r.getSetCookie()}keys(){return this.#r.keys()}values(){return this.#r.values()}entries(){return this.#r.entries()}forEach(e,t){this.#r.forEach((r,i)=>{e.call(t,r,i,this)})}[Symbol.iterator](){return this.entries()}};Object.defineProperty(H_.prototype,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){return`Headers (lightweight) ${r(Object.fromEntries(this),{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(H_.prototype,V_.prototype);var PC=e=>globalThis.Headers===V_?new H_(e):OC(e.rawHeaders,globalThis.Headers),rde=/^\/[!#$&-;=?-\[\]_a-z~]*$/,nde=/\/\.\.?(?:[/?#]|$)/,ide=/^[a-z0-9._-]+(?::(?:[1-5]\d{3,4}|[6-9]\d{3}))?$/,Pm=e=>{let t=e.indexOf("\\");if(t!==-1){let r=e.indexOf("?");if(r===-1||t<r)throw new wr("Backslash in request path")}},IC=(e,t,r)=>{let i=`${e}://${t}${r}`;if(ide.test(t)){if(r.length===0)return i+"/";if(r.charCodeAt(0)!==47)throw new wr("Invalid URL");return!rde.test(r)||nde.test(r)?(Pm(r),new URL(i).href):i}else{Pm(r);let n=new URL(i);if(n.hostname.length!==t.length&&n.hostname!==(t.includes(":")?t.replace(/:\d+$/,""):t).toLowerCase())throw new wr("Invalid host header");return n.href}},ade=e=>e instanceof wr?e:new wr(e.message,{cause:e}),ode=global.Request,Hs=class extends ode{constructor(e,t){if(typeof e=="object"&&Ma in e){let r=t!==void 0&&"body"in t&&t.body!=null;if(e[ta]&&!r)throw new TypeError("Cannot construct a Request with a Request object that has already been used.");e=e[Ma]()}typeof t?.body?.getReader<"u"&&(t.duplex??="half"),super(e,t)}},jC=Symbol("wrapBodyStream"),sde=new Set(["latin1","binary","hex","base64","base64url"]),cde=e=>e===null||sde.has(e),M_=Symbol("bodyBufferedBeforeDisconnect"),z_=Symbol("bodyBufferedLengthBeforeDisconnect"),EC=(e,t)=>Buffer.isBuffer(e)?e:Buffer.from(e,t??"utf8"),J_=e=>!(e instanceof Ei.Http2ServerRequest)&&!!e.complete&&!!e.readableAborted&&typeof e.read=="function"&&cde(e.readableEncoding),yC=e=>{if(e.readableDidRead||!J_(e))return;let t=e;t[z_]??=e.readableLength},Im=(e,t)=>{if(e.readableDidRead&&!t||!J_(e))return;let r=e;if(r[M_]!==void 0)return r[M_];let i,n=e.errored;if(n&&n.code!=="ECONNRESET")i=n;else if(r[z_]!==void 0&&e.readableLength!==r[z_])i=jm();else{let a=t??[],o=e.read();o!==null&&a.push(EC(o,e.readableEncoding));let s=a.length===1?a[0]:Buffer.concat(a);i=s;let c=e.headers["content-length"];if(typeof c=="string"&&/^\d+$/.test(c)){let u=Number(c);Number.isSafeInteger(u)&&s.length!==u&&(i=jm())}}return r[M_]=i,i},bC=(e,t)=>{if(t instanceof Error){e.error(t);return}t.length>0&&e.enqueue(t),e.close()},ude=(e,t,r,i,n)=>{let a={method:e,headers:r,signal:n.signal};if(e==="TRACE"){a.method="GET";let o=new Hs(t,a);return Object.defineProperty(o,"method",{get(){return"TRACE"}}),o}if(!(e==="GET"||e==="HEAD"))if("rawBody"in i&&i.rawBody instanceof Buffer)a.body=new ReadableStream({start(o){o.enqueue(i.rawBody),o.close()}});else if(i[jC]){let o;a.body=new ReadableStream({async pull(s){try{if(!o){let l=Im(i);if(l!==void 0){bC(s,l);return}}o||=hC.Readable.toWeb(i).getReader();let{done:c,value:u}=await o.read();c?s.close():s.enqueue(u)}catch(c){s.error(c)}}})}else{let o=Im(i);o!==void 0?a.body=new ReadableStream({start(s){bC(s,o)}}):a.body=hC.Readable.toWeb(i)}return new Hs(t,a)},Ma=Symbol("getRequestCache"),Qi=Symbol("requestCache"),Js=Symbol("incomingKey"),Au=Symbol("urlKey"),TC=Symbol("methodKey"),kC=Symbol("headersKey"),ku=Symbol("abortControllerKey"),Z_=Symbol("getAbortController"),q_=Symbol("abortRequest"),Ra=Symbol("bodyBuffer"),Om=Symbol("bodyReadPromise"),ta=Symbol("bodyConsumedDirectly"),_C=Symbol("bodyLockReader"),Cu=Symbol("abortReason"),jm=()=>new TypeError("Body is unusable"),Du=()=>Promise.reject(jm()),lde=new TextDecoder,dde=e=>{if(e[ta])return Du();e[ta]=!0},fde=e=>e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength),pde=e=>(e[kC]||=PC(e[Js])).get("content-type")||"",mde=/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/,hde=e=>{if(typeof e!="string"||e.length===0)return"GET";switch(e){case"DELETE":case"GET":case"HEAD":case"OPTIONS":case"PATCH":case"POST":case"PUT":case"QUERY":return e}let t=e.toUpperCase();switch(t){case"DELETE":case"GET":case"HEAD":case"OPTIONS":case"POST":case"PUT":return t;default:return e}},gde=e=>{if(!mde.test(e))return new TypeError(`'${e}' is not a valid HTTP method.`);let t=e.toUpperCase();if(t==="CONNECT"||t==="TRACK"||t==="TRACE"&&e!=="TRACE")return new TypeError(`'${e}' HTTP method is unsupported.`)},G_=(e,t,r)=>{if(e[ta])return Du();let i=e.method;if(i==="GET"||i==="HEAD")return e[Ma]()[t]();let n=gde(i);if(n)return Promise.reject(n);if(e[Qi]&&i!=="TRACE")return e[Qi][t]();let a=dde(e);if(a)return a;let o=vde(e);if(o){let s=Promise.resolve(r(o,e));return e[Ra]=void 0,s}return yde(e).then(s=>{let c=r(s,e);return e[Ra]=void 0,c})},vde=e=>{let t=e[Js];if("rawBody"in t&&t.rawBody instanceof Buffer)return t.rawBody},wC=(e,t)=>{if(t.errored)return t.errored;let r=e[Cu];return r!==void 0?r instanceof Error?r:new Error(String(r)):new Error("Client connection prematurely closed.")},yde=e=>{if(e[Ra])return Promise.resolve(e[Ra]);if(e[Om])return e[Om];let t=e[Js];if(t.readableDidRead)return Du();let r=Im(t);if(r!==void 0)return r instanceof Error?Promise.reject(r):(e[Ra]=r,Promise.resolve(r));let i=new Promise((n,a)=>{let o=[],s=!1,c=g=>{s||(s=!0,m(),g())},u=g=>{let w=t.errored??g;return!J_(t)||w&&w.code!=="ECONNRESET"?!1:(c(()=>{let $=Im(t,o);$ instanceof Error?a($):$===void 0?a(g??wC(e,t)):(e[Ra]=$,n($))}),!0)},l=g=>{o.push(EC(g,t.readableEncoding))},d=()=>{c(()=>{let g=o.length===1?o[0]:Buffer.concat(o);e[Ra]=g,n(g)})},f=g=>{u(g)||c(()=>{a(g)})},p=()=>{if(t.readableEnded){d();return}u()||c(()=>{a(wC(e,t))})},m=()=>{t.off("data",l),t.off("end",d),t.off("error",f),t.off("close",p),e[Om]=void 0};t.on("data",l),t.on("end",d),t.on("error",f),t.on("close",p),queueMicrotask(()=>{s||(t.readableEnded?d():t.errored?f(t.errored):t.destroyed&&p())})});return e[Om]=i,i},ki={get method(){return this[TC]},get url(){return this[Au]},get headers(){return this[kC]||=PC(this[Js])},[q_](e){this[Cu]===void 0&&(this[Cu]=e);let t=this[ku];t&&!t.signal.aborted&&t.abort(e)},[Z_](){return this[ku]||=new AbortController,this[Cu]!==void 0&&!this[ku].signal.aborted&&this[ku].abort(this[Cu]),this[ku]},[Ma](){let e=this[Z_]();if(this[Qi])return this[Qi];let t=this.method;if(this[ta]&&!(t==="GET"||t==="HEAD")){this[Ra]=void 0;let r={method:t==="TRACE"?"GET":t,headers:this.headers,signal:e.signal};t!=="TRACE"&&(r.body=new ReadableStream({start(n){n.close()}}),r.duplex="half");let i=new Hs(this[Au],r);return t==="TRACE"&&Object.defineProperty(i,"method",{get(){return"TRACE"}}),this[Qi]=i}return this[Qi]=ude(this.method,this[Au],this.headers,this[Js],e)},get body(){if(!this[ta])return this[Ma]().body;let e=this[Ma]();return!this[_C]&&e.body&&(this[_C]=e.body.getReader()),e.body},get bodyUsed(){return this[ta]?!0:this[Qi]?this[Qi].bodyUsed:!1}};Object.defineProperty(ki,"signal",{get(){return this[Z_]().signal}});["cache","credentials","destination","integrity","mode","redirect","referrer","referrerPolicy","keepalive"].forEach(e=>{Object.defineProperty(ki,e,{get(){return this[Ma]()[e]}})});["clone","formData"].forEach(e=>{Object.defineProperty(ki,e,{value:function(){if(this[ta]){if(e==="clone")throw jm();return Du()}return this[Ma]()[e]()}})});Object.defineProperty(ki,"text",{value:function(){return G_(this,"text",e=>lde.decode(e))}});Object.defineProperty(ki,"arrayBuffer",{value:function(){return G_(this,"arrayBuffer",e=>fde(e))}});Object.defineProperty(ki,"blob",{value:function(){return G_(this,"blob",(e,t)=>{let r=pde(t),i=r?{headers:{"content-type":r}}:void 0;return new Response(e,i).blob()})}});Object.defineProperty(ki,"json",{value:function(){return this[ta]?Du():this.text().then(JSON.parse)}});Object.defineProperty(ki,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){return`Request (lightweight) ${r({method:this.method,url:this.url,headers:this.headers,nativeRequest:this[Qi]},{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(ki,Hs.prototype);var bde=(e,t)=>{let r=Object.create(ki);r[Js]=e,r[TC]=hde(e.method);let i=e.url||"";if(i[0]!=="/"&&(i.startsWith("http://")||i.startsWith("https://"))){if(e instanceof Ei.Http2ServerRequest)throw new wr("Absolute URL for :path is not allowed in HTTP/2");try{Pm(i),r[Au]=new URL(i).href}catch(o){throw new wr("Invalid absolute URL",{cause:o})}return r}let n=(e instanceof Ei.Http2ServerRequest?e.authority:e.headers.host)||t;if(!n)throw new wr("Missing host header");let a;if(e instanceof Ei.Http2ServerRequest){if(a=e.scheme,!(a==="http"||a==="https"))throw new wr("Unsupported scheme")}else a=e.socket&&e.socket.encrypted?"https":"http";try{r[Au]=IC(a,n,i)}catch(o){throw o instanceof wr?o:new wr("Invalid URL",{cause:o})}return r},Ro="text/plain; charset=UTF-8",U_=Symbol("responseCache"),Vs=Symbol("getResponseCache"),ea=Symbol("cache"),Em=global.Response,Ti=class CC{#e;#t;[Vs](){let t=this[ea],r=t&&t[2]instanceof Headers?t[2]:void 0;return delete this[ea],this[U_]||=new Em(this.#e,r?{status:this.#t?.status,statusText:this.#t?.statusText,headers:r}:this.#t)}constructor(t,r){let i;if(this.#e=t,r instanceof Em){let n=r[U_];if(n){this.#t=n,this[Vs]();return}this.#t=r instanceof CC?r.#t:r,i=new Headers(r.headers)}else this.#t=r;(t==null||typeof t=="string"||typeof t?.getReader<"u"||t instanceof Blob||t instanceof Uint8Array)&&(this[ea]=[r?.status||200,t??null,i||r?.headers])}get headers(){let t=this[ea];return t?(t[2]instanceof Headers||(t[2]=new Headers(t[2]||(t[1]===null?void 0:{"content-type":Ro}))),t[2]):this[Vs]().headers}get status(){return this[ea]?.[0]??this[Vs]().status}get ok(){let t=this.status;return t>=200&&t<300}};["body","bodyUsed","redirected","statusText","trailers","type","url"].forEach(e=>{Object.defineProperty(Ti.prototype,e,{get(){return this[Vs]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty(Ti.prototype,e,{value:function(){return this[Vs]()[e]()}})});Object.defineProperty(Ti.prototype,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){return`Response (lightweight) ${r({status:this.status,headers:this.headers,ok:this.ok,nativeResponse:this[U_]},{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(Ti,Em);Object.setPrototypeOf(Ti.prototype,Em.prototype);var _de=/^https?:\/\/[!#-;=?-[\]_a-z~A-Z]+$/,wde=e=>e instanceof URL?e.href:_de.test(e)?e:new URL(e).href,Sde=new Set([301,302,303,307,308]);Object.defineProperty(Ti,"redirect",{value:function(t,r=302){if(!Sde.has(r))throw new RangeError("Invalid status code");return new Ti(null,{status:r,headers:{location:wde(t)}})},writable:!0,configurable:!0});Object.defineProperty(Ti,"json",{value:function(t,r){let i=JSON.stringify(t);if(i===void 0)throw new TypeError("The data is not JSON serializable");let n=r?.headers,a;return n?(a=new Headers(n),a.has("content-type")||a.set("content-type","application/json")):a={"content-type":"application/json"},new Ti(i,{status:r?.status??200,statusText:r?.statusText,headers:a})},writable:!0,configurable:!0});async function $de(e){return Promise.race([e,Promise.resolve().then(()=>Promise.resolve(void 0))])}function AC(e,t,r){let i=s=>{e.cancel(s).catch(()=>{})};return t.on("close",i),t.on("error",i),(r??e.read()).then(o,n),e.closed.finally(()=>{t.off("close",i),t.off("error",i)});function n(s){s&&t.destroy(s)}function a(){e.read().then(o,n)}function o({done:s,value:c}){try{if(s)t.end();else if(!t.write(c))t.once("drain",a);else return e.read().then(o,n)}catch(u){n(u)}}}function SC(e,t){if(e.locked)throw new TypeError("ReadableStream is locked.");return t.destroyed?void 0:AC(e.getReader(),t)}var L_=(e,t)=>{let r={};if(e instanceof Headers||(e=new Headers(e??void 0)),e.has("set-cookie")){let i=[];for(let[n,a]of e)n==="set-cookie"?i.push(a):r[n]=a;i.length>0&&(r["set-cookie"]=i)}else for(let[i,n]of e)r[i]=n;return t&&(r["content-type"]??=t),r},Tm=Symbol("outgoingEnded"),$C=Symbol("incomingDraining"),xde=500,Ode=64*1024*1024,DC=e=>{let t=e;if(e.destroyed||t[$C])return;if(t[$C]=!0,e instanceof Ei.Http2ServerRequest){try{e.stream?.close?.(Ei.constants.NGHTTP2_NO_ERROR)}catch{}return}let r=0,i=()=>{clearTimeout(a),e.off("data",o),e.off("end",i),e.off("error",i)},n=()=>{i();let s=e.socket;s&&!s.destroyed&&(typeof s.destroySoon=="function"?s.destroySoon():typeof s.destroy=="function"&&s.destroy())},a=setTimeout(n,xde);a.unref?.();let o=s=>{r+=s.length,r>Ode&&n()};e.on("data",o),e.on("end",i),e.on("error",i),e.resume()},Pde=(e,t,r,i)=>()=>{t.errored?(yC(t),e[q_](t.errored.toString())):(!r.writableFinished||t instanceof Ei.Http2ServerRequest&&t.aborted)&&(yC(t),e[q_]("Client connection prematurely closed.")),i&&!t.readableEnded&&setTimeout(()=>{t.readableEnded||setTimeout(()=>{DC(t)})})},Ide=e=>{if(!(ea in e))return!1;let t=e[ea][1];return t===null||typeof t=="string"||t instanceof Uint8Array},jde=()=>new Response(null,{status:400}),RC=e=>new Response(null,{status:e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError")?504:500}),km=(e,t)=>{let r=e instanceof Error?e:new Error("unknown error",{cause:e});r.code==="ERR_STREAM_PREMATURE_CLOSE"?console.info("The user aborted a request."):(console.error(e),t.headersSent||(t instanceof B_.ServerResponse&&(t._contentLength=null),t.writeHead(500,{"Content-Type":"text/plain"})),t.end(`Error: ${r.message}`),t.destroy(r))},F_=e=>{"flushHeaders"in e&&e.writable&&e.flushHeaders()},MC=(e,t,r)=>{let i=e;return i._contentLength===null&&i._hasBody&&i.useChunkedEncodingByDefault&&!i._removedContLen&&t>=200&&t!==204&&t!==304&&!e.hasHeader("content-length")&&!e.hasHeader("transfer-encoding")&&!e.hasHeader("trailer")?(i._contentLength=r,!0):!1},N_=(e,t,r)=>{MC(e,t,r)?e.writeHead(t,{"Content-Type":Ro}):e.writeHead(t,{"Content-Type":Ro,"Content-Length":r})},NC=async(e,t)=>{let[r,i,n]=e[ea];if(!n){i===null?(t.writeHead(r),t.end()):typeof i=="string"?(N_(t,r,Buffer.byteLength(i)),t.end(i)):i instanceof Uint8Array?(N_(t,r,i.byteLength),t.end(i)):i instanceof Blob?(N_(t,r,i.size),t.end(new Uint8Array(await i.arrayBuffer()))):(t.writeHead(r,{"Content-Type":Ro}),F_(t),await SC(i,t)?.catch(c=>km(c,t))),t[Tm]?.();return}let a=!1,o=!1,s=!0;if(n instanceof Headers)a=n.has("content-length"),n=L_(n,i===null?void 0:Ro);else if(Array.isArray(n)){let c=new Headers(n);a=c.has("content-length"),n=L_(c,i===null?void 0:Ro)}else{o=!0;for(let c in n){if(c.length===14&&c.toLowerCase()==="content-length"){a=!0;break}(c.length===17&&c.toLowerCase()==="transfer-encoding"||c.length===7&&c.toLowerCase()==="trailer")&&(s=!1)}}if(!a){let c;typeof i=="string"?c=Buffer.byteLength(i):i instanceof Uint8Array?c=i.byteLength:i instanceof Blob&&(c=i.size),c!==void 0&&(!o||!s||!MC(t,r,c))&&(o&&(n={...n}),n["Content-Length"]=c)}t.writeHead(r,n),i==null?t.end():typeof i=="string"||i instanceof Uint8Array?t.end(i):i instanceof Blob?t.end(new Uint8Array(await i.arrayBuffer())):(F_(t),await SC(i,t)?.catch(c=>km(c,t))),t[Tm]?.()},zC=e=>typeof e.then=="function",Ede=async(e,t,r={})=>{if(zC(e))if(r.errorHandler)try{e=await e}catch(n){let a=await r.errorHandler(n);if(!a)return;e=a}else e=await e.catch(RC);if(ea in e)return NC(e,t);let i=L_(e.headers,e.body===null?void 0:Ro);if(e.body){let n=e.body.getReader(),a=[],o=!1,s;if(i["transfer-encoding"]!=="chunked"){let c=2;for(let u=0;u<c;u++){s||=n.read();let l=await $de(s).catch(d=>{console.error(d),o=!0});if(!l){if(u===1){await new Promise(d=>setTimeout(d)),c=3;continue}break}if(s=void 0,l.value&&a.push(l.value),l.done){o=!0;break}}o&&!("content-length"in i)&&(i["content-length"]=a.reduce((u,l)=>u+l.length,0))}t.writeHead(e.status,i),a.forEach(c=>{t.write(c)}),o?t.end():(a.length===0&&F_(t),await AC(n,t,s))}else i[Yle.X_ALREADY_SENT]||(t.writeHead(e.status,i),t.end());t[Tm]?.()},ZC=(e,t={})=>{let r=t.autoCleanupIncoming??!0;return t.overrideGlobalObjects!==!1&&global.Request!==Hs&&(Object.defineProperty(global,"Request",{value:Hs}),Object.defineProperty(global,"Response",{value:Ti})),async(i,n)=>{let a,o,s=!1,c=!1,u=()=>{!o||c||(c=!0,n.on("close",Pde(o,i,n,s)))};try{if(o=bde(i,t.hostname),s=r&&!(i.method==="GET"||i.method==="HEAD"),s&&(i[jC]=!0,i instanceof Ei.Http2ServerRequest&&(n[Tm]=()=>{i.readableEnded||setTimeout(()=>{i.readableEnded||setTimeout(()=>{i.destroy(),n.destroy()})})})),a=e(o,{incoming:i,outgoing:n}),!zC(a)&&Ide(a))return s&&!i.readableEnded&&n.once("finish",()=>{i.readableEnded||DC(i)}),NC(a,n);u()}catch(l){if(a)return km(l,n);if(t.errorHandler){if(u(),a=await t.errorHandler(o?l:ade(l)),!a)return}else o?a=RC(l):a=jde()}try{return await Ede(a,n,t)}catch(l){return km(l,n)}}},Tde=globalThis.CloseEvent??class extends Event{#e;constructor(e,t={}){super(e,t),this.#e=t}get wasClean(){return this.#e.wasClean??!1}get code(){return this.#e.code??0}get reason(){return this.#e.reason??""}},kde=globalThis.ErrorEvent??class extends Event{#e;constructor(e,t={}){super(e,t),this.#e=t}get message(){return this.#e.message??""}get filename(){return this.#e.filename??""}get lineno(){return this.#e.lineno??0}get colno(){return this.#e.colno??0}get error(){return this.#e.error??null}},Cde=()=>Symbol("connection"),qC=Symbol("CONNECTION_SYMBOL_KEY"),UC=Symbol("WAIT_FOR_WEBSOCKET_SYMBOL"),Ade=new Set(["connection","content-length","keep-alive","proxy-authenticate","proxy-authorization","te","trailer","transfer-encoding","upgrade","sec-websocket-accept","sec-websocket-extensions","sec-websocket-protocol"]),LC=(e,t)=>{t&&t.forEach((r,i)=>{Ade.has(i.toLowerCase())||e.push(`${i}: ${r}`)})},xC=(e,t,r)=>{if(e.destroyed)return;let i=["Connection: close","Content-Length: 0"];LC(i,r),e.end(`HTTP/1.1 ${t.toString()} ${B_.STATUS_CODES[t]??""}\r
|
|
169
|
+
ON-DEMAND DEPENDENCY: this tool requires Playwright AND the Chromium browser binary, which are NOT installed by default (Chromium is a ~150MB download). The tool checks for them first and, when either is missing, returns cost_available:false with reason and the exact install_commands instead of failing. Do NOT install them silently \u2014 surface the commands and ask the user to confirm before running them, then retry.`+$m});var dC=_((qxe,Jle)=>{Jle.exports={name:"sample-aws-pricing-calculator-mcp",version:"1.3.7",bin:"dist/mcp-server.js",files:["dist/mcp-server.js","catalog/schema.json","catalog/services/*.json"],description:"MCP server for creating, reading, updating AWS Pricing Calculator estimates through natural language.",license:"MIT-0",main:"mcp-server.js",scripts:{test:"npm run validate-catalog && SKIP_NETWORK=1 node --test test/*.test.js","test:network":"npm run validate-catalog && node --test test/*.test.js","test:roundtrip":"node --test test/catalog-roundtrip.test.js",mcp:"node mcp-server.js","validate-catalog":"node scripts/validate-catalog.js","validate-catalog:cost":"node scripts/validate-verified-catalog.js",build:"esbuild mcp-server.js --bundle --platform=node --outfile=dist/mcp-server.js --format=cjs --minify --external:@aws-sdk/client-dynamodb --external:@aws-sdk/lib-dynamodb --external:playwright --external:playwright-core && node scripts/emit-bundle-contract.js && rm -f dist/aws-calculator.zip && zip dist/aws-calculator.zip mcp-server.js lib/aws/aws-client.js lib/aws/fetch-resilience.js lib/aws/estimate-builder.js lib/aws/ec2.js lib/dom-cost.js package.json"},dependencies:{"@modelcontextprotocol/sdk":"1.32.1",express:"5.2.1"},peerDependencies:{"@aws-sdk/client-dynamodb":">=3.700.0","@aws-sdk/lib-dynamodb":">=3.700.0"},peerDependenciesMeta:{"@aws-sdk/client-dynamodb":{optional:!0},"@aws-sdk/lib-dynamodb":{optional:!0}},devDependencies:{"@aws-sdk/client-dynamodb":"3.1046.0","@aws-sdk/lib-dynamodb":"3.1046.0",ajv:"8.20.0","ajv-formats":"3.0.1",esbuild:"0.28.2",playwright:"1.63.0"}}});var pC=_(fC=>{var Gle="x-hono-already-sent";Object.defineProperty(fC,"X_ALREADY_SENT",{enumerable:!0,get:function(){return Gle}})});var mC=_(Tu=>{Object.defineProperty(Tu,Symbol.toStringTag,{value:"Module"});var Kle=class{#e;constructor(e){this.#e=e,this.raw=e.raw,this.url=e.url?new URL(e.url):null,this.protocol=e.protocol??null}send(e,t){this.#e.send(e,t??{})}raw;binaryType="arraybuffer";get readyState(){return this.#e.readyState}url;protocol;close(e,t){this.#e.close(e,t)}},Wle=e=>new MessageEvent("message",{data:e}),Xle=e=>((...t)=>{if(typeof t[0]=="function"){let[r,i]=t;return async function(a,o){let s=await e(a,await r(a),i);if(s)return s;await o()}}else{let[r,i,n]=t;return(async()=>{let a=await e(r,i,n);if(!a)throw new Error("Failed to upgrade WebSocket");return a})()}});Tu.WSContext=Kle;Tu.createWSMessageEvent=Wle;Tu.defineWebSocketHelper=Xle});var BC=_(Mo=>{Object.defineProperty(Mo,Symbol.toStringTag,{value:"Module"});var Yle=pC(),B_=require("node:http"),Ei=require("node:http2"),hC=require("node:stream"),Qle=mC(),wr=class extends Error{constructor(e,t){super(e,t),this.name="RequestError"}},ede=new Set(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","server","user-agent"]),tde=/^[!#$%&'*+\-.^_`|~\dA-Za-z]+$/,xm=e=>e===9||e===10||e===13||e===32,gC=e=>{if(!xm(e.charCodeAt(0))&&!xm(e.charCodeAt(e.length-1)))return e;let t=0,r=e.length;for(;t<r&&xm(e.charCodeAt(t));)t++;for(;r>t&&xm(e.charCodeAt(r-1));)r--;return e.slice(t,r)},vC=/[\0\r\n]/,V_=globalThis.Headers,OC=(e,t=V_)=>{let r=new t;for(let i=0;i<e.length;i+=2){let n=e[i];n.startsWith(":")||r.append(n,e[i+1])}return r},H_=class{#e;#t;#n;#i;constructor(e){this.#e=e,e instanceof Ei.Http2ServerRequest&&(this.#t=e.rawHeaders.slice())}get#a(){return this.#t??=this.#e.rawHeaders.slice()}get#r(){return this.#n||(this.#n=OC(this.#a),this.#t=void 0),this.#n}#o(e){if(typeof e=="string"){if(!tde.test(e))throw new TypeError(`Invalid header name: ${e}`);return e.toLowerCase()}}#s(e){let t=this.#e instanceof Ei.Http2ServerRequest?void 0:this.#e.headers;if(!t||ede.has(e)||e==="set-cookie"||e==="__proto__")return;if(!Object.hasOwn(t,e))return null;let r=t[e];if(typeof r=="string"){let i=gC(r);return vC.test(i)?void 0:i}}#c(e,t){let r=t==="cookie"?"; ":", ",i=null;for(let n=0;n<e.length;n+=2){let a=e[n];if(a.length===t.length&&a.toLowerCase()===t){let o=gC(e[n+1]);if(vC.test(o)){this.#i=!0;return}i=i===null?o:i+r+o}}return i}append(e,t){this.#r.append(e,t)}delete(e){this.#r.delete(e)}get(e){let t=this.#o(e);if(t&&!this.#n&&!this.#i){let r=this.#s(t);if(r!==void 0)return r;let i=this.#c(this.#a,t);if(i!==void 0)return i}return this.#r.get(e)}has(e){let t=this.#o(e);if(t&&!this.#n&&!this.#i){let r=this.#s(t);if(r!==void 0)return r!==null;let i=this.#c(this.#a,t);if(i!==void 0)return i!==null}return this.#r.has(e)}set(e,t){this.#r.set(e,t)}getSetCookie(){return this.#r.getSetCookie()}keys(){return this.#r.keys()}values(){return this.#r.values()}entries(){return this.#r.entries()}forEach(e,t){this.#r.forEach((r,i)=>{e.call(t,r,i,this)})}[Symbol.iterator](){return this.entries()}};Object.defineProperty(H_.prototype,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){return`Headers (lightweight) ${r(Object.fromEntries(this),{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(H_.prototype,V_.prototype);var PC=e=>globalThis.Headers===V_?new H_(e):OC(e.rawHeaders,globalThis.Headers),rde=/^\/[!#$&-;=?-\[\]_a-z~]*$/,nde=/\/\.\.?(?:[/?#]|$)/,ide=/^[a-z0-9._-]+(?::(?:[1-5]\d{3,4}|[6-9]\d{3}))?$/,Pm=e=>{let t=e.indexOf("\\");if(t!==-1){let r=e.indexOf("?");if(r===-1||t<r)throw new wr("Backslash in request path")}},IC=(e,t,r)=>{let i=`${e}://${t}${r}`;if(ide.test(t)){if(r.length===0)return i+"/";if(r.charCodeAt(0)!==47)throw new wr("Invalid URL");return!rde.test(r)||nde.test(r)?(Pm(r),new URL(i).href):i}else{Pm(r);let n=new URL(i);if(n.hostname.length!==t.length&&n.hostname!==(t.includes(":")?t.replace(/:\d+$/,""):t).toLowerCase())throw new wr("Invalid host header");return n.href}},ade=e=>e instanceof wr?e:new wr(e.message,{cause:e}),ode=global.Request,Hs=class extends ode{constructor(e,t){if(typeof e=="object"&&Ma in e){let r=t!==void 0&&"body"in t&&t.body!=null;if(e[ta]&&!r)throw new TypeError("Cannot construct a Request with a Request object that has already been used.");e=e[Ma]()}typeof t?.body?.getReader<"u"&&(t.duplex??="half"),super(e,t)}},jC=Symbol("wrapBodyStream"),sde=new Set(["latin1","binary","hex","base64","base64url"]),cde=e=>e===null||sde.has(e),M_=Symbol("bodyBufferedBeforeDisconnect"),z_=Symbol("bodyBufferedLengthBeforeDisconnect"),EC=(e,t)=>Buffer.isBuffer(e)?e:Buffer.from(e,t??"utf8"),J_=e=>!(e instanceof Ei.Http2ServerRequest)&&!!e.complete&&!!e.readableAborted&&typeof e.read=="function"&&cde(e.readableEncoding),yC=e=>{if(e.readableDidRead||!J_(e))return;let t=e;t[z_]??=e.readableLength},Im=(e,t)=>{if(e.readableDidRead&&!t||!J_(e))return;let r=e;if(r[M_]!==void 0)return r[M_];let i,n=e.errored;if(n&&n.code!=="ECONNRESET")i=n;else if(r[z_]!==void 0&&e.readableLength!==r[z_])i=jm();else{let a=t??[],o=e.read();o!==null&&a.push(EC(o,e.readableEncoding));let s=a.length===1?a[0]:Buffer.concat(a);i=s;let c=e.headers["content-length"];if(typeof c=="string"&&/^\d+$/.test(c)){let u=Number(c);Number.isSafeInteger(u)&&s.length!==u&&(i=jm())}}return r[M_]=i,i},bC=(e,t)=>{if(t instanceof Error){e.error(t);return}t.length>0&&e.enqueue(t),e.close()},ude=(e,t,r,i,n)=>{let a={method:e,headers:r,signal:n.signal};if(e==="TRACE"){a.method="GET";let o=new Hs(t,a);return Object.defineProperty(o,"method",{get(){return"TRACE"}}),o}if(!(e==="GET"||e==="HEAD"))if("rawBody"in i&&i.rawBody instanceof Buffer)a.body=new ReadableStream({start(o){o.enqueue(i.rawBody),o.close()}});else if(i[jC]){let o;a.body=new ReadableStream({async pull(s){try{if(!o){let l=Im(i);if(l!==void 0){bC(s,l);return}}o||=hC.Readable.toWeb(i).getReader();let{done:c,value:u}=await o.read();c?s.close():s.enqueue(u)}catch(c){s.error(c)}}})}else{let o=Im(i);o!==void 0?a.body=new ReadableStream({start(s){bC(s,o)}}):a.body=hC.Readable.toWeb(i)}return new Hs(t,a)},Ma=Symbol("getRequestCache"),Qi=Symbol("requestCache"),Js=Symbol("incomingKey"),Au=Symbol("urlKey"),TC=Symbol("methodKey"),kC=Symbol("headersKey"),ku=Symbol("abortControllerKey"),Z_=Symbol("getAbortController"),q_=Symbol("abortRequest"),Ra=Symbol("bodyBuffer"),Om=Symbol("bodyReadPromise"),ta=Symbol("bodyConsumedDirectly"),_C=Symbol("bodyLockReader"),Cu=Symbol("abortReason"),jm=()=>new TypeError("Body is unusable"),Du=()=>Promise.reject(jm()),lde=new TextDecoder,dde=e=>{if(e[ta])return Du();e[ta]=!0},fde=e=>e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength),pde=e=>(e[kC]||=PC(e[Js])).get("content-type")||"",mde=/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/,hde=e=>{if(typeof e!="string"||e.length===0)return"GET";switch(e){case"DELETE":case"GET":case"HEAD":case"OPTIONS":case"PATCH":case"POST":case"PUT":case"QUERY":return e}let t=e.toUpperCase();switch(t){case"DELETE":case"GET":case"HEAD":case"OPTIONS":case"POST":case"PUT":return t;default:return e}},gde=e=>{if(!mde.test(e))return new TypeError(`'${e}' is not a valid HTTP method.`);let t=e.toUpperCase();if(t==="CONNECT"||t==="TRACK"||t==="TRACE"&&e!=="TRACE")return new TypeError(`'${e}' HTTP method is unsupported.`)},G_=(e,t,r)=>{if(e[ta])return Du();let i=e.method;if(i==="GET"||i==="HEAD")return e[Ma]()[t]();let n=gde(i);if(n)return Promise.reject(n);if(e[Qi]&&i!=="TRACE")return e[Qi][t]();let a=dde(e);if(a)return a;let o=vde(e);if(o){let s=Promise.resolve(r(o,e));return e[Ra]=void 0,s}return yde(e).then(s=>{let c=r(s,e);return e[Ra]=void 0,c})},vde=e=>{let t=e[Js];if("rawBody"in t&&t.rawBody instanceof Buffer)return t.rawBody},wC=(e,t)=>{if(t.errored)return t.errored;let r=e[Cu];return r!==void 0?r instanceof Error?r:new Error(String(r)):new Error("Client connection prematurely closed.")},yde=e=>{if(e[Ra])return Promise.resolve(e[Ra]);if(e[Om])return e[Om];let t=e[Js];if(t.readableDidRead)return Du();let r=Im(t);if(r!==void 0)return r instanceof Error?Promise.reject(r):(e[Ra]=r,Promise.resolve(r));let i=new Promise((n,a)=>{let o=[],s=!1,c=g=>{s||(s=!0,m(),g())},u=g=>{let w=t.errored??g;return!J_(t)||w&&w.code!=="ECONNRESET"?!1:(c(()=>{let $=Im(t,o);$ instanceof Error?a($):$===void 0?a(g??wC(e,t)):(e[Ra]=$,n($))}),!0)},l=g=>{o.push(EC(g,t.readableEncoding))},d=()=>{c(()=>{let g=o.length===1?o[0]:Buffer.concat(o);e[Ra]=g,n(g)})},f=g=>{u(g)||c(()=>{a(g)})},p=()=>{if(t.readableEnded){d();return}u()||c(()=>{a(wC(e,t))})},m=()=>{t.off("data",l),t.off("end",d),t.off("error",f),t.off("close",p),e[Om]=void 0};t.on("data",l),t.on("end",d),t.on("error",f),t.on("close",p),queueMicrotask(()=>{s||(t.readableEnded?d():t.errored?f(t.errored):t.destroyed&&p())})});return e[Om]=i,i},ki={get method(){return this[TC]},get url(){return this[Au]},get headers(){return this[kC]||=PC(this[Js])},[q_](e){this[Cu]===void 0&&(this[Cu]=e);let t=this[ku];t&&!t.signal.aborted&&t.abort(e)},[Z_](){return this[ku]||=new AbortController,this[Cu]!==void 0&&!this[ku].signal.aborted&&this[ku].abort(this[Cu]),this[ku]},[Ma](){let e=this[Z_]();if(this[Qi])return this[Qi];let t=this.method;if(this[ta]&&!(t==="GET"||t==="HEAD")){this[Ra]=void 0;let r={method:t==="TRACE"?"GET":t,headers:this.headers,signal:e.signal};t!=="TRACE"&&(r.body=new ReadableStream({start(n){n.close()}}),r.duplex="half");let i=new Hs(this[Au],r);return t==="TRACE"&&Object.defineProperty(i,"method",{get(){return"TRACE"}}),this[Qi]=i}return this[Qi]=ude(this.method,this[Au],this.headers,this[Js],e)},get body(){if(!this[ta])return this[Ma]().body;let e=this[Ma]();return!this[_C]&&e.body&&(this[_C]=e.body.getReader()),e.body},get bodyUsed(){return this[ta]?!0:this[Qi]?this[Qi].bodyUsed:!1}};Object.defineProperty(ki,"signal",{get(){return this[Z_]().signal}});["cache","credentials","destination","integrity","mode","redirect","referrer","referrerPolicy","keepalive"].forEach(e=>{Object.defineProperty(ki,e,{get(){return this[Ma]()[e]}})});["clone","formData"].forEach(e=>{Object.defineProperty(ki,e,{value:function(){if(this[ta]){if(e==="clone")throw jm();return Du()}return this[Ma]()[e]()}})});Object.defineProperty(ki,"text",{value:function(){return G_(this,"text",e=>lde.decode(e))}});Object.defineProperty(ki,"arrayBuffer",{value:function(){return G_(this,"arrayBuffer",e=>fde(e))}});Object.defineProperty(ki,"blob",{value:function(){return G_(this,"blob",(e,t)=>{let r=pde(t),i=r?{headers:{"content-type":r}}:void 0;return new Response(e,i).blob()})}});Object.defineProperty(ki,"json",{value:function(){return this[ta]?Du():this.text().then(JSON.parse)}});Object.defineProperty(ki,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){return`Request (lightweight) ${r({method:this.method,url:this.url,headers:this.headers,nativeRequest:this[Qi]},{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(ki,Hs.prototype);var bde=(e,t)=>{let r=Object.create(ki);r[Js]=e,r[TC]=hde(e.method);let i=e.url||"";if(i[0]!=="/"&&(i.startsWith("http://")||i.startsWith("https://"))){if(e instanceof Ei.Http2ServerRequest)throw new wr("Absolute URL for :path is not allowed in HTTP/2");try{Pm(i),r[Au]=new URL(i).href}catch(o){throw new wr("Invalid absolute URL",{cause:o})}return r}let n=(e instanceof Ei.Http2ServerRequest?e.authority:e.headers.host)||t;if(!n)throw new wr("Missing host header");let a;if(e instanceof Ei.Http2ServerRequest){if(a=e.scheme,!(a==="http"||a==="https"))throw new wr("Unsupported scheme")}else a=e.socket&&e.socket.encrypted?"https":"http";try{r[Au]=IC(a,n,i)}catch(o){throw o instanceof wr?o:new wr("Invalid URL",{cause:o})}return r},Ro="text/plain; charset=UTF-8",U_=Symbol("responseCache"),Vs=Symbol("getResponseCache"),ea=Symbol("cache"),Em=global.Response,Ti=class CC{#e;#t;[Vs](){let t=this[ea],r=t&&t[2]instanceof Headers?t[2]:void 0;return delete this[ea],this[U_]||=new Em(this.#e,r?{status:this.#t?.status,statusText:this.#t?.statusText,headers:r}:this.#t)}constructor(t,r){let i;if(this.#e=t,r instanceof Em){let n=r[U_];if(n){this.#t=n,this[Vs]();return}this.#t=r instanceof CC?r.#t:r,i=new Headers(r.headers)}else this.#t=r;(t==null||typeof t=="string"||typeof t?.getReader<"u"||t instanceof Blob||t instanceof Uint8Array)&&(this[ea]=[r?.status||200,t??null,i||r?.headers])}get headers(){let t=this[ea];return t?(t[2]instanceof Headers||(t[2]=new Headers(t[2]||(t[1]===null?void 0:{"content-type":Ro}))),t[2]):this[Vs]().headers}get status(){return this[ea]?.[0]??this[Vs]().status}get ok(){let t=this.status;return t>=200&&t<300}};["body","bodyUsed","redirected","statusText","trailers","type","url"].forEach(e=>{Object.defineProperty(Ti.prototype,e,{get(){return this[Vs]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty(Ti.prototype,e,{value:function(){return this[Vs]()[e]()}})});Object.defineProperty(Ti.prototype,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){return`Response (lightweight) ${r({status:this.status,headers:this.headers,ok:this.ok,nativeResponse:this[U_]},{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(Ti,Em);Object.setPrototypeOf(Ti.prototype,Em.prototype);var _de=/^https?:\/\/[!#-;=?-[\]_a-z~A-Z]+$/,wde=e=>e instanceof URL?e.href:_de.test(e)?e:new URL(e).href,Sde=new Set([301,302,303,307,308]);Object.defineProperty(Ti,"redirect",{value:function(t,r=302){if(!Sde.has(r))throw new RangeError("Invalid status code");return new Ti(null,{status:r,headers:{location:wde(t)}})},writable:!0,configurable:!0});Object.defineProperty(Ti,"json",{value:function(t,r){let i=JSON.stringify(t);if(i===void 0)throw new TypeError("The data is not JSON serializable");let n=r?.headers,a;return n?(a=new Headers(n),a.has("content-type")||a.set("content-type","application/json")):a={"content-type":"application/json"},new Ti(i,{status:r?.status??200,statusText:r?.statusText,headers:a})},writable:!0,configurable:!0});async function $de(e){return Promise.race([e,Promise.resolve().then(()=>Promise.resolve(void 0))])}function AC(e,t,r){let i=s=>{e.cancel(s).catch(()=>{})};return t.on("close",i),t.on("error",i),(r??e.read()).then(o,n),e.closed.finally(()=>{t.off("close",i),t.off("error",i)});function n(s){s&&t.destroy(s)}function a(){e.read().then(o,n)}function o({done:s,value:c}){try{if(s)t.end();else if(!t.write(c))t.once("drain",a);else return e.read().then(o,n)}catch(u){n(u)}}}function SC(e,t){if(e.locked)throw new TypeError("ReadableStream is locked.");return t.destroyed?void 0:AC(e.getReader(),t)}var L_=(e,t)=>{let r={};if(e instanceof Headers||(e=new Headers(e??void 0)),e.has("set-cookie")){let i=[];for(let[n,a]of e)n==="set-cookie"?i.push(a):r[n]=a;i.length>0&&(r["set-cookie"]=i)}else for(let[i,n]of e)r[i]=n;return t&&(r["content-type"]??=t),r},Tm=Symbol("outgoingEnded"),$C=Symbol("incomingDraining"),xde=500,Ode=64*1024*1024,DC=e=>{let t=e;if(e.destroyed||t[$C])return;if(t[$C]=!0,e instanceof Ei.Http2ServerRequest){try{e.stream?.close?.(Ei.constants.NGHTTP2_NO_ERROR)}catch{}return}let r=0,i=()=>{clearTimeout(a),e.off("data",o),e.off("end",i),e.off("error",i)},n=()=>{i();let s=e.socket;s&&!s.destroyed&&(typeof s.destroySoon=="function"?s.destroySoon():typeof s.destroy=="function"&&s.destroy())},a=setTimeout(n,xde);a.unref?.();let o=s=>{r+=s.length,r>Ode&&n()};e.on("data",o),e.on("end",i),e.on("error",i),e.resume()},Pde=(e,t,r,i)=>()=>{t.errored?(yC(t),e[q_](t.errored.toString())):(!r.writableFinished||t instanceof Ei.Http2ServerRequest&&t.aborted)&&(yC(t),e[q_]("Client connection prematurely closed.")),i&&!t.readableEnded&&setTimeout(()=>{t.readableEnded||setTimeout(()=>{DC(t)})})},Ide=e=>{if(!(ea in e))return!1;let t=e[ea][1];return t===null||typeof t=="string"||t instanceof Uint8Array},jde=()=>new Response(null,{status:400}),RC=e=>new Response(null,{status:e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError")?504:500}),km=(e,t)=>{let r=e instanceof Error?e:new Error("unknown error",{cause:e});r.code==="ERR_STREAM_PREMATURE_CLOSE"?console.info("The user aborted a request."):(console.error(e),t.headersSent||(t instanceof B_.ServerResponse&&(t._contentLength=null),t.writeHead(500,{"Content-Type":"text/plain"})),t.end(`Error: ${r.message}`),t.destroy(r))},F_=e=>{"flushHeaders"in e&&e.writable&&e.flushHeaders()},MC=(e,t,r)=>{let i=e;return i._contentLength===null&&i._hasBody&&i.useChunkedEncodingByDefault&&!i._removedContLen&&t>=200&&t!==204&&t!==304&&!e.hasHeader("content-length")&&!e.hasHeader("transfer-encoding")&&!e.hasHeader("trailer")?(i._contentLength=r,!0):!1},N_=(e,t,r)=>{MC(e,t,r)?e.writeHead(t,{"Content-Type":Ro}):e.writeHead(t,{"Content-Type":Ro,"Content-Length":r})},NC=async(e,t)=>{let[r,i,n]=e[ea];if(!n){i===null?(t.writeHead(r),t.end()):typeof i=="string"?(N_(t,r,Buffer.byteLength(i)),t.end(i)):i instanceof Uint8Array?(N_(t,r,i.byteLength),t.end(i)):i instanceof Blob?(N_(t,r,i.size),t.end(new Uint8Array(await i.arrayBuffer()))):(t.writeHead(r,{"Content-Type":Ro}),F_(t),await SC(i,t)?.catch(c=>km(c,t))),t[Tm]?.();return}let a=!1,o=!1,s=!0;if(n instanceof Headers)a=n.has("content-length"),n=L_(n,i===null?void 0:Ro);else if(Array.isArray(n)){let c=new Headers(n);a=c.has("content-length"),n=L_(c,i===null?void 0:Ro)}else{o=!0;for(let c in n){if(c.length===14&&c.toLowerCase()==="content-length"){a=!0;break}(c.length===17&&c.toLowerCase()==="transfer-encoding"||c.length===7&&c.toLowerCase()==="trailer")&&(s=!1)}}if(!a){let c;typeof i=="string"?c=Buffer.byteLength(i):i instanceof Uint8Array?c=i.byteLength:i instanceof Blob&&(c=i.size),c!==void 0&&(!o||!s||!MC(t,r,c))&&(o&&(n={...n}),n["Content-Length"]=c)}t.writeHead(r,n),i==null?t.end():typeof i=="string"||i instanceof Uint8Array?t.end(i):i instanceof Blob?t.end(new Uint8Array(await i.arrayBuffer())):(F_(t),await SC(i,t)?.catch(c=>km(c,t))),t[Tm]?.()},zC=e=>typeof e.then=="function",Ede=async(e,t,r={})=>{if(zC(e))if(r.errorHandler)try{e=await e}catch(n){let a=await r.errorHandler(n);if(!a)return;e=a}else e=await e.catch(RC);if(ea in e)return NC(e,t);let i=L_(e.headers,e.body===null?void 0:Ro);if(e.body){let n=e.body.getReader(),a=[],o=!1,s;if(i["transfer-encoding"]!=="chunked"){let c=2;for(let u=0;u<c;u++){s||=n.read();let l=await $de(s).catch(d=>{console.error(d),o=!0});if(!l){if(u===1){await new Promise(d=>setTimeout(d)),c=3;continue}break}if(s=void 0,l.value&&a.push(l.value),l.done){o=!0;break}}o&&!("content-length"in i)&&(i["content-length"]=a.reduce((u,l)=>u+l.length,0))}t.writeHead(e.status,i),a.forEach(c=>{t.write(c)}),o?t.end():(a.length===0&&F_(t),await AC(n,t,s))}else i[Yle.X_ALREADY_SENT]||(t.writeHead(e.status,i),t.end());t[Tm]?.()},ZC=(e,t={})=>{let r=t.autoCleanupIncoming??!0;return t.overrideGlobalObjects!==!1&&global.Request!==Hs&&(Object.defineProperty(global,"Request",{value:Hs}),Object.defineProperty(global,"Response",{value:Ti})),async(i,n)=>{let a,o,s=!1,c=!1,u=()=>{!o||c||(c=!0,n.on("close",Pde(o,i,n,s)))};try{if(o=bde(i,t.hostname),s=r&&!(i.method==="GET"||i.method==="HEAD"),s&&(i[jC]=!0,i instanceof Ei.Http2ServerRequest&&(n[Tm]=()=>{i.readableEnded||setTimeout(()=>{i.readableEnded||setTimeout(()=>{i.destroy(),n.destroy()})})})),a=e(o,{incoming:i,outgoing:n}),!zC(a)&&Ide(a))return s&&!i.readableEnded&&n.once("finish",()=>{i.readableEnded||DC(i)}),NC(a,n);u()}catch(l){if(a)return km(l,n);if(t.errorHandler){if(u(),a=await t.errorHandler(o?l:ade(l)),!a)return}else o?a=RC(l):a=jde()}try{return await Ede(a,n,t)}catch(l){return km(l,n)}}},Tde=globalThis.CloseEvent??class extends Event{#e;constructor(e,t={}){super(e,t),this.#e=t}get wasClean(){return this.#e.wasClean??!1}get code(){return this.#e.code??0}get reason(){return this.#e.reason??""}},kde=globalThis.ErrorEvent??class extends Event{#e;constructor(e,t={}){super(e,t),this.#e=t}get message(){return this.#e.message??""}get filename(){return this.#e.filename??""}get lineno(){return this.#e.lineno??0}get colno(){return this.#e.colno??0}get error(){return this.#e.error??null}},Cde=()=>Symbol("connection"),qC=Symbol("CONNECTION_SYMBOL_KEY"),UC=Symbol("WAIT_FOR_WEBSOCKET_SYMBOL"),Ade=new Set(["connection","content-length","keep-alive","proxy-authenticate","proxy-authorization","te","trailer","transfer-encoding","upgrade","sec-websocket-accept","sec-websocket-extensions","sec-websocket-protocol"]),LC=(e,t)=>{t&&t.forEach((r,i)=>{Ade.has(i.toLowerCase())||e.push(`${i}: ${r}`)})},xC=(e,t,r)=>{if(e.destroyed)return;let i=["Connection: close","Content-Length: 0"];LC(i,r),e.end(`HTTP/1.1 ${t.toString()} ${B_.STATUS_CODES[t]??""}\r
|
|
170
170
|
${i.join(`\r
|
|
171
171
|
`)}\r
|
|
172
172
|
\r
|