175 lines
5.0 KiB
TypeScript
175 lines
5.0 KiB
TypeScript
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<IPlannedChange[]> {
|
|
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<void> {
|
|
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');
|
|
}
|
|
}
|