2026-04-04 14:33:52 +09:00
import { existsSync , readFileSync , renameSync , rmSync } from "node:fs"
2026-03-27 15:40:04 +09:00
import { join , dirname , basename } from "node:path"
import { log } from "./logger"
2026-04-25 00:41:19 +09:00
import { getSidecarPath } from "./migration/migrations-sidecar"
2026-03-27 15:40:04 +09:00
import { CONFIG_BASENAME , LEGACY_CONFIG_BASENAME } from "./plugin-identity"
2026-04-04 14:33:52 +09:00
import { writeFileAtomically } from "./write-file-atomically"
2026-03-27 15:40:04 +09:00
function buildCanonicalPath ( legacyPath : string ) : string {
const dir = dirname ( legacyPath )
const ext = basename ( legacyPath ) . includes ( ".jsonc" ) ? ".jsonc" : ".json"
return join ( dir , ` ${ CONFIG_BASENAME } ${ ext } ` )
}
2026-04-04 01:32:31 +09:00
function archiveLegacyConfigFile ( legacyPath : string ) : boolean {
const backupPath = ` ${ legacyPath } .bak `
try {
renameSync ( legacyPath , backupPath )
log ( "[migrateLegacyConfigFile] Legacy config was migrated and renamed to backup. Update the canonical file only." , {
legacyPath ,
backupPath ,
} )
return true
} catch ( renameError ) {
try {
rmSync ( legacyPath )
log ( "[migrateLegacyConfigFile] Legacy config was migrated and removed after backup rename failed. Update the canonical file only." , {
legacyPath ,
backupPath ,
renameError ,
} )
return true
} catch ( removeError ) {
log ( "[migrateLegacyConfigFile] WARNING: canonical config was written but the legacy file still exists and will be ignored. Remove or rename it manually." , {
legacyPath ,
backupPath ,
renameError ,
removeError ,
} )
return false
}
}
}
2026-04-25 00:41:19 +09:00
function migrateLegacySidecarFile ( legacyPath : string , canonicalPath : string ) : boolean {
const legacySidecarPath = getSidecarPath ( legacyPath )
if ( ! existsSync ( legacySidecarPath ) ) return true
const canonicalSidecarPath = getSidecarPath ( canonicalPath )
if ( existsSync ( canonicalSidecarPath ) ) return true
try {
const content = readFileSync ( legacySidecarPath , "utf-8" )
writeFileAtomically ( canonicalSidecarPath , content )
log ( "[migrateLegacyConfigFile] Migrated legacy migration sidecar to canonical path" , {
from : legacySidecarPath ,
to : canonicalSidecarPath ,
} )
return true
} catch ( error ) {
log ( "[migrateLegacyConfigFile] Failed to migrate legacy migration sidecar" , {
legacySidecarPath ,
canonicalSidecarPath ,
error ,
} )
return false
}
}
2026-03-27 15:40:04 +09:00
export function migrateLegacyConfigFile ( legacyPath : string ) : boolean {
if ( ! existsSync ( legacyPath ) ) return false
if ( ! basename ( legacyPath ) . startsWith ( LEGACY_CONFIG_BASENAME ) ) return false
const canonicalPath = buildCanonicalPath ( legacyPath )
if ( existsSync ( canonicalPath ) ) return false
try {
2026-04-04 01:32:31 +09:00
const content = readFileSync ( legacyPath , "utf-8" )
writeFileAtomically ( canonicalPath , content )
2026-04-25 00:41:19 +09:00
const migratedSidecar = migrateLegacySidecarFile ( legacyPath , canonicalPath )
2026-04-04 01:32:31 +09:00
const archivedLegacyConfig = archiveLegacyConfigFile ( legacyPath )
log ( "[migrateLegacyConfigFile] Migrated legacy config to canonical path" , {
2026-03-27 15:40:04 +09:00
from : legacyPath ,
to : canonicalPath ,
2026-04-25 00:41:19 +09:00
migratedSidecar ,
2026-04-04 01:32:31 +09:00
archivedLegacyConfig ,
2026-03-27 15:40:04 +09:00
} )
2026-04-12 02:27:56 +09:00
return true
2026-03-27 15:40:04 +09:00
} catch ( error ) {
2026-04-04 01:32:31 +09:00
log ( "[migrateLegacyConfigFile] Failed to migrate legacy config file" , { legacyPath , error } )
2026-03-27 15:40:04 +09:00
return false
}
}