Skip to content

Commit

Permalink
fix: now working as a loader
Browse files Browse the repository at this point in the history
  • Loading branch information
marco-ippolito committed Aug 10, 2024
1 parent 95b0e0e commit a712b1a
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 23 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,19 @@ Stack traces are preserved, by replacing removed types with white spaces.

```javascript
const amaro = require('amaro');
const { code } = amaro.transformSync("const foo: string = 'bar';");
const { code } = amaro.transformSync("const foo: string = 'bar';", { mode: "strip-only" });
console.log(code); // "const foo = 'bar';"
```

### Loader

It is possible to use Amaro as an external loader to execute TypeScript files.
This allows the installed Amaro to override the Amaro version used by Node.js.

```bash
node --experimental-strip-types --import="amaro/register" script.ts
```

### How to update SWC

To update the SWC version, run:
Expand Down
18 changes: 18 additions & 0 deletions esbuild.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const { copy } = require("esbuild-plugin-copy");
const esbuild = require("esbuild");

esbuild.build({
entryPoints: ["src/index.ts"],
bundle: true,
platform: "node",
target: "node20",
outdir: "dist",
plugins: [
copy({
assets: {
from: ["./src/register/register.mjs"],
to: ["."],
},
}),
],
});
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"ci:fix": "biome check --write",
"prepack": "npm run build",
"postpack": "npm run clean",
"build": "esbuild --bundle --platform=node --target=node18 --outdir=dist src/index.ts",
"build": "node esbuild.config.js",
"typecheck": "tsc --noEmit",
"test": "node --test --experimental-test-snapshots \"**/*.test.js\"",
"test:regenerate": "node --test --experimental-test-snapshots --test-update-snapshots \"**/*.test.js\""
Expand All @@ -30,11 +30,13 @@
"@biomejs/biome": "1.8.3",
"@types/node": "^20.14.11",
"esbuild": "^0.23.0",
"esbuild-plugin-copy": "^2.1.1",
"rimraf": "^6.0.1",
"typescript": "^5.5.3"
},
"files": [
"dist",
"LICENSE.md"
]
"exports": {
".": "./dist/index.js",
"./register": "./dist/register.mjs"
},
"files": ["dist", "LICENSE.md"]
}
38 changes: 28 additions & 10 deletions src/loader.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
import swc from "../lib/wasm.js";
import type { LoadHook } from "node:module";
import { readFile } from "node:fs/promises";
import assert from "node:assert";
import type { LoadFnOutput, LoadHookContext } from "node:module";
import { transformSync } from "./index.ts";

export const load: LoadHook = async (source, context, nextLoad) => {
if (context.format?.includes("typescript")) {
const data = await readFile(source, "utf8");
type NextLoad = (
url: string,
context?: LoadHookContext,
) => LoadFnOutput | Promise<LoadFnOutput>;

export async function load(
url: string,
context: LoadHookContext,
nextLoad: NextLoad,
) {
const { format } = context;
if (format.endsWith("-typescript")) {
// Use format 'module' so it returns the source as-is, without stripping the types.
// Format 'commonjs' would not return the source for historical reasons.
const { source } = await nextLoad(url, {
...context,
format: "module",
});
if (source == null)
throw new Error("Source code cannot be null or undefined");
const { code } = transformSync(source.toString(), { mode: "strip-only" });
return {
source: swc.transformSync(data).code,
shortCircuit: true, // Skips bundled transpilation
format: format.replace("-typescript", ""),
source: code,
};
}
return { source: await nextLoad(source, context) };
};
return nextLoad(url, context);
}
3 changes: 3 additions & 0 deletions src/register/register.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { register } from "node:module";

register("./index.js", import.meta.url);
2 changes: 1 addition & 1 deletion src/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const DEFAULT_OPTIONS: Options = {

export function transformSync(
source: string,
options: Options,
options?: Options,
): TransformOutput {
// Ensure that the source code is a string
const input = `${source ?? ""}`;
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/enum.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
enum Foo {
A = "Hello, TypeScript!"
A = "Hello, TypeScript!",
}
console.log(Foo.A);
10 changes: 5 additions & 5 deletions test/loader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ test("should work as a loader", async () => {
const result = await spawnPromisified(process.execPath, [
"--experimental-strip-types",
"--no-warnings",
"--import=./dist/index.js",
"--import=./dist/register.mjs",
fixturesPath("hello.ts"),
]);

Expand All @@ -19,11 +19,11 @@ test("should work with enums", async () => {
const result = await spawnPromisified(process.execPath, [
"--experimental-strip-types",
"--no-warnings",
"--import=./dist/index.js",
"--import=./dist/register.mjs",
fixturesPath("enum.ts"),
]);

strictEqual(result.stderr, "");
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
strictEqual(result.stdout, "");
match(result.stderr, /TypeScript enum is not supported in strip-only mode/);
strictEqual(result.code, 1);
});

0 comments on commit a712b1a

Please sign in to comment.