UNPKG

aem-mcp-server

Version:

AEM MCP server. Chat with your AEM instance for content, component, and asset operations.

2 lines (1 loc) 4.96 kB
"use strict";import{LOGGER as E}from"../utils/logger.js";export class AEMOperationError extends Error{code;details;recoverable;retryAfter;constructor(s){super(s.message),this.name="AEMOperationError",this.code=s.code,this.details=s.details,this.recoverable=s.recoverable,this.retryAfter=s.retryAfter}}export const AEM_ERROR_CODES={CONNECTION_FAILED:"CONNECTION_FAILED",TIMEOUT:"TIMEOUT",AUTHENTICATION_FAILED:"AUTHENTICATION_FAILED",UNAUTHORIZED:"UNAUTHORIZED",INVALID_PATH:"INVALID_PATH",INVALID_COMPONENT_TYPE:"INVALID_COMPONENT_TYPE",INVALID_LOCALE:"INVALID_LOCALE",INVALID_PARAMETERS:"INVALID_PARAMETERS",RESOURCE_NOT_FOUND:"RESOURCE_NOT_FOUND",COMPONENT_NOT_FOUND:"COMPONENT_NOT_FOUND",PAGE_NOT_FOUND:"PAGE_NOT_FOUND",UPDATE_FAILED:"UPDATE_FAILED",VALIDATION_FAILED:"VALIDATION_FAILED",REPLICATION_FAILED:"REPLICATION_FAILED",QUERY_FAILED:"QUERY_FAILED",INSUFFICIENT_PERMISSIONS:"INSUFFICIENT_PERMISSIONS",SYSTEM_ERROR:"SYSTEM_ERROR",RATE_LIMITED:"RATE_LIMITED"};export function createAEMError(e,s,r,t=!1,n){return new AEMOperationError({code:e,message:s,details:r,recoverable:t,retryAfter:n})}export function handleAEMHttpError(e,s){if(e.response){const r=e.response.status,t=e.response.data;switch(r){case 401:return createAEMError(AEM_ERROR_CODES.AUTHENTICATION_FAILED,"Authentication failed. Check AEM credentials.",{status:r,data:t});case 403:return createAEMError(AEM_ERROR_CODES.INSUFFICIENT_PERMISSIONS,"Insufficient permissions for this operation.",{status:r,data:t,operation:s});case 404:return createAEMError(AEM_ERROR_CODES.RESOURCE_NOT_FOUND,"Resource not found in AEM.",{status:r,data:t,operation:s});case 429:const n=e.response.headers["retry-after"];return createAEMError(AEM_ERROR_CODES.RATE_LIMITED,"Rate limit exceeded. Please try again later.",{status:r,data:t},!0,n?parseInt(n)*1e3:6e4);case 500:case 502:case 503:return createAEMError(AEM_ERROR_CODES.SYSTEM_ERROR,"AEM system error. Please try again later.",{status:r,data:t},!0,3e4);default:let a="Unknown error";if(typeof t=="string"&&t.trim().length>0)try{const o=JSON.parse(t);a=o.message||JSON.stringify(o)}catch{a=t}else t&&typeof t=="object"&&t.message?a=t.message:t&&typeof t=="object"&&(a=JSON.stringify(t));return createAEMError(AEM_ERROR_CODES.SYSTEM_ERROR,`HTTP ${r}: ${a}`,{status:r,data:t,operation:s})}}else return e.code==="ECONNREFUSED"||e.code==="ENOTFOUND"?createAEMError(AEM_ERROR_CODES.CONNECTION_FAILED,"Cannot connect to AEM instance. Check host and network.",{originalError:e.message},!0,5e3):e.code==="ETIMEDOUT"?createAEMError(AEM_ERROR_CODES.TIMEOUT,"Request to AEM timed out.",{originalError:e.message},!0,1e4):createAEMError(AEM_ERROR_CODES.SYSTEM_ERROR,`Unexpected error during ${s}: ${e.message}`,{originalError:e.message})}export async function safeExecute(e,s,r=3){let t;for(let n=1;n<=r;n++)try{return await e()}catch(a){if(t=a instanceof AEMOperationError?a:handleAEMHttpError(a,s),!t.recoverable||n===r)break;const o=t.retryAfter||Math.pow(2,n)*1e3;E.warn(`[${s}] Attempt ${n} failed, retrying in ${o}ms:`,t.message),await new Promise(i=>setTimeout(i,o))}throw t}const c={COMPONENT_NOT_FOUND:{suggestion:"Check the component resourceType spelling. Use getComponents to list all available components.",alternatives:["scanPageComponents to find components on a specific page","searchContent to search by partial name"]},PAGE_NOT_FOUND:{suggestion:"Verify the page path exists. Use listPages or enhancedPageSearch to find pages.",alternatives:["listPages to list children of a parent path","enhancedPageSearch for fulltext page search"]},RESOURCE_NOT_FOUND:{suggestion:"The path may not exist or may have a different structure. Use getNodeContent with depth:1 to explore.",alternatives:["listChildren to see what exists at the parent path"]},AUTHENTICATION_FAILED:{suggestion:"Check credentials. For Basic Auth: verify username/password. For OAuth: verify client ID/secret and IMS endpoint.",alternatives:[]},INVALID_PATH:{suggestion:"Paths must start with /content, /content/dam, /conf, or /content/experience-fragments.",alternatives:["fetchSites to discover valid site roots"]},INVALID_COMPONENT_TYPE:{suggestion:"The resourceType may be incorrect. Use getComponents to list valid component types.",alternatives:["scanPageComponents to see what components exist on a page"]},TIMEOUT:{suggestion:"AEM may be under load or restarting. Retry after a few seconds.",alternatives:[]},CONNECTION_FAILED:{suggestion:"AEM instance may not be running. Check the configured URL and port.",alternatives:[]}};export function createSuccessResponse(e,s){return{success:!0,operation:s,timestamp:new Date().toISOString(),data:e}}export function createErrorResponse(e,s){const r=c[e.code]||{};return{success:!1,operation:s,timestamp:new Date().toISOString(),error:{code:e.code,message:e.message,details:e.details,recoverable:e.recoverable,retryAfter:e.retryAfter,...r.suggestion&&{suggestion:r.suggestion},...r.alternatives?.length&&{alternatives:r.alternatives}}}}