| name | maintainx-upgrade-migration |
| description | Migrate MaintainX API versions and handle breaking changes.
Use when upgrading API versions, handling deprecations,
or migrating between MaintainX API releases.
Trigger with phrases like "maintainx upgrade", "maintainx api version",
"maintainx migration", "maintainx breaking changes", "maintainx deprecation".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*), Grep |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
MaintainX Upgrade & Migration
Overview
Guide for handling MaintainX API version upgrades, deprecations, and breaking changes in your integrations.
Prerequisites
- Existing MaintainX integration
- Understanding of current API usage
- Test environment available
Migration Planning
Step 1: Assess Current Usage
interface ApiUsageReport {
endpoints: Map<string, number>;
methods: Map<string, number>;
fields: Map<string, Set<string>>;
deprecations: string[];
}
async function analyzeApiUsage(logFile: string): Promise<ApiUsageReport> {
const fs = require('fs');
const logs = JSON.parse(fs.readFileSync(logFile, 'utf8'));
const report: ApiUsageReport = {
endpoints: new Map(),
methods: new Map(),
fields: new Map(),
deprecations: [],
};
logs.forEach((log: any) => {
const endpoint = log.url?.replace(/\/[a-z0-9_-]+$/i, '/:id');
if (endpoint) {
report.endpoints.set(endpoint, (report.endpoints.get(endpoint) || 0) + 1);
}
if (log.method) {
report.methods.set(log.method, (report.methods.get(log.method) || 0) + 1);
}
if (log.requestBody) {
const fields = Object.keys(log.requestBody);
const endpointFields = report.fields.get(endpoint) || new Set();
fields.forEach(f => endpointFields.add(f));
report.fields.set(endpoint, endpointFields);
}
if (log.responseHeaders?.['x-deprecation-warning']) {
report.deprecations.push(log.responseHeaders['x-deprecation-warning']);
}
});
return report;
}
async function printUsageReport() {
const report = await analyzeApiUsage('./logs/api-requests.json');
console.log('=== MaintainX API Usage Analysis ===\n');
console.log('Endpoints Used:');
report.endpoints.forEach((count, endpoint) => {
console.log(` ${endpoint}: ${count} calls`);
});
console.log('\nHTTP Methods:');
report.methods.forEach((count, method) => {
console.log(` ${method}: ${count} calls`);
});
console.log('\nFields by Endpoint:');
report.fields.forEach((fields, endpoint) => {
console.log(` ${endpoint}: ${[...fields].join(', ')}`);
});
if (report.deprecations.length > 0) {
console.log('\nDeprecation Warnings:');
[...new Set(report.deprecations)].forEach(d => {
console.log(` - ${d}`);
});
}
}
Step 2: Version Compatibility Layer
type ApiVersion = 'v1' | 'v2';
interface VersionAdapter {
transformRequest(data: any): any;
transformResponse(data: any): any;
getBaseUrl(): string;
}
class V1Adapter implements VersionAdapter {
getBaseUrl(): string {
return 'https://api.getmaintainx.com/v1';
}
transformRequest(data: any): any {
return data;
}
transformResponse(data: any): any {
return data;
}
}
class V2Adapter implements VersionAdapter {
getBaseUrl(): string {
return 'https://api.getmaintainx.com/v2';
}
transformRequest(data: ): {
transformed = { ...data };
(transformed.) {
transformed. = transformed.;
transformed.;
}
(transformed.) {
: <, > = {
: ,
: ,
: ,
: ,
};
transformed. = priorityMap[transformed.] || transformed.;
}
transformed;
}
(: ): {
transformed = { ...data };
(transformed.) {
transformed. = transformed.;
transformed.;
}
(transformed.) {
: <, > = {
: ,
: ,
: ,
: ,
};
transformed. = priorityMap[transformed.] || transformed.;
}
transformed;
}
}
(): {
(version) {
:
();
:
:
();
}
}
{
: ;
: ;
() {
. = (version);
. = axios.({
: ..(),
: {
: ,
: ,
},
});
}
() {
transformedRequest = ..(data);
response = ..(, transformedRequest);
..(response.);
}
}
Step 3: Feature Flag for Gradual Migration
interface FeatureFlags {
useV2Api: boolean;
useNewWorkOrderFormat: boolean;
enableBetaFeatures: boolean;
}
function getFeatureFlags(): FeatureFlags {
return {
useV2Api: process.env.USE_V2_API === 'true',
useNewWorkOrderFormat: process.env.USE_NEW_WO_FORMAT === 'true',
enableBetaFeatures: process.env.ENABLE_BETA === 'true',
};
}
class MigratableMaintainXClient {
private v1Client: MaintainXClient;
private v2Client?: MaintainXClient;
private flags: FeatureFlags;
constructor() {
this.flags = getFeatureFlags();
this.v1Client = new MaintainXClient();
if (this.flags.useV2Api) {
}
}
() {
(.. && .) {
..(data);
}
..(data);
}
}
Step 4: Migration Testing
describe('API Migration Tests', () => {
describe('Request Transformation', () => {
it('should transform V1 work order to V2 format', () => {
const v1Data = {
title: 'Test Work Order',
priority: 'HIGH',
assignees: ['user1', 'user2'],
};
const adapter = new V2Adapter();
const v2Data = adapter.transformRequest(v1Data);
expect(v2Data.title).toBe('Test Work Order');
expect(v2Data.priority).toBe('P1');
expect(v2Data.assigned_users).toEqual(['user1', 'user2']);
expect(v2Data.assignees).toBeUndefined();
});
});
describe('Response Transformation', () => {
it('should transform V2 response to V1 format', () => {
const v2Response = {
id: 'wo_123',
: ,
: ,
: [],
};
adapter = ();
v1Response = adapter.(v2Response);
(v1Response.).();
(v1Response.).([]);
(v1Response.).();
});
});
(, {
(, () => {
v1Client = ();
v1WorkOrders = v1Client.({ : });
});
});
});
Step 5: Rollback Plan
interface RollbackStep {
name: string;
execute: () => Promise<void>;
}
const rollbackSteps: RollbackStep[] = [
{
name: 'Disable V2 API flag',
execute: async () => {
console.log('Setting USE_V2_API=false');
},
},
{
name: 'Restart services',
execute: async () => {
console.log('Restarting services to pick up flag change');
},
},
{
name: 'Verify V1 API usage',
execute: async () => {
console.log('Verifying API calls are using V1');
},
},
{
name: 'Monitor for errors',
execute: async () => {
console.log('Monitoring error rates...');
},
},
];
async () {
.();
( step rollbackSteps) {
.();
{
step.();
.();
} (: ) {
.();
.();
process.();
}
}
.();
}
Migration Checklist
Output
- API usage analysis report
- Version compatibility layer
- Feature flag configuration
- Migration tests passing
- Rollback procedure documented
Resources
Next Steps
For CI/CD integration, see maintainx-ci-integration.