aem-mcp-server 1.3.7 → 1.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{getAEMConfig as T,isValidContentPath as g,isValidLocale as E}from"./aem.config.js";import{AEM_ERROR_CODES as d,createAEMError as m,createSuccessResponse as p,handleAEMHttpError as y,safeExecute as l,validateComponentOperation as S}from"./aem.errors.js";import{AEMFetch as M}from"./aem.fetch.js";import{LOGGER as P}from"../utils/logger.js";export class AEMConnector{isInitialized;isAEMaaCS;config;aemConfig;fetch;constructor(e){this.isInitialized=!1,this.config=this.loadConfig(e),this.aemConfig=T({}),this.isAEMaaCS=this.isConfigAEMaaCS(),this.fetch=new M({host:this.config.aem.host,auth:this.config.aem.auth,timeout:this.aemConfig.queries.timeoutMs})}async init(){try{await this.fetch.init(),this.isInitialized=!0}catch{this.isInitialized=!1}}isConfigAEMaaCS(){return!!(this.config.aem.auth.clientId&&this.config.aem.auth.clientSecret)}loadConfig(e={}){let t;return e.id&&e.secret?t={clientId:e.id,clientSecret:e.secret}:t={username:e.user||"admin",password:e.pass||"admin"},{aem:{host:e.host||"http://localhost:4502",author:e.host||"http://localhost:4502",publish:"http://localhost:4503",auth:t,endpoints:{content:"/content",dam:"/content/dam",query:"/bin/querybuilder.json",crxde:"/crx/de",jcr:""}},mcp:{name:"NAEM MCP Server",version:"1.0.0"}}}async testConnection(){const e=await this.testAEMConnection(),t=e?await this.testAuthConnection():!1;return{aem:e,auth:t}}async testAEMConnection(){try{this.isInitialized||await this.init();const e="/libs/granite/core/content/login.html";P.log("Testing AEM connection to:",e);const t=await this.fetch.get(e,void 0,void 0,5e3,!0);return P.log("\u2705 AEM connection successful!"),!0}catch(e){return P.error("\u274C AEM connection failed:",e.message),!1}}async testAuthConnection(){try{this.isInitialized||await this.init();const e="/libs/granite/security/currentuser.json";P.log("Testing AEM authentication connection to:",e);const t=await this.fetch.get(e,void 0,void 0,5e3);return P.log("\u2705 AEM authentication connection successful!"),!0}catch(e){return P.error("\u274C AEM authentication connection failed:",e.message),!1}}async validateComponent(e){return l(async()=>{const t=e.pagePath||e.page_path,{locale:n,component:s,props:a}=e;if(S(n,t,s,a),!E(n,this.aemConfig))throw m(d.INVALID_LOCALE,`Locale '${n}' is not supported`,{locale:n,allowedLocales:this.aemConfig.validation.allowedLocales});if(!g(t,this.aemConfig))throw m(d.INVALID_PATH,`Path '${t}' is not within allowed content roots`,{path:t,allowedRoots:Object.values(this.aemConfig.contentPaths)});const r=`${t}.json`,o=await this.fetch.get(r,{params:{":depth":"2"},timeout:this.aemConfig.queries.timeoutMs}),c=this.validateComponentProps(o.data,s,a);return p({message:"Component validation completed successfully",pageData:o.data,component:s,locale:n,validation:c,configUsed:{allowedLocales:this.aemConfig.validation.allowedLocales}},"validateComponent")},"validateComponent")}validateComponentProps(e,t,n){const s=[],a=[];return t==="text"&&!n.text&&!n.richText&&s.push("Text component should have text or richText property"),t==="image"&&!n.fileReference&&!n.src&&a.push("Image component requires fileReference or src property"),{valid:a.length===0,errors:a,warnings:s,componentType:t,propsValidated:Object.keys(n).length}}async updateComponent(e){return l(async()=>{if(!e.componentPath||typeof e.componentPath!="string")throw m(d.INVALID_PARAMETERS,"Component path is required and must be a string");if(!e.properties||typeof e.properties!="object")throw m(d.INVALID_PARAMETERS,"Properties are required and must be an object");if(!g(e.componentPath,this.aemConfig))throw m(d.INVALID_PATH,`Component path '${e.componentPath}' is not within allowed content roots`,{path:e.componentPath,allowedRoots:Object.values(this.aemConfig.contentPaths)});const t=`${e.componentPath}.json`,n=await this.fetch.get(t);try{await n.json()}catch(o){throw o.response?.status===404?m(d.COMPONENT_NOT_FOUND,`Component not found at path: ${e.componentPath}`,{componentPath:e.componentPath}):y(o,"updateComponent")}const s=new URLSearchParams;Object.entries(e.properties).forEach(([o,c])=>{c==null?s.append(`${o}@Delete`,""):Array.isArray(c)?c.forEach(i=>{s.append(`${o}`,i.toString())}):typeof c=="object"?s.append(o,JSON.stringify(c)):s.append(o,c.toString())});const a=await this.fetch.post(e.componentPath,s),r=await this.fetch.get(`${e.componentPath}.json`);return p({message:"Component updated successfully",path:e.componentPath,properties:e.properties,updatedProperties:r.data,response:a.data,verification:{success:!0,propertiesChanged:Object.keys(e.properties).length,timestamp:new Date().toISOString()}},"updateComponent")},"updateComponent")}async undoChanges(e){return p({message:"undoChanges is not implemented. Please use AEM version history for undo/rollback.",request:e,timestamp:new Date().toISOString()},"undoChanges")}async scanPageComponents(e){return l(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),s=[],a=(r,o)=>{!r||typeof r!="object"||(r["sling:resourceType"]&&s.push({path:o,resourceType:r["sling:resourceType"],properties:{...r}}),Object.entries(r).forEach(([c,i])=>{if(typeof i=="object"&&i!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const h=o?`${o}/${c}`:c;a(i,h)}}))};return n.data["jcr:content"]?a(n.data["jcr:content"],"jcr:content"):a(n.data,e),p({pagePath:e,components:s,totalComponents:s.length},"scanPageComponents")},"scanPageComponents")}async fetchSites(){return l(async()=>{const t=await this.fetch.get("/content.json",{":depth":"2"}),n=[];return Object.entries(t).forEach(([s,a])=>{s.startsWith("jcr:")||s.startsWith("sling:")||a&&typeof a=="object"&&a["jcr:content"]&&n.push({name:s,path:`/content/${s}`,title:a["jcr:content"]["jcr:title"]||s,template:a["jcr:content"]["cq:template"],lastModified:a["jcr:content"]["cq:lastModified"]})}),p({sites:n,totalCount:n.length},"fetchSites")},"fetchSites")}async fetchLanguageMasters(e){return l(async()=>{const t=`/content/${e}.json`,n=await this.fetch.get(t,{":depth":"3"}),s=[];return Object.entries(n).forEach(([a,r])=>{a.startsWith("jcr:")||a.startsWith("sling:")||r&&typeof r=="object"&&r["jcr:content"]&&s.push({name:a,path:`/content/${a}`,title:r["jcr:content"]["jcr:title"]||a,language:r["jcr:content"]["jcr:language"]||"en"})}),p({site:e,languageMasters:s},"fetchLanguageMasters")},"fetchLanguageMasters")}async fetchAvailableLocales(e,t){return l(async()=>{const n=`${t}.json`,s=await this.fetch.get(n,{":depth":"2"}),a=[];return Object.entries(s).forEach(([r,o])=>{r.startsWith("jcr:")||r.startsWith("sling:")||o&&typeof o=="object"&&a.push({name:r,title:o["jcr:content"]?.["jcr:title"]||r,language:o["jcr:content"]?.["jcr:language"]||r})}),p({site:e,languageMasterPath:t,availableLocales:a},"fetchAvailableLocales")},"fetchAvailableLocales")}async replicateAndPublish(e,t,n){return l(async()=>p({message:"Replication simulated",selectedLocales:e,componentData:t,localizedOverrides:n},"replicateAndPublish"),"replicateAndPublish")}async getAllTextContent(e){return l(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),s=[],a=(r,o)=>{!r||typeof r!="object"||((r.text||r["jcr:title"]||r["jcr:description"])&&s.push({path:o,title:r["jcr:title"],text:r.text,description:r["jcr:description"]}),Object.entries(r).forEach(([c,i])=>{if(typeof i=="object"&&i!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const h=o?`${o}/${c}`:c;a(i,h)}}))};return n["jcr:content"]?a(n["jcr:content"],"jcr:content"):a(n,e),p({pagePath:e,textContent:s},"getAllTextContent")},"getAllTextContent")}async getPageTextContent(e){return l(async()=>this.getAllTextContent(e),"getPageTextContent")}async getPageImages(e){return l(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),s=[],a=(r,o)=>{!r||typeof r!="object"||((r.fileReference||r.src)&&s.push({path:o,fileReference:r.fileReference,src:r.src,alt:r.alt||r.altText,title:r["jcr:title"]||r.title}),Object.entries(r).forEach(([c,i])=>{if(typeof i=="object"&&i!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const h=o?`${o}/${c}`:c;a(i,h)}}))};return n["jcr:content"]?a(n["jcr:content"],"jcr:content"):a(n,e),p({pagePath:e,images:s},"getPageImages")},"getPageImages")}async updateImagePath(e,t){return l(async()=>this.updateComponent({componentPath:e,properties:{fileReference:t}}),"updateImagePath")}async getPageContent(e){return l(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t);return p({pagePath:e,content:n},"getPageContent")},"getPageContent")}async listChildren(e,t=1){return l(async()=>{try{const n=await this.fetch.get(`${e}.${t}.json`),s=[];return n&&typeof n=="object"&&Object.entries(n).forEach(([a,r])=>{if(!(a.startsWith("jcr:")||a.startsWith("sling:")||a.startsWith("cq:")||a.startsWith("rep:")||a.startsWith("oak:")||a==="jcr:content")&&r&&typeof r=="object"){const o=`${e}/${a}`;s.push({name:a,path:o,primaryType:r["jcr:primaryType"]||"nt:unstructured",title:r["jcr:content"]?.["jcr:title"]||r["jcr:title"]||a,lastModified:r["jcr:content"]?.["cq:lastModified"]||r["cq:lastModified"],resourceType:r["jcr:content"]?.["sling:resourceType"]||r["sling:resourceType"]})}}),s}catch(n){if(n.response?.status===404||n.response?.status===403)return((await this.fetch.get("/bin/querybuilder.json",{path:e,type:"cq:Page","p.nodedepth":"1","p.limit":"1000","p.hits":"full"})).hits||[]).map(a=>({name:a.name||a.path?.split("/").pop(),path:a.path,primaryType:a["jcr:primaryType"]||"cq:Page",title:a["jcr:content/jcr:title"]||a.title||a.name,lastModified:a["jcr:content/cq:lastModified"],resourceType:a["jcr:content/sling:resourceType"]}));throw n}},"listChildren")}async listPages(e,t=1,n=20){return l(async()=>{try{const s=await this.fetch.get(`${e}.${t}.json`),a=[],r=(o,c,i)=>{i>t||a.length>=n||Object.entries(o).forEach(([h,f])=>{if(!(a.length>=n)&&!(h.startsWith("jcr:")||h.startsWith("sling:")||h.startsWith("cq:")||h.startsWith("rep:")||h.startsWith("oak:"))&&f&&typeof f=="object"){const j=`${c}/${h}`;f["jcr:primaryType"]==="cq:Page"&&a.push({name:h,path:j,primaryType:"cq:Page",title:f["jcr:content"]?.["jcr:title"]||h,template:f["jcr:content"]?.["cq:template"],lastModified:f["jcr:content"]?.["cq:lastModified"],lastModifiedBy:f["jcr:content"]?.["cq:lastModifiedBy"],resourceType:f["jcr:content"]?.["sling:resourceType"],type:"page"}),i<t&&r(f,j,i+1)}})};return s&&typeof s=="object"&&r(s,e,0),p({siteRoot:e,pages:a,pageCount:a.length,depth:t,limit:n,totalChildrenScanned:a.length},"listPages")}catch(s){if(P.warn("JSON API failed, falling back to QueryBuilder:",s.message),s.response?.status===404||s.response?.status===403){const a=await this.fetch.get("/bin/querybuilder.json",{path:e,type:"cq:Page","p.nodedepth":t.toString(),"p.limit":n.toString(),"p.hits":"full"}),r=(a.hits||[]).map(o=>({name:o.name||o.path?.split("/").pop(),path:o.path,primaryType:"cq:Page",title:o["jcr:content/jcr:title"]||o.title||o.name,template:o["jcr:content/cq:template"],lastModified:o["jcr:content/cq:lastModified"],lastModifiedBy:o["jcr:content/cq:lastModifiedBy"],resourceType:o["jcr:content/sling:resourceType"],type:"page"}));return p({siteRoot:e,pages:r,pageCount:r.length,depth:t,limit:n,totalChildrenScanned:a.total||r.length,fallbackUsed:"QueryBuilder"},"listPages")}throw s}},"listPages")}async executeJCRQuery(e,t=20){return l(async()=>{if(!e||e.trim().length===0)throw new Error("Query is required and must be a non-empty string. Note: Only QueryBuilder fulltext is supported, not JCR SQL2.");const n=e.toLowerCase();if(/drop|delete|update|insert|exec|script|\.|<script/i.test(n)||e.length>1e3)throw new Error("Query contains potentially unsafe patterns or is too long");const s=await this.fetch.get("/bin/querybuilder.json",{path:"/content",type:"cq:Page",fulltext:e,"p.limit":t});return{query:e,results:s.hits||[],total:s.total||0,limit:t}},"executeJCRQuery")}async getPageProperties(e){return l(async()=>{const t=`${e}/jcr:content.json`,n=await this.fetch.get(t),s={title:n["jcr:title"],description:n["jcr:description"],template:n["cq:template"],lastModified:n["cq:lastModified"],lastModifiedBy:n["jcr:createdBy"],created:n["jcr:created"],createdBy:n["jcr:createdBy"],primaryType:n["jcr:primaryType"],resourceType:n["sling:resourceType"],tags:n["cq:tags"]||[],properties:n};return p({pagePath:e,properties:s},"getPageProperties")},"getPageProperties")}async searchContent(e){return l(async()=>{const t=await this.fetch.get(this.config.aem.endpoints.query,e);return p({params:e,results:t.hits||[],total:t.total||0,rawResponse:t},"searchContent")},"searchContent")}async getAssetMetadata(e){return l(async()=>{const t=`${e}.json`,n=await this.fetch.get(t),s=n["jcr:content"]?.metadata||{};return p({assetPath:e,metadata:s,fullData:n},"getAssetMetadata")},"getAssetMetadata")}async createPage(e){return this.createPageWithTemplate(e)}async deletePage(e){return l(async()=>{const{pagePath:t}=e;if(!g(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});let n=!1;try{await this.fetch.delete(t),n=!0}catch(s){if(s?.status===405||s?.response?.status===405)try{await this.fetch.post("/bin/wcmcommand",{cmd:"deletePage",path:t,force:e.force?"true":"false"}),n=!0}catch{try{await this.fetch.post(t,{":operation":"delete"}),n=!0}catch(r){throw r}}else throw console.error("DELETE failed:",s.response?.status,s.response?.data),s}return p({success:n,deletedPath:t,timestamp:new Date().toISOString()},"deletePage")},"deletePage")}async createComponent(e){return l(async()=>{const{pagePath:t,componentPath:n,componentType:s,resourceType:a,properties:r={},name:o}=e;if(!g(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});const c=o||`${s}_${Date.now()}`,i=n||`${t}/jcr:content/${c}`;return await this.fetch.post(i,{"jcr:primaryType":"nt:unstructured","sling:resourceType":a,...r,":operation":"import",":contentType":"json",":replace":"true"}),p({success:!0,componentPath:i,componentType:s,resourceType:a,properties:r,timestamp:new Date().toISOString()},"createComponent")},"createComponent")}async deleteComponent(e){return l(async()=>{const{componentPath:t}=e;if(!g(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid component path: ${String(t)}`,{componentPath:t});let n=!1;try{await this.fetch.delete(t),n=!0}catch(s){if(s?.status===405||s?.response?.status===405)try{await this.fetch.post(t,{":operation":"delete"}),n=!0}catch(a){throw a}else throw console.error("DELETE failed:",s.response?.status,s.response?.data),s}return p({success:n,deletedPath:t,timestamp:new Date().toISOString()},"deleteComponent")},"deleteComponent")}async unpublishContent(e){return l(async()=>{const{contentPaths:t,unpublishTree:n=!1}=e;if(!t||Array.isArray(t)&&t.length===0)throw m(d.INVALID_PARAMETERS,"Content paths array is required and cannot be empty",{contentPaths:t});const s=[];for(const a of Array.isArray(t)?t:[t])try{const r=new URLSearchParams;r.append("cmd","Deactivate"),r.append("path",a),r.append("ignoredeactivated","false"),r.append("onlymodified","false"),n&&r.append("deep","true");const o=await this.fetch.post("/bin/replicate.json",r);s.push({path:a,success:!0,response:o})}catch(r){s.push({path:a,success:!1,error:r.message})}return p({success:s.every(a=>a.success),results:s,unpublishedPaths:t,unpublishTree:n,timestamp:new Date().toISOString()},"unpublishContent")},"unpublishContent")}async activatePage(e){return l(async()=>{const{pagePath:t,activateTree:n=!1}=e;if(!g(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});try{const s=new URLSearchParams;s.append("cmd","Activate"),s.append("path",t),s.append("ignoredeactivated","false"),s.append("onlymodified","false"),n&&s.append("deep","true");const a=await this.fetch.post("/bin/replicate.json",s);return p({success:!0,activatedPath:t,activateTree:n,response:a,timestamp:new Date().toISOString()},"activatePage")}catch(s){try{const a=await this.fetch.post("/bin/wcmcommand",{cmd:"activate",path:t,ignoredeactivated:!1,onlymodified:!1});return p({success:!0,activatedPath:t,activateTree:n,response:a,fallbackUsed:"WCM Command",timestamp:new Date().toISOString()},"activatePage")}catch{throw y(s,"activatePage")}}},"activatePage")}async deactivatePage(e){return l(async()=>{const{pagePath:t,deactivateTree:n=!1}=e;if(!g(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});try{const s=new URLSearchParams;s.append("cmd","Deactivate"),s.append("path",t),s.append("ignoredeactivated","false"),s.append("onlymodified","false"),n&&s.append("deep","true");const a=await this.fetch.post("/bin/replicate.json",s);return p({success:!0,deactivatedPath:t,deactivateTree:n,response:a,timestamp:new Date().toISOString()},"deactivatePage")}catch(s){try{const a=await this.fetch.post("/bin/wcmcommand",{cmd:"deactivate",path:t,ignoredeactivated:!1,onlymodified:!1});return p({success:!0,deactivatedPath:t,deactivateTree:n,response:a,fallbackUsed:"WCM Command",timestamp:new Date().toISOString()},"deactivatePage")}catch{throw y(s,"deactivatePage")}}},"deactivatePage")}async uploadAsset(e){return l(async()=>{const{parentPath:t,fileName:n,fileContent:s,mimeType:a,metadata:r={}}=e;if(!g(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid parent path: ${String(t)}`,{parentPath:t});const o=`${t}/${n}`;try{const c=new URLSearchParams;typeof s=="string"?c.append("file",s):c.append("file",s.toString()),c.append("fileName",n),c.append(":operation","import"),c.append(":contentType","json"),c.append(":replace","true"),c.append("jcr:primaryType","dam:Asset"),a&&c.append("jcr:content/jcr:mimeType",a),Object.entries(r).forEach(([f,j])=>{c.append(`jcr:content/metadata/${f}`,String(j))});const i=await this.fetch.post(o,c),h=await this.fetch.get(`${o}.json`);return p({success:!0,assetPath:o,fileName:n,mimeType:a,metadata:r,uploadResponse:i,assetData:h,timestamp:new Date().toISOString()},"uploadAsset")}catch(c){try{const i=await this.fetch.post("/api/assets"+t,{fileName:n,fileContent:s,mimeType:a,metadata:r});return p({success:!0,assetPath:o,fileName:n,mimeType:a,metadata:r,uploadResponse:i,fallbackUsed:"DAM API",timestamp:new Date().toISOString()},"uploadAsset")}catch{throw y(c,"uploadAsset")}}},"uploadAsset")}async updateAsset(e){return l(async()=>{const{assetPath:t,metadata:n,fileContent:s,mimeType:a}=e;if(!g(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid asset path: ${String(t)}`,{assetPath:t});const r=new URLSearchParams;s&&(r.append("file",s),a&&r.append("jcr:content/jcr:mimeType",a)),n&&typeof n=="object"&&Object.entries(n).forEach(([o,c])=>{r.append(`jcr:content/metadata/${o}`,String(c))});try{const o=await this.fetch.post(t,r),c=await this.fetch.get(`${t}.json`);return p({success:!0,assetPath:t,updatedMetadata:n,updateResponse:o,assetData:c,timestamp:new Date().toISOString()},"updateAsset")}catch(o){throw y(o,"updateAsset")}},"updateAsset")}async deleteAsset(e){return l(async()=>{const{assetPath:t,force:n=!1}=e;if(!g(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid asset path: ${String(t)}`,{assetPath:t});return await this.fetch.delete(t),p({success:!0,deletedPath:t,force:n,timestamp:new Date().toISOString()},"deleteAsset")},"deleteAsset")}async getTemplates(e){return l(async()=>{if(e)try{const t=`/conf${e.replace("/content","")}/settings/wcm/templates`,n=await this.fetch.get(`${t}.json`,{":depth":"2"}),s=[];return n&&typeof n=="object"&&Object.entries(n).forEach(([a,r])=>{a.startsWith("jcr:")||a.startsWith("sling:")||r&&typeof r=="object"&&r["jcr:content"]&&s.push({name:a,path:`${t}/${a}`,title:r["jcr:content"]["jcr:title"]||a,description:r["jcr:content"]["jcr:description"],allowedPaths:r["jcr:content"].allowedPaths,ranking:r["jcr:content"].ranking||0})}),p({sitePath:e,templates:s,totalCount:s.length,source:"site-specific"},"getTemplates")}catch{}try{const t=["/apps/wcm/core/content/sites/templates","/libs/wcm/core/content/sites/templates"],n=[];for(const s of t)try{const a=await this.fetch.get(`${s}.json`,{":depth":"2"});a&&typeof a=="object"&&Object.entries(a).forEach(([r,o])=>{r.startsWith("jcr:")||r.startsWith("sling:")||o&&typeof o=="object"&&n.push({name:r,path:`${s}/${r}`,title:o["jcr:content"]?.["jcr:title"]||r,description:o["jcr:content"]?.["jcr:description"],allowedPaths:o["jcr:content"]?.allowedPaths,ranking:o["jcr:content"]?.ranking||0,source:s.includes("/apps/")?"apps":"libs"})})}catch{}return p({sitePath:e||"global",templates:n,totalCount:n.length,source:"global"},"getTemplates")}catch(t){throw y(t,"getTemplates")}},"getTemplates")}async getTemplateStructure(e){return l(async()=>{try{const t=await this.fetch.get(`${e}.infinity.json`),n={path:e,properties:t["jcr:content"]||{},policies:t["jcr:content"]?.policies||{},structure:t["jcr:content"]?.structure||{},initialContent:t["jcr:content"]?.initial||{},allowedComponents:[],allowedPaths:t["jcr:content"]?.allowedPaths||[]},s=(a,r="")=>{if(!(!a||typeof a!="object")){if(a.components){const o=Object.keys(a.components);n.allowedComponents.push(...o)}Object.entries(a).forEach(([o,c])=>{typeof c=="object"&&c!==null&&!o.startsWith("jcr:")&&s(c,r?`${r}/${o}`:o)})}};return s(n.policies),n.allowedComponents=[...new Set(n.allowedComponents)],p({templatePath:e,structure:n,fullData:t},"getTemplateStructure")}catch(t){throw y(t,"getTemplateStructure")}},"getTemplateStructure")}async bulkUpdateComponents(e){return l(async()=>{const{updates:t,validateFirst:n=!0,continueOnError:s=!1}=e;if(!Array.isArray(t)||t.length===0)throw m(d.INVALID_PARAMETERS,"Updates array is required and cannot be empty");const a=[];if(n)for(const o of t)try{await this.fetch.get(`${o.componentPath}.json`)}catch(c){if(c.response?.status===404&&(a.push({componentPath:o.componentPath,success:!1,error:`Component not found: ${o.componentPath}`,phase:"validation"}),!s))return p({success:!1,message:"Bulk update failed during validation phase",results:a,totalUpdates:t.length,successfulUpdates:0},"bulkUpdateComponents")}let r=0;for(const o of t)try{const c=await this.updateComponent({componentPath:o.componentPath,properties:o.properties});a.push({componentPath:o.componentPath,success:!0,result:c,phase:"update"}),r++}catch(c){if(a.push({componentPath:o.componentPath,success:!1,error:c.message,phase:"update"}),!s)break}return p({success:r===t.length,message:`Bulk update completed: ${r}/${t.length} successful`,results:a,totalUpdates:t.length,successfulUpdates:r,failedUpdates:t.length-r},"bulkUpdateComponents")},"bulkUpdateComponents")}async getNodeContent(e,t=1){return l(async()=>{const n=`${e}.json`,s=await this.fetch.get(n,{":depth":t.toString()});return{path:e,depth:t,content:s,timestamp:new Date().toISOString()}},"getNodeContent")}async getAvailableTemplates(e){return l(async()=>{let t="/conf";const n=e.split("/");n.length>=3&&n[1]==="content"&&(t=`/conf/${n[2]}`);const s=`${t}/settings/wcm/templates`;try{const a=await this.fetch.get(`${s}.json`,{":depth":"3"}),r=[];return a&&typeof a=="object"&&Object.entries(a).forEach(([o,c])=>{if(!(o.startsWith("jcr:")||o.startsWith("sling:"))&&c&&typeof c=="object"&&c["jcr:content"]){const i=`${s}/${o}`,h=c["jcr:content"];r.push({name:o,path:i,title:h["jcr:title"]||o,description:h["jcr:description"]||"",thumbnail:h.thumbnail||"",allowedPaths:h.allowedPaths||[],status:h.status||"enabled",ranking:h.ranking||0,templateType:h.templateType||"page",lastModified:h["cq:lastModified"],createdBy:h["jcr:createdBy"]})}}),r.sort((o,c)=>o.ranking!==c.ranking?c.ranking-o.ranking:o.name.localeCompare(c.name)),p({parentPath:e,templatesPath:s,templates:r,totalCount:r.length,availableTemplates:r.filter(o=>o.status==="enabled")},"getAvailableTemplates")}catch(a){if(a.response?.status===404){const r="/libs/wcm/foundation/templates",o=await this.fetch.get(`${r}.json`,{":depth":"2"}),c=[];return o&&typeof o=="object"&&Object.entries(o).forEach(([i,h])=>{i.startsWith("jcr:")||i.startsWith("sling:")||h&&typeof h=="object"&&c.push({name:i,path:`${r}/${i}`,title:h["jcr:title"]||i,description:h["jcr:description"]||"Global template",status:"enabled",ranking:0,templateType:"page",isGlobal:!0})}),p({parentPath:e,templatesPath:r,templates:c,totalCount:c.length,availableTemplates:c,fallbackUsed:!0},"getAvailableTemplates")}throw a}},"getAvailableTemplates")}async createPageWithTemplate(e){return l(async()=>{const{parentPath:t,title:n,template:s,name:a,properties:r={}}=e;if(!g(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid parent path: ${String(t)}`,{parentPath:t});let o=s;if(!o){const b=(await this.getAvailableTemplates(t)).data.availableTemplates;if(b.length===0)throw m(d.INVALID_PARAMETERS,"No templates available for this path",{parentPath:t});o=b[0].path,console.log(`\u{1F3AF} Auto-selected template: ${o} (${b[0].title})`)}try{await this.fetch.get(`${o}.json`)}catch(u){throw u?.response?.status===404?m(d.INVALID_PARAMETERS,`Template not found: ${o}`,{template:o}):y(u,"createPageWithTemplate")}const c=a||n.replace(/\s+/g,"-").toLowerCase(),i=`${t}/${c}`,h={"jcr:primaryType":"cq:Page","jcr:content":{"jcr:primaryType":"cq:PageContent","jcr:title":n,"cq:template":o,"sling:resourceType":"foundation/components/page","cq:lastModified":new Date().toISOString(),"cq:lastModifiedBy":"admin",...r}},f=new URLSearchParams;f.append("jcr:primaryType","cq:Page"),await this.fetch.post(i,f);const j=new URLSearchParams;Object.entries(h["jcr:content"]).forEach(([u,b])=>{u==="jcr:created"||u==="jcr:createdBy"||(typeof b=="object"?j.append(u,JSON.stringify(b)):j.append(u,String(b)))}),await this.fetch.post(`${i}/jcr:content`,j);const w=await this.fetch.get(`${i}.json`),A=w["jcr:content"]!==void 0;let C=!1;try{C=(await this.fetch.get(`${i}.html`)).status===200}catch{C=!1}return p({success:!0,pagePath:i,title:n,templateUsed:o,jcrContentCreated:A,pageAccessible:C,errorLogCheck:{hasErrors:!1,errors:[]},creationDetails:{timestamp:new Date().toISOString(),steps:["Template validation completed","Page node created","jcr:content node created","Page structure verified","Accessibility check completed"]},pageStructure:w.data},"createPageWithTemplate")},"createPageWithTemplate")}async validateTemplate(e,t){return l(async()=>{try{const n=await this.fetch.get(`${e}.json`);if(!n||!n["jcr:content"])throw m(d.INVALID_PARAMETERS,"Invalid template structure",{templatePath:e});const s=n["jcr:content"],a=s.allowedPaths||[];let r=a.length===0;return a.length>0&&(r=a.some(o=>t.startsWith(o))),p({templatePath:e,targetPath:t,isValid:r,templateTitle:s["jcr:title"]||"Untitled Template",templateDescription:s["jcr:description"]||"",allowedPaths:a,restrictions:{hasPathRestrictions:a.length>0,allowedPaths:a}},"validateTemplate")}catch(n){throw n.response?.status===404?m(d.INVALID_PARAMETERS,`Template not found: ${e}`,{templatePath:e}):y(n,"validateTemplate")}},"validateTemplate")}templateCache=new Map;templateCacheExpiry=new Map;TEMPLATE_CACHE_TTL=300*1e3;async getTemplateMetadata(e,t=!0){return l(async()=>{if(t&&this.templateCache.has(e)){const r=this.templateCacheExpiry.get(e)||0;if(Date.now()<r)return p({...this.templateCache.get(e),fromCache:!0},"getTemplateMetadata")}const n=await this.fetch.get(`${e}.json`);if(!n||!n["jcr:content"])throw m(d.INVALID_PARAMETERS,"Invalid template structure",{templatePath:e});const s=n["jcr:content"],a={templatePath:e,title:s["jcr:title"]||"Untitled Template",description:s["jcr:description"]||"",thumbnail:s.thumbnail||"",allowedPaths:s.allowedPaths||[],status:s.status||"enabled",ranking:s.ranking||0,templateType:s.templateType||"page",lastModified:s["cq:lastModified"],createdBy:s["jcr:createdBy"],policies:s.policies||{},structure:s.structure||{},initialContent:s.initial||{}};return t&&(this.templateCache.set(e,a),this.templateCacheExpiry.set(e,Date.now()+this.TEMPLATE_CACHE_TTL)),p(a,"getTemplateMetadata")},"getTemplateMetadata")}clearTemplateCache(){this.templateCache.clear(),this.templateCacheExpiry.clear(),console.log("\u{1F5D1}\uFE0F Template cache cleared")}}
|
|
1
|
+
"use strict";import{getAEMConfig as M,isValidContentPath as y,isValidLocale as $}from"./aem.config.js";import{AEM_ERROR_CODES as d,createAEMError as m,createSuccessResponse as p,handleAEMHttpError as j,safeExecute as l,validateComponentOperation as I}from"./aem.errors.js";import{AEMFetch as R}from"./aem.fetch.js";import{LOGGER as u}from"../utils/logger.js";export class AEMConnector{isInitialized;isAEMaaCS;config;aemConfig;fetch;constructor(e){this.isInitialized=!1,this.config=this.loadConfig(e),this.aemConfig=M({}),this.isAEMaaCS=this.isConfigAEMaaCS(),this.fetch=new R({host:this.config.aem.host,auth:this.config.aem.auth,timeout:this.aemConfig.queries.timeoutMs})}async init(){try{await this.fetch.init(),this.isInitialized=!0}catch{this.isInitialized=!1}}isConfigAEMaaCS(){return!!(this.config.aem.auth.clientId&&this.config.aem.auth.clientSecret)}loadConfig(e={}){let t;return e.id&&e.secret?t={clientId:e.id,clientSecret:e.secret}:t={username:e.user||"admin",password:e.pass||"admin"},{aem:{host:e.host||"http://localhost:4502",author:e.host||"http://localhost:4502",publish:"http://localhost:4503",auth:t,endpoints:{content:"/content",dam:"/content/dam",query:"/bin/querybuilder.json",crxde:"/crx/de",jcr:""}},mcp:{name:"NAEM MCP Server",version:"1.0.0"}}}async testConnection(){const e=await this.testAEMConnection(),t=e?await this.testAuthConnection():!1;return{aem:e,auth:t}}async testAEMConnection(){try{this.isInitialized||await this.init();const e="/libs/granite/core/content/login.html";u.log("Testing AEM connection to:",e);const t=await this.fetch.get(e,void 0,void 0,5e3,!0);return u.log("\u2705 AEM connection successful!"),!0}catch(e){return u.error("\u274C AEM connection failed:",e.message),!1}}async testAuthConnection(){try{this.isInitialized||await this.init();const e="/libs/granite/security/currentuser.json";u.log("Testing AEM authentication connection to:",e);const t=await this.fetch.get(e,void 0,void 0,5e3);return u.log("\u2705 AEM authentication connection successful!"),!0}catch(e){return u.error("\u274C AEM authentication connection failed:",e.message),!1}}async validateComponent(e){return l(async()=>{const t=e.pagePath||e.page_path,{locale:n,component:a,props:s}=e;if(I(n,t,a,s),!$(n,this.aemConfig))throw m(d.INVALID_LOCALE,`Locale '${n}' is not supported`,{locale:n,allowedLocales:this.aemConfig.validation.allowedLocales});if(!y(t,this.aemConfig))throw m(d.INVALID_PATH,`Path '${t}' is not within allowed content roots`,{path:t,allowedRoots:Object.values(this.aemConfig.contentPaths)});const r=`${t}.json`,o=await this.fetch.get(r,{params:{":depth":"2"},timeout:this.aemConfig.queries.timeoutMs}),c=this.validateComponentProps(o.data,a,s);return p({message:"Component validation completed successfully",pageData:o.data,component:a,locale:n,validation:c,configUsed:{allowedLocales:this.aemConfig.validation.allowedLocales}},"validateComponent")},"validateComponent")}validateComponentProps(e,t,n){const a=[],s=[];return t==="text"&&!n.text&&!n.richText&&a.push("Text component should have text or richText property"),t==="image"&&!n.fileReference&&!n.src&&s.push("Image component requires fileReference or src property"),{valid:s.length===0,errors:s,warnings:a,componentType:t,propsValidated:Object.keys(n).length}}async updateComponent(e){return l(async()=>{if(!e.componentPath||typeof e.componentPath!="string")throw m(d.INVALID_PARAMETERS,"Component path is required and must be a string");if(!e.properties||typeof e.properties!="object")throw m(d.INVALID_PARAMETERS,"Properties are required and must be an object");if(!y(e.componentPath,this.aemConfig))throw m(d.INVALID_PATH,`Component path '${e.componentPath}' is not within allowed content roots`,{path:e.componentPath,allowedRoots:Object.values(this.aemConfig.contentPaths)});const t=`${e.componentPath}.json`,n=await this.fetch.get(t);try{await n.json()}catch(o){throw o.response?.status===404?m(d.COMPONENT_NOT_FOUND,`Component not found at path: ${e.componentPath}`,{componentPath:e.componentPath}):j(o,"updateComponent")}const a=new URLSearchParams;Object.entries(e.properties).forEach(([o,c])=>{c==null?a.append(`${o}@Delete`,""):Array.isArray(c)?c.forEach(i=>{a.append(`${o}`,i.toString())}):typeof c=="object"?a.append(o,JSON.stringify(c)):a.append(o,c.toString())});const s=await this.fetch.post(e.componentPath,a),r=await this.fetch.get(`${e.componentPath}.json`);return p({message:"Component updated successfully",path:e.componentPath,properties:e.properties,updatedProperties:r.data,response:s.data,verification:{success:!0,propertiesChanged:Object.keys(e.properties).length,timestamp:new Date().toISOString()}},"updateComponent")},"updateComponent")}async undoChanges(e){return p({message:"undoChanges is not implemented. Please use AEM version history for undo/rollback.",request:e,timestamp:new Date().toISOString()},"undoChanges")}async scanPageComponents(e){return l(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),a=[],s=(r,o)=>{!r||typeof r!="object"||(r["sling:resourceType"]&&a.push({path:o,resourceType:r["sling:resourceType"],properties:{...r}}),Object.entries(r).forEach(([c,i])=>{if(typeof i=="object"&&i!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const h=o?`${o}/${c}`:c;s(i,h)}}))};return n.data["jcr:content"]?s(n.data["jcr:content"],"jcr:content"):s(n.data,e),p({pagePath:e,components:a,totalComponents:a.length},"scanPageComponents")},"scanPageComponents")}async fetchSites(){return l(async()=>{const t=await this.fetch.get("/content.json",{":depth":"2"}),n=[];return Object.entries(t).forEach(([a,s])=>{a.startsWith("jcr:")||a.startsWith("sling:")||s&&typeof s=="object"&&s["jcr:content"]&&n.push({name:a,path:`/content/${a}`,title:s["jcr:content"]["jcr:title"]||a,template:s["jcr:content"]["cq:template"],lastModified:s["jcr:content"]["cq:lastModified"]})}),p({sites:n,totalCount:n.length},"fetchSites")},"fetchSites")}async fetchLanguageMasters(e){return l(async()=>{const t=`/content/${e}.json`,n=await this.fetch.get(t,{":depth":"3"}),a=[];return Object.entries(n).forEach(([s,r])=>{s.startsWith("jcr:")||s.startsWith("sling:")||r&&typeof r=="object"&&r["jcr:content"]&&a.push({name:s,path:`/content/${s}`,title:r["jcr:content"]["jcr:title"]||s,language:r["jcr:content"]["jcr:language"]||"en"})}),p({site:e,languageMasters:a},"fetchLanguageMasters")},"fetchLanguageMasters")}async fetchAvailableLocales(e,t){return l(async()=>{const n=`${t}.json`,a=await this.fetch.get(n,{":depth":"2"}),s=[];return Object.entries(a).forEach(([r,o])=>{r.startsWith("jcr:")||r.startsWith("sling:")||o&&typeof o=="object"&&s.push({name:r,title:o["jcr:content"]?.["jcr:title"]||r,language:o["jcr:content"]?.["jcr:language"]||r})}),p({site:e,languageMasterPath:t,availableLocales:s},"fetchAvailableLocales")},"fetchAvailableLocales")}async replicateAndPublish(e,t,n){return l(async()=>p({message:"Replication simulated",selectedLocales:e,componentData:t,localizedOverrides:n},"replicateAndPublish"),"replicateAndPublish")}async getAllTextContent(e){return l(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),a=[],s=(r,o)=>{!r||typeof r!="object"||((r.text||r["jcr:title"]||r["jcr:description"])&&a.push({path:o,title:r["jcr:title"],text:r.text,description:r["jcr:description"]}),Object.entries(r).forEach(([c,i])=>{if(typeof i=="object"&&i!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const h=o?`${o}/${c}`:c;s(i,h)}}))};return n["jcr:content"]?s(n["jcr:content"],"jcr:content"):s(n,e),p({pagePath:e,textContent:a},"getAllTextContent")},"getAllTextContent")}async getPageTextContent(e){return l(async()=>this.getAllTextContent(e),"getPageTextContent")}async getPageImages(e){return l(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),a=[],s=(r,o)=>{!r||typeof r!="object"||((r.fileReference||r.src)&&a.push({path:o,fileReference:r.fileReference,src:r.src,alt:r.alt||r.altText,title:r["jcr:title"]||r.title}),Object.entries(r).forEach(([c,i])=>{if(typeof i=="object"&&i!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const h=o?`${o}/${c}`:c;s(i,h)}}))};return n["jcr:content"]?s(n["jcr:content"],"jcr:content"):s(n,e),p({pagePath:e,images:a},"getPageImages")},"getPageImages")}async updateImagePath(e,t){return l(async()=>this.updateComponent({componentPath:e,properties:{fileReference:t}}),"updateImagePath")}async getPageContent(e){return l(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t);return p({pagePath:e,content:n},"getPageContent")},"getPageContent")}async listChildren(e,t=1){return l(async()=>{try{const n=await this.fetch.get(`${e}.${t}.json`),a=[];return n&&typeof n=="object"&&Object.entries(n).forEach(([s,r])=>{if(!(s.startsWith("jcr:")||s.startsWith("sling:")||s.startsWith("cq:")||s.startsWith("rep:")||s.startsWith("oak:")||s==="jcr:content")&&r&&typeof r=="object"){const o=`${e}/${s}`;a.push({name:s,path:o,primaryType:r["jcr:primaryType"]||"nt:unstructured",title:r["jcr:content"]?.["jcr:title"]||r["jcr:title"]||s,lastModified:r["jcr:content"]?.["cq:lastModified"]||r["cq:lastModified"],resourceType:r["jcr:content"]?.["sling:resourceType"]||r["sling:resourceType"]})}}),a}catch(n){if(n.response?.status===404||n.response?.status===403)return((await this.fetch.get("/bin/querybuilder.json",{path:e,type:"cq:Page","p.nodedepth":"1","p.limit":"1000","p.hits":"full"})).hits||[]).map(s=>({name:s.name||s.path?.split("/").pop(),path:s.path,primaryType:s["jcr:primaryType"]||"cq:Page",title:s["jcr:content/jcr:title"]||s.title||s.name,lastModified:s["jcr:content/cq:lastModified"],resourceType:s["jcr:content/sling:resourceType"]}));throw n}},"listChildren")}async listPages(e,t=1,n=20){return l(async()=>{try{const a=await this.fetch.get(`${e}.${t}.json`),s=[],r=(o,c,i)=>{i>t||s.length>=n||Object.entries(o).forEach(([h,f])=>{if(!(s.length>=n)&&!(h.startsWith("jcr:")||h.startsWith("sling:")||h.startsWith("cq:")||h.startsWith("rep:")||h.startsWith("oak:"))&&f&&typeof f=="object"){const P=`${c}/${h}`;f["jcr:primaryType"]==="cq:Page"&&s.push({name:h,path:P,primaryType:"cq:Page",title:f["jcr:content"]?.["jcr:title"]||h,template:f["jcr:content"]?.["cq:template"],lastModified:f["jcr:content"]?.["cq:lastModified"],lastModifiedBy:f["jcr:content"]?.["cq:lastModifiedBy"],resourceType:f["jcr:content"]?.["sling:resourceType"],type:"page"}),i<t&&r(f,P,i+1)}})};return a&&typeof a=="object"&&r(a,e,0),p({siteRoot:e,pages:s,pageCount:s.length,depth:t,limit:n,totalChildrenScanned:s.length},"listPages")}catch(a){if(u.warn("JSON API failed, falling back to QueryBuilder:",a.message),a.response?.status===404||a.response?.status===403){const s=await this.fetch.get("/bin/querybuilder.json",{path:e,type:"cq:Page","p.nodedepth":t.toString(),"p.limit":n.toString(),"p.hits":"full"}),r=(s.hits||[]).map(o=>({name:o.name||o.path?.split("/").pop(),path:o.path,primaryType:"cq:Page",title:o["jcr:content/jcr:title"]||o.title||o.name,template:o["jcr:content/cq:template"],lastModified:o["jcr:content/cq:lastModified"],lastModifiedBy:o["jcr:content/cq:lastModifiedBy"],resourceType:o["jcr:content/sling:resourceType"],type:"page"}));return p({siteRoot:e,pages:r,pageCount:r.length,depth:t,limit:n,totalChildrenScanned:s.total||r.length,fallbackUsed:"QueryBuilder"},"listPages")}throw a}},"listPages")}async executeJCRQuery(e,t=20){return l(async()=>{if(!e||e.trim().length===0)throw new Error("Query is required and must be a non-empty string. Note: Only QueryBuilder fulltext is supported, not JCR SQL2.");const n=e.toLowerCase();if(/drop|delete|update|insert|exec|script|\.|<script/i.test(n)||e.length>1e3)throw new Error("Query contains potentially unsafe patterns or is too long");const a=await this.fetch.get("/bin/querybuilder.json",{path:"/content",type:"cq:Page",fulltext:e,"p.limit":t});return{query:e,results:a.hits||[],total:a.total||0,limit:t}},"executeJCRQuery")}async getPageProperties(e){return l(async()=>{const t=`${e}/jcr:content.json`,n=await this.fetch.get(t),a={title:n["jcr:title"],description:n["jcr:description"],template:n["cq:template"],lastModified:n["cq:lastModified"],lastModifiedBy:n["jcr:createdBy"],created:n["jcr:created"],createdBy:n["jcr:createdBy"],primaryType:n["jcr:primaryType"],resourceType:n["sling:resourceType"],tags:n["cq:tags"]||[],properties:n};return p({pagePath:e,properties:a},"getPageProperties")},"getPageProperties")}async searchContent(e){return l(async()=>{const t=await this.fetch.get(this.config.aem.endpoints.query,e);return p({params:e,results:t.hits||[],total:t.total||0,rawResponse:t},"searchContent")},"searchContent")}async getAssetMetadata(e){return l(async()=>{const t=`${e}.json`,n=await this.fetch.get(t),a=n["jcr:content"]?.metadata||{};return p({assetPath:e,metadata:a,fullData:n},"getAssetMetadata")},"getAssetMetadata")}async createPage(e){return this.createPageWithTemplate(e)}async deletePage(e){return l(async()=>{const{pagePath:t}=e;if(!y(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});let n=!1;try{await this.fetch.delete(t),n=!0}catch(a){if(a?.status===405||a?.response?.status===405)try{await this.fetch.post("/bin/wcmcommand",{cmd:"deletePage",path:t,force:e.force?"true":"false"}),n=!0}catch{try{await this.fetch.post(t,{":operation":"delete"}),n=!0}catch(r){throw r}}else throw u.error("DELETE failed:",a.response?.status,a.response?.data),a}return p({success:n,deletedPath:t,timestamp:new Date().toISOString()},"deletePage")},"deletePage")}async createComponent(e){return l(async()=>{const{pagePath:t,componentPath:n,componentType:a,resourceType:s,properties:r={},name:o}=e;if(!y(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});const c=o||`${a}_${Date.now()}`,i=n||`${t}/jcr:content/${c}`;return await this.fetch.post(i,{"jcr:primaryType":"nt:unstructured","sling:resourceType":s,...r,":operation":"import",":contentType":"json",":replace":"true"}),p({success:!0,componentPath:i,componentType:a,resourceType:s,properties:r,timestamp:new Date().toISOString()},"createComponent")},"createComponent")}async deleteComponent(e){return l(async()=>{const{componentPath:t}=e;if(!y(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid component path: ${String(t)}`,{componentPath:t});let n=!1;try{await this.fetch.delete(t),n=!0}catch(a){if(a?.status===405||a?.response?.status===405)try{await this.fetch.post(t,{":operation":"delete"}),n=!0}catch(s){throw s}else throw u.error("DELETE failed:",a.response?.status,a.response?.data),a}return p({success:n,deletedPath:t,timestamp:new Date().toISOString()},"deleteComponent")},"deleteComponent")}async unpublishContent(e){return l(async()=>{const{contentPaths:t,unpublishTree:n=!1}=e;if(!t||Array.isArray(t)&&t.length===0)throw m(d.INVALID_PARAMETERS,"Content paths array is required and cannot be empty",{contentPaths:t});const a=[];for(const s of Array.isArray(t)?t:[t])try{const r=new URLSearchParams;r.append("cmd","Deactivate"),r.append("path",s),r.append("ignoredeactivated","false"),r.append("onlymodified","false"),n&&r.append("deep","true");const o=await this.fetch.post("/bin/replicate.json",r);a.push({path:s,success:!0,response:o})}catch(r){a.push({path:s,success:!1,error:r.message})}return p({success:a.every(s=>s.success),results:a,unpublishedPaths:t,unpublishTree:n,timestamp:new Date().toISOString()},"unpublishContent")},"unpublishContent")}async activatePage(e){return l(async()=>{const{pagePath:t,activateTree:n=!1}=e;if(!y(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});try{const a=new URLSearchParams;a.append("cmd","Activate"),a.append("path",t),a.append("ignoredeactivated","false"),a.append("onlymodified","false"),n&&a.append("deep","true");const s=await this.fetch.post("/bin/replicate.json",a);return p({success:!0,activatedPath:t,activateTree:n,response:s,timestamp:new Date().toISOString()},"activatePage")}catch(a){try{const s=await this.fetch.post("/bin/wcmcommand",{cmd:"activate",path:t,ignoredeactivated:!1,onlymodified:!1});return p({success:!0,activatedPath:t,activateTree:n,response:s,fallbackUsed:"WCM Command",timestamp:new Date().toISOString()},"activatePage")}catch{throw j(a,"activatePage")}}},"activatePage")}async deactivatePage(e){return l(async()=>{const{pagePath:t,deactivateTree:n=!1}=e;if(!y(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});try{const a=new URLSearchParams;a.append("cmd","Deactivate"),a.append("path",t),a.append("ignoredeactivated","false"),a.append("onlymodified","false"),n&&a.append("deep","true");const s=await this.fetch.post("/bin/replicate.json",a);return p({success:!0,deactivatedPath:t,deactivateTree:n,response:s,timestamp:new Date().toISOString()},"deactivatePage")}catch(a){try{const s=await this.fetch.post("/bin/wcmcommand",{cmd:"deactivate",path:t,ignoredeactivated:!1,onlymodified:!1});return p({success:!0,deactivatedPath:t,deactivateTree:n,response:s,fallbackUsed:"WCM Command",timestamp:new Date().toISOString()},"deactivatePage")}catch{throw j(a,"deactivatePage")}}},"deactivatePage")}async uploadAsset(e){return l(async()=>{const{parentPath:t,fileName:n,fileContent:a,mimeType:s,metadata:r={}}=e;if(!y(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid parent path: ${String(t)}`,{parentPath:t});const o=`${t}/${n}`;try{const c=new URLSearchParams;typeof a=="string"?c.append("file",a):c.append("file",a.toString()),c.append("fileName",n),c.append(":operation","import"),c.append(":contentType","json"),c.append(":replace","true"),c.append("jcr:primaryType","dam:Asset"),s&&c.append("jcr:content/jcr:mimeType",s),Object.entries(r).forEach(([f,P])=>{c.append(`jcr:content/metadata/${f}`,String(P))});const i=await this.fetch.post(o,c),h=await this.fetch.get(`${o}.json`);return p({success:!0,assetPath:o,fileName:n,mimeType:s,metadata:r,uploadResponse:i,assetData:h,timestamp:new Date().toISOString()},"uploadAsset")}catch(c){try{const i=await this.fetch.post("/api/assets"+t,{fileName:n,fileContent:a,mimeType:s,metadata:r});return p({success:!0,assetPath:o,fileName:n,mimeType:s,metadata:r,uploadResponse:i,fallbackUsed:"DAM API",timestamp:new Date().toISOString()},"uploadAsset")}catch{throw j(c,"uploadAsset")}}},"uploadAsset")}async updateAsset(e){return l(async()=>{const{assetPath:t,metadata:n,fileContent:a,mimeType:s}=e;if(!y(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid asset path: ${String(t)}`,{assetPath:t});const r=new URLSearchParams;a&&(r.append("file",a),s&&r.append("jcr:content/jcr:mimeType",s)),n&&typeof n=="object"&&Object.entries(n).forEach(([o,c])=>{r.append(`jcr:content/metadata/${o}`,String(c))});try{const o=await this.fetch.post(t,r),c=await this.fetch.get(`${t}.json`);return p({success:!0,assetPath:t,updatedMetadata:n,updateResponse:o,assetData:c,timestamp:new Date().toISOString()},"updateAsset")}catch(o){throw j(o,"updateAsset")}},"updateAsset")}async deleteAsset(e){return l(async()=>{const{assetPath:t,force:n=!1}=e;if(!y(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid asset path: ${String(t)}`,{assetPath:t});return await this.fetch.delete(t),p({success:!0,deletedPath:t,force:n,timestamp:new Date().toISOString()},"deleteAsset")},"deleteAsset")}getTemplatesPath(e){if(!e||e.trim().length===0)return"";let t=e.trim(),n="/conf",a="/settings/wcm/templates";return t=t.replace(/\/+$/,""),t.startsWith("/content/")&&(t=t.replace("/content","")),t.startsWith(n)||(t=`${n}/${t.replace(/^\//,"")}`),t.endsWith(a)||(t+=a),t}async getTemplates(e){return l(async()=>{if(e)try{const t=this.getTemplatesPath(e);if(!t)throw m(d.INVALID_PARAMETERS,`Cannot determine configuration path for site: ${e}`,{sitePath:e});u.log("Looking for site-specific templates at:",t);const n=await this.fetch.get(`${t}.2.json`),a=[];return n&&typeof n=="object"&&Object.entries(n).forEach(([s,r])=>{s.startsWith("jcr:")||s.startsWith("sling:")||r&&typeof r=="object"&&r["jcr:content"]&&a.push({name:s,path:`${t}/${s}`,title:r["jcr:content"]["jcr:title"]||s,description:r["jcr:content"]["jcr:description"],allowedPaths:r["jcr:content"].allowedPaths,ranking:r["jcr:content"].ranking||0})}),p({sitePath:e,templates:a,totalCount:a.length,source:"site-specific"},"getTemplates")}catch{}try{const t=["/apps/wcm/core/content/sites/templates","/libs/wcm/core/content/sites/templates"],n=[];for(const a of t)try{const s=await this.fetch.get(`${a}.json`,{":depth":"2"});s&&typeof s=="object"&&Object.entries(s).forEach(([r,o])=>{r.startsWith("jcr:")||r.startsWith("sling:")||o&&typeof o=="object"&&n.push({name:r,path:`${a}/${r}`,title:o["jcr:content"]?.["jcr:title"]||r,description:o["jcr:content"]?.["jcr:description"],allowedPaths:o["jcr:content"]?.allowedPaths,ranking:o["jcr:content"]?.ranking||0,source:a.includes("/apps/")?"apps":"libs"})})}catch{}return p({sitePath:e||"global",templates:n,totalCount:n.length,source:"global"},"getTemplates")}catch(t){throw j(t,"getTemplates")}},"getTemplates")}async getTemplateStructure(e){return l(async()=>{try{const t=await this.fetch.get(`${e}.infinity.json`),n={path:e,properties:t["jcr:content"]||{},policies:t["jcr:content"]?.policies||{},structure:t["jcr:content"]?.structure||{},initialContent:t["jcr:content"]?.initial||{},allowedComponents:[],allowedPaths:t["jcr:content"]?.allowedPaths||[]},a=(s,r="")=>{if(!(!s||typeof s!="object")){if(s.components){const o=Object.keys(s.components);n.allowedComponents.push(...o)}Object.entries(s).forEach(([o,c])=>{typeof c=="object"&&c!==null&&!o.startsWith("jcr:")&&a(c,r?`${r}/${o}`:o)})}};return a(n.policies),n.allowedComponents=[...new Set(n.allowedComponents)],p({templatePath:e,structure:n,fullData:t},"getTemplateStructure")}catch(t){throw j(t,"getTemplateStructure")}},"getTemplateStructure")}async bulkUpdateComponents(e){return l(async()=>{const{updates:t,validateFirst:n=!0,continueOnError:a=!1}=e;if(!Array.isArray(t)||t.length===0)throw m(d.INVALID_PARAMETERS,"Updates array is required and cannot be empty");const s=[];if(n)for(const o of t)try{await this.fetch.get(`${o.componentPath}.json`)}catch(c){if(c.response?.status===404&&(s.push({componentPath:o.componentPath,success:!1,error:`Component not found: ${o.componentPath}`,phase:"validation"}),!a))return p({success:!1,message:"Bulk update failed during validation phase",results:s,totalUpdates:t.length,successfulUpdates:0},"bulkUpdateComponents")}let r=0;for(const o of t)try{const c=await this.updateComponent({componentPath:o.componentPath,properties:o.properties});s.push({componentPath:o.componentPath,success:!0,result:c,phase:"update"}),r++}catch(c){if(s.push({componentPath:o.componentPath,success:!1,error:c.message,phase:"update"}),!a)break}return p({success:r===t.length,message:`Bulk update completed: ${r}/${t.length} successful`,results:s,totalUpdates:t.length,successfulUpdates:r,failedUpdates:t.length-r},"bulkUpdateComponents")},"bulkUpdateComponents")}async getNodeContent(e,t=1){return l(async()=>{const n=`${e}.json`,a=await this.fetch.get(n,{":depth":t.toString()});return{path:e,depth:t,content:a,timestamp:new Date().toISOString()}},"getNodeContent")}async getAvailableTemplates(e){return l(async()=>{console.log("getAvailableTemplates for parentPath:",e);let t="/conf";const n=e.split("/");n.length>=3&&n[1]==="content"&&(t=`/conf/${n[2]}`);const a=`${t}/settings/wcm/templates`;try{const s=await this.fetch.get(`${a}.3.json`),r=[];return s&&typeof s=="object"&&Object.entries(s).forEach(([o,c])=>{if(!(o.startsWith("jcr:")||o.startsWith("sling:"))&&c&&typeof c=="object"&&c["jcr:content"]){const i=`${a}/${o}`,h=c["jcr:content"],f=c?.structure?.["jcr:content"]||{};r.push({name:o,path:i,title:h["jcr:title"]||o,description:h["jcr:description"]||"",thumbnail:h.thumbnail||"",allowedPaths:h.allowedPaths||[],status:h.status||"enabled",ranking:h.ranking||0,templateType:h.templateType||"page",resourceType:f["sling:resourceType"]||"",lastModified:h["cq:lastModified"],createdBy:h["jcr:createdBy"]})}}),r.sort((o,c)=>o.ranking!==c.ranking?c.ranking-o.ranking:o.name.localeCompare(c.name)),p({parentPath:e,templatesPath:a,templates:r,totalCount:r.length,availableTemplates:r.filter(o=>o.status==="enabled")},"getAvailableTemplates")}catch(s){if(s.response?.status===404){const r="/libs/wcm/foundation/templates",o=await this.fetch.get(`${r}.json`,{":depth":"2"}),c=[];return o&&typeof o=="object"&&Object.entries(o).forEach(([i,h])=>{i.startsWith("jcr:")||i.startsWith("sling:")||h&&typeof h=="object"&&c.push({name:i,path:`${r}/${i}`,title:h["jcr:title"]||i,description:h["jcr:description"]||"Global template",status:"enabled",ranking:0,templateType:"page",isGlobal:!0})}),p({parentPath:e,templatesPath:r,templates:c,totalCount:c.length,availableTemplates:c,fallbackUsed:!0},"getAvailableTemplates")}throw s}},"getAvailableTemplates")}async createPageWithTemplate(e){return l(async()=>{const{parentPath:t,title:n,template:a,name:s,properties:r={},resourceType:o=""}=e;if(!y(t,this.aemConfig))throw m(d.INVALID_PARAMETERS,`Invalid parent path: ${String(t)}`,{parentPath:t});let c=a,i=o;if(!c||!i){const b=(await this.getAvailableTemplates(t)).data.availableTemplates;if(b.length===0)throw m(d.INVALID_PARAMETERS,"No templates available for this path",{parentPath:t});const T=b[0];c&&(c=T.path),!i&&T.resourceType&&(i=T.resourceType),u.log(`\u{1F3AF} Auto-selected template: ${c} (${b[0].title})`,i)}try{const g=await this.fetch.get(`${c}.json`);u.log(`\u2705 Template verified: ${c}`,g)}catch(g){throw u.error("Template verification failed:",g.message,g),g?.response?.status===404?m(d.INVALID_PARAMETERS,`Template not found: ${c}`,{template:c}):j(g,"createPageWithTemplate")}const h=s||n.replace(/\s+/g,"-").toLowerCase(),f=`${t}/${h}`,P={"jcr:primaryType":"cq:Page","jcr:content":{"jcr:primaryType":"cq:PageContent","jcr:title":n,"cq:template":c,"sling:resourceType":i||"foundation/components/page","cq:lastModified":new Date().toISOString(),"cq:lastModifiedBy":"admin",...r}},w=new URLSearchParams;w.append("jcr:primaryType","cq:Page"),await this.fetch.post(f,w);const C=new URLSearchParams;Object.entries(P["jcr:content"]).forEach(([g,b])=>{g==="jcr:created"||g==="jcr:createdBy"||(typeof b=="object"?C.append(g,JSON.stringify(b)):C.append(g,String(b)))}),await this.fetch.post(`${f}/jcr:content`,C);const E=await this.fetch.get(`${f}.json`),S=E["jcr:content"]!==void 0;let A=!1;try{A=(await this.fetch.get(`${f}.html`)).status===200}catch{A=!1}return p({success:!0,pagePath:f,title:n,templateUsed:c,jcrContentCreated:S,pageAccessible:A,errorLogCheck:{hasErrors:!1,errors:[]},creationDetails:{timestamp:new Date().toISOString(),steps:["Template validation completed","Page node created","jcr:content node created","Page structure verified","Accessibility check completed"]},pageStructure:E.data},"createPageWithTemplate")},"createPageWithTemplate")}async validateTemplate(e,t){return l(async()=>{try{const n=await this.fetch.get(`${e}.json`);if(!n||!n["jcr:content"])throw m(d.INVALID_PARAMETERS,"Invalid template structure",{templatePath:e});const a=n["jcr:content"],s=a.allowedPaths||[];let r=s.length===0;return s.length>0&&(r=s.some(o=>t.startsWith(o))),p({templatePath:e,targetPath:t,isValid:r,templateTitle:a["jcr:title"]||"Untitled Template",templateDescription:a["jcr:description"]||"",allowedPaths:s,restrictions:{hasPathRestrictions:s.length>0,allowedPaths:s}},"validateTemplate")}catch(n){throw n.response?.status===404?m(d.INVALID_PARAMETERS,`Template not found: ${e}`,{templatePath:e}):j(n,"validateTemplate")}},"validateTemplate")}templateCache=new Map;templateCacheExpiry=new Map;TEMPLATE_CACHE_TTL=300*1e3;async getTemplateMetadata(e,t=!0){return l(async()=>{if(t&&this.templateCache.has(e)){const r=this.templateCacheExpiry.get(e)||0;if(Date.now()<r)return p({...this.templateCache.get(e),fromCache:!0},"getTemplateMetadata")}const n=await this.fetch.get(`${e}.json`);if(!n||!n["jcr:content"])throw m(d.INVALID_PARAMETERS,"Invalid template structure",{templatePath:e});const a=n["jcr:content"],s={templatePath:e,title:a["jcr:title"]||"Untitled Template",description:a["jcr:description"]||"",thumbnail:a.thumbnail||"",allowedPaths:a.allowedPaths||[],status:a.status||"enabled",ranking:a.ranking||0,templateType:a.templateType||"page",lastModified:a["cq:lastModified"],createdBy:a["jcr:createdBy"],policies:a.policies||{},structure:a.structure||{},initialContent:a.initial||{}};return t&&(this.templateCache.set(e,s),this.templateCacheExpiry.set(e,Date.now()+this.TEMPLATE_CACHE_TTL)),p(s,"getTemplateMetadata")},"getTemplateMetadata")}clearTemplateCache(){this.templateCache.clear(),this.templateCacheExpiry.clear(),console.log("\u{1F5D1}\uFE0F Template cache cleared")}}
|
package/dist/aem/aem.fetch.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{getAccessToken as
|
|
1
|
+
"use strict";import{getAccessToken as u}from"./aem.auth.js";import{LOGGER as h}from"../utils/logger.js";export class AEMFetch{fetch;config;token;tokenExpiry;constructor(t){this.config=t,this.fetch=null,this.token="",this.tokenExpiry=0}async init(){this.token=await this.getAuthToken(this.config.auth),this.fetch=this.getFetchInstance()}getFetchInstance(){return(t,e={})=>{const n=new Headers(e.headers||{});return n.set("Authorization",`Basic ${this.token}`),n.set("Accept","application/json"),n.has("Content-Type")||n.set("Content-Type","application/json"),fetch(t,{...e,headers:n})}}async getAuthToken(t){if(t.clientId&&t.clientSecret){const e=Date.now();if(this.token&&e<this.tokenExpiry)return this.token;const n=await u(t.clientId,t.clientSecret,t.scope);return this.token=n.access_token,this.tokenExpiry=e+(n.expires_in-60)*1e3,this.token}if(t.username&&t.password)return Buffer.from(`${t.username}:${t.password}`).toString("base64");throw new Error("No authentication credentials provided")}async refreshAuthToken(){this.token="",this.tokenExpiry=0,this.token=await this.getAuthToken(this.config.auth)}getTimeoutOptions(t){let e,n,s;const i=t||this.config.timeout;return i&&(e=new AbortController,s=e.signal,n=setTimeout(()=>e.abort(),i)),{signal:s,timeoutId:n}}buildUrlWithParams(t,e){const n=this.config.host.endsWith("/")?this.config.host.slice(0,-1):this.config.host,s=t.startsWith("/")?t:`/${t}`,i=`${n}${s}`;if(!e||Object.keys(e).length===0)return i;const o=new URL(i);return Object.entries(e).forEach(([r,a])=>{a!=null&&o.searchParams.append(r,String(a))}),o.toString()}async request(t,e={},n,s){if(!this.fetch)throw new Error("AEMFetch not initialized. Call await init(config) before making requests.");const{timeoutId:i,signal:o}=this.getTimeoutOptions(n);n&&(e.signal=o);let r;try{if(h.log("AEM Request:",t,e),r=await this.fetch(t,e),r.status===401&&(h.warn(`AEM request to ${t} returned 401 Unauthorized. Attempting to refresh token...`),await this.refreshAuthToken(),r=await this.fetch(t,e)),!r.ok)throw new Error(`AEM ${e.method||"GET"} failed: ${r.status}`);return s?r.text():r.json()}finally{i&&clearTimeout(i)}}async get(t,e,n={},s,i){const o=this.buildUrlWithParams(t,e);return this.request(o,n,s,i)}async post(t,e,n={},s){let i,o=new Headers(n.headers||{});e instanceof URLSearchParams?(i=e,o.set("Content-Type","application/x-www-form-urlencoded")):(i=JSON.stringify(e),o.set("Content-Type","application/json"));const r=this.buildUrlWithParams(t);return this.request(r,{...n,method:"POST",body:i,headers:o},s)}async delete(t,e={},n){const s=this.buildUrlWithParams(t);return this.request(s,{...e,method:"DELETE"},n)}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{AEMConnector as o}from"../aem/aem.connector.js";import{handleAEMHttpError as r}from"../aem/aem.errors.js";import{LOGGER as a}from"../utils/logger.js";export class MCPRequestHandler{aemConnector;config;constructor(t){this.config=t,this.aemConnector=new o(t)}async init(){this.aemConnector.isInitialized?a.log("AEM Connector already initialized."):(await this.aemConnector.init(),a.log("AEM Connector initialized."))}async handleRequest(t,e){try{await this.init()}catch(n){throw a.error("ERROR initializing MCP Server",n.message),r(n,"MCP Server Initialization")}try{switch(t){case"validateComponent":return await this.aemConnector.validateComponent(e);case"updateComponent":return await this.aemConnector.updateComponent(e);case"undoChanges":return await this.aemConnector.undoChanges(e);case"scanPageComponents":return await this.aemConnector.scanPageComponents(e.pagePath);case"fetchSites":return await this.aemConnector.fetchSites();case"fetchLanguageMasters":return await this.aemConnector.fetchLanguageMasters(e.site);case"fetchAvailableLocales":return await this.aemConnector.fetchAvailableLocales(e.site,e.languageMasterPath);case"replicateAndPublish":return await this.aemConnector.replicateAndPublish(e.selectedLocales,e.componentData,e.localizedOverrides);case"getAllTextContent":return await this.aemConnector.getAllTextContent(e.pagePath);case"getPageTextContent":return await this.aemConnector.getPageTextContent(e.pagePath);case"getPageImages":return await this.aemConnector.getPageImages(e.pagePath);case"updateImagePath":return await this.aemConnector.updateImagePath(e.componentPath,e.newImagePath);case"getPageContent":return await this.aemConnector.getPageContent(e.pagePath);case"listPages":return await this.aemConnector.listPages(e.siteRoot||e.path||"/content",e.depth||1,e.limit||20);case"getNodeContent":return await this.aemConnector.getNodeContent(e.path,e.depth||1);case"listChildren":return await this.aemConnector.listChildren(e.path);case"getPageProperties":return await this.aemConnector.getPageProperties(e.pagePath);case"searchContent":return await this.aemConnector.searchContent(e);case"executeJCRQuery":return await this.aemConnector.executeJCRQuery(e.query,e.limit);case"getAssetMetadata":return await this.aemConnector.getAssetMetadata(e.assetPath);case"getStatus":return this.getWorkflowStatus(e.workflowId);case"enhancedPageSearch":return await this.aemConnector.searchContent({fulltext:e.searchTerm,path:e.basePath,type:"cq:Page",limit:20});case"createPage":return await this.aemConnector.createPage(e);case"deletePage":return await this.aemConnector.deletePage(e);case"createComponent":return await this.aemConnector.createComponent(e);case"deleteComponent":return await this.aemConnector.deleteComponent(e);case"unpublishContent":return await this.aemConnector.unpublishContent(e);case"activatePage":return await this.aemConnector.activatePage(e);case"deactivatePage":return await this.aemConnector.deactivatePage(e);case"uploadAsset":return await this.aemConnector.uploadAsset(e);case"updateAsset":return await this.aemConnector.updateAsset(e);case"deleteAsset":return await this.aemConnector.deleteAsset(e);case"getTemplates":case"getTemplateStructure":return await this.aemConnector.getTemplateStructure(e.templatePath);case"bulkUpdateComponents":return await this.aemConnector.bulkUpdateComponents(e);default:throw new Error(`Unknown method: ${t}`)}}catch(n){return{error:n.message,method:t,params:e}}}getWorkflowStatus(t){return{success:!0,workflowId:t,status:"completed",message:"Mock workflow status - always returns completed",timestamp:new Date().toISOString()}}}
|
|
1
|
+
"use strict";import{AEMConnector as o}from"../aem/aem.connector.js";import{handleAEMHttpError as r}from"../aem/aem.errors.js";import{LOGGER as a}from"../utils/logger.js";export class MCPRequestHandler{aemConnector;config;constructor(t){this.config=t,this.aemConnector=new o(t)}async init(){this.aemConnector.isInitialized?a.log("AEM Connector already initialized."):(await this.aemConnector.init(),a.log("AEM Connector initialized."))}async handleRequest(t,e){try{await this.init()}catch(n){throw a.error("ERROR initializing MCP Server",n.message),r(n,"MCP Server Initialization")}try{switch(t){case"validateComponent":return await this.aemConnector.validateComponent(e);case"updateComponent":return await this.aemConnector.updateComponent(e);case"undoChanges":return await this.aemConnector.undoChanges(e);case"scanPageComponents":return await this.aemConnector.scanPageComponents(e.pagePath);case"fetchSites":return await this.aemConnector.fetchSites();case"fetchLanguageMasters":return await this.aemConnector.fetchLanguageMasters(e.site);case"fetchAvailableLocales":return await this.aemConnector.fetchAvailableLocales(e.site,e.languageMasterPath);case"replicateAndPublish":return await this.aemConnector.replicateAndPublish(e.selectedLocales,e.componentData,e.localizedOverrides);case"getAllTextContent":return await this.aemConnector.getAllTextContent(e.pagePath);case"getPageTextContent":return await this.aemConnector.getPageTextContent(e.pagePath);case"getPageImages":return await this.aemConnector.getPageImages(e.pagePath);case"updateImagePath":return await this.aemConnector.updateImagePath(e.componentPath,e.newImagePath);case"getPageContent":return await this.aemConnector.getPageContent(e.pagePath);case"listPages":return await this.aemConnector.listPages(e.siteRoot||e.path||"/content",e.depth||1,e.limit||20);case"getNodeContent":return await this.aemConnector.getNodeContent(e.path,e.depth||1);case"listChildren":return await this.aemConnector.listChildren(e.path);case"getPageProperties":return await this.aemConnector.getPageProperties(e.pagePath);case"searchContent":return await this.aemConnector.searchContent(e);case"executeJCRQuery":return await this.aemConnector.executeJCRQuery(e.query,e.limit);case"getAssetMetadata":return await this.aemConnector.getAssetMetadata(e.assetPath);case"getStatus":return this.getWorkflowStatus(e.workflowId);case"enhancedPageSearch":return await this.aemConnector.searchContent({fulltext:e.searchTerm,path:e.basePath,type:"cq:Page",limit:20});case"createPage":return await this.aemConnector.createPage(e);case"deletePage":return await this.aemConnector.deletePage(e);case"createComponent":return await this.aemConnector.createComponent(e);case"deleteComponent":return await this.aemConnector.deleteComponent(e);case"unpublishContent":return await this.aemConnector.unpublishContent(e);case"activatePage":return await this.aemConnector.activatePage(e);case"deactivatePage":return await this.aemConnector.deactivatePage(e);case"uploadAsset":return await this.aemConnector.uploadAsset(e);case"updateAsset":return await this.aemConnector.updateAsset(e);case"deleteAsset":return await this.aemConnector.deleteAsset(e);case"getTemplates":return await this.aemConnector.getTemplates(e.sitePath);case"getTemplateStructure":return await this.aemConnector.getTemplateStructure(e.templatePath);case"bulkUpdateComponents":return await this.aemConnector.bulkUpdateComponents(e);default:throw new Error(`Unknown method: ${t}`)}}catch(n){return{error:n.message,method:t,params:e}}}getWorkflowStatus(t){return{success:!0,workflowId:t,status:"completed",message:"Mock workflow status - always returns completed",timestamp:new Date().toISOString()}}}
|
package/dist/mcp/mcp.tools.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export const tools=[{name:"validateComponent",description:"Validate component changes before applying them",inputSchema:{type:"object",properties:{locale:{type:"string"},pagePath:{type:"string"},component:{type:"string"},props:{type:"object"}},required:["locale","pagePath","component","props"]}},{name:"updateComponent",description:"Update component properties in AEM",inputSchema:{type:"object",properties:{componentPath:{type:"string"},properties:{type:"object"}},required:["componentPath","properties"]}},{name:"undoChanges",description:"Undo the last component changes",inputSchema:{type:"object",properties:{jobId:{type:"string"}},required:["jobId"]}},{name:"scanPageComponents",description:"Scan a page to discover all components and their properties",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"fetchSites",description:"Get all available sites in AEM",inputSchema:{type:"object",properties:{}}},{name:"fetchLanguageMasters",description:"Get language masters for a specific site",inputSchema:{type:"object",properties:{site:{type:"string"}},required:["site"]}},{name:"fetchAvailableLocales",description:"Get available locales for a site and language master",inputSchema:{type:"object",properties:{site:{type:"string"},languageMasterPath:{type:"string"}},required:["site","languageMasterPath"]}},{name:"replicateAndPublish",description:"Replicate and publish content to selected locales",inputSchema:{type:"object",properties:{selectedLocales:{type:"array",items:{type:"string"}},componentData:{type:"object"},localizedOverrides:{type:"object"}},required:["selectedLocales","componentData"]}},{name:"getAllTextContent",description:"Get all text content from a page including titles, text components, and descriptions",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"getPageTextContent",description:"Get text content from a specific page",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"getPageImages",description:"Get all images from a page, including those within Experience Fragments",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"updateImagePath",description:"Update the image path for an image component and verify the update",inputSchema:{type:"object",properties:{componentPath:{type:"string"},newImagePath:{type:"string"}},required:["componentPath","newImagePath"]}},{name:"getPageContent",description:"Get all content from a page including Experience Fragments and Content Fragments",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"listPages",description:"List all pages under a site root",inputSchema:{type:"object",properties:{siteRoot:{type:"string"},depth:{type:"number"},limit:{type:"number"}}}},{name:"getNodeContent",description:"Legacy: Get JCR node content",inputSchema:{type:"object",properties:{path:{type:"string"},depth:{type:"number"}},required:["path"]}},{name:"listChildren",description:"Legacy: List child nodes",inputSchema:{type:"object",properties:{path:{type:"string"}},required:["path"]}},{name:"getPageProperties",description:"Get page properties",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"searchContent",description:"Search content using Query Builder",inputSchema:{type:"object",properties:{type:{type:"string"},fulltext:{type:"string"},path:{type:"string"},limit:{type:"number"}}}},{name:"executeJCRQuery",description:"Execute JCR query",inputSchema:{type:"object",properties:{query:{type:"string"},limit:{type:"number"}},required:["query"]}},{name:"getAssetMetadata",description:"Get asset metadata",inputSchema:{type:"object",properties:{assetPath:{type:"string"}},required:["assetPath"]}},{name:"getStatus",description:"Get workflow status by ID",inputSchema:{type:"object",properties:{workflowId:{type:"string"}},required:["workflowId"]}},{name:"enhancedPageSearch",description:"Intelligent page search with comprehensive fallback strategies and cross-section search",inputSchema:{type:"object",properties:{searchTerm:{type:"string"},basePath:{type:"string"},includeAlternateLocales:{type:"boolean"}},required:["searchTerm","basePath"]}},{name:"createPage",description:"Create a new page in AEM",inputSchema:{type:"object",properties:{parentPath:{type:"string"},title:{type:"string"},template:{type:"string"},name:{type:"string"},properties:{type:"object"}},required:["parentPath","title","template"]}},{name:"deletePage",description:"Delete a page from AEM",inputSchema:{type:"object",properties:{pagePath:{type:"string"},force:{type:"boolean"}},required:["pagePath"]}},{name:"createComponent",description:"Create a new component on a page",inputSchema:{type:"object",properties:{pagePath:{type:"string"},componentType:{type:"string"},resourceType:{type:"string"},properties:{type:"object"},name:{type:"string"}},required:["pagePath","componentType","resourceType"]}},{name:"deleteComponent",description:"Delete a component from AEM",inputSchema:{type:"object",properties:{componentPath:{type:"string"},force:{type:"boolean"}},required:["componentPath"]}},{name:"unpublishContent",description:"Unpublish content from the publish environment",inputSchema:{type:"object",properties:{contentPaths:{type:"array",items:{type:"string"}},unpublishTree:{type:"boolean"}},required:["contentPaths"]}},{name:"activatePage",description:"Activate (publish) a single page",inputSchema:{type:"object",properties:{pagePath:{type:"string"},activateTree:{type:"boolean"}},required:["pagePath"]}},{name:"deactivatePage",description:"Deactivate (unpublish) a single page",inputSchema:{type:"object",properties:{pagePath:{type:"string"},deactivateTree:{type:"boolean"}},required:["pagePath"]}},{name:"uploadAsset",description:"Upload a new asset to AEM DAM",inputSchema:{type:"object",properties:{parentPath:{type:"string"},fileName:{type:"string"},fileContent:{type:"string"},mimeType:{type:"string"},metadata:{type:"object"}},required:["parentPath","fileName","fileContent"]}},{name:"updateAsset",description:"Update an existing asset in AEM DAM",inputSchema:{type:"object",properties:{assetPath:{type:"string"},metadata:{type:"object"},fileContent:{type:"string"},mimeType:{type:"string"}},required:["assetPath"]}},{name:"deleteAsset",description:"Delete an asset from AEM DAM",inputSchema:{type:"object",properties:{assetPath:{type:"string"},force:{type:"boolean"}},required:["assetPath"]}},{name:"getTemplates",description:"Get available page templates",inputSchema:{type:"object",properties:{sitePath:{type:"string"}}}},{name:"getTemplateStructure",description:"Get detailed structure of a specific template",inputSchema:{type:"object",properties:{templatePath:{type:"string"}},required:["templatePath"]}},{name:"bulkUpdateComponents",description:"Update multiple components in a single operation with validation and rollback support",inputSchema:{type:"object",properties:{updates:{type:"array",items:{type:"object",properties:{componentPath:{type:"string"},properties:{type:"object"}},required:["componentPath","properties"]}},validateFirst:{type:"boolean"},continueOnError:{type:"boolean"}},required:["updates"]}}];
|
|
1
|
+
"use strict";export const tools=[{name:"validateComponent",description:"Validate component changes before applying them",inputSchema:{type:"object",properties:{locale:{type:"string"},pagePath:{type:"string"},component:{type:"string"},props:{type:"object"}},required:["locale","pagePath","component","props"]}},{name:"updateComponent",description:"Update component properties in AEM",inputSchema:{type:"object",properties:{componentPath:{type:"string"},properties:{type:"object"}},required:["componentPath","properties"]}},{name:"undoChanges",description:"Undo the last component changes",inputSchema:{type:"object",properties:{jobId:{type:"string"}},required:["jobId"]}},{name:"scanPageComponents",description:"Scan a page to discover all components and their properties",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"fetchSites",description:"Get all available sites in AEM",inputSchema:{type:"object",properties:{}}},{name:"fetchLanguageMasters",description:"Get language masters for a specific site",inputSchema:{type:"object",properties:{site:{type:"string"}},required:["site"]}},{name:"fetchAvailableLocales",description:"Get available locales for a site and language master",inputSchema:{type:"object",properties:{site:{type:"string"},languageMasterPath:{type:"string"}},required:["site","languageMasterPath"]}},{name:"replicateAndPublish",description:"Replicate and publish content to selected locales",inputSchema:{type:"object",properties:{selectedLocales:{type:"array",items:{type:"string"}},componentData:{type:"object"},localizedOverrides:{type:"object"}},required:["selectedLocales","componentData"]}},{name:"getAllTextContent",description:"Get all text content from a page including titles, text components, and descriptions",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"getPageTextContent",description:"Get text content from a specific page",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"getPageImages",description:"Get all images from a page, including those within Experience Fragments",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"updateImagePath",description:"Update the image path for an image component and verify the update",inputSchema:{type:"object",properties:{componentPath:{type:"string"},newImagePath:{type:"string"}},required:["componentPath","newImagePath"]}},{name:"getPageContent",description:"Get all content from a page including Experience Fragments and Content Fragments",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"listPages",description:"List all pages under a site root",inputSchema:{type:"object",properties:{siteRoot:{type:"string"},depth:{type:"number"},limit:{type:"number"}}}},{name:"getNodeContent",description:"Legacy: Get JCR node content",inputSchema:{type:"object",properties:{path:{type:"string"},depth:{type:"number"}},required:["path"]}},{name:"listChildren",description:"Legacy: List child nodes",inputSchema:{type:"object",properties:{path:{type:"string"}},required:["path"]}},{name:"getPageProperties",description:"Get page properties",inputSchema:{type:"object",properties:{pagePath:{type:"string"}},required:["pagePath"]}},{name:"searchContent",description:"Search content using Query Builder",inputSchema:{type:"object",properties:{type:{type:"string"},fulltext:{type:"string"},path:{type:"string"},limit:{type:"number"}}}},{name:"executeJCRQuery",description:"Execute JCR query",inputSchema:{type:"object",properties:{query:{type:"string"},limit:{type:"number"}},required:["query"]}},{name:"getAssetMetadata",description:"Get asset metadata",inputSchema:{type:"object",properties:{assetPath:{type:"string"}},required:["assetPath"]}},{name:"getStatus",description:"Get workflow status by ID",inputSchema:{type:"object",properties:{workflowId:{type:"string"}},required:["workflowId"]}},{name:"enhancedPageSearch",description:"Intelligent page search with comprehensive fallback strategies and cross-section search",inputSchema:{type:"object",properties:{searchTerm:{type:"string"},basePath:{type:"string"},includeAlternateLocales:{type:"boolean"}},required:["searchTerm","basePath"]}},{name:"createPage",description:"Create a new page in AEM",inputSchema:{type:"object",properties:{parentPath:{type:"string"},title:{type:"string"},template:{type:"string"},resourceType:{type:"string"},name:{type:"string"},properties:{type:"object"}},required:["parentPath","title","template","resourceType"]}},{name:"deletePage",description:"Delete a page from AEM",inputSchema:{type:"object",properties:{pagePath:{type:"string"},force:{type:"boolean"}},required:["pagePath"]}},{name:"createComponent",description:"Create a new component on a page",inputSchema:{type:"object",properties:{pagePath:{type:"string"},componentType:{type:"string"},resourceType:{type:"string"},properties:{type:"object"},name:{type:"string"}},required:["pagePath","componentType","resourceType"]}},{name:"deleteComponent",description:"Delete a component from AEM",inputSchema:{type:"object",properties:{componentPath:{type:"string"},force:{type:"boolean"}},required:["componentPath"]}},{name:"unpublishContent",description:"Unpublish content from the publish environment",inputSchema:{type:"object",properties:{contentPaths:{type:"array",items:{type:"string"}},unpublishTree:{type:"boolean"}},required:["contentPaths"]}},{name:"activatePage",description:"Activate (publish) a single page",inputSchema:{type:"object",properties:{pagePath:{type:"string"},activateTree:{type:"boolean"}},required:["pagePath"]}},{name:"deactivatePage",description:"Deactivate (unpublish) a single page",inputSchema:{type:"object",properties:{pagePath:{type:"string"},deactivateTree:{type:"boolean"}},required:["pagePath"]}},{name:"uploadAsset",description:"Upload a new asset to AEM DAM",inputSchema:{type:"object",properties:{parentPath:{type:"string"},fileName:{type:"string"},fileContent:{type:"string"},mimeType:{type:"string"},metadata:{type:"object"}},required:["parentPath","fileName","fileContent"]}},{name:"updateAsset",description:"Update an existing asset in AEM DAM",inputSchema:{type:"object",properties:{assetPath:{type:"string"},metadata:{type:"object"},fileContent:{type:"string"},mimeType:{type:"string"}},required:["assetPath"]}},{name:"deleteAsset",description:"Delete an asset from AEM DAM",inputSchema:{type:"object",properties:{assetPath:{type:"string"},force:{type:"boolean"}},required:["assetPath"]}},{name:"getTemplates",description:"Get available page templates",inputSchema:{type:"object",properties:{sitePath:{type:"string"}}}},{name:"getTemplateStructure",description:"Get detailed structure of a specific template",inputSchema:{type:"object",properties:{templatePath:{type:"string"}},required:["templatePath"]}},{name:"bulkUpdateComponents",description:"Update multiple components in a single operation with validation and rollback support",inputSchema:{type:"object",properties:{updates:{type:"array",items:{type:"object",properties:{componentPath:{type:"string"},properties:{type:"object"}},required:["componentPath","properties"]}},validateFirst:{type:"boolean"},continueOnError:{type:"boolean"}},required:["updates"]}}];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aem-mcp-server",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
4
4
|
"description": "AEM Model Context Protocol (MCP) server",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"build": "npm run build:types && npm run build:ts",
|
|
33
33
|
"build:ts": "esbuild src/**/*.ts src/*.ts --outdir=dist --platform=node --minify",
|
|
34
34
|
"build:types": "tsc --emitDeclarationOnly",
|
|
35
|
-
"start": "node dist/
|
|
35
|
+
"start": "MCP_LOGGER=true node dist/cli.js",
|
|
36
36
|
"test:dev": "node ./dist/cli.js",
|
|
37
37
|
"test:npm": "npm pack && npm install -g ./aem-mcp-server-$npm_package_version.tgz && aem-mcp -e -H=http://localhost:5502"
|
|
38
38
|
},
|