@sdkgen/node-runtime 0.0.0-dev.20230106165109 → 0.0.0-dev.20230109134521

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.
Files changed (41) hide show
  1. package/dist/spec/error.spec.js +3 -4
  2. package/dist/spec/rest/rest.spec.js +24 -24
  3. package/dist/spec/runtime/errors.spec.js +15 -14
  4. package/dist/spec/runtime/middleware.spec.js +15 -14
  5. package/dist/spec/simple/legacyNodeClient.js +6 -32
  6. package/dist/spec/simple/simple.spec.js +27 -28
  7. package/dist/spec/types.js +27 -28
  8. package/dist/spec/types.spec.js +54 -55
  9. package/dist/src/api-config.js +4 -8
  10. package/dist/src/context.js +2 -2
  11. package/dist/src/encode-decode.js +12 -50
  12. package/dist/src/error.js +4 -9
  13. package/dist/src/execute.js +12 -14
  14. package/dist/src/http-client.js +25 -27
  15. package/dist/src/http-server.js +160 -170
  16. package/dist/src/index.js +8 -18
  17. package/dist/src/new-interface.js +200 -0
  18. package/dist/src/swagger.js +126 -115
  19. package/dist/src/test-wrapper.js +25 -23
  20. package/dist/src/utils.js +2 -5
  21. package/package.json +27 -22
  22. package/dist/spec/error.spec.d.ts +0 -1
  23. package/dist/spec/rest/rest.spec.d.ts +0 -1
  24. package/dist/spec/runtime/errors.spec.d.ts +0 -1
  25. package/dist/spec/runtime/middleware.spec.d.ts +0 -1
  26. package/dist/spec/simple/legacyNodeClient.d.ts +0 -17
  27. package/dist/spec/simple/simple.spec.d.ts +0 -1
  28. package/dist/spec/types.d.ts +0 -1
  29. package/dist/spec/types.spec.d.ts +0 -1
  30. package/dist/src/api-config.d.ts +0 -15
  31. package/dist/src/context.d.ts +0 -38
  32. package/dist/src/encode-decode.d.ts +0 -32
  33. package/dist/src/error.d.ts +0 -18
  34. package/dist/src/execute.d.ts +0 -3
  35. package/dist/src/http-client.d.ts +0 -17
  36. package/dist/src/http-server.d.ts +0 -37
  37. package/dist/src/index.d.ts +0 -7
  38. package/dist/src/swagger.d.ts +0 -2
  39. package/dist/src/test-wrapper.d.ts +0 -3
  40. package/dist/src/utils.d.ts +0 -6
  41. package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/src/index.js CHANGED
