UNPKG

aem-mcp-server

Version:

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

2 lines (1 loc) 9.08 kB
"use strict";import{createSuccessResponse as d,safeExecute as p,createAEMError as m,AEM_ERROR_CODES as l}from"./aem.errors.js";import{mergeJsonString as u,JsonMergeError as y}from"./aem.json-merge.js";export class ContentFragmentManager{fetch;isAEMaaCS;constructor(t,n){this.fetch=t,this.isAEMaaCS=n}async getContentFragment(t){return p(async()=>{if(this.isAEMaaCS){const n=await this.fetch.get("/adobe/sites/cf/fragments",{path:t}),e=n.items?.[0]||n;return d(this.normalizeFragment(e),"getContentFragment")}else{const n=await this.fetch.get(`/api/assets${t}.json`);return d(this.normalizeFragmentFrom65(n,t),"getContentFragment")}},"getContentFragment")}normalizeFragment(t){return{path:t.path||t.id,title:t.title,model:t.model?.path||t.model,description:t.description||"",fields:this.extractFields(t),variations:this.extractVariations(t),metadata:{created:t.created?.at,modified:t.modified?.at,createdBy:t.created?.by,status:t.status}}}normalizeFragmentFrom65(t,n){const e=t.properties?.elements||{},a=t.properties?.variations||{};return{path:n,title:t.properties?.title||t.properties?.["jcr:title"]||"",model:t.properties?.["cq:model"]||"",description:t.properties?.description||"",fields:Object.entries(e).map(([r,o])=>({name:r,value:o.value??o[":value"]??"",type:o[":type"]||"text"})),variations:Object.entries(a).map(([r,o])=>({name:r,title:o.title||r,fields:Object.entries(o.elements||{}).map(([s,c])=>({name:s,value:c.value??c[":value"]??"",type:c[":type"]||"text"}))})),metadata:{created:t.properties?.["jcr:created"],modified:t.properties?.["jcr:lastModified"]||t.properties?.["cq:lastModified"],createdBy:t.properties?.["jcr:createdBy"],status:t.properties?.["cq:lastReplicationAction"]||"not published"}}}extractFields(t){const n=t.fields||t.elements||[];return Array.isArray(n)?n.map(e=>({name:e.name,value:e.values?.[0]??e.value??"",type:e.type||"text"})):Object.entries(n).map(([e,a])=>({name:e,value:a.values?.[0]??a.value??"",type:a.type||"text"}))}extractVariations(t){const n=t.variations||[];return Array.isArray(n)?n.map(e=>({name:e.name||e.id,title:e.title||e.name||"",fields:this.extractFields(e)})):Object.entries(n).map(([e,a])=>({name:e,title:a.title||e,fields:this.extractFields(a)}))}async listContentFragments(t){const{path:n,model:e,limit:a=20,offset:r=0}=t;return p(async()=>{if(this.isAEMaaCS){const o={parentPath:n,limit:a};e&&(o.modelId=e),r>0&&(o.offset=r);const s=await this.fetch.get("/adobe/sites/cf/fragments",o),c=s.items||[];return d({fragments:c.map(i=>({path:i.path||i.id,title:i.title,model:i.model?.path||i.model,modified:i.modified?.at,status:i.status})),totalCount:s.total||c.length,limit:a,offset:r},"listContentFragments")}else{const o={type:"dam:Asset",path:n,"p.limit":a,"p.offset":r,orderby:"@jcr:content/jcr:lastModified","orderby.sort":"desc"};e&&(o.property="jcr:content/data/cq:model",o["property.value"]=e);const s=await this.fetch.get("/bin/querybuilder.json",o),c=s.hits||[];return d({fragments:c.map(i=>({path:i.path,title:i["jcr:content"]?.["jcr:title"]||i.name,model:i["jcr:content"]?.data?.["cq:model"]||"",modified:i["jcr:content"]?.["jcr:lastModified"]||"",status:i["jcr:content"]?.["cq:lastReplicationAction"]||"not published"})),totalCount:s.total||c.length,limit:a,offset:r},"listContentFragments")}},"listContentFragments")}async manageContentFragment(t){const{action:n}=t;switch(n){case"create":return this.createContentFragment(t);case"update":return this.updateContentFragment(t);case"delete":return this.deleteContentFragment(t);case"mergeJsonField":return this.mergeJsonField(t);default:throw m(l.INVALID_PARAMETERS,`Invalid action: ${n}. Must be "create", "update", "delete", or "mergeJsonField".`)}}async createContentFragment(t){const{parentPath:n,title:e,model:a,fields:r,description:o,name:s}=t;if(!n||!e||!a)throw m(l.INVALID_PARAMETERS,"create requires parentPath, title, and model");const c=s||e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");return p(async()=>{if(this.isAEMaaCS){const i={title:e,model:a,description:o||""};r&&(i.fields=Object.entries(r).map(([g,h])=>({name:g,value:h})));const f=await this.fetch.post(`/adobe/sites/cf/fragments?parentPath=${encodeURIComponent(n)}&name=${encodeURIComponent(c)}`,i);return d({action:"create",path:f.path||`${n}/${c}`,title:e,model:a},"manageContentFragment")}else{const i=new URLSearchParams;if(i.append("./jcr:primaryType","dam:Asset"),i.append("./jcr:content/jcr:primaryType","dam:AssetContent"),i.append("./jcr:content/jcr:title",e),i.append("./jcr:content/data/jcr:primaryType","nt:unstructured"),i.append("./jcr:content/data/cq:model",a),o&&i.append("./jcr:content/data/description",o),r)for(const[g,h]of Object.entries(r))i.append(`./jcr:content/data/master/${g}`,String(h));const f=`${n}/${c}`;return await this.fetch.post(f,i),d({action:"create",path:f,title:e,model:a},"manageContentFragment")}},"createContentFragment")}async updateContentFragment(t){const{fragmentPath:n,fields:e,description:a,title:r,variation:o="master"}=t;if(!n)throw m(l.INVALID_PARAMETERS,"update requires fragmentPath");return p(async()=>(await this.writeFields(n,o,e||{},{title:r,description:a}),d({action:"update",path:n,variation:o},"manageContentFragment")),"updateContentFragment")}async readFieldValue(t,n,e){const r=(await this.fetch.get(`${t}/jcr:content/data/${n}.json`))?.[e];if(r==null)throw m(l.RESOURCE_NOT_FOUND,`Field "${e}" not found at ${t} (variation "${n}").`);return String(r)}async writeFields(t,n,e,a={}){const{title:r,description:o}=a;if(this.isAEMaaCS){const s={};r&&(s.title=r);const c=Object.entries(e);c.length&&(s.fields=c.map(([i,f])=>({name:i,value:f}))),n&&n!=="master"?await this.fetch.put(`/adobe/sites/cf/fragments?path=${encodeURIComponent(t)}/variations/${n}`,s):(o&&(s.description=o),await this.fetch.put(`/adobe/sites/cf/fragments?path=${encodeURIComponent(t)}`,s))}else{const s=new URLSearchParams;r&&s.append("./jcr:content/jcr:title",r),o&&s.append("./jcr:content/data/description",o);for(const[c,i]of Object.entries(e))s.append(`./jcr:content/data/${n}/${c}`,String(i));await this.fetch.post(t,s)}}async mergeJsonField(t){const{fragmentPath:n,field:e,jsonPointer:a="",merge:r,variation:o="master"}=t;if(!n||!e)throw m(l.INVALID_PARAMETERS,"mergeJsonField requires fragmentPath and field");if(!r||typeof r!="object"||Array.isArray(r)||Object.keys(r).length===0)throw m(l.INVALID_PARAMETERS,'mergeJsonField requires a non-empty "merge" object of keys to upsert');return p(async()=>{const s=await this.readFieldValue(n,o,e);let c;try{c=u(s,a,r)}catch(i){throw i instanceof y?m(l[i.code],i.message):i}return await this.writeFields(n,o,{[e]:c.result}),d({action:"mergeJsonField",path:n,variation:o,field:e,jsonPointer:a||"(root)",added:c.added,overwritten:c.overwritten,beforeKeyCount:c.beforeKeyCount,afterKeyCount:c.afterKeyCount},"manageContentFragment")},"mergeJsonField")}async deleteContentFragment(t){const{fragmentPath:n,force:e}=t;if(!n)throw m(l.INVALID_PARAMETERS,"delete requires fragmentPath");return p(async()=>{if(this.isAEMaaCS){const a=`/adobe/sites/cf/fragments?path=${encodeURIComponent(n)}${e?"&force=true":""}`;return await this.fetch.delete(a),d({action:"delete",path:n},"manageContentFragment")}else{const a=new URLSearchParams;return a.append(":operation","delete"),await this.fetch.post(n,a),d({action:"delete",path:n},"manageContentFragment")}},"deleteContentFragment")}async manageContentFragmentVariation(t){const{action:n,fragmentPath:e,variationName:a,title:r,fields:o}=t;return p(async()=>{switch(n){case"create":{if(!r)throw m(l.INVALID_PARAMETERS,"create requires title");if(this.isAEMaaCS)await this.fetch.post(`/adobe/sites/cf/fragments?path=${encodeURIComponent(e)}/variations`,{name:a,title:r,fields:o?Object.entries(o).map(([s,c])=>({name:s,value:c})):void 0});else{const s=new URLSearchParams;if(s.append("./jcr:primaryType","nt:unstructured"),s.append("./jcr:title",r),o)for(const[c,i]of Object.entries(o))s.append(`./${c}`,String(i));await this.fetch.post(`${e}/jcr:content/data/${a}`,s)}return d({action:"create",fragmentPath:e,variationName:a,title:r},"manageContentFragmentVariation")}case"update":{if(this.isAEMaaCS){const s={};r&&(s.title=r),o&&(s.fields=Object.entries(o).map(([c,i])=>({name:c,value:i}))),await this.fetch.put(`/adobe/sites/cf/fragments?path=${encodeURIComponent(e)}/variations/${a}`,s)}else{const s=new URLSearchParams;if(r&&s.append("./jcr:title",r),o)for(const[c,i]of Object.entries(o))s.append(`./${c}`,String(i));await this.fetch.post(`${e}/jcr:content/data/${a}`,s)}return d({action:"update",fragmentPath:e,variationName:a},"manageContentFragmentVariation")}case"delete":{if(this.isAEMaaCS)await this.fetch.delete(`/adobe/sites/cf/fragments?path=${encodeURIComponent(e)}/variations/${a}`);else{const s=new URLSearchParams;s.append(":operation","delete"),await this.fetch.post(`${e}/jcr:content/data/${a}`,s)}return d({action:"delete",fragmentPath:e,variationName:a},"manageContentFragmentVariation")}default:throw m(l.INVALID_PARAMETERS,`Invalid action: ${n}. Must be "create", "update", or "delete".`)}},"manageContentFragmentVariation")}}