Merge pull request #54 from jfmengels/node-api

Add Node.js library API
This commit is contained in:
Matthew Griffith 2021-10-01 20:17:00 -04:00 committed by GitHub
commit eeef6529e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 183 additions and 126 deletions

View File

@ -1,2 +1,2 @@
#!/usr/bin/env node #!/usr/bin/env node
const index = require('../dist/index.js'); const index = require('../dist/bin.js');

49
src/bin.ts Normal file
View File

@ -0,0 +1,49 @@
import program from 'commander';
import chalk from 'chalk';
import { run } from './run';
const { version } = require('../package.json');
// import * as BenchInit from './benchmark/init'
// import * as Benchmark from './benchmark/benchmark';
// import * as Reporting from './benchmark/reporting';
program
.version(version)
.description(
`${chalk.yellow('Elm Optimize Level 2!')}
This applies a second level of optimization to the javascript that Elm creates.
Make sure you're familiar with Elm's built-in optimization first: ${chalk.cyan(
'https://guide.elm-lang.org/optimization/asset_size.html'
)}
Give me an Elm file, I'll compile it behind the scenes using Elm 0.19.1, and then I'll make some more optimizations!`
)
.usage('[options] <src/Main.elm>')
.option('--output <output>', 'the javascript file to create.', 'elm.js')
.option('-O3, --optimize-speed', 'Enable optimizations that likely increases asset size', false)
.option('--verbose', 'Show more error details, useful to provide better bug reports', false)
// .option('--init-benchmark <dir>', 'Generate some files to help run benchmarks')
// .option('--benchmark <dir>', 'Run the benchmark in the given directory.')
// .option('--replacements <dir>', 'Replace stuff')
.parse(process.argv);
const { output, optimizeSpeed, verbose } = program.opts();
run(
{
inputFilePath: program.args[0],
outputFilePath: output,
optimizeSpeed,
verbose,
processOpts: { stdio: ['inherit', 'ignore', 'inherit'] },
},
program.helpInformation(),
console.log.bind(console),
).catch((e) => {
if (verbose) {
console.error(e);
} else {
console.error(e.toString());
}
process.exit(1);
});

View File

@ -1,127 +1,20 @@
// tslint:disable-next-line no-require-imports no-var-requires import * as Run from './run';
import program from 'commander';
import * as path from 'path';
import * as Transform from './transform';
import { toolDefaults } from './types';
import { compileToStringSync } from 'node-elm-compiler';
import * as fs from 'fs';
import chalk from 'chalk';
const { version } = require('../package.json');
// import * as BenchInit from './benchmark/init'
// import * as Benchmark from './benchmark/benchmark';
// import * as Reporting from './benchmark/reporting';
program export async function run(options: {
.version(version) inputFilePath: string | undefined,
.description( outputFilePath: string,
`${chalk.yellow('Elm Optimize Level 2!')} optimizeSpeed: boolean,
processOpts: {
This applies a second level of optimization to the javascript that Elm creates. stdio: [string, string, string],
} | null,
Make sure you're familiar with Elm's built-in optimization first: ${chalk.cyan( }) {
'https://guide.elm-lang.org/optimization/asset_size.html' return Run.run(
)}
Give me an Elm file, I'll compile it behind the scenes using Elm 0.19.1, and then I'll make some more optimizations!`
)
.usage('[options] <src/Main.elm>')
.option('--output <output>', 'the javascript file to create.', 'elm.js')
.option('-O3, --optimize-speed', 'Enable optimizations that likely increases asset size', false)
// .option('--init-benchmark <dir>', 'Generate some files to help run benchmarks')
// .option('--benchmark <dir>', 'Run the benchmark in the given directory.')
// .option('--replacements <dir>', 'Replace stuff')
.parse(process.argv);
async function run(inputFilePath: string | undefined) {
const dirname = process.cwd();
let jsSource: string = '';
let elmFilePath = undefined;
const options = program.opts();
const replacements = null;
const o3Enabled = options.optimizeSpeed;
// if (program.initBenchmark) {
// console.log(`Initializing benchmark ${program.initBenchmark}`)
// BenchInit.generate(program.initBenchmark)
// process.exit(0)
// }
// if (program.benchmark) {
// const options = {
// compile: true,
// gzip: true,
// minify: true,
// verbose: true,
// assetSizes: true,
// runBenchmark: [
// {
// browser: Browser.Chrome,
// headless: true,
// }
// ],
// transforms: benchmarkDefaults(o3Enabled, replacements),
// };
// const report = await Benchmark.run(options, [
// {
// name: 'Benchmark',
// dir: program.benchmark,
// elmFile: 'V8/Benchmark.elm',
// }
// ]);
// console.log(Reporting.terminal(report));
// // fs.writeFileSync('./results.markdown', Reporting.markdownTable(result));
// process.exit(0)
// }
if (inputFilePath && inputFilePath.endsWith('.js')) {
jsSource = fs.readFileSync(inputFilePath, 'utf8');
console.log('Optimizing existing JS...');
} else if (inputFilePath && inputFilePath.endsWith('.elm')) {
elmFilePath = inputFilePath;
jsSource = compileToStringSync([inputFilePath], {
output: 'output/elm.opt.js',
cwd: dirname,
optimize: true,
processOpts:
// ignore stdout
{ {
stdio: ['inherit', 'ignore', 'inherit'], ...options,
verbose: false,
processOpts: options.processOpts || { stdio: ['inherit', 'ignore', 'inherit'] },
}, },
}); '',
if (jsSource != '') { () => { }
console.log('Compiled, optimizing JS...');
} else {
process.exit(1)
}
} else {
console.error('Please provide a path to an Elm file.');
program.outputHelp();
return;
}
if (jsSource != '') {
const transformed = await Transform.transform(
dirname,
jsSource,
elmFilePath,
false,
toolDefaults(o3Enabled, replacements),
); );
// Make sure all the folders up to the output file exist, if not create them.
// This mirrors elm make behavior.
const outputDirectory = path.dirname(program.output);
if (!fs.existsSync(outputDirectory)) {
fs.mkdirSync(outputDirectory, { recursive: true });
} }
fs.writeFileSync(program.output, transformed);
const fileName = path.basename(inputFilePath);
console.log('Success!');
console.log('');
console.log(` ${fileName} ───> ${program.output}`);
console.log('');
}
}
run(program.args[0]).catch((e) => console.error(e));

