import { BaseFormatter } from "../classes.baseformatter.js"; import type { IPlannedChange } from "../interfaces.format.js"; import * as plugins from "../mod.plugins.js"; import { logger, logVerbose } from "../../gitzone.logging.js"; import { migrateSmartconfigData } from "../../helpers.smartconfigmigrations.js"; const CONFIG_FILE = ".smartconfig.json"; export class SmartconfigFormatter extends BaseFormatter { get name(): string { return "smartconfig"; } async analyze(): Promise { const changes: IPlannedChange[] = []; // File rename (npmextra.json/smartconfig.json → .smartconfig.json) // is handled by the orchestrator before analysis. // This formatter only operates on .smartconfig.json. const exists = await plugins.smartfs.file(CONFIG_FILE).exists(); if (!exists) { logVerbose(".smartconfig.json does not exist, skipping"); return changes; } const currentContent = (await plugins.smartfs .file(CONFIG_FILE) .encoding("utf8") .read()) as string; const smartconfigJson = JSON.parse(currentContent); migrateSmartconfigData(smartconfigJson); // Ensure namespaces exist if (!smartconfigJson["@git.zone/cli"]) { smartconfigJson["@git.zone/cli"] = {}; } if (!smartconfigJson["@ship.zone/szci"]) { smartconfigJson["@ship.zone/szci"] = {}; } const newContent = JSON.stringify(smartconfigJson, null, 2); if (newContent !== currentContent) { changes.push({ type: "modify", path: CONFIG_FILE, module: this.name, description: "Migrate and format .smartconfig.json", content: newContent, }); } return changes; } async applyChange(change: IPlannedChange): Promise { if (change.type !== "modify" || !change.content) return; const smartconfigJson = JSON.parse(change.content); // Check for missing required module information const expectedRepoInformation: string[] = [ "projectType", "module.githost", "module.gitscope", "module.gitrepo", "module.description", "module.npmPackagename", "module.license", ]; const interactInstance = new plugins.smartinteract.SmartInteract(); const missingRepoInformation = expectedRepoInformation.filter( (expectedRepoInformationItem) => { return !plugins.smartobject.smartGet( smartconfigJson["@git.zone/cli"], expectedRepoInformationItem, ); }, ); if (missingRepoInformation.length > 0 && !this.context.isInteractive()) { throw new Error( `Missing required .smartconfig.json fields: ${missingRepoInformation.join(", ")}`, ); } for (const expectedRepoInformationItem of expectedRepoInformation) { if ( !plugins.smartobject.smartGet( smartconfigJson["@git.zone/cli"], expectedRepoInformationItem, ) ) { interactInstance.addQuestions([ { message: `What is the value of ${expectedRepoInformationItem}`, name: expectedRepoInformationItem, type: "input", default: "undefined variable", }, ]); } } const answerbucket = await interactInstance.runQueue(); for (const expectedRepoInformationItem of expectedRepoInformation) { const cliProvidedValue = answerbucket.getAnswerFor( expectedRepoInformationItem, ); if (cliProvidedValue) { plugins.smartobject.smartAdd( smartconfigJson["@git.zone/cli"], expectedRepoInformationItem, cliProvidedValue, ); } } const finalContent = JSON.stringify(smartconfigJson, null, 2); await this.modifyFile(change.path, finalContent); logger.log("info", "Updated .smartconfig.json"); } }