@ 261027.7

240810.3 · a712b1a540262fe4a2e1753f15096ee506087195

fix: now working as a loader

reading declarations

README.md

@@ -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

new file mode 100644@@ -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: ["."],+			},+		}),+	],+});

package.json

@@ -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

new file mode 100644@@ -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 ?? ""}`;

test/fixtures/enum.ts

@@ -1,4 +1,4 @@ enum Foo {-    A = "Hello, TypeScript!"+	A = "Hello, TypeScript!", } console.log(Foo.A);

test/loader.test.js

@@ -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); });