feat(create): 支持从空白模板创建前端项目
- 新增 create 命令,可选择 Ant Design 5 或 6 模板 - 自动生成并支持手动覆盖 Java Git、仓库名、应用标识和生产分支 - 根据 Java Git 仓库名生成小驼峰 appIdentifier - 使用 AES-256-GCM 混淆模板及默认 Java Git 地址 - 创建后删除模板 Git 记录,不自动安装依赖 - 补充创建流程测试和使用说明master
parent
dd307e7262
commit
ab47a55d72
29
README.md
29
README.md
|
|
@ -10,7 +10,7 @@
|
||||||
- Git
|
- Git
|
||||||
- Yarn
|
- Yarn
|
||||||
|
|
||||||
`src/push.js` 使用的模块均为 Node.js 内置模块,无需安装运行时依赖。
|
工具使用的模块均为 Node.js 内置模块,无需安装运行时依赖。
|
||||||
|
|
||||||
业务项目的依赖安装和项目构建只使用 Yarn;Windows 下会自动调用 `yarn.cmd`。
|
业务项目的依赖安装和项目构建只使用 Yarn;Windows 下会自动调用 `yarn.cmd`。
|
||||||
|
|
||||||
|
|
@ -36,9 +36,32 @@ npm install -g
|
||||||
|
|
||||||
在业务项目根目录创建或修改 `jjb.config.js`:
|
在业务项目根目录创建或修改 `jjb.config.js`:
|
||||||
|
|
||||||
`javaGit` 必须是完整的 Git 克隆地址,不能只填写 Git 服务地址。
|
`javaGit` 必须是完整的 Git 克隆地址,不能只填写 Git 服务地址。[jsconfig.json](../../../asdas/jsconfig.json)
|
||||||
|
|
||||||
## 使用
|
## 创建项目
|
||||||
|
|
||||||
|
在存放项目根目录执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zy-gbs-cmd create
|
||||||
|
```
|
||||||
|
|
||||||
|
根据提示输入项目目录名并选择模板:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. 1.0(Ant Design 5)
|
||||||
|
2. 2.0(Ant Design 6)
|
||||||
|
```
|
||||||
|
|
||||||
|
工具会为 `javaGit`、`javaGitName`、`appIdentifier` 和 production 分支生成默认值,直接回车即可使用,也可以手动输入。`appIdentifier` 根据最终 `javaGit` 的仓库名去除 `zcloud_gbs_`、`_gwj` 后转换为小驼峰。
|
||||||
|
|
||||||
|
创建成功后模板自带的 Git 记录会被删除,工具不会自动安装依赖。进入新项目后手动执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
## 推送项目
|
||||||
|
|
||||||
在业务项目根目录执行:
|
在业务项目根目录执行:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,8 @@ const { version } = require('../package.json');
|
||||||
/*
|
/*
|
||||||
* 命令启动入口:
|
* 命令启动入口:
|
||||||
* 1. package.json 的 bin 配置把全局命令 zy-gbs-cmd 指向本文件。
|
* 1. package.json 的 bin 配置把全局命令 zy-gbs-cmd 指向本文件。
|
||||||
* 2. 用户执行 zy-gbs-cmd push java production。
|
* 2. 本文件解析 create、push、help、v 等用户参数。
|
||||||
* 3. 本文件从 process.argv 取出 push、java、production。
|
* 3. 根据命令调用对应模块执行项目创建或构建推送。
|
||||||
* 4. 确认是 push java 后,调用 src/push.js 开始真正的构建和推送。
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function printHelp() {
|
function printHelp() {
|
||||||
|
|
@ -16,6 +15,7 @@ function printHelp() {
|
||||||
使用:
|
使用:
|
||||||
zy-gbs-cmd help 查看帮助
|
zy-gbs-cmd help 查看帮助
|
||||||
zy-gbs-cmd v 查看版本
|
zy-gbs-cmd v 查看版本
|
||||||
|
zy-gbs-cmd create 从空白模板创建项目
|
||||||
zy-gbs-cmd push java [environment] 构建并推送到 Java Git 仓库
|
zy-gbs-cmd push java [environment] 构建并推送到 Java Git 仓库
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
@ -34,6 +34,11 @@ async function main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (command === 'create' && !argument) {
|
||||||
|
await require('../src/create')();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (command === 'push' && argument === 'java') {
|
if (command === 'push' && argument === 'java') {
|
||||||
// 第 2 步:进入推送主流程。production 会作为 environment 传给 pushJava。
|
// 第 2 步:进入推送主流程。production 会作为 environment 传给 pushJava。
|
||||||
await require('../src/push')({ environment });
|
await require('../src/push')({ environment });
|
||||||
|
|
@ -46,6 +51,6 @@ async function main() {
|
||||||
|
|
||||||
main().catch(error => {
|
main().catch(error => {
|
||||||
// 统一设置非零退出码,便于终端和 CI 判断命令执行失败。
|
// 统一设置非零退出码,便于终端和 CI 判断命令执行失败。
|
||||||
console.error(`推送失败: ${error.message}`);
|
console.error(`执行失败: ${error.message}`);
|
||||||
process.exitCode = 1;
|
process.exitCode = 1;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
"zy-gbs-cmd": "bin/command.js"
|
"zy-gbs-cmd": "bin/command.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test/package-manager.test.js && node test/push.test.js && node bin/command.js help",
|
"test": "node test/package-manager.test.js && node test/push.test.js && node test/create.test.js && node test/template-repository.test.js && node bin/command.js help",
|
||||||
"prepublishOnly": "yarn test",
|
"prepublishOnly": "yarn test",
|
||||||
"patch": "npm version patch",
|
"patch": "npm version patch",
|
||||||
"minor": "npm version minor",
|
"minor": "npm version minor",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,299 @@
|
||||||
|
const childProcess = require('child_process');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const readline = require('readline/promises');
|
||||||
|
const getTemplateRepository = require('./template-repository');
|
||||||
|
const { getDefaultJavaGitRoot } = getTemplateRepository;
|
||||||
|
|
||||||
|
const TEMPLATE_OPTIONS = [
|
||||||
|
{ branch: '1.0', label: '1.0(Ant Design 5)' },
|
||||||
|
{ branch: '2.0', label: '2.0(Ant Design 6)' },
|
||||||
|
];
|
||||||
|
const INVALID_PROJECT_NAME = /[<>:"/\\|?*\u0000-\u001f]/;
|
||||||
|
const RESERVED_PROJECT_NAME = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\..*)?$/i;
|
||||||
|
|
||||||
|
function getProjectBaseName(projectName) {
|
||||||
|
return projectName.endsWith('-react')
|
||||||
|
? projectName.slice(0, -'-react'.length)
|
||||||
|
: projectName;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateProjectName(projectName) {
|
||||||
|
const normalizedName = projectName.trim();
|
||||||
|
const baseName = getProjectBaseName(normalizedName);
|
||||||
|
|
||||||
|
if (!normalizedName || normalizedName === '.' || normalizedName === '..') {
|
||||||
|
throw new Error('项目目录名不能为空或特殊路径');
|
||||||
|
}
|
||||||
|
if (INVALID_PROJECT_NAME.test(normalizedName) || /[. ]$/.test(normalizedName)) {
|
||||||
|
throw new Error('项目目录名包含非法字符');
|
||||||
|
}
|
||||||
|
if (RESERVED_PROJECT_NAME.test(normalizedName)) {
|
||||||
|
throw new Error('项目目录名不能使用 Windows 保留名称');
|
||||||
|
}
|
||||||
|
if (!baseName) {
|
||||||
|
throw new Error('项目目录名去掉 -react 后不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultJavaGit(projectName) {
|
||||||
|
return `${getDefaultJavaGitRoot()}/${getProjectBaseName(projectName)}.git`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRepositoryName(javaGit) {
|
||||||
|
const normalizedGit = javaGit.trim().replace(/[?#].*$/, '').replace(/[\\/]+$/, '');
|
||||||
|
const repositoryName = normalizedGit.split(/[/:\\]/).pop().replace(/\.git$/i, '');
|
||||||
|
|
||||||
|
if (!repositoryName) {
|
||||||
|
throw new Error('无法从 Java Git 地址提取仓库名称');
|
||||||
|
}
|
||||||
|
return repositoryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toCamelCase(value) {
|
||||||
|
const parts = value.split(/[-_]+/).filter(Boolean);
|
||||||
|
if (!parts.length) {
|
||||||
|
throw new Error('无法根据 Java Git 地址生成 appIdentifier');
|
||||||
|
}
|
||||||
|
|
||||||
|
const [first, ...rest] = parts;
|
||||||
|
return `${first.charAt(0).toLowerCase()}${first.slice(1)}${rest
|
||||||
|
.map(part => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
|
||||||
|
.join('')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultAppIdentifier(javaGit) {
|
||||||
|
const repositoryName = getRepositoryName(javaGit)
|
||||||
|
.replace(/^zcloud_gbs_/, '')
|
||||||
|
.replace(/_gwj$/, '');
|
||||||
|
return toCamelCase(repositoryName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceConfigValue(source, pattern, value, fieldName) {
|
||||||
|
let replacements = 0;
|
||||||
|
const result = source.replace(pattern, (matched, prefix) => {
|
||||||
|
replacements += 1;
|
||||||
|
return `${prefix}${JSON.stringify(value)}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (replacements !== 1) {
|
||||||
|
throw new Error(`jjb.config.js 中无法唯一定位 ${fieldName}`);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateConfigSource(source, values) {
|
||||||
|
// 模板中 development 和 production 都有 javaGitBranch,分支正则必须限定在 production 块内。
|
||||||
|
let result = replaceConfigValue(
|
||||||
|
source,
|
||||||
|
/^(\s*javaGit\s*:\s*)["'][^"'\r\n]*["']/gm,
|
||||||
|
values.javaGit,
|
||||||
|
'javaGit'
|
||||||
|
);
|
||||||
|
result = replaceConfigValue(
|
||||||
|
result,
|
||||||
|
/^(\s*javaGitName\s*:\s*)["'][^"'\r\n]*["']/gm,
|
||||||
|
values.javaGitName,
|
||||||
|
'javaGitName'
|
||||||
|
);
|
||||||
|
result = replaceConfigValue(
|
||||||
|
result,
|
||||||
|
/(\bproduction\s*:\s*\{[\s\S]*?^\s*javaGitBranch\s*:\s*)["'][^"'\r\n]*["']/gm,
|
||||||
|
values.productionBranch,
|
||||||
|
'environment.production.javaGitBranch'
|
||||||
|
);
|
||||||
|
return replaceConfigValue(
|
||||||
|
result,
|
||||||
|
/^(\s*appIdentifier\s*:\s*)["'][^"'\r\n]*["']/gm,
|
||||||
|
values.appIdentifier,
|
||||||
|
'appIdentifier'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateConfig(configPath, expectedValues) {
|
||||||
|
delete require.cache[require.resolve(configPath)];
|
||||||
|
const importedConfig = require(configPath);
|
||||||
|
const config = importedConfig.default || importedConfig;
|
||||||
|
const actualValues = {
|
||||||
|
javaGit: config.javaGit,
|
||||||
|
javaGitName: config.javaGitName,
|
||||||
|
appIdentifier: config.appIdentifier,
|
||||||
|
productionBranch: config.environment
|
||||||
|
&& config.environment.production
|
||||||
|
&& config.environment.production.javaGitBranch,
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(expectedValues).forEach(field => {
|
||||||
|
if (actualValues[field] !== expectedValues[field]) {
|
||||||
|
throw new Error(`jjb.config.js 写入失败: ${field}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
delete require.cache[require.resolve(configPath)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateProjectConfig(projectPath, values) {
|
||||||
|
const configPath = path.join(projectPath, 'jjb.config.js');
|
||||||
|
if (!fs.existsSync(configPath)) {
|
||||||
|
throw new Error('空白模板中未找到 jjb.config.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
const source = fs.readFileSync(configPath, 'utf8');
|
||||||
|
fs.writeFileSync(configPath, updateConfigSource(source, values), 'utf8');
|
||||||
|
validateConfig(configPath, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function askProjectName(input) {
|
||||||
|
while (true) {
|
||||||
|
const answer = await input.question('请输入项目目录名: ');
|
||||||
|
try {
|
||||||
|
return validateProjectName(answer);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function selectTemplate(input) {
|
||||||
|
console.log('请选择模板版本:');
|
||||||
|
TEMPLATE_OPTIONS.forEach((option, index) => {
|
||||||
|
console.log(` ${index + 1}. ${option.label}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const answer = await input.question('请输入序号: ');
|
||||||
|
const selected = TEMPLATE_OPTIONS[Number(answer) - 1];
|
||||||
|
if (selected) {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
console.log('请输入有效序号。');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function askWithDefault(input, message, defaultValue, validate) {
|
||||||
|
while (true) {
|
||||||
|
const answer = (await input.question(`${message}\n(${defaultValue}): `)).trim();
|
||||||
|
const value = answer || defaultValue;
|
||||||
|
try {
|
||||||
|
if (validate) {
|
||||||
|
validate(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validatePathSegment(value, fieldName) {
|
||||||
|
if (!value || INVALID_PROJECT_NAME.test(value) || value === '.' || value === '..') {
|
||||||
|
throw new Error(`${fieldName} 不能作为目录或文件名称`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateGitBranch(branch) {
|
||||||
|
const result = childProcess.spawnSync('git', ['check-ref-format', '--branch', branch], {
|
||||||
|
stdio: 'ignore',
|
||||||
|
});
|
||||||
|
if (result.status !== 0) {
|
||||||
|
throw new Error('请输入有效的 Git 分支名称');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneTemplate(template, temporaryRoot, temporaryProject) {
|
||||||
|
console.log(`正在拉取空白模板 ${template.label}...`);
|
||||||
|
childProcess.execFileSync('git', [
|
||||||
|
'clone',
|
||||||
|
'--quiet',
|
||||||
|
'--depth',
|
||||||
|
'1',
|
||||||
|
'--single-branch',
|
||||||
|
'--branch',
|
||||||
|
template.branch,
|
||||||
|
getTemplateRepository(),
|
||||||
|
temporaryProject,
|
||||||
|
], { cwd: temporaryRoot, stdio: 'inherit' });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createProject() {
|
||||||
|
// 全部输入确认后才克隆到临时目录,配置验证成功再移动为正式项目,避免留下半成品。
|
||||||
|
const projectRoot = process.cwd();
|
||||||
|
const input = readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||||
|
let temporaryRoot;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const projectName = await askProjectName(input);
|
||||||
|
const targetProject = path.join(projectRoot, projectName);
|
||||||
|
if (fs.existsSync(targetProject)) {
|
||||||
|
throw new Error(`目标目录已存在: ${targetProject}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const template = await selectTemplate(input);
|
||||||
|
const defaultJavaGit = getDefaultJavaGit(projectName);
|
||||||
|
const javaGit = await askWithDefault(
|
||||||
|
input,
|
||||||
|
'请输入 Java Git 地址',
|
||||||
|
defaultJavaGit,
|
||||||
|
getRepositoryName
|
||||||
|
);
|
||||||
|
const defaultJavaGitName = getRepositoryName(javaGit);
|
||||||
|
const defaultAppIdentifier = getDefaultAppIdentifier(javaGit);
|
||||||
|
const javaGitName = await askWithDefault(
|
||||||
|
input,
|
||||||
|
'请输入 javaGitName',
|
||||||
|
defaultJavaGitName,
|
||||||
|
value => validatePathSegment(value, 'javaGitName')
|
||||||
|
);
|
||||||
|
const appIdentifier = await askWithDefault(
|
||||||
|
input,
|
||||||
|
'请输入 appIdentifier',
|
||||||
|
defaultAppIdentifier,
|
||||||
|
value => validatePathSegment(value, 'appIdentifier')
|
||||||
|
);
|
||||||
|
const productionBranch = await askWithDefault(
|
||||||
|
input,
|
||||||
|
'请输入 production 分支',
|
||||||
|
'main',
|
||||||
|
validateGitBranch
|
||||||
|
);
|
||||||
|
|
||||||
|
temporaryRoot = fs.mkdtempSync(path.join(projectRoot, '.zy-gbs-cmd-create-'));
|
||||||
|
const temporaryProject = path.join(temporaryRoot, 'project');
|
||||||
|
cloneTemplate(template, temporaryRoot, temporaryProject);
|
||||||
|
updateProjectConfig(temporaryProject, {
|
||||||
|
javaGit,
|
||||||
|
javaGitName,
|
||||||
|
appIdentifier,
|
||||||
|
productionBranch,
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.rmSync(path.join(temporaryProject, '.git'), { recursive: true, force: true });
|
||||||
|
fs.renameSync(temporaryProject, targetProject);
|
||||||
|
|
||||||
|
console.log(`项目创建成功: ${targetProject}`);
|
||||||
|
console.log(`模板版本: ${template.label}`);
|
||||||
|
console.log(`javaGit: ${javaGit}`);
|
||||||
|
console.log(`javaGitName: ${javaGitName}`);
|
||||||
|
console.log(`appIdentifier: ${appIdentifier}`);
|
||||||
|
console.log(`production 分支: ${productionBranch}`);
|
||||||
|
console.log(`请进入项目目录后执行: yarn install`);
|
||||||
|
} finally {
|
||||||
|
input.close();
|
||||||
|
if (temporaryRoot) {
|
||||||
|
try {
|
||||||
|
fs.rmSync(temporaryRoot, { recursive: true, force: true });
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`临时目录清理失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = createProject;
|
||||||
|
module.exports.getDefaultAppIdentifier = getDefaultAppIdentifier;
|
||||||
|
module.exports.getDefaultJavaGit = getDefaultJavaGit;
|
||||||
|
module.exports.getProjectBaseName = getProjectBaseName;
|
||||||
|
module.exports.getRepositoryName = getRepositoryName;
|
||||||
|
module.exports.updateConfigSource = updateConfigSource;
|
||||||
|
module.exports.validateProjectName = validateProjectName;
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
const TEMPLATE_REPOSITORY = {
|
||||||
|
ciphertext: 'cxR6dGDVpS51WPbHS21TA6o0wbVouuzXVfbv6lz+ppiYksW4Sb1JZOAap4XgkWZtxxydHCEYciQxPavixupdLw==',
|
||||||
|
iv: 'KilocwyDH0kSLAOZ',
|
||||||
|
authTag: 'sH48QfZClkASGy8gOotjnA==',
|
||||||
|
};
|
||||||
|
const DEFAULT_JAVA_GIT_ROOT = {
|
||||||
|
ciphertext: 'qvY4mKNSVQWHIXach/Py87nOSx0/SNu2oTVq5eP620eutGmv',
|
||||||
|
iv: 'lwToXY+Q5UNPbxZE',
|
||||||
|
authTag: 't3FAc0J5bTLP3fLWLTRh5w==',
|
||||||
|
};
|
||||||
|
const KEY_DATA = [
|
||||||
|
142, 229, 64, 17, 180, 222, 153, 195,
|
||||||
|
169, 83, 61, 150, 52, 62, 139, 6,
|
||||||
|
18, 96, 219, 59, 173, 135, 206, 23,
|
||||||
|
242, 21, 114, 152, 102, 235, 121, 191,
|
||||||
|
];
|
||||||
|
const KEY_MASK = [
|
||||||
|
147, 217, 89, 108, 185, 148, 24, 86,
|
||||||
|
5, 239, 241, 7, 32, 16, 246, 137,
|
||||||
|
247, 234, 180, 150, 199, 181, 214, 139,
|
||||||
|
221, 241, 15, 34, 175, 234, 162, 243,
|
||||||
|
];
|
||||||
|
|
||||||
|
function decrypt(value) {
|
||||||
|
// 地址只做客户端源码混淆,运行时使用 Node.js 内置 crypto 解密,不需要用户提供密钥。
|
||||||
|
const key = Buffer.from(KEY_DATA.map((value, index) => value ^ KEY_MASK[index]));
|
||||||
|
const decipher = crypto.createDecipheriv(
|
||||||
|
'aes-256-gcm',
|
||||||
|
key,
|
||||||
|
Buffer.from(value.iv, 'base64')
|
||||||
|
);
|
||||||
|
decipher.setAuthTag(Buffer.from(value.authTag, 'base64'));
|
||||||
|
|
||||||
|
return Buffer.concat([
|
||||||
|
decipher.update(Buffer.from(value.ciphertext, 'base64')),
|
||||||
|
decipher.final(),
|
||||||
|
]).toString('utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTemplateRepository() {
|
||||||
|
return decrypt(TEMPLATE_REPOSITORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultJavaGitRoot() {
|
||||||
|
return decrypt(DEFAULT_JAVA_GIT_ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = getTemplateRepository;
|
||||||
|
module.exports.getDefaultJavaGitRoot = getDefaultJavaGitRoot;
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
const assert = require('assert');
|
||||||
|
const {
|
||||||
|
getDefaultAppIdentifier,
|
||||||
|
getDefaultJavaGit,
|
||||||
|
getProjectBaseName,
|
||||||
|
getRepositoryName,
|
||||||
|
updateConfigSource,
|
||||||
|
validateProjectName,
|
||||||
|
} = require('../src/create');
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
getProjectBaseName('zcloud_gbs_basic_info_gwj-react'),
|
||||||
|
'zcloud_gbs_basic_info_gwj'
|
||||||
|
);
|
||||||
|
assert.strictEqual(getProjectBaseName('custom-project'), 'custom-project');
|
||||||
|
assert.match(
|
||||||
|
getDefaultJavaGit('zcloud_gbs_basic_info_gwj-react'),
|
||||||
|
/\/zcloud_gbs\/zcloud_gbs_basic_info_gwj\.git$/
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
getRepositoryName('https://example.com/group/custom-server.git'),
|
||||||
|
'custom-server'
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
getDefaultAppIdentifier(
|
||||||
|
'https://example.com/group/zcloud_gbs_enterprise_user_gwj.git'
|
||||||
|
),
|
||||||
|
'enterpriseUser'
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
getDefaultAppIdentifier('https://example.com/group/zcloud_gbs_aqd.git'),
|
||||||
|
'aqd'
|
||||||
|
);
|
||||||
|
assert.strictEqual(validateProjectName('demo-react'), 'demo-react');
|
||||||
|
assert.throws(() => validateProjectName('../demo'), /非法字符/);
|
||||||
|
|
||||||
|
const configSource = `module.exports = {
|
||||||
|
javaGit: "<git-url>",
|
||||||
|
javaGitName: "<git-name>",
|
||||||
|
environment: {
|
||||||
|
development: {
|
||||||
|
javaGitBranch: "<branch-name>",
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
javaGitBranch: "<branch-name>",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
appIdentifier: "唯一应用标识,与后端gateway相同",
|
||||||
|
};
|
||||||
|
`;
|
||||||
|
const updatedConfig = updateConfigSource(configSource, {
|
||||||
|
javaGit: 'https://example.com/group/zcloud_gbs_basic_info_gwj.git',
|
||||||
|
javaGitName: 'customJavaRepository',
|
||||||
|
appIdentifier: 'customApp',
|
||||||
|
productionBranch: 'release',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.match(updatedConfig, /javaGit: "https:\/\/example\.com\/group\/zcloud_gbs_basic_info_gwj\.git"/);
|
||||||
|
assert.match(updatedConfig, /javaGitName: "customJavaRepository"/);
|
||||||
|
assert.match(updatedConfig, /appIdentifier: "customApp"/);
|
||||||
|
assert.match(updatedConfig, /development: \{\s+javaGitBranch: "<branch-name>"/);
|
||||||
|
assert.match(updatedConfig, /production: \{\s+javaGitBranch: "release"/);
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
const assert = require('assert');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const getTemplateRepository = require('../src/template-repository');
|
||||||
|
|
||||||
|
function getHash(value) {
|
||||||
|
return crypto.createHash('sha256').update(value).digest('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
getHash(getTemplateRepository()),
|
||||||
|
'd2ecabf072ef4b49e60080b0cfa63232d643fdbaff55dfe789dea92e8a09e545'
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
getHash(getTemplateRepository.getDefaultJavaGitRoot()),
|
||||||
|
'61f9226c13559eb5eff239ddeade23a0485c9bbba539373cff114589cf305b02'
|
||||||
|
);
|
||||||
Loading…
Reference in New Issue