UNPKG

esm-to-plain-js

Version:

Simplistic string substitution to replace export with a globalThis assignment (CLI tool designed for use in npm package.json scripts)

83 lines (81 loc) 3.67 kB
//! esm-to-plain-js v1.2.4 ~~ https://github.com/center-key/esm-to-plain-js ~~ MIT License import { cliArgvUtil } from 'cli-argv-util'; import chalk from 'chalk'; import fs from 'node:fs'; import log from 'fancy-log'; import os from 'node:os'; import path from 'node:path'; import slash from 'slash'; const esmToPlainJs = { version: '1.2.4', assertOk(ok, message) { if (!ok) throw new Error(`[esm-to-plain-js] ${message}`); }, transform(sourceFile, targetFile, options) { const defaults = { cd: null, }; const settings = { ...defaults, ...options }; const startTime = Date.now(); const clean = (folder) => slash(path.normalize(folder)).replace(/\/$/, ''); const cleanPath = (folder) => !folder ? '' : clean(folder); const startFolder = settings.cd ? cleanPath(settings.cd) + '/' : ''; const source = sourceFile ? cleanPath(startFolder + sourceFile) : ''; const sourceExists = source && fs.existsSync(source); const sourceIsFile = sourceExists && fs.statSync(source).isFile(); const target = targetFile ? cleanPath(startFolder + targetFile) : null; const targetFolder = target ? path.dirname(target) : null; if (targetFolder) fs.mkdirSync(targetFolder, { recursive: true }); const badTargetFolder = !targetFolder || !fs.existsSync(targetFolder); const error = !sourceFile ? 'Must specify a source file.' : !sourceExists ? 'Source file does not exist: ' + source : !sourceIsFile ? 'Source is not a file: ' + source : !target ? 'Must specify a target file.' : badTargetFolder ? 'Target folder cannot be written to: ' + String(targetFolder) : null; esmToPlainJs.assertOk(!error, error); const esm = fs.readFileSync(source, 'utf-8'); const importPattern = /^import .*/mg; const exportPattern = /^export \{ (.*) \};$/m; const replaceImport = (stmt) => '// Ensure library is loaded => ' + stmt; const toGlobal = (module) => `globalThis.${module} = ${module};`; const replaceExport = (stmt, modules) => modules.split(', ').map(toGlobal).join(os.EOL); const plainJs = esm .replace(importPattern, replaceImport) .replace(exportPattern, replaceExport); fs.writeFileSync(target, plainJs); return { origin: source, dest: target, length: plainJs.length, duration: Date.now() - startTime, }; }, reporter(result) { const name = chalk.gray('esm-to-plain-js'); const version = chalk.gray('v' + esmToPlainJs.version); const info = chalk.gray(`(${result.duration}ms)`); log(name, version, cliArgvUtil.colorizePath(result.dest), info); }, cli() { const validFlags = ['cd', 'note', 'quiet']; const cli = cliArgvUtil.parse(validFlags); const source = cli.params[0]; const target = cli.params[1]; const error = cli.invalidFlag ? cli.invalidFlagMsg : cli.paramCount > 2 ? 'Extraneous parameter: ' + cli.params[2] : !source ? 'Missing source file.' : !target ? 'Missing target file.' : null; esmToPlainJs.assertOk(!error, error); const options = { cd: cli.flagMap.cd ?? null, }; const result = esmToPlainJs.transform(source, target, options); if (!cli.flagOn.quiet) esmToPlainJs.reporter(result); }, }; export { esmToPlainJs };