aem-client.ts•11.6 kB
import axios, { AxiosInstance } from 'axios';
import FormData from 'form-data';
import * as fs from 'fs';
import { promisify } from 'util';
export interface AEMConfig {
host: string;
port: number;
username: string;
password: string;
protocol?: string;
}
export class AEMClient {
private axiosInstance: AxiosInstance;
constructor() {
this.axiosInstance = axios.create({
timeout: 30000,
validateStatus: () => true, // Don't throw on HTTP error status codes
});
}
private getBaseUrl(config: AEMConfig): string {
const protocol = config.protocol || 'http';
return `${protocol}://${config.host}:${config.port}`;
}
private getAuthHeader(config: AEMConfig): string {
const credentials = Buffer.from(`${config.username}:${config.password}`).toString('base64');
return `Basic ${credentials}`;
}
async checkStatus(config: AEMConfig): Promise<any> {
const baseUrl = this.getBaseUrl(config);
const authHeader = this.getAuthHeader(config);
try {
const response = await this.axiosInstance.get(`${baseUrl}/system/console/bundles.json`, {
headers: {
'Authorization': authHeader,
},
});
if (response.status === 200) {
const data = response.data;
console.log('AEM Status Data:', data);
return {
status: 'running',
totalBundles: data.s?.length || 0,
activeBundles: data.s?.filter((bundle: any) => bundle.state === 'Active').length || 0,
version: await this.getAEMVersion(config),
};
} else {
return {
status: 'error',
message: `HTTP ${response.status}: ${response.statusText}`,
};
}
} catch (error) {
return {
status: 'offline',
message: error instanceof Error ? error.message : 'Unknown error',
};
}
}
async getAEMVersion(config: AEMConfig): Promise<string> {
const baseUrl = this.getBaseUrl(config);
const authHeader = this.getAuthHeader(config);
try {
const response = await this.axiosInstance.get(`${baseUrl}/system/console/status-productinfo.json`, {
headers: {
'Authorization': authHeader,
},
});
if (response.status === 200 && response.data) {
return response.data.productVersion || 'Unknown';
}
} catch (error) {
// Fallback method
try {
const response = await this.axiosInstance.get(`${baseUrl}/libs/granite/core/content/login.html`, {
headers: {
'Authorization': authHeader,
},
});
if (response.status === 200) {
const versionMatch = response.data.match(/Adobe Experience Manager (\d+\.\d+)/);
return versionMatch ? versionMatch[1] : 'Unknown';
}
} catch (fallbackError) {
// Ignore fallback errors
}
}
return 'Unknown';
}
async installPackage(config: AEMConfig, packagePath: string, force: boolean = false): Promise<any> {
const baseUrl = this.getBaseUrl(config);
const authHeader = this.getAuthHeader(config);
const readFile = promisify(fs.readFile);
const access = promisify(fs.access);
try {
// Check if file exists
await access(packagePath, fs.constants.F_OK);
} catch (error) {
throw new Error(`Package file not found: ${packagePath}`);
}
try {
// Read the file as buffer instead of using createReadStream
const fileBuffer = await readFile(packagePath);
const formData = new FormData();
formData.append('file', fileBuffer, {
filename: packagePath.split(/[/\\]/).pop() || 'package.zip',
contentType: 'application/zip'
});
formData.append('force', force.toString());
formData.append('install', 'true');
const response = await this.axiosInstance.post(
`${baseUrl}/crx/packmgr/service.jsp`,
formData,
{
headers: {
'Authorization': authHeader,
...formData.getHeaders(),
},
}
);
if (response.status === 200) {
return {
success: true,
message: 'Package installed successfully',
response: response.data,
};
} else {
return {
success: false,
message: `Installation failed: HTTP ${response.status}`,
response: response.data,
};
}
} catch (error) {
throw new Error(`Package installation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
async listPackages(config: AEMConfig): Promise<any> {
const baseUrl = this.getBaseUrl(config);
const authHeader = this.getAuthHeader(config);
try {
const response = await this.axiosInstance.get(`${baseUrl}/crx/packmgr/list.jsp`, {
headers: {
'Authorization': authHeader,
},
});
if (response.status === 200) {
return {
success: true,
packages: response.data,
};
} else {
return {
success: false,
message: `Failed to list packages: HTTP ${response.status}`,
};
}
} catch (error) {
throw new Error(`Failed to list packages: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
async createPage(config: AEMConfig, parentPath: string, pageName: string, pageTitle: string, template: string): Promise<any> {
const baseUrl = this.getBaseUrl(config);
const authHeader = this.getAuthHeader(config);
const formData = new FormData();
formData.append('cmd', 'createPage');
formData.append('parentPath', parentPath);
formData.append('title', pageTitle);
formData.append('label', pageName);
formData.append('template', template);
try {
const response = await this.axiosInstance.post(
`${baseUrl}/bin/wcmcommand`,
formData,
{
headers: {
'Authorization': authHeader,
...formData.getHeaders(),
},
}
);
if (response.status === 200 || response.status === 201) {
return {
success: true,
message: `Page created successfully at ${parentPath}/${pageName}`,
path: `${parentPath}/${pageName}`,
};
} else {
return {
success: false,
message: `Page creation failed: HTTP ${response.status}`,
response: response.data,
};
}
} catch (error) {
throw new Error(`Page creation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
async replicateContent(config: AEMConfig, contentPath: string, action: string = 'activate'): Promise<any> {
const baseUrl = this.getBaseUrl(config);
const authHeader = this.getAuthHeader(config);
const formData = new FormData();
formData.append('cmd', action);
formData.append('path', contentPath);
try {
const response = await this.axiosInstance.post(
`${baseUrl}/bin/replicate.json`,
formData,
{
headers: {
'Authorization': authHeader,
...formData.getHeaders(),
},
}
);
if (response.status === 200) {
return {
success: true,
message: `Content ${action}d successfully: ${contentPath}`,
response: response.data,
};
} else {
return {
success: false,
message: `Replication failed: HTTP ${response.status}`,
response: response.data,
};
}
} catch (error) {
throw new Error(`Replication failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
async queryContent(config: AEMConfig, query: string, type: string = 'JCR-SQL2', limit: number = 20): Promise<any> {
const baseUrl = this.getBaseUrl(config);
const authHeader = this.getAuthHeader(config);
const params = new URLSearchParams();
params.append('query', query);
params.append('type', type);
params.append('p.limit', limit.toString());
try {
const response = await this.axiosInstance.get(
`${baseUrl}/bin/querybuilder.json?${params.toString()}`,
{
headers: {
'Authorization': authHeader,
},
}
);
if (response.status === 200) {
return {
success: true,
results: response.data,
};
} else {
return {
success: false,
message: `Query failed: HTTP ${response.status}`,
};
}
} catch (error) {
throw new Error(`Query failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
async getBundleStatus(config: AEMConfig, bundleId?: string): Promise<any> {
const baseUrl = this.getBaseUrl(config);
const authHeader = this.getAuthHeader(config);
try {
const url = bundleId
? `${baseUrl}/system/console/bundles/${bundleId}.json`
: `${baseUrl}/system/console/bundles.json`;
const response = await this.axiosInstance.get(url, {
headers: {
'Authorization': authHeader,
},
});
if (response.status === 200) {
return {
success: true,
bundles: response.data,
};
} else {
return {
success: false,
message: `Failed to get bundle status: HTTP ${response.status}`,
};
}
} catch (error) {
throw new Error(`Failed to get bundle status: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
async clearCache(config: AEMConfig, cacheType: string = 'all'): Promise<any> {
const baseUrl = this.getBaseUrl(config);
const authHeader = this.getAuthHeader(config);
const results: any[] = [];
try {
if (cacheType === 'clientlibs' || cacheType === 'all') {
// Clear client libraries cache
const clientlibsResponse = await this.axiosInstance.post(
`${baseUrl}/libs/granite/ui/content/dumplibs.rebuild.html`,
{},
{
headers: {
'Authorization': authHeader,
},
}
);
results.push({
type: 'clientlibs',
success: clientlibsResponse.status === 200,
message: clientlibsResponse.status === 200 ? 'Client libraries cache cleared' : 'Failed to clear client libraries cache',
});
}
if (cacheType === 'dispatcher' || cacheType === 'all') {
// Invalidate dispatcher cache (if available)
try {
const dispatcherResponse = await this.axiosInstance.post(
`${baseUrl}/dispatcher/invalidate.cache`,
{},
{
headers: {
'Authorization': authHeader,
},
}
);
results.push({
type: 'dispatcher',
success: dispatcherResponse.status === 200,
message: dispatcherResponse.status === 200 ? 'Dispatcher cache invalidated' : 'Failed to invalidate dispatcher cache',
});
} catch (error) {
results.push({
type: 'dispatcher',
success: false,
message: 'Dispatcher cache invalidation not available or failed',
});
}
}
return {
success: true,
results: results,
};
} catch (error) {
throw new Error(`Cache clearing failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
}