sensai
Version:
Because even AI needs a master
132 lines (131 loc) • 4.64 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _promises = require("node:fs/promises");
const _nodepath = require("node:path");
const _nodechild_process = require("node:child_process");
const _fs = require("../utils/fs");
const _constants = require("../constants");
const _object = require("../utils/object");
const _default = async ()=>{
try {
await Promise.all([
setupSensaiTypes(),
setupTsConfig(),
setupPackageJson(),
setupGitIgnore()
]);
} catch (error) {
// TODO we should never have errors or make sure one error does not prevent the others to run
console.error(error);
}
};
/**
* Add types needed by sensai to facilitate developement experience with Typescript.
* Those types are added to the artifacts folder `.sensai` as they should never be modified
* by the user.
*
* @note we will rewrite sensai types everytime the user runs the development server.
*/ const setupSensaiTypes = async (rootPath = process.cwd())=>{
const artifacts = (0, _nodepath.join)(rootPath, `.${_constants.ARTIFACTS_NAMESPACE}`, "types");
await (0, _promises.mkdir)(artifacts, {
recursive: true
});
await (0, _fs.write)((0, _nodepath.join)(artifacts, "sensai.d.ts"), `
declare global {
const guard: typeof import('sensai/guard')['default']
}
export { guard }
`);
};
/**
* Create or update typescript configuration file (tsconfig.json)
*/ const setupTsConfig = async (rootPath = process.cwd())=>{
const filePath = (0, _nodepath.join)(rootPath, "tsconfig.json");
const hasTsConfig = await (0, _fs.hasFile)(filePath);
const config = {
exclude: [
"node_modules",
"dist"
],
include: [
".sensai/types/**/*.ts",
"**/*.ts",
"**/*.tsx"
]
};
if (hasTsConfig) {
try {
const { default: json } = require(filePath);
// console.log("UPDATE TSCONFIG");
await (0, _fs.write)(filePath, JSON.stringify((0, _object.merge)(json, config), null, 2));
} catch (error) {
console.error(error);
}
} else {
// console.log("CREATE TSCONFIG");
await (0, _fs.write)(filePath, JSON.stringify(config, null, 2));
}
};
/**
* Install dependencies such as typescript and node types if they are missing.
*/ const setupPackageJson = async ()=>{
// filter dependencies to install
const deps = (await Promise.all([
"typescript",
"@types/node"
].map(async (name)=>{
const bool = await hasDependency(name);
if (!bool) return name;
}))).filter(Boolean);
if (deps.length > 0) await installDevDependency(deps);
};
// TODO We might need a more robust solution, as a dependency might exist in node_modules but not in the package.json
const hasDependency = async (name)=>{
const depPath = (0, _nodepath.join)(process.cwd(), "node_modules", name);
return (0, _fs.hasFile)(depPath);
};
const installDevDependency = async (deps, engine = getPackageManager())=>{
return new Promise(async (resolve, reject)=>{
(0, _nodechild_process.exec)(`${engine} install --save-dev ${deps.join(" ")}`, (error, _stdout, stderr)=>{
if (error) {
reject(error);
return;
}
if (stderr) {
reject(stderr);
return;
}
resolve(true);
});
});
};
/**
* Get package manager.
*/ const getPackageManager = ()=>{
const userAgent = process.env.npm_config_user_agent || "";
if (userAgent.startsWith("pnpm")) return "pnpm";
if (userAgent.startsWith("yarn")) return "yarn";
if (userAgent.startsWith("bun")) return "bun";
return "npm";
};
const artifactsRegexp = new RegExp(`(^|\\n)\\.${_constants.ARTIFACTS_NAMESPACE}(\/)?($|\\n)`);
/**
* We will silently add sensai artofacts to the git ignore file if it exists.
*/ const setupGitIgnore = async (rootPath = process.cwd())=>{
const filePath = (0, _nodepath.join)(rootPath, ".gitignore");
if (await (0, _fs.hasFile)(filePath)) {
const gitignore = await (0, _promises.readFile)(filePath, "utf-8");
const hasIgnore = artifactsRegexp.test(gitignore);
if (!hasIgnore) {
await (0, _fs.write)(filePath, `${gitignore}\n\n# Sensai build artifacts\n.${_constants.ARTIFACTS_NAMESPACE}/`);
}
}
};