@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
147 lines (146 loc) • 4.37 kB
JavaScript
import path from "@reliverse/pathkit";
import fs from "@reliverse/relifso";
import { relinka } from "@reliverse/relinka";
import { readPackageJSON, writePackageJSON } from "pkg-types";
import { tsconfigJson } from "../../constants.js";
const MONOREPO_CONFIGS = {
turborepo: {
"turbo.json": {
$schema: "https://turbo.build/schema.json",
globalDependencies: ["**/.env.*local"],
pipeline: {
build: {
dependsOn: ["^build"],
outputs: ["dist/**", ".next/**", "!.next/cache/**"]
},
lint: {},
dev: {
cache: false,
persistent: true
}
}
}
},
moonrepo: {
"moon.yml": `
workspace:
extends: 'typescript'
projects:
- 'apps/*'
- 'packages/*'
`
},
"bun-workspaces": {
"package.json": {
workspaces: ["apps/*", "packages/*"]
}
},
"pnpm-workspaces": {
"pnpm-workspace.yaml": `
packages:
- 'apps/*'
- 'packages/*'
`
}
};
export async function convertToMonorepo(projectPath, type, packages = [], sharedPackages = []) {
relinka("info", `Converting to ${type} monorepo in ${projectPath}`);
await fs.mkdir(path.join(projectPath, "apps"), { recursive: true });
await fs.mkdir(path.join(projectPath, "packages"), { recursive: true });
const packageJson = await readPackageJSON(
path.join(projectPath, "package.json")
);
if (!packageJson.workspaces) {
await fs.move(
path.join(projectPath, "src"),
path.join(projectPath, "apps", "web", "src"),
{ overwrite: true }
);
await fs.move(
path.join(projectPath, "package.json"),
path.join(projectPath, "apps", "web", "package.json"),
{ overwrite: true }
);
const commonFiles = [
tsconfigJson,
"eslint.config.js",
".prettierrc",
"next.config.js",
"postcss.config.js",
"tailwind.config.js"
];
for (const file of commonFiles) {
if (await fs.pathExists(path.join(projectPath, file))) {
await fs.move(
path.join(projectPath, file),
path.join(projectPath, "apps", "web", file),
{ overwrite: true }
);
}
}
}
const rootPackageJson = {
name: `${packageJson.name}-monorepo`,
private: true,
scripts: {
build: type === "turborepo" ? "turbo run build" : "bun run --cwd apps/web build",
dev: type === "turborepo" ? "turbo run dev" : "bun run --cwd apps/web dev",
lint: type === "turborepo" ? "turbo run lint" : "bun run --cwd apps/web lint"
}
};
await writePackageJSON(
path.join(projectPath, "package.json"),
rootPackageJson
);
const configs = MONOREPO_CONFIGS[type];
for (const [filename, content] of Object.entries(configs)) {
const filePath = path.join(projectPath, filename);
if (typeof content === "string") {
await fs.writeFile(filePath, content);
} else {
await fs.writeJSON(filePath, content, { spaces: 2 });
}
}
for (const pkg of packages) {
const pkgPath = path.join(projectPath, "apps", pkg);
await fs.mkdir(pkgPath, { recursive: true });
await writePackageJSON(path.join(pkgPath, "package.json"), {
name: `@${packageJson.name}/${pkg}`,
version: "0.0.0",
private: true
});
}
for (const pkg of sharedPackages) {
const pkgPath = path.join(projectPath, "packages", pkg);
await fs.mkdir(pkgPath, { recursive: true });
await writePackageJSON(path.join(pkgPath, "package.json"), {
name: `@${packageJson.name}/${pkg}`,
version: "0.0.0",
main: "./src/index.ts",
types: "./src/index.ts",
private: true
});
await fs.mkdir(path.join(pkgPath, "src"), { recursive: true });
await fs.writeFile(path.join(pkgPath, "src", "index.ts"), "export {};\n");
}
const rootTsConfig = {
compilerOptions: {
module: "esnext",
moduleResolution: "bundler",
target: "esnext",
lib: ["dom", "dom.iterable", "esnext"],
strict: true,
skipLibCheck: true,
jsx: "preserve"
},
references: [
{ path: "apps/web" },
...packages.map((pkg) => ({ path: `apps/${pkg}` })),
...sharedPackages.map((pkg) => ({ path: `packages/${pkg}` }))
]
};
await fs.writeJSON(path.join(projectPath, tsconfigJson), rootTsConfig, {
spaces: 2
});
relinka("success", `Converted to ${type} monorepo`);
}