UNPKG

aem-mcp-server

Version:

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

2 lines (1 loc) 5.93 kB
"use strict";import{createSuccessResponse as m,safeExecute as d,createAEMError as l,AEM_ERROR_CODES as g}from"./aem.errors.js";import{LOGGER as j}from"../utils/logger.js";export class ExperienceFragmentManager{fetch;host;constructor(c,e){this.fetch=c,this.host=e}getPreviewUrl(c){return`${this.host}${c}.html?wcmmode=disabled`}async getExperienceFragment(c){return d(async()=>{const e=await this.fetch.get(`${c}.infinity.json`),n=e["jcr:content"]||{},o=[];for(const[r,a]of Object.entries(e)){if(r.startsWith("jcr:")||r.startsWith("rep:")||typeof a!="object")continue;const p=a["jcr:content"];if(!p)continue;const i=p["cq:xfVariantType"];i&&o.push({name:r,type:i,path:`${c}/${r}`,title:p["jcr:title"]||r})}return m({path:c,title:n["jcr:title"]||"",template:n["cq:template"]||"",description:n["jcr:description"]||"",variations:o,tags:n["cq:tags"]||[],lastModified:n["cq:lastModified"]||n["jcr:lastModified"]||"",status:n["cq:lastReplicationAction"]||"not published"},"getExperienceFragment")},"getExperienceFragment")}async listExperienceFragments(c){const{path:e="/content/experience-fragments",template:n,limit:o=20,offset:r=0}=c;return d(async()=>{const a={type:"cq:Page",path:e,property:"jcr:content/sling:resourceType","property.value":"cq/experience-fragments/components/experiencefragment","p.limit":o,"p.offset":r,orderby:"@jcr:content/cq:lastModified","orderby.sort":"desc"};n&&(a["2_property"]="jcr:content/cq:template",a["2_property.value"]=n);const s=await this.fetch.get("/bin/querybuilder.json",a),p=s.hits||[];return m({fragments:p.map(i=>({path:i.path,title:i["jcr:content"]?.["jcr:title"]||i.name,variationCount:Object.keys(i).filter(t=>!t.startsWith("jcr:")&&!t.startsWith("rep:")).length,lastModified:i["jcr:content"]?.["cq:lastModified"]||""})),totalCount:s.total||p.length,limit:o,offset:r},"listExperienceFragments")},"listExperienceFragments")}async manageExperienceFragment(c){const{action:e}=c;switch(e){case"create":return this.createExperienceFragment(c);case"update":return this.updateExperienceFragment(c);case"delete":return this.deleteExperienceFragment(c);default:throw l(g.INVALID_PARAMETERS,`Invalid action: ${e}. Must be "create", "update", or "delete".`)}}async createExperienceFragment(c){const{parentPath:e,title:n,template:o,description:r,tags:a,name:s}=c;if(!e||!n||!o)throw l(g.INVALID_PARAMETERS,"create requires parentPath, title, and template");const p=s||n.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),i=`${e}/${p}`;return d(async()=>{const t=new URLSearchParams;t.append("./jcr:primaryType","cq:Page"),t.append("./jcr:content/jcr:primaryType","cq:PageContent"),t.append("./jcr:content/jcr:title",n),t.append("./jcr:content/sling:resourceType","cq/experience-fragments/components/experiencefragment"),t.append("./jcr:content/cq:template",o),r&&t.append("./jcr:content/jcr:description",r),a?.length&&a.forEach(h=>t.append("./jcr:content/cq:tags",h)),await this.fetch.post(i,t);const f=new URLSearchParams;return f.append("./jcr:primaryType","cq:Page"),f.append("./jcr:content/jcr:primaryType","cq:PageContent"),f.append("./jcr:content/jcr:title","Master"),f.append("./jcr:content/sling:resourceType","cq/experience-fragments/components/xfpage"),f.append("./jcr:content/cq:xfVariantType","web"),await this.fetch.post(`${i}/master`,f),m({action:"create",path:i,title:n,previewUrl:this.getPreviewUrl(i)},"manageExperienceFragment")},"createExperienceFragment")}async updateExperienceFragment(c){const{xfPath:e,title:n,description:o,tags:r}=c;if(!e)throw l(g.INVALID_PARAMETERS,"update requires xfPath");return d(async()=>{const a=new URLSearchParams;return n&&a.append("./jcr:content/jcr:title",n),o&&a.append("./jcr:content/jcr:description",o),r?.length&&r.forEach(s=>a.append("./jcr:content/cq:tags",s)),await this.fetch.post(e,a),m({action:"update",path:e},"manageExperienceFragment")},"updateExperienceFragment")}async deleteExperienceFragment(c){const{xfPath:e,force:n}=c;if(!e)throw l(g.INVALID_PARAMETERS,"delete requires xfPath");return d(async()=>{if(!n)try{const a=(await this.fetch.get(`${e}.references.json`))?.pages?.filter(s=>s.path!==e)||[];if(a.length>0)throw l(g.INVALID_PARAMETERS,`Cannot delete: XF is referenced by ${a.length} page(s): ${a.map(s=>s.path).join(", ")}. Use force=true to delete anyway.`)}catch(r){if(r.code===g.INVALID_PARAMETERS)throw r;j.warn(`Could not check references for ${e}: ${r.message}`)}const o=new URLSearchParams;return o.append(":operation","delete"),await this.fetch.post(e,o),m({action:"delete",path:e},"manageExperienceFragment")},"deleteExperienceFragment")}async manageExperienceFragmentVariation(c){const{action:e,xfPath:n,variationName:o,variationType:r="web",title:a,template:s,force:p}=c,i=`${n}/${o}`;return d(async()=>{switch(e){case"create":{if(!a)throw l(g.INVALID_PARAMETERS,"create requires title");const t=new URLSearchParams;return t.append("./jcr:primaryType","cq:Page"),t.append("./jcr:content/jcr:primaryType","cq:PageContent"),t.append("./jcr:content/jcr:title",a),t.append("./jcr:content/sling:resourceType","cq/experience-fragments/components/xfpage"),t.append("./jcr:content/cq:xfVariantType",r),s&&t.append("./jcr:content/cq:template",s),await this.fetch.post(i,t),m({action:"create",xfPath:n,variationName:o,variationPath:i,variationType:r,title:a},"manageExperienceFragmentVariation")}case"update":{const t=new URLSearchParams;return a&&t.append("./jcr:content/jcr:title",a),r&&t.append("./jcr:content/cq:xfVariantType",r),await this.fetch.post(i,t),m({action:"update",xfPath:n,variationName:o,variationPath:i},"manageExperienceFragmentVariation")}case"delete":{const t=new URLSearchParams;return t.append(":operation","delete"),await this.fetch.post(i,t),m({action:"delete",xfPath:n,variationName:o,variationPath:i},"manageExperienceFragmentVariation")}default:throw l(g.INVALID_PARAMETERS,`Invalid action: ${e}. Must be "create", "update", or "delete".`)}},"manageExperienceFragmentVariation")}}