@reliverse/rse
Version:
@reliverse/rse is your all-in-one companion for bootstrapping and improving any kind of projects (especially web apps built with frameworks like Next.js) — whether you're kicking off something new or upgrading an existing app. It is also a little AI-power
128 lines (127 loc) • 4.81 kB
JavaScript
import path from "@reliverse/pathkit";
import fs from "@reliverse/relifso";
import { relinka } from "@reliverse/relinka";
import { destr } from "destr";
import { glob } from "tinyglobby";
import { tsconfigJson } from "../../constants.js";
const RUNTIME_REPLACEMENTS = {
bun: {
// Node.js fs to Bun's fs
'import fs from "@reliverse/relifso"': 'import { readFile, writeFile, readdir, mkdir, stat } from "@reliverse/relifso"',
'import fs from "fs/promises"': 'import { readFile, writeFile, readdir, mkdir, stat } from "@reliverse/relifso"',
"import { promises as fs }": 'import { readFile, writeFile, readdir, mkdir, stat } from "@reliverse/relifso"',
// Node.js path to Bun's path
'import path from "path"': 'import { join, resolve, dirname, basename } from "path"',
// Node.js crypto to Bun's crypto
'import crypto from "uncrypto"': 'import { crypto } from "bun"',
// Node.js buffer to Bun's buffer
"import { Buffer }": "// Bun has Buffer globally available",
// Node.js process to Bun's process
"process.env": "Bun.env",
"process.cwd()": "import.meta.dir"
},
deno: {
// Node.js fs to Deno's fs
'import fs from "@reliverse/relifso"': 'import * as fs from "https://deno.land/std/fs/mod.ts"',
'import fs from "fs/promises"': 'import * as fs from "https://deno.land/std/fs/mod.ts"',
"import { promises as fs }": 'import * as fs from "https://deno.land/std/fs/mod.ts"',
// Node.js path to Deno's path
'import path from "path"': 'import * as path from "https://deno.land/std/path/mod.ts"',
// Node.js crypto to Deno's crypto
'import crypto from "uncrypto"': 'import * as crypto from "https://deno.land/std/crypto/mod.ts"',
// Node.js buffer to Deno's buffer
"import { Buffer }": 'import { Buffer } from "https://deno.land/std/io/buffer.ts"',
// Node.js process to Deno
"process.env": "Deno.env.toObject()",
"process.cwd()": "Deno.cwd()"
}
};
export async function convertRuntime(projectPath, targetRuntime) {
relinka(
"info",
`Converting Node.js code to ${targetRuntime} in ${projectPath}`
);
const files = await glob("**/*.{js,jsx,ts,tsx}", {
cwd: path.resolve(projectPath)
});
const runtimeReplacements = RUNTIME_REPLACEMENTS[targetRuntime];
for (const file of files) {
const filePath = path.join(projectPath, file);
const content = await fs.readFile(filePath, "utf-8");
let updatedContent = content;
for (const [nodePattern, runtimePattern] of Object.entries(
runtimeReplacements
)) {
updatedContent = updatedContent.replace(
new RegExp(nodePattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
runtimePattern
);
}
if (targetRuntime === "bun") {
if (file === "package.json") {
const packageJson = destr(
updatedContent
);
if (packageJson?.scripts) {
for (const [key, value] of Object.entries(packageJson.scripts)) {
if (typeof value === "string") {
packageJson.scripts[key] = value.replace(/^node\s/, "bun ").replace(/^ts-node\s/, "bun ");
}
}
updatedContent = JSON.stringify(packageJson, null, 2);
}
}
}
if (targetRuntime === "deno") {
if (file === "package.json") {
await fs.writeFile(
path.join(projectPath, "deno.json"),
JSON.stringify(
{
compilerOptions: {
allowJs: true,
lib: ["deno.window"]
},
importMap: "import_map.json"
},
null,
2
)
);
const packageJson = destr(
content
);
const importMap = {
imports: {}
};
if (packageJson?.dependencies) {
for (const dep of Object.keys(packageJson.dependencies)) {
importMap.imports[dep] = `https://esm.sh/${dep}`;
}
}
await fs.writeFile(
path.join(projectPath, "import_map.json"),
JSON.stringify(importMap, null, 2)
);
}
}
if (content !== updatedContent) {
await fs.writeFile(filePath, updatedContent, "utf-8");
relinka("info", `Updated runtime code in ${filePath}`);
}
}
if (targetRuntime === "bun") {
const tsconfigPath = path.join(projectPath, tsconfigJson);
if (await fs.pathExists(tsconfigPath)) {
const tsconfig = destr(
await fs.readFile(tsconfigPath, "utf-8")
);
tsconfig.compilerOptions = {
...tsconfig.compilerOptions,
types: [...tsconfig.compilerOptions?.types ?? [], "bun-types"]
};
await fs.writeJSON(tsconfigPath, tsconfig, { spaces: 2 });
}
}
relinka("success", `Converted project to ${targetRuntime}`);
}