Skip to content

Commit

Permalink
Refactor: split constants into two classes (#1189)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmercm authored Jun 28, 2024
1 parent f34f9d4 commit 860693d
Show file tree
Hide file tree
Showing 52 changed files with 257 additions and 251 deletions.
8 changes: 4 additions & 4 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import semver from 'semver';

import Logger from './src/console/logger.js';
import ProgressBarCLI from './src/console/progressBarCli.js';
import Constants from './src/constants.js';
import Package from './src/constants/package.js';
import Igir from './src/igir.js';
import ArgumentsParser from './src/modules/argumentsParser.js';
import EndOfLifeChecker from './src/modules/endOfLifeChecker.js';
Expand All @@ -21,14 +21,14 @@ gracefulFs.gracefulify(realFs);
const logger = new Logger();
logger.printHeader();

if (!semver.satisfies(process.version, Constants.ENGINES_NODE)) {
logger.error(`${Constants.COMMAND_NAME} requires a Node.js version of ${Constants.ENGINES_NODE}`);
if (!semver.satisfies(process.version, Package.ENGINES_NODE)) {
logger.error(`${Package.NAME} requires a Node.js version of ${Package.ENGINES_NODE}`);
process.exit(1);
}

process.once('SIGINT', async () => {
logger.newLine();
logger.notice(`Exiting ${Constants.COMMAND_NAME} early`);
logger.notice(`Exiting ${Package.NAME} early`);
await ProgressBarCLI.stop();
process.exit(0);
// TODO(cemmer): does exit here cause cleanup not to happen?
Expand Down
4 changes: 2 additions & 2 deletions package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import yargs from 'yargs';

import Logger from './src/console/logger.js';
import LogLevel from './src/console/logLevel.js';
import Constants from './src/constants.js';
import Package from './src/constants/package.js';
import FsPoly from './src/polyfill/fsPoly.js';

interface FileFilter extends GlobOptions {
Expand Down Expand Up @@ -61,7 +61,7 @@ const fileFilter = (filters: FileFilter[]): string[] => {
.positional('output', {
description: 'output file',
type: 'string',
default: Constants.COMMAND_NAME + (process.platform === 'win32' ? '.exe' : ''),
default: Package.NAME + (process.platform === 'win32' ? '.exe' : ''),
}).argv;

const input = path.resolve(argv.input);
Expand Down
12 changes: 6 additions & 6 deletions src/console/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import chalk from 'chalk';
import figlet from 'figlet';
import moment from 'moment';

import Constants from '../constants.js';
import Package from '../constants/package.js';
import LogLevel from './logLevel.js';
import ProgressBar, { ProgressBarSymbol } from './progressBar.js';
import ProgressBarCLI from './progressBarCli.js';
Expand Down Expand Up @@ -119,16 +119,16 @@ export default class Logger {
* Print the CLI header.
*/
printHeader(): void {
const logo = figlet.textSync(Constants.COMMAND_NAME.toUpperCase(), {
const logo = figlet.textSync(Package.NAME.toUpperCase(), {
font: 'Big Money-se',
}).trimEnd();

const logoSplit = logo.split('\n');
const midLine = Math.min(Math.ceil(logoSplit.length / 2), logoSplit.length - 1);
const maxLineLen = logoSplit.reduce((max, line) => Math.max(max, line.length), 0);
logoSplit[midLine - 2] = `${logoSplit[midLine - 1].padEnd(maxLineLen, ' ')} ROM collection manager`;
logoSplit[midLine - 1] = `${logoSplit[midLine - 1].padEnd(maxLineLen, ' ')} ${Constants.HOMEPAGE}`;
logoSplit[midLine + 1] = `${logoSplit[midLine + 1].padEnd(maxLineLen, ' ')} v${Constants.COMMAND_VERSION}`;
logoSplit[midLine - 1] = `${logoSplit[midLine - 1].padEnd(maxLineLen, ' ')} ${Package.HOMEPAGE}`;
logoSplit[midLine + 1] = `${logoSplit[midLine + 1].padEnd(maxLineLen, ' ')} v${Package.VERSION}`;

this.print(LogLevel.ALWAYS, `${logoSplit.join('\n')}\n\n`);
}
Expand All @@ -143,7 +143,7 @@ export default class Logger {
.replace(/^(Usage:.+)/, chalk.bold('$1'))

.replace(/(\[commands\.*\])/g, chalk.magenta('$1'))
.replace(new RegExp(`(${Constants.COMMAND_NAME}) (( ?[a-z0-9])+)`, 'g'), `$1 ${chalk.magenta('$2')}`)
.replace(new RegExp(`(${Package.NAME}) (( ?[a-z0-9])+)`, 'g'), `$1 ${chalk.magenta('$2')}`)

.replace(/(\[options\.*\])/g, chalk.cyan('$1'))
.replace(/([^a-zA-Z0-9-])(-[a-zA-Z0-9]([a-zA-Z0-9]|\n[ \t]*)*)/g, `$1${chalk.cyanBright('$2')}`)
Expand All @@ -157,7 +157,7 @@ export default class Logger {

.replace(/(\{[a-zA-Z]+\})/g, chalk.yellow('$1'))

.replace(new RegExp(` (${Constants.COMMAND_NAME}) `, 'g'), ` ${chalk.blueBright('$1')} `),
.replace(new RegExp(` (${Package.NAME}) `, 'g'), ` ${chalk.blueBright('$1')} `),
);
}

Expand Down
47 changes: 4 additions & 43 deletions src/constants.ts → src/constants/defaults.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,10 @@
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import url from 'node:url';

import fsPoly from './polyfill/fsPoly.js';
import fsPoly from '../polyfill/fsPoly.js';
import Package from './package.js';

/**
* Search for a {@link fileName} in {@link filePath} or any of its parent directories.
*/
function scanUpPathForFile(filePath: string, fileName: string): string | undefined {
const fullPath = path.join(filePath, fileName);
if (fs.existsSync(fullPath)) {
return fullPath;
}

const parentPath = path.dirname(filePath);
if (parentPath !== filePath) {
return scanUpPathForFile(path.dirname(filePath), fileName);
}

return undefined;
}

const PACKAGE_JSON_PATH = scanUpPathForFile(
url.fileURLToPath(new URL('.', import.meta.url)),
'package.json',
) as string;
const PACKAGE_JSON = JSON.parse(
fs.readFileSync(PACKAGE_JSON_PATH).toString(),
);
const COMMAND_NAME = PACKAGE_JSON.name;

const ROOT_DIR = path.dirname(PACKAGE_JSON_PATH);

const GLOBAL_TEMP_DIR = fsPoly.mkdtempSync(path.join(os.tmpdir(), COMMAND_NAME));
const GLOBAL_TEMP_DIR = fsPoly.mkdtempSync(path.join(os.tmpdir(), Package.NAME));
process.once('beforeExit', async () => {
// WARN: Jest won't call this: https://github.com/jestjs/jest/issues/10927
await fsPoly.rm(GLOBAL_TEMP_DIR, {
Expand All @@ -45,17 +16,7 @@ process.once('beforeExit', async () => {
/**
* A static class of constants that are determined at startup, to be used widely.
*/
export default class Constants {
static readonly ROOT_DIR = ROOT_DIR;

static readonly COMMAND_NAME = COMMAND_NAME;

static readonly HOMEPAGE = PACKAGE_JSON.homepage;

static readonly COMMAND_VERSION = PACKAGE_JSON.version;

static readonly ENGINES_NODE = PACKAGE_JSON.engines?.node ?? '*';

export default class Defaults {
static readonly GLOBAL_TEMP_DIR = GLOBAL_TEMP_DIR;

/**
Expand Down
43 changes: 43 additions & 0 deletions src/constants/package.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import fs from 'node:fs';
import path from 'node:path';
import url from 'node:url';

/**
* Search for a {@link fileName} in {@link filePath} or any of its parent directories.
*/
function scanUpPathForFile(filePath: string, fileName: string): string | undefined {
const fullPath = path.join(filePath, fileName);
if (fs.existsSync(fullPath)) {
return fullPath;
}

const parentPath = path.dirname(filePath);
if (parentPath !== filePath) {
return scanUpPathForFile(path.dirname(filePath), fileName);
}

return undefined;
}

const PACKAGE_JSON_PATH = scanUpPathForFile(
url.fileURLToPath(new URL('.', import.meta.url)),
'package.json',
) as string;
const PACKAGE_JSON = JSON.parse(
fs.readFileSync(PACKAGE_JSON_PATH).toString(),
);

/**
* A static class of constants that are parsed from `package.json` at startup, to be used widely.
*/
export default class Package {
static readonly DIRECTORY = path.dirname(PACKAGE_JSON_PATH);

static readonly NAME = PACKAGE_JSON.name;

static readonly HOMEPAGE = PACKAGE_JSON.homepage;

static readonly VERSION = PACKAGE_JSON.version;

static readonly ENGINES_NODE = PACKAGE_JSON.engines?.node ?? '*';
}
4 changes: 2 additions & 2 deletions src/driveSemaphore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'node:path';
import async, { AsyncResultCallback } from 'async';
import { Mutex, Semaphore } from 'async-mutex';

import Constants from './constants.js';
import Defaults from './constants/defaults.js';
import FsPoly from './polyfill/fsPoly.js';
import File from './types/files/file.js';

Expand Down Expand Up @@ -37,7 +37,7 @@ export default class DriveSemaphore {
// Limit the number of ongoing threads to something reasonable
return async.mapLimit(
files,
Constants.MAX_FS_THREADS,
Defaults.MAX_FS_THREADS,
async (file, callback: AsyncResultCallback<V, Error>) => {
try {
const val = await this.processFile(file, runnable, disks);
Expand Down
13 changes: 7 additions & 6 deletions src/igir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import isAdmin from 'is-admin';
import Logger from './console/logger.js';
import ProgressBar, { ProgressBarSymbol } from './console/progressBar.js';
import ProgressBarCLI from './console/progressBarCli.js';
import Constants from './constants.js';
import Defaults from './constants/defaults.js';
import Package from './constants/package.js';
import CandidateArchiveFileHasher from './modules/candidateArchiveFileHasher.js';
import CandidateCombiner from './modules/candidateCombiner.js';
import CandidateGenerator from './modules/candidateGenerator.js';
Expand Down Expand Up @@ -72,11 +73,11 @@ export default class Igir {
&& process.platform === 'win32'
) {
this.logger.trace('checking Windows for symlink permissions');
if (!await FsPoly.canSymlink(Constants.GLOBAL_TEMP_DIR)) {
if (!await FsPoly.canSymlink(Defaults.GLOBAL_TEMP_DIR)) {
if (!await isAdmin()) {
throw new Error(`${Constants.COMMAND_NAME} does not have permissions to create symlinks, please try running as administrator`);
throw new Error(`${Package.NAME} does not have permissions to create symlinks, please try running as administrator`);
}
throw new Error(`${Constants.COMMAND_NAME} does not have permissions to create symlinks`);
throw new Error(`${Package.NAME} does not have permissions to create symlinks`);
}
this.logger.trace('Windows has symlink permissions');
}
Expand Down Expand Up @@ -208,7 +209,7 @@ export default class Igir {
}

private async getCachePath(): Promise<string | undefined> {
const defaultFileName = `${Constants.COMMAND_NAME}.cache`;
const defaultFileName = `${Package.NAME}.cache`;

// Try to use the provided path
let cachePath = this.options.getCachePath();
Expand All @@ -225,7 +226,7 @@ export default class Igir {

// Otherwise, use a default path
return [
path.join(path.resolve(Constants.ROOT_DIR), defaultFileName),
path.join(path.resolve(Package.DIRECTORY), defaultFileName),
path.join(os.homedir(), defaultFileName),
path.join(process.cwd(), defaultFileName),
]
Expand Down
15 changes: 8 additions & 7 deletions src/modules/argumentsParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import fs from 'node:fs';
import yargs, { Argv } from 'yargs';

import Logger from '../console/logger.js';
import Constants from '../constants.js';
import Defaults from '../constants/defaults.js';
import Package from '../constants/package.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import ConsolePoly from '../polyfill/consolePoly.js';
import { ChecksumBitmask } from '../types/files/fileChecksums.js';
Expand Down Expand Up @@ -165,7 +166,7 @@ export default class ArgumentsParser {
'boolean-negation': false,
})
.locale('en')
.scriptName(Constants.COMMAND_NAME)
.scriptName(Package.NAME)
.usage('Usage: $0 [commands..] [options]')
.updateStrings({
'Commands:': 'Commands (can specify multiple):',
Expand Down Expand Up @@ -768,7 +769,7 @@ export default class ArgumentsParser {
type: 'string',
coerce: ArgumentsParser.getLastValue, // don't allow string[] values
requiresArg: true,
default: `./${Constants.COMMAND_NAME}_%YYYY-%MM-%DDT%HH:%mm:%ss.csv`,
default: `./${Package.NAME}_%YYYY-%MM-%DDT%HH:%mm:%ss.csv`,
})

.option('dat-threads', {
Expand All @@ -777,23 +778,23 @@ export default class ArgumentsParser {
type: 'number',
coerce: (val: number) => Math.max(val, 1),
requiresArg: true,
default: Constants.DAT_DEFAULT_THREADS,
default: Defaults.DAT_DEFAULT_THREADS,
})
.option('reader-threads', {
group: groupHelpDebug,
description: 'Maximum number of ROMs to read in parallel per disk',
type: 'number',
coerce: (val: number) => Math.max(val, 1),
requiresArg: true,
default: Constants.FILE_READER_DEFAULT_THREADS,
default: Defaults.FILE_READER_DEFAULT_THREADS,
})
.option('writer-threads', {
group: groupHelpDebug,
description: 'Maximum number of ROMs to write in parallel',
type: 'number',
coerce: (val: number) => Math.max(val, 1),
requiresArg: true,
default: Constants.ROM_WRITER_DEFAULT_THREADS,
default: Defaults.ROM_WRITER_DEFAULT_THREADS,
})
.middleware((middlewareArgv) => {
if (middlewareArgv.zipDatName) {
Expand All @@ -807,7 +808,7 @@ export default class ArgumentsParser {
type: 'number',
coerce: (val: number) => Math.max(val, 0),
requiresArg: true,
default: Constants.ROM_WRITER_ADDITIONAL_RETRIES,
default: Defaults.ROM_WRITER_ADDITIONAL_RETRIES,
})
.option('disable-cache', {
group: groupHelpDebug,
Expand Down
4 changes: 2 additions & 2 deletions src/modules/candidateWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'node:path';
import { Semaphore } from 'async-mutex';

import ProgressBar, { ProgressBarSymbol } from '../console/progressBar.js';
import Constants from '../constants.js';
import Defaults from '../constants/defaults.js';
import ElasticSemaphore from '../elasticSemaphore.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import fsPoly from '../polyfill/fsPoly.js';
Expand Down Expand Up @@ -31,7 +31,7 @@ export default class CandidateWriter extends Module {
// WARN(cemmer): there is an undocumented semaphore max value that can be used, the full
// 4,700,372,992 bytes of a DVD+R will cause runExclusive() to never run or return.
private static readonly FILESIZE_SEMAPHORE = new ElasticSemaphore(
Constants.MAX_READ_WRITE_CONCURRENT_KILOBYTES,
Defaults.MAX_READ_WRITE_CONCURRENT_KILOBYTES,
);

private readonly options: Options;
Expand Down
8 changes: 4 additions & 4 deletions src/modules/datCombiner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import moment from 'moment';

import ProgressBar from '../console/progressBar.js';
import Constants from '../constants.js';
import Package from '../constants/package.js';
import DAT from '../types/dats/dat.js';
import Header from '../types/dats/logiqx/header.js';
import LogiqxDAT from '../types/dats/logiqx/logiqxDat.js';
Expand Down Expand Up @@ -38,10 +38,10 @@ export default class DATCombiner extends Module {
description: datName,
version: date,
date,
author: Constants.COMMAND_NAME,
url: Constants.HOMEPAGE,
author: Package.NAME,
url: Package.HOMEPAGE,
comment: [
`Combined DAT generated by ${Constants.COMMAND_NAME} v${Constants.COMMAND_VERSION}`,
`Combined DAT generated by ${Package.NAME} v${Package.VERSION}`,
...dats.map((dat) => dat.getName()),
].join('\n'),
});
Expand Down
10 changes: 5 additions & 5 deletions src/modules/datGameInferrer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'node:path';
import moment from 'moment';

import ProgressBar from '../console/progressBar.js';
import Constants from '../constants.js';
import Package from '../constants/package.js';
import ArrayPoly from '../polyfill/arrayPoly.js';
import DAT from '../types/dats/dat.js';
import Game from '../types/dats/game.js';
Expand All @@ -21,7 +21,7 @@ import Module from './module.js';
* path (without the extension).
*/
export default class DATGameInferrer extends Module {
private static readonly DEFAULT_DAT_NAME = Constants.COMMAND_NAME;
private static readonly DEFAULT_DAT_NAME = Package.NAME;

private readonly options: Options;

Expand Down Expand Up @@ -71,10 +71,10 @@ export default class DATGameInferrer extends Module {
description: datName,
version: date,
date,
author: Constants.COMMAND_NAME,
url: Constants.HOMEPAGE,
author: Package.NAME,
url: Package.HOMEPAGE,
comment: [
`dir2dat generated by ${Constants.COMMAND_NAME} v${Constants.COMMAND_VERSION}`,
`dir2dat generated by ${Package.NAME} v${Package.VERSION}`,
`Input path: ${inputPath}`,
].join('\n'),
});
Expand Down
Loading

0 comments on commit 860693d

Please sign in to comment.