yds-tool 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/app.js ADDED
@@ -0,0 +1,74 @@
1
+
2
+ // 禁用vweb logo
3
+ global.__vweb_logo = false;
4
+ const {LoggerFactory, startup, defineEnvironment, getApplicationContext } = require('vweb-core');
5
+ const confUtil = require('vweb-core/lib/conf/util')
6
+ const {program} = require('commander');
7
+ confUtil.logger.info = () => {}
8
+
9
+ !(() => {
10
+ const {program} = require('commander');
11
+ let result = program.parseOptions(process.argv);
12
+ for (let i = 0; i < result.unknown?.length; i++) {
13
+ let name = result.unknown[i];
14
+ let value = result.unknown[i + 1] || '';
15
+ if (!value || value.startsWith('-')) continue;
16
+ if (name === '-l' || name === '--level') {
17
+ process.env.level = value;
18
+ }
19
+ }})()
20
+
21
+ process.on('unhandledRejection', (reason, p) => {
22
+ console.error(`${reason}`, p);
23
+ });
24
+ startup({
25
+ conf: defineEnvironment({
26
+ app: {
27
+ name: 'yds'
28
+ },
29
+ config: {
30
+ src: 'lib'
31
+ },
32
+ logger: {
33
+ appenders: {
34
+ console: {
35
+ type: 'console'
36
+ },
37
+ file: {
38
+ type: 'dateFile',
39
+ filename: 'yds',
40
+ pattern: 'yyyy-MM-dd.log',
41
+ alwaysIncludePattern: true,
42
+ compress: true,
43
+ numBackups: 7,
44
+ keepFileExt: true,
45
+ layout: {
46
+ type: 'pattern',
47
+ pattern: '%d{yyyy-MM-dd hh.mm.ss.SSS} [%p] %m'
48
+ }
49
+ }
50
+ },
51
+ categories: {
52
+ default: {
53
+ appenders: [
54
+ 'console', 'file'
55
+ ],
56
+ level: '${level:info}'
57
+ },
58
+ VWebApplicationContext: {
59
+ appenders: [
60
+ 'file'
61
+ ],
62
+ level: '${level:info}'
63
+ }
64
+ },
65
+ disableClustering: true
66
+ }
67
+ })
68
+ }).then(() => {
69
+ let Main = require('./index');
70
+ return new Main(getApplicationContext()).startup();
71
+ }).catch(err => {
72
+ console.log(err);
73
+ })
74
+
package/bin/cli.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('./app')
package/bin/index.js ADDED
@@ -0,0 +1,3 @@
1
+ (function() {
2
+ module.exports = require('./main').default;
3
+ }).call(this);
package/bin/main.js ADDED
@@ -0,0 +1,459 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const commander_1 = require("commander");
46
+ const process = __importStar(require("process"));
47
+ const vweb_core_1 = require("vweb-core");
48
+ const path = __importStar(require("node:path"));
49
+ const child_process = __importStar(require("node:child_process"));
50
+ const fs = __importStar(require("node:fs"));
51
+ const os = __importStar(require("node:os"));
52
+ const crypto_1 = require("crypto");
53
+ const domainKey = 'p-hcc-i000-p00a-hrcpe';
54
+ const pkg = require('../package.json');
55
+ const RS_URL = 'https://dfs.zhiper.com/v3r6';
56
+ const logger = vweb_core_1.LoggerFactory.getLogger('YDS');
57
+ const execCmd = (command, cwd) => __awaiter(void 0, void 0, void 0, function* () {
58
+ logger.info(`执行命令 ${command} ${cwd ? `,执行目录为${cwd}` : ''}`);
59
+ let start = Date.now();
60
+ child_process.execSync(command, {
61
+ cwd, encoding: 'utf-8',
62
+ timeout: 60000,
63
+ stdio: [0, 1, 2]
64
+ });
65
+ logger.info(`执行命令 ${command} 耗时 \x1B[34m <${Date.now() - start}ms>]`);
66
+ });
67
+ const platform = os.platform();
68
+ if (platform !== 'win32') {
69
+ logger.error('当前工具仅支持windows系统');
70
+ process.exit(1);
71
+ }
72
+ const isAdmin = () => {
73
+ try {
74
+ child_process.execSync('net session >nul 2>&1');
75
+ return true;
76
+ }
77
+ catch (err) {
78
+ return false;
79
+ }
80
+ };
81
+ let wget = path.resolve('wget.exe');
82
+ let zip = path.resolve('zip.exe');
83
+ let unzip = path.resolve('unzip.exe');
84
+ commander_1.program.name("yds")
85
+ .usage("[command] [options]")
86
+ .description("yds 制盘工具 如果命令参数中存在空格 使用双引号\"\"包裹")
87
+ .version(`yds ${pkg.version}`);
88
+ class Main {
89
+ startup() {
90
+ commander_1.program
91
+ .command('init [workdir]')
92
+ .usage('init [workdir]')
93
+ .description('初始化YDS制盘环境, workdir表示制盘工作目录,如果不指定则使用当前目录')
94
+ .action((...args_1) => __awaiter(this, [...args_1], void 0, function* (workdir = path.resolve(process.cwd())) {
95
+ const dir = path.resolve(workdir);
96
+ logger.info(`初始化YDS制盘环境 工作目录:${dir}`);
97
+ const gitExists = yield vweb_core_1.util.cmd.exists('git');
98
+ logger.info(`检查是否安装了git >> ${gitExists ? '已安装' : '未安装'}`);
99
+ if (!gitExists && !fs.existsSync(`${dir}/git-for-windows`)) {
100
+ const gitZipName = 'git-for-windows.zip';
101
+ logger.info(`下载git 安装包 ${gitZipName}`);
102
+ const gitZipFile = `${dir}/${gitZipName}`;
103
+ if (fs.existsSync(gitZipFile)) {
104
+ logger.info(`删除已存在安装包 ${gitZipFile}`);
105
+ fs.rmSync(gitZipFile);
106
+ }
107
+ yield execCmd(`${wget} ${RS_URL}/${gitZipName} -O "${gitZipFile}"`);
108
+ logger.info(`解压安装包 ${gitZipFile}`);
109
+ yield execCmd(`"${unzip}" "${gitZipFile}" -d "${dir}"`);
110
+ fs.rmSync(gitZipFile);
111
+ logger.info(`git 安装完成`);
112
+ }
113
+ const javaExists = yield vweb_core_1.util.cmd.exists('java');
114
+ logger.info(`检查是否安装了java >> ${javaExists ? '已安装' : '未安装'}`);
115
+ if (!javaExists) {
116
+ logger.info('未找到java,准备安装java,开始下载jdk');
117
+ const jdkZipName = 'jdk-11.0.15.1_windows-x64_bin.zip';
118
+ yield execCmd(`${wget} ${RS_URL}/${jdkZipName} -O "${dir}/${jdkZipName}"`);
119
+ logger.info(`解压jdk 安装包 ${dir}/${jdkZipName}`);
120
+ yield execCmd(`"${unzip}" "${dir}/${jdkZipName}"`, dir);
121
+ logger.info(`配置java环境变量`);
122
+ let javaHome = `${dir}/jdk-11.0.15.1`;
123
+ yield execCmd(`setx JAVA_HOME "${javaHome}"`);
124
+ yield execCmd(`setx CLASS_PATH ".;%JAVA_HOME%\lib;"`);
125
+ yield execCmd(`setx PATH "%PATH%;%JAVA_HOME%\bin;"`);
126
+ process.env.JAVA_HOME = javaHome;
127
+ logger.info(`java 安装完成`);
128
+ }
129
+ logger.info(`检查java版本`);
130
+ yield execCmd('java -version');
131
+ const javaHome = process.env.JAVA_HOME;
132
+ if (javaHome) {
133
+ let certsFilename = 'lib/security/cacerts';
134
+ let certsFile = `${javaHome}/${certsFilename}`;
135
+ if (!fs.existsSync(certsFile)) {
136
+ certsFile = `${javaHome}/jre/${certsFilename}`;
137
+ }
138
+ logger.info(`检查java证书目录 ${certsFile}`);
139
+ if (fs.existsSync(certsFile)) {
140
+ try {
141
+ yield execCmd(`keytool -list -v -keystore "${certsFile}" -storepass changeit --alias yyrd`);
142
+ logger.info(`yyrd.crt 证书已存在`);
143
+ }
144
+ catch (e) {
145
+ logger.info(`导入 yyrd.crt 证书到java ${certsFile}`);
146
+ yield execCmd(`keytool -importcert -file "${dir}/yyrd.crt" -keystore "${certsFile}" -storepass changeit -noprompt`);
147
+ logger.info(`yyrd.crt 证书导入完成`);
148
+ }
149
+ }
150
+ }
151
+ const mavenHome = `${dir}/maven-3.8.6`;
152
+ const mavenExists = vweb_core_1.util.cmd.exists('mvn');
153
+ logger.info(`检查是否安装了maven >> ${mavenExists ? '已安装' : '未安装'}`);
154
+ if (!mavenExists) {
155
+ const mavenZipName = 'maven-3.8.6.zip';
156
+ logger.info(`下载maven 安装包 ${mavenZipName}`);
157
+ const mavenZipFile = `${dir}/${mavenZipName}`;
158
+ if (fs.existsSync(mavenZipFile)) {
159
+ logger.info(`删除已存在安装包 ${mavenZipFile}`);
160
+ fs.rmSync(mavenZipFile);
161
+ }
162
+ yield execCmd(`${wget} ${RS_URL}/${mavenZipName} -O "${mavenZipFile}"`);
163
+ logger.info(`解压安装包 ${mavenZipFile}`);
164
+ yield execCmd(`"${unzip}" "${mavenZipFile}" -d "${dir}"`);
165
+ fs.rmSync(mavenZipFile);
166
+ try {
167
+ let mvnPath = path.resolve(`${mavenHome}/bin`);
168
+ yield execCmd(`setx PATH "%PATH%;${mvnPath}"`);
169
+ logger.info(`✅ 成功!Maven路径【${mvnPath}】已添加到系统PATH环境变量`);
170
+ }
171
+ catch (err) {
172
+ console.error('❌ 添加失败:', err.message);
173
+ }
174
+ logger.info(`maven 安装完成`);
175
+ }
176
+ logger.info(`初始化node环境`);
177
+ yield execCmd('npm install -g pnpm typescript --registry=https://registry.npmmirror.com');
178
+ logger.info(`初始化node环境完成`);
179
+ logger.info(`检测code是否存在`);
180
+ const codeDir = `${dir}/yds-1.0.3`;
181
+ if (!fs.existsSync(codeDir)) {
182
+ const codeZipName = 'yds-1.0.3-jdk-8-windows-x86_64.zip';
183
+ logger.info(`下载code IDE 安装包 ${codeZipName}`);
184
+ const codeZipFile = `${dir}/${codeZipName}`;
185
+ if (fs.existsSync(codeZipFile)) {
186
+ logger.info(`删除已存在安装包 ${codeZipFile}`);
187
+ fs.rmSync(codeZipFile);
188
+ }
189
+ yield execCmd(`${wget} https://yoncommunity.yonyoucloud.com/YDSDownload/Window/x64/${codeZipName} -O "${codeZipFile}"`);
190
+ logger.info(`解压安装包 ${codeZipFile}`);
191
+ fs.mkdirSync(codeDir, { recursive: true });
192
+ yield execCmd(`"${unzip}" "${codeZipFile}" -d "${codeDir}"`);
193
+ fs.rmSync(codeZipFile);
194
+ yield new Promise((resolve) => setTimeout(resolve, 5000));
195
+ logger.info(`code IDE 安装完成`);
196
+ }
197
+ logger.info(`初始化YDS IDE 全局配置`);
198
+ const settingsJson = `${codeDir}/Code/data/user-data/User/settings.json`;
199
+ let settingsJsonObj = {};
200
+ if (fs.existsSync(settingsJson)) {
201
+ settingsJsonObj = JSON.parse(fs.readFileSync(settingsJson).toString('utf-8'));
202
+ }
203
+ let settingXml = path.resolve(`${mavenHome}/conf/settings.xml`);
204
+ if (!fs.existsSync(settingXml) && !fs.existsSync(`${dir}/settings.xml`)) {
205
+ yield execCmd(`${wget} ${RS_URL}/settings.xml`);
206
+ settingXml = path.resolve(`${dir}/settings.xml`);
207
+ }
208
+ settingsJsonObj["java.configuration.maven.globalSettings"] = settingXml;
209
+ settingsJsonObj["java.configuration.maven.userSettings"] = settingXml;
210
+ settingsJsonObj["maven.settingsFile"] = settingXml;
211
+ fs.writeFileSync(settingsJson, JSON.stringify(settingsJsonObj, null, 4));
212
+ logger.info(`初始化YDS IDE 全局配置完成`);
213
+ const sshDir = path.resolve(process.env.USERPROFILE, '.ssh');
214
+ if (!fs.existsSync(sshDir)) {
215
+ fs.mkdirSync(sshDir);
216
+ }
217
+ if (!fs.existsSync(`${sshDir}/id_ed25519.pub`)) {
218
+ logger.info(`拷贝密钥文件`);
219
+ fs.copyFileSync(`${dir}/id_ed25519.pub`, `${sshDir}/id_ed25519.pub`);
220
+ fs.copyFileSync(`${dir}/id_ed25519`, `${sshDir}/id_ed25519`);
221
+ logger.info(`拷贝密钥文件完成`);
222
+ }
223
+ logger.info(`初始化YDS制盘环境完成`);
224
+ })).hook('postAction', () => process.exit(0));
225
+ commander_1.program
226
+ .command('start <catalog> [workdir]')
227
+ .usage('start <catalog> [workdir]')
228
+ .option('-f, --file <file>', '配置文件')
229
+ .addHelpText('after', `
230
+ 配置文件内容示例:
231
+ {
232
+ hosts?: Array<string>;
233
+ git: Record<'hrcpe' | 'fecode', string>;
234
+ catalogs: {
235
+ [catalog: string]: Record<'hrcpe' | 'fecode', string | { url: string, branch: string }>
236
+ }
237
+ }`)
238
+ .description('启动制盘环境,catalog表示需要制盘的模块,对应配置文件中catalogs的key值,用于指定需要出盘的信息,workdir表示制盘工作目录,如果不指定则使用当前目录')
239
+ .action((catalog_1, ...args_1) => __awaiter(this, [catalog_1, ...args_1], void 0, function* (catalog, workdir = path.resolve(process.cwd()), options) {
240
+ const dir = path.resolve(workdir);
241
+ logger.info(`开始检测制盘环境检测`);
242
+ let gitCmd = 'git';
243
+ const gitExists = yield vweb_core_1.util.cmd.exists(gitCmd);
244
+ if (!gitExists) {
245
+ gitCmd = `${dir}/git-for-windows/bin/git.exe`;
246
+ if (!fs.existsSync(gitCmd)) {
247
+ logger.error(`未找到git命令 ${gitCmd}, 请先执行 init 初始化制盘环境`);
248
+ process.exit(1);
249
+ }
250
+ }
251
+ let settingXml = path.resolve(`${dir}/settings.xml`);
252
+ let mvnCmd = 'mvn';
253
+ if (!fs.existsSync(settingXml)) {
254
+ let mavenHome = `${dir}/maven-3.8.6`;
255
+ mvnCmd = `"${mavenHome}/bin/mvn.cmd"`;
256
+ settingXml = `${mavenHome}/conf/settings.xml`;
257
+ if (!fs.existsSync(mvnCmd)) {
258
+ logger.error(`未找到mvn命令 ${mvnCmd}, 请先执行 init 初始化制盘环境`);
259
+ process.exit(1);
260
+ }
261
+ }
262
+ let idePath = `${dir}/yds-1.0.3`;
263
+ if (!fs.existsSync(idePath)) {
264
+ logger.error(`未找到IDE ${idePath}, 请先执行 init 初始化制盘环境`);
265
+ process.exit(1);
266
+ }
267
+ logger.info(`制盘环境检测完成`);
268
+ const ydsJson = path.resolve(options.file || `${dir}/yds.json`);
269
+ logger.info(`开始制盘 ${catalog} 工作目录:${dir}`);
270
+ if (!fs.existsSync(ydsJson)) {
271
+ logger.error(`未找到配置文件 ${ydsJson}`);
272
+ process.exit(1);
273
+ }
274
+ const ydsJsonStr = fs.readFileSync(ydsJson).toString('utf-8');
275
+ let config;
276
+ const checkConfigError = () => {
277
+ logger.error(`配置文件 ${ydsJson} 格式错误 参考示例:
278
+ {
279
+ hosts?: Array<string>;
280
+ git: Record<'hrcpe' | 'fecode', string>;
281
+ catalogs: {
282
+ [catalog: string]: Record<'hrcpe' | 'fecode', string | { url: string, branch: string }>
283
+ }
284
+ }`);
285
+ process.exit(1);
286
+ };
287
+ try {
288
+ config = JSON.parse(ydsJsonStr);
289
+ if (!config.catalogs) {
290
+ checkConfigError();
291
+ }
292
+ }
293
+ catch (e) {
294
+ checkConfigError();
295
+ }
296
+ const git = config.git;
297
+ const catalogConfig = config.catalogs[catalog];
298
+ if (typeof catalogConfig === 'undefined') {
299
+ logger.error(`配置文件 ${ydsJson} 找不到 catalogs.${catalog} 先关配置`);
300
+ process.exit(1);
301
+ }
302
+ if (typeof catalogConfig.hrcpe === 'undefined' || typeof catalogConfig.fecode === 'undefined') {
303
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog}.hrcpe 或 catalogs.${catalog}.fecode 字段缺失`);
304
+ process.exit(1);
305
+ }
306
+ const namespace = `${dir}/${catalog}`;
307
+ if (!fs.existsSync(namespace)) {
308
+ logger.info(`创建目录 ${namespace}`);
309
+ fs.mkdirSync(namespace);
310
+ }
311
+ else {
312
+ logger.info(`目录 ${namespace} 已存在`);
313
+ }
314
+ let hrcpeUrl = typeof catalogConfig.hrcpe === 'string' ? git === null || git === void 0 ? void 0 : git.hrcpe : catalogConfig.hrcpe.url;
315
+ if (!hrcpeUrl) {
316
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog} 后端服务 未指定仓库地址,请通过 git.hrcpe 或者 catalogs.${catalog}.hrcpe.url 指定仓库地址`);
317
+ }
318
+ logger.info(`开始拉取后端服务仓库 ${hrcpeUrl}`);
319
+ if (fs.existsSync(`${namespace}/.git`)) {
320
+ logger.info(`目录 ${namespace} 已存在,开始更新仓库`);
321
+ yield execCmd(`"${gitCmd}" pull`, namespace);
322
+ }
323
+ else {
324
+ logger.info(`目录 ${namespace} 不存在,开始创建仓库`);
325
+ let branch = typeof catalogConfig.hrcpe === 'string' ? catalogConfig.hrcpe : catalogConfig.hrcpe.branch;
326
+ if (!branch) {
327
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog} 后端服务 未指定分支,请通过 git.hrcpe 或者 catalogs.${catalog}.hrcpe.branch 配置分支`);
328
+ process.exit(1);
329
+ }
330
+ yield execCmd(`"${gitCmd}" clone -b ${branch} ${hrcpeUrl} ${namespace}`, namespace);
331
+ }
332
+ logger.info(`拉取后端服务仓库完成`);
333
+ let boostrapPomXml = `${namespace}/${domainKey}-be/dev-${domainKey}-bootstrap/pom.xml`;
334
+ logger.info(`替换文件 ${boostrapPomXml} 中的ROOT为domainKey,否则会导致制盘失败,无法找到制品`);
335
+ const boostrapPomXmlString = fs.readFileSync(boostrapPomXml).toString('utf-8');
336
+ if (boostrapPomXmlString.includes('ROOT')) {
337
+ fs.writeFileSync(boostrapPomXml, boostrapPomXmlString.replace(/ROOT/g, domainKey));
338
+ }
339
+ if (config.hosts && config.hosts.length) {
340
+ logger.info(`存在hosts配置,检测系统hosts配置文件是否已经配置`);
341
+ let hostsFile = path.resolve(process.env.WINDIR, 'System32', 'drivers', 'etc', 'hosts');
342
+ const hostList = fs.readFileSync(hostsFile).toString('utf-8').split('\n');
343
+ let appendHosts = [...config.hosts];
344
+ for (let hostItem of hostList) {
345
+ if (/#/.test(hostItem)) {
346
+ continue;
347
+ }
348
+ for (let appendHost of config.hosts) {
349
+ const [ip, domain] = appendHost.split(' ').filter(item => item);
350
+ if (hostItem.includes(ip) && hostItem.includes(domain)) {
351
+ logger.info(`系统hosts配置文件已存在 ${appendHost}`);
352
+ appendHosts.remove(appendHost);
353
+ }
354
+ }
355
+ }
356
+ if (appendHosts.length) {
357
+ if (isAdmin()) {
358
+ fs.appendFileSync(hostsFile, `\n${appendHosts.join('\n')}\n`, {
359
+ encoding: 'utf-8'
360
+ });
361
+ }
362
+ else {
363
+ logger.error(`当前非管理员启动无法更改hosts文件,请使用管理员启动或者手动添加 ${appendHosts.join('\n')} 到文件 ${hostsFile}`);
364
+ }
365
+ }
366
+ logger.info(`hosts 配置检测完成`);
367
+ }
368
+ logger.info('初始化项目maven环境');
369
+ let mvnConfigDir = `${namespace}/.mvn`;
370
+ if (!fs.existsSync(mvnConfigDir)) {
371
+ yield execCmd(`${mvnCmd} -N io.takari:maven:wrapper -Dmaven=3.8.6`, namespace);
372
+ }
373
+ let configFile = `${mvnConfigDir}/maven.config`;
374
+ if (fs.existsSync(configFile)) {
375
+ fs.rmSync(configFile);
376
+ }
377
+ fs.writeFileSync(`${mvnConfigDir}/maven.config`, `-s\n${settingXml}\n-Dmaven.wagon.http.ssl.insecure=true\n-Dmaven.wagon.http.ssl.allowall=true`);
378
+ logger.info(`当前maven信息`);
379
+ yield execCmd(`${mvnCmd} --version`, namespace);
380
+ logger.info('项目maven清理');
381
+ yield execCmd(`${mvnCmd} clean -DskipTests`, `${namespace}/${domainKey}-be`);
382
+ logger.info('处理前端构建,增加构建文件');
383
+ let feDir = `${namespace}/${domainKey}-fe`;
384
+ let feBuildJs = `${feDir}/build.js`;
385
+ if (!fs.existsSync(feBuildJs)) {
386
+ fs.cpSync(`${dir}/fe-build.js`, feBuildJs);
387
+ }
388
+ let fePackageJson = `${feDir}/package.json`;
389
+ const packageString = fs.readFileSync(fePackageJson).toString('utf-8');
390
+ if (!packageString.includes('build.js')) {
391
+ logger.info(`修改${fePackageJson}`);
392
+ const packageJson = JSON.parse(packageString);
393
+ packageJson.scripts['build:extend'] += ' && node build.js';
394
+ fs.writeFileSync(fePackageJson, JSON.stringify(packageJson, null, 4));
395
+ logger.info(`修改${fePackageJson}完成`);
396
+ }
397
+ let fecodeUrl = typeof catalogConfig.fecode === 'string' ? git === null || git === void 0 ? void 0 : git.fecode : catalogConfig.fecode.url;
398
+ if (!fecodeUrl) {
399
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog} 后端服务 未指定仓库地址,请通过 git.fecode 或者 catalogs.${catalog}.fecode.url 指定仓库地址`);
400
+ }
401
+ logger.info(`开始拉取报告服务仓库 ${fecodeUrl}`);
402
+ let reportNamespace = `${namespace}/yonbip-yisv-izp1-dev-fecode`;
403
+ if (fs.existsSync(`${reportNamespace}/.git`)) {
404
+ logger.info(`目录 ${reportNamespace} 已存在,开始更新仓库`);
405
+ yield execCmd(`"${gitCmd}" pull`, reportNamespace);
406
+ }
407
+ else {
408
+ logger.info(`目录 ${reportNamespace} 不存在,开始创建仓库`);
409
+ let branch = typeof catalogConfig.fecode === 'string' ? catalogConfig.fecode : catalogConfig.fecode.branch;
410
+ if (!branch) {
411
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog} 报告服务未指定分支,请通过 git.fecode 或者 catalogs.${catalog}.fecode.branch 配置分支`);
412
+ process.exit(1);
413
+ }
414
+ yield execCmd(`"${gitCmd}" clone -b ${branch} ${fecodeUrl} ${reportNamespace}`);
415
+ }
416
+ logger.info(`拉取报告服务仓库完成`);
417
+ logger.info('处理报告构建,增加构建文件');
418
+ let fecodeBuildJs = `${reportNamespace}/build.js`;
419
+ if (!fs.existsSync(fecodeBuildJs)) {
420
+ fs.cpSync(`${dir}/fecode-build.js`, fecodeBuildJs);
421
+ }
422
+ let fecodePackageJson = `${reportNamespace}/package.json`;
423
+ const fecodePackageString = fs.readFileSync(fecodePackageJson).toString('utf-8');
424
+ if (!fecodePackageString.includes('build.js')) {
425
+ logger.info(`修改${fecodePackageJson}`);
426
+ const packageJson = JSON.parse(fecodePackageString);
427
+ packageJson.scripts['build'] += ' && node build.js';
428
+ packageJson.domainKey = domainKey;
429
+ delete packageJson.dependencies.zlib;
430
+ fs.writeFileSync(fecodePackageJson, JSON.stringify(packageJson, null, 4));
431
+ logger.info(`修改${fecodePackageJson}完成`);
432
+ }
433
+ logger.info(`安装报告服务依赖`);
434
+ yield execCmd('npm i', reportNamespace);
435
+ logger.info(`生成version.json 文件`);
436
+ const uuid = (0, crypto_1.randomUUID)().toString();
437
+ fs.writeFileSync(`${reportNamespace}/version.json`, `{"version": "${uuid}"}`);
438
+ logger.info('初始化项目环境资源');
439
+ if (fs.existsSync(`${namespace}/disk`) || fs.existsSync(`${namespace}/disks`)) {
440
+ logger.info(`已存在,跳过环境资源文件下载`);
441
+ }
442
+ else {
443
+ logger.info(`开始下载项目环境资源文件`);
444
+ let gitZipFile = `${namespace}/env.zip`;
445
+ yield execCmd(`${wget} ${RS_URL}/env.zip -O "${gitZipFile}"`);
446
+ logger.info(`解压资源文件包 ${gitZipFile}`);
447
+ yield execCmd(`"${unzip}" "${gitZipFile}"`, namespace);
448
+ fs.rmSync(gitZipFile);
449
+ }
450
+ logger.info('启动IDE');
451
+ yield execCmd(`"${idePath}/Code/Code.exe" "${namespace}"`);
452
+ yield new Promise(resolve => setTimeout(resolve, 3000));
453
+ logger.info('已启动IDE,请按照文档说明进行制盘操作');
454
+ })).hook('postAction', () => process.exit(0));
455
+ commander_1.program.parse(process.argv);
456
+ }
457
+ }
458
+ exports.default = Main;
459
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEseUNBQWtDO0FBQ2xDLGlEQUFtQztBQUNuQyx5Q0FBOEM7QUFDOUMsZ0RBQWtDO0FBQ2xDLGtFQUFvRDtBQUNwRCw0Q0FBOEI7QUFDOUIsNENBQThCO0FBQzlCLG1DQUFpQztBQUVqQyxNQUFNLFNBQVMsR0FBRyx1QkFBdUIsQ0FBQztBQUMxQyxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUN2QyxNQUFNLE1BQU0sR0FBRyw2QkFBNkIsQ0FBQztBQUU3QyxNQUFNLE1BQU0sR0FBVyx5QkFBYSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUV0RCxNQUFNLE9BQU8sR0FBRyxDQUFPLE9BQWUsRUFBRSxHQUFZLEVBQUUsRUFBRTtJQUNwRCxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsT0FBTyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUEsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMzRCxJQUFJLEtBQUssR0FBSSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDeEIsYUFBYSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUU7UUFDNUIsR0FBRyxFQUFFLFFBQVEsRUFBRSxPQUFPO1FBQ3RCLE9BQU8sRUFBRSxLQUFLO1FBQ2QsS0FBSyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7S0FDbkIsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLE9BQU8saUJBQWlCLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLE1BQU0sQ0FBQyxDQUFBO0FBQ3pFLENBQUMsQ0FBQSxDQUFBO0FBRUQsTUFBTSxRQUFR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Q0FBQztnQkFDNUUsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1lBQ2xDLENBQUM7aUJBQU0sQ0FBQztnQkFFSixNQUFNLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFBO2dCQUMzQixJQUFJLFVBQVUsR0FBRyxHQUFHLFNBQVMsVUFBVSxDQUFDO2dCQUN4QyxNQUFNLE9BQU8sQ0FBQyxHQUFHLElBQUksSUFBSSxNQUFNLGdCQUFnQixVQUFVLEdBQUcsQ0FBQyxDQUFDO2dCQUU5RCxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsVUFBVSxFQUFFLENBQUMsQ0FBQTtnQkFDcEMsTUFBTSxPQUFPLENBQUMsSUFBSSxLQUFLLE1BQU0sVUFBVSxHQUFHLEVBQUUsU0FBUyxDQUFDLENBQUM7Z0JBQ3ZELEVBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUE7WUFDekIsQ0FBQztZQUVELE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDckIsTUFBTSxPQUFPLENBQUMsSUFBSSxPQUFPLG9CQUFvQixTQUFTLEdBQUcsQ0FBQyxDQUFDO1lBRTNELE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUE7WUFDdkQsTUFBTSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFBO1FBQ3ZDLENBQUMsQ0FBQSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFFaEQsbUJBQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQy9CLENBQUM7Q0FDSjtBQTNaRCx1QkEyWkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge3Byb2dyYW19IGZyb20gXCJjb21tYW5kZXJcIjtcclxuaW1wb3J0ICogYXMgcHJvY2VzcyBmcm9tIFwicHJvY2Vzc1wiO1xyXG5pbXBvcnQge0xvZ2dlckZhY3RvcnksIHV0aWx9IGZyb20gXCJ2d2ViLWNvcmVcIjtcclxuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCI7XHJcbmltcG9ydCAqIGFzIGNoaWxkX3Byb2Nlc3MgZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xyXG5pbXBvcnQgKiBhcyBmcyBmcm9tIFwibm9kZTpmc1wiO1xyXG5pbXBvcnQgKiBhcyBvcyBmcm9tICdub2RlOm9zJztcclxuaW1wb3J0IHtyYW5kb21VVUlEfSBmcm9tICdjcnlwdG8nXHJcblxyXG5jb25zdCBkb21haW5LZXkgPSAncC1oY2MtaTAwMC1wMDBhLWhyY3BlJztcclxuY29uc3QgcGtnID0gcmVxdWlyZSgnLi4vcGFja2FnZS5qc29uJyk7XHJcbmNvbnN0IFJTX1VSTCA9ICdodHRwczovL2Rmcy56aGlwZXIuY29tL3YzcjYnO1xyXG5cclxuY29uc3QgbG9nZ2VyOiBMb2dnZXIgPSBMb2dnZXJGYWN0b3J5LmdldExvZ2dlcignWURTJyk7XHJcblxyXG5jb25zdCBleGVjQ21kID0gYXN5bmMgKGNvbW1hbmQ6IHN0cmluZywgY3dkPzogc3RyaW5nKSA9PiB7XHJcbiAgICBsb2dnZXIuaW5mbyhg5omn6KGM5ZG95LukICR7Y29tbWFuZH0gJHtjd2QgPyBg77yM5omn6KGM55uu5b2V5Li6JHtjd2R9YCA6Jyd9YCk7XHJcbiAgICBsZXQgc3RhcnQgID0gRGF0ZS5ub3coKTtcclxuICAgIGNoaWxkX3Byb2Nlc3MuZXhlY1N5bmMoY29tbWFuZCwge1xyXG4gICAgICAgIGN3ZCwgZW5jb2Rpbmc6ICd1dGYtOCcsXHJcbiAgICAgICAgdGltZW91dDogNjAwMDAsXHJcbiAgICAgICAgc3RkaW86IFswLCAxLCAyXVxyXG4gICAgfSk7XHJcbiAgICBsb2dnZXIuaW5mbyhg5omn6KGM5ZG95LukICR7Y29tbWFuZH0g6ICX5pe2IFxceDFCWzM0bSA8JHtEYXRlLm5vdygpIC0gc3RhcnR9bXM+XWApXHJcbn1cclxuXHJcbmNvbnN0IHBsYXRmb3JtID0gb3MucGxhdGZvcm0oKVxyXG5pZiAocGxhdGZvcm0gIT09ICd3aW4zMicpIHtcclxuICAgIGxvZ2dlci5lcnJvcign5b2T5YmN5bel5YW35LuF5pSv5oyBd2luZG93c+ezu+e7nycpO1xyXG4gICAgcHJvY2Vzcy5leGl0KDEpO1xyXG59XHJcblxyXG5jb25zdCBpc0FkbWluID0gKCkgPT4ge1xyXG4gICAgdHJ5IHtcclxuICAgICAgICAvLyDlsJ3or5XmiafooYzkuIDkuKrlj6rmnInnrqHnkIblkZjmiY3og73ov5DooYznmoTlkb3ku6RcclxuICAgICAgICAvLyDkvb/nlKggPm51bCAyPiYxIOadpeaKkeWItui+k+WHulxyXG4gICAgICAgIGNoaWxkX3Byb2Nlc3MuZXhlY1N5bmMoJ25ldCBzZXNzaW9uID5udWwgMj4mMScpO1xyXG4gICAgICAgIHJldHVybiB0cnVlOyAvLyDmiJDlip/miafooYxcclxuICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTsgLy8g5omn6KGM5aSx6LSl77yM5p2D6ZmQ5LiN6LazXHJcbiAgICB9XHJcbn1cclxuXHJcbmxldCB3Z2V0ID0gcGF0aC5yZXNvbHZlKCAnd2dldC5leGUnKTtcclxubGV0IHppcCA9IHBhdGgucmVzb2x2ZSgnemlwLmV4ZScpO1xyXG5sZXQgdW56aXAgPSBwYXRoLnJlc29sdmUoJ3VuemlwLmV4ZScpO1xyXG5cclxucHJvZ3JhbS5uYW1lKFwieWRzXCIpXHJcbiAgICAudXNhZ2UoXCJbY29tbWFuZF0gW29wdGlvbnNdXCIpXHJcbiAgICAuZGVzY3JpcHRpb24oXCJ5ZHMg5Yi255uY5bel5YW3IOWmguaenOWRveS7pOWPguaVsOS4reWtmOWcqOepuuagvCDkvb/nlKjlj4zlvJXlj7dcXFwiXFxcIuWMheijuVwiKVxyXG4gICAgLnZlcnNpb24oYHlkcyAke3BrZy52ZXJzaW9ufWApO1xyXG5cclxudHlwZSBNaWNyb1NlcnZpY2UgPSAnaHJjcGUnIHwgJ2ZlY29kZSc7XHJcblxyXG50eXBlIEdpdCA9IHtcclxuICAgIHVybDogc3RyaW5nLFxyXG4gICAgYnJhbmNoOiBzdHJpbmdcclxufVxyXG5cclxudHlwZSBZZHNDb25maWcgPSB7XHJcbiAgICBob3N0czogQXJyYXk8c3RyaW5nPjtcclxuICAgIGdpdDogUmVjb3JkPE1pY3JvU2VydmljZSwgc3RyaW5nPjtcclxuICAgIGNhdGFsb2dzOiB7XHJcbiAgICAgICAgW2NhdGFsb2c6IHN0cmluZ106IFJlY29yZDxNaWNyb1NlcnZpY2UsIHN0cmluZyB8IEdpdD5cclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWFpbiB7XHJcblxyXG4gICAgc3RhcnR1cCgpIHtcclxuICAgICAgICBwcm9ncmFtXHJcbiAgICAgICAgICAgIC5jb21tYW5kKCdpbml0IFt3b3JrZGlyXScpXHJcbiAgICAgICAgICAgIC51c2FnZSgnaW5pdCBbd29ya2Rpcl0nKVxyXG4gICAgICAgICAgICAuZGVzY3JpcHRpb24oJ+WIneWni+WMlllEU+WItuebmOeOr+Wigywgd29ya2RpcuihqOekuuWItuebmOW3peS9nOebruW9le+8jOWmguaenOS4jeaMh+WumuWImeS9v+eUqOW9k+WJjeebruW9lScpXHJcbiAgICAgICAgICAgIC5hY3Rpb24oYXN5bmMgKHdvcmtkaXI6IHN0cmluZyA9IHBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpKSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGlyID0gcGF0aC5yZXNvbHZlKHdvcmtkaXIpO1xyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOWIneWni+WMlllEU+WItuebmOeOr+WigyDlt6XkvZznm67lvZXvvJoke2Rpcn1gKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGdpdEV4aXN0cyA9IGF3YWl0IHV0aWwuY21kLmV4aXN0cygnZ2l0Jyk7XHJcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg5qOA5p+l5piv5ZCm5a6J6KOF5LqGZ2l0ID4+ICR7Z2l0RXhpc3RzID8gJ+W3suWuieijhScgOiAn5pyq5a6J6KOFJ31gKTtcclxuICAgICAgICAgICAgICAgIGlmICghZ2l0RXhpc3RzICYmICFmcy5leGlzdHNTeW5jKGAke2Rpcn0vZ2l0LWZvci13aW5kb3dzYCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBnaXRaaXBOYW1lID0gJ2dpdC1mb3Itd2luZG93cy56aXAnXHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOS4i+i9vWdpdCDlronoo4XljIUgJHtnaXRaaXBOYW1lfWApO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGdpdFppcEZpbGUgPSBgJHtkaXJ9LyR7Z2l0WmlwTmFtZX1gO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIOajgOafpeaYr+WQpuW3sue7j+WtmOWcqOWuieijheWMhSDlpoLmnpzmnInlhYjliKDpmaRcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhnaXRaaXBGaWxlKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg5Yig6Zmk5bey5a2Y5Zyo5a6J6KOF5YyFICR7Z2l0WmlwRmlsZX1gKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZnMucm1TeW5jKGdpdFppcEZpbGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAvLyDkuIvovb3lronoo4XljIXlubbovpPlh7rml6Xlv5dcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGAke3dnZXR9ICR7UlNfVVJMfS8ke2dpdFppcE5hbWV9IC1PIFwiJHtnaXRaaXBGaWxlfVwiYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOino+WOi+WuieijheWMhSAke2dpdFppcEZpbGV9YClcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGBcIiR7dW56aXB9XCIgXCIke2dpdFppcEZpbGV9XCIgLWQgXCIke2Rpcn1cImApO1xyXG4gICAgICAgICAgICAgICAgICAgIGZzLnJtU3luYyhnaXRaaXBGaWxlKVxyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBnaXQg5a6J6KOF5a6M5oiQYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgamF2YUV4aXN0cyA9IGF3YWl0IHV0aWwuY21kLmV4aXN0cygnamF2YScpO1xyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOajgOafpeaYr+WQpuWuieijheS6hmphdmEgPj4gJHtqYXZhRXhpc3RzID8gJ+W3suWuieijhScgOiAn5pyq5a6J6KOFJ31gKTtcclxuICAgICAgICAgICAgICAgIGlmICghamF2YUV4aXN0cykge1xyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCfmnKrmib7liLBqYXZh77yM5YeG5aSH5a6J6KOFamF2Ye+8jOW8gOWni+S4i+i9vWpkaycpO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGpka1ppcE5hbWUgPSAnamRrLTExLjAuMTUuMV93aW5kb3dzLXg2NF9iaW4uemlwJ1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGV4ZWNDbWQoYCR7d2dldH0gJHtSU19VUkx9LyR7amRrWmlwTmFtZX0gLU8gXCIke2Rpcn0vJHtqZGtaaXBOYW1lfVwiYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOino+WOi2pkayDlronoo4XljIUgJHtkaXJ9LyR7amRrWmlwTmFtZX1gKVxyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGV4ZWNDbWQoYFwiJHt1bnppcH1cIiBcIiR7ZGlyfS8ke2pka1ppcE5hbWV9XCJgLCBkaXIpO1xyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDphY3nva5qYXZh546v5aKD5Y+Y6YePYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGphdmFIb21lID0gYCR7ZGlyfS9qZGstMTEuMC4xNS4xYDtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGBzZXR4IEpBVkFfSE9NRSBcIiR7amF2YUhvbWV9XCJgKTtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGBzZXR4IENMQVNTX1BBVEggXCIuOyVKQVZBX0hPTUUlXFxsaWI7XCJgKTtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKCBgc2V0eCBQQVRIIFwiJVBBVEglOyVKQVZBX0hPTUUlXFxiaW47XCJgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzcy5lbnYuSkFWQV9IT01FID0gamF2YUhvbWU7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYGphdmEg5a6J6KOF5a6M5oiQYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOajgOafpWphdmHniYjmnKxgKTtcclxuICAgICAgICAgICAgICAgIGF3YWl0IGV4ZWNDbWQoJ2phdmEgLXZlcnNpb24nKTtcclxuICAgICAgICAgICAgICAgIC8vIOWvvOWFpeivgeS5puWIsGphdmEg5aaC5p6camF2YeaYrzEuOOeJiOacrCDpnIDopoHlr7zlhaXliLAgSkFWQV9IT01FL2pyZS9saWIvc2VjdXJpdHkvY2FjZXJ0cyDlpoLmnpzmmK8xMeeJiOacrCDpnIDopoHlr7zlhaXliLAgSkFWQV9IT01FL2xpYi9zZWN1cml0eS9jYWNlcnRzXHJcbiAgICAgICAgICAgICAgICBjb25zdCBqYXZhSG9tZSA9IHByb2Nlc3MuZW52LkpBVkFfSE9NRTtcclxuICAgICAgICAgICAgICAgIGlmIChqYXZhSG9tZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBjZXJ0c0ZpbGVuYW1lID0gJ2xpYi9zZWN1cml0eS9jYWNlcnRzJztcclxuICAgICAgICAgICAgICAgICAgICBsZXQgY2VydHNGaWxlID0gYCR7amF2YUhvbWV9LyR7Y2VydHNGaWxlbmFtZX1gO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhjZXJ0c0ZpbGUpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNlcnRzRmlsZSA9IGAke2phdmFIb21lfS9qcmUvJHtjZXJ0c0ZpbGVuYW1lfWA7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDmo4Dmn6VqYXZh6K+B5Lmm55uu5b2VICR7Y2VydHNGaWxlfWApO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmcy5leGlzdHNTeW5jKGNlcnRzRmlsZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8g5Yik5pat6K+B5Lmm5piv5ZCm5bey57uP5a+85YWlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGBrZXl0b29sIC1saXN0IC12IC1rZXlzdG9yZSBcIiR7Y2VydHNGaWxlfVwiIC1zdG9yZXBhc3MgY2hhbmdlaXQgLS1hbGlhcyB5eXJkYClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGB5eXJkLmNydCDor4Hkuablt7LlrZjlnKhgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8g6K+B5Lmm5LiN5a2Y5ZyoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg5a+85YWlIHl5cmQuY3J0IOivgeS5puWIsGphdmEgJHtjZXJ0c0ZpbGV9YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGBrZXl0b29sIC1pbXBvcnRjZXJ0IC1maWxlIFwiJHtkaXJ9L3l5cmQuY3J0XCIgLWtleXN0b3JlIFwiJHtjZXJ0c0ZpbGV9XCIgLXN0b3JlcGFzcyBjaGFuZ2VpdCAtbm9wcm9tcHRgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGB5eXJkLmNydCDor4Hkuablr7zlhaXlrozmiJBgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBtYXZlbkhvbWUgPSBgJHtkaXJ9L21hdmVuLTMuOC42YDtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG1hdmVuRXhpc3RzID0gdXRpbC5jbWQuZXhpc3RzKCdtdm4nKTtcclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDmo4Dmn6XmmK/lkKblronoo4XkuoZtYXZlbiA+PiAke21hdmVuRXhpc3RzID8gJ+W3suWuieijhScgOiAn5pyq5a6J6KOFJ31gKTtcclxuICAgICAgICAgICAgICAgIGlmICghbWF2ZW5FeGlzdHMpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXZlblppcE5hbWUgPSAnbWF2ZW4tMy44LjYuemlwJ1xyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDkuIvovb1tYXZlbiDlronoo4XljIUgJHttYXZlblppcE5hbWV9YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF2ZW5aaXBGaWxlID0gYCR7ZGlyfS8ke21hdmVuWmlwTmFtZX1gO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIOajgOafpeaYr+WQpuW3sue7j+WtmOWcqOWuieijheWMhSDlpoLmnpzmnInlhYjliKDpmaRcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhtYXZlblppcEZpbGUpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDliKDpmaTlt7LlrZjlnKjlronoo4XljIUgJHttYXZlblppcEZpbGV9YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZzLnJtU3luYyhtYXZlblppcEZpbGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAvLyDkuIvovb3lronoo4XljIXlubbovpPlh7rml6Xlv5dcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGAke3dnZXR9ICR7UlNfVVJMfS8ke21hdmVuWmlwTmFtZX0gLU8gXCIke21hdmVuWmlwRmlsZX1cImApO1xyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDop6Pljovlronoo4XljIUgJHttYXZlblppcEZpbGV9YClcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGBcIiR7dW56aXB9XCIgXCIke21hdmVuWmlwRmlsZX1cIiAtZCBcIiR7ZGlyfVwiYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZnMucm1TeW5jKG1hdmVuWmlwRmlsZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIOa3u+WKoG1hdmVuIOeOr+Wig+WPmOmHj1xyXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3PmoLjlv4Plkb3ku6TvvJrmsLjkuYXov73liqDot6/lvoTliLDjgJDnlKjmiLfnjq/looPlj5jph49QQVRI44CR77yM5rC45LmF55Sf5pWIXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtdm5QYXRoID0gcGF0aC5yZXNvbHZlKGAke21hdmVuSG9tZX0vYmluYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGV4ZWNDbWQoIGBzZXR4IFBBVEggXCIlUEFUSCU7JHttdm5QYXRofVwiYCApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg4pyFIOaIkOWKn++8gU1hdmVu6Lev5b6E44CQJHttdm5QYXRofeOAkeW3sua3u+WKoOWIsOezu+e7n1BBVEjnjq/looPlj5jph49gKTtcclxuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcign4p2MIOa3u+WKoOWksei0pe+8micsIGVyci5tZXNzYWdlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBtYXZlbiDlronoo4XlrozmiJBgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg5Yid5aeL5YyWbm9kZeeOr+Wig2ApO1xyXG4gICAgICAgICAgICAgICAgYXdhaXQgZXhlY0NtZCgnbnBtIGluc3RhbGwgLWcgcG5wbSB0eXBlc2NyaXB0IC0tcmVnaXN0cnk9aHR0cHM6Ly9yZWdpc3RyeS5ucG1taXJyb3IuY29tJyk7XHJcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg5Yid5aeL5YyWbm9kZeeOr+Wig+WujOaIkGApO1xyXG5cclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDmo4DmtYtjb2Rl5piv5ZCm5a2Y5ZyoYClcclxuICAgICAgICAgICAgICAgIGNvbnN0IGNvZGVEaXIgPSBgJHtkaXJ9L3lkcy0xLjAuM2A7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoY29kZURpcikpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2RlWmlwTmFtZSA9ICd5ZHMtMS4wLjMtamRrLTgtd2luZG93cy14ODZfNjQuemlwJ1xyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDkuIvovb1jb2RlIElERSDlronoo4XljIUgJHtjb2RlWmlwTmFtZX1gKTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2RlWmlwRmlsZSA9IGAke2Rpcn0vJHtjb2RlWmlwTmFtZX1gO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIOajgOafpeaYr+WQpuW3sue7j+WtmOWcqOWuieijheWMhSDlpoLmnpzmnInlhYjliKDpmaRcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhjb2RlWmlwRmlsZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOWIoOmZpOW3suWtmOWcqOWuieijheWMhSAke2NvZGVaaXBGaWxlfWApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmcy5ybVN5bmMoY29kZVppcEZpbGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAvLyDkuIvovb3lronoo4XljIXlubbovpPlh7rml6Xlv5dcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGAke3dnZXR9IGh0dHBzOi8veW9uY29tbXVuaXR5LnlvbnlvdWNsb3VkLmNvbS9ZRFNEb3dubG9hZC9XaW5kb3cveDY0LyR7Y29kZVppcE5hbWV9IC1PIFwiJHtjb2RlWmlwRmlsZX1cImApO1xyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDop6Pljovlronoo4XljIUgJHtjb2RlWmlwRmlsZX1gKVxyXG4gICAgICAgICAgICAgICAgICAgIGZzLm1rZGlyU3luYyhjb2RlRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGBcIiR7dW56aXB9XCIgXCIke2NvZGVaaXBGaWxlfVwiIC1kIFwiJHtjb2RlRGlyfVwiYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZnMucm1TeW5jKGNvZGVaaXBGaWxlKVxyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDUwMDApKVxyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBjb2RlIElERSDlronoo4XlrozmiJBgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDliJ3lp4vljJZZRFMgSURFIOWFqOWxgOmFjee9rmApXHJcbiAgICAgICAgICAgICAgICBjb25zdCBzZXR0aW5nc0pzb24gPSBgJHtjb2RlRGlyfS9Db2RlL2RhdGEvdXNlci1kYXRhL1VzZXIvc2V0dGluZ3MuanNvbmA7XHJcbiAgICAgICAgICAgICAgICBsZXQgc2V0dGluZ3NKc29uT2JqID0ge307XHJcbiAgICAgICAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhzZXR0aW5nc0pzb24pKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3NKc29uT2JqID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMoc2V0dGluZ3NKc29uKS50b1N0cmluZygndXRmLTgnKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsZXQgc2V0dGluZ1htbCA9IHBhdGgucmVzb2x2ZShgJHttYXZlbkhvbWV9L2NvbmYvc2V0dGluZ3MueG1sYCk7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoc2V0dGluZ1htbCkgJiYgIWZzLmV4aXN0c1N5bmMoYCR7ZGlyfS9zZXR0aW5ncy54bWxgKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGV4ZWNDbWQoYCR7d2dldH0gJHtSU19VUkx9L3NldHRpbmdzLnhtbGApO1xyXG4gICAgICAgICAgICAgICAgICAgIHNldHRpbmdYbWwgPSBwYXRoLnJlc29sdmUoYCR7ZGlyfS9zZXR0aW5ncy54bWxgKVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgc2V0dGluZ3NKc29uT2JqW1wiamF2YS5jb25maWd1cmF0aW9uLm1hdmVuLmdsb2JhbFNldHRpbmdzXCJdID0gc2V0dGluZ1htbDtcclxuICAgICAgICAgICAgICAgIHNldHRpbmdzSnNvbk9ialtcImphdmEuY29uZmlndXJhdGlvbi5tYXZlbi51c2VyU2V0dGluZ3NcIl0gPSBzZXR0aW5nWG1sO1xyXG4gICAgICAgICAgICAgICAgc2V0dGluZ3NKc29uT2JqW1wibWF2ZW4uc2V0dGluZ3NGaWxlXCJdID0gc2V0dGluZ1htbDtcclxuICAgICAgICAgICAgICAgIGZzLndyaXRlRmlsZVN5bmMoc2V0dGluZ3NKc29uLCBKU09OLnN0cmluZ2lmeShzZXR0aW5nc0pzb25PYmosIG51bGwsIDQpKTtcclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDliJ3lp4vljJZZRFMgSURFIOWFqOWxgOmFjee9ruWujOaIkGApO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIOajgOafpeW9k+WJjeeUqOaIt+ebruW9leS4iy5zc2jmmK/lkKblrZjlnKggaWRfZWQyNTUxOS5wdWIg5a+G6ZKl5paH5Lu277yM5aaC5p6c5rKh5pyJ5YiZ5pS+5YiwLnNzaCDnm67lvZXkuItcclxuICAgICAgICAgICAgICAgIGNvbnN0IHNzaERpciA9IHBhdGgucmVzb2x2ZShwcm9jZXNzLmVudi5VU0VSUFJPRklMRSwgJy5zc2gnKTtcclxuICAgICAgICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhzc2hEaXIpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZnMubWtkaXJTeW5jKHNzaERpcik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoYCR7c3NoRGlyfS9pZF9lZDI1NTE5LnB1YmApKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOaLt+i0neWvhumSpeaWh+S7tmApO1xyXG4gICAgICAgICAgICAgICAgICAgIGZzLmNvcHlGaWxlU3luYyhgJHtkaXJ9L2lkX2VkMjU1MTkucHViYCwgYCR7c3NoRGlyfS9pZF9lZDI1NTE5LnB1YmApO1xyXG4gICAgICAgICAgICAgICAgICAgIGZzLmNvcHlGaWxlU3luYyhgJHtkaXJ9L2lkX2VkMjU1MTlgLCBgJHtzc2hEaXJ9L2lkX2VkMjU1MTlgKTtcclxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg5ou36LSd5a+G6ZKl5paH5Lu25a6M5oiQYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOWIneWni+WMlllEU+WItuebmOeOr+Wig+WujOaIkGApXHJcbiAgICAgICAgICAgIH0pLmhvb2soJ3Bvc3RBY3Rpb24nLCAoKSA9PiBwcm9jZXNzLmV4aXQoMCkpO1xyXG5cclxuICAgICAgICBwcm9ncmFtXHJcbiAgICAgICAgICAgIC5jb21tYW5kKCdzdGFydCA8Y2F0YWxvZz4gW3dvcmtkaXJdJylcclxuICAgICAgICAgICAgLnVzYWdlKCdzdGFydCA8Y2F0YWxvZz4gW3dvcmtkaXJdJylcclxuICAgICAgICAgICAgLm9wdGlvbignLWYsIC0tZmlsZSA8ZmlsZT4nLCAn6YWN572u5paH5Lu2JylcclxuICAgICAgICAgICAgLmFkZEhlbHBUZXh0KCdhZnRlcicsIGBcclxu6YWN572u5paH5Lu25YaF5a6556S65L6L77yaXHJcbntcclxuICAgIGhvc3RzPzogQXJyYXk8c3RyaW5nPjtcclxuICAgIGdpdDogUmVjb3JkPCdocmNwZScgfCAnZmVjb2RlJywgc3RyaW5nPjtcclxuICAgIGNhdGFsb2dzOiB7XHJcbiAgICAgICAgW2NhdGFsb2c6IHN0cmluZ106IFJlY29yZDwnaHJjcGUnIHwgJ2ZlY29kZScsIHN0cmluZyB8IHsgdXJsOiBzdHJpbmcsIGJyYW5jaDogc3RyaW5nIH0+XHJcbiAgICB9XHJcbn1gKVxyXG4gICAgICAgICAgICAuZGVzY3JpcHRpb24oJ+WQr+WKqOWItuebmOeOr+Wig++8jGNhdGFsb2fooajnpLrpnIDopoHliLbnm5jnmoTmqKHlnZfvvIzlr7nlupTphY3nva7mlofku7bkuK1jYXRhbG9nc+eahGtleeWAvO+8jOeUqOS6juaMh+WumumcgOimgeWHuuebmOeahOS/oeaBr++8jHdvcmtkaXLooajnpLrliLbnm5jlt6XkvZznm67lvZXvvIzlpoLmnpzkuI3mjIflrprliJnkvb/nlKjlvZPliY3nm67lvZUnKVxyXG4gICAgICAgICAgICAuYWN0aW9uKGFzeW5jIChjYXRhbG9nOiBzdHJpbmcsIHdvcmtkaXI6IHN0cmluZyA9IHBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpKSwgb3B0aW9uczogeyBmaWxlOiBzdHJpbmcgfSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGlyID0gcGF0aC5yZXNvbHZlKHdvcmtkaXIpO1xyXG5cclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDlvIDlp4vmo4DmtYvliLbnm5jnjq/looPmo4DmtYtgKTtcclxuICAgICAgICAgICAgICAgIGxldCBnaXRDbWQgPSAnZ2l0JztcclxuICAgICAgICAgICAgICAgIGNvbnN0IGdpdEV4aXN0cyA9IGF3YWl0IHV0aWwuY21kLmV4aXN0cyhnaXRDbWQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFnaXRFeGlzdHMpIHtcclxuICAgICAgICAgICAgICAgICAgICBnaXRDbWQgPSBgJHtkaXJ9L2dpdC1mb3Itd2luZG93cy9iaW4vZ2l0LmV4ZWA7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKGdpdENtZCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGDmnKrmib7liLBnaXTlkb3ku6QgJHtnaXRDbWR9LCDor7flhYjmiafooYwgaW5pdCDliJ3lp4vljJbliLbnm5jnjq/looNgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzcy5leGl0KDEpXHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGxldCBzZXR0aW5nWG1sID0gcGF0aC5yZXNvbHZlKGAke2Rpcn0vc2V0dGluZ3MueG1sYCk7XHJcbiAgICAgICAgICAgICAgICBsZXQgbXZuQ21kID0gJ212bic7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoc2V0dGluZ1htbCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgbWF2ZW5Ib21lID0gYCR7ZGlyfS9tYXZlbi0zLjguNmA7XHJcbiAgICAgICAgICAgICAgICAgICAgbXZuQ21kID0gYFwiJHttYXZlbkhvbWV9L2Jpbi9tdm4uY21kXCJgO1xyXG4gICAgICAgICAgICAgICAgICAgIHNldHRpbmdYbWwgPSBgJHttYXZlbkhvbWV9L2NvbmYvc2V0dGluZ3MueG1sYDtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMobXZuQ21kKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYOacquaJvuWIsG12buWRveS7pCAke212bkNtZH0sIOivt+WFiOaJp+ihjCBpbml0IOWIneWni+WMluWItuebmOeOr+Wig2ApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLmV4aXQoMSlcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IGlkZVBhdGggPSBgJHtkaXJ9L3lkcy0xLjAuM2BcclxuICAgICAgICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhpZGVQYXRoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihg5pyq5om+5YiwSURFICR7aWRlUGF0aH0sIOivt+WFiOaJp+ihjCBpbml0IOWIneWni+WMluWItuebmOeOr+Wig2ApO1xyXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDliLbnm5jnjq/looPmo4DmtYvlrozmiJBgKVxyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IHlkc0pzb24gPSBwYXRoLnJlc29sdmUob3B0aW9ucy5maWxlIHx8IGAke2Rpcn0veWRzLmpzb25gKTtcclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDlvIDlp4vliLbnm5ggJHtjYXRhbG9nfSDlt6XkvZznm67lvZXvvJoke2Rpcn1gKTtcclxuICAgICAgICAgICAgICAgIC8vIOivu+WPlumFjee9ruaWh+S7tlxyXG4gICAgICAgICAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKHlkc0pzb24pKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGDmnKrmib7liLDphY3nva7mlofku7YgJHt5ZHNKc29ufWApO1xyXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGNvbnN0IHlkc0pzb25TdHIgPSBmcy5yZWFkRmlsZVN5bmMoeWRzSnNvbikudG9TdHJpbmcoJ3V0Zi04Jyk7XHJcbiAgICAgICAgICAgICAgICAvLyDmo4DmtYvphY3nva7mlofku7bmmK/lkKblrozmlbRcclxuICAgICAgICAgICAgICAgIGxldCBjb25maWc6IFlkc0NvbmZpZztcclxuICAgICAgICAgICAgICAgIGNvbnN0IGNoZWNrQ29uZmlnRXJyb3IgPSAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGDphY3nva7mlofku7YgJHt5ZHNKc29ufSDmoLzlvI/plJnor68g5Y+C6ICD56S65L6L77yaXHJcbntcclxuICAgIGhvc3RzPzogQXJyYXk8c3RyaW5nPjtcclxuICAgIGdpdDogUmVjb3JkPCdocmNwZScgfCAnZmVjb2RlJywgc3RyaW5nPjtcclxuICAgIGNhdGFsb2dzOiB7XHJcbiAgICAgICAgW2NhdGFsb2c6IHN0cmluZ106IFJlY29yZDwnaHJjcGUnIHwgJ2ZlY29kZScsIHN0cmluZyB8IHsgdXJsOiBzdHJpbmcsIGJyYW5jaDogc3RyaW5nIH0+XHJcbiAgICB9XHJcbn1gKTtcclxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZyA9IEpTT04ucGFyc2UoeWRzSnNvblN0cik7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb25maWcuY2F0YWxvZ3MpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tDb25maWdFcnJvcigpXHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNoZWNrQ29uZmlnRXJyb3IoKVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgY29uc3QgZ2l0ID0gY29uZmlnLmdpdDtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGNhdGFsb2dDb25maWcgPSBjb25maWcuY2F0YWxvZ3NbY2F0YWxvZ107XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNhdGFsb2dDb25maWcgPT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGDphY3nva7mlofku7YgJHt5ZHNKc29ufSDmib7kuI3liLAgY2F0YWxvZ3MuJHtjYXRhbG9nfSDlhYjlhbPphY3nva5gKTtcclxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNhdGFsb2dDb25maWcuaHJjcGUgPT09ICd1bmRlZmluZWQnIHx8IHR5cGVvZiBjYXRhbG9nQ29uZmlnLmZlY29kZSA9PT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYOmFjee9ruaWh+S7tiAke3lkc0pzb259IGNhdGFsb2dzLiR7Y2F0YWxvZ30uaHJjcGUg5oiWIGNhdGFsb2dzLiR7Y2F0YWxvZ30uZmVjb2RlIOWtl+autee8uuWksWApO1xyXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBuYW1lc3BhY2UgPSBgJHtkaXJ9LyR7Y2F0YWxvZ31gO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKG5hbWVzcGFjZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg5Yib5bu655uu5b2VICR7bmFtZXNwYWNlfWApO1xyXG4gICAgICAgICAgICAgICAgICAgIGZzLm1rZGlyU3luYyhuYW1lc3BhY2UpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg55uu5b2VICR7bmFtZXNwYWNlfSDlt7LlrZjlnKhgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxldCBocmNwZVVybCA9IHR5cGVvZiBjYXRhbG9nQ29uZmlnLmhyY3BlID09PSAnc3RyaW5nJyA/IGdpdD8uaHJjcGUgOiBjYXRhbG9nQ29uZmlnLmhyY3BlLnVybDtcclxuICAgICAgICAgICAgICAgIGlmICghaHJjcGVVcmwpIHtcclxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYOmFjee9ruaWh+S7tiAke3lkc0pzb259IGNhdGFsb2dzLiR7Y2F0YWxvZ30g5ZCO56uv5pyN5YqhIOacquaMh+WumuS7k+W6k+WcsOWdgO+8jOivt+mAmui/hyBnaXQuaHJjcGUg5oiW6ICFIGNhdGFsb2dzLiR7Y2F0YWxvZ30uaHJjcGUudXJsIOaMh+WumuS7k+W6k+WcsOWdgGApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOW8gOWni+aLieWPluWQjuerr+acjeWKoeS7k+W6kyAke2hyY3BlVXJsfWApO1xyXG4gICAgICAgICAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMoYCR7bmFtZXNwYWNlfS8uZ2l0YCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg55uu5b2VICR7bmFtZXNwYWNlfSDlt7LlrZjlnKjvvIzlvIDlp4vmm7TmlrDku5PlupNgKTtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGBcIiR7Z2l0Q21kfVwiIHB1bGxgLCBuYW1lc3BhY2UpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg55uu5b2VICR7bmFtZXNwYWNlfSDkuI3lrZjlnKjvvIzlvIDlp4vliJvlu7rku5PlupNgKTtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgYnJhbmNoID0gdHlwZW9mIGNhdGFsb2dDb25maWcuaHJjcGUgPT09ICdzdHJpbmcnID8gY2F0YWxvZ0NvbmZpZy5ocmNwZSA6IGNhdGFsb2dDb25maWcuaHJjcGUuYnJhbmNoO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICghYnJhbmNoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihg6YWN572u5paH5Lu2ICR7eWRzSnNvbn0gY2F0YWxvZ3MuJHtjYXRhbG9nfSDlkI7nq6/mnI3liqEg5pyq5oyH5a6a5YiG5pSv77yM6K+36YCa6L+HIGdpdC5ocmNwZSDmiJbogIUgY2F0YWxvZ3MuJHtjYXRhbG9nfS5ocmNwZS5icmFuY2gg6YWN572u5YiG5pSvYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZXhlY0NtZChgXCIke2dpdENtZH1cIiBjbG9uZSAtYiAke2JyYW5jaH0gJHtocmNwZVVybH0gJHtuYW1lc3BhY2V9YCwgbmFtZXNwYWNlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDmi4nlj5blkI7nq6/mnI3liqHku5PlupPlrozmiJBgKTtcclxuICAgICAgICAgICAgICAgIGxldCBib29zdHJhcFBvbVhtbCA9IGAke25hbWVzcGFjZX0vJHtkb21haW5LZXl9LWJlL2Rldi0ke2RvbWFpbktleX0tYm9vdHN0cmFwL3BvbS54bWxgO1xyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOabv+aNouaWh+S7tiAke2Jvb3N0cmFwUG9tWG1sfSDkuK3nmoRST09U5Li6ZG9tYWluS2V577yM5ZCm5YiZ5Lya5a+86Ie05Yi255uY5aSx6LSl77yM5peg5rOV5om+5Yiw5Yi25ZOBYCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBib29zdHJhcFBvbVhtbFN0cmluZyA9IGZzLnJlYWRGaWxlU3luYyhib29zdHJhcFBvbVhtbCkudG9TdHJpbmcoJ3V0Zi04Jyk7XHJcbiAgICAgICAgICAgICAgICBpZiAoYm9vc3RyYXBQb21YbWxTdHJpbmcuaW5jbHVkZXMoJ1JPT1QnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGZzLndyaXRlRmlsZVN5bmMoYm9vc3RyYXBQb21YbWwsIGJvb3N0cmFwUG9tWG1sU3RyaW5nLnJlcGxhY2UoL1JPT1QvZywgZG9tYWluS2V5KSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5ob3N0cyAmJiBjb25maWcuaG9zdHMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOWtmOWcqGhvc3Rz6YWN572u77yM5qOA5rWL57O757ufaG9zdHPphY3nva7mlofku7bmmK/lkKblt7Lnu4/phY3nva5gKTtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgaG9zdHNGaWxlID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuZW52LldJTkRJUiwgJ1N5c3RlbTMyJywgJ2RyaXZlcnMnLCAnZXRjJywgJ2hvc3RzJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaG9zdExpc3QgPSBmcy5yZWFkRmlsZVN5bmMoaG9zdHNGaWxlKS50b1N0cmluZygndXRmLTgnKS5zcGxpdCgnXFxuJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGFwcGVuZEhvc3RzID0gWy4uLmNvbmZpZy5ob3N0c11cclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBob3N0SXRlbSBvZiBob3N0TGlzdCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoLyMvLnRlc3QoaG9zdEl0ZW0pKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBhcHBlbmRIb3N0IG9mIGNvbmZpZy5ob3N0cykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW2lwLCBkb21haW5dID0gYXBwZW5kSG9zdC5zcGxpdCgnICcpLmZpbHRlcihpdGVtID0+IGl0ZW0pXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaG9zdEl0ZW0uaW5jbHVkZXMoaXApICYmIGhvc3RJdGVtLmluY2x1ZGVzKGRvbWFpbikpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg57O757ufaG9zdHPphY3nva7mlofku7blt7LlrZjlnKggJHthcHBlbmRIb3N0fWApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGVuZEhvc3RzLnJlbW92ZShhcHBlbmRIb3N0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAvLyDor7vlj5bns7vnu59ob3N0c+mFjee9ruaWh+S7tlxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChhcHBlbmRIb3N0cy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzQWRtaW4oKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZnMuYXBwZW5kRmlsZVN5bmMoaG9zdHNGaWxlLCBgXFxuJHthcHBlbmRIb3N0cy5qb2luKCdcXG4nKX1cXG5gLCB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jb2Rpbmc6ICd1dGYtOCdcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYOW9k+WJjemdnueuoeeQhuWRmOWQr+WKqOaXoOazleabtOaUuWhvc3Rz5paH5Lu277yM6K+35L2/55So566h55CG5ZGY5ZCv5Yqo5oiW6ICF5omL5Yqo5re75YqgICR7YXBwZW5kSG9zdHMuam9pbignXFxuJyl9IOWIsOaWh+S7tiAke2hvc3RzRmlsZX1gKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhgaG9zdHMg6YWN572u5qOA5rWL5a6M5oiQYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ+WIneWni+WMlumhueebrm1hdmVu546v5aKDJyk7XHJcbiAgICAgICAgICAgICAgICBsZXQgbXZuQ29uZmlnRGlyID0gYCR7bmFtZXNwYWNlfS8ubXZuYDtcclxuICAgICAgICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhtdm5Db25maWdEaXIpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZXhlY0NtZChgJHttdm5DbWR9IC1OIGlvLnRha2FyaTptYXZlbjp3cmFwcGVyIC1EbWF2ZW49My44LjZgLCBuYW1lc3BhY2UpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgLy8g5YaZ5YWlbWF2ZW7phY3nva7liLAgLm12bi9tYXZlbi5jb25maWdcclxuICAgICAgICAgICAgICAgIGxldCBjb25maWdGaWxlID0gYCR7bXZuQ29uZmlnRGlyfS9tYXZlbi5jb25maWdgO1xyXG4gICAgICAgICAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMoY29uZmlnRmlsZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICBmcy5ybVN5bmMoY29uZmlnRmlsZSlcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGZzLndyaXRlRmlsZVN5bmMoYCR7bXZuQ29uZmlnRGlyfS9tYXZlbi5jb25maWdgLCBgLXNcXG4ke3NldHRpbmdYbWx9XFxuLURtYXZlbi53YWdvbi5odHRwLnNzbC5pbnNlY3VyZT10cnVlXFxuLURtYXZlbi53YWdvbi5odHRwLnNzbC5hbGxvd2FsbD10cnVlYCk7XHJcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhg5b2T5YmNbWF2ZW7kv6Hmga9gKVxyXG4gICAgICAgICAgICAgICAgYXdhaXQgZXhlY0NtZChgJHttdm5DbWR9IC0tdmVyc2lvbmAsIG5hbWVzcGFjZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ+mhueebrm1hdmVu5riF55CGJylcclxuICAgICAgICAgICAgICAgIGF3YWl0IGV4ZWNDbWQoYCR7bXZuQ21kfSBjbGVhbiAtRHNraXBUZXN0c2AsIGAke25hbWVzcGFjZX0vJHtkb21haW5LZXl9LWJlYCk7XHJcblxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ+WkhOeQhuWJjeerr+aehOW7uu+8jOWinuWKoOaehOW7uuaWh+S7ticpO1xyXG4gICAgICAgICAgICAgICAgbGV0IGZlRGlyID0gYCR7bmFtZXNwYWNlfS8ke2RvbWFpbktleX0tZmVgO1xyXG4gICAgICAgICAgICAgICAgbGV0IGZlQnVpbGRKcyA9IGAke2ZlRGlyfS9idWlsZC5qc2A7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZmVCdWlsZEpzKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGZzLmNwU3luYyhgJHtkaXJ9L2ZlLWJ1aWxkLmpzYCwgZmVCdWlsZEpzKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxldCBmZVBhY2thZ2VKc29uID0gYCR7ZmVEaXJ9L3BhY2thZ2UuanNvbmA7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBwYWNrYWdlU3RyaW5nID0gZnMucmVhZEZpbGVTeW5jKGZlUGFja2FnZUpzb24pLnRvU3RyaW5nKCd1dGYtOCcpO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFwYWNrYWdlU3RyaW5nLmluY2x1ZGVzKCdidWlsZC5qcycpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOS/ruaUuSR7ZmVQYWNrYWdlSnNvbn1gKTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWNrYWdlSnNvbiA9IEpTT04ucGFyc2UocGFja2FnZVN0cmluZyk7XHJcbiAgICAgICAgICAgICAgICAgICAgcGFja2FnZUpzb24uc2NyaXB0c1snYnVpbGQ6ZXh0ZW5kJ10gKz0gJyAmJiBub2RlIGJ1aWxkLmpzJztcclxuICAgICAgICAgICAgICAgICAgICBmcy53cml0ZUZpbGVTeW5jKGZlUGFja2FnZUpzb24sIEpTT04uc3RyaW5naWZ5KHBhY2thZ2VKc29uLCBudWxsLCA0KSk7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOS/ruaUuSR7ZmVQYWNrYWdlSnNvbn3lrozmiJBgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IGZlY29kZVVybCA9IHR5cGVvZiBjYXRhbG9nQ29uZmlnLmZlY29kZSA9PT0gJ3N0cmluZycgPyBnaXQ/LmZlY29kZSA6IGNhdGFsb2dDb25maWcuZmVjb2RlLnVybDtcclxuICAgICAgICAgICAgICAgIGlmICghZmVjb2RlVXJsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGDphY3nva7mlofku7YgJHt5ZHNKc29ufSBjYXRhbG9ncy4ke2NhdGFsb2d9IOWQjuerr+acjeWKoSDmnKrmjIflrprku5PlupPlnLDlnYDvvIzor7fpgJrov4cgZ2l0LmZlY29kZSDmiJbogIUgY2F0YWxvZ3MuJHtjYXRhbG9nfS5mZWNvZGUudXJsIOaMh+WumuS7k+W6k+WcsOWdgGApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOW8gOWni+aLieWPluaKpeWRiuacjeWKoeS7k+W6kyAke2ZlY29kZVVybH1gKTtcclxuICAgICAgICAgICAgICAgIGxldCByZXBvcnROYW1lc3BhY2UgPSBgJHtuYW1lc3BhY2V9L3lvbmJpcC15aXN2LWl6cDEtZGV2LWZlY29kZWA7XHJcbiAgICAgICAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhgJHtyZXBvcnROYW1lc3BhY2V9Ly5naXRgKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDnm67lvZUgJHtyZXBvcnROYW1lc3BhY2V9IOW3suWtmOWcqO+8jOW8gOWni+abtOaWsOS7k+W6k2ApO1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGV4ZWNDbWQoYFwiJHtnaXRDbWR9XCIgcHVsbGAsIHJlcG9ydE5hbWVzcGFjZSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDnm67lvZUgJHtyZXBvcnROYW1lc3BhY2V9IOS4jeWtmOWcqO+8jOW8gOWni+WIm+W7uuS7k+W6k2ApO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBicmFuY2ggPSB0eXBlb2YgY2F0YWxvZ0NvbmZpZy5mZWNvZGUgPT09ICdzdHJpbmcnID8gY2F0YWxvZ0NvbmZpZy5mZWNvZGUgOiBjYXRhbG9nQ29uZmlnLmZlY29kZS5icmFuY2g7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFicmFuY2gpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGDphY3nva7mlofku7YgJHt5ZHNKc29ufSBjYXRhbG9ncy4ke2NhdGFsb2d9IOaKpeWRiuacjeWKoeacquaMh+WumuWIhuaUr++8jOivt+mAmui/hyBnaXQuZmVjb2RlIOaIluiAhSBjYXRhbG9ncy4ke2NhdGFsb2d9LmZlY29kZS5icmFuY2gg6YWN572u5YiG5pSvYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZXhlY0NtZChgXCIke2dpdENtZH1cIiBjbG9uZSAtYiAke2JyYW5jaH0gJHtmZWNvZGVVcmx9ICR7cmVwb3J0TmFtZXNwYWNlfWApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOaLieWPluaKpeWRiuacjeWKoeS7k+W6k+WujOaIkGApO1xyXG5cclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCflpITnkIbmiqXlkYrmnoTlu7rvvIzlop7liqDmnoTlu7rmlofku7YnKTtcclxuICAgICAgICAgICAgICAgIGxldCBmZWNvZGVCdWlsZEpzID0gYCR7cmVwb3J0TmFtZXNwYWNlfS9idWlsZC5qc2A7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZmVjb2RlQnVpbGRKcykpIHtcclxuICAgICAgICAgICAgICAgICAgICBmcy5jcFN5bmMoYCR7ZGlyfS9mZWNvZGUtYnVpbGQuanNgLCBmZWNvZGVCdWlsZEpzKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxldCBmZWNvZGVQYWNrYWdlSnNvbiA9IGAke3JlcG9ydE5hbWVzcGFjZX0vcGFja2FnZS5qc29uYDtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGZlY29kZVBhY2thZ2VTdHJpbmcgPSBmcy5yZWFkRmlsZVN5bmMoZmVjb2RlUGFja2FnZUpzb24pLnRvU3RyaW5nKCd1dGYtOCcpO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFmZWNvZGVQYWNrYWdlU3RyaW5nLmluY2x1ZGVzKCdidWlsZC5qcycpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOS/ruaUuSR7ZmVjb2RlUGFja2FnZUpzb259YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFja2FnZUpzb24gPSBKU09OLnBhcnNlKGZlY29kZVBhY2thZ2VTdHJpbmcpO1xyXG4gICAgICAgICAgICAgICAgICAgIHBhY2thZ2VKc29uLnNjcmlwdHNbJ2J1aWxkJ10gKz0gJyAmJiBub2RlIGJ1aWxkLmpzJztcclxuICAgICAgICAgICAgICAgICAgICBwYWNrYWdlSnNvbi5kb21haW5LZXkgPSBkb21haW5LZXk7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8g5Yig6Zmk5q2k5L6d6LWWIOS8muWvvOiHtG5wbSBpIOWksei0pVxyXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBwYWNrYWdlSnNvbi5kZXBlbmRlbmNpZXMuemxpYlxyXG4gICAgICAgICAgICAgICAgICAgIGZzLndyaXRlRmlsZVN5bmMoZmVjb2RlUGFja2FnZUpzb24sIEpTT04uc3RyaW5naWZ5KHBhY2thZ2VKc29uLCBudWxsLCA0KSk7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOS/ruaUuSR7ZmVjb2RlUGFja2FnZUpzb2595a6M5oiQYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOWuieijheaKpeWRiuacjeWKoeS+nei1lmApO1xyXG4gICAgICAgICAgICAgICAgYXdhaXQgZXhlY0NtZCgnbnBtIGknLCByZXBvcnROYW1lc3BhY2UpO1xyXG5cclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDnlJ/miJB2ZXJzaW9uLmpzb24g5paH5Lu2YClcclxuICAgICAgICAgICAgICAgIGNvbnN0IHV1aWQgPSByYW5kb21VVUlEKCkudG9TdHJpbmcoKVxyXG4gICAgICAgICAgICAgICAgZnMud3JpdGVGaWxlU3luYyhgJHtyZXBvcnROYW1lc3BhY2V9L3ZlcnNpb24uanNvbmAsIGB7XCJ2ZXJzaW9uXCI6IFwiJHt1dWlkfVwifWApO1xyXG5cclxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCfliJ3lp4vljJbpobnnm67njq/looPotYTmupAnKTtcclxuICAgICAgICAgICAgICAgIC8vIOWmguaenCBuYW1lc3BhY2UvKGRpc2t8ZGlza3MpIOWmguaenOWtmOWcqCDot7Pov4dcclxuICAgICAgICAgICAgICAgIGlmIChmcy5leGlzdHNTeW5jKGAke25hbWVzcGFjZX0vZGlza2ApIHx8IGZzLmV4aXN0c1N5bmMoYCR7bmFtZXNwYWNlfS9kaXNrc2ApKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYOW3suWtmOWcqO+8jOi3s+i/h+eOr+Wig+i1hOa6kOaWh+S7tuS4i+i9vWApO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBodHRwczovL2Rmcy56aGlwZXIuY29tL3YzcjYvZW52LnppcFxyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDlvIDlp4vkuIvovb3pobnnm67njq/looPotYTmupDmlofku7ZgKVxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBnaXRaaXBGaWxlID0gYCR7bmFtZXNwYWNlfS9lbnYuemlwYDtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGAke3dnZXR9ICR7UlNfVVJMfS9lbnYuemlwIC1PIFwiJHtnaXRaaXBGaWxlfVwiYCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDop6PljovotYTmupDmlofku7bljIUgJHtnaXRaaXBGaWxlfWApXHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZXhlY0NtZChgXCIke3VuemlwfVwiIFwiJHtnaXRaaXBGaWxlfVwiYCwgbmFtZXNwYWNlKTtcclxuICAgICAgICAgICAgICAgICAgICBmcy5ybVN5bmMoZ2l0WmlwRmlsZSlcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygn5ZCv5YqoSURFJyk7XHJcbiAgICAgICAgICAgICAgICBhd2FpdCBleGVjQ21kKGBcIiR7aWRlUGF0aH0vQ29kZS9Db2RlLmV4ZVwiIFwiJHtuYW1lc3BhY2V9XCJgKTtcclxuICAgICAgICAgICAgICAgIC8vIOmcgOimgeetieW+hUlEReWQr+WKqOWujOaIkOWQjuWFs+mXrVxyXG4gICAgICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDMwMDApKVxyXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ+W3suWQr+WKqElERe+8jOivt+aMieeFp+aWh+aho+ivtOaYjui/m+ihjOWItuebmOaTjeS9nCcpXHJcbiAgICAgICAgICAgIH0pLmhvb2soJ3Bvc3RBY3Rpb24nLCAoKSA9PiBwcm9jZXNzLmV4aXQoMCkpXHJcblxyXG4gICAgICAgIHByb2dyYW0ucGFyc2UocHJvY2Vzcy5hcmd2KVxyXG4gICAgfVxyXG59XHJcbiJdfQ==
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "yds-tool",
3
+ "version": "0.0.1",
4
+ "description": "isv本地制盘工具",
5
+ "main": "./bin/index.js",
6
+ "bin": {
7
+ "yds": "./bin/cli.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "src"
12
+ ],
13
+ "keywords": [
14
+ "yds"
15
+ ],
16
+ "scripts": {
17
+ "init": "tsc -p tsconfig.json&node bin/app.js init",
18
+ "start": "tsc -p tsconfig.json&node bin/app.js start geer"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git@codeup.aliyun.com:6166f78958608c6ab5d8d66d/isv/create-disk.git"
23
+ },
24
+ "engines": {
25
+ "node": ">=20.0.0"
26
+ },
27
+ "author": "",
28
+ "license": "ISC",
29
+ "dependencies": {
30
+ "@babel/cli": "^7.16.0",
31
+ "@babel/core": "^7.16.5",
32
+ "@babel/plugin-proposal-decorators": "^7.16.5",
33
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
34
+ "@babel/plugin-transform-runtime": "^7.16.5",
35
+ "@babel/preset-env": "^7.16.5",
36
+ "@babel/register": "^7.16.5",
37
+ "@babel/runtime": "^7.16.5",
38
+ "@types/node": "^20.1.3",
39
+ "babel-plugin-transform-decorators-legacy": "^1.3.5",
40
+ "commander": "^14.0.2",
41
+ "sqlite3": "^5.1.7",
42
+ "vweb-core": "^3.2.3"
43
+ }
44
+ }
package/readme.md ADDED
@@ -0,0 +1,24 @@
1
+ # YDS制盘工具
2
+
3
+ > 支持ISV V3R6出盘
4
+
5
+ ## 本地开发
6
+
7
+ ```shell
8
+ npm run init
9
+ npm run start
10
+ ```
11
+
12
+ ## 本地安装调试
13
+
14
+ ```shell
15
+ # 查看全局安装的包
16
+
17
+ npm list -g --depth 0
18
+
19
+ # 临时安装 退出时候务必卸载 否则会污染全局环境
20
+ npm link
21
+
22
+ # 卸载
23
+ npm uninstall -g yds-tool
24
+ ```
package/src/main.ts ADDED
@@ -0,0 +1,479 @@
1
+ import {program} from "commander";
2
+ import * as process from "process";
3
+ import {LoggerFactory, util} from "vweb-core";
4
+ import * as path from "node:path";
5
+ import * as child_process from "node:child_process";
6
+ import * as fs from "node:fs";
7
+ import * as os from 'node:os';
8
+ import {randomUUID} from 'crypto'
9
+
10
+ const domainKey = 'p-hcc-i000-p00a-hrcpe';
11
+ const pkg = require('../package.json');
12
+ const RS_URL = 'https://dfs.zhiper.com/v3r6';
13
+
14
+ const logger: Logger = LoggerFactory.getLogger('YDS');
15
+
16
+ const execCmd = async (command: string, cwd?: string) => {
17
+ logger.info(`执行命令 ${command} ${cwd ? `,执行目录为${cwd}` :''}`);
18
+ let start = Date.now();
19
+ child_process.execSync(command, {
20
+ cwd, encoding: 'utf-8',
21
+ timeout: 60000,
22
+ stdio: [0, 1, 2]
23
+ });
24
+ logger.info(`执行命令 ${command} 耗时 \x1B[34m <${Date.now() - start}ms>]`)
25
+ }
26
+
27
+ const platform = os.platform()
28
+ if (platform !== 'win32') {
29
+ logger.error('当前工具仅支持windows系统');
30
+ process.exit(1);
31
+ }
32
+
33
+ const isAdmin = () => {
34
+ try {
35
+ // 尝试执行一个只有管理员才能运行的命令
36
+ // 使用 >nul 2>&1 来抑制输出
37
+ child_process.execSync('net session >nul 2>&1');
38
+ return true; // 成功执行
39
+ } catch (err) {
40
+ return false; // 执行失败,权限不足
41
+ }
42
+ }
43
+
44
+ let wget = path.resolve( 'wget.exe');
45
+ let zip = path.resolve('zip.exe');
46
+ let unzip = path.resolve('unzip.exe');
47
+
48
+ program.name("yds")
49
+ .usage("[command] [options]")
50
+ .description("yds 制盘工具 如果命令参数中存在空格 使用双引号\"\"包裹")
51
+ .version(`yds ${pkg.version}`);
52
+
53
+ type MicroService = 'hrcpe' | 'fecode';
54
+
55
+ type Git = {
56
+ url: string,
57
+ branch: string
58
+ }
59
+
60
+ type YdsConfig = {
61
+ hosts: Array<string>;
62
+ git: Record<MicroService, string>;
63
+ catalogs: {
64
+ [catalog: string]: Record<MicroService, string | Git>
65
+ }
66
+ }
67
+
68
+ export default class Main {
69
+
70
+ startup() {
71
+ program
72
+ .command('init [workdir]')
73
+ .usage('init [workdir]')
74
+ .description('初始化YDS制盘环境, workdir表示制盘工作目录,如果不指定则使用当前目录')
75
+ .action(async (workdir: string = path.resolve(process.cwd())) => {
76
+ const dir = path.resolve(workdir);
77
+ logger.info(`初始化YDS制盘环境 工作目录:${dir}`);
78
+ const gitExists = await util.cmd.exists('git');
79
+ logger.info(`检查是否安装了git >> ${gitExists ? '已安装' : '未安装'}`);
80
+ if (!gitExists && !fs.existsSync(`${dir}/git-for-windows`)) {
81
+ const gitZipName = 'git-for-windows.zip'
82
+ logger.info(`下载git 安装包 ${gitZipName}`);
83
+ const gitZipFile = `${dir}/${gitZipName}`;
84
+ // 检查是否已经存在安装包 如果有先删除
85
+ if (fs.existsSync(gitZipFile)) {
86
+ logger.info(`删除已存在安装包 ${gitZipFile}`);
87
+ fs.rmSync(gitZipFile);
88
+ }
89
+ // 下载安装包并输出日志
90
+ await execCmd(`${wget} ${RS_URL}/${gitZipName} -O "${gitZipFile}"`);
91
+ logger.info(`解压安装包 ${gitZipFile}`)
92
+ await execCmd(`"${unzip}" "${gitZipFile}" -d "${dir}"`);
93
+ fs.rmSync(gitZipFile)
94
+ logger.info(`git 安装完成`);
95
+ }
96
+
97
+ const javaExists = await util.cmd.exists('java');
98
+ logger.info(`检查是否安装了java >> ${javaExists ? '已安装' : '未安装'}`);
99
+ if (!javaExists) {
100
+ logger.info('未找到java,准备安装java,开始下载jdk');
101
+ const jdkZipName = 'jdk-11.0.15.1_windows-x64_bin.zip'
102
+ await execCmd(`${wget} ${RS_URL}/${jdkZipName} -O "${dir}/${jdkZipName}"`);
103
+ logger.info(`解压jdk 安装包 ${dir}/${jdkZipName}`)
104
+ await execCmd(`"${unzip}" "${dir}/${jdkZipName}"`, dir);
105
+ logger.info(`配置java环境变量`);
106
+ let javaHome = `${dir}/jdk-11.0.15.1`;
107
+ await execCmd(`setx JAVA_HOME "${javaHome}"`);
108
+ await execCmd(`setx CLASS_PATH ".;%JAVA_HOME%\lib;"`);
109
+ await execCmd( `setx PATH "%PATH%;%JAVA_HOME%\bin;"` );
110
+ process.env.JAVA_HOME = javaHome;
111
+ logger.info(`java 安装完成`);
112
+ }
113
+
114
+ logger.info(`检查java版本`);
115
+ await execCmd('java -version');
116
+ // 导入证书到java 如果java是1.8版本 需要导入到 JAVA_HOME/jre/lib/security/cacerts 如果是11版本 需要导入到 JAVA_HOME/lib/security/cacerts
117
+ const javaHome = process.env.JAVA_HOME;
118
+ if (javaHome) {
119
+ let certsFilename = 'lib/security/cacerts';
120
+ let certsFile = `${javaHome}/${certsFilename}`;
121
+ if (!fs.existsSync(certsFile)) {
122
+ certsFile = `${javaHome}/jre/${certsFilename}`;
123
+ }
124
+ logger.info(`检查java证书目录 ${certsFile}`);
125
+ if (fs.existsSync(certsFile)) {
126
+ // 判断证书是否已经导入
127
+ try {
128
+ await execCmd(`keytool -list -v -keystore "${certsFile}" -storepass changeit --alias yyrd`)
129
+ logger.info(`yyrd.crt 证书已存在`);
130
+ } catch (e) {
131
+ // 证书不存在
132
+ logger.info(`导入 yyrd.crt 证书到java ${certsFile}`);
133
+ await execCmd(`keytool -importcert -file "${dir}/yyrd.crt" -keystore "${certsFile}" -storepass changeit -noprompt`);
134
+ logger.info(`yyrd.crt 证书导入完成`);
135
+ }
136
+ }
137
+ }
138
+
139
+ const mavenHome = `${dir}/maven-3.8.6`;
140
+ const mavenExists = util.cmd.exists('mvn');
141
+ logger.info(`检查是否安装了maven >> ${mavenExists ? '已安装' : '未安装'}`);
142
+ if (!mavenExists) {
143
+ const mavenZipName = 'maven-3.8.6.zip'
144
+ logger.info(`下载maven 安装包 ${mavenZipName}`);
145
+ const mavenZipFile = `${dir}/${mavenZipName}`;
146
+ // 检查是否已经存在安装包 如果有先删除
147
+ if (fs.existsSync(mavenZipFile)) {
148
+ logger.info(`删除已存在安装包 ${mavenZipFile}`);
149
+ fs.rmSync(mavenZipFile);
150
+ }
151
+ // 下载安装包并输出日志
152
+ await execCmd(`${wget} ${RS_URL}/${mavenZipName} -O "${mavenZipFile}"`);
153
+ logger.info(`解压安装包 ${mavenZipFile}`)
154
+ await execCmd(`"${unzip}" "${mavenZipFile}" -d "${dir}"`);
155
+ fs.rmSync(mavenZipFile);
156
+
157
+ // 添加maven 环境变量
158
+ try {
159
+ // Windows核心命令:永久追加路径到【用户环境变量PATH】,永久生效
160
+ let mvnPath = path.resolve(`${mavenHome}/bin`);
161
+ await execCmd( `setx PATH "%PATH%;${mvnPath}"` );
162
+ logger.info(`✅ 成功!Maven路径【${mvnPath}】已添加到系统PATH环境变量`);
163
+ } catch (err) {
164
+ console.error('❌ 添加失败:', err.message);
165
+ }
166
+
167
+ logger.info(`maven 安装完成`);
168
+ }
169
+
170
+ logger.info(`初始化node环境`);
171
+ await execCmd('npm install -g pnpm typescript --registry=https://registry.npmmirror.com');
172
+ logger.info(`初始化node环境完成`);
173
+
174
+ logger.info(`检测code是否存在`)
175
+ const codeDir = `${dir}/yds-1.0.3`;
176
+ if (!fs.existsSync(codeDir)) {
177
+ const codeZipName = 'yds-1.0.3-jdk-8-windows-x86_64.zip'
178
+ logger.info(`下载code IDE 安装包 ${codeZipName}`);
179
+ const codeZipFile = `${dir}/${codeZipName}`;
180
+ // 检查是否已经存在安装包 如果有先删除
181
+ if (fs.existsSync(codeZipFile)) {
182
+ logger.info(`删除已存在安装包 ${codeZipFile}`);
183
+ fs.rmSync(codeZipFile);
184
+ }
185
+ // 下载安装包并输出日志
186
+ await execCmd(`${wget} https://yoncommunity.yonyoucloud.com/YDSDownload/Window/x64/${codeZipName} -O "${codeZipFile}"`);
187
+ logger.info(`解压安装包 ${codeZipFile}`)
188
+ fs.mkdirSync(codeDir, { recursive: true });
189
+ await execCmd(`"${unzip}" "${codeZipFile}" -d "${codeDir}"`);
190
+ fs.rmSync(codeZipFile)
191
+ await new Promise((resolve) => setTimeout(resolve, 5000))
192
+ logger.info(`code IDE 安装完成`);
193
+ }
194
+ logger.info(`初始化YDS IDE 全局配置`)
195
+ const settingsJson = `${codeDir}/Code/data/user-data/User/settings.json`;
196
+ let settingsJsonObj = {};
197
+ if (fs.existsSync(settingsJson)) {
198
+ settingsJsonObj = JSON.parse(fs.readFileSync(settingsJson).toString('utf-8'));
199
+ }
200
+ let settingXml = path.resolve(`${mavenHome}/conf/settings.xml`);
201
+ if (!fs.existsSync(settingXml) && !fs.existsSync(`${dir}/settings.xml`)) {
202
+ await execCmd(`${wget} ${RS_URL}/settings.xml`);
203
+ settingXml = path.resolve(`${dir}/settings.xml`)
204
+ }
205
+ settingsJsonObj["java.configuration.maven.globalSettings"] = settingXml;
206
+ settingsJsonObj["java.configuration.maven.userSettings"] = settingXml;
207
+ settingsJsonObj["maven.settingsFile"] = settingXml;
208
+ fs.writeFileSync(settingsJson, JSON.stringify(settingsJsonObj, null, 4));
209
+ logger.info(`初始化YDS IDE 全局配置完成`);
210
+
211
+ // 检查当前用户目录下.ssh是否存在 id_ed25519.pub 密钥文件,如果没有则放到.ssh 目录下
212
+ const sshDir = path.resolve(process.env.USERPROFILE, '.ssh');
213
+ if (!fs.existsSync(sshDir)) {
214
+ fs.mkdirSync(sshDir);
215
+ }
216
+ if (!fs.existsSync(`${sshDir}/id_ed25519.pub`)) {
217
+ logger.info(`拷贝密钥文件`);
218
+ fs.copyFileSync(`${dir}/id_ed25519.pub`, `${sshDir}/id_ed25519.pub`);
219
+ fs.copyFileSync(`${dir}/id_ed25519`, `${sshDir}/id_ed25519`);
220
+ logger.info(`拷贝密钥文件完成`);
221
+ }
222
+
223
+ logger.info(`初始化YDS制盘环境完成`)
224
+ }).hook('postAction', () => process.exit(0));
225
+
226
+ program
227
+ .command('start <catalog> [workdir]')
228
+ .usage('start <catalog> [workdir]')
229
+ .option('-f, --file <file>', '配置文件')
230
+ .addHelpText('after', `
231
+ 配置文件内容示例:
232
+ {
233
+ hosts?: Array<string>;
234
+ git: Record<'hrcpe' | 'fecode', string>;
235
+ catalogs: {
236
+ [catalog: string]: Record<'hrcpe' | 'fecode', string | { url: string, branch: string }>
237
+ }
238
+ }`)
239
+ .description('启动制盘环境,catalog表示需要制盘的模块,对应配置文件中catalogs的key值,用于指定需要出盘的信息,workdir表示制盘工作目录,如果不指定则使用当前目录')
240
+ .action(async (catalog: string, workdir: string = path.resolve(process.cwd()), options: { file: string }) => {
241
+ const dir = path.resolve(workdir);
242
+
243
+ logger.info(`开始检测制盘环境检测`);
244
+ let gitCmd = 'git';
245
+ const gitExists = await util.cmd.exists(gitCmd);
246
+ if (!gitExists) {
247
+ gitCmd = `${dir}/git-for-windows/bin/git.exe`;
248
+ if (!fs.existsSync(gitCmd)) {
249
+ logger.error(`未找到git命令 ${gitCmd}, 请先执行 init 初始化制盘环境`);
250
+ process.exit(1)
251
+ }
252
+ }
253
+
254
+ let settingXml = path.resolve(`${dir}/settings.xml`);
255
+ let mvnCmd = 'mvn';
256
+ if (!fs.existsSync(settingXml)) {
257
+ let mavenHome = `${dir}/maven-3.8.6`;
258
+ mvnCmd = `"${mavenHome}/bin/mvn.cmd"`;
259
+ settingXml = `${mavenHome}/conf/settings.xml`;
260
+ if (!fs.existsSync(mvnCmd)) {
261
+ logger.error(`未找到mvn命令 ${mvnCmd}, 请先执行 init 初始化制盘环境`);
262
+ process.exit(1)
263
+ }
264
+ }
265
+
266
+ let idePath = `${dir}/yds-1.0.3`
267
+ if (!fs.existsSync(idePath)) {
268
+ logger.error(`未找到IDE ${idePath}, 请先执行 init 初始化制盘环境`);
269
+ process.exit(1)
270
+ }
271
+
272
+ logger.info(`制盘环境检测完成`)
273
+
274
+ const ydsJson = path.resolve(options.file || `${dir}/yds.json`);
275
+ logger.info(`开始制盘 ${catalog} 工作目录:${dir}`);
276
+ // 读取配置文件
277
+ if (!fs.existsSync(ydsJson)) {
278
+ logger.error(`未找到配置文件 ${ydsJson}`);
279
+ process.exit(1);
280
+ }
281
+ const ydsJsonStr = fs.readFileSync(ydsJson).toString('utf-8');
282
+ // 检测配置文件是否完整
283
+ let config: YdsConfig;
284
+ const checkConfigError = () => {
285
+ logger.error(`配置文件 ${ydsJson} 格式错误 参考示例:
286
+ {
287
+ hosts?: Array<string>;
288
+ git: Record<'hrcpe' | 'fecode', string>;
289
+ catalogs: {
290
+ [catalog: string]: Record<'hrcpe' | 'fecode', string | { url: string, branch: string }>
291
+ }
292
+ }`);
293
+ process.exit(1);
294
+ }
295
+ try {
296
+ config = JSON.parse(ydsJsonStr);
297
+ if (!config.catalogs) {
298
+ checkConfigError()
299
+ }
300
+ } catch (e) {
301
+ checkConfigError()
302
+ }
303
+ const git = config.git;
304
+ const catalogConfig = config.catalogs[catalog];
305
+ if (typeof catalogConfig === 'undefined') {
306
+ logger.error(`配置文件 ${ydsJson} 找不到 catalogs.${catalog} 先关配置`);
307
+ process.exit(1);
308
+ }
309
+ if (typeof catalogConfig.hrcpe === 'undefined' || typeof catalogConfig.fecode === 'undefined') {
310
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog}.hrcpe 或 catalogs.${catalog}.fecode 字段缺失`);
311
+ process.exit(1);
312
+ }
313
+
314
+ const namespace = `${dir}/${catalog}`;
315
+ if (!fs.existsSync(namespace)) {
316
+ logger.info(`创建目录 ${namespace}`);
317
+ fs.mkdirSync(namespace);
318
+ } else {
319
+ logger.info(`目录 ${namespace} 已存在`);
320
+ }
321
+ let hrcpeUrl = typeof catalogConfig.hrcpe === 'string' ? git?.hrcpe : catalogConfig.hrcpe.url;
322
+ if (!hrcpeUrl) {
323
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog} 后端服务 未指定仓库地址,请通过 git.hrcpe 或者 catalogs.${catalog}.hrcpe.url 指定仓库地址`);
324
+ }
325
+ logger.info(`开始拉取后端服务仓库 ${hrcpeUrl}`);
326
+ if (fs.existsSync(`${namespace}/.git`)) {
327
+ logger.info(`目录 ${namespace} 已存在,开始更新仓库`);
328
+ await execCmd(`"${gitCmd}" pull`, namespace);
329
+ } else {
330
+ logger.info(`目录 ${namespace} 不存在,开始创建仓库`);
331
+ let branch = typeof catalogConfig.hrcpe === 'string' ? catalogConfig.hrcpe : catalogConfig.hrcpe.branch;
332
+ if (!branch) {
333
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog} 后端服务 未指定分支,请通过 git.hrcpe 或者 catalogs.${catalog}.hrcpe.branch 配置分支`);
334
+ process.exit(1);
335
+ }
336
+ await execCmd(`"${gitCmd}" clone -b ${branch} ${hrcpeUrl} ${namespace}`, namespace);
337
+ }
338
+ logger.info(`拉取后端服务仓库完成`);
339
+ let boostrapPomXml = `${namespace}/${domainKey}-be/dev-${domainKey}-bootstrap/pom.xml`;
340
+ logger.info(`替换文件 ${boostrapPomXml} 中的ROOT为domainKey,否则会导致制盘失败,无法找到制品`);
341
+ const boostrapPomXmlString = fs.readFileSync(boostrapPomXml).toString('utf-8');
342
+ if (boostrapPomXmlString.includes('ROOT')) {
343
+ fs.writeFileSync(boostrapPomXml, boostrapPomXmlString.replace(/ROOT/g, domainKey));
344
+ }
345
+
346
+ if (config.hosts && config.hosts.length) {
347
+ logger.info(`存在hosts配置,检测系统hosts配置文件是否已经配置`);
348
+ let hostsFile = path.resolve(process.env.WINDIR, 'System32', 'drivers', 'etc', 'hosts');
349
+ const hostList = fs.readFileSync(hostsFile).toString('utf-8').split('\n');
350
+ let appendHosts = [...config.hosts]
351
+ for (let hostItem of hostList) {
352
+ if (/#/.test(hostItem)) {
353
+ continue;
354
+ }
355
+ for (let appendHost of config.hosts) {
356
+ const [ip, domain] = appendHost.split(' ').filter(item => item)
357
+ if (hostItem.includes(ip) && hostItem.includes(domain)) {
358
+ logger.info(`系统hosts配置文件已存在 ${appendHost}`);
359
+ appendHosts.remove(appendHost);
360
+ }
361
+ }
362
+ }
363
+ // 读取系统hosts配置文件
364
+ if (appendHosts.length) {
365
+ if (isAdmin()) {
366
+ fs.appendFileSync(hostsFile, `\n${appendHosts.join('\n')}\n`, {
367
+ encoding: 'utf-8'
368
+ })
369
+ } else {
370
+ logger.error(`当前非管理员启动无法更改hosts文件,请使用管理员启动或者手动添加 ${appendHosts.join('\n')} 到文件 ${hostsFile}`);
371
+ }
372
+ }
373
+ logger.info(`hosts 配置检测完成`);
374
+ }
375
+
376
+ logger.info('初始化项目maven环境');
377
+ let mvnConfigDir = `${namespace}/.mvn`;
378
+ if (!fs.existsSync(mvnConfigDir)) {
379
+ await execCmd(`${mvnCmd} -N io.takari:maven:wrapper -Dmaven=3.8.6`, namespace);
380
+ }
381
+ // 写入maven配置到 .mvn/maven.config
382
+ let configFile = `${mvnConfigDir}/maven.config`;
383
+ if (fs.existsSync(configFile)) {
384
+ fs.rmSync(configFile)
385
+ }
386
+ fs.writeFileSync(`${mvnConfigDir}/maven.config`, `-s\n${settingXml}\n-Dmaven.wagon.http.ssl.insecure=true\n-Dmaven.wagon.http.ssl.allowall=true`);
387
+ logger.info(`当前maven信息`)
388
+ await execCmd(`${mvnCmd} --version`, namespace);
389
+
390
+ logger.info('项目maven清理')
391
+ await execCmd(`${mvnCmd} clean -DskipTests`, `${namespace}/${domainKey}-be`);
392
+
393
+ logger.info('处理前端构建,增加构建文件');
394
+ let feDir = `${namespace}/${domainKey}-fe`;
395
+ let feBuildJs = `${feDir}/build.js`;
396
+ if (!fs.existsSync(feBuildJs)) {
397
+ fs.cpSync(`${dir}/fe-build.js`, feBuildJs);
398
+ }
399
+ let fePackageJson = `${feDir}/package.json`;
400
+ const packageString = fs.readFileSync(fePackageJson).toString('utf-8');
401
+ if (!packageString.includes('build.js')) {
402
+ logger.info(`修改${fePackageJson}`);
403
+ const packageJson = JSON.parse(packageString);
404
+ packageJson.scripts['build:extend'] += ' && node build.js';
405
+ fs.writeFileSync(fePackageJson, JSON.stringify(packageJson, null, 4));
406
+ logger.info(`修改${fePackageJson}完成`);
407
+ }
408
+
409
+
410
+ let fecodeUrl = typeof catalogConfig.fecode === 'string' ? git?.fecode : catalogConfig.fecode.url;
411
+ if (!fecodeUrl) {
412
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog} 后端服务 未指定仓库地址,请通过 git.fecode 或者 catalogs.${catalog}.fecode.url 指定仓库地址`);
413
+ }
414
+ logger.info(`开始拉取报告服务仓库 ${fecodeUrl}`);
415
+ let reportNamespace = `${namespace}/yonbip-yisv-izp1-dev-fecode`;
416
+ if (fs.existsSync(`${reportNamespace}/.git`)) {
417
+ logger.info(`目录 ${reportNamespace} 已存在,开始更新仓库`);
418
+ await execCmd(`"${gitCmd}" pull`, reportNamespace);
419
+ } else {
420
+ logger.info(`目录 ${reportNamespace} 不存在,开始创建仓库`);
421
+ let branch = typeof catalogConfig.fecode === 'string' ? catalogConfig.fecode : catalogConfig.fecode.branch;
422
+ if (!branch) {
423
+ logger.error(`配置文件 ${ydsJson} catalogs.${catalog} 报告服务未指定分支,请通过 git.fecode 或者 catalogs.${catalog}.fecode.branch 配置分支`);
424
+ process.exit(1);
425
+ }
426
+ await execCmd(`"${gitCmd}" clone -b ${branch} ${fecodeUrl} ${reportNamespace}`);
427
+ }
428
+ logger.info(`拉取报告服务仓库完成`);
429
+
430
+ logger.info('处理报告构建,增加构建文件');
431
+ let fecodeBuildJs = `${reportNamespace}/build.js`;
432
+ if (!fs.existsSync(fecodeBuildJs)) {
433
+ fs.cpSync(`${dir}/fecode-build.js`, fecodeBuildJs);
434
+ }
435
+ let fecodePackageJson = `${reportNamespace}/package.json`;
436
+ const fecodePackageString = fs.readFileSync(fecodePackageJson).toString('utf-8');
437
+ if (!fecodePackageString.includes('build.js')) {
438
+ logger.info(`修改${fecodePackageJson}`);
439
+ const packageJson = JSON.parse(fecodePackageString);
440
+ packageJson.scripts['build'] += ' && node build.js';
441
+ packageJson.domainKey = domainKey;
442
+ // 删除此依赖 会导致npm i 失败
443
+ delete packageJson.dependencies.zlib
444
+ fs.writeFileSync(fecodePackageJson, JSON.stringify(packageJson, null, 4));
445
+ logger.info(`修改${fecodePackageJson}完成`);
446
+ }
447
+
448
+ logger.info(`安装报告服务依赖`);
449
+ await execCmd('npm i', reportNamespace);
450
+
451
+ logger.info(`生成version.json 文件`)
452
+ const uuid = randomUUID().toString()
453
+ fs.writeFileSync(`${reportNamespace}/version.json`, `{"version": "${uuid}"}`);
454
+
455
+ logger.info('初始化项目环境资源');
456
+ // 如果 namespace/(disk|disks) 如果存在 跳过
457
+ if (fs.existsSync(`${namespace}/disk`) || fs.existsSync(`${namespace}/disks`)) {
458
+ logger.info(`已存在,跳过环境资源文件下载`);
459
+ } else {
460
+ // https://dfs.zhiper.com/v3r6/env.zip
461
+ logger.info(`开始下载项目环境资源文件`)
462
+ let gitZipFile = `${namespace}/env.zip`;
463
+ await execCmd(`${wget} ${RS_URL}/env.zip -O "${gitZipFile}"`);
464
+
465
+ logger.info(`解压资源文件包 ${gitZipFile}`)
466
+ await execCmd(`"${unzip}" "${gitZipFile}"`, namespace);
467
+ fs.rmSync(gitZipFile)
468
+ }
469
+
470
+ logger.info('启动IDE');
471
+ await execCmd(`"${idePath}/Code/Code.exe" "${namespace}"`);
472
+ // 需要等待IDE启动完成后关闭
473
+ await new Promise(resolve => setTimeout(resolve, 3000))
474
+ logger.info('已启动IDE,请按照文档说明进行制盘操作')
475
+ }).hook('postAction', () => process.exit(0))
476
+
477
+ program.parse(process.argv)
478
+ }
479
+ }