oak-cli/lib/create.js

324 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = create;
exports.update = update;
const tslib_1 = require("tslib");
const ts = tslib_1.__importStar(require("typescript"));
const fs_1 = require("fs");
const { factory } = ts;
const file_handle_1 = require("./file-handle");
const enum_1 = require("./enum");
const config_1 = require("./config");
const template_1 = require("./template");
const path_1 = require("path");
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
const axios_1 = tslib_1.__importDefault(require("axios"));
const tip_style_1 = require("./tip-style");
const shelljs_1 = tslib_1.__importDefault(require("shelljs"));
const rename_1 = require("./rename");
const assert_1 = tslib_1.__importDefault(require("assert"));
const DEFAULT_PROJECT_NAME = 'oak_template';
const DEFAULT_PROJECT_TITLE = 'oak template project';
const prompt = [
{
type: 'input',
name: 'version',
message: 'version',
default: '1.0.0',
},
{
type: 'input',
name: 'description',
message: 'description',
},
{
name: 'useOgb',
type: 'confirm',
message: 'add oak-general-business into dependency?',
default: true,
},
{
name: 'moreDeps',
type: 'input',
message: 'do you have more dependent oak-family libraries? type their names, use comma as separator.',
default: '',
},
{
name: 'example',
type: 'confirm',
message: 'load an initial example about personal blog? It will load correspond Entities/Pages/Components/Checkers and etc.',
default: true,
},
];
/**
* 将项目的依赖关系加入
*/
function addDependencies(dependencies) {
const dependencyFile = (0, path_1.join)(process.cwd(), 'src', 'configuration', 'dependency.ts');
const program = ts.createProgram([
dependencyFile,
], {});
const sourceFile = program.getSourceFile(dependencyFile);
const { statements } = sourceFile;
const stmt1 = statements[1];
(0, assert_1.default)(ts.isVariableStatement(stmt1));
const { declarationList: { declarations: [vd] } } = stmt1;
const { name, initializer } = vd;
(0, assert_1.default)(ts.isIdentifier(name) && name.text === 'dependencyConfiguration');
(0, assert_1.default)(ts.isArrayLiteralExpression(initializer));
Object.assign(initializer, {
elements: dependencies.map(ele => factory.createStringLiteral(ele))
});
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements), sourceFile);
(0, fs_1.writeFileSync)(dependencyFile, result, { flag: 'w' });
(0, tip_style_1.Success)((0, tip_style_1.success)(`${dependencyFile} has been built.`));
}
/**
* @name 检查项目名是否已存在
* @param dirName
*/
function checkProjectName(dirName, exists) {
// 项目根路径
const rootPath = process.cwd() + '/' + dirName;
const isExists = (0, file_handle_1.checkFileExists)(rootPath);
if (isExists && !exists) {
throw new global.Error(`Cannot create a project named ${(0, tip_style_1.success)(`"${dirName}"`)} because a path with the same name exists.\nPlease choose a different project name.`);
}
else if (!isExists && exists) {
throw new global.Error(`${(0, tip_style_1.success)(dirName)} is not a valid project dir.\nPlease choose a different project name.`);
}
}
/**
* @name 获取oak-cli最新版本号
* @returns
*/
async function getOakCliVersion() {
const res = await axios_1.default.get(config_1.CNPM_BASE_URL);
return res.data['dist-tags']['latest'];
}
/**
* @name 获取微信小程序稳定基础版本库
* @returns
*/
async function getMiniVersion() {
try {
const res = await axios_1.default.get(config_1.MINI_VERSION_URL);
const versions = JSON.parse(res.data['json_data'])['total'];
const versionsSort = versions.sort((a, b) => {
return b['percentage'] - a['percentage'];
});
return versionsSort[0]['sdkVer'];
}
catch (err) {
(0, tip_style_1.Warn)((0, tip_style_1.warn)(`can't access a-o-s weixin mini version, using 3.4.1`));
return '3.4.1';
}
}
async function createWechatMpBoilplate(dir, isDev, isUpdate) {
// 获取微信小程序稳定基础版本库
const miniVersion = await getMiniVersion();
// 获取小程序项目app.json内容
const appJsonWithWeChatMp = (0, template_1.appJsonContentWithWeChatMp)(isDev);
// 获取小程序项目project.config.json内容
const projectConfigWithWeChatMp = (0, template_1.projectConfigContentWithWeChatMp)(config_1.USER_CONFIG_FILE_NAME, DEFAULT_PROJECT_TITLE, miniVersion);
// 获取小程序项目oak.config.json内容
const oakConfigWithWeChatMp = (0, template_1.oakConfigContentWithWeChatMp)();
const appJsonPathWithWeChatMp = (0, path_1.join)(dir, 'src', 'app.json');
// 小程序项目project.config.json路径
const projectConfigPathWithWeChatMp = (0, path_1.join)(dir, 'src', 'project.config.json');
// 小程序项目project.config.json路径
const oakConfigPathWithWeChatMp = (0, path_1.join)(dir, 'src', config_1.USER_CONFIG_FILE_NAME);
// 创建小程序项目project.config.json
(0, file_handle_1.checkFileExistsAndCreate)(projectConfigPathWithWeChatMp, projectConfigWithWeChatMp, enum_1.checkFileExistsAndCreateType.FILE, isUpdate);
// 创建小程序项目app.json
(0, file_handle_1.checkFileExistsAndCreate)(appJsonPathWithWeChatMp, appJsonWithWeChatMp, enum_1.checkFileExistsAndCreateType.FILE, isUpdate);
// 创建小程序项目oak.config.json
(0, file_handle_1.checkFileExistsAndCreate)(oakConfigPathWithWeChatMp, oakConfigWithWeChatMp, enum_1.checkFileExistsAndCreateType.FILE, isUpdate);
}
async function createWebBoilplate(dir, isDev, isUpdate) {
// 获取web项目oak.config.json内容
const oakConfigWithWeb = (0, template_1.oakConfigContentWithWeb)();
// web项目oak.config.json路径
const oakConfigPathWithWeb = (0, path_1.join)(dir, 'src', config_1.USER_CONFIG_FILE_NAME);
// 创建web项目oak.config.json
(0, file_handle_1.checkFileExistsAndCreate)(oakConfigPathWithWeb, oakConfigWithWeb, enum_1.checkFileExistsAndCreateType.FILE, isUpdate);
}
async function create(dirName, cmd) {
const nameOption = {
type: 'input',
name: 'name',
message: `name`,
default: dirName,
};
const titleOption = {
type: 'input',
name: 'title',
message: 'title of the project shown in App/Html',
default: dirName,
};
prompt.unshift(nameOption, titleOption);
const isDev = cmd.dev ? true : false;
const isModule = cmd.module ? true : false;
const { name, version, title, description, useOgb, moreDeps, example } = await inquirer_1.default.prompt(prompt);
// 项目根路径
const rootPath = process.cwd() + '/' + dirName;
// package.json路径
const packageJsonPath = `${rootPath}/package.json`;
// tsconfig.json路径
const tsconfigJsonPath = `${rootPath}/tsconfig.json`;
// tsconfig.build.json路径
const tsConfigBuildJsonPath = `${rootPath}/tsconfig.build.json`;
// tsconfig.build.paths.json路径
const tsConfigBuildPathsJsonPath = `${rootPath}/tsconfig.build.paths.json`;
// tsconfig.paths.json路径
const tsconfigPathsJsonPath = `${rootPath}/tsconfig.paths.json`;
// tsconfig.mp.json路径
const tsConfigMpJsonPath = `${rootPath}/tsconfig.mp.json`;
// tsconfig.web.json路径
const tsConfigWebJsonPath = `${rootPath}/tsconfig.web.json`;
// web项目根路径
const webRootPath = `${rootPath}/web`;
// 小程序项目根路径
const weChatMpRootPath = `${rootPath}/wechatMp`;
// 被复制的文件夹路径
const emptyTemplatePath = (0, path_1.join)(__dirname, '..', 'template');
const examplePath = (0, path_1.join)(__dirname, '..', 'templateExample');
//检查项目名是否存在
checkProjectName(dirName);
try {
// 创建根目录
(0, file_handle_1.checkFileExistsAndCreate)(rootPath);
// 复制项目文件
if (isModule) {
// 模块化的项目,只拷贝 src 下的内容,但跳过 pages 目录;同时拷贝 typings
const templateSrc = (0, path_1.join)(emptyTemplatePath, 'src');
const destSrc = (0, path_1.join)(rootPath, 'src');
// 确保目标 src 目录存在
if (!(0, fs_1.existsSync)(destSrc)) {
(0, fs_1.mkdirSync)(destSrc, { recursive: true });
}
const entries = (0, fs_1.readdirSync)(templateSrc, { withFileTypes: true });
for (const entry of entries) {
if (entry.name === 'pages') {
continue; // 模块模式下跳过 pages
}
const from = (0, path_1.join)(templateSrc, entry.name);
const to = (0, path_1.join)(destSrc, entry.name);
(0, file_handle_1.copyFolder)(from, to);
}
(0, file_handle_1.copyFolder)((0, path_1.join)(emptyTemplatePath, 'typings'), (0, path_1.join)(rootPath, 'typings'));
}
else {
(0, file_handle_1.copyFolder)(emptyTemplatePath, rootPath);
await createWechatMpBoilplate(weChatMpRootPath, isDev);
await createWebBoilplate(webRootPath, isDev);
/* if (!shell.which('npm')) {
Warn(warn('Sorry, this script requires npm! Please install npm!'));
shell.exit(1);
}
Success(`${success(`Waiting...`)}`);
Success(`${success(`Dependencies are now being installed`)}`);
shell.cd(dirName).exec('npm install'); */
}
const deps = [];
if (useOgb) {
deps.push('oak-general-business');
}
if (moreDeps) {
deps.push(...(moreDeps.split(',').map(ele => ele.trim()).filter(ele => !!ele)));
}
// 获取tsconfig.json内容
const tsconfigJson = (0, template_1.tsConfigJsonContent)();
const tsConfigBuildJson = (0, template_1.tsConfigBuildJsonContent)();
const tsConfigBuildPathsJson = (0, template_1.tsConfigPathsJsonContent)(deps);
const tsConfigPathsJson = (0, template_1.tsConfigPathsJsonContent)(deps);
const tsConfigMpJson = (0, template_1.tsConfigMpJsonContent)();
const tsConfigWebJson = (0, template_1.tsConfigWebJsonContent)();
// 创建tsconfig.json
(0, file_handle_1.checkFileExistsAndCreate)(tsconfigJsonPath, tsconfigJson, enum_1.checkFileExistsAndCreateType.FILE);
// 创建tsconfig.build.json
(0, file_handle_1.checkFileExistsAndCreate)(tsConfigBuildJsonPath, tsConfigBuildJson, enum_1.checkFileExistsAndCreateType.FILE);
// 创建tsconfig.build.paths.json
(0, file_handle_1.checkFileExistsAndCreate)(tsConfigBuildPathsJsonPath, tsConfigBuildPathsJson, enum_1.checkFileExistsAndCreateType.FILE);
// 创建tsconfig.paths.json
(0, file_handle_1.checkFileExistsAndCreate)(tsconfigPathsJsonPath, tsConfigPathsJson, enum_1.checkFileExistsAndCreateType.FILE);
// 创建tsconfig.mp.json
(0, file_handle_1.checkFileExistsAndCreate)(tsConfigMpJsonPath, tsConfigMpJson, enum_1.checkFileExistsAndCreateType.FILE);
// 创建tsconfig.web.json
(0, file_handle_1.checkFileExistsAndCreate)(tsConfigWebJsonPath, tsConfigWebJson, enum_1.checkFileExistsAndCreateType.FILE);
// 更新configuration/compiler.js (仅在非模块化模式下)
if (!isModule) {
(0, template_1.updateCompilerJsContent)(rootPath, deps);
}
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`Successfully created project ${(0, tip_style_1.primary)(name)}, directory name is ${(0, tip_style_1.primary)(dirName)}`)}`);
shelljs_1.default.cd(dirName);
if (deps.length > 0) {
addDependencies(deps);
}
// 获取package.json内容
const packageJson = (0, template_1.packageJsonContent)({
name: DEFAULT_PROJECT_NAME, // 后面再统一rename
version,
description,
cliName: config_1.CLI_NAME,
cliBinName: config_1.CLI_BIN_NAME,
isDev,
isModule,
dependencies: deps,
});
// 创建package.json
(0, file_handle_1.checkFileExistsAndCreate)(packageJsonPath, packageJson, enum_1.checkFileExistsAndCreateType.FILE);
// 只在非模块化模式下重命名整个项目包括web、wechatMp等
if (!isModule) {
(0, rename_1.renameProject)(rootPath, name, title, DEFAULT_PROJECT_NAME, DEFAULT_PROJECT_TITLE);
}
else {
// 模块化模式下只更新 package.json 的 name
const packageJsonFilePath = (0, path_1.join)(rootPath, 'package.json');
const packageJsonContent = (0, fs_1.readFileSync)(packageJsonFilePath, 'utf-8');
const packageJsonJson = JSON.parse(packageJsonContent);
packageJsonJson.name = name;
const newPackageJsonContent = JSON.stringify(packageJsonJson, undefined, 4);
(0, fs_1.writeFileSync)(packageJsonFilePath, newPackageJsonContent);
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`Change project name to ${(0, tip_style_1.primary)(name)}`)}`);
}
if (example && !isModule) {
// todo: copy template example files
(0, file_handle_1.copyFolder)(examplePath, rootPath, true);
}
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`Ok, type 'npm install' to install libs, then start!`)}`);
}
catch (err) {
(0, tip_style_1.Error)((0, tip_style_1.error)('create error'));
(0, tip_style_1.Error)((0, tip_style_1.error)(err));
}
}
async function update(dirName, subDirName, cmd) {
const isDev = cmd.dev ? true : false;
try {
// 需要拷贝的路径
const destPath = (0, path_1.join)(process.cwd(), dirName, subDirName);
const templatePath = (0, path_1.join)(__dirname, '..', 'template');
//检查项目名是否存在
checkProjectName(dirName, true);
if (subDirName === 'src') {
const fromPath = (0, path_1.join)(templatePath, subDirName);
(0, file_handle_1.copyFolder)(fromPath, destPath, true);
}
else if (subDirName.startsWith('wechatMp')) {
const fromPath = (0, path_1.join)(templatePath, 'wechatMp');
(0, file_handle_1.copyFolder)(fromPath, destPath, true);
await createWechatMpBoilplate(destPath, isDev, true);
}
else {
throw new global.Error(`Cannot recoganize ${(0, tip_style_1.success)(`"${subDirName}"`)} for update.\n Please choose src/wechatMp%.`);
}
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`Successfully update directory ${(0, tip_style_1.primary)(subDirName)} for project ${(0, tip_style_1.primary)(dirName)}}`)}`);
}
catch (err) {
console.error((0, tip_style_1.error)(err.message));
}
}