sonamu 0.7.34 → 0.7.35

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.
@@ -1,30 +1,21 @@
1
+ export type BuildArtifact<BuildCommandArgs = {}> = {
2
+ name: string;
3
+ description: string;
4
+ projectPath: string;
5
+ preBuildCommand?: () => string;
6
+ buildCommand: (args: BuildCommandArgs) => string;
7
+ postBuildCommand?: () => string;
8
+ };
1
9
  /**
2
10
  * API 프로젝트 빌드 산출물에 대한 규칙들.
3
11
  * cli.ts의 build 함수가 이것을 보고 그대로 실행합니다.
4
- *
5
- * 경로(projectPath, outputDir, destDir)는 app root에서 시작하는 상대경로로 작성되어 있습니다.
6
- * 다만 buildCommand는 projectPath를 기준으로 실행됩니다.
7
12
  */
8
- export declare const API_ARTIFACTS: {
9
- name: string;
10
- description: string;
11
- projectPath: string;
12
- buildCommand: (configFilePath: string) => string;
13
- outputDir: string;
14
- }[];
13
+ export declare const API_ARTIFACTS: BuildArtifact<{
14
+ configFilePath: string;
15
+ }>[];
15
16
  /**
16
17
  * 웹 프로젝트 빌드 산출물에 대한 규칙들.
17
18
  * cli.ts의 build 함수가 이것을 보고 그대로 실행합니다.
18
- *
19
- * 경로(projectPath, outputDir, destDir)는 app root에서 시작하는 상대경로로 작성되어 있습니다.
20
- * 다만 buildCommand는 projectPath를 기준(cwd)으로 실행됩니다.
21
19
  */
22
- export declare const WEB_ARTIFACTS: {
23
- name: string;
24
- description: string;
25
- projectPath: string;
26
- buildCommand: () => string;
27
- outputDir: string;
28
- destDir: string;
29
- }[];
20
+ export declare const WEB_ARTIFACTS: BuildArtifact[];
30
21
  //# sourceMappingURL=build-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-config.d.ts","sourceRoot":"","sources":["../../src/bin/build-config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;;;;mCAKS,MAAM;;GAIxC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;;;;;;;GAiBzB,CAAC"}
