Skip to content

Commit

Permalink
Add Context::changeRuntimeTo
Browse files Browse the repository at this point in the history
  • Loading branch information
wojpawlik committed Oct 8, 2023
1 parent 40d534f commit d86df3f
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 32 deletions.
22 changes: 17 additions & 5 deletions src/_transformations/specifiers.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import fc from "https://esm.sh/[email protected]";
import { name, services, transpileSpecifier } from "./specifiers.ts";
import {
name,
services,
transpileHttpsImport,
transpileSpecifier,
} from "./specifiers.ts";

const runtime = fc.stringMatching(/^\w+$/);
const join = (array: string[]) => array.join("");
const relativePrefix = fc.constantFrom("./", "../");
const extension = fc.constantFrom("js", "ts", "jsx", "tsx");
Expand All @@ -20,9 +26,15 @@ Deno.test(function localSpecifiers() {
fc.property(
relativePath,
extension,
(path, ext) =>
transpileSpecifier(`${path}.deno.m${ext}`) === `${path}.node.mjs` &&
transpileSpecifier(`${path}.deno.${ext}`) === `${path}.node.js`,
runtime,
runtime,
(path, ext, oldRuntime, newRuntime) => {
const fn = transpileSpecifier(oldRuntime, newRuntime);
return (
fn(`${path}.${oldRuntime}.m${ext}`) === `${path}.${newRuntime}.mjs` &&
fn(`${path}.${oldRuntime}.${ext}`) === `${path}.${newRuntime}.js`
);
},
),
);
});
Expand All @@ -31,7 +43,7 @@ Deno.test(function remoteSpecifiers() {
fc.assert(
fc.property(urlSegments, (segments) => {
const [, scopedPackage, , path] = segments;
return transpileSpecifier(join(segments)) === scopedPackage + path;
return transpileHttpsImport(join(segments)) === scopedPackage + path;
}),
);
});
24 changes: 12 additions & 12 deletions src/_transformations/specifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,30 @@ const version = /^@[^/?]+$/;
const path = /\/[^?]*/;
const url = re.tag()`^${re.union(services)}(${name})${version}?(${path})?.*$`;

const transpileHttpsImport = (specifier: string) =>
export const transpileHttpsImport = (specifier: string) =>
specifier.replace(url, "$1$2");

export const transpileExtension = (specifier: string) =>
specifier.replace(/[jt]sx?$/i, "js");

const transpileRelativeImport = (specifier: string) =>
transpileExtension(specifier).replace(".deno.", ".node.");

const isRelative = (specifier: string) => /^\.\.?\//.test(specifier);

export const transpileSpecifier = (specifier: string) => {
if (isRelative(specifier)) return transpileRelativeImport(specifier);
return transpileHttpsImport(specifier);
};
export const transpileSpecifier =
(oldRuntime: string, newRuntime: string) => (specifier: string) =>
isRelative(specifier)
? transpileExtension(specifier).replace(
`.${oldRuntime}.`,
`.${newRuntime}.`,
)
: transpileHttpsImport(specifier);

/**
* Replaces all import/export specifiers in `sourceFile`
* according to the specified `transpileSpecifier` function.
* The default one makes specifiers Node-friendly.
* according to the specified `fn`.
*/
export function transpileSpecifiers(
export function replaceSpecifiers(
sourceFile: SourceFile,
fn = transpileSpecifier,
fn: (specifier: string) => string,
) {
for (const statement of sourceFile.getStatements()) {
if (
Expand Down
21 changes: 21 additions & 0 deletions src/context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import path from "node:path";
import {
replaceSpecifiers,
transpileSpecifier,
} from "./_transformations/specifiers.ts";
import { type Config, parse } from "./config.ts";
import { Project, ts } from "./deps.deno.ts";

Expand All @@ -18,6 +22,7 @@ export class Context {
public baseDir: string;
public config: Config;
readonly project: Project;
private _runtime = "deno";

/**
* Synchronously loads `tsconfig.json` and `"files"`.
Expand All @@ -42,4 +47,20 @@ export class Context {
resolve(...pathSegments: string[]) {
return path.join(this.baseDir, ...pathSegments);
}

changeRuntimeTo(newRuntime: string) {
const label = `Changing runtime from ${this._runtime} to ${newRuntime}`;
const fn = transpileSpecifier(this._runtime, newRuntime);

console.time(label);
for (const sourceFile of this.project.getSourceFiles()) {
if (sourceFile.getBaseName().includes(`.${this._runtime}.`)) {
sourceFile.forget();
} else {
replaceSpecifiers(sourceFile, fn);
}
}
this._runtime = newRuntime;
console.timeEnd(label);
}
}
16 changes: 1 addition & 15 deletions src/deno2node.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { shimEverything } from "./_transformations/shim.ts";
import { transpileSpecifiers } from "./_transformations/specifiers.ts";
import { vendorEverything } from "./_transformations/vendor.ts";
import { type Context } from "./context.ts";
import { type SourceFile } from "./deps.deno.ts";

const isDenoSpecific = (sourceFile: SourceFile) =>
sourceFile.getBaseNameWithoutExtension().toLowerCase().endsWith(".deno");

/**
* Attempts to transform arbitrary `ctx.project` into a valid Node.js project:
Expand Down Expand Up @@ -44,16 +39,7 @@ const isDenoSpecific = (sourceFile: SourceFile) =>
* [shim file]: https://github.com/fromdeno/deno2node/blob/main/src/shim.node.ts
*/
export function deno2node(ctx: Context): void {
console.time("Basic transformations");
for (const sourceFile of ctx.project.getSourceFiles()) {
if (isDenoSpecific(sourceFile)) {
ctx.project.removeSourceFile(sourceFile);
continue;
}
transpileSpecifiers(sourceFile);
}
console.timeEnd("Basic transformations");

ctx.changeRuntimeTo("node");
vendorEverything(ctx);
shimEverything(ctx);
}

0 comments on commit d86df3f

Please sign in to comment.