2026-04-07 21:02:37 +00:00
|
|
|
/// <reference types="node" />
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* dcrouter migration runner.
|
|
|
|
|
*
|
|
|
|
|
* Uses @push.rocks/smartmigration via dynamic import so smartmigration's type
|
|
|
|
|
* chain (which pulls in mongodb 7.x and related types) doesn't leak into
|
|
|
|
|
* compile-time type checking for this folder.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** Matches the subset of IMigrationRunResult we actually log. */
|
|
|
|
|
export interface IMigrationRunResult {
|
|
|
|
|
stepsApplied: Array<unknown>;
|
|
|
|
|
wasFreshInstall: boolean;
|
|
|
|
|
currentVersionBefore: string | null;
|
|
|
|
|
currentVersionAfter: string;
|
|
|
|
|
totalDurationMs: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface IMigrationRunner {
|
|
|
|
|
run(): Promise<IMigrationRunResult>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a configured SmartMigration runner with all dcrouter migration steps registered.
|
|
|
|
|
*
|
|
|
|
|
* Call `.run()` on the returned instance at startup (after DcRouterDb is ready,
|
|
|
|
|
* before any service that reads migrated collections).
|
|
|
|
|
*
|
|
|
|
|
* @param db - The initialized SmartdataDb instance from DcRouterDb.getDb()
|
|
|
|
|
* @param targetVersion - The current app version (from commitinfo.version)
|
|
|
|
|
*/
|
|
|
|
|
export async function createMigrationRunner(
|
|
|
|
|
db: unknown,
|
|
|
|
|
targetVersion: string,
|
|
|
|
|
): Promise<IMigrationRunner> {
|
|
|
|
|
const sm = await import('@push.rocks/smartmigration');
|
|
|
|
|
const migration = new sm.SmartMigration({
|
|
|
|
|
targetVersion,
|
|
|
|
|
db: db as any,
|
|
|
|
|
// Brand-new installs skip all migrations and stamp directly to the current version.
|
|
|
|
|
freshInstallVersion: targetVersion,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Register steps in execution order. Each step's .from() must match the
|
|
|
|
|
// previous step's .to() to form a contiguous chain.
|
|
|
|
|
migration
|
|
|
|
|
.step('rename-target-profile-host-to-ip')
|
|
|
|
|
.from('13.0.11').to('13.1.0')
|
|
|
|
|
.description('Rename ITargetProfileTarget.host → ip on all target profiles')
|
|
|
|
|
.up(async (ctx) => {
|
|
|
|
|
const collection = ctx.mongo!.collection('targetprofiledoc');
|
|
|
|
|
const cursor = collection.find({ 'targets.host': { $exists: true } });
|
|
|
|
|
let migrated = 0;
|
|
|
|
|
for await (const doc of cursor) {
|
|
|
|
|
const targets = ((doc as any).targets || []).map((t: any) => {
|
|
|
|
|
if (t && typeof t === 'object' && 'host' in t && !('ip' in t)) {
|
|
|
|
|
const { host, ...rest } = t;
|
|
|
|
|
return { ...rest, ip: host };
|
|
|
|
|
}
|
|
|
|
|
return t;
|
|
|
|
|
});
|
|
|
|
|
await collection.updateOne({ _id: (doc as any)._id }, { $set: { targets } });
|
|
|
|
|
migrated++;
|
|
|
|
|
}
|
|
|
|
|
ctx.log.log('info', `rename-target-profile-host-to-ip: migrated ${migrated} profile(s)`);
|
2026-04-08 14:54:49 +00:00
|
|
|
})
|
|
|
|
|
.step('rename-domain-source-manual-to-dcrouter')
|
|
|
|
|
.from('13.1.0').to('13.8.1')
|
|
|
|
|
.description('Rename DomainDoc.source value from "manual" to "dcrouter"')
|
|
|
|
|
.up(async (ctx) => {
|
|
|
|
|
const collection = ctx.mongo!.collection('domaindoc');
|
|
|
|
|
const result = await collection.updateMany(
|
|
|
|
|
{ source: 'manual' },
|
|
|
|
|
{ $set: { source: 'dcrouter' } },
|
|
|
|
|
);
|
|
|
|
|
ctx.log.log(
|
|
|
|
|
'info',
|
|
|
|
|
`rename-domain-source-manual-to-dcrouter: migrated ${result.modifiedCount} domain(s)`,
|
|
|
|
|
);
|
|
|
|
|
})
|
|
|
|
|
.step('rename-record-source-manual-to-local')
|
|
|
|
|
.from('13.8.1').to('13.8.2')
|
|
|
|
|
.description('Rename DnsRecordDoc.source value from "manual" to "local"')
|
|
|
|
|
.up(async (ctx) => {
|
|
|
|
|
const collection = ctx.mongo!.collection('dnsrecorddoc');
|
|
|
|
|
const result = await collection.updateMany(
|
|
|
|
|
{ source: 'manual' },
|
|
|
|
|
{ $set: { source: 'local' } },
|
|
|
|
|
);
|
|
|
|
|
ctx.log.log(
|
|
|
|
|
'info',
|
|
|
|
|
`rename-record-source-manual-to-local: migrated ${result.modifiedCount} record(s)`,
|
|
|
|
|
);
|
2026-04-07 21:02:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return migration;
|
|
|
|
|
}
|