@sdkgen/node-runtime 0.0.0-dev.20230110171718 → 0.0.0-dev.20230120141325
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/spec/error.spec.js +4 -3
- package/dist/spec/rest/rest.spec.js +24 -24
- package/dist/spec/runtime/errors.spec.js +14 -15
- package/dist/spec/runtime/middleware.spec.js +14 -15
- package/dist/spec/simple/legacyNodeClient.js +32 -6
- package/dist/spec/simple/simple.spec.js +28 -27
- package/dist/spec/types.js +28 -27
- package/dist/spec/types.spec.js +55 -54
- package/dist/src/api-config.d.ts +4 -3
- package/dist/src/api-config.js +8 -4
- package/dist/src/context.d.ts +3 -3
- package/dist/src/context.js +2 -2
- package/dist/src/encode-decode.d.ts +2 -2
- package/dist/src/encode-decode.js +50 -12
- package/dist/src/error.js +9 -4
- package/dist/src/execute.d.ts +2 -2
- package/dist/src/execute.js +14 -12
- package/dist/src/http-client.d.ts +3 -3
- package/dist/src/http-client.js +27 -25
- package/dist/src/http-server.d.ts +3 -3
- package/dist/src/http-server.js +182 -168
- package/dist/src/index.d.ts +7 -11
- package/dist/src/index.js +18 -8
- package/dist/src/swagger.d.ts +1 -1
- package/dist/src/swagger.js +159 -146
- package/dist/src/test-wrapper.d.ts +2 -2
- package/dist/src/test-wrapper.js +23 -25
- package/dist/src/utils.js +5 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -26
- package/dist/src/new-interface.d.ts +0 -156
- package/dist/src/new-interface.js +0 -200
|
@@ -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=
|