feat(logging): Enhance logging and module publishing with color-coded output, progress tracking, and improved CLI startup

This commit is contained in:
2025-08-08 12:06:41 +00:00
parent 9b3d77189a
commit 8a6058c421
16 changed files with 404 additions and 28 deletions

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@git.zone/tspublish',
version: '1.9.1',
version: '1.10.0',
description: 'A tool to publish multiple, concise, and small packages from monorepos, specifically for TypeScript projects within a git environment.'
}

View File

@@ -1,6 +1,6 @@
import * as plugins from './plugins.js';
import * as paths from './paths.js';
import { logger } from './logging.js';
import { logger, logInfo, logSuccess, logWarn, logError, logBuild, logPublish, logOngoing, logStart, logDone } from './logging.js';
import { type ITsPublishJson } from './interfaces/index.js';
import type { TsPublish } from './classes.tspublish.js';
@@ -66,16 +66,15 @@ export class PublishModule {
try {
packageInfo = await smartnpmInstance.getPackageInfo(this.options.name);
} catch (error) {
logger.log('warn', `package does not yet seem to exist. Proceeding in 10 seconds...`);
logWarn(`Package ${this.options.name} does not yet seem to exist. Proceeding in 10 seconds...`);
await plugins.smartdelay.delayFor(10000);
}
if (packageInfo) {
const availableVersions = packageInfo.allVersions.map((versionArg) => versionArg.version);
logger.log('info', `available versions are: ${availableVersions.toString()}`);
logInfo(`Available versions for ${this.options.name}: ${availableVersions.join(', ')}`);
if (availableVersions.includes(this.options.version)) {
logger.log(
'error',
`package ${this.options.name} already exists with version ${this.options.version}`
logError(
`Package ${this.options.name} already exists with version ${this.options.version}`
);
process.exit(1);
}
@@ -162,6 +161,7 @@ export class PublishModule {
}
public async createPublishModuleDir() {
logOngoing(`Creating publish directory for ${this.options.name}`);
this.options.publishModDirFullPath = plugins.path.join(
this.options.monoRepoDir,
`dist_publish_${this.options.packageSubFolder}`
@@ -207,10 +207,12 @@ export class PublishModule {
}
public async build() {
logBuild(`Building ${this.options.name}...`);
const smartshellInstance = new plugins.smartshell.Smartshell({
executor: 'bash',
});
await smartshellInstance.exec(`cd ${this.options.publishModDirFullPath} && pnpm run build`);
logSuccess(`Build completed for ${this.options.name}`);
}
public async createBinCliSetup() {
@@ -229,6 +231,7 @@ export class PublishModule {
}
public async publish() {
logPublish(`Publishing ${this.options.name} v${this.options.version}...`);
const smartshellInstance = new plugins.smartshell.Smartshell({
executor: 'bash',
});
@@ -242,5 +245,6 @@ export class PublishModule {
} --no-git-checks --registry https://${registryUrl}`
);
}
logSuccess(`Successfully published ${this.options.name} v${this.options.version}!`);
}
}

View File

@@ -1,4 +1,4 @@
import { logger } from './logging.js';
import { logger, logInfo, logSuccess, logWarn, logError, logHeader, logPackage, logProgress, logSeparator, logStart, logDone } from './logging.js';
import * as plugins from './plugins.js';
import * as interfaces from './interfaces/index.js';
@@ -15,24 +15,26 @@ export class TsPublish {
}
public async publish(monorepoDirArg: string) {
logHeader('TSPublish - Module Publisher');
const publishModules = await this.getModuleSubDirs(monorepoDirArg);
logger.log('info', `Found ${Object.keys(publishModules).length} publish modules:`);
logInfo(`Found ${Object.keys(publishModules).length} publish modules`);
logSeparator();
for (const publishModule of Object.keys(publishModules)) {
logger.log(
'info',
`Publishing module: ${publishModule} -> ${publishModules[publishModule].name}`
);
logPackage('Module found', `${publishModule}${publishModules[publishModule].name}`);
}
for (const publishModule of Object.keys(publishModules)) {
// lets check wether there is a name
if (!publishModules[publishModule].name) {
logger.log('warn', `no name found in tspublish.json for ${publishModule}. Skipping...`);
logWarn(`No name found in tspublish.json for ${publishModule}. Skipping...`);
continue;
}
const publishModuleInstance = new PublishModule(this, {
monoRepoDir: monorepoDirArg,
packageSubFolder: publishModule,
});
const moduleCount = Object.keys(publishModules).indexOf(publishModule) + 1;
const totalCount = Object.keys(publishModules).length;
logProgress(moduleCount, totalCount, publishModules[publishModule].name || publishModule);
await publishModuleInstance.init();
await publishModuleInstance.createPublishModuleDir();
await publishModuleInstance.build();
@@ -53,13 +55,13 @@ export class TsPublish {
continue;
}
logger.log('info', `found publish module: ${subDir}`);
logPackage('Found module', subDir);
publishModules[subDir] = JSON.parse(
plugins.smartfile.fs.toStringSync(plugins.path.join(subDir, 'tspublish.json'))
);
}
logger.log('ok', `found ${Object.keys(publishModules).length} publish modules`);
logger.log('info', `Ordering publish modules...`);
logSuccess(`Found ${Object.keys(publishModules).length} publish modules`);
logInfo('Ordering publish modules...');
return publishModules;
}

View File

@@ -1,10 +1,11 @@
import * as paths from './paths.js';
import { TsPublish } from './classes.tspublish.js';
import { logStart } from './logging.js';
export * from './classes.tspublish.js';
export const runCli = async () => {
console.log('Starting tspublish...');
logStart('tspublish');
const tspublish = new TsPublish();
await tspublish.publish(paths.cwd);
};

View File

@@ -3,3 +3,102 @@ import * as commitinfo from './00_commitinfo_data.js';
export const logger = plugins.smartlog.Smartlog.createForCommitinfo(commitinfo.commitinfo);
logger.enableConsole();
// Color-coded log level indicators
const logIcons = {
info: plugins.consolecolor.coloredString('', 'cyan'),
success: plugins.consolecolor.coloredString('✓', 'green'),
warn: plugins.consolecolor.coloredString('⚠', 'orange'),
error: plugins.consolecolor.coloredString('✖', 'red'),
start: plugins.consolecolor.coloredString('▶', 'blue'),
done: plugins.consolecolor.coloredString('✔', 'green'),
package: plugins.consolecolor.coloredString('📦', 'blue'),
build: plugins.consolecolor.coloredString('🔨', 'cyan'),
publish: plugins.consolecolor.coloredString('🚀', 'green'),
};
// Helper function for info messages with color
export const logInfo = (message: string, data?: any) => {
const coloredMessage = `${logIcons.info} ${plugins.consolecolor.coloredString(message, 'cyan')}`;
logger.log('info', coloredMessage, data);
};
// Helper function for success messages
export const logSuccess = (message: string, data?: any) => {
const coloredMessage = `${logIcons.success} ${plugins.consolecolor.coloredString(message, 'green')}`;
logger.log('ok', coloredMessage, data);
};
// Helper function for warning messages
export const logWarn = (message: string, data?: any) => {
const coloredMessage = `${logIcons.warn} ${plugins.consolecolor.coloredString(message, 'orange')}`;
logger.log('warn', coloredMessage, data);
};
// Helper function for error messages
export const logError = (message: string, data?: any) => {
const coloredMessage = `${logIcons.error} ${plugins.consolecolor.coloredString(message, 'red')}`;
logger.log('error', coloredMessage, data);
};
// Helper function for start of operations
export const logStart = (operation: string) => {
const coloredMessage = `${logIcons.start} ${plugins.consolecolor.coloredString(`Starting ${operation}...`, 'blue')}`;
logger.log('info', coloredMessage);
};
// Helper function for completion of operations
export const logDone = (operation: string) => {
const coloredMessage = `${logIcons.done} ${plugins.consolecolor.coloredString(`Completed ${operation}`, 'green')}`;
logger.log('ok', coloredMessage);
};
// Helper function for package-related messages
export const logPackage = (message: string, packageName: string) => {
const coloredMessage = `${logIcons.package} ${message}: ${plugins.consolecolor.coloredString(packageName, 'blue', 'white')}`;
logger.log('info', coloredMessage);
};
// Helper function for build-related messages
export const logBuild = (message: string) => {
const coloredMessage = `${logIcons.build} ${plugins.consolecolor.coloredString(message, 'cyan')}`;
logger.log('info', coloredMessage);
};
// Helper function for publish-related messages
export const logPublish = (message: string) => {
const coloredMessage = `${logIcons.publish} ${plugins.consolecolor.coloredString(message, 'green')}`;
logger.log('info', coloredMessage);
};
// Create a visual separator for different phases
export const logSeparator = () => {
const separator = plugins.consolecolor.coloredString('━'.repeat(60), 'cyan');
console.log(separator);
};
// Create a header for major sections
export const logHeader = (title: string) => {
logSeparator();
const header = plugins.consolecolor.coloredString(` ${title.toUpperCase()} `, 'white', 'blue');
console.log(header);
logSeparator();
};
// Helper for indicating ongoing operations
export const logOngoing = (text: string) => {
const spinnerIcon = plugins.consolecolor.coloredString('⟳', 'cyan');
const coloredMessage = `${spinnerIcon} ${plugins.consolecolor.coloredString(text, 'cyan')}`;
logger.log('info', coloredMessage);
};
// Progress indicator helper
export const logProgress = (current: number, total: number, item: string) => {
const percentage = Math.round((current / total) * 100);
const progressBar = '█'.repeat(Math.floor(percentage / 5)) + '░'.repeat(20 - Math.floor(percentage / 5));
const coloredProgress = plugins.consolecolor.coloredString(
`[${progressBar}] ${percentage}% - ${item}`,
percentage === 100 ? 'green' : 'blue'
);
logger.log('info', coloredProgress);
};

View File

@@ -3,6 +3,7 @@ import * as path from 'path';
export { path };
// @push.rocks scope
import * as consolecolor from '@push.rocks/consolecolor';
import * as smartfile from '@push.rocks/smartfile';
import * as smartcli from '@push.rocks/smartcli';
import * as smartdelay from '@push.rocks/smartdelay';
@@ -12,4 +13,4 @@ import * as smartpath from '@push.rocks/smartpath';
import * as smartrequest from '@push.rocks/smartrequest';
import * as smartshell from '@push.rocks/smartshell';
export { smartfile, smartcli, smartdelay, smartlog, smartnpm, smartpath, smartrequest, smartshell };
export { consolecolor, smartfile, smartcli, smartdelay, smartlog, smartnpm, smartpath, smartrequest, smartshell };