240810.3 · a712b1a540262fe4a2e1753f15096ee506087195
fix: now working as a loader
reading declarations
@@ -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:
esbuild.config.js
@@ -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: ["."],+ },+ }),+ ],+});
@@ -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\""@@ -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"] }
src/loader.ts
@@ -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);+}
src/register/register.mjs
@@ -0,0 +1,3 @@+import { register } from "node:module";++register("./index.js", import.meta.url);
src/transform.ts
@@ -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 ?? ""}`;
@@ -1,4 +1,4 @@ enum Foo {- A = "Hello, TypeScript!"+ A = "Hello, TypeScript!", } console.log(Foo.A);
@@ -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"), ]); @@ -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); });