Skip to content

Commit

Permalink
feat: add transform loader
Browse files Browse the repository at this point in the history
  • Loading branch information
marco-ippolito committed Aug 20, 2024
1 parent 9fe26d2 commit a6c4f2a
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 33 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ 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
node --experimental-strip-types --import="amaro/strip" script.ts
```

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

### How to update SWC
Expand Down
62 changes: 42 additions & 20 deletions esbuild.config.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,46 @@
const { copy } = require("esbuild-plugin-copy");
const esbuild = require("esbuild");
const { build } = 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: ["."],
},
}),
copy({
assets: {
from: ["./lib/LICENSE", "./lib/package.json"],
to: ["."],
},
}),
const copyPlugin = copy({
assets: [
{
from: ["./src/register/register-strip.mjs"],
to: ["."],
},
{
from: ["./src/register/register-transform.mjs"],
to: ["."],
},
{
from: ["./lib/LICENSE", "./lib/package.json"],
to: ["."],
},
],
});

(async () => {
await build({
entryPoints: ["src/index.ts"],
bundle: true,
platform: "node",
target: "node20",
outfile: "dist/index.js",
plugins: [copyPlugin],
});

await build({
entryPoints: ["src/strip-loader.ts"],
bundle: false,
outfile: "dist/strip-loader.js",
platform: "node",
target: "node20",
});

await build({
entryPoints: ["src/transform-loader.ts"],
bundle: false,
outfile: "dist/transform-loader.js",
platform: "node",
target: "node20",
});
})();
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@
},
"exports": {
".": "./dist/index.js",
"./register": "./dist/register.mjs"
"./strip": "./dist/register-strip.mjs",
"./transform": "./dist/register-transform.mjs"
},
"files": ["dist", "LICENSE.md"]
}
"files": [
"dist",
"LICENSE.md"
]
}
1 change: 0 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { transformSync } from "./transform.ts";
export { load } from "./loader.ts";
3 changes: 3 additions & 0 deletions src/register/register-strip.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { register } from "node:module";

register("./strip-loader.js", import.meta.url);
3 changes: 3 additions & 0 deletions src/register/register-transform.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { register } from "node:module";

register("./transform-loader.js", import.meta.url);
3 changes: 0 additions & 3 deletions src/register/register.mjs

This file was deleted.

13 changes: 10 additions & 3 deletions src/loader.ts → src/strip-loader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { LoadFnOutput, LoadHookContext } from "node:module";
import type { Options } from "../lib/wasm";
import { transformSync } from "./index.ts";
import { transformSync } from "./index.js";

type NextLoad = (
url: string,
Expand All @@ -20,14 +20,21 @@ export async function load(
...context,
format: "module",
});
if (source == null)

if (source == null) {
throw new Error("Source code cannot be null or undefined");
}

const { code } = transformSync(source.toString(), {
mode: "strip-only",
} as Options);

return {
format: format.replace("-typescript", ""),
source: code,
// Source map is not necessary in strip-only mode. However, to map the source
// file in debuggers to the original TypeScript source, add a sourceURL magic
// comment to hint that it is a generated source.
source: `${code}\n\n//# sourceURL=${url}`,
};
}
return nextLoad(url, context);
Expand Down
47 changes: 47 additions & 0 deletions src/transform-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { LoadFnOutput, LoadHookContext } from "node:module";
import type { Options } from "../lib/wasm";
import { transformSync } from "./index.js";

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, map } = transformSync(source.toString(), {
mode: "transform",
sourceMap: true,
filename: url,
} as Options);

let output = code;

if (map) {
const base64SourceMap = Buffer.from(map).toString("base64");
output = `${code}\n\n//# sourceMappingURL=data:application/json;base64,${base64SourceMap}`;
}

return {
format: format.replace("-typescript", ""),
source: output,
};
}
return nextLoad(url, context);
}
5 changes: 5 additions & 0 deletions src/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import swc from "../lib/wasm.js";

const DEFAULT_OPTIONS = {
mode: "strip-only",
// default transform will only work when mode is "transform"
transform: {
verbatimModuleSyntax: true,
nativeClassProperties: true,
},
} as Options;

export function transformSync(
Expand Down
4 changes: 2 additions & 2 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/register.mjs",
"--import=./dist/register-strip.mjs",
fixturesPath("hello.ts"),
]);

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

Expand Down

0 comments on commit a6c4f2a

Please sign in to comment.