modules/material-parser/src/localize.ts (73 lines of code) (raw):
import spawn from 'cross-spawn-promise';
import { ensureDir, ensureFile, writeFile } from 'fs-extra';
import { join, resolve } from 'path';
import uuid from 'short-uuid';
import { debug } from './core';
import { IMaterializeOnlineOptions, IMaterializeOnlinePackageAndVersionOptions } from './types';
const log = debug.extend('localize');
/**
* 创建组件包
*
* @private
* @param {{
* pkgName: string;
* pkgVersion: string;
* }} params
* @returns {Promise<void>}
* @memberof OnlineAccesser
*/
export async function createFakePackage(params: {
workDir: string;
pkgName: string;
pkgVersion: string;
npmClient?: string;
}): Promise<void> {
// 创建临时组件包
const { workDir } = params;
const pkgJsonFilePath = join(workDir, 'package.json');
await ensureFile(pkgJsonFilePath);
await writeFile(
pkgJsonFilePath,
JSON.stringify(
{
name: params.pkgName,
version: params.pkgVersion || '0.0.0',
dependencies: {
[params.pkgName]: params.pkgVersion || 'latest',
react: 'latest',
'react-dom': 'latest',
'parse-prop-types': '^0.3.0',
typesync: 'latest',
},
},
null,
2,
),
);
// 安装依赖
const npmClient = params.npmClient || 'tnpm';
await spawn(npmClient, ['i'], { stdio: 'inherit', cwd: workDir } as any);
}
/**
* 创建临时目录
*
* @private
* @returns {Promise<string>} 返回临时文件夹路径
* @memberof LocalGenerator
*/
export async function createworkDir(tempDir?: string): Promise<string> {
const workDirName = uuid.generate();
const workDir = resolve(tempDir || '../../node_modules/.temp/', workDirName);
await ensureDir(workDir);
log('create temp dir successfully', workDir);
return workDir;
}
/**
* 分离物料组件名称和版本号
*
* @private
* @param {string} pkgNameWithVersion
* @returns {{ [key: string]: any }}
* @memberof OnlineAccesser
*/
export function getPkgNameAndVersion(pkgNameWithVersion: string): { [key: string]: any } {
const matches = pkgNameWithVersion.match(/(@[^/]+)$/);
if (!matches) {
return {
name: pkgNameWithVersion,
};
}
const name = pkgNameWithVersion.replace(matches[0], '');
return {
version: matches[0].slice(1),
name,
};
}
// 将问题转化为本地物料化场景
export default async function localize(options: IMaterializeOnlineOptions): Promise<{
workDir: string;
moduleDir: string;
entry?: string;
}> {
// 创建临时目录
const workDir = await createworkDir(options.tempDir);
await ensureDir(workDir);
let { name, version = 'latest' } = options as IMaterializeOnlinePackageAndVersionOptions;
if (!name) {
const pkgNameAndVersion = getPkgNameAndVersion(options.entry);
name = pkgNameAndVersion.name;
version = pkgNameAndVersion.version;
}
// 创建组件包
await createFakePackage({
pkgName: name,
pkgVersion: version,
workDir,
npmClient: options.npmClient,
});
const result = {
workDir,
moduleDir: join(workDir, 'node_modules', name),
entry: undefined,
};
if ((options as IMaterializeOnlinePackageAndVersionOptions)?.name) {
result.entry = options.entry;
}
return result;
}