Skip to content

Commit

Permalink
refactor: esbuild strategy.
Browse files Browse the repository at this point in the history
  • Loading branch information
darkobits committed Jun 27, 2023
1 parent 6d5554d commit 856d786
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 21 deletions.
60 changes: 40 additions & 20 deletions src/lib/configuration/strategies/esbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,25 @@ import type { PackageInfo } from 'lib/package';
* Uses esbuild to transpile the user's configuration file.
*/
export async function esbuildStrategy(filePath: string, pkgInfo: PackageInfo) {
const fileName = path.basename(filePath);

const outFileBasename = fileName
.replace(/\.(ts|tsx)$/, '.js')
.replace(/\.cts$/, '.cjs')
.replace(/\.mts$/, '.mjs')
.replace(/\.jsx$/, '.js');

const isExplicitCommonJs = fileName.endsWith('.cjs') || fileName.endsWith('.cts');
const isExplicitESM = fileName.endsWith('.mjs') || fileName.endsWith('.mts');
const parsedFileName = path.parse(filePath);
const isExplicitCommonJs = ['.cjs', '.cts'].includes(parsedFileName.ext);
const isExplicitESM = ['.mjs', '.mts'].includes(parsedFileName.ext);

const extMap: Record<string, string | undefined> = {
'.ts': '.js',
'.tsx': '.js',
'.cts': '.cjs',
'.mts': '.mjs',
'.jsx':' .js',
'.cjs': '.cjs',
'.mjs': '.mjs'
};

const outExt = extMap[parsedFileName.ext];

if (!outExt) throw new Error(
`${log.prefix('strategy:esbuild')} Unable to determine output file extension from input extension: ${parsedFileName.ext}`
);

// Determine the output format to use by first honoring any explicit
// transpilation hints based on file extension, then fall back to relying on
Expand All @@ -37,10 +46,11 @@ export async function esbuildStrategy(filePath: string, pkgInfo: PackageInfo) {
? 'esm'
: 'cjs';

log.verbose(log.prefix('esbuild'), `Using format: ${log.chalk.bold(format)}`);
log.verbose(log.prefix('strategy:esbuild'), `Using format: ${log.chalk.bold(format)}`);

const tempFileName = `.temp-saffron.${outFileBasename}`;
const tempFileName = `.${parsedFileName.name}.${Date.now()}${outExt}`;
const tempFilePath = path.join(path.dirname(filePath), tempFileName);
log.silly(log.prefix('strategy:esbuild'), `Temporary file will be written to: ${log.chalk.green(tempFilePath)}`);

try {
const buildOptions: esbuild.BuildOptions = {
Expand All @@ -50,32 +60,42 @@ export async function esbuildStrategy(filePath: string, pkgInfo: PackageInfo) {
format,
plugins: [],
banner: {
'js': '// This temporary file was generated by @darkobits/saffron and can be safely removed.\n'
'js': '/** This file was generated by @darkobits/saffron and can be safely removed. */\n'
}
};

// If the user has a TypeScript configuration file, enable TypeScript
// features.
const tsConfigFilePath = await tsConfck.find(filePath);

if (tsConfigFilePath) {
log.verbose(log.prefix('esbuild'), `Using TypeScript configuration: ${log.chalk.green(tsConfigFilePath)}`);

log.verbose(log.prefix('strategy:esbuild'), `Using TypeScript configuration: ${log.chalk.green(tsConfigFilePath)}`);
buildOptions.tsconfig = tsConfigFilePath;

buildOptions.plugins?.push(TsconfigPathsPlugin({
tsconfig: tsConfigFilePath
}));
buildOptions.plugins?.push(TsconfigPathsPlugin({ tsconfig: tsConfigFilePath }));
}

// Transpile the input file.
await esbuild.build(buildOptions);
} catch (cause: any) {
throw new Error(
`${log.prefix('strategy:esbuild')} ${log.chalk.red('Failed to transpile configuration file')} ${log.chalk.green(filePath)}: ${cause}`,
{ cause }
);
}

try {
// Load the input file.
const result = await import(tempFilePath);

// Note: This assumes the consumer wants the default export.
return result?.default ?? result;
} catch (cause: any) {
throw new Error(
`${log.prefix('esbuildStrategy')} Failed to load configuration file: ${cause}`,
`${log.prefix('strategy:esbuild')} ${log.chalk.red('Failed to load configuration file')} ${log.chalk.green(tempFilePath)}: ${cause}`,
{ cause }
);
} finally {
// Remove the temporary file.
if (await fs.exists(tempFilePath)) {
await fs.remove(tempFilePath);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/configuration/strategies/ts-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export function TypeScriptLoader(options: RegisterOptions = {}) {

// ----- [2] Compute Path for Temporary Configuration File ---------------

const tempConfigFileName = computeFileExtension(`.saffron-temporary-${path.basename(filePath)}`);
const tempConfigFileName = computeFileExtension(`.${path.basename(filePath)}.${Date.now()}`);
const tempConfigFileDirectory = path.dirname(filePath);
tempConfigFilePath = path.join(tempConfigFileDirectory, tempConfigFileName);

Expand Down

0 comments on commit 856d786

Please sign in to comment.