digitalpages-api-client.js•9.72 kB
/**
* @document DigitalPages API Client for EuConquisto Platform Integration
* @version 1.0.0
* @status active
* @author Claude Code
* @created 2025-07-01
* @description Complete DigitalPages API integration for server-side composition persistence
*/
import fetch from 'node-fetch';
export class DigitalPagesAPIClient {
constructor(jwtToken) {
this.jwtToken = jwtToken;
this.config = {
BASE_URL: 'https://api.digitalpages.com.br',
DYNAMIC_CONTENT_URL: 'https://dynamic-content.euconquisto.com',
PROJECT_UID: '36c92686-c494-ec11-a22a-dc984041c95d',
CONNECTOR_UID: '93c952c2-680c-ed11-bd6e-dc98407f3f93',
PROJECT_KEY: 'e3894d14dbb743d78a7efc5819edc52e',
API_ENV: 'prd'
};
}
/**
* Validate user authentication
* @returns {Promise<Object>} User validation response
*/
async validateUser() {
try {
const response = await fetch(`${this.config.BASE_URL}/auth/v1.0/user/me`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.jwtToken}`,
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`User validation failed: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('❌ User validation error:', error);
throw error;
}
}
/**
* Validate project access
* @returns {Promise<Object>} Project validation response
*/
async validateProject() {
try {
const response = await fetch(`${this.config.BASE_URL}/auth/v1.0/project/uid/${this.config.PROJECT_UID}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.jwtToken}`,
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Project validation failed: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('❌ Project validation error:', error);
throw error;
}
}
/**
* Validate connector access
* @returns {Promise<Object>} Connector validation response
*/
async validateConnector() {
try {
const response = await fetch(`${this.config.BASE_URL}/auth/v1.1/connector/uid/${this.config.CONNECTOR_UID}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.jwtToken}`,
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Connector validation failed: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('❌ Connector validation error:', error);
throw error;
}
}
/**
* Generate composition UID
* @param {Object} composition - Composition data
* @returns {string} Base64/gzip encoded UID
*/
generateCompositionUid(composition) {
// For now, generate a unique identifier
// In production, this should match the UID encoding pattern from network traffic
const timestamp = Date.now();
const random = Math.random().toString(36).substring(2, 15);
return `composition-${timestamp}-${random}`;
}
/**
* Save composition to DigitalPages API
* @param {Object} composition - Composition data to save
* @returns {Promise<Object>} Save response with composition details
*/
async saveComposition(composition) {
try {
console.log('💾 Saving composition to DigitalPages API...');
// Generate composition UID
const compositionUid = this.generateCompositionUid(composition);
// Prepare the API endpoint
const saveUrl = `${this.config.BASE_URL}/storage/v1.0/content/versions/dynamic`;
const params = new URLSearchParams({
manual_project_uid: this.config.PROJECT_UID,
uid: compositionUid
});
// Make the POST request
const response = await fetch(`${saveUrl}?${params}`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.jwtToken}`,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
...composition,
metadata: {
...composition.metadata,
projectUid: this.config.PROJECT_UID,
connectorUid: this.config.CONNECTOR_UID,
contentType: 'digitalpages/composer',
apiEnv: this.config.API_ENV
}
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Composition save failed: ${response.status} - ${errorText}`);
}
const result = await response.json();
console.log('✅ Composition saved successfully');
console.log(`📍 Composition UID: ${compositionUid}`);
return {
success: true,
compositionUid: compositionUid,
response: result,
timestamp: new Date().toISOString()
};
} catch (error) {
console.error('❌ Composition save error:', error);
return {
success: false,
error: error.message,
timestamp: new Date().toISOString()
};
}
}
/**
* Verify composition was saved successfully
* @param {string} compositionUid - UID of the composition to verify
* @returns {Promise<Object>} Verification response
*/
async verifyComposition(compositionUid) {
try {
console.log('🔍 Verifying composition persistence...');
const verifyUrl = `${this.config.BASE_URL}/storage/v1.0/content/versions/`;
const params = new URLSearchParams({
uid: compositionUid
});
const response = await fetch(`${verifyUrl}?${params}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.jwtToken}`,
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Verification failed: ${response.status}`);
}
const result = await response.json();
console.log('✅ Composition verified successfully');
return {
success: true,
verified: true,
data: result,
timestamp: new Date().toISOString()
};
} catch (error) {
console.error('❌ Verification error:', error);
return {
success: false,
verified: false,
error: error.message,
timestamp: new Date().toISOString()
};
}
}
/**
* Retrieve composition content
* @param {string} compositionUid - UID of the composition to retrieve
* @returns {Promise<Object>} Composition content
*/
async getComposition(compositionUid) {
try {
const contentUrl = `${this.config.BASE_URL}/storage/v1.0/content`;
const params = new URLSearchParams({
uid: compositionUid,
access_token: this.jwtToken,
project_key: this.config.PROJECT_KEY,
api_env: this.config.API_ENV
});
const response = await fetch(`${contentUrl}?${params}`, {
method: 'GET',
headers: {
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Content retrieval failed: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('❌ Content retrieval error:', error);
throw error;
}
}
/**
* Generate permanent composition URL
* @param {string} compositionUid - UID of the composition
* @returns {string} Permanent URL for the composition
*/
generatePermanentUrl(compositionUid) {
// Generate the permanent URL based on the dynamic content pattern
const directoryUid = this.config.PROJECT_UID.substring(0, 8); // Example extraction
const stateHash = Date.now().toString(36); // Example state hash
return `${this.config.DYNAMIC_CONTENT_URL}/storage/v1.0/content/instance/uid/${compositionUid}/d/${directoryUid}/p/${this.config.PROJECT_UID}/state/${stateHash}/path/`;
}
/**
* Complete workflow: validate, save, and verify composition
* @param {Object} composition - Composition data
* @returns {Promise<Object>} Complete workflow result
*/
async saveAndVerifyComposition(composition) {
try {
console.log('🚀 Starting complete DigitalPages API workflow...');
// Step 1: Validate authentication
console.log('🔐 Validating authentication...');
await this.validateUser();
await this.validateProject();
// Step 2: Save composition
console.log('💾 Saving composition...');
const saveResult = await this.saveComposition(composition);
if (!saveResult.success) {
throw new Error(`Save failed: ${saveResult.error}`);
}
// Step 3: Verify persistence
console.log('🔍 Verifying persistence...');
const verifyResult = await this.verifyComposition(saveResult.compositionUid);
// Step 4: Generate permanent URL
const permanentUrl = this.generatePermanentUrl(saveResult.compositionUid);
console.log('✅ Complete workflow successful');
console.log(`🌐 Permanent URL: ${permanentUrl}`);
return {
success: true,
compositionUid: saveResult.compositionUid,
permanentUrl: permanentUrl,
saveResult: saveResult,
verifyResult: verifyResult,
timestamp: new Date().toISOString()
};
} catch (error) {
console.error('❌ Complete workflow error:', error);
return {
success: false,
error: error.message,
timestamp: new Date().toISOString()
};
}
}
}
export default DigitalPagesAPIClient;