@wessberg/cjs-to-esm-transformer
Version:
A Custom Transformer for Typescript that transforms Node-style CommonJS to tree-shakeable ES Modules
264 lines (253 loc) • 7.26 kB
JavaScript
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var commander = _interopDefault(require('commander'));
var fs = require('fs');
var fs__default = _interopDefault(fs);
var TS = require('typescript');
var chalk = _interopDefault(require('chalk'));
// tslint:disable:no-any
/**
* Coerces the given option value into an acceptable data type
*
* @param type
* @param value
*/
function coerceOptionValue(type, value) {
switch (type) {
case "string":
if (value === null)
return "null";
else if (value === undefined)
return "undefined";
return String(value);
case "number":
if (typeof value === "number")
return value;
else if (value === true)
return 1;
else if (value === false)
return 0;
return parseFloat(value);
case "boolean":
if (value === "true" || value === "" || value === "1" || value === 1)
return true;
else if (value === "false" || value === "0" || value === 0)
return false;
return Boolean(value);
}
}
/**
* Formats the given option flags
*
* @param shortHand
* @param longHand
* @returns
*/
function formatOptionFlags(shortHand, longHand) {
const formattedLongHand = `${longHand} [arg]`;
return shortHand != null ? `-${shortHand}, --${formattedLongHand}` : `--${formattedLongHand}`;
}
/**
* Formats the given command name, along with its arguments
*
* @param options
* @returns
*/
function formatCommandNameWithArgs(options) {
const formattedArgs = Object.entries(options.args)
.map(([argName, { type, required }]) => {
const left = required ? `<` : `[`;
const right = required ? ">" : `]`;
if (type === "string[]") {
return `${left}${argName}...${right}`;
}
else {
return `${left}${argName}${right}`;
}
})
.join(" ");
return `${options.name} ${formattedArgs}`;
}
/**
* Creates a new command
*
* @param options
* @param action
*/
function createCommand(options, action) {
// Add the command to the program
const result = commander
.command(formatCommandNameWithArgs(options), {
isDefault: options.isDefault
})
.description(options.description);
// Add options to the command
Object.entries(options.options).forEach(([longhand, { shortHand, description, type, defaultValue }]) => {
result.option(formatOptionFlags(shortHand, longhand), description, coerceOptionValue.bind(null, type), defaultValue);
});
// Add the action to the command
result.action((...args) => {
const argKeys = Object.keys(options.args);
const optionKeys = Object.keys(options.options);
const actionOptions = {};
for (let i = 0; i < args.length; i++) {
if (argKeys[i] == null)
continue;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
actionOptions[argKeys[i]] = args[i];
}
// Take the last argument
const lastArg = args[args.length - 1];
// Apply all option values
for (const key of optionKeys) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
actionOptions[key] = lastArg[key];
}
// Invoke the action
action(actionOptions);
});
}
const TRANSFORM_COMMAND_OPTIONS = {};
/**
* Selects a LogLevel based on the given options
*
* @param options
* @returns
*/
function selectLogLevel(options) {
if (options.debug) {
return 3 /* DEBUG */;
}
else if (options.verbose) {
return 2 /* VERBOSE */;
}
else if (options.silent) {
return 0 /* NONE */;
}
else {
return 1 /* INFO */;
}
}
/**
* A logger that can print to the console
*/
class Logger {
constructor(logLevel) {
this.logLevel = logLevel;
this.INFO_COLOR = "white";
this.VERBOSE_COLOR = "gray";
this.WARNING_COLOR = "yellow";
this.DEBUG_COLOR = "cyan";
}
/**
* Logs info-related messages
*/
info(...messages) {
if (this.logLevel < 1 /* INFO */)
return;
console.log(chalk[this.INFO_COLOR](...messages));
}
/**
* Logs verbose-related messages
*/
verbose(...messages) {
if (this.logLevel < 2 /* VERBOSE */)
return;
console.log(chalk[this.VERBOSE_COLOR](...messages));
}
/**
* Logs debug-related messages
*/
debug(...messages) {
if (this.logLevel < 3 /* DEBUG */)
return;
console.log(chalk[this.DEBUG_COLOR](...messages));
}
/**
* Logs warning-related messages
*/
warn(...messages) {
console.warn(chalk[this.WARNING_COLOR](`(!)`, ...messages));
}
}
/**
* Generates the task options that are shared across all commands
*
* @param options
* @returns
*/
async function generateTaskOptions(options) {
// Prepare a logger
const logLevel = selectLogLevel(options);
const logger = new Logger(logLevel);
// Inform about the log level (if applicable)
if (logLevel === 2 /* VERBOSE */) {
logger.verbose(`Logging mode: VERBOSE`);
}
else if (logLevel === 3 /* DEBUG */)
logger.debug(`Logging mode: DEBUG`);
return {
fs: fs__default,
logger,
root: process.cwd(),
typescript: TS
};
}
const SHARED_OPTIONS = {
debug: {
shortHand: "d",
type: "boolean",
description: "Whether to print debug information"
},
verbose: {
shortHand: "v",
type: "boolean",
description: "Whether to print verbose information"
},
silent: {
shortHand: "s",
type: "boolean",
description: "Whether to not print anything"
}
};
createCommand({
name: "transform",
description: `Transforms CJS to ESM modules based on the input glob`,
isDefault: true,
args: {
input: {
type: "string",
required: true,
description: "A glob for all the files that should be transformed"
},
outDir: {
type: "string",
required: true,
description: `The directory to write the transformed files to.`
}
},
options: {
...SHARED_OPTIONS,
...TRANSFORM_COMMAND_OPTIONS
}
}, async (args) => {
// Load the task
const { transformTask } = await Promise.resolve().then(function () { return require('./transform-task-5c7b7086.js'); });
const taskOptions = await generateTaskOptions(args);
// Execute it
await transformTask({
...taskOptions,
input: args.input,
outDir: args.outDir
});
});
const args = [...process.argv];
if (args[2] !== "transform") {
args.splice(2, 0, "transform");
}
commander.parse(args);
// Show help if no arguments are given
if (commander.args.length === 0) {
commander.help(text => `Welcome to the CJS to ESM CLI!\n\n` + text);
}
//# sourceMappingURL=index.js.map
;