Skip to content

Commit

Permalink
Allow specifying options with sucrase/register and related tools (#813)
Browse files Browse the repository at this point in the history
Fixes #792

This PR adds a new environment variable SUCRASE_OPTIONS that works with the
require hook and other tools that are based on the require hook (`sucrase-node`
and programmatically registering a hook). Its format is simply a JSON string
that is parsed and merged with the usual options. Hopefully this will be rare,
especially after a semver-major change to better defaults, but it's important
for some cases.
  • Loading branch information
alangpierce committed Jul 19, 2023
1 parent d617368 commit 4bd800b
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 5 deletions.
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -191,6 +191,9 @@ reasonable defaults that can be accessed in a few ways:
* When invoking Node: `node -r sucrase/register main.ts`
* As a separate binary: `sucrase-node main.ts`

Options can be passed to the require hook via a `SUCRASE_OPTIONS` environment
variable holding a JSON string of options.

### Compiling a project to JS

For simple use cases, Sucrase comes with a `sucrase` CLI that mirrors your
Expand Down
13 changes: 10 additions & 3 deletions integration-test/integration-tests.ts
Expand Up @@ -2,7 +2,7 @@ import assert from "assert";
import {exec} from "child_process";
import {readdirSync, statSync} from "fs";
import {rm, writeFile} from "fs/promises";
import {join, dirname, resolve} from "path";
import {join, dirname, resolve, basename} from "path";
import {promisify} from "util";

import {
Expand Down Expand Up @@ -44,8 +44,15 @@ describe("integration tests", () => {
* in such a way that the execution throws an exception if the test fails.
*/
for (const testFile of discoverTests("test-cases/register-cases", "main")) {
it(testFile, async () => {
await execPromise(`node -r ${__dirname}/../register ${testFile}`);
const testDir = dirname(testFile);
it(testDir, async () => {
process.chdir(testDir);
const testConfig = await readJSONFileContentsIfExists("./test.json");
let envPrefix = "";
if (testConfig?.sucraseOptions) {
envPrefix = `SUCRASE_OPTIONS='${JSON.stringify(testConfig.sucraseOptions)}' `;
}
await execPromise(`${envPrefix}node -r ${__dirname}/../register ${basename(testFile)}`);
});
}

Expand Down
@@ -0,0 +1 @@
export const foo = 3;
@@ -0,0 +1,7 @@
async function main() {
const plainESMFile = await import("./esm-file.mjs");
if (plainESMFile.foo !== 3) {
throw new Error();
}
}
main();
@@ -0,0 +1,5 @@
{
"sucraseOptions": {
"preserveDynamicImport": true
}
}
9 changes: 7 additions & 2 deletions src/register.ts
Expand Up @@ -11,13 +11,18 @@ export type RevertFunction = () => void;

export function addHook(
extension: string,
options: Options,
sucraseOptions: Options,
hookOptions?: HookOptions,
): RevertFunction {
let mergedSucraseOptions = sucraseOptions;
const sucraseOptionsEnvJSON = process.env.SUCRASE_OPTIONS;
if (sucraseOptionsEnvJSON) {
mergedSucraseOptions = {...mergedSucraseOptions, ...JSON.parse(sucraseOptionsEnvJSON)};
}
return pirates.addHook(
(code: string, filePath: string): string => {
const {code: transformedCode, sourceMap} = transform(code, {
...options,
...mergedSucraseOptions,
sourceMapOptions: {compiledFilename: filePath},
filePath,
});
Expand Down

0 comments on commit 4bd800b

Please sign in to comment.