@@ -1,18 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.apiTestWrapper = exports.SdkgenHttpServer = exports.SdkgenHttpClient = exports.SdkgenErrorWithData = exports.SdkgenError = exports.Fatal = exports.encode = exports.decode = exports.BaseApiConfig = void 0;
4
- var api_config_1 = require("./api-config");
5
- Object.defineProperty(exports, "BaseApiConfig", { enumerable: true, get: function () { return api_config_1.BaseApiConfig; } });
6
- var encode_decode_1 = require("./encode-decode");
7
- Object.defineProperty(exports, "decode", { enumerable: true, get: function () { return encode_decode_1.decode; } });
8
- Object.defineProperty(exports, "encode", { enumerable: true, get: function () { return encode_decode_1.encode; } });
9
- var error_1 = require("./error");
10
- Object.defineProperty(exports, "Fatal", { enumerable: true, get: function () { return error_1.Fatal; } });
11
- Object.defineProperty(exports, "SdkgenError", { enumerable: true, get: function () { return error_1.SdkgenError; } });
12
- Object.defineProperty(exports, "SdkgenErrorWithData", { enumerable: true, get: function () { return error_1.SdkgenErrorWithData; } });
13
- var http_client_1 = require("./http-client");
14
- Object.defineProperty(exports, "SdkgenHttpClient", { enumerable: true, get: function () { return http_client_1.SdkgenHttpClient; } });
15
- var http_server_1 = require("./http-server");
16
- Object.defineProperty(exports, "SdkgenHttpServer", { enumerable: true, get: function () { return http_server_1.SdkgenHttpServer; } });
17
- var test_wrapper_1 = require("./test-wrapper");
18
- Object.defineProperty(exports, "apiTestWrapper", { enumerable: true, get: function () { return test_wrapper_1.apiTestWrapper; } });
1
+ export { BaseApiConfig } from "./api-config.js";
2
+ export { decode, encode } from "./encode-decode.js";
3
+ export { Fatal, SdkgenError, SdkgenErrorWithData } from "./error.js";
4
+ export { SdkgenHttpClient } from "./http-client.js";
5
+ export { SdkgenHttpServer } from "./http-server.js";
6
+ export { apiTestWrapper } from "./test-wrapper.js";
7
+ export { startSdkgenServer, createSdkgenEndpoint, createSdkgenType, createSdkgenTestClient, Uuid, Int, UInt, encodeValue, decodeValue, } from "./new-interface.js";
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBR2hELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDcEQsT0FBTyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDckUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25ELE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsb0JBQW9CLEVBQ3BCLGdCQUFnQixFQUNoQixzQkFBc0IsRUFDdEIsSUFBSSxFQUNKLEdBQUcsRUFDSCxJQUFJLEVBQ0osV0FBVyxFQUNYLFdBQVcsR0FJWixNQUFNLG9CQUFvQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgQmFzZUFwaUNvbmZpZyB9IGZyb20gXCIuL2FwaS1jb25maWcuanNcIjtcbmV4cG9ydCB0eXBlIHsgTWlkZGxld2FyZSBhcyBTZGtnZW5NaWRkbGV3YXJlIH0gZnJvbSBcIi4vYXBpLWNvbmZpZy5qc1wiO1xuZXhwb3J0IHR5cGUgeyBDb250ZXh0LCBDb250ZXh0UmVwbHksIENvbnRleHRSZXF1ZXN0IH0gZnJvbSBcIi4vY29udGV4dC5qc1wiO1xuZXhwb3J0IHsgZGVjb2RlLCBlbmNvZGUgfSBmcm9tIFwiLi9lbmNvZGUtZGVjb2RlLmpzXCI7XG5leHBvcnQgeyBGYXRhbCwgU2RrZ2VuRXJyb3IsIFNka2dlbkVycm9yV2l0aERhdGEgfSBmcm9tIFwiLi9lcnJvci5qc1wiO1xuZXhwb3J0IHsgU2RrZ2VuSHR0cENsaWVudCB9IGZyb20gXCIuL2h0dHAtY2xpZW50LmpzXCI7XG5leHBvcnQgeyBTZGtnZW5IdHRwU2VydmVyIH0gZnJvbSBcIi4vaHR0cC1zZXJ2ZXIuanNcIjtcbmV4cG9ydCB7IGFwaVRlc3RXcmFwcGVyIH0gZnJvbSBcIi4vdGVzdC13cmFwcGVyLmpzXCI7XG5leHBvcnQge1xuICBzdGFydFNka2dlblNlcnZlcixcbiAgY3JlYXRlU2RrZ2VuRW5kcG9pbnQsXG4gIGNyZWF0ZVNka2dlblR5cGUsXG4gIGNyZWF0ZVNka2dlblRlc3RDbGllbnQsXG4gIFV1aWQsXG4gIEludCxcbiAgVUludCxcbiAgZW5jb2RlVmFsdWUsXG4gIGRlY29kZVZhbHVlLFxuICB0eXBlIFR5cGVTcGVjLFxuICB0eXBlIEdlbmVyYXRlVHlwaW5nLFxuICB0eXBlIEdlbmVyYXRlVHlwaW5nRnJvbUZpZWxkcyxcbn0gZnJvbSBcIi4vbmV3LWludGVyZmFjZS5qc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIERlZmF1bHRFeHRyYUNvbnRleHQge31cbiJdfQ==
@@ -0,0 +1,200 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
3
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
4
+ /* eslint-disable @typescript-eslint/no-explicit-any */
5
+ import { inspect } from "util";
6
+ import Decimal from "decimal.js";
7
+ import { BaseApiConfig } from "./api-config.js";
8
+ import { decode, encode } from "./encode-decode.js";
9
+ import { SdkgenHttpServer } from "./http-server.js";
10
+ import { apiTestWrapper } from "./test-wrapper.js";
11
+ // eslint-disable-next-line @typescript-eslint/naming-convention
12
+ export const Uuid = Symbol("Uuid");
13
+ // eslint-disable-next-line @typescript-eslint/naming-convention
14
+ export const Int = Symbol("Int");
15
+ // eslint-disable-next-line @typescript-eslint/naming-convention
16
+ export const UInt = Symbol("UInt");
17
+ // eslint-disable-next-line @typescript-eslint/naming-convention
18
+ export const Cpf = Symbol("Cpf");
19
+ // eslint-disable-next-line @typescript-eslint/naming-convention
20
+ export const Cnpj = Symbol("Cnpj");
21
+ class ApiConfig extends BaseApiConfig {
22
+ constructor(astJson, fn, middlewares) {
23
+ super();
24
+ this.astJson = astJson;
25
+ this.fn = fn;
26
+ this.middlewares = middlewares;
27
+ }
28
+ }
29
+ class CustomTypeBaseClass {
30
+ }
31
+ CustomTypeBaseClass.mark = Symbol();
32
+ CustomTypeBaseClass.fields = {};
33
+ function getSdkgenType(type, registry) {
34
+ let normalizedType;
35
+ if (type === String ||
36
+ type === Uuid ||
37
+ type === Number ||
38
+ type === Boolean ||
39
+ type === BigInt ||
40
+ type === Int ||
41
+ type === UInt ||
42
+ type === Date ||
43
+ type === Buffer ||
44
+ type === Decimal ||
45
+ type === Cpf ||
46
+ type === Cnpj ||
47
+ type === URL ||
48
+ type === undefined) {
49
+ normalizedType = { type };
50
+ }
51
+ else if (type instanceof Function && type.mark === CustomTypeBaseClass.mark) {
52
+ normalizedType = { type };
53
+ }
54
+ else if (Array.isArray(type)) {
55
+ normalizedType = { type: Array, of: type[0] };
56
+ }
57
+ else {
58
+ normalizedType = type;
59
+ }
60
+ if (normalizedType.nullable === true) {
61
+ delete normalizedType.nullable;
62
+ return `${getSdkgenType(normalizedType, registry)}?`;
63
+ }
64
+ if (normalizedType.type === String) {
65
+ return "string";
66
+ }
67
+ else if (normalizedType.type === Number) {
68
+ return "float";
69
+ }
70
+ else if (normalizedType.type === Int) {
71
+ return "int";
72
+ }
73
+ else if (normalizedType.type === UInt) {
74
+ return "uint";
75
+ }
76
+ else if (normalizedType.type === Uuid) {
77
+ return "uuid";
78
+ }
79
+ else if (normalizedType.type === Boolean) {
80
+ return "bool";
81
+ }
82
+ else if (normalizedType.type === BigInt) {
83
+ return "bigint";
84
+ }
85
+ else if (normalizedType.type === Date) {
86
+ return "datetime";
87
+ }
88
+ else if (normalizedType.type === Buffer) {
89
+ return "bytes";
90
+ }
91
+ else if (normalizedType.type === Decimal) {
92
+ return "decimal";
93
+ }
94
+ else if (normalizedType.type === Cpf) {
95
+ return "cpf";
96
+ }
97
+ else if (normalizedType.type === Cnpj) {
98
+ return "cnpj";
99
+ }
100
+ else if (normalizedType.type === URL) {
101
+ return "url";
102
+ }
103
+ else if (normalizedType.type === undefined) {
104
+ return "void";
105
+ }
106
+ else if (normalizedType.type === Array) {
107
+ return `${getSdkgenType(normalizedType.of, registry)}[]`;
108
+ }
109
+ else if (normalizedType.type instanceof Function && normalizedType.type.mark === CustomTypeBaseClass.mark) {
110
+ for (let counter = 1;; ++counter) {
111
+ const name = counter === 1 ? `${normalizedType.type.name}` : `${normalizedType.type.name}${counter}`;
112
+ const existing = registry.get(name);
113
+ if (existing === normalizedType.type) {
114
+ return name;
115
+ }
116
+ else if (existing) {
117
+ continue;
118
+ }
119
+ registry.set(name, normalizedType.type);
120
+ return name;
121
+ }
122
+ }
123
+ throw new Error(`Unhandled sdkgen type: ${inspect(normalizedType)}`);
124
+ }
125
+ function getTypeTableFromRegistry(registry) {
126
+ const typeTable = {};
127
+ let newNamesFound = true;
128
+ while (newNamesFound) {
129
+ newNamesFound = false;
130
+ for (const [name, type] of registry) {
131
+ if (name in typeTable) {
132
+ continue;
133
+ }
134
+ newNamesFound = true;
135
+ typeTable[name] = Object.fromEntries(Object.entries(type.fields).map(([fieldName, fieldType]) => [fieldName, getSdkgenType(fieldType, registry)]));
136
+ }
137
+ }
138
+ return typeTable;
139
+ }
140
+ function createApiConfig(config) {
141
+ const astJson = {
142
+ functionTable: {},
143
+ typeTable: {},
144
+ errors: [],
145
+ annotations: {},
146
+ };
147
+ const handlers = {};
148
+ const registry = new Map();
149
+ for (const [name, endpoint] of Object.entries(config.endpoints)) {
150
+ astJson.functionTable[name] = {
151
+ args: Object.fromEntries(Object.entries(endpoint.options.args ?? {}).map(([arg, type]) => [arg, getSdkgenType(type, registry)])),
152
+ ret: getSdkgenType(endpoint.options.return, registry),
153
+ };
154
+ handlers[name] = endpoint.handler;
155
+ }
156
+ astJson.typeTable = getTypeTableFromRegistry(registry);
157
+ return new ApiConfig(astJson, handlers, config.middlewares ?? []);
158
+ }
159
+ export async function startSdkgenServer(config) {
160
+ const api = createApiConfig(config);
161
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
162
+ const server = new SdkgenHttpServer(api, config.extraContext);
163
+ await server.listen(config.port ?? 80);
164
+ }
165
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
166
+ export function createSdkgenTestClient(config) {
167
+ const api = createApiConfig(config);
168
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
169
+ return apiTestWrapper(api, config.extraContext).fn;
170
+ }
171
+ export function createSdkgenType(fields) {
172
+ var _a;
173
+ const customType = (_a = class extends CustomTypeBaseClass {
174
+ },
175
+ _a.fields = fields,
176
+ _a);
177
+ return customType;
178
+ }
179
+ class SdkgenEndpoint {
180
+ constructor(options, handler) {
181
+ this.options = options;
182
+ this.handler = handler;
183
+ }
184
+ }
185
+ export function createSdkgenEndpoint(options, handler) {
186
+ return new SdkgenEndpoint(options, handler);
187
+ }
188
+ export function encodeValue(type, value) {
189
+ const registry = new Map();
190
+ const legacyType = getSdkgenType(type, registry);
191
+ const typeTable = getTypeTableFromRegistry(registry);
192
+ return encode(typeTable, "", legacyType, value);
193
+ }
194
+ export function decodeValue(type, value) {
195
+ const registry = new Map();
196
+ const legacyType = getSdkgenType(type, registry);
197
+ const typeTable = getTypeTableFromRegistry(registry);
198
+ return decode(typeTable, "", legacyType, value);
199
+ }
200
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV3LWludGVyZmFjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9uZXctaW50ZXJmYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDREQUE0RDtBQUM1RCwwREFBMEQ7QUFDMUQsK0RBQStEO0FBQy9ELHVEQUF1RDtBQUN2RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRy9CLE9BQU8sT0FBTyxNQUFNLFlBQVksQ0FBQztBQUdqQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFaEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVwRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFHbkQsZ0VBQWdFO0FBQ2hFLE1BQU0sQ0FBQyxNQUFNLElBQUksR0FBa0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2xELGdFQUFnRTtBQUNoRSxNQUFNLENBQUMsTUFBTSxHQUFHLEdBQWtCLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNoRCxnRUFBZ0U7QUFDaEUsTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUFrQixNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDbEQsZ0VBQWdFO0FBQ2hFLE1BQU0sQ0FBQyxNQUFNLEdBQUcsR0FBa0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hELGdFQUFnRTtBQUNoRSxNQUFNLENBQUMsTUFBTSxJQUFJLEdBQWtCLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUVsRCxNQUFNLFNBQW1DLFNBQVEsYUFBNEI7SUFDM0UsWUFDUyxPQUE4QixFQUM5QixFQUdOLEVBQ2UsV0FBNkM7UUFFN0QsS0FBSyxFQUFFLENBQUM7UUFQRCxZQUFPLEdBQVAsT0FBTyxDQUF1QjtRQUM5QixPQUFF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U0FBTSxHQUFHLE1BQU87V0FDeEIsQ0FBQztJQUVGLE9BQU8sVUFDNEIsQ0FBQztBQUN0QyxDQUFDO0FBK0ZELE1BQU0sY0FBYztJQUNsQixZQUNrQixPQUEyQixFQUMzQixPQUFnRjtRQURoRixZQUFPLEdBQVAsT0FBTyxDQUFvQjtRQUMzQixZQUFPLEdBQVAsT0FBTyxDQUF5RTtJQUMvRixDQUFDO0NBQ0w7QUFVRCxNQUFNLFVBQVUsb0JBQW9CLENBQ2xDLE9BQWdCLEVBQ2hCLE9BQXdIO0lBRXhILE9BQU8sSUFBSSxjQUFjLENBQXVELE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztBQUNwRyxDQUFDO0FBWUQsTUFBTSxVQUFVLFdBQVcsQ0FBd0IsSUFBVSxFQUFFLEtBQTJCO0lBQ3hGLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxFQUFzQyxDQUFDO0lBRS9ELE1BQU0sVUFBVSxHQUFHLGFBQWEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDakQsTUFBTSxTQUFTLEdBQUcsd0JBQXdCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFckQsT0FBTyxNQUFNLENBQUMsU0FBUyxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDbEQsQ0FBQztBQUVELE1BQU0sVUFBVSxXQUFXLENBQXdCLElBQVUsRUFBRSxLQUFnQjtJQUM3RSxNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBc0MsQ0FBQztJQUUvRCxNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2pELE1BQU0sU0FBUyxHQUFHLHdCQUF3QixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRXJELE9BQU8sTUFBTSxDQUFDLFNBQVMsRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBeUIsQ0FBQztBQUMxRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hc3NpZ25tZW50ICovXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFyZ3VtZW50ICovXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLW1lbWJlci1hY2Nlc3MgKi9cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi9cbmltcG9ydCB7IGluc3BlY3QgfSBmcm9tIFwidXRpbFwiO1xuXG5pbXBvcnQgdHlwZSB7IEFzdEpzb24gfSBmcm9tIFwiQHNka2dlbi9wYXJzZXJcIjtcbmltcG9ydCBEZWNpbWFsIGZyb20gXCJkZWNpbWFsLmpzXCI7XG5cbmltcG9ydCB0eXBlIHsgTWlkZGxld2FyZSB9IGZyb20gXCIuL2FwaS1jb25maWcuanNcIjtcbmltcG9ydCB7IEJhc2VBcGlDb25maWcgfSBmcm9tIFwiLi9hcGktY29uZmlnLmpzXCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQgfSBmcm9tIFwiLi9jb250ZXh0LmpzXCI7XG5pbXBvcnQgeyBkZWNvZGUsIGVuY29kZSB9IGZyb20gXCIuL2VuY29kZS1kZWNvZGUuanNcIjtcbmltcG9ydCB7IFNka2dlbkh0dHBTZXJ2ZXIgfSBmcm9tIFwiLi9odHRwLXNlcnZlci5qc1wiO1xuaW1wb3J0IHR5cGUgeyBEZWZhdWx0RXh0cmFDb250ZXh0IH0gZnJvbSBcIi4vaW5kZXguanNcIjtcbmltcG9ydCB7IGFwaVRlc3RXcmFwcGVyIH0gZnJvbSBcIi4vdGVzdC13cmFwcGVyLmpzXCI7XG5pbXBvcnQgdHlwZSB7IERlZXBSZWFkb25seSB9IGZyb20gXCIuL3V0aWxzLmpzXCI7XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbmV4cG9ydCBjb25zdCBVdWlkOiB1bmlxdWUgc3ltYm9sID0gU3ltYm9sKFwiVXVpZFwiKTtcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbmV4cG9ydCBjb25zdCBJbnQ6IHVuaXF1ZSBzeW1ib2wgPSBTeW1ib2woXCJJbnRcIik7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG5leHBvcnQgY29uc3QgVUludDogdW5pcXVlIHN5bWJvbCA9IFN5bWJvbChcIlVJbnRcIik7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG5leHBvcnQgY29uc3QgQ3BmOiB1bmlxdWUgc3ltYm9sID0gU3ltYm9sKFwiQ3BmXCIpO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuZXhwb3J0IGNvbnN0IENucGo6IHVuaXF1ZSBzeW1ib2wgPSBTeW1ib2woXCJDbnBqXCIpO1xuXG5jbGFzcyBBcGlDb25maWc8RXh0cmFDb250ZXh0VCA9IHVua25vd24+IGV4dGVuZHMgQmFzZUFwaUNvbmZpZzxFeHRyYUNvbnRleHRUPiB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBhc3RKc29uOiBEZWVwUmVhZG9ubHk8QXN0SnNvbj4sXG4gICAgcHVibGljIGZuOiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgW25hbWU6IHN0cmluZ106ICgoY3R4OiBDb250ZXh0ICYgRXh0cmFDb250ZXh0VCwgYXJnczogYW55KSA9PiBQcm9taXNlPGFueT4pIHwgdW5kZWZpbmVkO1xuICAgIH0sXG4gICAgcHVibGljIHJlYWRvbmx5IG1pZGRsZXdhcmVzOiBBcnJheTxNaWRkbGV3YXJlPEV4dHJhQ29udGV4dFQ+PixcbiAgKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNka2dlbkNvbmZpZzxFeHRyYUNvbnRleHRUPiB7XG4gIHBvcnQ/OiBudW1iZXI7XG4gIGVuZHBvaW50czogUmVjb3JkPHN0cmluZywgU2RrZ2VuRW5kcG9pbnQ8YW55LCBhbnk+PjtcbiAgbWlkZGxld2FyZXM/OiBBcnJheTxNaWRkbGV3YXJlPEV4dHJhQ29udGV4dFQ+PjtcbiAgZXh0cmFDb250ZXh0OiBFeHRyYUNvbnRleHRUO1xufVxuXG5jbGFzcyBDdXN0b21UeXBlQmFzZUNsYXNzIHtcbiAgc3RhdGljIHJlYWRvbmx5IG1hcms6IHVuaXF1ZSBzeW1ib2wgPSBTeW1ib2woKTtcbiAgc3RhdGljIHJlYWRvbmx5IGZpZWxkczogUmVjb3JkPHN0cmluZywgVHlwZVNwZWM+ID0ge307XG59XG5cbnR5cGUgQ3VzdG9tVHlwZVJlZ2lzdHJ5ID0gTWFwPHN0cmluZywgdHlwZW9mIEN1c3RvbVR5cGVCYXNlQ2xhc3M+O1xuXG5mdW5jdGlvbiBnZXRTZGtnZW5UeXBlKHR5cGU6IFR5cGVTcGVjLCByZWdpc3RyeTogQ3VzdG9tVHlwZVJlZ2lzdHJ5KTogc3RyaW5nIHtcbiAgbGV0IG5vcm1hbGl6ZWRUeXBlOiBhbnk7XG5cbiAgaWYgKFxuICAgIHR5cGUgPT09IFN0cmluZyB8fFxuICAgIHR5cGUgPT09IFV1aWQgfHxcbiAgICB0eXBlID09PSBOdW1iZXIgfHxcbiAgICB0eXBlID09PSBCb29sZWFuIHx8XG4gICAgdHlwZSA9PT0gQmlnSW50IHx8XG4gICAgdHlwZSA9PT0gSW50IHx8XG4gICAgdHlwZSA9PT0gVUludCB8fFxuICAgIHR5cGUgPT09IERhdGUgfHxcbiAgICB0eXBlID09PSBCdWZmZXIgfHxcbiAgICB0eXBlID09PSBEZWNpbWFsIHx8XG4gICAgdHlwZSA9PT0gQ3BmIHx8XG4gICAgdHlwZSA9PT0gQ25waiB8fFxuICAgIHR5cGUgPT09IFVSTCB8fFxuICAgIHR5cGUgPT09IHVuZGVmaW5lZFxuICApIHtcbiAgICBub3JtYWxpemVkVHlwZSA9IHsgdHlwZSB9O1xuICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiAodHlwZSBhcyB0eXBlb2YgQ3VzdG9tVHlwZUJhc2VDbGFzcykubWFyayA9PT0gQ3VzdG9tVHlwZUJhc2VDbGFzcy5tYXJrKSB7XG4gICAgbm9ybWFsaXplZFR5cGUgPSB7IHR5cGUgfTtcbiAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHR5cGUpKSB7XG4gICAgbm9ybWFsaXplZFR5cGUgPSB7IHR5cGU6IEFycmF5LCBvZjogdHlwZVswXSB9O1xuICB9IGVsc2Uge1xuICAgIG5vcm1hbGl6ZWRUeXBlID0gdHlwZTtcbiAgfVxuXG4gIGlmIChub3JtYWxpemVkVHlwZS5udWxsYWJsZSA9PT0gdHJ1ZSkge1xuICAgIGRlbGV0ZSBub3JtYWxpemVkVHlwZS5udWxsYWJsZTtcbiAgICByZXR1cm4gYCR7Z2V0U2RrZ2VuVHlwZShub3JtYWxpemVkVHlwZSwgcmVnaXN0cnkpfT9gO1xuICB9XG5cbiAgaWYgKG5vcm1hbGl6ZWRUeXBlLnR5cGUgPT09IFN0cmluZykge1xuICAgIHJldHVybiBcInN0cmluZ1wiO1xuICB9IGVsc2UgaWYgKG5vcm1hbGl6ZWRUeXBlLnR5cGUgPT09IE51bWJlcikge1xuICAgIHJldHVybiBcImZsb2F0XCI7XG4gIH0gZWxzZSBpZiAobm9ybWFsaXplZFR5cGUudHlwZSA9PT0gSW50KSB7XG4gICAgcmV0dXJuIFwiaW50XCI7XG4gIH0gZWxzZSBpZiAobm9ybWFsaXplZFR5cGUudHlwZSA9PT0gVUludCkge1xuICAgIHJldHVybiBcInVpbnRcIjtcbiAgfSBlbHNlIGlmIChub3JtYWxpemVkVHlwZS50eXBlID09PSBVdWlkKSB7XG4gICAgcmV0dXJuIFwidXVpZFwiO1xuICB9IGVsc2UgaWYgKG5vcm1hbGl6ZWRUeXBlLnR5cGUgPT09IEJvb2xlYW4pIHtcbiAgICByZXR1cm4gXCJib29sXCI7XG4gIH0gZWxzZSBpZiAobm9ybWFsaXplZFR5cGUudHlwZSA9PT0gQmlnSW50KSB7XG4gICAgcmV0dXJuIFwiYmlnaW50XCI7XG4gIH0gZWxzZSBpZiAobm9ybWFsaXplZFR5cGUudHlwZSA9PT0gRGF0ZSkge1xuICAgIHJldHVybiBcImRhdGV0aW1lXCI7XG4gIH0gZWxzZSBpZiAobm9ybWFsaXplZFR5cGUudHlwZSA9PT0gQnVmZmVyKSB7XG4gICAgcmV0dXJuIFwiYnl0ZXNcIjtcbiAgfSBlbHNlIGlmIChub3JtYWxpemVkVHlwZS50eXBlID09PSBEZWNpbWFsKSB7XG4gICAgcmV0dXJuIFwiZGVjaW1hbFwiO1xuICB9IGVsc2UgaWYgKG5vcm1hbGl6ZWRUeXBlLnR5cGUgPT09IENwZikge1xuICAgIHJldHVybiBcImNwZlwiO1xuICB9IGVsc2UgaWYgKG5vcm1hbGl6ZWRUeXBlLnR5cGUgPT09IENucGopIHtcbiAgICByZXR1cm4gXCJjbnBqXCI7XG4gIH0gZWxzZSBpZiAobm9ybWFsaXplZFR5cGUudHlwZSA9PT0gVVJMKSB7XG4gICAgcmV0dXJuIFwidXJsXCI7XG4gIH0gZWxzZSBpZiAobm9ybWFsaXplZFR5cGUudHlwZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIFwidm9pZFwiO1xuICB9IGVsc2UgaWYgKG5vcm1hbGl6ZWRUeXBlLnR5cGUgPT09IEFycmF5KSB7XG4gICAgcmV0dXJuIGAke2dldFNka2dlblR5cGUobm9ybWFsaXplZFR5cGUub2YsIHJlZ2lzdHJ5KX1bXWA7XG4gIH0gZWxzZSBpZiAobm9ybWFsaXplZFR5cGUudHlwZSBpbnN0YW5jZW9mIEZ1bmN0aW9uICYmIChub3JtYWxpemVkVHlwZS50eXBlIGFzIHR5cGVvZiBDdXN0b21UeXBlQmFzZUNsYXNzKS5tYXJrID09PSBDdXN0b21UeXBlQmFzZUNsYXNzLm1hcmspIHtcbiAgICBmb3IgKGxldCBjb3VudGVyID0gMTsgOyArK2NvdW50ZXIpIHtcbiAgICAgIGNvbnN0IG5hbWUgPSBjb3VudGVyID09PSAxID8gYCR7bm9ybWFsaXplZFR5cGUudHlwZS5uYW1lfWAgOiBgJHtub3JtYWxpemVkVHlwZS50eXBlLm5hbWV9JHtjb3VudGVyfWA7XG4gICAgICBjb25zdCBleGlzdGluZyA9IHJlZ2lzdHJ5LmdldChuYW1lKTtcblxuICAgICAgaWYgKGV4aXN0aW5nID09PSBub3JtYWxpemVkVHlwZS50eXBlKSB7XG4gICAgICAgIHJldHVybiBuYW1lO1xuICAgICAgfSBlbHNlIGlmIChleGlzdGluZykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgcmVnaXN0cnkuc2V0KG5hbWUsIG5vcm1hbGl6ZWRUeXBlLnR5cGUpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBVbmhhbmRsZWQgc2RrZ2VuIHR5cGU6ICR7aW5zcGVjdChub3JtYWxpemVkVHlwZSl9YCk7XG59XG5cbmZ1bmN0aW9uIGdldFR5cGVUYWJsZUZyb21SZWdpc3RyeShyZWdpc3RyeTogQ3VzdG9tVHlwZVJlZ2lzdHJ5KSB7XG4gIGNvbnN0IHR5cGVUYWJsZTogQXN0SnNvbltcInR5cGVUYWJsZVwiXSA9IHt9O1xuXG4gIGxldCBuZXdOYW1lc0ZvdW5kID0gdHJ1ZTtcblxuICB3aGlsZSAobmV3TmFtZXNGb3VuZCkge1xuICAgIG5ld05hbWVzRm91bmQgPSBmYWxzZTtcblxuICAgIGZvciAoY29uc3QgW25hbWUsIHR5cGVdIG9mIHJlZ2lzdHJ5KSB7XG4gICAgICBpZiAobmFtZSBpbiB0eXBlVGFibGUpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIG5ld05hbWVzRm91bmQgPSB0cnVlO1xuXG4gICAgICB0eXBlVGFibGVbbmFtZV0gPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICAgIE9iamVjdC5lbnRyaWVzKHR5cGUuZmllbGRzKS5tYXAoKFtmaWVsZE5hbWUsIGZpZWxkVHlwZV0pID0+IFtmaWVsZE5hbWUsIGdldFNka2dlblR5cGUoZmllbGRUeXBlLCByZWdpc3RyeSldKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR5cGVUYWJsZTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlQXBpQ29uZmlnPEV4dHJhQ29udGV4dFQ+KGNvbmZpZzogU2RrZ2VuQ29uZmlnPEV4dHJhQ29udGV4dFQ+KSB7XG4gIGNvbnN0IGFzdEpzb246IEFzdEpzb24gPSB7XG4gICAgZnVuY3Rpb25UYWJsZToge30sXG4gICAgdHlwZVRhYmxlOiB7fSxcbiAgICBlcnJvcnM6IFtdLFxuICAgIGFubm90YXRpb25zOiB7fSxcbiAgfTtcblxuICBjb25zdCBoYW5kbGVyczoge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgW25hbWU6IHN0cmluZ106IChjdHg6IENvbnRleHQgJiBFeHRyYUNvbnRleHRULCBhcmdzOiBhbnkpID0+IFByb21pc2U8YW55PjtcbiAgfSA9IHt9O1xuXG4gIGNvbnN0IHJlZ2lzdHJ5ID0gbmV3IE1hcDxzdHJpbmcsIHR5cGVvZiBDdXN0b21UeXBlQmFzZUNsYXNzPigpO1xuXG4gIGZvciAoY29uc3QgW25hbWUsIGVuZHBvaW50XSBvZiBPYmplY3QuZW50cmllcyhjb25maWcuZW5kcG9pbnRzKSkge1xuICAgIGFzdEpzb24uZnVuY3Rpb25UYWJsZVtuYW1lXSA9IHtcbiAgICAgIGFyZ3M6IE9iamVjdC5mcm9tRW50cmllcyhPYmplY3QuZW50cmllcyhlbmRwb2ludC5vcHRpb25zLmFyZ3MgPz8ge30pLm1hcCgoW2FyZywgdHlwZV0pID0+IFthcmcsIGdldFNka2dlblR5cGUodHlwZSwgcmVnaXN0cnkpXSkpLFxuICAgICAgcmV0OiBnZXRTZGtnZW5UeXBlKGVuZHBvaW50Lm9wdGlvbnMucmV0dXJuLCByZWdpc3RyeSksXG4gICAgfTtcbiAgICBoYW5kbGVyc1tuYW1lXSA9IGVuZHBvaW50LmhhbmRsZXI7XG4gIH1cblxuICBhc3RKc29uLnR5cGVUYWJsZSA9IGdldFR5cGVUYWJsZUZyb21SZWdpc3RyeShyZWdpc3RyeSk7XG5cbiAgcmV0dXJuIG5ldyBBcGlDb25maWc8RXh0cmFDb250ZXh0VD4oYXN0SnNvbiwgaGFuZGxlcnMsIGNvbmZpZy5taWRkbGV3YXJlcyA/PyBbXSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydFNka2dlblNlcnZlcjxFeHRyYUNvbnRleHRUPihjb25maWc6IFNka2dlbkNvbmZpZzxFeHRyYUNvbnRleHRUPikge1xuICBjb25zdCBhcGkgPSBjcmVhdGVBcGlDb25maWcoY29uZmlnKTtcblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hcmd1bWVudCwgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBjb25zdCBzZXJ2ZXIgPSBuZXcgU2RrZ2VuSHR0cFNlcnZlcjxFeHRyYUNvbnRleHRUPihhcGksIGNvbmZpZy5leHRyYUNvbnRleHQgYXMgYW55KTtcblxuICBhd2FpdCBzZXJ2ZXIubGlzdGVuKGNvbmZpZy5wb3J0ID8/IDgwKTtcbn1cblxudHlwZSBDYWxsYWJsZUVuZHBvaW50PEV4dHJhQ29udGV4dFQsIEVuZHBvaW50IGV4dGVuZHMgU2RrZ2VuRW5kcG9pbnQ8dW5rbm93biwgdW5rbm93bj4+ID0gRW5kcG9pbnQgZXh0ZW5kcyBTZGtnZW5FbmRwb2ludDxpbmZlciBBcmdzLCBpbmZlciBSZXR1cm4+XG4gID8gKGN0eDogUGFydGlhbDxDb250ZXh0ICYgRXh0cmFDb250ZXh0VD4sIGFyZ3M6IEFyZ3MpID0+IFByb21pc2U8UmV0dXJuPlxuICA6IG5ldmVyO1xuXG50eXBlIENhbGxhYmxlRW5kcG9pbnRzPEV4dHJhQ29udGV4dFQsIEVuZHBvaW50cyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIFNka2dlbkVuZHBvaW50PHVua25vd24sIHVua25vd24+Pj4gPSB7XG4gIFtFbmRwb2ludE5hbWUgaW4ga2V5b2YgRW5kcG9pbnRzXTogQ2FsbGFibGVFbmRwb2ludDxFeHRyYUNvbnRleHRULCBFbmRwb2ludHNbRW5kcG9pbnROYW1lXT47XG59O1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNka2dlblRlc3RDbGllbnQ8Q29uZmlnVCBleHRlbmRzIFNka2dlbkNvbmZpZzxhbnk+Pihjb25maWc6IENvbmZpZ1QpIHtcbiAgY29uc3QgYXBpID0gY3JlYXRlQXBpQ29uZmlnKGNvbmZpZyk7XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtYXJndW1lbnRcbiAgcmV0dXJuIGFwaVRlc3RXcmFwcGVyKGFwaSwgY29uZmlnLmV4dHJhQ29udGV4dCkuZm4gYXMgdW5rbm93biBhcyBDYWxsYWJsZUVuZHBvaW50czxDb25maWdUW1wiZXh0cmFDb250ZXh0XCJdLCBDb25maWdUW1wiZW5kcG9pbnRzXCJdPjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNka2dlblR5cGU8RmllbGRzIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgVHlwZVNwZWM+PihmaWVsZHM6IEZpZWxkcykge1xuICBjb25zdCBjdXN0b21UeXBlID0gY2xhc3MgZXh0ZW5kcyBDdXN0b21UeXBlQmFzZUNsYXNzIHtcbiAgICBzdGF0aWMgZmllbGRzID0gZmllbGRzO1xuICB9O1xuXG4gIHJldHVybiBjdXN0b21UeXBlIGFzIHVua25vd24gYXMgeyBtYXJrOiB0eXBlb2YgQ3VzdG9tVHlwZUJhc2VDbGFzc1tcIm1hcmtcIl07IGZpZWxkczogRmllbGRzIH0gJiAobmV3ICgpID0+IEN1c3RvbVR5cGVCYXNlQ2xhc3MgJlxuICAgIEdlbmVyYXRlVHlwaW5nRnJvbUZpZWxkczxGaWVsZHM+KTtcbn1cblxuZXhwb3J0IHR5cGUgVHlwZVNwZWMgPVxuICB8IHR5cGVvZiBTdHJpbmdcbiAgfCB0eXBlb2YgQm9vbGVhblxuICB8IHR5cGVvZiBOdW1iZXJcbiAgfCB0eXBlb2YgSW50XG4gIHwgdHlwZW9mIFVJbnRcbiAgfCB0eXBlb2YgQmlnSW50XG4gIHwgdHlwZW9mIEN1c3RvbVR5cGVCYXNlQ2xhc3NcbiAgfCB0eXBlb2YgVXVpZFxuICB8IHR5cGVvZiBEYXRlXG4gIHwgdHlwZW9mIEJ1ZmZlclxuICB8IHR5cGVvZiBEZWNpbWFsXG4gIHwgdHlwZW9mIENwZlxuICB8IHR5cGVvZiBDbnBqXG4gIHwgdHlwZW9mIFVSTFxuICB8IHVuZGVmaW5lZFxuICB8IFtUeXBlU3BlY11cbiAgfCAoKFxuICAgICAgfCB7IHR5cGU6IHR5cGVvZiBTdHJpbmc7IG1pbkxlbmd0aD86IG51bWJlcjsgbWF4TGVuZ3RoPzogbnVtYmVyOyBwYXR0ZXJuPzogUmVnRXhwIH1cbiAgICAgIHwgeyB0eXBlOiB0eXBlb2YgQm9vbGVhbiB9XG4gICAgICB8IHsgdHlwZTogdHlwZW9mIE51bWJlcjsgbWluPzogbnVtYmVyOyBtYXg/OiBudW1iZXIgfVxuICAgICAgfCB7IHR5cGU6IHR5cGVvZiBJbnQ7IG1pbj86IG51bWJlcjsgbWF4PzogbnVtYmVyIH1cbiAgICAgIHwgeyB0eXBlOiB0eXBlb2YgVUludDsgbWluPzogbnVtYmVyOyBtYXg/OiBudW1iZXIgfVxuICAgICAgfCB7IHR5cGU6IHR5cGVvZiBCaWdJbnQ7IG1pbj86IGJpZ2ludDsgbWF4PzogYmlnaW50IH1cbiAgICAgIHwgeyB0eXBlOiB0eXBlb2YgQ3VzdG9tVHlwZUJhc2VDbGFzcyB9XG4gICAgICB8IHsgdHlwZTogdHlwZW9mIFV1aWQgfVxuICAgICAgfCB7IHR5cGU6IHR5cGVvZiBEYXRlIH1cbiAgICAgIHwgeyB0eXBlOiB0eXBlb2YgQnVmZmVyIH1cbiAgICAgIHwgeyB0eXBlOiB0eXBlb2YgRGVjaW1hbCB9XG4gICAgICB8IHsgdHlwZTogdHlwZW9mIENwZiB9XG4gICAgICB8IHsgdHlwZTogdHlwZW9mIENucGogfVxuICAgICAgfCB7IHR5cGU6IHR5cGVvZiBVUkwgfVxuICAgICAgfCB7IHR5cGU6IHVuZGVmaW5lZCB9XG4gICAgICB8IHsgdHlwZTogW1R5cGVTcGVjXTsgbWluTGVuZ3RoPzogbnVtYmVyOyBtYXhMZW5ndGg/OiBudW1iZXIgfVxuICAgICAgfCB7IHR5cGU6IHR5cGVvZiBBcnJheTsgb2Y6IFR5cGVTcGVjOyBtaW5MZW5ndGg/OiBudW1iZXI7IG1heExlbmd0aD86IG51bWJlciB9XG4gICAgKSAmIHsgbnVsbGFibGU/OiB0cnVlIH0pO1xuXG5pbnRlcmZhY2UgQXBpRW5kcG9pbnRPcHRpb25zIHtcbiAgcmVzdD86IHtcbiAgICBtZXRob2Q6IFwiR0VUXCIgfCBcIlBPU1RcIiB8IFwiUFVUXCIgfCBcIlBBVENIXCIgfCBcIkRFTEVURVwiO1xuICAgIHBhdGg6IHN0cmluZztcbiAgICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgICBib2R5Pzogc3RyaW5nO1xuICB9O1xuICBhcmdzPzogUmVjb3JkPHN0cmluZywgVHlwZVNwZWM+O1xuICByZXR1cm4/OiBUeXBlU3BlYztcbiAgbWlkZGxld2FyZXM/OiBBcnJheTxNaWRkbGV3YXJlPEluZmVyQ29udGV4dDxEZWZhdWx0RXh0cmFDb250ZXh0Pj4+O1xufVxuXG5leHBvcnQgdHlwZSBHZW5lcmF0ZVR5cGluZzxUeXBlPiA9IFR5cGUgZXh0ZW5kcyB7IG51bGxhYmxlOiB0cnVlIH1cbiAgPyBudWxsIHwgR2VuZXJhdGVUeXBpbmc8T21pdDxUeXBlLCBcIm51bGxhYmxlXCI+PlxuICA6IFR5cGUgZXh0ZW5kcyB0eXBlb2YgU3RyaW5nIHwgeyB0eXBlOiB0eXBlb2YgU3RyaW5nIH1cbiAgPyBzdHJpbmdcbiAgOiBUeXBlIGV4dGVuZHMgdHlwZW9mIEJvb2xlYW4gfCB7IHR5cGU6IHR5cGVvZiBCb29sZWFuIH1cbiAgPyBib29sZWFuXG4gIDogVHlwZSBleHRlbmRzIHR5cGVvZiBOdW1iZXIgfCB7IHR5cGU6IHR5cGVvZiBOdW1iZXIgfVxuICA/IG51bWJlclxuICA6IFR5cGUgZXh0ZW5kcyB0eXBlb2YgSW50IHwgeyB0eXBlOiB0eXBlb2YgSW50IH1cbiAgPyBudW1iZXJcbiAgOiBUeXBlIGV4dGVuZHMgdHlwZW9mIFVJbnQgfCB7IHR5cGU6IHR5cGVvZiBVSW50IH1cbiAgPyBudW1iZXJcbiAgOiBUeXBlIGV4dGVuZHMgdHlwZW9mIEJpZ0ludCB8IHsgdHlwZTogdHlwZW9mIEJpZ0ludCB9XG4gID8gYmlnaW50XG4gIDogVHlwZSBleHRlbmRzIHR5cGVvZiBVdWlkIHwgeyB0eXBlOiB0eXBlb2YgVXVpZCB9XG4gID8gc3RyaW5nXG4gIDogVHlwZSBleHRlbmRzIHR5cGVvZiBEYXRlIHwgeyB0eXBlOiB0eXBlb2YgRGF0ZSB9XG4gID8gRGF0ZVxuICA6IFR5cGUgZXh0ZW5kcyB0eXBlb2YgQnVmZmVyIHwgeyB0eXBlOiB0eXBlb2YgQnVmZmVyIH1cbiAgPyBCdWZmZXJcbiAgOiBUeXBlIGV4dGVuZHMgdHlwZW9mIENwZiB8IHsgdHlwZTogdHlwZW9mIENwZiB9XG4gID8gc3RyaW5nXG4gIDogVHlwZSBleHRlbmRzIHR5cGVvZiBDbnBqIHwgeyB0eXBlOiB0eXBlb2YgQ25waiB9XG4gID8gc3RyaW5nXG4gIDogVHlwZSBleHRlbmRzIHR5cGVvZiBVUkwgfCB7IHR5cGU6IHR5cGVvZiBVUkwgfVxuICA/IHN0cmluZ1xuICA6IFR5cGUgZXh0ZW5kcyBbaW5mZXIgSW5uZXJdXG4gID8gQXJyYXk8R2VuZXJhdGVUeXBpbmc8SW5uZXI+PlxuICA6IFR5cGUgZXh0ZW5kcyB7IHR5cGU6IHR5cGVvZiBBcnJheTsgb2Y6IGluZmVyIElubmVyIH1cbiAgPyBBcnJheTxHZW5lcmF0ZVR5cGluZzxJbm5lcj4+XG4gIDogVHlwZSBleHRlbmRzIHsgdHlwZTogW2luZmVyIElubmVyXSB9XG4gID8gQXJyYXk8R2VuZXJhdGVUeXBpbmc8SW5uZXI+PlxuICA6IFR5cGUgZXh0ZW5kcyB0eXBlb2YgQ3VzdG9tVHlwZUJhc2VDbGFzc1xuICA/IEluc3RhbmNlVHlwZTxUeXBlPlxuICA6IFR5cGUgZXh0ZW5kcyB7IHR5cGU6IHR5cGVvZiBDdXN0b21UeXBlQmFzZUNsYXNzIH1cbiAgPyBJbnN0YW5jZVR5cGU8VHlwZVtcInR5cGVcIl0+XG4gIDogdW5kZWZpbmVkIGV4dGVuZHMgVHlwZVxuICA/IHZvaWRcbiAgOiB7ICRlcnJvcjogXCLinYwgdW5yZWNvZ25pemVkIHR5cGVcIiB9O1xuXG5leHBvcnQgdHlwZSBHZW5lcmF0ZVR5cGluZ0Zyb21GaWVsZHM8RmllbGRzIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgVHlwZVNwZWM+PiA9IHtcbiAgW0ZpZWxkIGluIGtleW9mIEZpZWxkc106IEdlbmVyYXRlVHlwaW5nPEZpZWxkc1tGaWVsZF0+O1xufTtcblxuY2xhc3MgU2RrZ2VuRW5kcG9pbnQ8QXJncywgUmV0dXJuPiB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBvcHRpb25zOiBBcGlFbmRwb2ludE9wdGlvbnMsXG4gICAgcHVibGljIHJlYWRvbmx5IGhhbmRsZXI6IChjdHg6IEluZmVyQ29udGV4dDxEZWZhdWx0RXh0cmFDb250ZXh0PiwgYXJnczogQXJncykgPT4gUHJvbWlzZTxSZXR1cm4+LFxuICApIHt9XG59XG5cbnR5cGUgSW5mZXJDb250ZXh0PE9iaj4gPSBPYmogZXh0ZW5kcyB7IGN0eDogdW5rbm93biB9ID8gT2JqW1wiY3R4XCJdICYgQ29udGV4dCA6IENvbnRleHQ7XG5cbnR5cGUgR2V0RW5kcG9pbnRBcmdzPE9wdGlvbnMgZXh0ZW5kcyBBcGlFbmRwb2ludE9wdGlvbnM+ID0gT3B0aW9ucyBleHRlbmRzIHsgYXJnczogUmVjb3JkPHN0cmluZywgVHlwZVNwZWM+IH1cbiAgPyBHZW5lcmF0ZVR5cGluZ0Zyb21GaWVsZHM8T3B0aW9uc1tcImFyZ3NcIl0+XG4gIDoge307XG5cbnR5cGUgR2V0RW5kcG9pbnRSZXR1cm48T3B0aW9ucyBleHRlbmRzIEFwaUVuZHBvaW50T3B0aW9ucz4gPSBHZW5lcmF0ZVR5cGluZzxPcHRpb25zW1wicmV0dXJuXCJdPjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNka2dlbkVuZHBvaW50PE9wdGlvbnMgZXh0ZW5kcyBBcGlFbmRwb2ludE9wdGlvbnM+KFxuICBvcHRpb25zOiBPcHRpb25zLFxuICBoYW5kbGVyOiAoY3R4OiBJbmZlckNvbnRleHQ8RGVmYXVsdEV4dHJhQ29udGV4dD4sIGFyZ3M6IEdldEVuZHBvaW50QXJnczxPcHRpb25zPikgPT4gUHJvbWlzZTxHZXRFbmRwb2ludFJldHVybjxPcHRpb25zPj4sXG4pIHtcbiAgcmV0dXJuIG5ldyBTZGtnZW5FbmRwb2ludDxHZXRFbmRwb2ludEFyZ3M8T3B0aW9ucz4sIEdldEVuZHBvaW50UmV0dXJuPE9wdGlvbnM+PihvcHRpb25zLCBoYW5kbGVyKTtcbn1cblxuZXhwb3J0IHR5cGUgSnNvbkFycmF5ID0gSnNvblZhbHVlW107XG5cbmV4cG9ydCB0eXBlIEpzb25PYmplY3QgPSB7XG4gIFtLIGluIHN0cmluZ10/OiBKc29uVmFsdWU7XG59O1xuXG5leHBvcnQgdHlwZSBKc29uUHJpbWl0aXZlID0gYm9vbGVhbiB8IG51bGwgfCBudW1iZXIgfCBzdHJpbmc7XG5cbmV4cG9ydCB0eXBlIEpzb25WYWx1ZSA9IEpzb25BcnJheSB8IEpzb25PYmplY3QgfCBKc29uUHJpbWl0aXZlO1xuXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RlVmFsdWU8VHlwZSBleHRlbmRzIFR5cGVTcGVjPih0eXBlOiBUeXBlLCB2YWx1ZTogR2VuZXJhdGVUeXBpbmc8VHlwZT4pOiBKc29uVmFsdWUge1xuICBjb25zdCByZWdpc3RyeSA9IG5ldyBNYXA8c3RyaW5nLCB0eXBlb2YgQ3VzdG9tVHlwZUJhc2VDbGFzcz4oKTtcblxuICBjb25zdCBsZWdhY3lUeXBlID0gZ2V0U2RrZ2VuVHlwZSh0eXBlLCByZWdpc3RyeSk7XG4gIGNvbnN0IHR5cGVUYWJsZSA9IGdldFR5cGVUYWJsZUZyb21SZWdpc3RyeShyZWdpc3RyeSk7XG5cbiAgcmV0dXJuIGVuY29kZSh0eXBlVGFibGUsIFwiXCIsIGxlZ2FjeVR5cGUsIHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVZhbHVlPFR5cGUgZXh0ZW5kcyBUeXBlU3BlYz4odHlwZTogVHlwZSwgdmFsdWU6IEpzb25WYWx1ZSk6IEdlbmVyYXRlVHlwaW5nPFR5cGU+IHtcbiAgY29uc3QgcmVnaXN0cnkgPSBuZXcgTWFwPHN0cmluZywgdHlwZW9mIEN1c3RvbVR5cGVCYXNlQ2xhc3M+KCk7XG5cbiAgY29uc3QgbGVnYWN5VHlwZSA9IGdldFNka2dlblR5cGUodHlwZSwgcmVnaXN0cnkpO1xuICBjb25zdCB0eXBlVGFibGUgPSBnZXRUeXBlVGFibGVGcm9tUmVnaXN0cnkocmVnaXN0cnkpO1xuXG4gIHJldHVybiBkZWNvZGUodHlwZVRhYmxlLCBcIlwiLCBsZWdhY3lUeXBlLCB2YWx1ZSkgYXMgR2VuZXJhdGVUeXBpbmc8VHlwZT47XG59XG4iXX0=