@sdkgen/node-runtime 0.0.0-dev.20230110171718 → 0.0.0-dev.20230120140203

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,156 +0,0 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- /// <reference types="node" resolution-mode="require"/>
3
- import Decimal from "decimal.js";
4
- import type { Middleware } from "./api-config.js";
5
- import type { Context } from "./context.js";
6
- import type { DefaultExtraContext } from "./index.js";
7
- export declare const Uuid: unique symbol;
8
- export declare const Int: unique symbol;
9
- export declare const UInt: unique symbol;
10
- export declare const Cpf: unique symbol;
11
- export declare const Cnpj: unique symbol;
12
- export interface SdkgenConfig<ExtraContextT> {
13
- port?: number;
14
- endpoints: Record<string, SdkgenEndpoint<any, any>>;
15
- middlewares?: Array<Middleware<ExtraContextT>>;
16
- extraContext: ExtraContextT;
17
- }
18
- declare class CustomTypeBaseClass {
19
- static readonly mark: unique symbol;
20
- static readonly fields: Record<string, TypeSpec>;
21
- }
22
- export declare function startSdkgenServer<ExtraContextT>(config: SdkgenConfig<ExtraContextT>): Promise<void>;
23
- type CallableEndpoint<ExtraContextT, Endpoint extends SdkgenEndpoint<unknown, unknown>> = Endpoint extends SdkgenEndpoint<infer Args, infer Return> ? (ctx: Partial<Context & ExtraContextT>, args: Args) => Promise<Return> : never;
24
- type CallableEndpoints<ExtraContextT, Endpoints extends Record<string, SdkgenEndpoint<unknown, unknown>>> = {
25
- [EndpointName in keyof Endpoints]: CallableEndpoint<ExtraContextT, Endpoints[EndpointName]>;
26
- };
27
- export declare function createSdkgenTestClient<ConfigT extends SdkgenConfig<any>>(config: ConfigT): CallableEndpoints<ConfigT["extraContext"], ConfigT["endpoints"]>;
28
- export declare function createSdkgenType<Fields extends Record<string, TypeSpec>>(fields: Fields): {
29
- mark: (typeof CustomTypeBaseClass)["mark"];
30
- fields: Fields;
31
- } & (new () => CustomTypeBaseClass & GenerateTypingFromFields<Fields>);
32
- export type TypeSpec = typeof String | typeof Boolean | typeof Number | typeof Int | typeof UInt | typeof BigInt | typeof CustomTypeBaseClass | typeof Uuid | typeof Date | typeof Buffer | typeof Decimal | typeof Cpf | typeof Cnpj | typeof URL | undefined | [TypeSpec] | (({
33
- type: typeof String;
34
- minLength?: number;
35
- maxLength?: number;
36
- pattern?: RegExp;
37
- } | {
38
- type: typeof Boolean;
39
- } | {
40
- type: typeof Number;
41
- min?: number;
42
- max?: number;
43
- } | {
44
- type: typeof Int;
45
- min?: number;
46
- max?: number;
47
- } | {
48
- type: typeof UInt;
49
- min?: number;
50
- max?: number;
51
- } | {
52
- type: typeof BigInt;
53
- min?: bigint;
54
- max?: bigint;
55
- } | {
56
- type: typeof CustomTypeBaseClass;
57
- } | {
58
- type: typeof Uuid;
59
- } | {
60
- type: typeof Date;
61
- } | {
62
- type: typeof Buffer;
63
- } | {
64
- type: typeof Decimal;
65
- } | {
66
- type: typeof Cpf;
67
- } | {
68
- type: typeof Cnpj;
69
- } | {
70
- type: typeof URL;
71
- } | {
72
- type: undefined;
73
- } | {
74
- type: [TypeSpec];
75
- minLength?: number;
76
- maxLength?: number;
77
- } | {
78
- type: typeof Array;
79
- of: TypeSpec;
80
- minLength?: number;
81
- maxLength?: number;
82
- }) & {
83
- nullable?: true;
84
- });
85
- interface ApiEndpointOptions {
86
- rest?: {
87
- method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
88
- path: string;
89
- headers?: Record<string, string>;
90
- body?: string;
91
- };
92
- args?: Record<string, TypeSpec>;
93
- return?: TypeSpec;
94
- middlewares?: Array<Middleware<InferContext<DefaultExtraContext>>>;
95
- }
96
- export type GenerateTyping<Type> = Type extends {
97
- nullable: true;
98
- } ? null | GenerateTyping<Omit<Type, "nullable">> : Type extends typeof String | {
99
- type: typeof String;
100
- } ? string : Type extends typeof Boolean | {
101
- type: typeof Boolean;
102
- } ? boolean : Type extends typeof Number | {
103
- type: typeof Number;
104
- } ? number : Type extends typeof Int | {
105
- type: typeof Int;
106
- } ? number : Type extends typeof UInt | {
107
- type: typeof UInt;
108
- } ? number : Type extends typeof BigInt | {
109
- type: typeof BigInt;
110
- } ? bigint : Type extends typeof Uuid | {
111
- type: typeof Uuid;
112
- } ? string : Type extends typeof Date | {
113
- type: typeof Date;
114
- } ? Date : Type extends typeof Buffer | {
115
- type: typeof Buffer;
116
- } ? Buffer : Type extends typeof Cpf | {
117
- type: typeof Cpf;
118
- } ? string : Type extends typeof Cnpj | {
119
- type: typeof Cnpj;
120
- } ? string : Type extends typeof URL | {
121
- type: typeof URL;
122
- } ? string : Type extends [infer Inner] ? Array<GenerateTyping<Inner>> : Type extends {
123
- type: typeof Array;
124
- of: infer Inner;
125
- } ? Array<GenerateTyping<Inner>> : Type extends {
126
- type: [infer Inner];
127
- } ? Array<GenerateTyping<Inner>> : Type extends typeof CustomTypeBaseClass ? InstanceType<Type> : Type extends {
128
- type: typeof CustomTypeBaseClass;
129
- } ? InstanceType<Type["type"]> : undefined extends Type ? void : {
130
- $error: "❌ unrecognized type";
131
- };
132
- export type GenerateTypingFromFields<Fields extends Record<string, TypeSpec>> = {
133
- [Field in keyof Fields]: GenerateTyping<Fields[Field]>;
134
- };
135
- declare class SdkgenEndpoint<Args, Return> {
136
- readonly options: ApiEndpointOptions;
137
- readonly handler: (ctx: InferContext<DefaultExtraContext>, args: Args) => Promise<Return>;
138
- constructor(options: ApiEndpointOptions, handler: (ctx: InferContext<DefaultExtraContext>, args: Args) => Promise<Return>);
139
- }
140
- type InferContext<Obj> = Obj extends {
141
- ctx: unknown;
142
- } ? Obj["ctx"] & Context : Context;
143
- type GetEndpointArgs<Options extends ApiEndpointOptions> = Options extends {
144
- args: Record<string, TypeSpec>;
145
- } ? GenerateTypingFromFields<Options["args"]> : {};
146
- type GetEndpointReturn<Options extends ApiEndpointOptions> = GenerateTyping<Options["return"]>;
147
- export declare function createSdkgenEndpoint<Options extends ApiEndpointOptions>(options: Options, handler: (ctx: InferContext<DefaultExtraContext>, args: GetEndpointArgs<Options>) => Promise<GetEndpointReturn<Options>>): SdkgenEndpoint<GetEndpointArgs<Options>, GenerateTyping<Options["return"]>>;
148
- export type JsonArray = JsonValue[];
149
- export type JsonObject = {
150
- [K in string]?: JsonValue;
151
- };
152
- export type JsonPrimitive = boolean | null | number | string;
153
- export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
154
- export declare function encodeValue<Type extends TypeSpec>(type: Type, value: GenerateTyping<Type>): JsonValue;
155
- export declare function decodeValue<Type extends TypeSpec>(type: Type, value: JsonValue): GenerateTyping<Type>;
156
- export {};
@@ -1,200 +0,0 @@
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=