@react-gnome/core
Version:
## Getting Started
200 lines (198 loc) • 7.15 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
// src/programs/init-program.ts
import { exec } from "child_process";
import { defineOption } from "clify.js";
import fsbase from "fs";
import fs from "fs/promises";
import path from "path";
import { html, Output } from "termx-markup";
import { getJsProjectConfigFile } from "../init-project/config-file-js.mjs";
import { getTsProjectConfigFile } from "../init-project/config-file-ts.mjs";
import { getJsEntryFile } from "../init-project/entry-file-js.mjs";
import { getTsEntryFile } from "../init-project/entry-file-ts.mjs";
import { getTsConfig } from "../init-project/tsconfig-file.mjs";
var ForceTypescriptArg = defineOption({
char: "t",
name: "typescript",
description: "Initiate project with typescript. By default this will be enabled automatically if a tsconfig.json file is detected.",
type: "boolean"
});
var InitProgram = class {
constructor(init) {
__publicField(this, "type", "init");
__publicField(this, "forceTypescript");
__publicField(this, "packageManager");
__publicField(this, "projectDir", process.cwd());
this.forceTypescript = init.option(ForceTypescriptArg);
}
detectPackageManager(projectFiles) {
if (this.packageManager) {
return this.packageManager;
}
if (projectFiles == null) {
projectFiles = fsbase.readdirSync(this.projectDir);
}
if (projectFiles.includes("yarn.lock")) {
this.packageManager = "yarn";
} else if (projectFiles.includes("package-lock.json")) {
this.packageManager = "npm";
} else if (projectFiles.includes("pnpm-lock.yaml")) {
this.packageManager = "pnpm";
} else if (projectFiles.includes("bun.lockb")) {
this.packageManager = "bun";
} else {
this.packageManager = "npm";
}
return this.packageManager;
}
async createFiles(projectDir, useTypescript) {
const srcDir = path.resolve(projectDir, "src");
if (!fsbase.existsSync(srcDir)) {
await fs.mkdir(srcDir);
}
const entryFilePath = path.resolve(
projectDir,
"src",
useTypescript ? "start.tsx" : "start.jsx"
);
if (!fsbase.existsSync(entryFilePath)) {
const entryFileContent = useTypescript ? getTsEntryFile() : getJsEntryFile();
Output.print(
html`<span>
Creating entrypoint file:
<span color="white">
./${path.relative(projectDir, entryFilePath)}
</span>
</span>`
);
await fs.writeFile(entryFilePath, entryFileContent);
}
const configFilePath = path.resolve(
projectDir,
useTypescript ? "react-gtk.config.ts" : "react-gtk.config.mjs"
);
if (!fsbase.existsSync(configFilePath)) {
const configFileContent = useTypescript ? getTsProjectConfigFile() : getJsProjectConfigFile();
Output.print(
html`<span>
Creating config file:
<span color="white">
./${path.relative(projectDir, configFilePath)}
</span>
</span>`
);
await fs.writeFile(configFilePath, configFileContent);
}
if (useTypescript) {
const tsconfigPath = path.resolve(projectDir, "tsconfig.json");
if (!fsbase.existsSync(tsconfigPath)) {
const fileContent = getTsConfig();
Output.print(
html`<span>
Creating tsconfig file:
<span color="white">
./${path.relative(projectDir, tsconfigPath)}
</span>
</span>`
);
await fs.writeFile(tsconfigPath, fileContent);
}
}
}
async updatePackageJson(packageJson, filepath) {
Output.print(
html`<span>
Updating scripts in:
<span color="white">./package.json</span>
</span>`
);
const scripts = packageJson.scripts ?? {};
scripts.build = `react-gtk build`;
scripts.bundle = `react-gtk bundle`;
scripts.start = `react-gtk start -m development -w`;
scripts["install-pkg"] = "meson install -C ./dist/.build/_build";
packageJson.type = "module";
packageJson.scripts = scripts;
await fs.writeFile(filepath, JSON.stringify(packageJson, null, 2));
}
async installDependencies(packageJson, useTypescript) {
const hasDep = (dep) => {
return packageJson.dependencies && !!packageJson.dependencies[dep] || packageJson.devDependencies && !!packageJson.devDependencies[dep];
};
Output.print(html`<span>Installing dependencies...</span>`);
const neededDeps = {
dev: [],
prod: []
};
if (!hasDep("react")) {
neededDeps.prod.push("react");
}
if (!hasDep("@reactgjs/renderer")) {
neededDeps.prod.push("@reactgjs/renderer");
}
if (useTypescript) {
if (!hasDep("typescript")) {
neededDeps.dev.push("typescript");
}
if (!hasDep("@types/react")) {
neededDeps.dev.push("@types/react");
}
if (!hasDep("ts-node")) {
neededDeps.dev.push("ts-node");
}
if (!hasDep("gjs-esm-types")) {
neededDeps.dev.push("gjs-esm-types");
}
}
switch (this.detectPackageManager()) {
case "yarn":
await execute(`yarn add -D ${neededDeps.dev.join(" ")}`);
await execute(`yarn add ${neededDeps.prod.join(" ")}`);
break;
case "pnpm":
await execute(`pnpm add -D ${neededDeps.dev.join(" ")}`);
await execute(`pnpm add ${neededDeps.prod.join(" ")}`);
break;
case "bun":
await execute(`bun add -D ${neededDeps.dev.join(" ")}`);
await execute(`bun add ${neededDeps.prod.join(" ")}`);
break;
case "npm":
await execute(`npm install --save-dev ${neededDeps.dev.join(" ")}`);
await execute(`npm install --save ${neededDeps.prod.join(" ")}`);
break;
}
}
async run() {
Output.print(html` <span color="green">Initializing new project.</span> `);
const projectDir = process.cwd();
const projectFiles = await fs.readdir(projectDir);
const useTypescript = this.forceTypescript.value ?? projectFiles.includes("tsconfig.json");
this.detectPackageManager(projectFiles);
await this.createFiles(projectDir, useTypescript);
const packageJsonPath = path.resolve(projectDir, "package.json");
let packageJson = {};
if (fsbase.existsSync(packageJsonPath)) {
packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
}
await this.updatePackageJson(packageJson, packageJsonPath);
await this.installDependencies(packageJson, useTypescript);
Output.print(html` <span color="green">Done.</span> `);
}
};
function execute(command) {
return new Promise((resolve) => {
exec(command, (err, stdout, stderr) => {
if (err) {
resolve({ stdout, stderr, code: err.code ?? null });
} else {
resolve({ stdout, stderr, code: 0 });
}
});
});
}
export {
InitProgram
};