139 lines
4.1 KiB
TypeScript

import { pathExists, readFileSync, writeFile } from 'fs-extra';
import { isPlainObject } from 'lodash';
import originalSafeEval from 'safe-eval';
import * as path from 'path';
import spawn from 'cross-spawn-promise';
import { DSLType } from './types';
export async function isNPMInstalled(args: {
workDir: string;
moduleDir: string;
npmClient?: string;
}) {
return pathExists(path.join(args.workDir, 'node_modules'));
}
export async function isNPMModuleInstalled(
args: { workDir: string; moduleDir: string; npmClient?: string },
name: string,
) {
const modulePkgJsonPath = path.resolve(args.workDir, 'node_modules', name, 'package.json');
return pathExists(modulePkgJsonPath);
}
export async function install(args: { workDir: string; moduleDir: string; npmClient?: string }) {
if (await isNPMInstalled(args)) return;
const { workDir, npmClient = 'tnpm' } = args;
try {
await spawn(npmClient, ['i'], { stdio: 'inherit', cwd: workDir } as any);
} catch (e) {
// TODO
}
}
export async function installModule(
args: { workDir: string; moduleDir: string; npmClient?: string },
name: string,
) {
if (await isNPMModuleInstalled(args, name)) return;
const { workDir, npmClient = 'tnpm' } = args;
try {
await spawn(npmClient, ['i', name], { stdio: 'inherit', cwd: workDir } as any);
} catch (e) {
// TODO
}
}
export function installTypeDTS(args: {
workDir: string;
moduleDir: string;
npmClient?: string;
dslType?: DSLType;
}) {
return installModule(args, `@types/${args.dslType || 'react'}`);
}
export async function installTypeScript(args: {
workDir: string;
moduleDir: string;
npmClient?: string;
}) {
if (await pathExists(path.join(args.workDir, 'node_modules', '.bin', 'tsc'))) return;
const { workDir, npmClient = 'tnpm' } = args;
await spawn(npmClient, ['i', 'typescript'], { stdio: 'inherit', cwd: workDir } as any);
}
export async function installPeerAndDevDeps(args: {
workDir: string;
moduleDir: string;
npmClient?: string;
}) {
const { workDir, moduleDir, npmClient = 'tnpm' } = args;
const modulePkgJsonPath = path.resolve(moduleDir, 'package.json');
if (!(await pathExists(modulePkgJsonPath))) {
return;
}
const pkgJsonPath = path.resolve(workDir, 'package.json');
if (!(await pathExists(pkgJsonPath))) {
return;
}
const modulePkgJson = await resolvePkgJson(modulePkgJsonPath);
const pkgJson = await resolvePkgJson(pkgJsonPath);
const { peerDependencies = {}, devDependencies = {} } = modulePkgJson;
pkgJson.dependencies = pkgJson.dependencies || {};
pkgJson.dependencies = {
...pkgJson.dependencies,
...peerDependencies,
...devDependencies,
};
await writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
await spawn(npmClient, ['i'], { stdio: 'inherit', cwd: workDir } as any);
}
export async function syncTypeModules(args: {
workDir: string;
moduleDir: string;
npmClient?: string;
}) {
const { workDir, moduleDir, npmClient = 'tnpm' } = args;
const pkgJsonPath = path.resolve(moduleDir, 'package.json');
if (!(await pathExists(pkgJsonPath))) {
return;
}
await installModule(args, 'typesync');
await spawn(npmClient.replace('m', 'x'), ['typesync'], { stdio: 'inherit', cwd: workDir } as any);
}
export async function resolvePkgJson(pkgJsonPath: string): Promise<{ [k: string]: any }> {
const content = await loadFile(pkgJsonPath);
const json = JSON.parse(content);
return json;
}
export function loadFile(filePath: string): string {
const content: string | Buffer = readFileSync(filePath);
if (typeof content === 'string') {
return content;
}
return content.toString();
}
export function isPrimitive(val) {
return !['object', 'function'].includes(typeof val) || val === null;
}
export function isEvaluable(value) {
if (isPrimitive(value)) return true;
if (Array.isArray(value)) {
return value.every(isEvaluable);
} else if (isPlainObject(value)) {
return Object.keys(value).every((key) => isEvaluable(value[key]));
}
return false;
}
export function safeEval(value: any) {
if (typeof value === 'string') return originalSafeEval(value);
return value;
}