patchwork-preloadconverter
Version:
A specialized converter for handling preload (.pld) files.
126 lines (110 loc) • 5.46 kB
text/typescript
import { Argument, program } from 'commander'
import { NAME, DESCRIPTION, VERSION } from './metadata'
import { ILogObj, Logger } from 'tslog'
import { LoggerFactory } from './logging/LoggerFactory'
import { PreloadConverter } from './converter/PreloadConverter'
import { lstatSync } from 'node:fs'
import { mkdir } from 'node:fs/promises'
import path from 'node:path'
import directoryTree from 'directory-tree'
import chokidar from 'chokidar';
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-var-requires
require('source-map-support').install()
let log: Logger<ILogObj>
let watchForChanges = false;
let skip = false;
async function protectedAction(input: string, output: string, action: (input: string, output: string) => Promise<void>) {
try {
await action(input, output);
} catch (exception) {
log.fatal(exception);
}
}
async function conversionAction(input: string, output: string, outputFileExtension: string | undefined, action: (input: string, output: string) => Promise<void>) {
let folderMode = false;
const inputFileStat = lstatSync(input, { throwIfNoEntry: false });
if (inputFileStat == null) {
throw new Error("Input file or directory doesn't exist!");
}
const outputFileStat = lstatSync(output, { throwIfNoEntry: false });
if (inputFileStat.isDirectory()) {
if (outputFileStat != null && !outputFileStat.isDirectory()) {
throw new Error("Input is a directory, output path exists and was identified as not a directory.");
}
if (!outputFileExtension) {
throw new Error("Input and output are directories, you must define a outputFileExtension!");
}
folderMode = true;
}
const resolvedOutputs = new Set();
if (watchForChanges) {
const watcher = chokidar.watch(input, { persistent: true });
watcher.on('change', async (inputPath) => {
log.info("File change detected for: ", inputPath);
let outputPath;
if (folderMode) {
outputPath = path.join(output, path.relative(input, inputPath)).replace(path.extname(inputPath), outputFileExtension as string);
const outputFolder = path.dirname(outputPath);
if (!resolvedOutputs.has(outputFolder)) {
resolvedOutputs.add(outputFolder);
await mkdir(outputFolder, { recursive: true });
}
} else {
outputPath = output;
}
await protectedAction(inputPath, outputPath, action);
});
}
if (!skip) {
if (folderMode) {
directoryTree(input, undefined, async (item, filePath, stats) => {
const outputPath = path.join(output, path.relative(input, filePath)).replace(path.extname(filePath), outputFileExtension as string);
const outputFolder = path.dirname(outputPath);
if (!resolvedOutputs.has(outputFolder)) {
resolvedOutputs.add(outputFolder);
await mkdir(outputFolder, { recursive: true });
}
await protectedAction(filePath, outputPath, action);;
})
} else {
await protectedAction(input, output, action);
}
}
}
program
.name(NAME)
.version(VERSION)
.description(DESCRIPTION)
.option('-w --watch', 'Command will trigger now and automatically on file change event.')
.option('-s --watch-skip', 'Command will automatically trigger only on file change event.')
.hook('preAction', (thisCommand, actionCommand) => {
log = LoggerFactory.createLogger('main');
const options = thisCommand.opts();
log.debug('command:', actionCommand.name())
log.debug('arguments:', actionCommand.args.join(', '))
log.debug('options:', JSON.stringify(thisCommand.opts()))
watchForChanges = options.watch || options.watchSkip;
skip = options.watchSkip;
});
program
.command('pld2text')
.description('Convert preload file (.pld or .txt) into a text readable file without the Preload calls.')
.addArgument(new Argument('<input>', 'input file or folder').argRequired())
.addArgument(new Argument('<output>', 'output file or folder').argRequired())
.addArgument(new Argument('<outputFileExtension>', 'output file extension required if input and output are folders').argOptional())
.action(async (input: string, output: string, outputFileExtension: string | undefined) => {
await conversionAction(input, output, outputFileExtension, PreloadConverter.parsePreloadFile);
});
program
.command('text2pld')
.description('Compile any given file into a preload (.pld) file by wrapping each line in a \'Preload\' call and the entire file into a standard preload procedure.')
.addArgument(new Argument('<input>', 'input file or folder').argRequired())
.addArgument(new Argument('<output>', 'output file or folder').argRequired())
.addArgument(new Argument('<functionName>', 'preload file\'s main function name.').argRequired())
.addArgument(new Argument('<outputFileExtension>', 'output file extension required if input and output are folders').argOptional())
.action(async (input: string, output: string, functionName: string, outputFileExtension: string | undefined) => {
await conversionAction(input, output, outputFileExtension, (inputPath, outputPath) => PreloadConverter.compilePreloadFile(inputPath, outputPath, functionName));
});
program.parse();