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'; /** * Migrates npmextra.json from old namespace keys to new package-scoped keys */ const migrateNamespaceKeys = (npmextraJson: any): boolean => { let migrated = false; const migrations = [ { oldKey: 'gitzone', newKey: '@git.zone/cli' }, { oldKey: 'tsdoc', newKey: '@git.zone/tsdoc' }, { oldKey: 'npmdocker', newKey: '@git.zone/tsdocker' }, { oldKey: 'npmci', newKey: '@ship.zone/szci' }, { oldKey: 'szci', newKey: '@ship.zone/szci' }, ]; for (const { oldKey, newKey } of migrations) { if (npmextraJson[oldKey]) { if (!npmextraJson[newKey]) { // New key doesn't exist - simple rename npmextraJson[newKey] = npmextraJson[oldKey]; } else { // New key exists - merge old into new (old values don't overwrite new) npmextraJson[newKey] = { ...npmextraJson[oldKey], ...npmextraJson[newKey], }; } delete npmextraJson[oldKey]; migrated = true; } } return migrated; }; /** * Migrates npmAccessLevel from @ship.zone/szci to @git.zone/cli.release.accessLevel */ const migrateAccessLevel = (npmextraJson: any): boolean => { const szciConfig = npmextraJson['@ship.zone/szci']; if (!szciConfig?.npmAccessLevel) { return false; } const gitzoneConfig = npmextraJson['@git.zone/cli'] || {}; if (gitzoneConfig?.release?.accessLevel) { delete szciConfig.npmAccessLevel; return true; } if (!npmextraJson['@git.zone/cli']) { npmextraJson['@git.zone/cli'] = {}; } if (!npmextraJson['@git.zone/cli'].release) { npmextraJson['@git.zone/cli'].release = {}; } npmextraJson['@git.zone/cli'].release.accessLevel = szciConfig.npmAccessLevel; delete szciConfig.npmAccessLevel; return true; }; export class NpmextraFormatter extends BaseFormatter { get name(): string { return 'npmextra'; } async analyze(): Promise { const changes: IPlannedChange[] = []; const npmextraPath = 'npmextra.json'; // Check if file exists const exists = await plugins.smartfs.file(npmextraPath).exists(); if (!exists) { logVerbose('npmextra.json does not exist, skipping'); return changes; } // Read current content const currentContent = (await plugins.smartfs .file(npmextraPath) .encoding('utf8') .read()) as string; // Parse and compute new content const npmextraJson = JSON.parse(currentContent); // Apply migrations (these are automatic, non-interactive) migrateNamespaceKeys(npmextraJson); migrateAccessLevel(npmextraJson); // Ensure namespaces exist if (!npmextraJson['@git.zone/cli']) { npmextraJson['@git.zone/cli'] = {}; } if (!npmextraJson['@ship.zone/szci']) { npmextraJson['@ship.zone/szci'] = {}; } const newContent = JSON.stringify(npmextraJson, null, 2); // Only add change if content differs if (newContent !== currentContent) { changes.push({ type: 'modify', path: npmextraPath, module: this.name, description: 'Migrate and format npmextra.json', content: newContent, }); } return changes; } async applyChange(change: IPlannedChange): Promise { if (change.type !== 'modify' || !change.content) return; // Parse the content to check for missing required fields const npmextraJson = 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(); for (const expectedRepoInformationItem of expectedRepoInformation) { if ( !plugins.smartobject.smartGet( npmextraJson['@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( npmextraJson['@git.zone/cli'], expectedRepoInformationItem, cliProvidedValue, ); } } // Write the final content const finalContent = JSON.stringify(npmextraJson, null, 2); await this.modifyFile(change.path, finalContent); logger.log('info', 'Updated npmextra.json'); } }