UNPKG

apisix-sdk

Version:

Apache APISIX SDK - Complete TypeScript/JavaScript client for APISIX Admin API and Control API with APISIX 3.0+ support

4 lines 84 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const suspectProtoRx=/"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/,suspectConstructorRx=/"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/,JsonSigRx=/^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;function jsonParseTransform(o,t){if(o==="__proto__"||o==="constructor"&&t&&typeof t=="object"&&"prototype"in t){warnKeyDropped(o);return}return t}function warnKeyDropped(o){console.warn(`[destr] Dropping "${o}" key to prevent prototype pollution.`)}function destr(o,t={}){if(typeof o!="string")return o;const e=o.trim();if(o[0]==='"'&&o.endsWith('"')&&!o.includes("\\"))return e.slice(1,-1);if(e.length<=9){const i=e.toLowerCase();if(i==="true")return!0;if(i==="false")return!1;if(i==="undefined")return;if(i==="null")return null;if(i==="nan")return Number.NaN;if(i==="infinity")return Number.POSITIVE_INFINITY;if(i==="-infinity")return Number.NEGATIVE_INFINITY}if(!JsonSigRx.test(o)){if(t.strict)throw new SyntaxError("[destr] Invalid JSON");return o}try{if(suspectProtoRx.test(o)||suspectConstructorRx.test(o)){if(t.strict)throw new Error("[destr] Possible prototype pollution");return JSON.parse(o,jsonParseTransform)}return JSON.parse(o)}catch(i){if(t.strict)throw i;return o}}const HASH_RE=/#/g,AMPERSAND_RE=/&/g,SLASH_RE=/\//g,EQUAL_RE=/=/g,PLUS_RE=/\+/g,ENC_CARET_RE=/%5e/gi,ENC_BACKTICK_RE=/%60/gi,ENC_PIPE_RE=/%7c/gi,ENC_SPACE_RE=/%20/gi;function encode(o){return encodeURI(""+o).replace(ENC_PIPE_RE,"|")}function encodeQueryValue(o){return encode(typeof o=="string"?o:JSON.stringify(o)).replace(PLUS_RE,"%2B").replace(ENC_SPACE_RE,"+").replace(HASH_RE,"%23").replace(AMPERSAND_RE,"%26").replace(ENC_BACKTICK_RE,"`").replace(ENC_CARET_RE,"^").replace(SLASH_RE,"%2F")}function encodeQueryKey(o){return encodeQueryValue(o).replace(EQUAL_RE,"%3D")}function decode(o=""){try{return decodeURIComponent(""+o)}catch{return""+o}}function decodeQueryKey(o){return decode(o.replace(PLUS_RE," "))}function decodeQueryValue(o){return decode(o.replace(PLUS_RE," "))}function parseQuery(o=""){const t={};o[0]==="?"&&(o=o.slice(1));for(const e of o.split("&")){const i=e.match(/([^=]+)=?(.*)/)||[];if(i.length<2)continue;const s=decodeQueryKey(i[1]);if(s==="__proto__"||s==="constructor")continue;const n=decodeQueryValue(i[2]||"");t[s]===void 0?t[s]=n:Array.isArray(t[s])?t[s].push(n):t[s]=[t[s],n]}return t}function encodeQueryItem(o,t){return(typeof t=="number"||typeof t=="boolean")&&(t=String(t)),t?Array.isArray(t)?t.map(e=>`${encodeQueryKey(o)}=${encodeQueryValue(e)}`).join("&"):`${encodeQueryKey(o)}=${encodeQueryValue(t)}`:encodeQueryKey(o)}function stringifyQuery(o){return Object.keys(o).filter(t=>o[t]!==void 0).map(t=>encodeQueryItem(t,o[t])).filter(Boolean).join("&")}const PROTOCOL_STRICT_REGEX=/^[\s\w\0+.-]{2,}:([/\\]{1,2})/,PROTOCOL_REGEX=/^[\s\w\0+.-]{2,}:([/\\]{2})?/,PROTOCOL_RELATIVE_REGEX=/^([/\\]\s*){2,}[^/\\]/,JOIN_LEADING_SLASH_RE=/^\.?\//;function hasProtocol(o,t={}){return typeof t=="boolean"&&(t={acceptRelative:t}),t.strict?PROTOCOL_STRICT_REGEX.test(o):PROTOCOL_REGEX.test(o)||(t.acceptRelative?PROTOCOL_RELATIVE_REGEX.test(o):!1)}function hasTrailingSlash(o="",t){return o.endsWith("/")}function withoutTrailingSlash(o="",t){return(hasTrailingSlash(o)?o.slice(0,-1):o)||"/"}function withTrailingSlash(o="",t){return o.endsWith("/")?o:o+"/"}function withBase(o,t){if(isEmptyURL(t)||hasProtocol(o))return o;const e=withoutTrailingSlash(t);return o.startsWith(e)?o:joinURL(e,o)}function withQuery(o,t){const e=parseURL(o),i={...parseQuery(e.search),...t};return e.search=stringifyQuery(i),stringifyParsedURL(e)}function isEmptyURL(o){return!o||o==="/"}function isNonEmptyURL(o){return o&&o!=="/"}function joinURL(o,...t){let e=o||"";for(const i of t.filter(s=>isNonEmptyURL(s)))if(e){const s=i.replace(JOIN_LEADING_SLASH_RE,"");e=withTrailingSlash(e)+s}else e=i;return e}const protocolRelative=Symbol.for("ufo:protocolRelative");function parseURL(o="",t){const e=o.match(/^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i);if(e){const[,h,p=""]=e;return{protocol:h.toLowerCase(),pathname:p,href:h+p,auth:"",host:"",search:"",hash:""}}if(!hasProtocol(o,{acceptRelative:!0}))return parsePath(o);const[,i="",s,n=""]=o.replace(/\\/g,"/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/)||[];let[,a="",r=""]=n.match(/([^#/?]*)(.*)?/)||[];i==="file:"&&(r=r.replace(/\/(?=[A-Za-z]:)/,""));const{pathname:c,search:u,hash:l}=parsePath(r);return{protocol:i.toLowerCase(),auth:s?s.slice(0,Math.max(0,s.length-1)):"",host:a,pathname:c,search:u,hash:l,[protocolRelative]:!i}}function parsePath(o=""){const[t="",e="",i=""]=(o.match(/([^#?]*)(\?[^#]*)?(#.*)?/)||[]).splice(1);return{pathname:t,search:e,hash:i}}function stringifyParsedURL(o){const t=o.pathname||"",e=o.search?(o.search.startsWith("?")?"":"?")+o.search:"",i=o.hash||"",s=o.auth?o.auth+"@":"",n=o.host||"";return(o.protocol||o[protocolRelative]?(o.protocol||"")+"//":"")+s+n+t+e+i}class FetchError extends Error{constructor(t,e){super(t,e),this.name="FetchError",e?.cause&&!this.cause&&(this.cause=e.cause)}}function createFetchError(o){const t=o.error?.message||o.error?.toString()||"",e=o.request?.method||o.options?.method||"GET",i=o.request?.url||String(o.request)||"/",s=`[${e}] ${JSON.stringify(i)}`,n=o.response?`${o.response.status} ${o.response.statusText}`:"<no response>",a=`${s}: ${n}${t?` ${t}`:""}`,r=new FetchError(a,o.error?{cause:o.error}:void 0);for(const c of["request","options","response"])Object.defineProperty(r,c,{get(){return o[c]}});for(const[c,u]of[["data","_data"],["status","status"],["statusCode","status"],["statusText","statusText"],["statusMessage","statusText"]])Object.defineProperty(r,c,{get(){return o.response&&o.response[u]}});return r}const payloadMethods=new Set(Object.freeze(["PATCH","POST","PUT","DELETE"]));function isPayloadMethod(o="GET"){return payloadMethods.has(o.toUpperCase())}function isJSONSerializable(o){if(o===void 0)return!1;const t=typeof o;return t==="string"||t==="number"||t==="boolean"||t===null?!0:t!=="object"?!1:Array.isArray(o)?!0:o.buffer?!1:o.constructor&&o.constructor.name==="Object"||typeof o.toJSON=="function"}const textTypes=new Set(["image/svg","application/xml","application/xhtml","application/html"]),JSON_RE=/^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;function detectResponseType(o=""){if(!o)return"json";const t=o.split(";").shift()||"";return JSON_RE.test(t)?"json":textTypes.has(t)||t.startsWith("text/")?"text":"blob"}function resolveFetchOptions(o,t,e,i){const s=mergeHeaders(t?.headers??o?.headers,e?.headers,i);let n;return(e?.query||e?.params||t?.params||t?.query)&&(n={...e?.params,...e?.query,...t?.params,...t?.query}),{...e,...t,query:n,params:n,headers:s}}function mergeHeaders(o,t,e){if(!t)return new e(o);const i=new e(t);if(o)for(const[s,n]of Symbol.iterator in o||Array.isArray(o)?o:new e(o))i.set(s,n);return i}async function callHooks(o,t){if(t)if(Array.isArray(t))for(const e of t)await e(o);else await t(o)}const retryStatusCodes=new Set([408,409,425,429,500,502,503,504]),nullBodyResponses=new Set([101,204,205,304]);function createFetch(o={}){const{fetch:t=globalThis.fetch,Headers:e=globalThis.Headers,AbortController:i=globalThis.AbortController}=o;async function s(r){const c=r.error&&r.error.name==="AbortError"&&!r.options.timeout||!1;if(r.options.retry!==!1&&!c){let l;typeof r.options.retry=="number"?l=r.options.retry:l=isPayloadMethod(r.options.method)?0:1;const h=r.response&&r.response.status||500;if(l>0&&(Array.isArray(r.options.retryStatusCodes)?r.options.retryStatusCodes.includes(h):retryStatusCodes.has(h))){const p=typeof r.options.retryDelay=="function"?r.options.retryDelay(r):r.options.retryDelay||0;return p>0&&await new Promise(d=>setTimeout(d,p)),n(r.request,{...r.options,retry:l-1})}}const u=createFetchError(r);throw Error.captureStackTrace&&Error.captureStackTrace(u,n),u}const n=async function(c,u={}){const l={request:c,options:resolveFetchOptions(c,u,o.defaults,e),response:void 0,error:void 0};l.options.method&&(l.options.method=l.options.method.toUpperCase()),l.options.onRequest&&await callHooks(l,l.options.onRequest),typeof l.request=="string"&&(l.options.baseURL&&(l.request=withBase(l.request,l.options.baseURL)),l.options.query&&(l.request=withQuery(l.request,l.options.query),delete l.options.query),"query"in l.options&&delete l.options.query,"params"in l.options&&delete l.options.params),l.options.body&&isPayloadMethod(l.options.method)&&(isJSONSerializable(l.options.body)?(l.options.body=typeof l.options.body=="string"?l.options.body:JSON.stringify(l.options.body),l.options.headers=new e(l.options.headers||{}),l.options.headers.has("content-type")||l.options.headers.set("content-type","application/json"),l.options.headers.has("accept")||l.options.headers.set("accept","application/json")):("pipeTo"in l.options.body&&typeof l.options.body.pipeTo=="function"||typeof l.options.body.pipe=="function")&&("duplex"in l.options||(l.options.duplex="half")));let h;if(!l.options.signal&&l.options.timeout){const d=new i;h=setTimeout(()=>{const g=new Error("[TimeoutError]: The operation was aborted due to timeout");g.name="TimeoutError",g.code=23,d.abort(g)},l.options.timeout),l.options.signal=d.signal}try{l.response=await t(l.request,l.options)}catch(d){return l.error=d,l.options.onRequestError&&await callHooks(l,l.options.onRequestError),await s(l)}finally{h&&clearTimeout(h)}if((l.response.body||l.response._bodyInit)&&!nullBodyResponses.has(l.response.status)&&l.options.method!=="HEAD"){const d=(l.options.parseResponse?"json":l.options.responseType)||detectResponseType(l.response.headers.get("content-type")||"");switch(d){case"json":{const g=await l.response.text(),f=l.options.parseResponse||destr;l.response._data=f(g);break}case"stream":{l.response._data=l.response.body||l.response._bodyInit;break}default:l.response._data=await l.response[d]()}}return l.options.onResponse&&await callHooks(l,l.options.onResponse),!l.options.ignoreResponseError&&l.response.status>=400&&l.response.status<600?(l.options.onResponseError&&await callHooks(l,l.options.onResponseError),await s(l)):l.response},a=async function(c,u){return(await n(c,u))._data};return a.raw=n,a.native=(...r)=>t(...r),a.create=(r={},c={})=>createFetch({...o,...c,defaults:{...o.defaults,...c.defaults,...r}}),a}const _globalThis=function(){if(typeof globalThis<"u")return globalThis;if(typeof self<"u")return self;if(typeof window<"u")return window;if(typeof global<"u")return global;throw new Error("unable to locate global object")}(),fetch$1=_globalThis.fetch?(...o)=>_globalThis.fetch(...o):()=>Promise.reject(new Error("[ofetch] global.fetch is not supported!")),Headers=_globalThis.Headers,AbortController$1=_globalThis.AbortController,ofetch=createFetch({fetch:fetch$1,Headers,AbortController:AbortController$1}),$fetch=ofetch;class ApisixClient{adminBaseURL;controlBaseURL;apiKey;adminTimeout;controlTimeout;adminHeaders;controlHeaders;_serverInfo;_apiVersion;connectionPool;retryAttempts=3;retryDelay=1e3;queryCache;cacheTTL=3e4;constructor(t){this.adminBaseURL=t.adminAPI.baseURL.replace(/\/$/,""),this.controlBaseURL=t.controlAPI?.baseURL?.replace(/\/$/,"")||"http://127.0.0.1:9090",this.apiKey=t.adminAPI.apiKey,this.adminTimeout=t.adminAPI.timeout||3e4,this.controlTimeout=t.controlAPI?.timeout||this.adminTimeout,this.adminHeaders=t.adminAPI.headers||{},this.controlHeaders=t.controlAPI?.headers||{},this.connectionPool={admin:new Map,control:new Map,maxSize:10,ttl:3e5},this.queryCache=new Map}async getServerInfo(){if(!this._serverInfo)try{this._serverInfo=await this.get(this.getControlEndpoint("/v1/server_info"))}catch(t){console.warn("Failed to get server info from Control API:",t);try{await this.request("/",{method:"HEAD"}),console.warn("Fallback: using HEAD request, could not get real version"),this._serverInfo={hostname:"unknown",version:"unknown",up_time:0,boot_time:0,last_report_time:0,etcd_version:"unknown"}}catch{console.warn("All version detection methods failed, assuming v3.0.0"),this._serverInfo={hostname:"unknown",version:"3.0.0",up_time:0,boot_time:0,last_report_time:0,etcd_version:"unknown"}}}return this._serverInfo}async getVersion(){if(!this._apiVersion){const t=await this.getServerInfo();this._apiVersion=t.version}return this._apiVersion}async isVersionCompatible(t){const e=await this.getVersion();return this.compareVersions(e,t)>=0}compareVersions(t,e){const i=t.split(".").map(Number),s=e.split(".").map(Number),n=Math.max(i.length,s.length);for(let a=0;a<n;a++){const r=i[a]||0,c=s[a]||0;if(r<c)return-1;if(r>c)return 1}return 0}async isVersion3OrLater(){return this.isVersionCompatible("3.0.0")}async getApiVersionConfig(){const t=await this.getVersion(),e=await this.isVersion3OrLater();return{supportsCredentials:e,supportsSecrets:e,supportsNewResponseFormat:e,supportsStreamRoutes:this.compareVersions(t,"2.10.0")>=0,supportsPagination:e}}getConnection(t,e){const i=e?this.connectionPool.control:this.connectionPool.admin,s=Date.now();for(const[n,a]of i.entries())s-a.lastUsed>this.connectionPool.ttl&&i.delete(n);if(i.size>=this.connectionPool.maxSize){const n=i.keys().next().value;i.delete(n)}return i.set(t,{url:t,lastUsed:s,keepAlive:!0}),t}getCacheKey(t,e){const i=e.method||"GET",s=e.params?JSON.stringify(e.params):"";return`${i}:${t}:${s}`}getCachedResponse(t){const e=this.queryCache.get(t);return e?Date.now()>e.expires?(this.queryCache.delete(t),null):e.data:null}cacheResponse(t,e){this.queryCache.set(t,{data:e,expires:Date.now()+this.cacheTTL})}async retryRequest(t,e=this.retryAttempts,i=this.retryDelay){let s=new Error("Unknown error");for(let n=1;n<=e;n++)try{return await t()}catch(a){if(s=a instanceof Error?a:new Error(String(a)),this.isNonRetryableError(s))throw s;if(n===e)break;const r=Math.min(i*Math.pow(2,n-1)+Math.random()*100,1e4);await new Promise(c=>setTimeout(c,r))}throw s}isNonRetryableError(t){const e=["unauthorized","forbidden","not found","invalid","validation","already exists"],i=t.message.toLowerCase();return e.some(s=>i.includes(s))}async request(t,e={}){const i=t.startsWith("http://")||t.startsWith("https://")||!t.startsWith("/apisix/admin")&&(t.startsWith("/v1/")||t.includes("server_info")||t.includes("healthcheck")||t.includes("discovery")),s=i?this.controlBaseURL:this.adminBaseURL,n=i?this.controlTimeout:this.adminTimeout,a=i?this.controlHeaders:this.adminHeaders,r=`${s}${t}`;if(e.method==="GET"||!e.method){const u=this.getCacheKey(t,e),l=this.getCachedResponse(u);if(l&&!e.skipCache)return l}this.getConnection(r,i);const c={timeout:n,headers:{"Content-Type":"application/json",Connection:"keep-alive",...a,...!i&&this.apiKey&&{"X-API-KEY":this.apiKey},...e.headers},method:e.method||"GET",body:e.body,params:e.params,signal:e.signal};try{return await this.retryRequest(async()=>{const u=await $fetch(r,c);if((e.method==="GET"||!e.method)&&!e.skipCache){const l=this.getCacheKey(t,e);this.cacheResponse(l,u)}return u})}catch(u){if(u&&typeof u=="object"&&"data"in u){const h=u.data;if(h&&typeof h=="object"&&"error_msg"in h){const p=h;throw new Error(`APISIX API Error: ${p.error_msg} [${e.method||"GET"} ${t}]`)}}const l=u instanceof Error?u.message:"Unknown error";throw new Error(`APISIX SDK Request failed: [${e.method||"GET"}] "${r}" - ${this.getErrorMessage(l,e.method||"GET",t)}`)}}getErrorMessage(t,e,i){const s=t.toLowerCase();return s.includes("econnrefused")||s.includes("connection refused")?"Connection refused. Please check if APISIX is running and accessible.":s.includes("timeout")?"Request timeout. Consider increasing timeout or checking APISIX performance.":s.includes("unauthorized")||s.includes("401")?"Authentication failed. Please check your API key and permissions.":s.includes("not found")||s.includes("404")?`Resource not found. Check if the endpoint ${i} exists.`:s.includes("validation")||s.includes("invalid")?"Invalid request data. Please check your request format and required fields.":s.includes("rate limit")||s.includes("too many requests")?"Rate limit exceeded. Please wait before making another request.":t}async get(t,e){return this.request(t,{method:"GET",params:e})}async post(t,e,i){return this.request(t,{method:"POST",body:e,signal:i?.signal})}async put(t,e){return this.request(t,{method:"PUT",body:e})}async patch(t,e){return this.request(t,{method:"PATCH",body:e})}async delete(t){return this.request(t,{method:"DELETE"})}async supportsPagination(){return(await this.getApiVersionConfig()).supportsPagination}async list(t,e){if(e&&(e.page||e.page_size)&&!await this.supportsPagination()){const{page:i,page_size:s,...n}=e;return this.get(t,n)}return this.get(t,e)}async getOne(t,e){return this.get(`${t}/${e}`)}async create(t,e,i){return i?this.put(`${t}/${i}`,e):this.post(t,e)}async update(t,e,i){return this.put(`${t}/${e}`,i)}async partialUpdate(t,e,i){return this.patch(`${t}/${e}`,i)}async remove(t,e){return this.delete(`${t}/${e}`)}async removeWithQuery(t,e,i){const s=i?`?${new URLSearchParams(Object.fromEntries(Object.entries(i).map(([n,a])=>[n,String(a)]))).toString()}`:"";return this.delete(`${t}/${e}${s}`)}async extractValue(t){const e=await this.isVersion3OrLater();let i,s;if(!e&&t.node)i=t.node.value,s=t.node.key;else if("value"in t&&"key"in t)i=t.value,s=t.key;else return{};return i?(s&&typeof i=="object"&&i!==null&&(i.id=s.split("/").pop()||s),i):{}}extractList(t){if(!t||typeof t!="object")return[];const e=t;return e.list&&Array.isArray(e.list)?e.list.map(i=>i&&typeof i=="object"&&"value"in i?i.value:i):e.node&&typeof e.node=="object"&&"nodes"in e.node&&Array.isArray(e.node.nodes)?e.node.nodes.map(i=>i&&typeof i=="object"&&"value"in i?i.value:i):Array.isArray(t)?t:e.data&&Array.isArray(e.data)?e.data:e.value?[e.value]:[]}extractPaginationInfo(t){if(!t||typeof t!="object")return{total:0,hasMore:!1};const e=t;if(typeof e.total=="number"){const i=this.extractList(e);return{total:e.total,hasMore:i.length>0&&i.length>=(Number(e.page_size)||10)}}return e.node&&typeof e.node=="object"&&"nodes"in e.node&&Array.isArray(e.node.nodes)?{total:typeof e.count=="number"?e.count:e.node.nodes.length,hasMore:!1}:{total:this.extractList(e).length,hasMore:!1}}getAdminEndpoint(t){return`/apisix/admin${t}`}getControlEndpoint(t){return t}async controlRequest(t,e={}){return this.request(t,e)}async batch(t,e,i){const s=[];let n=0,a=0;for(const r of e)try{let c;switch(r.operation){case"create":{if(!r.data)throw new Error("Data is required for create operation");const u=await this.create(t,r.data,r.id);c=await this.extractValue(u);break}case"update":{if(!r.id||!r.data)throw new Error("ID and data are required for update operation");const u=await this.update(t,r.id,r.data);c=await this.extractValue(u);break}case"delete":if(!r.id)throw new Error("ID is required for delete operation");await this.remove(t,r.id),c={success:!0};break;default:throw new Error(`Unsupported operation: ${r.operation}`)}s.push({success:!0,id:r.id,data:c}),n++}catch(c){const u=c instanceof Error?c.message:"Unknown error";if(s.push({success:!1,id:r.id,error:u}),a++,!i?.continueOnError)break}return{total:e.length,successful:n,failed:a,results:s}}async importData(t,e,i){let s;if(typeof e=="string")try{s=JSON.parse(e)}catch(a){throw console.error("Error parsing JSON:",a),new Error("Invalid JSON data provided")}else s=e;const n={total:s.length,created:0,updated:0,skipped:0,errors:[]};if(i?.dryRun){for(const a of s)try{i.validate&&await this.validateData(a)}catch(r){const c=r instanceof Error?r.message:"Validation error";n.errors.push({id:typeof a=="object"&&a!==null&&"id"in a?String(a.id):void 0,error:c})}return n}for(const a of s)try{const r=typeof a=="object"&&a!==null&&"id"in a?String(a.id):void 0,c=i?.strategy||"merge";if(r&&c!=="replace"&&await this.checkExists(t,r)){if(c==="skip_existing"){n.skipped++;continue}if(c==="merge"){await this.update(t,r,a),n.updated++;continue}}await this.create(t,a,r),n.created++}catch(r){const c=r instanceof Error?r.message:"Import error";n.errors.push({id:typeof a=="object"&&a!==null&&"id"in a?String(a.id):void 0,error:c})}return n}async exportData(t,e){const i=await this.list(t),s=this.extractList(i);let n=s;(e?.include||e?.exclude)&&(n=s.map(r=>{const c=r,u={};if(e.include)for(const l of e.include)c[l]!==void 0&&(u[l]=c[l]);else if(Object.assign(u,c),e.exclude)for(const l of e.exclude)delete u[l];return u}));const a=e?.format||"json";if(a==="json")return JSON.stringify(n,null,e?.pretty?2:0);if(a==="yaml")return this.toYaml(n);throw new Error(`Unsupported export format: ${a}`)}toYaml(t,e=0){const i=" ".repeat(e);return Array.isArray(t)?t.map(s=>`${i}- ${this.toYaml(s,e+2).trim()}`).join(` `):t!==null&&typeof t=="object"?Object.entries(t).map(([s,n])=>typeof n=="object"&&n!==null?`${i}${s}: ${this.toYaml(n,e+2)}`:`${i}${s}: ${n}`).join(` `):String(t)}async checkExists(t,e){try{return await this.getOne(t,e),!0}catch{return!1}}async validateData(t){if(!t||typeof t!="object")throw new Error("Invalid data format");return!0}clearCache(){this.queryCache.clear()}clearCacheForEndpoint(t){const e=[];for(const[i]of this.queryCache.entries())i.includes(t)&&e.push(i);e.forEach(i=>this.queryCache.delete(i))}getCacheStats(){const t=Date.now();let e=0,i=0;for(const[s,n]of this.queryCache.entries())t>n.expires&&e++,i+=s.length+JSON.stringify(n).length;return{totalEntries:this.queryCache.size,expiredEntries:e,sizeInBytes:i}}clearConnectionPool(){this.connectionPool.admin.clear(),this.connectionPool.control.clear()}getConnectionPoolStats(){return{adminConnections:this.connectionPool.admin.size,controlConnections:this.connectionPool.control.size,totalConnections:this.connectionPool.admin.size+this.connectionPool.control.size,maxPoolSize:this.connectionPool.maxSize,ttl:this.connectionPool.ttl}}configureRetry(t){t.maxAttempts&&(this.retryAttempts=Math.max(1,t.maxAttempts)),t.baseDelay&&(this.retryDelay=Math.max(100,t.baseDelay))}configureCache(t){if(t.ttl&&(this.cacheTTL=Math.max(1e3,t.ttl)),t.maxSize&&this.queryCache.size>t.maxSize){const e=Array.from(this.queryCache.entries());e.sort((i,s)=>i[1].expires-s[1].expires),e.slice(0,this.queryCache.size-t.maxSize).forEach(([i])=>this.queryCache.delete(i))}}createAbortController(){return new AbortController}}class ConsumerGroups{endpoint="/consumer_groups";client;constructor(t){this.client=t}async list(t){const e=await this.client.list(this.client.getAdminEndpoint(this.endpoint),t);return this.client.extractList(e)}async get(t){const e=await this.client.getOne(this.client.getAdminEndpoint(this.endpoint),t);return this.client.extractValue(e)}async create(t,e){const i=await this.client.create(this.client.getAdminEndpoint(this.endpoint),t,e);return this.client.extractValue(i)}async update(t,e){const i=await this.client.update(this.client.getAdminEndpoint(this.endpoint),t,e);return this.client.extractValue(i)}async patch(t,e){const i=await this.client.partialUpdate(this.client.getAdminEndpoint(this.endpoint),t,e);return this.client.extractValue(i)}async delete(t,e){return e?.force?await this.client.removeWithQuery(this.client.getAdminEndpoint(this.endpoint),t,{force:"true"}):await this.client.remove(this.client.getAdminEndpoint(this.endpoint),t),!0}async exists(t){try{return await this.get(t),!0}catch{return!1}}async listPaginated(t=1,e=10,i){if(!await this.client.supportsPagination()){const r=await this.list(i),c=(t-1)*e,u=c+e;return{consumerGroups:r.slice(c,u),total:r.length,hasMore:u<r.length}}const s={page:t,page_size:e};i&&Object.assign(s,i);const n=await this.client.list(this.client.getAdminEndpoint(this.endpoint),s),a=this.client.extractPaginationInfo(n);return{consumerGroups:this.client.extractList(n),total:a.total,hasMore:a.hasMore}}async findByLabel(t,e){return(await this.list()).filter(i=>i.labels?e?i.labels[t]===e:t in i.labels:!1)}async findByPlugin(t){return(await this.list()).filter(e=>e.plugins&&t in e.plugins)}async addPlugin(t,e,i){const s={...(await this.get(t)).plugins,[e]:i};return this.patch(t,{plugins:s})}async removePlugin(t,e){const i=await this.get(t);if(i.plugins&&e in i.plugins){const s={...i.plugins};return delete s[e],this.patch(t,{plugins:s})}return i}async updatePlugin(t,e,i){const s=await this.get(t);if(s.plugins&&e in s.plugins){const n={...s.plugins,[e]:{...s.plugins[e],...i}};return this.patch(t,{plugins:n})}throw new Error(`Plugin ${e} not found in consumer group ${t}`)}async addLabel(t,e,i){const s={...(await this.get(t)).labels,[e]:i};return this.patch(t,{labels:s})}async removeLabel(t,e){const i=await this.get(t);if(i.labels&&e in i.labels){const s={...i.labels};return delete s[e],this.patch(t,{labels:s})}return i}async clone(t,e,i){const s=await this.get(t),{id:n,create_time:a,update_time:r,...c}=s,u={...c,...e};return this.create(u,i)}async getStatistics(){const t=await this.list(),e={},i={};for(const a of t){if(a.plugins)for(const r of Object.keys(a.plugins))e[r]=(e[r]||0)+1;if(a.labels)for(const r of Object.keys(a.labels))i[r]=(i[r]||0)+1}const s=Object.entries(e).map(([a,r])=>({plugin:a,count:r})).sort((a,r)=>r.count-a.count),n=Object.entries(i).map(([a,r])=>({label:a,count:r})).sort((a,r)=>r.count-a.count);return{total:t.length,pluginUsage:e,labelUsage:i,topPlugins:s,topLabels:n}}}class Consumers{endpoint="/consumers";client;constructor(t){this.client=t}async list(t){const e=await this.client.list(this.client.getAdminEndpoint(this.endpoint),t);return this.client.extractList(e)}async get(t){const e=await this.client.getOne(this.client.getAdminEndpoint(this.endpoint),t);return await this.client.extractValue(e)}async create(t){const e=await this.client.create(this.client.getAdminEndpoint(this.endpoint),t,t.username);return await this.client.extractValue(e)}async update(t,e){const i=await this.client.update(this.client.getAdminEndpoint(this.endpoint),t,e);return await this.client.extractValue(i)}async patch(t,e){const i=await this.client.partialUpdate(this.client.getAdminEndpoint(this.endpoint),t,e);return await this.client.extractValue(i)}async delete(t,e){return e?.force?await this.client.removeWithQuery(this.client.getAdminEndpoint(this.endpoint),t,{force:"true"}):await this.client.remove(this.client.getAdminEndpoint(this.endpoint),t),!0}async exists(t){try{return await this.get(t),!0}catch{return!1}}async listPaginated(t=1,e=10,i){if(!await this.client.supportsPagination()){const r=await this.list(i),c=(t-1)*e,u=c+e;return{consumers:r.slice(c,u),total:r.length,hasMore:u<r.length}}const s={page:t,page_size:e};i&&Object.assign(s,i);const n=await this.client.list(this.client.getAdminEndpoint(this.endpoint),s),a=this.client.extractPaginationInfo(n);return{consumers:this.client.extractList(n),total:a.total,hasMore:a.hasMore}}async findByLabel(t,e){return(await this.list()).filter(i=>i.labels?e?i.labels[t]===e:t in i.labels:!1)}async listCredentials(t){const e=await this.client.list(this.client.getAdminEndpoint(`${this.endpoint}/${t}/credentials`));return this.client.extractList(e)}async getCredential(t,e){const i=await this.client.getOne(this.client.getAdminEndpoint(`${this.endpoint}/${t}/credentials`),e);return await this.client.extractValue(i)}async createCredential(t,e,i){const s=await this.client.create(this.client.getAdminEndpoint(`${this.endpoint}/${t}/credentials`),i,e);return await this.client.extractValue(s)}async updateCredential(t,e,i){const s=await this.client.update(this.client.getAdminEndpoint(`${this.endpoint}/${t}/credentials`),e,i);return await this.client.extractValue(s)}async deleteCredential(t,e){return await this.client.remove(this.client.getAdminEndpoint(`${this.endpoint}/${t}/credentials`),e),!0}async addKeyAuth(t,e,i){const s=i||`key-auth-${Date.now()}`;return this.createCredential(t,s,{plugins:{"key-auth":{key:e}}})}async addBasicAuth(t,e,i,s){const n=s||`basic-auth-${Date.now()}`;return this.createCredential(t,n,{plugins:{"basic-auth":{username:e,password:i}}})}async addJwtAuth(t,e,i,s){const n=s||`jwt-auth-${Date.now()}`,a={key:e};return i&&(a.secret=i),this.createCredential(t,n,{plugins:{"jwt-auth":a}})}async addHmacAuth(t,e,i,s){const n=s||`hmac-auth-${Date.now()}`;return this.createCredential(t,n,{plugins:{"hmac-auth":{key_id:e,secret_key:i}}})}}class Control{client;constructor(t){this.client=t}async getUpstreams(){return this.client.controlRequest("/v1/upstreams")}async getUpstream(t){return this.client.controlRequest(`/v1/upstreams/${t}`)}async getSchemas(){return this.client.controlRequest("/v1/schema")}async getSchema(t){return this.client.controlRequest(`/v1/schema/${t}`)}async getPluginSchema(t){return this.client.controlRequest(`/v1/schema/plugin/${t}`)}async isHealthy(){try{const t=await this.client.controlRequest("/v1/healthcheck");return typeof t=="string"?t.trim()==="":t?.status==="ok"}catch{return!1}}async getServerInfo(){return this.client.controlRequest("/v1/server_info")}async getPlugins(){try{const t=await this.client.get(this.client.getAdminEndpoint("/plugins/list"));return Array.isArray(t)?t.map(e=>({name:e,enabled:!0})):Object.entries(t).map(([e,i])=>({name:e,enabled:i}))}catch(t){return console.warn("Failed to get plugins from Admin API:",t),[]}}async getUpstreamHealth(t){try{if(t)return[await this.client.controlRequest(`/v1/healthcheck/upstreams/${t}`)];try{const e=await this.client.controlRequest("/v1/healthcheck");return!e||typeof e=="string"&&e.trim()===""?[]:Array.isArray(e)?e:[]}catch(e){const i=e instanceof Error?e.message:"";if((e&&typeof e=="object"&&"response"in e?e.response?.status:void 0)===404||i.includes("missing src id"))return[];throw e}}catch(e){return console.warn("Upstream health check not available:",e),[]}}async hasDiscovery(t){try{return await this.client.controlRequest(`/v1/discovery/${t}/dump`),!0}catch{return!1}}async listDiscoveries(){const t=["nacos","consul","eureka"],e=[];for(const i of t)await this.hasDiscovery(i)&&e.push(i);return e}async getDiscoveryDump(t="nacos"){if(!await this.hasDiscovery(t))throw new Error(`Service discovery '${t}' is not configured or not available in this APISIX instance`);return this.client.controlRequest(`/v1/discovery/${t}/dump`)}async getDiscoveryDumpFiles(t="nacos"){if(!await this.hasDiscovery(t))throw new Error(`Service discovery '${t}' is not configured or not available in this APISIX instance`);try{return await this.client.controlRequest(`/v1/discovery/${t}/dump_files`)}catch(e){throw new Error(`Service discovery '${t}' dump files not available: ${e instanceof Error?e.message:"Unknown error"}`)}}async getDiscoveryDumpFile(t){return this.client.controlRequest(`/v1/discovery/nacos/dump_file/${t}`)}async getPluginMetadata(){return this.client.controlRequest("/v1/plugin_metadatas")}async getPluginMetadataById(t){return this.client.controlRequest(`/v1/plugin_metadata/${t}`)}async getConfig(){return this.client.controlRequest("/v1/config")}async getRoutes(){return this.client.controlRequest("/v1/routes")}async getRoute(t){return this.client.controlRequest(`/v1/routes/${t}`)}async getServices(){return this.client.controlRequest("/v1/services")}async getService(t){return this.client.controlRequest(`/v1/services/${t}`)}async getConsumers(){return this.client.controlRequest("/v1/consumers")}async getConsumer(t){return this.client.controlRequest(`/v1/consumers/${t}`)}async getSSLCertificates(){return this.client.controlRequest("/v1/ssl")}async getSSLCertificate(t){return this.client.controlRequest(`/v1/ssl/${t}`)}async getGlobalRules(){return this.client.controlRequest("/v1/global_rules")}async getGlobalRule(t){return this.client.controlRequest(`/v1/global_rules/${t}`)}async getConsumerGroups(){return this.client.controlRequest("/v1/consumer_groups")}async getConsumerGroup(t){return this.client.controlRequest(`/v1/consumer_groups/${t}`)}async triggerGC(){return this.client.controlRequest("/v1/gc",{method:"POST"})}async getSystemOverview(){const[t,e]=await Promise.all([this.getServerInfo(),this.getSchemas()]);let i=!1;try{i=await this.isHealthy()}catch{i=!1}let s=[];try{s=await this.getUpstreamHealth()}catch(a){console.warn("Upstream health check not available:",a),s=[]}const n={server:t,schemas:e,health:i,upstreamHealth:s};try{const a=await this.getDiscoveryDump();n.discoveryServices=a}catch{}return n}async getMemoryStats(){return this.client.controlRequest("/v1/memory_stats")}async getPrometheusMetrics(){try{const t=await fetch("http://127.0.0.1:9091/apisix/prometheus/metrics");if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);return await t.text()}catch(t){try{const e=await fetch("http://127.0.0.1:9080/apisix/prometheus/metrics");if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);return await e.text()}catch(e){throw new Error(`Prometheus metrics not available on both 9091 and 9080 ports. Original error: ${t instanceof Error?t.message:"Unknown error"}. Fallback error: ${e instanceof Error?e.message:"Unknown error"}`)}}}async healthCheck(){const t=await this.client.controlRequest("/v1/healthcheck");return typeof t=="string"&&t.trim()===""?{status:"ok",info:{version:"unknown",hostname:"unknown",up_time:0}}:typeof t=="object"&&t!==null?t:{status:"ok",info:{version:"unknown",hostname:"unknown",up_time:0}}}async reloadPlugins(){return this.client.controlRequest("/v1/plugins/reload")}async validateSchema(t,e,i){const s={valid:!0,errors:[],warnings:[]};try{const n=await this.getSchemas(),a=n.main[t];if(!a)return s.valid=!1,s.errors.push(`Schema not found for entity type: ${t}`),s;const r=this.performBasicValidation(e,a.properties);if(s.valid=r.valid,s.errors.push(...r.errors),s.warnings.push(...r.warnings),i?.validatePlugins&&e.plugins){const c=await this.validatePlugins(e.plugins,n.plugins);c.valid||(s.valid=!1),s.errors.push(...c.errors),s.warnings.push(...c.warnings)}if(i?.pluginName&&e[i.pluginName]){const c=n.plugins[i.pluginName];if(c?.schema){const u=this.performBasicValidation(e[i.pluginName],c.schema);u.valid||(s.valid=!1),s.errors.push(...u.errors),s.warnings.push(...u.warnings)}}}catch(n){s.valid=!1;const a=n instanceof Error?n.message:"Validation error";s.errors.push(a)}return s}async validatePlugins(t,e){const i={valid:!0,errors:[],warnings:[]};for(const[s,n]of Object.entries(t)){const a=e[s];if(!a){i.warnings.push(`Schema not found for plugin: ${s}`);continue}if(a.schema&&typeof n=="object"&&n!==null){const r=this.performBasicValidation(n,a.schema);r.valid||(i.valid=!1,i.errors.push(...r.errors.map(c=>`${s}: ${c}`))),i.warnings.push(...r.warnings.map(c=>`${s}: ${c}`))}}return i}performBasicValidation(t,e){const i={valid:!0,errors:[],warnings:[]},s=e.required;if(s)for(const a of s)(!(a in t)||t[a]===void 0||t[a]===null)&&(i.valid=!1,i.errors.push(`Required field missing: ${a}`));const n=e.properties;if(n)for(const a of Object.keys(t))a in n||i.warnings.push(`Unknown field: ${a}`);return i}async getValidationRecommendations(){const[t,e]=await Promise.all([this.getSchemas(),this.getServerInfo()]),i=Object.keys(t.plugins),s=Object.entries(t.plugins).filter(([,a])=>a.type==="deprecated").map(([a])=>a),n=[{category:"Security",setting:"enable_http2",description:"Enable HTTP/2 for better performance",recommended:!0},{category:"Performance",setting:"worker_processes",description:"Set worker processes to match CPU cores",recommended:"auto"},{category:"Monitoring",setting:"enable_prometheus",description:"Enable Prometheus metrics collection",recommended:!0}];return{schemaVersion:e.version,availablePlugins:i,deprecatedPlugins:s,recommendedSettings:n}}async getSchemaCompatibility(t){const e=(await this.getServerInfo()).version,i=t||e;return{currentVersion:e,targetVersion:i,compatible:this.compareVersions(e,i)>=0,breaking_changes:[],new_features:[],deprecated_features:[]}}compareVersions(t,e){const i=t.split(".").map(Number),s=e.split(".").map(Number),n=Math.max(i.length,s.length);for(let a=0;a<n;a++){const r=i[a]||0,c=s[a]||0;if(r<c)return-1;if(r>c)return 1}return 0}}class Credentials{client;constructor(t){this.client=t}async create(t,e,i){const s=i?`/consumers/${t}/credentials/${i}`:`/consumers/${t}/credentials`,n=await this.client.create(this.client.getAdminEndpoint(s),e,i);return this.client.extractValue(n)}async get(t,e){const i=await this.client.getOne(this.client.getAdminEndpoint(`/consumers/${t}/credentials`),e);return this.client.extractValue(i)}async list(t,e){const i=await this.client.list(this.client.getAdminEndpoint(`/consumers/${t}/credentials`),e);return this.client.extractList(i)}async update(t,e,i){const s=await this.client.update(this.client.getAdminEndpoint(`/consumers/${t}/credentials`),e,i);return this.client.extractValue(s)}async patch(t,e,i){console.warn("PATCH method not supported for credentials, using PUT instead");try{const s=await this.get(t,e);let n=s.plugins||{};i.plugins&&(n={...n,...i.plugins});const a={...s,...i,plugins:n},{id:r,create_time:c,update_time:u,...l}=a;return await this.update(t,e,l),this.get(t,e)}catch(s){throw s instanceof Error&&s.message.includes("not supported")?new Error("PATCH method is not supported for credentials"):s}}async delete(t,e){return await this.client.remove(this.client.getAdminEndpoint(`/consumers/${t}/credentials`),e),!0}async exists(t,e){try{return await this.get(t,e),!0}catch{return!1}}async listPaginated(t,e=1,i=10,s){if(!await this.client.supportsPagination()){const c=await this.list(t,s),u=(e-1)*i,l=u+i;return{credentials:c.slice(u,l),total:c.length,hasMore:l<c.length}}if(!(await this.client.getApiVersionConfig()).supportsNewResponseFormat){const c=await this.list(t);return{credentials:c,total:c.length,hasMore:!1}}const n={page:e,page_size:i,...s},a=await this.client.list(this.client.getAdminEndpoint(`/consumers/${t}/credentials`),n),r=this.client.extractPaginationInfo(a);return{credentials:this.client.extractList(a),total:r.total,hasMore:r.hasMore}}async findByPlugin(t,e){return(await this.list(t)).filter(i=>i.plugins?.[e])}async findByPattern(t,e){return(await this.list(t)).filter(i=>e.test(i.id||"")||Object.keys(i.plugins||{}).some(s=>e.test(s)))}async clone(t,e,i,s,n){const a=await this.get(t,e),{id:r,create_time:c,update_time:u,...l}=a,h={...l,...s};return this.create(i,h,n)}async getStatistics(t){if(t){const e=await this.list(t),i={};for(const s of e)if(s.plugins)for(const n of Object.keys(s.plugins))i[n]=(i[n]||0)+1;return{total:e.length,byPlugin:Object.entries(i).map(([s,n])=>({plugin:s,count:n})),byConsumer:[{consumer:t,count:e.length}]}}return{total:0,byPlugin:[],byConsumer:[]}}}class GlobalRules{endpoint="/global_rules";client;constructor(t){this.client=t}async list(t){const e=await this.client.list(this.client.getAdminEndpoint(this.endpoint),t);return this.client.extractList(e)}async get(t){const e=await this.client.getOne(this.client.getAdminEndpoint(this.endpoint),t);return this.client.extractValue(e)}async create(t,e){const i=await this.client.create(this.client.getAdminEndpoint(this.endpoint),t,e);return this.client.extractValue(i)}async update(t,e){const i=await this.client.update(this.client.getAdminEndpoint(this.endpoint),t,e);return this.client.extractValue(i)}async patch(t,e){const i=await this.client.partialUpdate(this.client.getAdminEndpoint(this.endpoint),t,e);return this.client.extractValue(i)}async delete(t,e){return e?.force?await this.client.removeWithQuery(this.client.getAdminEndpoint(this.endpoint),t,{force:"true"}):await this.client.remove(this.client.getAdminEndpoint(this.endpoint),t),!0}async exists(t){try{return await this.get(t),!0}catch{return!1}}async listPaginated(t=1,e=10,i){if(!await this.client.supportsPagination()){const r=await this.list(i),c=(t-1)*e,u=c+e;return{globalRules:r.slice(c,u),total:r.length,hasMore:u<r.length}}const s={page:t,page_size:e};i&&Object.assign(s,i);const n=await this.client.list(this.client.getAdminEndpoint(this.endpoint),s),a=this.client.extractPaginationInfo(n);return{globalRules:this.client.extractList(n),total:a.total,hasMore:a.hasMore}}async findByPlugin(t){return(await this.list()).filter(e=>e.plugins&&t in e.plugins)}async addPlugin(t,e,i){const s={...(await this.get(t)).plugins,[e]:i};return this.patch(t,{plugins:s})}async removePlugin(t,e){const i=await this.get(t);if(i.plugins&&e in i.plugins){const s={...i.plugins};return delete s[e],this.patch(t,{plugins:s})}return i}async updatePlugin(t,e,i){const s=await this.get(t);if(s.plugins&&e in s.plugins){const n={...s.plugins,[e]:{...s.plugins[e],...i}};return this.patch(t,{plugins:n})}throw new Error(`Plugin ${e} not found in global rule ${t}`)}async clone(t,e,i){const s=await this.get(t),{id:n,create_time:a,update_time:r,...c}=s,u={...c,...e};return this.create(u,i)}async getStatistics(){const t=await this.list(),e={};for(const s of t)if(s.plugins)for(const n of Object.keys(s.plugins))e[n]=(e[n]||0)+1;const i=Object.entries(e).map(([s,n])=>({plugin:s,count:n})).sort((s,n)=>n.count-s.count);return{total:t.length,pluginUsage:e,topPlugins:i}}}class PluginConfigs{client;constructor(t){this.client=t}async list(t){const e=await this.client.list(this.client.getAdminEndpoint("/plugin_configs"),t);return this.client.extractList(e)}async get(t){const e=await this.client.getOne(this.client.getAdminEndpoint("/plugin_configs"),t);return this.client.extractValue(e)}async create(t,e){const i=await this.client.create(this.client.getAdminEndpoint("/plugin_configs"),t,e);return this.client.extractValue(i)}async update(t,e){const i=await this.client.partialUpdate(this.client.getAdminEndpoint("/plugin_configs"),t,e);return this.client.extractValue(i)}async delete(t){return await this.client.remove(this.client.getAdminEndpoint("/plugin_configs"),t),!0}async addPlugin(t,e,i){const s={...(await this.get(t)).plugins,[e]:i};return this.update(t,{plugins:s})}async removePlugin(t,e){const i={...(await this.get(t)).plugins};return delete i[e],this.update(t,{plugins:i})}async updatePlugin(t,e,i){const s={...(await this.get(t)).plugins,[e]:i};return this.update(t,{plugins:s})}async togglePlugin(t,e,i){const s=await this.get(t);if(!s.plugins?.[e])throw new Error(`Plugin ${e} not found in config ${t}`);const n={...s.plugins,[e]:{...s.plugins[e],_meta:{disable:!i}}};return this.update(t,{plugins:n})}async getByLabel(t,e){return(await this.list()).filter(i=>i.labels?e?i.labels[t]===e:t in i.labels:!1)}async clone(t,e,i){const s=await this.get(t),n={plugins:s.plugins||{},desc:s.desc,labels:s.labels,...i};return this.create(n,e)}async validate(t){try{const e=t.plugins||{},i=[];for(const[s,n]of Object.entries(e))try{if(typeof n!="object"||n===null){i.push(`${s}: Invalid plugin configuration format`);continue}const a=n;(s==="limit-req"||s==="limit-count")&&typeof a.rate!="number"&&typeof a.count!="number"&&i.push(`${s}: Missing required rate or count parameter`),s==="cors"&&!a.allow_origins&&!a.origin&&i.push(`${s}: Missing allow_origins configuration`),s==="key-auth"&&!a.key&&!a.header&&i.push(`${s}: Missing key or header configuration`)}catch(a){const r=a instanceof Error?a.message:"Validation failed";i.push(`${s}: ${r}`)}return{valid:i.length===0,errors:i.length>0?i:void 0}}catch(e){return{valid:!1,errors:[e instanceof Error?e.message:"Validation failed"]}}}getTemplate(t){return{basic:{desc:"Basic plugin configuration",plugins:{"request-id":{_meta:{disable:!1}},"response-rewrite":{_meta:{disable:!1},headers:{"X-Server":"APISIX"}}}},security:{desc:"Security plugin configuration",plugins:{cors:{_meta:{disable:!1},allow_origins:"*",allow_methods:"GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS",allow_headers:"*"},"ip-restriction":{_meta:{disable:!1},whitelist:["127.0.0.1","::1"]}}},observability:{desc:"Observability plugin configuration",plugins:{prometheus:{_meta:{disable:!1}},zipkin:{_meta:{disable:!1},endpoint:"http://zipkin:9411/api/v2/spans",sample_ratio:1}}},traffic:{desc:"Traffic management plugin configuration",plugins:{"limit-req":{_meta:{disable:!1},rate:10,burst:20,key:"remote_addr"},"limit-count":{_meta:{disable:!1},count:100,time_window:60,key:"remote_addr"}}}}[t]}async batchCreate(t){const e=[];for(const{id:i,data:s}of t)try{const n=await this.create(s,i);e.push(n)}catch(n){throw console.error(`Failed to create plugin config ${i}:`,n),n}return e}async export(t){const e=await this.get(t);return JSON.stringify(e,null,2)}async import(t,e){try{const i=JSON.parse(t),{id:s,create_time:n,update_time:a,...r}=i;return this.create(r,e||s)}catch(i){throw console.error("Error parsing JSON:",i),new Error("Invalid JSON format for plugin config")}}}class Plugins{client;pluginCache=null;constructor(t){this.client=t}async list(){try{const t=await this.client.get(this.client.getAdminEndpoint("/plugins/list"));return Object.keys(t)}catch(t){return console.warn("Error fetching plugin list:",t),[]}}async getSchema(t){try{return await this.client.controlRequest(`/v1/schema/plugin/${t}`)}catch(e){throw new Error(`Failed to get schema for plugin ${t}: ${e instanceof Error?e.message:"Unknown error"}`)}}async setGlobalState(t,e){try{const i=e?this.client.getAdminEndpoint(`/plugins/${t}/enable`):this.client.getAdminEndpoint(`/plugins/${t}/disable`);return await this.client.post(i),!0}catch(i){return console.warn(`Plugin state management not available: ${i instanceof Error?i.message:"Unknown error"}`),!1}}async enable(t){return this.setGlobalState(t,!0)}async disable(t){return this.setGlobalState(t,!1)}async getMetadata(t){try{const e=await this.client.getOne(this.client.getAdminEndpoint("/plugin_metadata"),t);return await this.client.extractValue(e)}catch(e){throw new Error(`Failed to get metadata for plugin ${t}: ${e instanceof Error?e.message:"Unknown error"}`)}}async updateMetadata(t,e){try{const i=await this.client.create(this.client.getAdminEndpoint("/plugin_metadata"),e,t);return await this.client.extractValue(i)}catch(i){throw new Error(`Failed to update metadata for plugin ${t}: ${i instanceof Error?i.message:"Unknown error"}`)}}async deleteMetadata(t){try{return await this.client.remove(this.client.getAdminEndpoint("/plugin_metadata"),t),!0}catch(e){return e instanceof Error&&e.message.includes("404")?!0:(console.warn(`Plugin metadata deletion failed: ${e instanceof Error?e.message:"Unknown error"}`),!1)}}async listMetadata(){try{const t=await this.client.list(this.client.getAdminEndpoint("/plugin_metadata"));return this.client.extractList(t)}catch(t){return console.warn("Error fetching plugin metadata:",t),[]}}async isAvailable(t){try{return this.pluginCache||(this.pluginCache=await this.list()),this.pluginCache.includes(t)}catch(e){return console.warn(`Failed to check plugin availability for ${t}:`,e),!1}}async validateConfig(t,e){try{if(await this.getSchema(t),typeof e!="object"||e===null)return{valid:!1,errors:["Plugin configuration must be an object"]};const i=[];return(t==="limit-req"||t==="limit-count")&&typeof e.rate!="number"&&typeof e.count!="number"&&i.push("Missing required rate or count parameter"),t==="cors"&&!e.allow_origins&&!e.origin&&i.push("Missing allow_origins configuration"),{valid:i.length===0,errors:i.length>0?i:void 0}}catch(i){return{valid:!1,errors:[`Validation failed: ${i instanceof Error?i.message:"Unknown error"}`]}}}async getConfigTemplate(t){return{"key-auth":{header:"X-API-KEY",query:"api-key"},"basic-auth":{hide_credentials:!1},"jwt-auth":{header:"authorization",query:"token",cookie:"jwt"},cors:{allow_origins:"*",allow_methods:"GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS",allow_headers:"*",max_age:5},"limit-count":{count:10,time_window:60,key_type:"var",key:"remote_addr",rejected_code:503},"limit-req":{rate:10,burst:20,key_type:"var",key:"remote_addr",rejected_code:503}}[t]||{}}getPluginCategories(){return{authentication:["key-auth","basic-auth","jwt-auth","hmac-auth","oauth","openid-connect","authz-keycloak","authz-casbin","ldap-auth"],security:["cors","ip-restriction","ua-restriction","referer-restriction","csrf","uri-blocker","consumer-restriction"],traffic:["limit-count","limit-req","limit-conn","proxy-cache","request-validation","response-rewrite","proxy-rewrite"],observability:["prometheus","zipkin","skywalking","node-status","datadog","wolf-rbac"],logging:["http-logger","tcp-logger","kafka-logger","udp-logger","file-logger","loggly","sls-logger","syslog"],transformation:["response-rewrite","proxy-rewrite","redirect","grpc-transcode","fault-injection","mocking"],serverless:["azure-functions","aws-lambda","openwhisk"]}}async getPluginsByCategory(t){const e=this.getPluginCategories()[t]||[];try{const i=await this.list();return e.filter(s=>i.includes(s))}catch(i){return console.warn("Error filtering plugins by category:",i),e}}getPluginDocUrl(t){return`https://apisix.apache.org/docs/apisix/plugins/${t}`}async getPluginInfo(t){const e=await this.isAvailable(t);let i,s,n;if(e){try{i=await this.getSchema(t)}catch{}try{s=await this.getMetadata(t)}catch{}const a=this.getPluginCategories();for(const[r,c]of Object.entries(a))if(c.includes(t)){n=r;break}}return{name:t,available:e,schema:i,metadata:s,category:n,docUrl:this.getPluginDocUrl(t)}}clearCache(){this.pluginCache=null}async getAvailablePlugins(){return this.pluginCache||(this.pluginCache=await this.list()),[...this.pluginCache]}}class Protos{endpoint="/protos";client;constructor(t){this.client=t}async list(t){const e=await this.client.list(this.client.getAdminEndpoint(this.endpoint),t);return this.client.extractList(e)}async get(t){const e=await this.client.getOne(this.client.getAdminEndpoint(this.endpoint),t);return this.client.extractValue(e)}async create(t,e){const i=await this.client.create(this.client.getAdminEndpoint(this.endpoint),t,e);return this.client.extractValue(i)}async update(t,e){const i=await this.client.update(this.client.getAdminEndpoint(this.endpoint),t,e);return this.client.extractValue(i)}async patch(t,e){const i=await this.client.partialUpdate(this.client.getAdminEndpoint(this.endpoint),t,e);return this.client.extractValue(i)}async delete(t,e){return e?.force?await this.client.removeWithQuery(this.client.getAdminEndpoint(this.endpoint),t,{force:"true"}):await this.client.remove(this.client.getAdminEn