115
src/run.ts Normal file
View File

@ -0,0 +1,115 @@
import * as path from 'path';
import * as Transform from './transform';
import { toolDefaults } from './types';
import { compileToStringSync } from 'node-elm-compiler';
import * as fs from 'fs';
// import * as BenchInit from './benchmark/init'
// import * as Benchmark from './benchmark/benchmark';
// import * as Reporting from './benchmark/reporting';
export async function run(
options: {
inputFilePath: string | undefined,
outputFilePath: string,
optimizeSpeed: boolean,
verbose: boolean,
processOpts: { stdio: [string, string, string] },
},
helpInformation: string,
log: (message?: any, ...optionalParams: any[]) => void
) {
if (!options.outputFilePath) {
throw new Error('Missing an output file path');
}
const dirname = process.cwd();
let jsSource: string = '';
let elmFilePath = undefined;
const replacements = null;
const inputFilePath = options.inputFilePath;
const o3Enabled = options.optimizeSpeed;
// if (program.initBenchmark) {
// console.log(`Initializing benchmark ${program.initBenchmark}`)
// BenchInit.generate(program.initBenchmark)
// process.exit(0)
// }
// if (program.benchmark) {
// const options = {
// compile: true,
// gzip: true,
// minify: true,
// verbose: true,
// assetSizes: true,
// runBenchmark: [
// {
// browser: Browser.Chrome,
// headless: true,
// }
// ],
// transforms: benchmarkDefaults(o3Enabled, replacements),
// };
// const report = await Benchmark.run(options, [
// {
// name: 'Benchmark',
// dir: program.benchmark,
// elmFile: 'V8/Benchmark.elm',
// }
// ]);
// console.log(Reporting.terminal(report));
// // fs.writeFileSync('./results.markdown', Reporting.markdownTable(result));
// process.exit(0)
// }
if (inputFilePath && inputFilePath.endsWith('.js')) {
jsSource = fs.readFileSync(inputFilePath, 'utf8');
log('Optimizing existing JS...');
} else if (inputFilePath && inputFilePath.endsWith('.elm')) {
elmFilePath = inputFilePath;
jsSource = compileToStringSync([inputFilePath], {
output: 'output/elm.opt.js',
cwd: dirname,
optimize: true,
processOpts:
// ignore stdout
{
stdio: ['inherit', 'ignore', 'inherit'],
},
});
if (jsSource != '') {
log('Compiled, optimizing JS...');
} else {
throw new Error('An error occurred when compiling your application with Elm 0.19.1.');
}
} else {
throw new Error(`Please provide a path to an Elm file.\n${helpInformation}`.trim());
}
if (jsSource == '') {
throw new Error('Target JS file is empty.');
}
const transformed = await Transform.transform(
dirname,
jsSource,
elmFilePath,
options.verbose,
toolDefaults(o3Enabled, replacements),
);
// Make sure all the folders up to the output file exist, if not create them.
// This mirrors elm make behavior.
const outputDirectory = path.dirname(options.outputFilePath);
if (!fs.existsSync(outputDirectory)) {
fs.mkdirSync(outputDirectory, { recursive: true });
}
fs.writeFileSync(options.outputFilePath, transformed);
const fileName = path.basename(inputFilePath);
log('Success!');
log('');
log(` ${fileName} ───> ${options.outputFilePath}`);
log('');
return options.outputFilePath;
}