1
+ {"version":3,"file":"build-config.d.ts","sourceRoot":"","sources":["../../src/bin/build-config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,CAAC,gBAAgB,GAAG,EAAE,IAAI;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B,YAAY,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,MAAM,CAAC;IACjD,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;CACjC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,EASpE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,aAAa,EAkBxC,CAAC"}
@@ -1,41 +1,35 @@
1
1
  /**
2
2
  * API 프로젝트 빌드 산출물에 대한 규칙들.
3
3
  * cli.ts의 build 함수가 이것을 보고 그대로 실행합니다.
4
- *
5
- * 경로(projectPath, outputDir, destDir)는 app root에서 시작하는 상대경로로 작성되어 있습니다.
6
- * 다만 buildCommand는 projectPath를 기준으로 실행됩니다.
7
4
  */ export const API_ARTIFACTS = [
8
5
  {
9
6
  name: "API",
10
7
  description: "API 프로젝트 빌드 산출물",
11
8
  projectPath: "api",
12
- buildCommand: (configFilePath)=>`tsc --noEmit && swc src -d dist --config-file ${configFilePath} --strip-leading-paths`,
13
- outputDir: "api/dist"
9
+ preBuildCommand: ()=>"rm -rf dist",
10
+ buildCommand: ({ configFilePath })=>`tsc --noEmit && swc src -d dist --config-file ${configFilePath} --strip-leading-paths`
14
11
  }
15
12
  ];
16
13
  /**
17
14
  * 웹 프로젝트 빌드 산출물에 대한 규칙들.
18
15
  * cli.ts의 build 함수가 이것을 보고 그대로 실행합니다.
19
- *
20
- * 경로(projectPath, outputDir, destDir)는 app root에서 시작하는 상대경로로 작성되어 있습니다.
21
- * 다만 buildCommand는 projectPath를 기준(cwd)으로 실행됩니다.
22
16
  */ export const WEB_ARTIFACTS = [
23
17
  {
24
18
  name: "Web Client",
25
19
  description: "Web 프로젝트 클라이언트 빌드 산출물",
26
20
  projectPath: "web",
27
- buildCommand: ()=>"tsc && vite build --outDir dist/client",
28
- outputDir: "web/dist/client",
29
- destDir: "api/public/web"
21
+ preBuildCommand: ()=>"rm -rf dist/client && rm -rf ../api/public/web",
22
+ buildCommand: ()=>"tsc --noEmit && vite build --outDir dist/client",
23
+ postBuildCommand: ()=>"mkdir -p ../api/public/web && cp -r dist/client/* ../api/public/web"
30
24
  },
31
25
  {
32
26
  name: "Web Server",
33
27
  description: "Web 프로젝트 서버 빌드 산출물",
34
28
  projectPath: "web",
35
- buildCommand: ()=>"vite build --ssr src/entry-server.generated.tsx --outDir dist/server",
36
- outputDir: "web/dist/server",
37
- destDir: "api/dist/ssr"
29
+ preBuildCommand: ()=>"rm -rf dist/server",
30
+ buildCommand: ()=>"tsc --noEmit && vite build --ssr src/entry-server.generated.tsx --outDir dist/server",
31
+ postBuildCommand: ()=>"cp -r dist/server/* ../api/dist/ssr"
38
32
  }
39
33
  ];
40
34
 
41
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iaW4vYnVpbGQtY29uZmlnLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQVBJIO2UhOuhnOygne2KuCDruYzrk5wg7IKw7Lac66y87JeQIOuMgO2VnCDqt5zsuZnrk6QuXG4gKiBjbGkudHPsnZggYnVpbGQg7ZWo7IiY6rCAIOydtOqyg+ydhCDrs7Tqs6Ag6re464yA66GcIOyLpO2Wie2VqeuLiOuLpC5cbiAqXG4gKiDqsr3roZwocHJvamVjdFBhdGgsIG91dHB1dERpciwgZGVzdERpcinripQgYXBwIHJvb3Tsl5DshJwg7Iuc7J6R7ZWY64qUIOyDgeuMgOqyveuhnOuhnCDsnpHshLHrkJjslrQg7J6I7Iq164uI64ukLlxuICog64uk66eMIGJ1aWxkQ29tbWFuZOuKlCBwcm9qZWN0UGF0aOulvCDquLDspIDsnLzroZwg7Iuk7ZaJ65Cp64uI64ukLlxuICovXG5leHBvcnQgY29uc3QgQVBJX0FSVElGQUNUUyA9IFtcbiAge1xuICAgIG5hbWU6IFwiQVBJXCIsXG4gICAgZGVzY3JpcHRpb246IFwiQVBJIO2UhOuhnOygne2KuCDruYzrk5wg7IKw7Lac66y8XCIsXG4gICAgcHJvamVjdFBhdGg6IFwiYXBpXCIsXG4gICAgYnVpbGRDb21tYW5kOiAoY29uZmlnRmlsZVBhdGg6IHN0cmluZykgPT5cbiAgICAgIGB0c2MgLS1ub0VtaXQgJiYgc3djIHNyYyAtZCBkaXN0IC0tY29uZmlnLWZpbGUgJHtjb25maWdGaWxlUGF0aH0gLS1zdHJpcC1sZWFkaW5nLXBhdGhzYCxcbiAgICBvdXRwdXREaXI6IFwiYXBpL2Rpc3RcIixcbiAgfSxcbl07XG5cbi8qKlxuICog7Ju5IO2UhOuhnOygne2KuCDruYzrk5wg7IKw7Lac66y87JeQIOuMgO2VnCDqt5zsuZnrk6QuXG4gKiBjbGkudHPsnZggYnVpbGQg7ZWo7IiY6rCAIOydtOqyg+ydhCDrs7Tqs6Ag6re464yA66GcIOyLpO2Wie2VqeuLiOuLpC5cbiAqXG4gKiDqsr3roZwocHJvamVjdFBhdGgsIG91dHB1dERpciwgZGVzdERpcinripQgYXBwIHJvb3Tsl5DshJwg7Iuc7J6R7ZWY64qUIOyDgeuMgOqyveuhnOuhnCDsnpHshLHrkJjslrQg7J6I7Iq164uI64ukLlxuICog64uk66eMIGJ1aWxkQ29tbWFuZOuKlCBwcm9qZWN0UGF0aOulvCDquLDspIAoY3dkKeycvOuhnCDsi6TtlonrkKnri4jri6QuXG4gKi9cbmV4cG9ydCBjb25zdCBXRUJfQVJUSUZBQ1RTID0gW1xuICB7XG4gICAgbmFtZTogXCJXZWIgQ2xpZW50XCIsXG4gICAgZGVzY3JpcHRpb246IFwiV2ViIO2UhOuhnOygne2KuCDtgbTrnbzsnbTslrjtirgg67mM65OcIOyCsOy2nOusvFwiLFxuICAgIHByb2plY3RQYXRoOiBcIndlYlwiLFxuICAgIGJ1aWxkQ29tbWFuZDogKCkgPT4gXCJ0c2MgJiYgdml0ZSBidWlsZCAtLW91dERpciBkaXN0L2NsaWVudFwiLFxuICAgIG91dHB1dERpcjogXCJ3ZWIvZGlzdC9jbGllbnRcIixcbiAgICBkZXN0RGlyOiBcImFwaS9wdWJsaWMvd2ViXCIsXG4gIH0sXG4gIHtcbiAgICBuYW1lOiBcIldlYiBTZXJ2ZXJcIixcbiAgICBkZXNjcmlwdGlvbjogXCJXZWIg7ZSE66Gc7KCd7Yq4IOyEnOuyhCDruYzrk5wg7IKw7Lac66y8XCIsXG4gICAgcHJvamVjdFBhdGg6IFwid2ViXCIsXG4gICAgYnVpbGRDb21tYW5kOiAoKSA9PiBcInZpdGUgYnVpbGQgLS1zc3Igc3JjL2VudHJ5LXNlcnZlci5nZW5lcmF0ZWQudHN4IC0tb3V0RGlyIGRpc3Qvc2VydmVyXCIsXG4gICAgb3V0cHV0RGlyOiBcIndlYi9kaXN0L3NlcnZlclwiLFxuICAgIGRlc3REaXI6IFwiYXBpL2Rpc3Qvc3NyXCIsXG4gIH0sXG5dO1xuIl0sIm5hbWVzIjpbIkFQSV9BUlRJRkFDVFMiLCJuYW1lIiwiZGVzY3JpcHRpb24iLCJwcm9qZWN0UGF0aCIsImJ1aWxkQ29tbWFuZCIsImNvbmZpZ0ZpbGVQYXRoIiwib3V0cHV0RGlyIiwiV0VCX0FSVElGQUNUUyIsImRlc3REaXIiXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Q0FNQyxHQUNELE9BQU8sTUFBTUEsZ0JBQWdCO0lBQzNCO1FBQ0VDLE1BQU07UUFDTkMsYUFBYTtRQUNiQyxhQUFhO1FBQ2JDLGNBQWMsQ0FBQ0MsaUJBQ2IsQ0FBQyw4Q0FBOEMsRUFBRUEsZUFBZSxzQkFBc0IsQ0FBQztRQUN6RkMsV0FBVztJQUNiO0NBQ0QsQ0FBQztBQUVGOzs7Ozs7Q0FNQyxHQUNELE9BQU8sTUFBTUMsZ0JBQWdCO0lBQzNCO1FBQ0VOLE1BQU07UUFDTkMsYUFBYTtRQUNiQyxhQUFhO1FBQ2JDLGNBQWMsSUFBTTtRQUNwQkUsV0FBVztRQUNYRSxTQUFTO0lBQ1g7SUFDQTtRQUNFUCxNQUFNO1FBQ05DLGFBQWE7UUFDYkMsYUFBYTtRQUNiQyxjQUFjLElBQU07UUFDcEJFLFdBQVc7UUFDWEUsU0FBUztJQUNYO0NBQ0QsQ0FBQyJ9
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iaW4vYnVpbGQtY29uZmlnLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB0eXBlIEJ1aWxkQXJ0aWZhY3Q8QnVpbGRDb21tYW5kQXJncyA9IHt9PiA9IHtcbiAgbmFtZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICBwcm9qZWN0UGF0aDogc3RyaW5nO1xuICBwcmVCdWlsZENvbW1hbmQ/OiAoKSA9PiBzdHJpbmc7XG4gIGJ1aWxkQ29tbWFuZDogKGFyZ3M6IEJ1aWxkQ29tbWFuZEFyZ3MpID0+IHN0cmluZztcbiAgcG9zdEJ1aWxkQ29tbWFuZD86ICgpID0+IHN0cmluZztcbn07XG5cbi8qKlxuICogQVBJIO2UhOuhnOygne2KuCDruYzrk5wg7IKw7Lac66y87JeQIOuMgO2VnCDqt5zsuZnrk6QuXG4gKiBjbGkudHPsnZggYnVpbGQg7ZWo7IiY6rCAIOydtOqyg+ydhCDrs7Tqs6Ag6re464yA66GcIOyLpO2Wie2VqeuLiOuLpC5cbiAqL1xuZXhwb3J0IGNvbnN0IEFQSV9BUlRJRkFDVFM6IEJ1aWxkQXJ0aWZhY3Q8eyBjb25maWdGaWxlUGF0aDogc3RyaW5nIH0+W10gPSBbXG4gIHtcbiAgICBuYW1lOiBcIkFQSVwiLFxuICAgIGRlc2NyaXB0aW9uOiBcIkFQSSDtlITroZzsoJ3tirgg67mM65OcIOyCsOy2nOusvFwiLFxuICAgIHByb2plY3RQYXRoOiBcImFwaVwiLFxuICAgIHByZUJ1aWxkQ29tbWFuZDogKCkgPT4gXCJybSAtcmYgZGlzdFwiLFxuICAgIGJ1aWxkQ29tbWFuZDogKHsgY29uZmlnRmlsZVBhdGggfSkgPT5cbiAgICAgIGB0c2MgLS1ub0VtaXQgJiYgc3djIHNyYyAtZCBkaXN0IC0tY29uZmlnLWZpbGUgJHtjb25maWdGaWxlUGF0aH0gLS1zdHJpcC1sZWFkaW5nLXBhdGhzYCxcbiAgfSxcbl07XG5cbi8qKlxuICog7Ju5IO2UhOuhnOygne2KuCDruYzrk5wg7IKw7Lac66y87JeQIOuMgO2VnCDqt5zsuZnrk6QuXG4gKiBjbGkudHPsnZggYnVpbGQg7ZWo7IiY6rCAIOydtOqyg+ydhCDrs7Tqs6Ag6re464yA66GcIOyLpO2Wie2VqeuLiOuLpC5cbiAqL1xuZXhwb3J0IGNvbnN0IFdFQl9BUlRJRkFDVFM6IEJ1aWxkQXJ0aWZhY3RbXSA9IFtcbiAge1xuICAgIG5hbWU6IFwiV2ViIENsaWVudFwiLFxuICAgIGRlc2NyaXB0aW9uOiBcIldlYiDtlITroZzsoJ3tirgg7YG065287J207Ja47Yq4IOu5jOuTnCDsgrDstpzrrLxcIixcbiAgICBwcm9qZWN0UGF0aDogXCJ3ZWJcIixcbiAgICBwcmVCdWlsZENvbW1hbmQ6ICgpID0+IFwicm0gLXJmIGRpc3QvY2xpZW50ICYmIHJtIC1yZiAuLi9hcGkvcHVibGljL3dlYlwiLFxuICAgIGJ1aWxkQ29tbWFuZDogKCkgPT4gXCJ0c2MgLS1ub0VtaXQgJiYgdml0ZSBidWlsZCAtLW91dERpciBkaXN0L2NsaWVudFwiLFxuICAgIHBvc3RCdWlsZENvbW1hbmQ6ICgpID0+IFwibWtkaXIgLXAgLi4vYXBpL3B1YmxpYy93ZWIgJiYgY3AgLXIgZGlzdC9jbGllbnQvKiAuLi9hcGkvcHVibGljL3dlYlwiLFxuICB9LFxuICB7XG4gICAgbmFtZTogXCJXZWIgU2VydmVyXCIsXG4gICAgZGVzY3JpcHRpb246IFwiV2ViIO2UhOuhnOygne2KuCDshJzrsoQg67mM65OcIOyCsOy2nOusvFwiLFxuICAgIHByb2plY3RQYXRoOiBcIndlYlwiLFxuICAgIHByZUJ1aWxkQ29tbWFuZDogKCkgPT4gXCJybSAtcmYgZGlzdC9zZXJ2ZXJcIiwgLy8gYXBpL2Rpc3Qvc3Ny7J2AIOyViCDsp4Dsm4Hri4jri6QhIOqxsOq4sOuKlCBhcGnsnZgg67mM65OcIOqysOqzvOusvOydtCDrk6TslrTsnojsnYwhXG4gICAgYnVpbGRDb21tYW5kOiAoKSA9PlxuICAgICAgXCJ0c2MgLS1ub0VtaXQgJiYgdml0ZSBidWlsZCAtLXNzciBzcmMvZW50cnktc2VydmVyLmdlbmVyYXRlZC50c3ggLS1vdXREaXIgZGlzdC9zZXJ2ZXJcIixcbiAgICBwb3N0QnVpbGRDb21tYW5kOiAoKSA9PiBcImNwIC1yIGRpc3Qvc2VydmVyLyogLi4vYXBpL2Rpc3Qvc3NyXCIsXG4gIH0sXG5dO1xuIl0sIm5hbWVzIjpbIkFQSV9BUlRJRkFDVFMiLCJuYW1lIiwiZGVzY3JpcHRpb24iLCJwcm9qZWN0UGF0aCIsInByZUJ1aWxkQ29tbWFuZCIsImJ1aWxkQ29tbWFuZCIsImNvbmZpZ0ZpbGVQYXRoIiwiV0VCX0FSVElGQUNUUyIsInBvc3RCdWlsZENvbW1hbmQiXSwibWFwcGluZ3MiOiJBQVNBOzs7Q0FHQyxHQUNELE9BQU8sTUFBTUEsZ0JBQTZEO0lBQ3hFO1FBQ0VDLE1BQU07UUFDTkMsYUFBYTtRQUNiQyxhQUFhO1FBQ2JDLGlCQUFpQixJQUFNO1FBQ3ZCQyxjQUFjLENBQUMsRUFBRUMsY0FBYyxFQUFFLEdBQy9CLENBQUMsOENBQThDLEVBQUVBLGVBQWUsc0JBQXNCLENBQUM7SUFDM0Y7Q0FDRCxDQUFDO0FBRUY7OztDQUdDLEdBQ0QsT0FBTyxNQUFNQyxnQkFBaUM7SUFDNUM7UUFDRU4sTUFBTTtRQUNOQyxhQUFhO1FBQ2JDLGFBQWE7UUFDYkMsaUJBQWlCLElBQU07UUFDdkJDLGNBQWMsSUFBTTtRQUNwQkcsa0JBQWtCLElBQU07SUFDMUI7SUFDQTtRQUNFUCxNQUFNO1FBQ05DLGFBQWE7UUFDYkMsYUFBYTtRQUNiQyxpQkFBaUIsSUFBTTtRQUN2QkMsY0FBYyxJQUNaO1FBQ0ZHLGtCQUFrQixJQUFNO0lBQzFCO0NBQ0QsQ0FBQyJ9
package/dist/bin/cli.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import chalk from "chalk";
2
2
  import dotenv from "dotenv";
3
3
  dotenv.config();
4
+ import assert from "assert";
4
5
  import { execSync, spawn } from "child_process";
5
- import { cp, mkdir, readdir, rm, writeFile } from "node:fs/promises";
6
+ import { mkdir, readdir, writeFile } from "node:fs/promises";
6
7
  import knex from "knex";
7
8
  import { createRequire } from "module";
8
9
  import path from "path";
@@ -12,7 +13,7 @@ import { Sonamu } from "../api/index.js";
12
13
  import { EntityManager } from "../entity/entity-manager.js";
13
14
  import { Migrator } from "../migration/migrator.js";
14
15
  import { FixtureManager } from "../testing/fixture-manager.js";
15
- import { execWithLinePrefix, printBuildSummary, printTaskFailed, printTaskHeader, printTaskSkipped, printTaskStart, printTaskSuccess } from "../utils/console-util.js";
16
+ import { execWithLinePrefix, printBuildSummary, printTaskFailed, printTaskHeader, printTaskStart, printTaskSuccess } from "../utils/console-util.js";
16
17
  import { exists } from "../utils/fs-utils.js";
17
18
  import { findApiRootPath, findAppRootPath } from "../utils/utils.js";
18
19
  import { API_ARTIFACTS, WEB_ARTIFACTS } from "./build-config.js";
@@ -222,38 +223,6 @@ bootstrap().finally(async ()=>{
222
223
  * Sonamu.init 없이 호출될 것을 상정하여 구현되었습니다.
223
224
  */ async function build() {
224
225
  const appRoot = findAppRootPath();
225
- // 출력 디렉토리를 제거합니다.
226
- try {
227
- for (const artifact of API_ARTIFACTS){
228
- if (await exists(path.join(appRoot, artifact.outputDir))) {
229
- // API 프로젝트 자체의 빌드 결과물
230
- await rm(path.join(appRoot, artifact.outputDir), {
231
- recursive: true,
232
- force: true
233
- });
234
- }
235
- }
236
- for (const artifact of WEB_ARTIFACTS){
237
- if (await exists(path.join(appRoot, artifact.outputDir))) {
238
- // Web 프로젝트 자체의 빌드 결과물
239
- await rm(path.join(appRoot, artifact.outputDir), {
240
- recursive: true,
241
- force: true
242
- });
243
- }
244
- if (await exists(path.join(appRoot, artifact.destDir))) {
245
- // API 프로젝트로 복사되어 온 Web 빌드 결과물
246
- await rm(path.join(appRoot, artifact.destDir), {
247
- recursive: true,
248
- force: true
249
- });
250
- }
251
- }
252
- console.log(chalk.green("\nBuild artifacts removed successfully."));
253
- } catch (error) {
254
- console.error(chalk.red("Remove build directories failed."), error);
255
- process.exit(1);
256
- }
257
226
  // .swcrc 파일을 지정합니다.
258
227
  let swcFilePath = ".swcrc";
259
228
  try {
@@ -274,20 +243,13 @@ bootstrap().finally(async ()=>{
274
243
  try {
275
244
  for (const artifact of API_ARTIFACTS){
276
245
  const cwd = path.join(appRoot, artifact.projectPath);
277
- const cmd = artifact.buildCommand(swcFilePath);
278
246
  printTaskHeader(artifact.name, artifact.description, cwd);
279
- // build
280
- try {
281
- printTaskStart("build", cmd, true);
282
- // cmd를 spawn해서 build를 수행하는데, 이때 명령의 출력(stdout, stderr) 라인 앞에 들여쓰기를 붙여서 출력합니다.
283
- await execWithLinePrefix(cmd, {
284
- cwd
285
- });
286
- printTaskSuccess("build", true);
287
- } catch {
288
- printTaskFailed("build", true);
289
- throw new Error("build failed");
290
- }
247
+ await runBuildSteps(artifact, {
248
+ cwd,
249
+ buildCommandArgs: {
250
+ configFilePath: swcFilePath
251
+ }
252
+ });
291
253
  }
292
254
  printBuildSummary("API", true, Date.now() - apiStartedAt);
293
255
  } catch {
@@ -299,44 +261,11 @@ bootstrap().finally(async ()=>{
299
261
  try {
300
262
  for (const artifact of WEB_ARTIFACTS){
301
263
  const cwd = path.join(appRoot, artifact.projectPath);
302
- const cmd = artifact.buildCommand();
303
- const outputDirFull = path.join(appRoot, artifact.outputDir);
304
- const destDirFull = path.join(appRoot, artifact.destDir);
305
264
  printTaskHeader(artifact.name, artifact.description, cwd);
306
- // build
307
- try {
308
- printTaskStart("build", cmd);
309
- // cmd를 spawn해서 build를 수행하는데, 이때 명령의 출력(stdout, stderr) 라인 앞에 들여쓰기를 붙여서 출력합니다.
310
- await execWithLinePrefix(cmd, {
311
- cwd
312
- });
313
- printTaskSuccess("build");
314
- } catch {
315
- printTaskFailed("build");
316
- printTaskSkipped("copy", true);
317
- throw new Error("build failed");
318
- }
319
- // copy
320
- try {
321
- printTaskStart("copy", `${artifact.outputDir} → ${artifact.destDir}`, true);
322
- // Web 아티팩트는 빌드 결과물(outputDir)을 다른 위치(destDir)로 복사하는 작업이 추가로 필요합니다.
323
- if (await exists(destDirFull)) {
324
- await rm(destDirFull, {
325
- recursive: true,
326
- force: true
327
- });
328
- }
329
- await mkdir(destDirFull, {
330
- recursive: true
331
- });
332
- await cp(outputDirFull, destDirFull, {
333
- recursive: true
334
- });
335
- printTaskSuccess("copy", true);
336
- } catch {
337
- printTaskFailed("copy", true);
338
- throw new Error("copy failed");
339
- }
265
+ await runBuildSteps(artifact, {
266
+ cwd,
267
+ buildCommandArgs: {}
268
+ });
340
269
  }
341
270
  printBuildSummary("Web", true, Date.now() - webStartedAt);
342
271
  } catch {
@@ -344,6 +273,39 @@ bootstrap().finally(async ()=>{
344
273
  process.exit(1);
345
274
  }
346
275
  }
276
+ /**
277
+ * pre-build, build, post-build 단계를 순차적으로 실행합니다.
278
+ */ async function runBuildSteps(artifact, options) {
279
+ const steps = [
280
+ {
281
+ name: "pre-build",
282
+ cmd: artifact.preBuildCommand?.()
283
+ },
284
+ {
285
+ name: "build",
286
+ cmd: artifact.buildCommand(options.buildCommandArgs)
287
+ },
288
+ {
289
+ name: "post-build",
290
+ cmd: artifact.postBuildCommand?.()
291
+ }
292
+ ].filter((step)=>step.cmd);
293
+ for(let i = 0; i < steps.length; i++){
294
+ const step = steps[i];
295
+ const isLast = i === steps.length - 1;
296
+ try {
297
+ assert(step.cmd);
298
+ printTaskStart(step.name, step.cmd, isLast);
299
+ await execWithLinePrefix(step.cmd, {
300
+ cwd: options.cwd
301
+ });
302
+ printTaskSuccess(step.name, isLast);
303
+ } catch {
304
+ printTaskFailed(step.name, isLast);
305
+ throw new Error(`${step.name} failed`);
306
+ }
307
+ }
308
+ }
347
309
  /**
348
310
  * pnpm start 하면 실행되는 함수입니다.
349
311
  * 빌드된 프로젝트를 실행합니다.
@@ -521,4 +483,4 @@ async function scaffold_model_test(entityId) {
521
483
  });
522
484
  }
523
485
 
524
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iaW4vY2xpLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIjtcbmltcG9ydCBkb3RlbnYgZnJvbSBcImRvdGVudlwiO1xuXG5kb3RlbnYuY29uZmlnKCk7XG5cbmltcG9ydCB7IGV4ZWNTeW5jLCBzcGF3biB9IGZyb20gXCJjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgeyBjcCwgbWtkaXIsIHJlYWRkaXIsIHJtLCB3cml0ZUZpbGUgfSBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBrbmV4LCB7IHR5cGUgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSBcIm1vZHVsZVwiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCBwcm9jZXNzIGZyb20gXCJwcm9jZXNzXCI7XG5pbXBvcnQgeyB0c2ljbGkgfSBmcm9tIFwidHNpY2xpXCI7XG5pbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwiLi4vYXBpXCI7XG5pbXBvcnQgdHlwZSB7IFNvbmFtdURCQ29uZmlnIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHsgTWlncmF0b3IgfSBmcm9tIFwiLi4vbWlncmF0aW9uL21pZ3JhdG9yXCI7XG5pbXBvcnQgeyBGaXh0dXJlTWFuYWdlciB9IGZyb20gXCIuLi90ZXN0aW5nL2ZpeHR1cmUtbWFuYWdlclwiO1xuaW1wb3J0IHtcbiAgZXhlY1dpdGhMaW5lUHJlZml4LFxuICBwcmludEJ1aWxkU3VtbWFyeSxcbiAgcHJpbnRUYXNrRmFpbGVkLFxuICBwcmludFRhc2tIZWFkZXIsXG4gIHByaW50VGFza1NraXBwZWQsXG4gIHByaW50VGFza1N0YXJ0LFxuICBwcmludFRhc2tTdWNjZXNzLFxufSBmcm9tIFwiLi4vdXRpbHMvY29uc29sZS11dGlsXCI7XG5pbXBvcnQgeyBleGlzdHMgfSBmcm9tIFwiLi4vdXRpbHMvZnMtdXRpbHNcIjtcbmltcG9ydCB7IGZpbmRBcGlSb290UGF0aCwgZmluZEFwcFJvb3RQYXRoIH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBBUElfQVJUSUZBQ1RTLCBXRUJfQVJUSUZBQ1RTIH0gZnJvbSBcIi4vYnVpbGQtY29uZmlnXCI7XG5cbmxldCBtaWdyYXRvcjogTWlncmF0b3I7XG5cbmFzeW5jIGZ1bmN0aW9uIGJvb3RzdHJhcCgpIHtcbiAgY29uc3Qgbm90VG9Jbml0ID0gW1wiZGV2XCIsIFwiYnVpbGRcIiwgXCJzdGFydFwiXS5pbmNsdWRlcyhwcm9jZXNzLmFyZ3ZbMl0gPz8gXCJcIik7XG4gIGlmICghbm90VG9Jbml0KSB7XG4gICAgYXdhaXQgU29uYW11LmluaXQoZmFsc2UsIGZhbHNlKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgYXdhaXQgdHNpY2xpKHByb2Nlc3MuYXJndiwge1xuICAgICAgdHlwZXM6IHtcbiAgICAgICAgXCIjZW50aXR5SWRcIjoge1xuICAgICAgICAgIHR5cGU6IFwiYXV0b2NvbXBsZXRlXCIsXG4gICAgICAgICAgbmFtZTogXCIjZW50aXR5SWRcIixcbiAgICAgICAgICBtZXNzYWdlOiBcIlBsZWFzZSBpbnB1dCAjZW50aXR5SWRcIixcbiAgICAgICAgICBjaG9pY2VzOiBFbnRpdHlNYW5hZ2VyLmdldEFsbFBhcmVudElkcygpLm1hcCgoZW50aXR5SWQpID0+ICh7XG4gICAgICAgICAgICB0aXRsZTogZW50aXR5SWQsXG4gICAgICAgICAgICB2YWx1ZTogZW50aXR5SWQsXG4gICAgICAgICAgfSkpLFxuICAgICAgICB9LFxuICAgICAgICBcIiNyZWNvcmRJZHNcIjogXCJudW1iZXJbXVwiLFxuICAgICAgICBcIiNuYW1lXCI6IFwic3RyaW5nXCIsXG4gICAgICB9LFxuICAgICAgYXJnczogW1xuICAgICAgICBbXCJmaXh0dXJlXCIsIFwiaW5pdFwiXSxcbiAgICAgICAgW1wiZml4dHVyZVwiLCBcImltcG9ydFwiLCBcIiNlbnRpdHlJZFwiLCBcIiNyZWNvcmRJZHNcIl0sXG4gICAgICAgIFtcImZpeHR1cmVcIiwgXCJzeW5jXCJdLFxuICAgICAgICBbXCJtaWdyYXRlXCIsIFwicnVuXCJdLFxuICAgICAgICBbXCJtaWdyYXRlXCIsIFwiY2hlY2tcIl0sXG4gICAgICAgIFtcIm1pZ3JhdGVcIiwgXCJyb2xsYmFja1wiXSxcbiAgICAgICAgW1wibWlncmF0ZVwiLCBcInJlc2V0XCJdLFxuICAgICAgICBbXCJtaWdyYXRlXCIsIFwiY2xlYXJcIl0sXG4gICAgICAgIFtcIm1pZ3JhdGVcIiwgXCJzdGF0dXNcIl0sXG4gICAgICAgIFtcInN0dWJcIiwgXCJwcmFjdGljZVwiLCBcIiNuYW1lXCJdLFxuICAgICAgICBbXCJzdHViXCIsIFwiZW50aXR5XCIsIFwiI25hbWVcIl0sXG4gICAgICAgIFtcInNjYWZmb2xkXCIsIFwibW9kZWxcIiwgXCIjZW50aXR5SWRcIl0sXG4gICAgICAgIFtcInNjYWZmb2xkXCIsIFwibW9kZWxfdGVzdFwiLCBcIiNlbnRpdHlJZFwiXSxcbiAgICAgICAgW1wic2NhZmZvbGRcIiwgXCJ2aWV3X2xpc3RcIiwgXCIjZW50aXR5SWRcIl0sXG4gICAgICAgIFtcInNjYWZmb2xkXCIsIFwidmlld19mb3JtXCIsIFwiI2VudGl0eUlkXCJdLFxuICAgICAgICBbXCJzeW5jXCJdLFxuICAgICAgICBbXCJkZXZcIl0sXG4gICAgICAgIFtcImJ1aWxkXCJdLFxuICAgICAgICBbXCJzdGFydFwiXSxcbiAgICAgIF0sXG4gICAgICBydW5uZXJzOiB7XG4gICAgICAgIG1pZ3JhdGVfc3RhdHVzLFxuICAgICAgICBtaWdyYXRlX3J1bixcbiAgICAgICAgZml4dHVyZV9pbml0LFxuICAgICAgICBmaXh0dXJlX2ltcG9ydCxcbiAgICAgICAgZml4dHVyZV9zeW5jLFxuICAgICAgICBzdHViX3ByYWN0aWNlLFxuICAgICAgICBzdHViX2VudGl0eSxcbiAgICAgICAgc2NhZmZvbGRfbW9kZWwsXG4gICAgICAgIHNjYWZmb2xkX21vZGVsX3Rlc3QsXG4gICAgICAgIC8vIHNjYWZmb2xkX3ZpZXdfbGlzdCxcbiAgICAgICAgLy8gc2NhZmZvbGRfdmlld19mb3JtLFxuICAgICAgICBzeW5jLFxuICAgICAgICBkZXYsXG4gICAgICAgIGJ1aWxkLFxuICAgICAgICBzdGFydCxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgU29uYW11LmRlc3Ryb3koKTtcbiAgfVxufVxuXG5ib290c3RyYXAoKS5maW5hbGx5KGFzeW5jICgpID0+IHtcbiAgYXdhaXQgRml4dHVyZU1hbmFnZXIuZGVzdHJveSgpO1xufSk7XG5cbi8qKlxuICogcG5wbSBzeW5jIO2VmOuptCDsi6TtlonrkJjripQg7ZWo7IiY7J6F64uI64ukLlxuICog7ZSE66Gc7KCd7Yq466W8IOyLse2BrO2VqeuLiOuLpC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc3luYygpIHtcbiAgYXdhaXQgU29uYW11LnN5bmNlci5zeW5jKCk7XG59XG5cbi8qKlxuICogcG5wbSBkZXYg7ZWY66m0IOyLpO2WieuQmOuKlCDtlajsiJjsnoXri4jri6QuXG4gKiDtlITroZzsoJ3tirjsl5Ag64yA7ZW0IEhNUiDsp4Dsm5DtlZjripQg6rCc67CcIOyEnOuyhOulvCDrnYTsm4zspI3ri4jri6QuXG4gKlxuICogVHlwZVNjcmlwdOulvCDrsJTroZwg7Iuk7ZaJ7ZWgIOyImCDsnojrj4TroZ0gQHNvbmFtdS1raXQvdHMtbG9hZGVy66W8LFxuICogSE1S7J2EIOyngOybkO2VmOq4sCDsnITtlbQgQHNvbmFtdS1raXQvaG1yLWhvb2vsnYQgaW1wb3J07ZWY66mwLFxuICog7IaM7Iqk66e1IOyngOybkOydhCDsnITtlbQgLS1lbmFibGUtc291cmNlLW1hcHMg7ZSM656Y6re466W8IO2PrO2VqO2VmOyXrCDsi6Ttlontlanri4jri6QuXG4gKlxuICog7J2065WMIEBzb25hbXUta2l0L3RzLWxvYWRlcuyZgCBAc29uYW11LWtpdC9obXItaG9va+uKlCBzb25hbXXqsIAg7J6Q7LK07KCB7Jy866GcIOqwgOyngOqzoCDsnojripQgZGVwZW5kZW5jeeyeheuLiOuLpC5cbiAqIOuYkO2VnCDsi6Ttlonsl5Ag7IKs7Jqp7ZWY64qUIEBzb25hbXUta2l0L2htci1ydW5uZXLrj4Qg66eI7LCs6rCA7KeA66GcIHNvbmFtdeqwgCDsnpDssrTsoIHsnLzroZwg6rCA7KeA6rOgIOyeiOuKlCBkZXBlbmRlbmN57J6F64uI64ukLlxuICog65Sw65287IScIOyCrOyaqeyekCDtlITroZzsoJ3tirjsl5DshJzripQg7J20IOyEuCDtjKjtgqTsp4Drpbwg7KeB7KCRIOyEpOy5mO2VoCDtlYTsmpTqsIAg7JeG7Iq164uI64ukLlxuICpcbiAqIFNvbmFtdS5pbml0IOyXhuydtCDtmLjstpzrkKAg6rKD7J2EIOyDgeygle2VmOyXrCDqtaztmITrkJjsl4jsirXri4jri6QuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGRldigpIHtcbiAgY29uc3QgYXBpUm9vdCA9IGZpbmRBcGlSb290UGF0aCgpO1xuICBjb25zdCBlbnRyeVBvaW50ID0gXCJzcmMvaW5kZXgudHNcIjtcblxuICBjb25zb2xlLmxvZyhjaGFsay55ZWxsb3cuYm9sZChcIvCfmoAgU3RhcnRpbmcgU29uYW11IGRldiBzZXJ2ZXIuLi5cXG5cIikpO1xuXG4gIC8vIOydtCBzb25hbXUg7Yyo7YKk7KeA6rCAIGRlcGVuZGVuY2llc+uhnCDqsIDsp4Dqs6Ag7J6I64qUIEBzb25hbXUta2l0L2htci1ydW5uZXLsnZggYmluL3J1bi5qc+ulvCDsgqzsmqntlanri4jri6QuXG4gIC8vIOydtCDqsr3roZwoL2Jpbi9ydW4uanMp64qUIEBzb25hbXUta2l0L2htci1ydW5uZXLsnZggcGFja2FnZS5qc29u7J2YIGJpbiDtlYTrk5zsl5Ag66qF7Iuc65CY7Ja0IOyeiOuKlCDqt7jqsoPqs7wg6rCZ7Iq164uI64ukLlxuICBjb25zdCBob3RSdW5uZXJCaW5QYXRoID0gY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpLnJlc29sdmUoXG4gICAgXCJAc29uYW11LWtpdC9obXItcnVubmVyL2Jpbi9ydW4uanNcIixcbiAgKTtcblxuICBjb25zdCBzZXJ2ZXJQcm9jZXNzID0gc3Bhd24oXG4gICAgcHJvY2Vzcy5leGVjUGF0aCwgLy8gbm9kZVxuICAgIFtcbiAgICAgIGhvdFJ1bm5lckJpblBhdGgsIC8vIOydtOugh+qyjCDtlbTshJwgaG90LXJ1bm5lcuulvCDsi6TtlontlZjqtazsmpRcbiAgICAgIFwiLS1jbGVhci1zY3JlZW49ZmFsc2VcIiwgLy8g7J207ZWYIGhvdC1ydW5uZXLsl5Dqsowg64SY6rKo7KSEIOyduOyekOuTpOyeheuLiOuLpC5cbiAgICAgIFwiLS1ub2RlLWFyZ3M9LS1pbXBvcnQ9c29uYW11L3RzLWxvYWRlci1yZWdpc3RlclwiLCAvLyBUeXBlU2NyaXB0IOyEnO2PrO2KuOulvCDsnITtlZwg66Gc642ULFxuICAgICAgXCItLW5vZGUtYXJncz0tLWltcG9ydD1zb25hbXUvaG1yLWhvb2stcmVnaXN0ZXJcIiwgLy8gSE1S7J2EIOyngOybkO2VmOq4sCDsnITtlZwgaG9vayxcbiAgICAgIFwiLS1ub2RlLWFyZ3M9LS1lbmFibGUtc291cmNlLW1hcHNcIiwgLy8g6re466as6rOgIOyGjOyKpOuntSDsp4Dsm5DsnYQg7JyE7ZWcIO2UjOuemOq3uOyeheuLiOuLpC5cbiAgICAgIFwiLS1vbi1rZXk9cjpyZXN0YXJ0OlJlc3RhcnQgc2VydmVyXCIsIC8vIHIg64iE66W066m0IOyEnOuyhCDsnqzsi5zsnpHtlZjqsowg7ZW07KSY7JqULlxuICAgICAgYC0tb24ta2V5PWY6c2hlbGwocm0gJHtwYXRoLmpvaW4oYXBpUm9vdCwgXCJzb25hbXUubG9ja1wiKX0pOnJlc3RhcnQ6Rm9yY2UgcmVzdGFydGAsIC8vIGYg64iE66W066m0IHNvbmFtdS5sb2NrIO2MjOydvOydhCDsp4DsmrDqs6Ag7ISc67KEIOyerOyLnOyeke2VmOqyjCDtlbTspJjsmpQuXG5cbiAgICAgIFwiLS1vbi1rZXk9ZW50ZXI6c2hlbGwoZWNobyBoaSk6S2V5IGJpbmRpbmcgdGVzdFwiLCAvLyBlbnRlcuulvCBrZXnroZwg7JO4IOyImCDsnojsnYzsnYQg67O07J206riwIOychO2VnCDthYzsiqTtirjsnoXri4jri6QuXG4gICAgICBcIi0tb24ta2V5PWN0cmwrZiBjdHJsK2Y6c2hlbGwoZ2l0IHB1bGwgJiYgcG5wbSBpbnN0YWxsICYmIHBucG0gLS1maWx0ZXIgc29uYW11IGJ1aWxkICYmIGVjaG8gJ1NvbmFtdSBpcyBub3cgdXAtdG8tZGF0ZSEnKTpyZXN0YXJ0OlB1bGwgJiBpbnN0YWxsICYgYnVpbGQgJiByZXN0YXJ0XCIsIC8vIG1vZGlmaWVy7JmA7J2YIOyhsO2VqSwg6re466as6rOgIOuRkCDqsJzsnZggY2hvcmTrpbwg7IKs7Jqp7ZWgIOyImCDsnojsnYzsnYQg67O07J206riwIOychO2VnCDthYzsiqTtirjsnoXri4jri6QuXG4gICAgICBlbnRyeVBvaW50LCAvLyDrp4jsp4Drp4nsnLzroZwg7Iuk7KCcIOyLpO2Wie2VoCDsiqTtgazrpr3tirjsnZgg6rK966Gc66W8IOuEmOqyqOykjeuLiOuLpC5cbiAgICBdLFxuICAgIHtcbiAgICAgIGN3ZDogYXBpUm9vdCxcbiAgICAgIHN0ZGlvOiBcImluaGVyaXRcIixcbiAgICAgIGVudjoge1xuICAgICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgICAgTk9ERV9FTlY6IFwiZGV2ZWxvcG1lbnRcIixcbiAgICAgICAgSE9UOiBcInllc1wiLCAvLyDslpjqsIAg7J6I7Ja07JW8IEhNUuydtCDtmZzshLHtmZTrkKnri4jri6QuXG4gICAgICAgIEFQSV9ST09UX1BBVEg6IGFwaVJvb3QsIC8vIOydtCDqsr3roZzqsIAgaG1yLWhvb2vsnZgg66Oo7Yq4IOuUlOugie2GoOumrOqwgCDrkKnri4jri6QuXG4gICAgICB9LFxuICAgIH0sXG4gICk7XG5cbiAgLy8g7KKF66OMIOyymOumrFxuICBjb25zdCBjbGVhbnVwID0gKCkgPT4ge1xuICAgIGNvbnNvbGUubG9nKGNoYWxrLnllbGxvdyhcIlxcblxcbvCfkYsgU2h1dHRpbmcgZG93bi4uLlwiKSk7XG4gICAgc2VydmVyUHJvY2Vzcy5raWxsKFwiU0lHVEVSTVwiKTtcbiAgICBwcm9jZXNzLmV4aXQoMCk7XG4gIH07XG5cbiAgcHJvY2Vzcy5vbihcIlNJR0lOVFwiLCBjbGVhbnVwKTtcbiAgcHJvY2Vzcy5vbihcIlNJR1RFUk1cIiwgY2xlYW51cCk7XG5cbiAgc2VydmVyUHJvY2Vzcy5vbihcImV4aXRcIiwgKGNvZGUpID0+IHtcbiAgICBpZiAoY29kZSAhPT0gMCkge1xuICAgICAgY29uc29sZS5lcnJvcihjaGFsay5yZWQoYOKdjCBTZXJ2ZXIgZXhpdGVkIHdpdGggY29kZSAke2NvZGV9YCkpO1xuICAgICAgcHJvY2Vzcy5leGl0KGNvZGUgfHwgMSk7XG4gICAgfVxuICB9KTtcbn1cblxuLyoqXG4gKiBwbnBtIGJ1aWxkIO2VmOuptCDsi6TtlonrkJjripQg7ZWo7IiY7J6F64uI64ukLlxuICog7ZSE66Gc7KCd7Yq466W8IOu5jOuTnO2VqeuLiOuLpC5cbiAqXG4gKiDruYzrk5zsl5Ag7ZWE7JqU7ZWcIC5zd2NyY+uKlCDtlITroZzsoJ3tirgg66Oo7Yq47JeQ7IScIOywvuqzoCwg7JeG7Jy866m0IHNvbmFtdeqwgCDqtIDrpqztlZjripQgLnN3Y3JjLnByb2plY3QtZGVmYXVsdOulvCDsgqzsmqntlanri4jri6QuXG4gKlxuICog7Iuk7KCcIOu5jOuTnCDtg4Dqsp8o7JWE7Yuw7Yyp7Yq4KeqzvCDrj5nsnpHsnYAgYnVpbGQtY29uZmlnLnRz7JeQIOygleydmOuQmOyWtCDsnojsirXri4jri6QuXG4gKiDsnbQg7ZWo7IiY64qUIGJ1aWxkLWNvbmZpZy50c+yXkCDsoJXsnZjrkJwg64+Z7J6R65Ok7J2EIOyLpO2Wie2VtOyjvOuKlCDsl63tlaDrp4wg7ZWp64uI64ukLlxuICpcbiAqIFNvbmFtdS5pbml0IOyXhuydtCDtmLjstpzrkKAg6rKD7J2EIOyDgeygle2VmOyXrCDqtaztmITrkJjsl4jsirXri4jri6QuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkKCkge1xuICBjb25zdCBhcHBSb290ID0gZmluZEFwcFJvb3RQYXRoKCk7XG5cbiAgLy8g7Lac66ClIOuUlOugie2GoOumrOulvCDsoJzqsbDtlanri4jri6QuXG4gIHRyeSB7XG4gICAgZm9yIChjb25zdCBhcnRpZmFjdCBvZiBBUElfQVJUSUZBQ1RTKSB7XG4gICAgICBpZiAoYXdhaXQgZXhpc3RzKHBhdGguam9pbihhcHBSb290LCBhcnRpZmFjdC5vdXRwdXREaXIpKSkge1xuICAgICAgICAvLyBBUEkg7ZSE66Gc7KCd7Yq4IOyekOyytOydmCDruYzrk5wg6rKw6rO866y8XG4gICAgICAgIGF3YWl0IHJtKHBhdGguam9pbihhcHBSb290LCBhcnRpZmFjdC5vdXRwdXREaXIpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBhcnRpZmFjdCBvZiBXRUJfQVJUSUZBQ1RTKSB7XG4gICAgICBpZiAoYXdhaXQgZXhpc3RzKHBhdGguam9pbihhcHBSb290LCBhcnRpZmFjdC5vdXRwdXREaXIpKSkge1xuICAgICAgICAvLyBXZWIg7ZSE66Gc7KCd7Yq4IOyekOyytOydmCDruYzrk5wg6rKw6rO866y8XG4gICAgICAgIGF3YWl0IHJtKHBhdGguam9pbihhcHBSb290LCBhcnRpZmFjdC5vdXRwdXREaXIpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgICB9XG4gICAgICBpZiAoYXdhaXQgZXhpc3RzKHBhdGguam9pbihhcHBSb290LCBhcnRpZmFjdC5kZXN0RGlyKSkpIHtcbiAgICAgICAgLy8gQVBJIO2UhOuhnOygne2KuOuhnCDrs7XsgqzrkJjslrQg7JioIFdlYiDruYzrk5wg6rKw6rO866y8XG4gICAgICAgIGF3YWl0IHJtKHBhdGguam9pbihhcHBSb290LCBhcnRpZmFjdC5kZXN0RGlyKSwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKFwiXFxuQnVpbGQgYXJ0aWZhY3RzIHJlbW92ZWQgc3VjY2Vzc2Z1bGx5LlwiKSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5lcnJvcihjaGFsay5yZWQoXCJSZW1vdmUgYnVpbGQgZGlyZWN0b3JpZXMgZmFpbGVkLlwiKSwgZXJyb3IpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxuXG4gIC8vIC5zd2NyYyDtjIzsnbzsnYQg7KeA7KCV7ZWp64uI64ukLlxuICBsZXQgc3djRmlsZVBhdGggPSBcIi5zd2NyY1wiO1xuICB0cnkge1xuICAgIGlmIChhd2FpdCBleGlzdHMoc3djRmlsZVBhdGgpKSB7XG4gICAgICAvLyDsgqzsmqnsnpAg7ZSE66Gc7KCd7Yq47JeQIC5zd2NyY+qwgCDsnojsnLzrqbQg7Jqw7ISg7Jy866GcIOyCrOyaqe2VqeuLiOuLpC5cbiAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmRpbShcIlVzaW5nIC5zd2NyYyBmcm9tIHByb2plY3Qgcm9vdC4uLlwiKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIOyVhOuLiOudvOuptCBzb25hbXXqsIAg6rSA66as7ZWY64qUIC5zd2NyYy5wcm9qZWN0LWRlZmF1bHTrpbwg6rCA7KC464ukIOyUgeuLiOuLpC5cbiAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmRpbShcIlVzaW5nIGRlZmF1bHQgLnN3Y3JjIGZyb20gc29uYW11IHBhY2thZ2UuLi5cIikpO1xuICAgICAgc3djRmlsZVBhdGggPSBwYXRoLmpvaW4oaW1wb3J0Lm1ldGEuZGlybmFtZSwgXCIuLlwiLCBcIi4uXCIsIFwiLnN3Y3JjLnByb2plY3QtZGVmYXVsdFwiKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5lcnJvcihjaGFsay5yZWQoXCJTZXR0aW5nIHVwIHN3YyBjb25maWcgZmlsZSBmYWlsZWQuXCIpLCBlcnJvcik7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG5cbiAgLy8gQVBJIO2UhOuhnOygne2KuOulvCDruYzrk5ztlanri4jri6QuXG4gIGNvbnN0IGFwaVN0YXJ0ZWRBdCA9IERhdGUubm93KCk7XG4gIHRyeSB7XG4gICAgZm9yIChjb25zdCBhcnRpZmFjdCBvZiBBUElfQVJUSUZBQ1RTKSB7XG4gICAgICBjb25zdCBjd2QgPSBwYXRoLmpvaW4oYXBwUm9vdCwgYXJ0aWZhY3QucHJvamVjdFBhdGgpO1xuICAgICAgY29uc3QgY21kID0gYXJ0aWZhY3QuYnVpbGRDb21tYW5kKHN3Y0ZpbGVQYXRoKTtcblxuICAgICAgcHJpbnRUYXNrSGVhZGVyKGFydGlmYWN0Lm5hbWUsIGFydGlmYWN0LmRlc2NyaXB0aW9uLCBjd2QpO1xuXG4gICAgICAvLyBidWlsZFxuICAgICAgdHJ5IHtcbiAgICAgICAgcHJpbnRUYXNrU3RhcnQoXCJidWlsZFwiLCBjbWQsIHRydWUpO1xuICAgICAgICAvLyBjbWTrpbwgc3Bhd27tlbTshJwgYnVpbGTrpbwg7IiY7ZaJ7ZWY64qU642wLCDsnbTrlYwg66qF66C57J2YIOy2nOugpShzdGRvdXQsIHN0ZGVycikg65287J24IOyVnuyXkCDrk6Tsl6zsk7DquLDrpbwg67aZ7Jes7IScIOy2nOugpe2VqeuLiOuLpC5cbiAgICAgICAgYXdhaXQgZXhlY1dpdGhMaW5lUHJlZml4KGNtZCwgeyBjd2QgfSk7XG4gICAgICAgIHByaW50VGFza1N1Y2Nlc3MoXCJidWlsZFwiLCB0cnVlKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICBwcmludFRhc2tGYWlsZWQoXCJidWlsZFwiLCB0cnVlKTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYnVpbGQgZmFpbGVkXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICBwcmludEJ1aWxkU3VtbWFyeShcIkFQSVwiLCB0cnVlLCBEYXRlLm5vdygpIC0gYXBpU3RhcnRlZEF0KTtcbiAgfSBjYXRjaCB7XG4gICAgcHJpbnRCdWlsZFN1bW1hcnkoXCJBUElcIiwgZmFsc2UsIERhdGUubm93KCkgLSBhcGlTdGFydGVkQXQpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxuXG4gIC8vIFdlYiDtlITroZzsoJ3tirjrpbwg67mM65Oc7ZWp64uI64ukLlxuICBjb25zdCB3ZWJTdGFydGVkQXQgPSBEYXRlLm5vdygpO1xuICB0cnkge1xuICAgIGZvciAoY29uc3QgYXJ0aWZhY3Qgb2YgV0VCX0FSVElGQUNUUykge1xuICAgICAgY29uc3QgY3dkID0gcGF0aC5qb2luKGFwcFJvb3QsIGFydGlmYWN0LnByb2plY3RQYXRoKTtcbiAgICAgIGNvbnN0IGNtZCA9IGFydGlmYWN0LmJ1aWxkQ29tbWFuZCgpO1xuICAgICAgY29uc3Qgb3V0cHV0RGlyRnVsbCA9IHBhdGguam9pbihhcHBSb290LCBhcnRpZmFjdC5vdXRwdXREaXIpO1xuICAgICAgY29uc3QgZGVzdERpckZ1bGwgPSBwYXRoLmpvaW4oYXBwUm9vdCwgYXJ0aWZhY3QuZGVzdERpcik7XG5cbiAgICAgIHByaW50VGFza0hlYWRlcihhcnRpZmFjdC5uYW1lLCBhcnRpZmFjdC5kZXNjcmlwdGlvbiwgY3dkKTtcblxuICAgICAgLy8gYnVpbGRcbiAgICAgIHRyeSB7XG4gICAgICAgIHByaW50VGFza1N0YXJ0KFwiYnVpbGRcIiwgY21kKTtcbiAgICAgICAgLy8gY21k66W8IHNwYXdu7ZW07IScIGJ1aWxk66W8IOyImO2Wie2VmOuKlOuNsCwg7J2065WMIOuqheugueydmCDstpzroKUoc3Rkb3V0LCBzdGRlcnIpIOudvOyduCDslZ7sl5Ag65Ok7Jes7JOw6riw66W8IOu2meyXrOyEnCDstpzroKXtlanri4jri6QuXG4gICAgICAgIGF3YWl0IGV4ZWNXaXRoTGluZVByZWZpeChjbWQsIHsgY3dkIH0pO1xuICAgICAgICBwcmludFRhc2tTdWNjZXNzKFwiYnVpbGRcIik7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcHJpbnRUYXNrRmFpbGVkKFwiYnVpbGRcIik7XG4gICAgICAgIHByaW50VGFza1NraXBwZWQoXCJjb3B5XCIsIHRydWUpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJidWlsZCBmYWlsZWRcIik7XG4gICAgICB9XG5cbiAgICAgIC8vIGNvcHlcbiAgICAgIHRyeSB7XG4gICAgICAgIHByaW50VGFza1N0YXJ0KFwiY29weVwiLCBgJHthcnRpZmFjdC5vdXRwdXREaXJ9IOKGkiAke2FydGlmYWN0LmRlc3REaXJ9YCwgdHJ1ZSk7XG4gICAgICAgIC8vIFdlYiDslYTti7DtjKntirjripQg67mM65OcIOqysOqzvOusvChvdXRwdXREaXIp7J2EIOuLpOuluCDsnITsuZgoZGVzdERpcinroZwg67O17IKs7ZWY64qUIOyekeyXheydtCDstpTqsIDroZwg7ZWE7JqU7ZWp64uI64ukLlxuICAgICAgICBpZiAoYXdhaXQgZXhpc3RzKGRlc3REaXJGdWxsKSkge1xuICAgICAgICAgIGF3YWl0IHJtKGRlc3REaXJGdWxsLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgbWtkaXIoZGVzdERpckZ1bGwsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgICBhd2FpdCBjcChvdXRwdXREaXJGdWxsLCBkZXN0RGlyRnVsbCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICAgIHByaW50VGFza1N1Y2Nlc3MoXCJjb3B5XCIsIHRydWUpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHByaW50VGFza0ZhaWxlZChcImNvcHlcIiwgdHJ1ZSk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImNvcHkgZmFpbGVkXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICBwcmludEJ1aWxkU3VtbWFyeShcIldlYlwiLCB0cnVlLCBEYXRlLm5vdygpIC0gd2ViU3RhcnRlZEF0KTtcbiAgfSBjYXRjaCB7XG4gICAgcHJpbnRCdWlsZFN1bW1hcnkoXCJXZWJcIiwgZmFsc2UsIERhdGUubm93KCkgLSB3ZWJTdGFydGVkQXQpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxufVxuXG4vKipcbiAqIHBucG0gc3RhcnQg7ZWY66m0IOyLpO2WieuQmOuKlCDtlajsiJjsnoXri4jri6QuXG4gKiDruYzrk5zrkJwg7ZSE66Gc7KCd7Yq466W8IOyLpO2Wie2VqeuLiOuLpC5cbiAqXG4gKiDruYzrk5zrkJwg6rKw6rO866y8KGRpc3Qg65SU66CJ7Yag66as7J2YIGluZGV4LmpzIOyXlO2KuOumrO2PrOyduO2KuCnsnbQg7JeG64uk66m0IOyLpO2WieydhCDspJHri6jtlanri4jri6QuXG4gKiDshozsiqTrp7Ug7KeA7JuQ6rO8IGRvdGVudiDsp4Dsm5DsnYQg7Y+s7ZWo7ZWY7JesIOyLpO2Wie2VqeuLiOuLpC5cbiAqXG4gKiBTb25hbXUuaW5pdCDsl4bsnbQg7Zi47Lac65CgIOqyg+ydhCDsg4HsoJXtlZjsl6wg6rWs7ZiE65CY7JeI7Iq164uI64ukLlxuICovXG5hc3luYyBmdW5jdGlvbiBzdGFydCgpIHtcbiAgY29uc3QgYXBpUm9vdCA9IGZpbmRBcGlSb290UGF0aCgpO1xuICBjb25zdCBlbnRyeVBvaW50ID0gXCJkaXN0L2luZGV4LmpzXCI7XG5cbiAgaWYgKCEoYXdhaXQgZXhpc3RzKGVudHJ5UG9pbnQpKSkge1xuICAgIGNvbnNvbGUubG9nKGNoYWxrLnJlZChgJHtlbnRyeVBvaW50fSBub3QgZm91bmQuIFBsZWFzZSBidWlsZCB5b3VyIHByb2plY3QgZmlyc3QuYCkpO1xuICAgIGNvbnNvbGUubG9nKGNoYWxrLmJsdWUoXCJSdW46IHlhcm4gc29uYW11IGJ1aWxkXCIpKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCB7IHNwYXduIH0gPSBhd2FpdCBpbXBvcnQoXCJjaGlsZF9wcm9jZXNzXCIpO1xuICBjb25zdCBzZXJ2ZXJQcm9jZXNzID0gc3Bhd24oXG4gICAgcHJvY2Vzcy5leGVjUGF0aCxcbiAgICBbXCItLWVuYWJsZS1zb3VyY2UtbWFwc1wiLCBcIi1yXCIsIFwiZG90ZW52L2NvbmZpZ1wiLCBlbnRyeVBvaW50XSxcbiAgICB7XG4gICAgICBjd2Q6IGFwaVJvb3QsXG4gICAgICBzdGRpbzogXCJpbmhlcml0XCIsXG4gICAgfSxcbiAgKTtcblxuICBwcm9jZXNzLm9uKFwiU0lHSU5UXCIsICgpID0+IHtcbiAgICBzZXJ2ZXJQcm9jZXNzLmtpbGwoXCJTSUdURVJNXCIpO1xuICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNldHVwTWlncmF0b3IoKSB7XG4gIC8vIG1pZ3JhdG9yXG4gIG1pZ3JhdG9yID0gbmV3IE1pZ3JhdG9yKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNldHVwRml4dHVyZU1hbmFnZXIoKSB7XG4gIEZpeHR1cmVNYW5hZ2VyLmluaXQoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWlncmF0ZV9ydW4oKSB7XG4gIGF3YWl0IHNldHVwTWlncmF0b3IoKTtcblxuICBhd2FpdCBtaWdyYXRvci5ydW5BY3Rpb24oXG4gICAgXCJhcHBseVwiLFxuICAgIE9iamVjdC5rZXlzKFNvbmFtdS5kYkNvbmZpZykgYXMgKGtleW9mIFNvbmFtdURCQ29uZmlnKVtdIC8q7Iu5IOuLpCEqLyxcbiAgKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWlncmF0ZV9zdGF0dXMoKSB7XG4gIGF3YWl0IHNldHVwTWlncmF0b3IoKTtcblxuICBjb25zdCBzdGF0dXMgPSBhd2FpdCBtaWdyYXRvci5nZXRTdGF0dXMoKTtcbiAgLy8gc3RhdHVzO1xuICBjb25zb2xlLmxvZyhzdGF0dXMpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmaXh0dXJlX2luaXQoKSB7XG4gIGNvbnN0IHNyY0NvbmZpZyA9IFNvbmFtdS5kYkNvbmZpZy5kZXZlbG9wbWVudF9tYXN0ZXI7XG4gIGNvbnN0IHRhcmdldHMgPSBbXG4gICAge1xuICAgICAgbGFiZWw6IFwiKFJFTU9URSkgRml4dHVyZSBEQlwiLFxuICAgICAgY29uZmlnOiBTb25hbXUuZGJDb25maWcuZml4dHVyZSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGxhYmVsOiBcIihMT0NBTCkgVGVzdGluZyBEQlwiLFxuICAgICAgY29uZmlnOiBTb25hbXUuZGJDb25maWcudGVzdCxcbiAgICAgIHRvU2tpcDogKCgpID0+IHtcbiAgICAgICAgY29uc3QgcmVtb3RlQ29ubiA9IFNvbmFtdS5kYkNvbmZpZy5maXh0dXJlLmNvbm5lY3Rpb24gYXMgS25leC5Db25uZWN0aW9uQ29uZmlnO1xuICAgICAgICBjb25zdCBsb2NhbENvbm4gPSBTb25hbXUuZGJDb25maWcudGVzdC5jb25uZWN0aW9uIGFzIEtuZXguQ29ubmVjdGlvbkNvbmZpZztcbiAgICAgICAgcmV0dXJuIHJlbW90ZUNvbm4uaG9zdCA9PT0gbG9jYWxDb25uLmhvc3QgJiYgcmVtb3RlQ29ubi5kYXRhYmFzZSA9PT0gbG9jYWxDb25uLmRhdGFiYXNlO1xuICAgICAgfSkoKSxcbiAgICB9LFxuICBdIGFzIHtcbiAgICBsYWJlbDogc3RyaW5nO1xuICAgIGNvbmZpZzogS25leC5Db25maWc7XG4gICAgdG9Ta2lwPzogYm9vbGVhbjtcbiAgfVtdO1xuXG4gIC8vIDEuIOq4sOykgERCIOyKpO2CpOuniOulvCDrjaTtlIRcbiAgY29uc29sZS5sb2coXCJEVU1QLi4uXCIpO1xuICBjb25zdCBkdW1wRmlsZW5hbWUgPSBgL3RtcC9zb25hbXUtZml4dHVyZS1pbml0LSR7RGF0ZS5ub3coKX0uc3FsYDtcbiAgY29uc3Qgc3JjQ29ubiA9IHNyY0NvbmZpZy5jb25uZWN0aW9uIGFzIEtuZXguQ29ubmVjdGlvbkNvbmZpZztcbiAgY29uc3QgbWlncmF0aW9uc0R1bXAgPSBgL3RtcC9zb25hbXUtZml4dHVyZS1pbml0LW1pZ3JhdGlvbnMtJHtEYXRlLm5vdygpfS5zcWxgO1xuICBleGVjU3luYyhcbiAgICBgbXlzcWxkdW1wIC1oJHtzcmNDb25uLmhvc3R9IC11JHtzcmNDb25uLnVzZXJ9IC1wJHtzcmNDb25uLnBhc3N3b3JkfSAtLXNpbmdsZS10cmFuc2FjdGlvbiAtZCAtLW5vLWNyZWF0ZS1kYiAtLXRyaWdnZXJzICR7c3JjQ29ubi5kYXRhYmFzZX0gPiAke2R1bXBGaWxlbmFtZX1gLFxuICApO1xuICBjb25zdCBfZGIgPSBrbmV4KHNyY0NvbmZpZyk7XG4gIGNvbnN0IFtbbWlncmF0aW9uc11dID0gYXdhaXQgX2RiLnJhdyhcbiAgICBcIlNFTEVDVCBDT1VOVCgqKSBhcyBjb3VudCBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS50YWJsZXMgV0hFUkUgdGFibGVfc2NoZW1hID0gPyBBTkQgdGFibGVfbmFtZSA9ICdrbmV4X21pZ3JhdGlvbnMnXCIsXG4gICAgW3NyY0Nvbm4uZGF0YWJhc2VdLFxuICApO1xuICBpZiAobWlncmF0aW9ucy5jb3VudCA+IDApIHtcbiAgICBleGVjU3luYyhcbiAgICAgIGBteXNxbGR1bXAgLWgke3NyY0Nvbm4uaG9zdH0gLXUke3NyY0Nvbm4udXNlcn0gLXAke3NyY0Nvbm4ucGFzc3dvcmR9IC0tc2luZ2xlLXRyYW5zYWN0aW9uIC0tbm8tY3JlYXRlLWRiIC0tdHJpZ2dlcnMgJHtzcmNDb25uLmRhdGFiYXNlfSBrbmV4X21pZ3JhdGlvbnMga25leF9taWdyYXRpb25zX2xvY2sgPiAke21pZ3JhdGlvbnNEdW1wfWAsXG4gICAgKTtcbiAgfVxuXG4gIC8vIDIuIOuMgOyDgURCIOqwgeqwgeyXkCDrjIDtlZjsl6wg7KG07J6s7Jes67aAIO2ZleyduCDtm4Qg67aT6riwXG4gIGZvciBhd2FpdCAoY29uc3QgeyBsYWJlbCwgY29uZmlnLCB0b1NraXAgfSBvZiB0YXJnZXRzKSB7XG4gICAgY29uc3QgY29ubiA9IGNvbmZpZy5jb25uZWN0aW9uIGFzIEtuZXguQ29ubmVjdGlvbkNvbmZpZztcblxuICAgIGlmICh0b1NraXAgPT09IHRydWUpIHtcbiAgICAgIGNvbnNvbGUubG9nKGNoYWxrLnJlZChgJHtsYWJlbH06IFNraXBwZWQhYCkpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgZGIgPSBrbmV4KHtcbiAgICAgIC4uLmNvbmZpZyxcbiAgICAgIGNvbm5lY3Rpb246IHtcbiAgICAgICAgLi4uKChjb25maWcuY29ubmVjdGlvbiA/PyB7fSkgYXMgS25leC5Db25uZWN0aW9uQ29uZmlnKSxcbiAgICAgICAgZGF0YWJhc2U6IHVuZGVmaW5lZCxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgY29uc3QgW1tyb3ddXSA9IGF3YWl0IGRiLnJhdyhgU0hPVyBEQVRBQkFTRVMgTElLRSBcIiR7Y29ubi5kYXRhYmFzZX1cImApO1xuICAgIGlmIChyb3cpIHtcbiAgICAgIGNvbnNvbGUubG9nKGNoYWxrLnllbGxvdyhgJHtsYWJlbH06IERhdGFiYXNlIFwiJHtjb25uLmRhdGFiYXNlfVwiIEFscmVhZHkgZXhpc3RzYCkpO1xuICAgICAgYXdhaXQgZGIuZGVzdHJveSgpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc29sZS5sb2coYFNZTkMgdG8gJHtsYWJlbH0uLi5gKTtcbiAgICBjb25zdCBteXNxbENtZCA9IGBteXNxbCAtaCR7Y29ubi5ob3N0fSAtdSR7Y29ubi51c2VyfSAtcCR7Y29ubi5wYXNzd29yZH1gO1xuICAgIGV4ZWNTeW5jKGAke215c3FsQ21kfSAtZSAnRFJPUCBEQVRBQkFTRSBJRiBFWElTVFMgXFxgJHtjb25uLmRhdGFiYXNlfVxcYCdgKTtcbiAgICBleGVjU3luYyhgJHtteXNxbENtZH0gLWUgJ0NSRUFURSBEQVRBQkFTRSBcXGAke2Nvbm4uZGF0YWJhc2V9XFxgJ2ApO1xuICAgIGV4ZWNTeW5jKGAke215c3FsQ21kfSAke2Nvbm4uZGF0YWJhc2V9IDwgJHtkdW1wRmlsZW5hbWV9YCk7XG4gICAgaWYgKGF3YWl0IGV4aXN0cyhtaWdyYXRpb25zRHVtcCkpIHtcbiAgICAgIGV4ZWNTeW5jKGAke215c3FsQ21kfSAke2Nvbm4uZGF0YWJhc2V9IDwgJHttaWdyYXRpb25zRHVtcH1gKTtcbiAgICB9XG5cbiAgICBhd2FpdCBkYi5kZXN0cm95KCk7XG4gIH1cblxuICBhd2FpdCBfZGIuZGVzdHJveSgpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmaXh0dXJlX2ltcG9ydChlbnRpdHlJZDogc3RyaW5nLCByZWNvcmRJZHM6IG51bWJlcltdKSB7XG4gIGF3YWl0IHNldHVwRml4dHVyZU1hbmFnZXIoKTtcblxuICBhd2FpdCBGaXh0dXJlTWFuYWdlci5pbXBvcnRGaXh0dXJlKGVudGl0eUlkLCByZWNvcmRJZHMpO1xuICBhd2FpdCBGaXh0dXJlTWFuYWdlci5zeW5jKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpeHR1cmVfc3luYygpIHtcbiAgYXdhaXQgc2V0dXBGaXh0dXJlTWFuYWdlcigpO1xuXG4gIGF3YWl0IEZpeHR1cmVNYW5hZ2VyLnN5bmMoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3R1Yl9wcmFjdGljZShuYW1lOiBzdHJpbmcpIHtcbiAgY29uc3QgcHJhY3RpY2VEaXIgPSBwYXRoLmpvaW4oU29uYW11LmFwaVJvb3RQYXRoLCBcInNyY1wiLCBcInByYWN0aWNlc1wiKTtcbiAgY29uc3QgZmlsZU5hbWVzID0gYXdhaXQgcmVhZGRpcihwcmFjdGljZURpcik7XG5cbiAgY29uc3QgbWF4U2VxTm8gPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgIGlmICghKGF3YWl0IGV4aXN0cyhwcmFjdGljZURpcikpKSB7XG4gICAgICBhd2FpdCBta2RpcihwcmFjdGljZURpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgZmlsdGVyZWRTZXFzID0gZmlsZU5hbWVzXG4gICAgICAuZmlsdGVyKChmaWxlTmFtZSkgPT4gZmlsZU5hbWUuc3RhcnRzV2l0aChcInBcIikgJiYgZmlsZU5hbWUuZW5kc1dpdGgoXCIudHNcIikpXG4gICAgICAubWFwKChmaWxlTmFtZSkgPT4ge1xuICAgICAgICBjb25zdCBbLCBzZXFOb10gPSBmaWxlTmFtZS5tYXRjaCgvXnAoWzAtOV0rKS0vKSA/PyBbXCIwXCIsIFwiMFwiXTtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHNlcU5vKTtcbiAgICAgIH0pXG4gICAgICAuc29ydCgoYSwgYikgPT4gYiAtIGEpO1xuXG4gICAgaWYgKGZpbHRlcmVkU2Vxcy5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gZmlsdGVyZWRTZXFzWzBdO1xuICAgIH1cblxuICAgIHJldHVybiAwO1xuICB9KSgpO1xuXG4gIGNvbnN0IGN1cnJlbnRTZXFObyA9IG1heFNlcU5vICsgMTtcbiAgY29uc3QgZmlsZU5hbWUgPSBgcCR7Y3VycmVudFNlcU5vfS0ke25hbWV9LnRzYDtcbiAgY29uc3QgZHN0UGF0aCA9IHBhdGguam9pbihwcmFjdGljZURpciwgZmlsZU5hbWUpO1xuXG4gIGNvbnN0IGNvZGUgPSBbXG4gICAgYGltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCJzb25hbXVcIjtgLFxuICAgIFwiXCIsXG4gICAgYGNvbnNvbGUuY2xlYXIoKTtgLFxuICAgIGBjb25zb2xlLmxvZyhcIiR7ZmlsZU5hbWV9XCIpO2AsXG4gICAgXCJcIixcbiAgICBgU29uYW11LnJ1blNjcmlwdChhc3luYyAoKSA9PiB7YCxcbiAgICBgIC8vIFRPRE9gLFxuICAgIGB9KTtgLFxuICAgIFwiXCIsXG4gIF0uam9pbihcIlxcblwiKTtcbiAgYXdhaXQgd3JpdGVGaWxlKGRzdFBhdGgsIGNvZGUpO1xuXG4gIGV4ZWNTeW5jKGBjb2RlICR7ZHN0UGF0aH1gKTtcblxuICBjb25zdCBydW5Db2RlID0gYHlhcm4gbm9kZSAtciBkb3RlbnYvY29uZmlnIC0tZW5hYmxlLXNvdXJjZS1tYXBzIGRpc3QvcHJhY3RpY2VzLyR7ZmlsZU5hbWUucmVwbGFjZShcbiAgICBcIi50c1wiLFxuICAgIFwiLmpzXCIsXG4gICl9YDtcbiAgY29uc29sZS5sb2coYCR7Y2hhbGsuYmx1ZShydW5Db2RlKX0gY29waWVkIHRvIGNsaXBib2FyZC5gKTtcbiAgZXhlY1N5bmMoYGVjaG8gXCIke3J1bkNvZGV9XCIgfCBwYmNvcHlgKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3R1Yl9lbnRpdHkoZW50aXR5SWQ6IHN0cmluZykge1xuICBhd2FpdCBTb25hbXUuc3luY2VyLmNyZWF0ZUVudGl0eSh7IGVudGl0eUlkLCB0aXRsZTogZW50aXR5SWQgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNjYWZmb2xkX21vZGVsKGVudGl0eUlkOiBzdHJpbmcpIHtcbiAgYXdhaXQgU29uYW11LnN5bmNlci5nZW5lcmF0ZVRlbXBsYXRlKFwibW9kZWxcIiwge1xuICAgIGVudGl0eUlkLFxuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2NhZmZvbGRfbW9kZWxfdGVzdChlbnRpdHlJZDogc3RyaW5nKSB7XG4gIGF3YWl0IFNvbmFtdS5zeW5jZXIuZ2VuZXJhdGVUZW1wbGF0ZShcIm1vZGVsX3Rlc3RcIiwge1xuICAgIGVudGl0eUlkLFxuICB9KTtcbn1cbiJdLCJuYW1lcyI6WyJjaGFsayIsImRvdGVudiIsImNvbmZpZyIsImV4ZWNTeW5jIiwic3Bhd24iLCJjcCIsIm1rZGlyIiwicmVhZGRpciIsInJtIiwid3JpdGVGaWxlIiwia25leCIsImNyZWF0ZVJlcXVpcmUiLCJwYXRoIiwicHJvY2VzcyIsInRzaWNsaSIsIlNvbmFtdSIsIkVudGl0eU1hbmFnZXIiLCJNaWdyYXRvciIsIkZpeHR1cmVNYW5hZ2VyIiwiZXhlY1dpdGhMaW5lUHJlZml4IiwicHJpbnRCdWlsZFN1bW1hcnkiLCJwcmludFRhc2tGYWlsZWQiLCJwcmludFRhc2tIZWFkZXIiLCJwcmludFRhc2tTa2lwcGVkIiwicHJpbnRUYXNrU3RhcnQiLCJwcmludFRhc2tTdWNjZXNzIiwiZXhpc3RzIiwiZmluZEFwaVJvb3RQYXRoIiwiZmluZEFwcFJvb3RQYXRoIiwiQVBJX0FSVElGQUNUUyIsIldFQl9BUlRJRkFDVFMiLCJtaWdyYXRvciIsImJvb3RzdHJhcCIsIm5vdFRvSW5pdCIsImluY2x1ZGVzIiwiYXJndiIsImluaXQiLCJ0eXBlcyIsInR5cGUiLCJuYW1lIiwibWVzc2FnZSIsImNob2ljZXMiLCJnZXRBbGxQYXJlbnRJZHMiLCJtYXAiLCJlbnRpdHlJZCIsInRpdGxlIiwidmFsdWUiLCJhcmdzIiwicnVubmVycyIsIm1pZ3JhdGVfc3RhdHVzIiwibWlncmF0ZV9ydW4iLCJmaXh0dXJlX2luaXQiLCJmaXh0dXJlX2ltcG9ydCIsImZpeHR1cmVfc3luYyIsInN0dWJfcHJhY3RpY2UiLCJzdHViX2VudGl0eSIsInNjYWZmb2xkX21vZGVsIiwic2NhZmZvbGRfbW9kZWxfdGVzdCIsInN5bmMiLCJkZXYiLCJidWlsZCIsInN0YXJ0IiwiZGVzdHJveSIsImZpbmFsbHkiLCJzeW5jZXIiLCJhcGlSb290IiwiZW50cnlQb2ludCIsImNvbnNvbGUiLCJsb2ciLCJ5ZWxsb3ciLCJib2xkIiwiaG90UnVubmVyQmluUGF0aCIsInVybCIsInJlc29sdmUiLCJzZXJ2ZXJQcm9jZXNzIiwiZXhlY1BhdGgiLCJqb2luIiwiY3dkIiwic3RkaW8iLCJlbnYiLCJOT0RFX0VOViIsIkhPVCIsIkFQSV9ST09UX1BBVEgiLCJjbGVhbnVwIiwia2lsbCIsImV4aXQiLCJvbiIsImNvZGUiLCJlcnJvciIsInJlZCIsImFwcFJvb3QiLCJhcnRpZmFjdCIsIm91dHB1dERpciIsInJlY3Vyc2l2ZSIsImZvcmNlIiwiZGVzdERpciIsImdyZWVuIiwic3djRmlsZVBhdGgiLCJkaW0iLCJkaXJuYW1lIiwiYXBpU3RhcnRlZEF0IiwiRGF0ZSIsIm5vdyIsInByb2plY3RQYXRoIiwiY21kIiwiYnVpbGRDb21tYW5kIiwiZGVzY3JpcHRpb24iLCJFcnJvciIsIndlYlN0YXJ0ZWRBdCIsIm91dHB1dERpckZ1bGwiLCJkZXN0RGlyRnVsbCIsImJsdWUiLCJzZXR1cE1pZ3JhdG9yIiwic2V0dXBGaXh0dXJlTWFuYWdlciIsInJ1bkFjdGlvbiIsIk9iamVjdCIsImtleXMiLCJkYkNvbmZpZyIsInN0YXR1cyIsImdldFN0YXR1cyIsInNyY0NvbmZpZyIsImRldmVsb3BtZW50X21hc3RlciIsInRhcmdldHMiLCJsYWJlbCIsImZpeHR1cmUiLCJ0ZXN0IiwidG9Ta2lwIiwicmVtb3RlQ29ubiIsImNvbm5lY3Rpb24iLCJsb2NhbENvbm4iLCJob3N0IiwiZGF0YWJhc2UiLCJkdW1wRmlsZW5hbWUiLCJzcmNDb25uIiwibWlncmF0aW9uc0R1bXAiLCJ1c2VyIiwicGFzc3dvcmQiLCJfZGIiLCJtaWdyYXRpb25zIiwicmF3IiwiY291bnQiLCJjb25uIiwiZGIiLCJ1bmRlZmluZWQiLCJyb3ciLCJteXNxbENtZCIsInJlY29yZElkcyIsImltcG9ydEZpeHR1cmUiLCJwcmFjdGljZURpciIsImFwaVJvb3RQYXRoIiwiZmlsZU5hbWVzIiwibWF4U2VxTm8iLCJmaWx0ZXJlZFNlcXMiLCJmaWx0ZXIiLCJmaWxlTmFtZSIsInN0YXJ0c1dpdGgiLCJlbmRzV2l0aCIsInNlcU5vIiwibWF0Y2giLCJwYXJzZUludCIsInNvcnQiLCJhIiwiYiIsImxlbmd0aCIsImN1cnJlbnRTZXFObyIsImRzdFBhdGgiLCJydW5Db2RlIiwicmVwbGFjZSIsImNyZWF0ZUVudGl0eSIsImdlbmVyYXRlVGVtcGxhdGUiXSwibWFwcGluZ3MiOiJBQUFBLE9BQU9BLFdBQVcsUUFBUTtBQUMxQixPQUFPQyxZQUFZLFNBQVM7QUFFNUJBLE9BQU9DLE1BQU07QUFFYixTQUFTQyxRQUFRLEVBQUVDLEtBQUssUUFBUSxnQkFBZ0I7QUFDaEQsU0FBU0MsRUFBRSxFQUFFQyxLQUFLLEVBQUVDLE9BQU8sRUFBRUMsRUFBRSxFQUFFQyxTQUFTLFFBQVEsbUJBQWM7QUFDaEUsT0FBT0MsVUFBeUIsT0FBTztBQUN2QyxTQUFTQyxhQUFhLFFBQVEsU0FBUztBQUN2QyxPQUFPQyxVQUFVLE9BQU87QUFDeEIsT0FBT0MsYUFBYSxVQUFVO0FBQzlCLFNBQVNDLE1BQU0sUUFBUSxTQUFTO0FBQ2hDLFNBQVNDLE1BQU0sUUFBUSxrQkFBUztBQUVoQyxTQUFTQyxhQUFhLFFBQVEsOEJBQTJCO0FBQ3pELFNBQVNDLFFBQVEsUUFBUSwyQkFBd0I7QUFDakQsU0FBU0MsY0FBYyxRQUFRLGdDQUE2QjtBQUM1RCxTQUNFQyxrQkFBa0IsRUFDbEJDLGlCQUFpQixFQUNqQkMsZUFBZSxFQUNmQyxlQUFlLEVBQ2ZDLGdCQUFnQixFQUNoQkMsY0FBYyxFQUNkQyxnQkFBZ0IsUUFDWCwyQkFBd0I7QUFDL0IsU0FBU0Ms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
486
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iaW4vY2xpLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIjtcbmltcG9ydCBkb3RlbnYgZnJvbSBcImRvdGVudlwiO1xuXG5kb3RlbnYuY29uZmlnKCk7XG5cbmltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHsgZXhlY1N5bmMsIHNwYXduIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IG1rZGlyLCByZWFkZGlyLCB3cml0ZUZpbGUgfSBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBrbmV4LCB7IHR5cGUgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSBcIm1vZHVsZVwiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCBwcm9jZXNzIGZyb20gXCJwcm9jZXNzXCI7XG5pbXBvcnQgeyB0c2ljbGkgfSBmcm9tIFwidHNpY2xpXCI7XG5pbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwiLi4vYXBpXCI7XG5pbXBvcnQgdHlwZSB7IFNvbmFtdURCQ29uZmlnIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHsgTWlncmF0b3IgfSBmcm9tIFwiLi4vbWlncmF0aW9uL21pZ3JhdG9yXCI7XG5pbXBvcnQgeyBGaXh0dXJlTWFuYWdlciB9IGZyb20gXCIuLi90ZXN0aW5nL2ZpeHR1cmUtbWFuYWdlclwiO1xuaW1wb3J0IHtcbiAgZXhlY1dpdGhMaW5lUHJlZml4LFxuICBwcmludEJ1aWxkU3VtbWFyeSxcbiAgcHJpbnRUYXNrRmFpbGVkLFxuICBwcmludFRhc2tIZWFkZXIsXG4gIHByaW50VGFza1N0YXJ0LFxuICBwcmludFRhc2tTdWNjZXNzLFxufSBmcm9tIFwiLi4vdXRpbHMvY29uc29sZS11dGlsXCI7XG5pbXBvcnQgeyBleGlzdHMgfSBmcm9tIFwiLi4vdXRpbHMvZnMtdXRpbHNcIjtcbmltcG9ydCB7IGZpbmRBcGlSb290UGF0aCwgZmluZEFwcFJvb3RQYXRoIH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBBUElfQVJUSUZBQ1RTLCB0eXBlIEJ1aWxkQXJ0aWZhY3QsIFdFQl9BUlRJRkFDVFMgfSBmcm9tIFwiLi9idWlsZC1jb25maWdcIjtcblxubGV0IG1pZ3JhdG9yOiBNaWdyYXRvcjtcblxuYXN5bmMgZnVuY3Rpb24gYm9vdHN0cmFwKCkge1xuICBjb25zdCBub3RUb0luaXQgPSBbXCJkZXZcIiwgXCJidWlsZFwiLCBcInN0YXJ0XCJdLmluY2x1ZGVzKHByb2Nlc3MuYXJndlsyXSA/PyBcIlwiKTtcbiAgaWYgKCFub3RUb0luaXQpIHtcbiAgICBhd2FpdCBTb25hbXUuaW5pdChmYWxzZSwgZmFsc2UpO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCB0c2ljbGkocHJvY2Vzcy5hcmd2LCB7XG4gICAgICB0eXBlczoge1xuICAgICAgICBcIiNlbnRpdHlJZFwiOiB7XG4gICAgICAgICAgdHlwZTogXCJhdXRvY29tcGxldGVcIixcbiAgICAgICAgICBuYW1lOiBcIiNlbnRpdHlJZFwiLFxuICAgICAgICAgIG1lc3NhZ2U6IFwiUGxlYXNlIGlucHV0ICNlbnRpdHlJZFwiLFxuICAgICAgICAgIGNob2ljZXM6IEVudGl0eU1hbmFnZXIuZ2V0QWxsUGFyZW50SWRzKCkubWFwKChlbnRpdHlJZCkgPT4gKHtcbiAgICAgICAgICAgIHRpdGxlOiBlbnRpdHlJZCxcbiAgICAgICAgICAgIHZhbHVlOiBlbnRpdHlJZCxcbiAgICAgICAgICB9KSksXG4gICAgICAgIH0sXG4gICAgICAgIFwiI3JlY29yZElkc1wiOiBcIm51bWJlcltdXCIsXG4gICAgICAgIFwiI25hbWVcIjogXCJzdHJpbmdcIixcbiAgICAgIH0sXG4gICAgICBhcmdzOiBbXG4gICAgICAgIFtcImZpeHR1cmVcIiwgXCJpbml0XCJdLFxuICAgICAgICBbXCJmaXh0dXJlXCIsIFwiaW1wb3J0XCIsIFwiI2VudGl0eUlkXCIsIFwiI3JlY29yZElkc1wiXSxcbiAgICAgICAgW1wiZml4dHVyZVwiLCBcInN5bmNcIl0sXG4gICAgICAgIFtcIm1pZ3JhdGVcIiwgXCJydW5cIl0sXG4gICAgICAgIFtcIm1pZ3JhdGVcIiwgXCJjaGVja1wiXSxcbiAgICAgICAgW1wibWlncmF0ZVwiLCBcInJvbGxiYWNrXCJdLFxuICAgICAgICBbXCJtaWdyYXRlXCIsIFwicmVzZXRcIl0sXG4gICAgICAgIFtcIm1pZ3JhdGVcIiwgXCJjbGVhclwiXSxcbiAgICAgICAgW1wibWlncmF0ZVwiLCBcInN0YXR1c1wiXSxcbiAgICAgICAgW1wic3R1YlwiLCBcInByYWN0aWNlXCIsIFwiI25hbWVcIl0sXG4gICAgICAgIFtcInN0dWJcIiwgXCJlbnRpdHlcIiwgXCIjbmFtZVwiXSxcbiAgICAgICAgW1wic2NhZmZvbGRcIiwgXCJtb2RlbFwiLCBcIiNlbnRpdHlJZFwiXSxcbiAgICAgICAgW1wic2NhZmZvbGRcIiwgXCJtb2RlbF90ZXN0XCIsIFwiI2VudGl0eUlkXCJdLFxuICAgICAgICBbXCJzY2FmZm9sZFwiLCBcInZpZXdfbGlzdFwiLCBcIiNlbnRpdHlJZFwiXSxcbiAgICAgICAgW1wic2NhZmZvbGRcIiwgXCJ2aWV3X2Zvcm1cIiwgXCIjZW50aXR5SWRcIl0sXG4gICAgICAgIFtcInN5bmNcIl0sXG4gICAgICAgIFtcImRldlwiXSxcbiAgICAgICAgW1wiYnVpbGRcIl0sXG4gICAgICAgIFtcInN0YXJ0XCJdLFxuICAgICAgXSxcbiAgICAgIHJ1bm5lcnM6IHtcbiAgICAgICAgbWlncmF0ZV9zdGF0dXMsXG4gICAgICAgIG1pZ3JhdGVfcnVuLFxuICAgICAgICBmaXh0dXJlX2luaXQsXG4gICAgICAgIGZpeHR1cmVfaW1wb3J0LFxuICAgICAgICBmaXh0dXJlX3N5bmMsXG4gICAgICAgIHN0dWJfcHJhY3RpY2UsXG4gICAgICAgIHN0dWJfZW50aXR5LFxuICAgICAgICBzY2FmZm9sZF9tb2RlbCxcbiAgICAgICAgc2NhZmZvbGRfbW9kZWxfdGVzdCxcbiAgICAgICAgLy8gc2NhZmZvbGRfdmlld19saXN0LFxuICAgICAgICAvLyBzY2FmZm9sZF92aWV3X2Zvcm0sXG4gICAgICAgIHN5bmMsXG4gICAgICAgIGRldixcbiAgICAgICAgYnVpbGQsXG4gICAgICAgIHN0YXJ0LFxuICAgICAgfSxcbiAgICB9KTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBTb25hbXUuZGVzdHJveSgpO1xuICB9XG59XG5cbmJvb3RzdHJhcCgpLmZpbmFsbHkoYXN5bmMgKCkgPT4ge1xuICBhd2FpdCBGaXh0dXJlTWFuYWdlci5kZXN0cm95KCk7XG59KTtcblxuLyoqXG4gKiBwbnBtIHN5bmMg7ZWY66m0IOyLpO2WieuQmOuKlCDtlajsiJjsnoXri4jri6QuXG4gKiDtlITroZzsoJ3tirjrpbwg7Iux7YGs7ZWp64uI64ukLlxuICovXG5hc3luYyBmdW5jdGlvbiBzeW5jKCkge1xuICBhd2FpdCBTb25hbXUuc3luY2VyLnN5bmMoKTtcbn1cblxuLyoqXG4gKiBwbnBtIGRldiDtlZjrqbQg7Iuk7ZaJ65CY64qUIO2VqOyImOyeheuLiOuLpC5cbiAqIO2UhOuhnOygne2KuOyXkCDrjIDtlbQgSE1SIOyngOybkO2VmOuKlCDqsJzrsJwg7ISc67KE66W8IOudhOybjOykjeuLiOuLpC5cbiAqXG4gKiBUeXBlU2NyaXB066W8IOuwlOuhnCDsi6TtlontlaAg7IiYIOyeiOuPhOuhnSBAc29uYW11LWtpdC90cy1sb2FkZXLrpbwsXG4gKiBITVLsnYQg7KeA7JuQ7ZWY6riwIOychO2VtCBAc29uYW11LWtpdC9obXItaG9va+ydhCBpbXBvcnTtlZjrqbAsXG4gKiDshozsiqTrp7Ug7KeA7JuQ7J2EIOychO2VtCAtLWVuYWJsZS1zb3VyY2UtbWFwcyDtlIzrnpjqt7jrpbwg7Y+s7ZWo7ZWY7JesIOyLpO2Wie2VqeuLiOuLpC5cbiAqXG4gKiDsnbTrlYwgQHNvbmFtdS1raXQvdHMtbG9hZGVy7JmAIEBzb25hbXUta2l0L2htci1ob29r64qUIHNvbmFtdeqwgCDsnpDssrTsoIHsnLzroZwg6rCA7KeA6rOgIOyeiOuKlCBkZXBlbmRlbmN57J6F64uI64ukLlxuICog65iQ7ZWcIOyLpO2WieyXkCDsgqzsmqntlZjripQgQHNvbmFtdS1raXQvaG1yLXJ1bm5lcuuPhCDrp4jssKzqsIDsp4DroZwgc29uYW116rCAIOyekOyytOyggeycvOuhnCDqsIDsp4Dqs6Ag7J6I64qUIGRlcGVuZGVuY3nsnoXri4jri6QuXG4gKiDrlLDrnbzshJwg7IKs7Jqp7J6QIO2UhOuhnOygne2KuOyXkOyEnOuKlCDsnbQg7IS4IO2MqO2CpOyngOulvCDsp4HsoJEg7ISk7LmY7ZWgIO2VhOyalOqwgCDsl4bsirXri4jri6QuXG4gKlxuICogU29uYW11LmluaXQg7JeG7J20IO2YuOy2nOuQoCDqsoPsnYQg7IOB7KCV7ZWY7JesIOq1rO2YhOuQmOyXiOyKteuLiOuLpC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGV2KCkge1xuICBjb25zdCBhcGlSb290ID0gZmluZEFwaVJvb3RQYXRoKCk7XG4gIGNvbnN0IGVudHJ5UG9pbnQgPSBcInNyYy9pbmRleC50c1wiO1xuXG4gIGNvbnNvbGUubG9nKGNoYWxrLnllbGxvdy5ib2xkKFwi8J+agCBTdGFydGluZyBTb25hbXUgZGV2IHNlcnZlci4uLlxcblwiKSk7XG5cbiAgLy8g7J20IHNvbmFtdSDtjKjtgqTsp4DqsIAgZGVwZW5kZW5jaWVz66GcIOqwgOyngOqzoCDsnojripQgQHNvbmFtdS1raXQvaG1yLXJ1bm5lcuydmCBiaW4vcnVuLmpz66W8IOyCrOyaqe2VqeuLiOuLpC5cbiAgLy8g7J20IOqyveuhnCgvYmluL3J1bi5qcynripQgQHNvbmFtdS1raXQvaG1yLXJ1bm5lcuydmCBwYWNrYWdlLmpzb27snZggYmluIO2VhOuTnOyXkCDrqoXsi5zrkJjslrQg7J6I64qUIOq3uOqyg+qzvCDqsJnsirXri4jri6QuXG4gIGNvbnN0IGhvdFJ1bm5lckJpblBhdGggPSBjcmVhdGVSZXF1aXJlKGltcG9ydC5tZXRhLnVybCkucmVzb2x2ZShcbiAgICBcIkBzb25hbXUta2l0L2htci1ydW5uZXIvYmluL3J1bi5qc1wiLFxuICApO1xuXG4gIGNvbnN0IHNlcnZlclByb2Nlc3MgPSBzcGF3bihcbiAgICBwcm9jZXNzLmV4ZWNQYXRoLCAvLyBub2RlXG4gICAgW1xuICAgICAgaG90UnVubmVyQmluUGF0aCwgLy8g7J2066CH6rKMIO2VtOyEnCBob3QtcnVubmVy66W8IOyLpO2Wie2VmOq1rOyalFxuICAgICAgXCItLWNsZWFyLXNjcmVlbj1mYWxzZVwiLCAvLyDsnbTtlZggaG90LXJ1bm5lcuyXkOqyjCDrhJjqsqjspIQg7J247J6Q65Ok7J6F64uI64ukLlxuICAgICAgXCItLW5vZGUtYXJncz0tLWltcG9ydD1zb25hbXUvdHMtbG9hZGVyLXJlZ2lzdGVyXCIsIC8vIFR5cGVTY3JpcHQg7ISc7Y+s7Yq466W8IOychO2VnCDroZzrjZQsXG4gICAgICBcIi0tbm9kZS1hcmdzPS0taW1wb3J0PXNvbmFtdS9obXItaG9vay1yZWdpc3RlclwiLCAvLyBITVLsnYQg7KeA7JuQ7ZWY6riwIOychO2VnCBob29rLFxuICAgICAgXCItLW5vZGUtYXJncz0tLWVuYWJsZS1zb3VyY2UtbWFwc1wiLCAvLyDqt7jrpqzqs6Ag7IaM7Iqk66e1IOyngOybkOydhCDsnITtlZwg7ZSM656Y6re47J6F64uI64ukLlxuICAgICAgXCItLW9uLWtleT1yOnJlc3RhcnQ6UmVzdGFydCBzZXJ2ZXJcIiwgLy8gciDriITrpbTrqbQg7ISc67KEIOyerOyLnOyeke2VmOqyjCDtlbTspJjsmpQuXG4gICAgICBgLS1vbi1rZXk9ZjpzaGVsbChybSAke3BhdGguam9pbihhcGlSb290LCBcInNvbmFtdS5sb2NrXCIpfSk6cmVzdGFydDpGb3JjZSByZXN0YXJ0YCwgLy8gZiDriITrpbTrqbQgc29uYW11LmxvY2sg7YyM7J287J2EIOyngOyasOqzoCDshJzrsoQg7J6s7Iuc7J6R7ZWY6rKMIO2VtOykmOyalC5cblxuICAgICAgXCItLW9uLWtleT1lbnRlcjpzaGVsbChlY2hvIGhpKTpLZXkgYmluZGluZyB0ZXN0XCIsIC8vIGVudGVy66W8IGtleeuhnCDsk7gg7IiYIOyeiOydjOydhCDrs7TsnbTquLAg7JyE7ZWcIO2FjOyKpO2KuOyeheuLiOuLpC5cbiAgICAgIFwiLS1vbi1rZXk9Y3RybCtmIGN0cmwrZjpzaGVsbChnaXQgcHVsbCAmJiBwbnBtIGluc3RhbGwgJiYgcG5wbSAtLWZpbHRlciBzb25hbXUgYnVpbGQgJiYgZWNobyAnU29uYW11IGlzIG5vdyB1cC10by1kYXRlIScpOnJlc3RhcnQ6UHVsbCAmIGluc3RhbGwgJiBidWlsZCAmIHJlc3RhcnRcIiwgLy8gbW9kaWZpZXLsmYDsnZgg7KGw7ZWpLCDqt7jrpqzqs6Ag65GQIOqwnOydmCBjaG9yZOulvCDsgqzsmqntlaAg7IiYIOyeiOydjOydhCDrs7TsnbTquLAg7JyE7ZWcIO2FjOyKpO2KuOyeheuLiOuLpC5cbiAgICAgIGVudHJ5UG9pbnQsIC8vIOuniOyngOunieycvOuhnCDsi6TsoJwg7Iuk7ZaJ7ZWgIOyKpO2BrOumve2KuOydmCDqsr3roZzrpbwg64SY6rKo7KSN64uI64ukLlxuICAgIF0sXG4gICAge1xuICAgICAgY3dkOiBhcGlSb290LFxuICAgICAgc3RkaW86IFwiaW5oZXJpdFwiLFxuICAgICAgZW52OiB7XG4gICAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgICBOT0RFX0VOVjogXCJkZXZlbG9wbWVudFwiLFxuICAgICAgICBIT1Q6IFwieWVzXCIsIC8vIOyWmOqwgCDsnojslrTslbwgSE1S7J20IO2ZnOyEse2ZlOuQqeuLiOuLpC5cbiAgICAgICAgQVBJX1JPT1RfUEFUSDogYXBpUm9vdCwgLy8g7J20IOqyveuhnOqwgCBobXItaG9va+ydmCDro6jtirgg65SU66CJ7Yag66as6rCAIOuQqeuLiOuLpC5cbiAgICAgIH0sXG4gICAgfSxcbiAgKTtcblxuICAvLyDsooXro4wg7LKY66asXG4gIGNvbnN0IGNsZWFudXAgPSAoKSA9PiB7XG4gICAgY29uc29sZS5sb2coY2hhbGsueWVsbG93KFwiXFxuXFxu8J+RiyBTaHV0dGluZyBkb3duLi4uXCIpKTtcbiAgICBzZXJ2ZXJQcm9jZXNzLmtpbGwoXCJTSUdURVJNXCIpO1xuICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgfTtcblxuICBwcm9jZXNzLm9uKFwiU0lHSU5UXCIsIGNsZWFudXApO1xuICBwcm9jZXNzLm9uKFwiU0lHVEVSTVwiLCBjbGVhbnVwKTtcblxuICBzZXJ2ZXJQcm9jZXNzLm9uKFwiZXhpdFwiLCAoY29kZSkgPT4ge1xuICAgIGlmIChjb2RlICE9PSAwKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGNoYWxrLnJlZChg4p2MIFNlcnZlciBleGl0ZWQgd2l0aCBjb2RlICR7Y29kZX1gKSk7XG4gICAgICBwcm9jZXNzLmV4aXQoY29kZSB8fCAxKTtcbiAgICB9XG4gIH0pO1xufVxuXG4vKipcbiAqIHBucG0gYnVpbGQg7ZWY66m0IOyLpO2WieuQmOuKlCDtlajsiJjsnoXri4jri6QuXG4gKiDtlITroZzsoJ3tirjrpbwg67mM65Oc7ZWp64uI64ukLlxuICpcbiAqIOu5jOuTnOyXkCDtlYTsmpTtlZwgLnN3Y3Jj64qUIO2UhOuhnOygne2KuCDro6jtirjsl5DshJwg7LC+6rOgLCDsl4bsnLzrqbQgc29uYW116rCAIOq0gOumrO2VmOuKlCAuc3djcmMucHJvamVjdC1kZWZhdWx066W8IOyCrOyaqe2VqeuLiOuLpC5cbiAqXG4gKiDsi6TsoJwg67mM65OcIO2DgOqynyjslYTti7DtjKntirgp6rO8IOuPmeyekeydgCBidWlsZC1jb25maWcudHPsl5Ag7KCV7J2Y65CY7Ja0IOyeiOyKteuLiOuLpC5cbiAqIOydtCDtlajsiJjripQgYnVpbGQtY29uZmlnLnRz7JeQIOygleydmOuQnCDrj5nsnpHrk6TsnYQg7Iuk7ZaJ7ZW07KO864qUIOyXre2VoOunjCDtlanri4jri6QuXG4gKlxuICogU29uYW11LmluaXQg7JeG7J20IO2YuOy2nOuQoCDqsoPsnYQg7IOB7KCV7ZWY7JesIOq1rO2YhOuQmOyXiOyKteuLiOuLpC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gYnVpbGQoKSB7XG4gIGNvbnN0IGFwcFJvb3QgPSBmaW5kQXBwUm9vdFBhdGgoKTtcblxuICAvLyAuc3djcmMg7YyM7J287J2EIOyngOygle2VqeuLiOuLpC5cbiAgbGV0IHN3Y0ZpbGVQYXRoID0gXCIuc3djcmNcIjtcbiAgdHJ5IHtcbiAgICBpZiAoYXdhaXQgZXhpc3RzKHN3Y0ZpbGVQYXRoKSkge1xuICAgICAgLy8g7IKs7Jqp7J6QIO2UhOuhnOygne2KuOyXkCAuc3djcmPqsIAg7J6I7Jy866m0IOyasOyEoOycvOuhnCDsgqzsmqntlanri4jri6QuXG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5kaW0oXCJVc2luZyAuc3djcmMgZnJvbSBwcm9qZWN0IHJvb3QuLi5cIikpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyDslYTri4jrnbzrqbQgc29uYW116rCAIOq0gOumrO2VmOuKlCAuc3djcmMucHJvamVjdC1kZWZhdWx066W8IOqwgOyguOuLpCDslIHri4jri6QuXG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5kaW0oXCJVc2luZyBkZWZhdWx0IC5zd2NyYyBmcm9tIHNvbmFtdSBwYWNrYWdlLi4uXCIpKTtcbiAgICAgIHN3Y0ZpbGVQYXRoID0gcGF0aC5qb2luKGltcG9ydC5tZXRhLmRpcm5hbWUsIFwiLi5cIiwgXCIuLlwiLCBcIi5zd2NyYy5wcm9qZWN0LWRlZmF1bHRcIik7XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoY2hhbGsucmVkKFwiU2V0dGluZyB1cCBzd2MgY29uZmlnIGZpbGUgZmFpbGVkLlwiKSwgZXJyb3IpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxuXG4gIC8vIEFQSSDtlITroZzsoJ3tirjrpbwg67mM65Oc7ZWp64uI64ukLlxuICBjb25zdCBhcGlTdGFydGVkQXQgPSBEYXRlLm5vdygpO1xuICB0cnkge1xuICAgIGZvciAoY29uc3QgYXJ0aWZhY3Qgb2YgQVBJX0FSVElGQUNUUykge1xuICAgICAgY29uc3QgY3dkID0gcGF0aC5qb2luKGFwcFJvb3QsIGFydGlmYWN0LnByb2plY3RQYXRoKTtcbiAgICAgIHByaW50VGFza0hlYWRlcihhcnRpZmFjdC5uYW1lLCBhcnRpZmFjdC5kZXNjcmlwdGlvbiwgY3dkKTtcblxuICAgICAgYXdhaXQgcnVuQnVpbGRTdGVwcyhhcnRpZmFjdCwgeyBjd2QsIGJ1aWxkQ29tbWFuZEFyZ3M6IHsgY29uZmlnRmlsZVBhdGg6IHN3Y0ZpbGVQYXRoIH0gfSk7XG4gICAgfVxuICAgIHByaW50QnVpbGRTdW1tYXJ5KFwiQVBJXCIsIHRydWUsIERhdGUubm93KCkgLSBhcGlTdGFydGVkQXQpO1xuICB9IGNhdGNoIHtcbiAgICBwcmludEJ1aWxkU3VtbWFyeShcIkFQSVwiLCBmYWxzZSwgRGF0ZS5ub3coKSAtIGFwaVN0YXJ0ZWRBdCk7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG5cbiAgLy8gV2ViIO2UhOuhnOygne2KuOulvCDruYzrk5ztlanri4jri6QuXG4gIGNvbnN0IHdlYlN0YXJ0ZWRBdCA9IERhdGUubm93KCk7XG4gIHRyeSB7XG4gICAgZm9yIChjb25zdCBhcnRpZmFjdCBvZiBXRUJfQVJUSUZBQ1RTKSB7XG4gICAgICBjb25zdCBjd2QgPSBwYXRoLmpvaW4oYXBwUm9vdCwgYXJ0aWZhY3QucHJvamVjdFBhdGgpO1xuICAgICAgcHJpbnRUYXNrSGVhZGVyKGFydGlmYWN0Lm5hbWUsIGFydGlmYWN0LmRlc2NyaXB0aW9uLCBjd2QpO1xuXG4gICAgICBhd2FpdCBydW5CdWlsZFN0ZXBzKGFydGlmYWN0LCB7IGN3ZCwgYnVpbGRDb21tYW5kQXJnczoge30gfSk7XG4gICAgfVxuICAgIHByaW50QnVpbGRTdW1tYXJ5KFwiV2ViXCIsIHRydWUsIERhdGUubm93KCkgLSB3ZWJTdGFydGVkQXQpO1xuICB9IGNhdGNoIHtcbiAgICBwcmludEJ1aWxkU3VtbWFyeShcIldlYlwiLCBmYWxzZSwgRGF0ZS5ub3coKSAtIHdlYlN0YXJ0ZWRBdCk7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG59XG5cbi8qKlxuICogcHJlLWJ1aWxkLCBidWlsZCwgcG9zdC1idWlsZCDri6jqs4Trpbwg7Iic7LCo7KCB7Jy866GcIOyLpO2Wie2VqeuLiOuLpC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcnVuQnVpbGRTdGVwczxUPihcbiAgYXJ0aWZhY3Q6IEJ1aWxkQXJ0aWZhY3Q8VD4sXG4gIG9wdGlvbnM6IHsgY3dkOiBzdHJpbmc7IGJ1aWxkQ29tbWFuZEFyZ3M6IFQgfSxcbikge1xuICBjb25zdCBzdGVwcyA9IFtcbiAgICB7IG5hbWU6IFwicHJlLWJ1aWxkXCIsIGNtZDogYXJ0aWZhY3QucHJlQnVpbGRDb21tYW5kPy4oKSB9LFxuICAgIHsgbmFtZTogXCJidWlsZFwiLCBjbWQ6IGFydGlmYWN0LmJ1aWxkQ29tbWFuZChvcHRpb25zLmJ1aWxkQ29tbWFuZEFyZ3MpIH0sXG4gICAgeyBuYW1lOiBcInBvc3QtYnVpbGRcIiwgY21kOiBhcnRpZmFjdC5wb3N0QnVpbGRDb21tYW5kPy4oKSB9LFxuICBdLmZpbHRlcigoc3RlcCkgPT4gc3RlcC5jbWQpO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RlcHMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBzdGVwID0gc3RlcHNbaV07XG4gICAgY29uc3QgaXNMYXN0ID0gaSA9PT0gc3RlcHMubGVuZ3RoIC0gMTtcblxuICAgIHRyeSB7XG4gICAgICBhc3NlcnQoc3RlcC5jbWQpO1xuICAgICAgcHJpbnRUYXNrU3RhcnQoc3RlcC5uYW1lLCBzdGVwLmNtZCwgaXNMYXN0KTtcbiAgICAgIGF3YWl0IGV4ZWNXaXRoTGluZVByZWZpeChzdGVwLmNtZCwgeyBjd2Q6IG9wdGlvbnMuY3dkIH0pO1xuICAgICAgcHJpbnRUYXNrU3VjY2VzcyhzdGVwLm5hbWUsIGlzTGFzdCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBwcmludFRhc2tGYWlsZWQoc3RlcC5uYW1lLCBpc0xhc3QpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3N0ZXAubmFtZX0gZmFpbGVkYCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogcG5wbSBzdGFydCDtlZjrqbQg7Iuk7ZaJ65CY64qUIO2VqOyImOyeheuLiOuLpC5cbiAqIOu5jOuTnOuQnCDtlITroZzsoJ3tirjrpbwg7Iuk7ZaJ7ZWp64uI64ukLlxuICpcbiAqIOu5jOuTnOuQnCDqsrDqs7zrrLwoZGlzdCDrlJTroInthqDrpqzsnZggaW5kZXguanMg7JeU7Yq466as7Y+s7J247Yq4KeydtCDsl4bri6TrqbQg7Iuk7ZaJ7J2EIOykkeuLqO2VqeuLiOuLpC5cbiAqIOyGjOyKpOuntSDsp4Dsm5Dqs7wgZG90ZW52IOyngOybkOydhCDtj6ztlajtlZjsl6wg7Iuk7ZaJ7ZWp64uI64ukLlxuICpcbiAqIFNvbmFtdS5pbml0IOyXhuydtCDtmLjstpzrkKAg6rKD7J2EIOyDgeygle2VmOyXrCDqtaztmITrkJjsl4jsirXri4jri6QuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHN0YXJ0KCkge1xuICBjb25zdCBhcGlSb290ID0gZmluZEFwaVJvb3RQYXRoKCk7XG4gIGNvbnN0IGVudHJ5UG9pbnQgPSBcImRpc3QvaW5kZXguanNcIjtcblxuICBpZiAoIShhd2FpdCBleGlzdHMoZW50cnlQb2ludCkpKSB7XG4gICAgY29uc29sZS5sb2coY2hhbGsucmVkKGAke2VudHJ5UG9pbnR9IG5vdCBmb3VuZC4gUGxlYXNlIGJ1aWxkIHlvdXIgcHJvamVjdCBmaXJzdC5gKSk7XG4gICAgY29uc29sZS5sb2coY2hhbGsuYmx1ZShcIlJ1bjogeWFybiBzb25hbXUgYnVpbGRcIikpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHsgc3Bhd24gfSA9IGF3YWl0IGltcG9ydChcImNoaWxkX3Byb2Nlc3NcIik7XG4gIGNvbnN0IHNlcnZlclByb2Nlc3MgPSBzcGF3bihcbiAgICBwcm9jZXNzLmV4ZWNQYXRoLFxuICAgIFtcIi0tZW5hYmxlLXNvdXJjZS1tYXBzXCIsIFwiLXJcIiwgXCJkb3RlbnYvY29uZmlnXCIsIGVudHJ5UG9pbnRdLFxuICAgIHtcbiAgICAgIGN3ZDogYXBpUm9vdCxcbiAgICAgIHN0ZGlvOiBcImluaGVyaXRcIixcbiAgICB9LFxuICApO1xuXG4gIHByb2Nlc3Mub24oXCJTSUdJTlRcIiwgKCkgPT4ge1xuICAgIHNlcnZlclByb2Nlc3Mua2lsbChcIlNJR1RFUk1cIik7XG4gICAgcHJvY2Vzcy5leGl0KDApO1xuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2V0dXBNaWdyYXRvcigpIHtcbiAgLy8gbWlncmF0b3JcbiAgbWlncmF0b3IgPSBuZXcgTWlncmF0b3IoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2V0dXBGaXh0dXJlTWFuYWdlcigpIHtcbiAgRml4dHVyZU1hbmFnZXIuaW5pdCgpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBtaWdyYXRlX3J1bigpIHtcbiAgYXdhaXQgc2V0dXBNaWdyYXRvcigpO1xuXG4gIGF3YWl0IG1pZ3JhdG9yLnJ1bkFjdGlvbihcbiAgICBcImFwcGx5XCIsXG4gICAgT2JqZWN0LmtleXMoU29uYW11LmRiQ29uZmlnKSBhcyAoa2V5b2YgU29uYW11REJDb25maWcpW10gLyrsi7kg64ukISovLFxuICApO1xufVxuXG5hc3luYyBmdW5jdGlvbiBtaWdyYXRlX3N0YXR1cygpIHtcbiAgYXdhaXQgc2V0dXBNaWdyYXRvcigpO1xuXG4gIGNvbnN0IHN0YXR1cyA9IGF3YWl0IG1pZ3JhdG9yLmdldFN0YXR1cygpO1xuICAvLyBzdGF0dXM7XG4gIGNvbnNvbGUubG9nKHN0YXR1cyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpeHR1cmVfaW5pdCgpIHtcbiAgY29uc3Qgc3JjQ29uZmlnID0gU29uYW11LmRiQ29uZmlnLmRldmVsb3BtZW50X21hc3RlcjtcbiAgY29uc3QgdGFyZ2V0cyA9IFtcbiAgICB7XG4gICAgICBsYWJlbDogXCIoUkVNT1RFKSBGaXh0dXJlIERCXCIsXG4gICAgICBjb25maWc6IFNvbmFtdS5kYkNvbmZpZy5maXh0dXJlLFxuICAgIH0sXG4gICAge1xuICAgICAgbGFiZWw6IFwiKExPQ0FMKSBUZXN0aW5nIERCXCIsXG4gICAgICBjb25maWc6IFNvbmFtdS5kYkNvbmZpZy50ZXN0LFxuICAgICAgdG9Ta2lwOiAoKCkgPT4ge1xuICAgICAgICBjb25zdCByZW1vdGVDb25uID0gU29uYW11LmRiQ29uZmlnLmZpeHR1cmUuY29ubmVjdGlvbiBhcyBLbmV4LkNvbm5lY3Rpb25Db25maWc7XG4gICAgICAgIGNvbnN0IGxvY2FsQ29ubiA9IFNvbmFtdS5kYkNvbmZpZy50ZXN0LmNvbm5lY3Rpb24gYXMgS25leC5Db25uZWN0aW9uQ29uZmlnO1xuICAgICAgICByZXR1cm4gcmVtb3RlQ29ubi5ob3N0ID09PSBsb2NhbENvbm4uaG9zdCAmJiByZW1vdGVDb25uLmRhdGFiYXNlID09PSBsb2NhbENvbm4uZGF0YWJhc2U7XG4gICAgICB9KSgpLFxuICAgIH0sXG4gIF0gYXMge1xuICAgIGxhYmVsOiBzdHJpbmc7XG4gICAgY29uZmlnOiBLbmV4LkNvbmZpZztcbiAgICB0b1NraXA/OiBib29sZWFuO1xuICB9W107XG5cbiAgLy8gMS4g6riw7KSAREIg7Iqk7YKk66eI66W8IOuNpO2UhFxuICBjb25zb2xlLmxvZyhcIkRVTVAuLi5cIik7XG4gIGNvbnN0IGR1bXBGaWxlbmFtZSA9IGAvdG1wL3NvbmFtdS1maXh0dXJlLWluaXQtJHtEYXRlLm5vdygpfS5zcWxgO1xuICBjb25zdCBzcmNDb25uID0gc3JjQ29uZmlnLmNvbm5lY3Rpb24gYXMgS25leC5Db25uZWN0aW9uQ29uZmlnO1xuICBjb25zdCBtaWdyYXRpb25zRHVtcCA9IGAvdG1wL3NvbmFtdS1maXh0dXJlLWluaXQtbWlncmF0aW9ucy0ke0RhdGUubm93KCl9LnNxbGA7XG4gIGV4ZWNTeW5jKFxuICAgIGBteXNxbGR1bXAgLWgke3NyY0Nvbm4uaG9zdH0gLXUke3NyY0Nvbm4udXNlcn0gLXAke3NyY0Nvbm4ucGFzc3dvcmR9IC0tc2luZ2xlLXRyYW5zYWN0aW9uIC1kIC0tbm8tY3JlYXRlLWRiIC0tdHJpZ2dlcnMgJHtzcmNDb25uLmRhdGFiYXNlfSA+ICR7ZHVtcEZpbGVuYW1lfWAsXG4gICk7XG4gIGNvbnN0IF9kYiA9IGtuZXgoc3JjQ29uZmlnKTtcbiAgY29uc3QgW1ttaWdyYXRpb25zXV0gPSBhd2FpdCBfZGIucmF3KFxuICAgIFwiU0VMRUNUIENPVU5UKCopIGFzIGNvdW50IEZST00gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyBXSEVSRSB0YWJsZV9zY2hlbWEgPSA/IEFORCB0YWJsZV9uYW1lID0gJ2tuZXhfbWlncmF0aW9ucydcIixcbiAgICBbc3JjQ29ubi5kYXRhYmFzZV0sXG4gICk7XG4gIGlmIChtaWdyYXRpb25zLmNvdW50ID4gMCkge1xuICAgIGV4ZWNTeW5jKFxuICAgICAgYG15c3FsZHVtcCAtaCR7c3JjQ29ubi5ob3N0fSAtdSR7c3JjQ29ubi51c2VyfSAtcCR7c3JjQ29ubi5wYXNzd29yZH0gLS1zaW5nbGUtdHJhbnNhY3Rpb24gLS1uby1jcmVhdGUtZGIgLS10cmlnZ2VycyAke3NyY0Nvbm4uZGF0YWJhc2V9IGtuZXhfbWlncmF0aW9ucyBrbmV4X21pZ3JhdGlvbnNfbG9jayA+ICR7bWlncmF0aW9uc0R1bXB9YCxcbiAgICApO1xuICB9XG5cbiAgLy8gMi4g64yA7IOBREIg6rCB6rCB7JeQIOuMgO2VmOyXrCDsobTsnqzsl6zrtoAg7ZmV7J24IO2bhCDrtpPquLBcbiAgZm9yIGF3YWl0IChjb25zdCB7IGxhYmVsLCBjb25maWcsIHRvU2tpcCB9IG9mIHRhcmdldHMpIHtcbiAgICBjb25zdCBjb25uID0gY29uZmlnLmNvbm5lY3Rpb24gYXMgS25leC5Db25uZWN0aW9uQ29uZmlnO1xuXG4gICAgaWYgKHRvU2tpcCA9PT0gdHJ1ZSkge1xuICAgICAgY29uc29sZS5sb2coY2hhbGsucmVkKGAke2xhYmVsfTogU2tpcHBlZCFgKSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBkYiA9IGtuZXgoe1xuICAgICAgLi4uY29uZmlnLFxuICAgICAgY29ubmVjdGlvbjoge1xuICAgICAgICAuLi4oKGNvbmZpZy5jb25uZWN0aW9uID8/IHt9KSBhcyBLbmV4LkNvbm5lY3Rpb25Db25maWcpLFxuICAgICAgICBkYXRhYmFzZTogdW5kZWZpbmVkLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBjb25zdCBbW3Jvd11dID0gYXdhaXQgZGIucmF3KGBTSE9XIERBVEFCQVNFUyBMSUtFIFwiJHtjb25uLmRhdGFiYXNlfVwiYCk7XG4gICAgaWYgKHJvdykge1xuICAgICAgY29uc29sZS5sb2coY2hhbGsueWVsbG93KGAke2xhYmVsfTogRGF0YWJhc2UgXCIke2Nvbm4uZGF0YWJhc2V9XCIgQWxyZWFkeSBleGlzdHNgKSk7XG4gICAgICBhd2FpdCBkYi5kZXN0cm95KCk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhgU1lOQyB0byAke2xhYmVsfS4uLmApO1xuICAgIGNvbnN0IG15c3FsQ21kID0gYG15c3FsIC1oJHtjb25uLmhvc3R9IC11JHtjb25uLnVzZXJ9IC1wJHtjb25uLnBhc3N3b3JkfWA7XG4gICAgZXhlY1N5bmMoYCR7bXlzcWxDbWR9IC1lICdEUk9QIERBVEFCQVNFIElGIEVYSVNUUyBcXGAke2Nvbm4uZGF0YWJhc2V9XFxgJ2ApO1xuICAgIGV4ZWNTeW5jKGAke215c3FsQ21kfSAtZSAnQ1JFQVRFIERBVEFCQVNFIFxcYCR7Y29ubi5kYXRhYmFzZX1cXGAnYCk7XG4gICAgZXhlY1N5bmMoYCR7bXlzcWxDbWR9ICR7Y29ubi5kYXRhYmFzZX0gPCAke2R1bXBGaWxlbmFtZX1gKTtcbiAgICBpZiAoYXdhaXQgZXhpc3RzKG1pZ3JhdGlvbnNEdW1wKSkge1xuICAgICAgZXhlY1N5bmMoYCR7bXlzcWxDbWR9ICR7Y29ubi5kYXRhYmFzZX0gPCAke21pZ3JhdGlvbnNEdW1wfWApO1xuICAgIH1cblxuICAgIGF3YWl0IGRiLmRlc3Ryb3koKTtcbiAgfVxuXG4gIGF3YWl0IF9kYi5kZXN0cm95KCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpeHR1cmVfaW1wb3J0KGVudGl0eUlkOiBzdHJpbmcsIHJlY29yZElkczogbnVtYmVyW10pIHtcbiAgYXdhaXQgc2V0dXBGaXh0dXJlTWFuYWdlcigpO1xuXG4gIGF3YWl0IEZpeHR1cmVNYW5hZ2VyLmltcG9ydEZpeHR1cmUoZW50aXR5SWQsIHJlY29yZElkcyk7XG4gIGF3YWl0IEZpeHR1cmVNYW5hZ2VyLnN5bmMoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZml4dHVyZV9zeW5jKCkge1xuICBhd2FpdCBzZXR1cEZpeHR1cmVNYW5hZ2VyKCk7XG5cbiAgYXdhaXQgRml4dHVyZU1hbmFnZXIuc3luYygpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBzdHViX3ByYWN0aWNlKG5hbWU6IHN0cmluZykge1xuICBjb25zdCBwcmFjdGljZURpciA9IHBhdGguam9pbihTb25hbXUuYXBpUm9vdFBhdGgsIFwic3JjXCIsIFwicHJhY3RpY2VzXCIpO1xuICBjb25zdCBmaWxlTmFtZXMgPSBhd2FpdCByZWFkZGlyKHByYWN0aWNlRGlyKTtcblxuICBjb25zdCBtYXhTZXFObyA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgaWYgKCEoYXdhaXQgZXhpc3RzKHByYWN0aWNlRGlyKSkpIHtcbiAgICAgIGF3YWl0IG1rZGlyKHByYWN0aWNlRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBmaWx0ZXJlZFNlcXMgPSBmaWxlTmFtZXNcbiAgICAgIC5maWx0ZXIoKGZpbGVOYW1lKSA9PiBmaWxlTmFtZS5zdGFydHNXaXRoKFwicFwiKSAmJiBmaWxlTmFtZS5lbmRzV2l0aChcIi50c1wiKSlcbiAgICAgIC5tYXAoKGZpbGVOYW1lKSA9PiB7XG4gICAgICAgIGNvbnN0IFssIHNlcU5vXSA9IGZpbGVOYW1lLm1hdGNoKC9ecChbMC05XSspLS8pID8/IFtcIjBcIiwgXCIwXCJdO1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQoc2VxTm8pO1xuICAgICAgfSlcbiAgICAgIC5zb3J0KChhLCBiKSA9PiBiIC0gYSk7XG5cbiAgICBpZiAoZmlsdGVyZWRTZXFzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBmaWx0ZXJlZFNlcXNbMF07XG4gICAgfVxuXG4gICAgcmV0dXJuIDA7XG4gIH0pKCk7XG5cbiAgY29uc3QgY3VycmVudFNlcU5vID0gbWF4U2VxTm8gKyAxO1xuICBjb25zdCBmaWxlTmFtZSA9IGBwJHtjdXJyZW50U2VxTm99LSR7bmFtZX0udHNgO1xuICBjb25zdCBkc3RQYXRoID0gcGF0aC5qb2luKHByYWN0aWNlRGlyLCBmaWxlTmFtZSk7XG5cbiAgY29uc3QgY29kZSA9IFtcbiAgICBgaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcInNvbmFtdVwiO2AsXG4gICAgXCJcIixcbiAgICBgY29uc29sZS5jbGVhcigpO2AsXG4gICAgYGNvbnNvbGUubG9nKFwiJHtmaWxlTmFtZX1cIik7YCxcbiAgICBcIlwiLFxuICAgIGBTb25hbXUucnVuU2NyaXB0KGFzeW5jICgpID0+IHtgLFxuICAgIGAgLy8gVE9ET2AsXG4gICAgYH0pO2AsXG4gICAgXCJcIixcbiAgXS5qb2luKFwiXFxuXCIpO1xuICBhd2FpdCB3cml0ZUZpbGUoZHN0UGF0aCwgY29kZSk7XG5cbiAgZXhlY1N5bmMoYGNvZGUgJHtkc3RQYXRofWApO1xuXG4gIGNvbnN0IHJ1bkNvZGUgPSBgeWFybiBub2RlIC1yIGRvdGVudi9jb25maWcgLS1lbmFibGUtc291cmNlLW1hcHMgZGlzdC9wcmFjdGljZXMvJHtmaWxlTmFtZS5yZXBsYWNlKFxuICAgIFwiLnRzXCIsXG4gICAgXCIuanNcIixcbiAgKX1gO1xuICBjb25zb2xlLmxvZyhgJHtjaGFsay5ibHVlKHJ1bkNvZGUpfSBjb3BpZWQgdG8gY2xpcGJvYXJkLmApO1xuICBleGVjU3luYyhgZWNobyBcIiR7cnVuQ29kZX1cIiB8IHBiY29weWApO1xufVxuXG5hc3luYyBmdW5jdGlvbiBzdHViX2VudGl0eShlbnRpdHlJZDogc3RyaW5nKSB7XG4gIGF3YWl0IFNvbmFtdS5zeW5jZXIuY3JlYXRlRW50aXR5KHsgZW50aXR5SWQsIHRpdGxlOiBlbnRpdHlJZCB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2NhZmZvbGRfbW9kZWwoZW50aXR5SWQ6IHN0cmluZykge1xuICBhd2FpdCBTb25hbXUuc3luY2VyLmdlbmVyYXRlVGVtcGxhdGUoXCJtb2RlbFwiLCB7XG4gICAgZW50aXR5SWQsXG4gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBzY2FmZm9sZF9tb2RlbF90ZXN0KGVudGl0eUlkOiBzdHJpbmcpIHtcbiAgYXdhaXQgU29uYW11LnN5bmNlci5nZW5lcmF0ZVRlbXBsYXRlKFwibW9kZWxfdGVzdFwiLCB7XG4gICAgZW50aXR5SWQsXG4gIH0pO1xufVxuIl0sIm5hbWVzIjpbImNoYWxrIiwiZG90ZW52IiwiY29uZmlnIiwiYXNzZXJ0IiwiZXhlY1N5bmMiLCJzcGF3biIsIm1rZGlyIiwicmVhZGRpciIsIndyaXRlRmlsZSIsImtuZXgiLCJjcmVhdGVSZXF1aXJlIiwicGF0aCIsInByb2Nlc3MiLCJ0c2ljbGkiLCJTb25hbXUiLCJFbnRpdHlNYW5hZ2VyIiwiTWlncmF0b3IiLCJGaXh0dXJlTWFuYWdlciIsImV4ZWNXaXRoTGluZVByZWZpeCIsInByaW50QnVpbGRTdW1tYXJ5IiwicHJpbnRUYXNrRmFpbGVkIiwicHJpbnRUYXNrSGVhZGVyIiwicHJpbnRUYXNrU3RhcnQiLCJwcmludFRhc2tTdWNjZXNzIiwiZXhpc3RzIiwiZmluZEFwaVJvb3RQYXRoIiwiZmluZEFwcFJvb3RQYXRoIiwiQVBJX0FSVElGQUNUUyIsIldFQl9BUlRJRkFDVFMiLCJtaWdyYXRvciIsImJvb3RzdHJhcCIsIm5vdFRvSW5pdCIsImluY2x1ZGVzIiwiYXJndiIsImluaXQiLCJ0eXBlcyIsInR5cGUiLCJuYW1lIiwibWVzc2FnZSIsImNob2ljZXMiLCJnZXRBbGxQYXJlbnRJZHMiLCJtYXAiLCJlbnRpdHlJZCIsInRpdGxlIiwidmFsdWUiLCJhcmdzIiwicnVubmVycyIsIm1pZ3JhdGVfc3RhdHVzIiwibWlncmF0ZV9ydW4iLCJmaXh0dXJlX2luaXQiLCJmaXh0dXJlX2ltcG9ydCIsImZpeHR1cmVfc3luYyIsInN0dWJfcHJhY3RpY2UiLCJzdHViX2VudGl0eSIsInNjYWZmb2xkX21vZGVsIiwic2NhZmZvbGRfbW9kZWxfdGVzdCIsInN5bmMiLCJkZXYiLCJidWlsZCIsInN0YXJ0IiwiZGVzdHJveSIsImZpbmFsbHkiLCJzeW5jZXIiLCJhcGlSb290IiwiZW50cnlQb2ludCIsImNvbnNvbGUiLCJsb2ciLCJ5ZWxsb3ciLCJib2xkIiwiaG90UnVubmVyQmluUGF0aCIsInVybCIsInJlc29sdmUiLCJzZXJ2ZXJQcm9jZXNzIiwiZXhlY1BhdGgiLCJqb2luIiwiY3dkIiwic3RkaW8iLCJlbnYiLCJOT0RFX0VOViIsIkhPVCIsIkFQSV9ST09UX1BBVEgiLCJjbGVhbnVwIiwia2lsbCIsImV4aXQiLCJvbiIsImNvZGUiLCJlcnJvciIsInJlZCIsImFwcFJvb3QiLCJzd2NGaWxlUGF0aCIsImRpbSIsImRpcm5hbWUiLCJhcGlTdGFydGVkQXQiLCJEYXRlIiwibm93IiwiYXJ0aWZhY3QiLCJwcm9qZWN0UGF0aCIsImRlc2NyaXB0aW9uIiwicnVuQnVpbGRTdGVwcyIsImJ1aWxkQ29tbWFuZEFyZ3MiLCJjb25maWdGaWxlUGF0aCIsIndlYlN0YXJ0ZWRBdCIsIm9wdGlvbnMiLCJzdGVwcyIsImNtZCIsInByZUJ1aWxkQ29tbWFuZCIsImJ1aWxkQ29tbWFuZCIsInBvc3RCdWlsZENvbW1hbmQiLCJmaWx0ZXIiLCJzdGVwIiwiaSIsImxlbmd0aCIsImlzTGFzdCIsIkVycm9yIiwiYmx1ZSIsInNldHVwTWlncmF0b3IiLCJzZXR1cEZpeHR1cmVNYW5hZ2VyIiwicnVuQWN0aW9uIiwiT2JqZWN0Iiwia2V5cyIsImRiQ29uZmlnIiwic3RhdHVzIiwiZ2V0U3RhdHVzIiwic3JjQ29uZmlnIiwiZGV2ZWxvcG1lbnRfbWFzdGVyIiwidGFyZ2V0cyIsImxhYmVsIiwiZml4dHVyZSIsInRlc3QiLCJ0b1NraXAiLCJyZW1vdGVDb25uIiwiY29ubmVjdGlvbiIsImxvY2FsQ29ubiIsImhvc3QiLCJkYXRhYmFzZSIsImR1bXBGaWxlbmFtZSIsInNyY0Nvbm4iLCJtaWdyYXRpb25zRHVtcCIsInVzZXIiLCJwYXNzd29yZCIsIl9kYiIsIm1pZ3JhdGlvbnMiLCJyYXciLCJjb3VudCIsImNvbm4iLCJkYiIsInVuZGVmaW5lZCIsInJvdyIsIm15c3FsQ21kIiwicmVjb3JkSWRzIiwiaW1wb3J0Rml4dHVyZSIsInByYWN0aWNlRGlyIiwiYXBpUm9vdFBhdGgiLCJmaWxlTmFtZXMiLCJtYXhTZXFObyIsInJlY3Vyc2l2ZSIsImZpbHRlcmVkU2VxcyIsImZpbGVOYW1lIiwic3RhcnRzV2l0aCIsImVuZHNXaXRoIiwic2VxTm8iLCJtYXRjaCIsInBhcnNlSW50Iiwic29ydCIsImEiLCJiIiwiY3VycmVudFNlcU5vIiwiZHN0UGF0aCIsInJ1bkNvZGUiLCJyZXBsYWNlIiwiY3JlYXRlRW50aXR5IiwiZ2VuZXJhdGVUZW1wbGF0ZSJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBT0EsV0FBVyxRQUFRO0FBQzFCLE9BQU9DLFlBQVksU0FBUztBQUU1QkEsT0FBT0MsTUFBTTtBQUViLE9BQU9DLFlBQVksU0FBUztBQUM1QixTQUFTQyxRQUFRLEVBQUVDLEtBQUssUUFBUSxnQkFBZ0I7QUFDaEQsU0FBU0MsS0FBSyxFQUFFQyxPQUFPLEVBQUVDLFNBQVMsUUFBUSxtQkFBYztBQUN4RCxPQUFPQyxVQUF5QixPQUFPO0FBQ3ZDLFNBQVNDLGFBQWEsUUFBUSxTQUFTO0FBQ3ZDLE9BQU9DLFVBQVUsT0FBTztBQUN4QixPQUFPQyxhQUFhLFVBQVU7QUFDOUIsU0FBU0MsTUFBTSxRQUFRLFNBQVM7QUFDaEMsU0FBU0MsTUFBTSxRQUFRLGtCQUFTO0FBRWhDLFNBQVNDLGFBQWEsUUFBUSw4QkFBMkI7QUFDekQsU0FBU0MsUUFBUSxRQUFRLDJCQUF3QjtBQUNqRCxTQUFTQyxjQUFjLFFBQVEsZ0NBQTZCO0FBQzVELFNBQ0VDLGtCQUFrQixFQUNs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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonamu",
3
- "version": "0.7.34",
3
+ "version": "0.7.35",
4
4
  "description": "Sonamu — TypeScript Fullstack API Framework",
5
5
  "keywords": [
6
6
  "typescript",
@@ -111,9 +111,9 @@
111
111
  "vitest": "^4.0.10",
112
112
  "exceljs": "^4.4.0",
113
113
  "zod": "^4.1.12",
114
- "@sonamu-kit/hmr-hook": "^0.4.1",
115
114
  "@sonamu-kit/hmr-runner": "^0.1.1",
116
115
  "@sonamu-kit/tasks": "^0.1.3",
116
+ "@sonamu-kit/hmr-hook": "^0.4.1",
117
117
  "@sonamu-kit/ts-loader": "^2.1.3"
118
118
  },
119
119
  "devDependencies": {
@@ -1,43 +1,47 @@
1
+ export type BuildArtifact<BuildCommandArgs = {}> = {
2
+ name: string;
3
+ description: string;
4
+ projectPath: string;
5
+ preBuildCommand?: () => string;
6
+ buildCommand: (args: BuildCommandArgs) => string;
7
+ postBuildCommand?: () => string;
8
+ };
9
+
1
10
  /**
2
11
  * API 프로젝트 빌드 산출물에 대한 규칙들.
3
12
  * cli.ts의 build 함수가 이것을 보고 그대로 실행합니다.
4
- *
5
- * 경로(projectPath, outputDir, destDir)는 app root에서 시작하는 상대경로로 작성되어 있습니다.
6
- * 다만 buildCommand는 projectPath를 기준으로 실행됩니다.
7
13
  */
8
- export const API_ARTIFACTS = [
14
+ export const API_ARTIFACTS: BuildArtifact<{ configFilePath: string }>[] = [
9
15
  {
10
16
  name: "API",
11
17
  description: "API 프로젝트 빌드 산출물",
12
18
  projectPath: "api",
13
- buildCommand: (configFilePath: string) =>
19
+ preBuildCommand: () => "rm -rf dist",
20
+ buildCommand: ({ configFilePath }) =>
14
21
  `tsc --noEmit && swc src -d dist --config-file ${configFilePath} --strip-leading-paths`,
15
- outputDir: "api/dist",
16
22
  },
17
23
  ];
18
24
 
19
25
  /**
20
26
  * 웹 프로젝트 빌드 산출물에 대한 규칙들.
21
27
  * cli.ts의 build 함수가 이것을 보고 그대로 실행합니다.
22
- *
23
- * 경로(projectPath, outputDir, destDir)는 app root에서 시작하는 상대경로로 작성되어 있습니다.
24
- * 다만 buildCommand는 projectPath를 기준(cwd)으로 실행됩니다.
25
28
  */
26
- export const WEB_ARTIFACTS = [
29
+ export const WEB_ARTIFACTS: BuildArtifact[] = [
27
30
  {
28
31
  name: "Web Client",
29
32
  description: "Web 프로젝트 클라이언트 빌드 산출물",
30
33
  projectPath: "web",
31
- buildCommand: () => "tsc && vite build --outDir dist/client",
32
- outputDir: "web/dist/client",
33
- destDir: "api/public/web",
34
+ preBuildCommand: () => "rm -rf dist/client && rm -rf ../api/public/web",
35
+ buildCommand: () => "tsc --noEmit && vite build --outDir dist/client",
36
+ postBuildCommand: () => "mkdir -p ../api/public/web && cp -r dist/client/* ../api/public/web",
34
37
  },
35
38
  {
36
39
  name: "Web Server",
37
40
  description: "Web 프로젝트 서버 빌드 산출물",
38
41
  projectPath: "web",
39
- buildCommand: () => "vite build --ssr src/entry-server.generated.tsx --outDir dist/server",
40
- outputDir: "web/dist/server",
41
- destDir: "api/dist/ssr",
42
+ preBuildCommand: () => "rm -rf dist/server", // api/dist/ssr은 안 지웁니다! 거기는 api의 빌드 결과물이 들어있음!
43
+ buildCommand: () =>
44
+ "tsc --noEmit && vite build --ssr src/entry-server.generated.tsx --outDir dist/server",
45
+ postBuildCommand: () => "cp -r dist/server/* ../api/dist/ssr",
42
46
  },
43
47
  ];
package/src/bin/cli.ts CHANGED
@@ -3,8 +3,9 @@ import dotenv from "dotenv";
3
3
 
4
4
  dotenv.config();
5
5
 
6
+ import assert from "assert";
6
7
  import { execSync, spawn } from "child_process";
7
- import { cp, mkdir, readdir, rm, writeFile } from "fs/promises";
8
+ import { mkdir, readdir, writeFile } from "fs/promises";
8
9
  import knex, { type Knex } from "knex";
9
10
  import { createRequire } from "module";
10
11
  import path from "path";
@@ -20,13 +21,12 @@ import {
20
21
  printBuildSummary,
21
22
  printTaskFailed,
22
23
  printTaskHeader,
23
- printTaskSkipped,
24
24
  printTaskStart,
25
25
  printTaskSuccess,
26
26
  } from "../utils/console-util";
27
27
  import { exists } from "../utils/fs-utils";
28
28
  import { findApiRootPath, findAppRootPath } from "../utils/utils";
29
- import { API_ARTIFACTS, WEB_ARTIFACTS } from "./build-config";
29
+ import { API_ARTIFACTS, type BuildArtifact, WEB_ARTIFACTS } from "./build-config";
30
30
 
31
31
  let migrator: Migrator;
32
32
 
@@ -192,32 +192,6 @@ async function dev() {
192
192
  async function build() {
193
193
  const appRoot = findAppRootPath();
194
194
 
195
- // 출력 디렉토리를 제거합니다.
196
- try {
197
- for (const artifact of API_ARTIFACTS) {
198
- if (await exists(path.join(appRoot, artifact.outputDir))) {
199
- // API 프로젝트 자체의 빌드 결과물
200
- await rm(path.join(appRoot, artifact.outputDir), { recursive: true, force: true });
201
- }
202
- }
203
-
204
- for (const artifact of WEB_ARTIFACTS) {
205
- if (await exists(path.join(appRoot, artifact.outputDir))) {
206
- // Web 프로젝트 자체의 빌드 결과물
207
- await rm(path.join(appRoot, artifact.outputDir), { recursive: true, force: true });
208
- }
209
- if (await exists(path.join(appRoot, artifact.destDir))) {
210
- // API 프로젝트로 복사되어 온 Web 빌드 결과물
211
- await rm(path.join(appRoot, artifact.destDir), { recursive: true, force: true });
212
- }
213
- }
214
-
215
- console.log(chalk.green("\nBuild artifacts removed successfully."));
216
- } catch (error) {
217
- console.error(chalk.red("Remove build directories failed."), error);
218
- process.exit(1);
219
- }
220
-
221
195
  // .swcrc 파일을 지정합니다.
222
196
  let swcFilePath = ".swcrc";
223
197
  try {
@@ -239,20 +213,9 @@ async function build() {
239
213
  try {
240
214
  for (const artifact of API_ARTIFACTS) {
241
215
  const cwd = path.join(appRoot, artifact.projectPath);
242
- const cmd = artifact.buildCommand(swcFilePath);
243
-
244
216
  printTaskHeader(artifact.name, artifact.description, cwd);
245
217
 
246
- // build
247
- try {
248
- printTaskStart("build", cmd, true);
249
- // cmd를 spawn해서 build를 수행하는데, 이때 명령의 출력(stdout, stderr) 라인 앞에 들여쓰기를 붙여서 출력합니다.
250
- await execWithLinePrefix(cmd, { cwd });
251
- printTaskSuccess("build", true);
252
- } catch {
253
- printTaskFailed("build", true);
254
- throw new Error("build failed");
255
- }
218
+ await runBuildSteps(artifact, { cwd, buildCommandArgs: { configFilePath: swcFilePath } });
256
219
  }
257
220
  printBuildSummary("API", true, Date.now() - apiStartedAt);
258
221
  } catch {
@@ -265,38 +228,9 @@ async function build() {
265
228
  try {
266
229
  for (const artifact of WEB_ARTIFACTS) {
267
230
  const cwd = path.join(appRoot, artifact.projectPath);
268
- const cmd = artifact.buildCommand();
269
- const outputDirFull = path.join(appRoot, artifact.outputDir);
270
- const destDirFull = path.join(appRoot, artifact.destDir);
271
-
272
231
  printTaskHeader(artifact.name, artifact.description, cwd);
273
232
 
274
- // build
275
- try {
276
- printTaskStart("build", cmd);
277
- // cmd를 spawn해서 build를 수행하는데, 이때 명령의 출력(stdout, stderr) 라인 앞에 들여쓰기를 붙여서 출력합니다.
278
- await execWithLinePrefix(cmd, { cwd });
279
- printTaskSuccess("build");
280
- } catch {
281
- printTaskFailed("build");
282
- printTaskSkipped("copy", true);
283
- throw new Error("build failed");
284
- }
285
-
286
- // copy
287
- try {
288
- printTaskStart("copy", `${artifact.outputDir} → ${artifact.destDir}`, true);
289
- // Web 아티팩트는 빌드 결과물(outputDir)을 다른 위치(destDir)로 복사하는 작업이 추가로 필요합니다.
290
- if (await exists(destDirFull)) {
291
- await rm(destDirFull, { recursive: true, force: true });
292
- }
293
- await mkdir(destDirFull, { recursive: true });
294
- await cp(outputDirFull, destDirFull, { recursive: true });
295
- printTaskSuccess("copy", true);
296
- } catch {
297
- printTaskFailed("copy", true);
298
- throw new Error("copy failed");
299
- }
233
+ await runBuildSteps(artifact, { cwd, buildCommandArgs: {} });
300
234
  }
301
235
  printBuildSummary("Web", true, Date.now() - webStartedAt);
302
236
  } catch {
@@ -305,6 +239,35 @@ async function build() {
305
239
  }
306
240
  }
307
241
 
242
+ /**
243
+ * pre-build, build, post-build 단계를 순차적으로 실행합니다.
244
+ */
245
+ async function runBuildSteps<T>(
246
+ artifact: BuildArtifact<T>,
247
+ options: { cwd: string; buildCommandArgs: T },
248
+ ) {
249
+ const steps = [
250
+ { name: "pre-build", cmd: artifact.preBuildCommand?.() },
251
+ { name: "build", cmd: artifact.buildCommand(options.buildCommandArgs) },
252
+ { name: "post-build", cmd: artifact.postBuildCommand?.() },
253
+ ].filter((step) => step.cmd);
254
+
255
+ for (let i = 0; i < steps.length; i++) {
256
+ const step = steps[i];
257
+ const isLast = i === steps.length - 1;
258
+
259
+ try {
260
+ assert(step.cmd);
261
+ printTaskStart(step.name, step.cmd, isLast);
262
+ await execWithLinePrefix(step.cmd, { cwd: options.cwd });
263
+ printTaskSuccess(step.name, isLast);
264
+ } catch {
265
+ printTaskFailed(step.name, isLast);
266
+ throw new Error(`${step.name} failed`);
267
+ }
268
+ }
269
+ }
270
+
308
271
  /**
309
272
  * pnpm start 하면 실행되는 함수입니다.
310
273
  * 빌드된 프로젝트를 실행합니다.