nextlove 2.1.4 → 2.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.js +2 -2
- package/dist/chunk-2HL2TLDY.mjs +45 -0
- package/dist/{generate-openapi → generators}/index.d.ts +14 -1
- package/dist/generators/index.js +7013 -0
- package/dist/generators/index.mjs +6978 -0
- package/dist/index.d.ts +70 -8
- package/dist/index.js +23 -7343
- package/dist/index.mjs +270 -0
- package/package.json +21 -9
- package/dist/generate-openapi/index.js +0 -7277
- package/dist/generate-route-types/index.d.ts +0 -14
- package/dist/generate-route-types/index.js +0 -6748
- package/dist/lib/default-map-file-path-to-http-route.d.ts +0 -3
- package/dist/lib/default-map-file-path-to-http-route.js +0 -41
- package/dist/lib/parse-routes-in-package.d.ts +0 -21
- package/dist/lib/parse-routes-in-package.js +0 -6676
- package/dist/types/index.d.ts +0 -64
- package/dist/types/index.js +0 -19
- package/dist/with-route-spec/index.d.ts +0 -12
- package/dist/with-route-spec/index.js +0 -277
- package/dist/with-route-spec/middlewares/with-methods.d.ts +0 -4
- package/dist/with-route-spec/middlewares/with-methods.js +0 -42
- package/dist/with-route-spec/middlewares/with-validation.d.ts +0 -15
- package/dist/with-route-spec/middlewares/with-validation.js +0 -196
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/with-route-spec/middlewares/with-validation.ts
|
|
21
|
-
var with_validation_exports = {};
|
|
22
|
-
__export(with_validation_exports, {
|
|
23
|
-
default: () => with_validation_default,
|
|
24
|
-
withValidation: () => withValidation
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(with_validation_exports);
|
|
27
|
-
var import_zod = require("zod");
|
|
28
|
-
var import_nextjs_exception_middleware = require("nextjs-exception-middleware");
|
|
29
|
-
var import_lodash = require("lodash");
|
|
30
|
-
var getZodObjectSchemaFromZodEffectSchema = (isZodEffect, schema) => {
|
|
31
|
-
if (!isZodEffect) {
|
|
32
|
-
return schema;
|
|
33
|
-
}
|
|
34
|
-
let currentSchema = schema;
|
|
35
|
-
while (currentSchema instanceof import_zod.z.ZodEffects) {
|
|
36
|
-
currentSchema = currentSchema._def.schema;
|
|
37
|
-
}
|
|
38
|
-
return currentSchema;
|
|
39
|
-
};
|
|
40
|
-
var getZodDefFromZodSchemaHelpers = (schema) => {
|
|
41
|
-
const special_zod_types = [
|
|
42
|
-
import_zod.ZodFirstPartyTypeKind.ZodOptional,
|
|
43
|
-
import_zod.ZodFirstPartyTypeKind.ZodDefault,
|
|
44
|
-
import_zod.ZodFirstPartyTypeKind.ZodEffects
|
|
45
|
-
];
|
|
46
|
-
while (special_zod_types.includes(schema._def.typeName)) {
|
|
47
|
-
if (schema._def.typeName === import_zod.ZodFirstPartyTypeKind.ZodOptional || schema._def.typeName === import_zod.ZodFirstPartyTypeKind.ZodDefault) {
|
|
48
|
-
schema = schema._def.innerType;
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (schema._def.typeName === import_zod.ZodFirstPartyTypeKind.ZodEffects) {
|
|
52
|
-
schema = schema._def.schema;
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return schema._def;
|
|
57
|
-
};
|
|
58
|
-
var parseQueryParams = (schema, input) => {
|
|
59
|
-
const parsed_input = Object.assign({}, input);
|
|
60
|
-
const isZodEffect = schema._def.typeName === import_zod.ZodFirstPartyTypeKind.ZodEffects;
|
|
61
|
-
const safe_schema = getZodObjectSchemaFromZodEffectSchema(isZodEffect, schema);
|
|
62
|
-
const isZodObject = safe_schema._def.typeName === import_zod.ZodFirstPartyTypeKind.ZodObject;
|
|
63
|
-
if (isZodObject) {
|
|
64
|
-
const obj_schema = safe_schema;
|
|
65
|
-
for (const [key, value] of Object.entries(obj_schema.shape)) {
|
|
66
|
-
const def = getZodDefFromZodSchemaHelpers(value);
|
|
67
|
-
const isArray = def.typeName === import_zod.ZodFirstPartyTypeKind.ZodArray;
|
|
68
|
-
if (isArray) {
|
|
69
|
-
const array_input = input[key];
|
|
70
|
-
if (typeof array_input === "string") {
|
|
71
|
-
parsed_input[key] = array_input.split(",");
|
|
72
|
-
}
|
|
73
|
-
const bracket_syntax_array_input = input[`${key}[]`];
|
|
74
|
-
if (typeof bracket_syntax_array_input === "string") {
|
|
75
|
-
const pre_split_array = bracket_syntax_array_input;
|
|
76
|
-
parsed_input[key] = pre_split_array.split(",");
|
|
77
|
-
}
|
|
78
|
-
if (Array.isArray(bracket_syntax_array_input)) {
|
|
79
|
-
parsed_input[key] = bracket_syntax_array_input;
|
|
80
|
-
}
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
const isBoolean = def.typeName === import_zod.ZodFirstPartyTypeKind.ZodBoolean;
|
|
84
|
-
if (isBoolean) {
|
|
85
|
-
const boolean_input = input[key];
|
|
86
|
-
if (typeof boolean_input === "string") {
|
|
87
|
-
parsed_input[key] = boolean_input === "true";
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return schema.parse(parsed_input);
|
|
93
|
-
};
|
|
94
|
-
var zodIssueToString = (issue) => {
|
|
95
|
-
if (issue.path.join(".") === "") {
|
|
96
|
-
return issue.message;
|
|
97
|
-
}
|
|
98
|
-
if (issue.message === "Required") {
|
|
99
|
-
return `${issue.path.join(".")} is required`;
|
|
100
|
-
}
|
|
101
|
-
return `${issue.message} for "${issue.path.join(".")}"`;
|
|
102
|
-
};
|
|
103
|
-
function validateJsonResponse(jsonResponse, res) {
|
|
104
|
-
const original_res_json = res.json;
|
|
105
|
-
const override_res_json = (json) => {
|
|
106
|
-
const is_success = res.statusCode >= 200 && res.statusCode < 300;
|
|
107
|
-
if (!is_success) {
|
|
108
|
-
return original_res_json(json);
|
|
109
|
-
}
|
|
110
|
-
try {
|
|
111
|
-
jsonResponse == null ? void 0 : jsonResponse.parse(json);
|
|
112
|
-
} catch (err) {
|
|
113
|
-
throw new import_nextjs_exception_middleware.InternalServerErrorException({
|
|
114
|
-
type: "invalid_response",
|
|
115
|
-
message: "the response does not match with jsonResponse",
|
|
116
|
-
zodError: err
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
return original_res_json(json);
|
|
120
|
-
};
|
|
121
|
-
res.json = override_res_json;
|
|
122
|
-
}
|
|
123
|
-
var withValidation = (input) => (next) => async (req, res) => {
|
|
124
|
-
var _a, _b, _c, _d;
|
|
125
|
-
if (input.formData && input.jsonBody || input.formData && input.commonParams) {
|
|
126
|
-
throw new Error("Cannot use formData with jsonBody or commonParams");
|
|
127
|
-
}
|
|
128
|
-
if ((req.method === "POST" || req.method === "PATCH") && (input.jsonBody || input.commonParams) && !((_a = req.headers["content-type"]) == null ? void 0 : _a.includes("application/json")) && !(0, import_lodash.isEmpty)(req.body)) {
|
|
129
|
-
throw new import_nextjs_exception_middleware.BadRequestException({
|
|
130
|
-
type: "invalid_content_type",
|
|
131
|
-
message: `${req.method} requests must have Content-Type header with "application/json"`
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
if (input.formData && req.method !== "GET" && !((_b = req.headers["content-type"]) == null ? void 0 : _b.includes(
|
|
135
|
-
"application/x-www-form-urlencoded"
|
|
136
|
-
))) {
|
|
137
|
-
throw new import_nextjs_exception_middleware.BadRequestException({
|
|
138
|
-
type: "invalid_content_type",
|
|
139
|
-
message: `Must have Content-Type header with "application/x-www-form-urlencoded"`
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
const original_combined_params = { ...req.query, ...req.body };
|
|
144
|
-
const willValidateRequestBody = input.shouldValidateGetRequestBody ? true : req.method !== "GET";
|
|
145
|
-
const isFormData = Boolean(input.formData);
|
|
146
|
-
if (isFormData && willValidateRequestBody) {
|
|
147
|
-
req.body = (_c = input.formData) == null ? void 0 : _c.parse(req.body);
|
|
148
|
-
}
|
|
149
|
-
if (!isFormData && willValidateRequestBody) {
|
|
150
|
-
req.body = (_d = input.jsonBody) == null ? void 0 : _d.parse(req.body);
|
|
151
|
-
}
|
|
152
|
-
if (input.queryParams) {
|
|
153
|
-
req.query = parseQueryParams(input.queryParams, req.query);
|
|
154
|
-
}
|
|
155
|
-
if (input.commonParams) {
|
|
156
|
-
;
|
|
157
|
-
req.commonParams = parseQueryParams(
|
|
158
|
-
input.commonParams,
|
|
159
|
-
original_combined_params
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
} catch (error) {
|
|
163
|
-
if (error.name === "ZodError") {
|
|
164
|
-
let message;
|
|
165
|
-
if (error.issues.length === 1) {
|
|
166
|
-
const issue = error.issues[0];
|
|
167
|
-
message = zodIssueToString(issue);
|
|
168
|
-
} else {
|
|
169
|
-
const message_components = [];
|
|
170
|
-
for (const issue of error.issues) {
|
|
171
|
-
message_components.push(zodIssueToString(issue));
|
|
172
|
-
}
|
|
173
|
-
message = `${error.issues.length} Input Errors: ` + message_components.join(", ");
|
|
174
|
-
}
|
|
175
|
-
throw new import_nextjs_exception_middleware.BadRequestException({
|
|
176
|
-
type: "invalid_input",
|
|
177
|
-
message,
|
|
178
|
-
validation_errors: error.format()
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
throw new import_nextjs_exception_middleware.BadRequestException({
|
|
182
|
-
type: "invalid_input",
|
|
183
|
-
message: "Error while parsing input"
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
if (input.shouldValidateResponses) {
|
|
187
|
-
validateJsonResponse(input.jsonResponse, res);
|
|
188
|
-
}
|
|
189
|
-
return next(req, res);
|
|
190
|
-
};
|
|
191
|
-
var with_validation_default = withValidation;
|
|
192
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
193
|
-
0 && (module.exports = {
|
|
194
|
-
withValidation
|
|
195
|
-
});
|
|
196
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3dpdGgtcm91dGUtc3BlYy9taWRkbGV3YXJlcy93aXRoLXZhbGlkYXRpb24udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB0eXBlIHsgTmV4dEFwaVJlcXVlc3QsIE5leHRBcGlSZXNwb25zZSB9IGZyb20gXCJuZXh0XCJcbmltcG9ydCB7IHosIFpvZEZpcnN0UGFydHlUeXBlS2luZCB9IGZyb20gXCJ6b2RcIlxuaW1wb3J0IHtcbiAgQmFkUmVxdWVzdEV4Y2VwdGlvbixcbiAgSW50ZXJuYWxTZXJ2ZXJFcnJvckV4Y2VwdGlvbixcbn0gZnJvbSBcIm5leHRqcy1leGNlcHRpb24tbWlkZGxld2FyZVwiXG5pbXBvcnQgeyBpc0VtcHR5IH0gZnJvbSBcImxvZGFzaFwiXG5cbmNvbnN0IGdldFpvZE9iamVjdFNjaGVtYUZyb21ab2RFZmZlY3RTY2hlbWEgPSAoXG4gIGlzWm9kRWZmZWN0OiBib29sZWFuLFxuICBzY2hlbWE6IHouWm9kVHlwZUFueVxuKTogei5ab2RUeXBlQW55IHwgei5ab2RPYmplY3Q8YW55PiA9PiB7XG4gIGlmICghaXNab2RFZmZlY3QpIHtcbiAgICByZXR1cm4gc2NoZW1hIGFzIHouWm9kT2JqZWN0PGFueT5cbiAgfVxuXG4gIGxldCBjdXJyZW50U2NoZW1hID0gc2NoZW1hXG5cbiAgd2hpbGUgKGN1cnJlbnRTY2hlbWEgaW5zdGFuY2VvZiB6LlpvZEVmZmVjdHMpIHtcbiAgICBjdXJyZW50U2NoZW1hID0gY3VycmVudFNjaGVtYS5fZGVmLnNjaGVtYVxuICB9XG5cbiAgcmV0dXJuIGN1cnJlbnRTY2hlbWEgYXMgei5ab2RPYmplY3Q8YW55PlxufVxuXG4vKipcbiAqIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCB0byBnZXQgdGhlIGNvcnJlY3Qgc2NoZW1hIGZyb20gYSBab2RFZmZlY3QgfCBab2REZWZhdWx0IHwgWm9kT3B0aW9uYWwgc2NoZW1hLlxuICogVE9ETzogdGhpcyBmdW5jdGlvbiBzaG91bGQgaGFuZGxlIGFsbCBzcGVjaWFsIGNhc2VzIG9mIFpvZFNjaGVtYSBhbmQgbm90IGp1c3QgWm9kRWZmZWN0IHwgWm9kRGVmYXVsdCB8IFpvZE9wdGlvbmFsXG4gKi9cbmNvbnN0IGdldFpvZERlZkZyb21ab2RTY2hlbWFIZWxwZXJzID0gKHNjaGVtYTogei5ab2RUeXBlQW55KSA9PiB7XG4gIGNvbnN0IHNwZWNpYWxfem9kX3R5cGVzID0gW1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPcHRpb25hbCxcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRGVmYXVsdCxcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRWZmZWN0cyxcbiAgXVxuXG4gIHdoaWxlIChzcGVjaWFsX3pvZF90eXBlcy5pbmNsdWRlcyhzY2hlbWEuX2RlZi50eXBlTmFtZSkpIHtcbiAgICBpZiAoXG4gICAgICBzY2hlbWEuX2RlZi50eXBlTmFtZSA9PT0gWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE9wdGlvbmFsIHx8XG4gICAgICBzY2hlbWEuX2RlZi50eXBlTmFtZSA9PT0gWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZERlZmF1bHRcbiAgICApIHtcbiAgICAgIHNjaGVtYSA9IHNjaGVtYS5fZGVmLmlubmVyVHlwZVxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICBpZiAoc2NoZW1hLl9kZWYudHlwZU5hbWUgPT09IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RFZmZlY3RzKSB7XG4gICAgICBzY2hlbWEgPSBzY2hlbWEuX2RlZi5zY2hlbWFcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICB9XG4gIHJldHVybiBzY2hlbWEuX2RlZlxufVxuXG5jb25zdCBwYXJzZVF1ZXJ5UGFyYW1zID0gKFxuICBzY2hlbWE6IHouWm9kVHlwZUFueSxcbiAgaW5wdXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4pID0+IHtcbiAgY29uc3QgcGFyc2VkX2lucHV0ID0gT2JqZWN0LmFzc2lnbih7fSwgaW5wdXQpXG4gIGNvbnN0IGlzWm9kRWZmZWN0ID0gc2NoZW1hLl9kZWYudHlwZU5hbWUgPT09IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RFZmZlY3RzXG4gIGNvbnN0IHNhZmVfc2NoZW1hID0gZ2V0Wm9kT2JqZWN0U2NoZW1hRnJvbVpvZEVmZmVjdFNjaGVtYShpc1pvZEVmZmVjdCwgc2NoZW1hKVxuICBjb25zdCBpc1pvZE9iamVjdCA9XG4gICAgc2FmZV9zY2hlbWEuX2RlZi50eXBlTmFtZSA9PT0gWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE9iamVjdFxuXG4gIGlmIChpc1pvZE9iamVjdCkge1xuICAgIGNvbnN0IG9ial9zY2hlbWEgPSBzYWZlX3NjaGVtYSBhcyB6LlpvZE9iamVjdDxhbnk+XG5cbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhvYmpfc2NoZW1hLnNoYXBlKSkge1xuICAgICAgY29uc3QgZGVmID0gZ2V0Wm9kRGVmRnJvbVpvZFNjaGVtYUhlbHBlcnModmFsdWUgYXMgei5ab2RUeXBlQW55KVxuICAgICAgY29uc3QgaXNBcnJheSA9IGRlZi50eXBlTmFtZSA9PT0gWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEFycmF5XG4gICAgICBpZiAoaXNBcnJheSkge1xuICAgICAgICBjb25zdCBhcnJheV9pbnB1dCA9IGlucHV0W2tleV1cblxuICAgICAgICBpZiAodHlwZW9mIGFycmF5X2lucHV0ID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgcGFyc2VkX2lucHV0W2tleV0gPSBhcnJheV9pbnB1dC5zcGxpdChcIixcIilcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGJyYWNrZXRfc3ludGF4X2FycmF5X2lucHV0ID0gaW5wdXRbYCR7a2V5fVtdYF1cbiAgICAgICAgaWYgKHR5cGVvZiBicmFja2V0X3N5bnRheF9hcnJheV9pbnB1dCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgIGNvbnN0IHByZV9zcGxpdF9hcnJheSA9IGJyYWNrZXRfc3ludGF4X2FycmF5X2lucHV0XG4gICAgICAgICAgcGFyc2VkX2lucHV0W2tleV0gPSBwcmVfc3BsaXRfYXJyYXkuc3BsaXQoXCIsXCIpXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShicmFja2V0X3N5bnRheF9hcnJheV9pbnB1dCkpIHtcbiAgICAgICAgICBwYXJzZWRfaW5wdXRba2V5XSA9IGJyYWNrZXRfc3ludGF4X2FycmF5X2lucHV0XG4gICAgICAgIH1cblxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBjb25zdCBpc0Jvb2xlYW4gPSBkZWYudHlwZU5hbWUgPT09IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RCb29sZWFuXG4gICAgICBpZiAoaXNCb29sZWFuKSB7XG4gICAgICAgIGNvbnN0IGJvb2xlYW5faW5wdXQgPSBpbnB1dFtrZXldXG5cbiAgICAgICAgaWYgKHR5cGVvZiBib29sZWFuX2lucHV0ID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgcGFyc2VkX2lucHV0W2tleV0gPSBib29sZWFuX2lucHV0ID09PSBcInRydWVcIlxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHNjaGVtYS5wYXJzZShwYXJzZWRfaW5wdXQpXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVxdWVzdElucHV0PFxuICBKc29uQm9keSBleHRlbmRzIHouWm9kVHlwZUFueSxcbiAgUXVlcnlQYXJhbXMgZXh0ZW5kcyB6LlpvZFR5cGVBbnksXG4gIENvbW1vblBhcmFtcyBleHRlbmRzIHouWm9kVHlwZUFueSxcbiAgRm9ybURhdGEgZXh0ZW5kcyB6LlpvZFR5cGVBbnksXG4gIEpzb25SZXNwb25zZSBleHRlbmRzIHouWm9kVHlwZUFueVxuPiB7XG4gIGpzb25Cb2R5PzogSnNvbkJvZHlcbiAgcXVlcnlQYXJhbXM/OiBRdWVyeVBhcmFtc1xuICBjb21tb25QYXJhbXM/OiBDb21tb25QYXJhbXNcbiAgZm9ybURhdGE/OiBGb3JtRGF0YVxuICBqc29uUmVzcG9uc2U/OiBKc29uUmVzcG9uc2VcbiAgc2hvdWxkVmFsaWRhdGVSZXNwb25zZXM/OiBib29sZWFuXG4gIHNob3VsZFZhbGlkYXRlR2V0UmVxdWVzdEJvZHk/OiBib29sZWFuXG59XG5cbmNvbnN0IHpvZElzc3VlVG9TdHJpbmcgPSAoaXNzdWU6IHouWm9kSXNzdWUpID0+IHtcbiAgaWYgKGlzc3VlLnBhdGguam9pbihcIi5cIikgPT09IFwiXCIpIHtcbiAgICByZXR1cm4gaXNzdWUubWVzc2FnZVxuICB9XG4gIGlmIChpc3N1ZS5tZXNzYWdlID09PSBcIlJlcXVpcmVkXCIpIHtcbiAgICByZXR1cm4gYCR7aXNzdWUucGF0aC5qb2luKFwiLlwiKX0gaXMgcmVxdWlyZWRgXG4gIH1cbiAgcmV0dXJuIGAke2lzc3VlLm1lc3NhZ2V9IGZvciBcIiR7aXNzdWUucGF0aC5qb2luKFwiLlwiKX1cImBcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVKc29uUmVzcG9uc2U8SnNvblJlc3BvbnNlIGV4dGVuZHMgei5ab2RUeXBlQW55PihcbiAganNvblJlc3BvbnNlOiBKc29uUmVzcG9uc2UgfCB1bmRlZmluZWQsXG4gIHJlczogTmV4dEFwaVJlc3BvbnNlXG4pIHtcbiAgY29uc3Qgb3JpZ2luYWxfcmVzX2pzb24gPSByZXMuanNvblxuICBjb25zdCBvdmVycmlkZV9yZXNfanNvbiA9IChqc29uOiBhbnkpID0+IHtcbiAgICBjb25zdCBpc19zdWNjZXNzID0gcmVzLnN0YXR1c0NvZGUgPj0gMjAwICYmIHJlcy5zdGF0dXNDb2RlIDwgMzAwXG4gICAgaWYgKCFpc19zdWNjZXNzKSB7XG4gICAgICByZXR1cm4gb3JpZ2luYWxfcmVzX2pzb24oanNvbilcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAganNvblJlc3BvbnNlPy5wYXJzZShqc29uKVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsU2VydmVyRXJyb3JFeGNlcHRpb24oe1xuICAgICAgICB0eXBlOiBcImludmFsaWRfcmVzcG9uc2VcIixcbiAgICAgICAgbWVzc2FnZTogXCJ0aGUgcmVzcG9uc2UgZG9lcyBub3QgbWF0Y2ggd2l0aCBqc29uUmVzcG9uc2VcIixcbiAgICAgICAgem9kRXJyb3I6IGVycixcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgcmV0dXJuIG9yaWdpbmFsX3Jlc19qc29uKGpzb24pXG4gIH1cbiAgcmVzLmpzb24gPSBvdmVycmlkZV9yZXNfanNvblxufVxuXG5leHBvcnQgY29uc3Qgd2l0aFZhbGlkYXRpb24gPVxuICA8XG4gICAgSnNvbkJvZHkgZXh0ZW5kcyB6LlpvZFR5cGVBbnksXG4gICAgUXVlcnlQYXJhbXMgZXh0ZW5kcyB6LlpvZFR5cGVBbnksXG4gICAgQ29tbW9uUGFyYW1zIGV4dGVuZHMgei5ab2RUeXBlQW55LFxuICAgIEZvcm1EYXRhIGV4dGVuZHMgei5ab2RUeXBlQW55LFxuICAgIEpzb25SZXNwb25zZSBleHRlbmRzIHouWm9kVHlwZUFueVxuICA+KFxuICAgIGlucHV0OiBSZXF1ZXN0SW5wdXQ8XG4gICAgICBKc29uQm9keSxcbiAgICAgIFF1ZXJ5UGFyYW1zLFxuICAgICAgQ29tbW9uUGFyYW1zLFxuICAgICAgRm9ybURhdGEsXG4gICAgICBKc29uUmVzcG9uc2VcbiAgICA+XG4gICkgPT5cbiAgKG5leHQpID0+XG4gIGFzeW5jIChyZXE6IE5leHRBcGlSZXF1ZXN0LCByZXM6IE5leHRBcGlSZXNwb25zZSkgPT4ge1xuICAgIGlmIChcbiAgICAgIChpbnB1dC5mb3JtRGF0YSAmJiBpbnB1dC5qc29uQm9keSkgfHxcbiAgICAgIChpbnB1dC5mb3JtRGF0YSAmJiBpbnB1dC5jb21tb25QYXJhbXMpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgdXNlIGZvcm1EYXRhIHdpdGgganNvbkJvZHkgb3IgY29tbW9uUGFyYW1zXCIpXG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgKHJlcS5tZXRob2QgPT09IFwiUE9TVFwiIHx8IHJlcS5tZXRob2QgPT09IFwiUEFUQ0hcIikgJiZcbiAgICAgIChpbnB1dC5qc29uQm9keSB8fCBpbnB1dC5jb21tb25QYXJhbXMpICYmXG4gICAgICAhcmVxLmhlYWRlcnNbXCJjb250ZW50LXR5cGVcIl0/LmluY2x1ZGVzKFwiYXBwbGljYXRpb24vanNvblwiKSAmJlxuICAgICAgIWlzRW1wdHkocmVxLmJvZHkpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbih7XG4gICAgICAgIHR5cGU6IFwiaW52YWxpZF9jb250ZW50X3R5cGVcIixcbiAgICAgICAgbWVzc2FnZTogYCR7cmVxLm1ldGhvZH0gcmVxdWVzdHMgbXVzdCBoYXZlIENvbnRlbnQtVHlwZSBoZWFkZXIgd2l0aCBcImFwcGxpY2F0aW9uL2pzb25cImAsXG4gICAgICB9KVxuICAgIH1cblxuICAgIGlmIChcbiAgICAgIGlucHV0LmZvcm1EYXRhICYmXG4gICAgICByZXEubWV0aG9kICE9PSBcIkdFVFwiICYmXG4gICAgICAhcmVxLmhlYWRlcnNbXCJjb250ZW50LXR5cGVcIl0/LmluY2x1ZGVzKFxuICAgICAgICBcImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZFwiXG4gICAgICApXG4gICAgICAvLyBUT0RPIGV2ZW50dWFsbHkgd2Ugc2hvdWxkIHN1cHBvcnQgbXVsdGlwYXJ0L2Zvcm0tZGF0YVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oe1xuICAgICAgICB0eXBlOiBcImludmFsaWRfY29udGVudF90eXBlXCIsXG4gICAgICAgIG1lc3NhZ2U6IGBNdXN0IGhhdmUgQ29udGVudC1UeXBlIGhlYWRlciB3aXRoIFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCJgLFxuICAgICAgfSlcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgb3JpZ2luYWxfY29tYmluZWRfcGFyYW1zID0geyAuLi5yZXEucXVlcnksIC4uLnJlcS5ib2R5IH1cblxuICAgICAgY29uc3Qgd2lsbFZhbGlkYXRlUmVxdWVzdEJvZHkgPSBpbnB1dC5zaG91bGRWYWxpZGF0ZUdldFJlcXVlc3RCb2R5XG4gICAgICAgID8gdHJ1ZVxuICAgICAgICA6IHJlcS5tZXRob2QgIT09IFwiR0VUXCJcblxuICAgICAgY29uc3QgaXNGb3JtRGF0YSA9IEJvb2xlYW4oaW5wdXQuZm9ybURhdGEpXG5cbiAgICAgIGlmIChpc0Zvcm1EYXRhICYmIHdpbGxWYWxpZGF0ZVJlcXVlc3RCb2R5KSB7XG4gICAgICAgIHJlcS5ib2R5ID0gaW5wdXQuZm9ybURhdGE/LnBhcnNlKHJlcS5ib2R5KVxuICAgICAgfVxuXG4gICAgICBpZiAoIWlzRm9ybURhdGEgJiYgd2lsbFZhbGlkYXRlUmVxdWVzdEJvZHkpIHtcbiAgICAgICAgcmVxLmJvZHkgPSBpbnB1dC5qc29uQm9keT8ucGFyc2UocmVxLmJvZHkpXG4gICAgICB9XG5cbiAgICAgIGlmIChpbnB1dC5xdWVyeVBhcmFtcykge1xuICAgICAgICByZXEucXVlcnkgPSBwYXJzZVF1ZXJ5UGFyYW1zKGlucHV0LnF1ZXJ5UGFyYW1zLCByZXEucXVlcnkpXG4gICAgICB9XG5cbiAgICAgIGlmIChpbnB1dC5jb21tb25QYXJhbXMpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGFzIGNvbW1vblBhcmFtcyBpbmNsdWRlcyBxdWVyeSBwYXJhbXMsIHdlIGNhbiB1c2UgdGhlIHBhcnNlUXVlcnlQYXJhbXMgZnVuY3Rpb25cbiAgICAgICAgICovXG4gICAgICAgIDsocmVxIGFzIGFueSkuY29tbW9uUGFyYW1zID0gcGFyc2VRdWVyeVBhcmFtcyhcbiAgICAgICAgICBpbnB1dC5jb21tb25QYXJhbXMsXG4gICAgICAgICAgb3JpZ2luYWxfY29tYmluZWRfcGFyYW1zXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBpZiAoZXJyb3IubmFtZSA9PT0gXCJab2RFcnJvclwiKSB7XG4gICAgICAgIGxldCBtZXNzYWdlXG4gICAgICAgIGlmIChlcnJvci5pc3N1ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgY29uc3QgaXNzdWUgPSBlcnJvci5pc3N1ZXNbMF1cbiAgICAgICAgICBtZXNzYWdlID0gem9kSXNzdWVUb1N0cmluZyhpc3N1ZSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBtZXNzYWdlX2NvbXBvbmVudHM6IHN0cmluZ1tdID0gW11cbiAgICAgICAgICBmb3IgKGNvbnN0IGlzc3VlIG9mIGVycm9yLmlzc3Vlcykge1xuICAgICAgICAgICAgbWVzc2FnZV9jb21wb25lbnRzLnB1c2goem9kSXNzdWVUb1N0cmluZyhpc3N1ZSkpXG4gICAgICAgICAgfVxuICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAgYCR7ZXJyb3IuaXNzdWVzLmxlbmd0aH0gSW5wdXQgRXJyb3JzOiBgICtcbiAgICAgICAgICAgIG1lc3NhZ2VfY29tcG9uZW50cy5qb2luKFwiLCBcIilcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKHtcbiAgICAgICAgICB0eXBlOiBcImludmFsaWRfaW5wdXRcIixcbiAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgIHZhbGlkYXRpb25fZXJyb3JzOiBlcnJvci5mb3JtYXQoKSxcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oe1xuICAgICAgICB0eXBlOiBcImludmFsaWRfaW5wdXRcIixcbiAgICAgICAgbWVzc2FnZTogXCJFcnJvciB3aGlsZSBwYXJzaW5nIGlucHV0XCIsXG4gICAgICB9KVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHRoaXMgd2lsbCBvdmVycmlkZSB0aGUgcmVzLmpzb24gbWV0aG9kIHRvIHZhbGlkYXRlIHRoZSByZXNwb25zZVxuICAgICAqL1xuICAgIGlmIChpbnB1dC5zaG91bGRWYWxpZGF0ZVJlc3BvbnNlcykge1xuICAgICAgdmFsaWRhdGVKc29uUmVzcG9uc2UoaW5wdXQuanNvblJlc3BvbnNlLCByZXMpXG4gICAgfVxuXG4gICAgcmV0dXJuIG5leHQocmVxLCByZXMpXG4gIH1cblxuZXhwb3J0IGRlZmF1bHQgd2l0aFZhbGlkYXRpb25cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0EsaUJBQXlDO0FBQ3pDLHlDQUdPO0FBQ1Asb0JBQXdCO0FBRXhCLElBQU0sd0NBQXdDLENBQzVDLGFBQ0EsV0FDb0M7QUFDcEMsTUFBSSxDQUFDLGFBQWE7QUFDaEIsV0FBTztBQUFBLEVBQ1Q7QUFFQSxNQUFJLGdCQUFnQjtBQUVwQixTQUFPLHlCQUF5QixhQUFFLFlBQVk7QUFDNUMsb0JBQWdCLGNBQWMsS0FBSztBQUFBLEVBQ3JDO0FBRUEsU0FBTztBQUNUO0FBTUEsSUFBTSxnQ0FBZ0MsQ0FBQyxXQUF5QjtBQUM5RCxRQUFNLG9CQUFvQjtBQUFBLElBQ3hCLGlDQUFzQjtBQUFBLElBQ3RCLGlDQUFzQjtBQUFBLElBQ3RCLGlDQUFzQjtBQUFBLEVBQ3hCO0FBRUEsU0FBTyxrQkFBa0IsU0FBUyxPQUFPLEtBQUssUUFBUSxHQUFHO0FBQ3ZELFFBQ0UsT0FBTyxLQUFLLGFBQWEsaUNBQXNCLGVBQy9DLE9BQU8sS0FBSyxhQUFhLGlDQUFzQixZQUMvQztBQUNBLGVBQVMsT0FBTyxLQUFLO0FBQ3JCO0FBQUEsSUFDRjtBQUVBLFFBQUksT0FBTyxLQUFLLGFBQWEsaUNBQXNCLFlBQVk7QUFDN0QsZUFBUyxPQUFPLEtBQUs7QUFDckI7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNBLFNBQU8sT0FBTztBQUNoQjtBQUVBLElBQU0sbUJBQW1CLENBQ3ZCLFFBQ0EsVUFDRztBQUNILFFBQU0sZUFBZSxPQUFPLE9BQU8sQ0FBQyxHQUFHLEtBQUs7QUFDNUMsUUFBTSxjQUFjLE9BQU8sS0FBSyxhQUFhLGlDQUFzQjtBQUNuRSxRQUFNLGNBQWMsc0NBQXND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QUFBQSxFQUNIO0FBRUEsTUFBSTtBQUNGLFVBQU0sMkJBQTJCLEVBQUUsR0FBRyxJQUFJLE9BQU8sR0FBRyxJQUFJLEtBQUs7QUFFN0QsVUFBTSwwQkFBMEIsTUFBTSwrQkFDbEMsT0FDQSxJQUFJLFdBQVc7QUFFbkIsVUFBTSxhQUFhLFFBQVEsTUFBTSxRQUFRO0FBRXpDLFFBQUksY0FBYyx5QkFBeUI7QUFDekMsVUFBSSxRQUFPLFdBQU0sYUFBTixtQkFBZ0IsTUFBTSxJQUFJO0FBQUEsSUFDdkM7QUFFQSxRQUFJLENBQUMsY0FBYyx5QkFBeUI7QUFDMUMsVUFBSSxRQUFPLFdBQU0sYUFBTixtQkFBZ0IsTUFBTSxJQUFJO0FBQUEsSUFDdkM7QUFFQSxRQUFJLE1BQU0sYUFBYTtBQUNyQixVQUFJLFFBQVEsaUJBQWlCLE1BQU0sYUFBYSxJQUFJLEtBQUs7QUFBQSxJQUMzRDtBQUVBLFFBQUksTUFBTSxjQUFjO0FBSXRCO0FBQUMsTUFBQyxJQUFZLGVBQWU7QUFBQSxRQUMzQixNQUFNO0FBQUEsUUFDTjtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsRUFDRixTQUFTLE9BQVA7QUFDQSxRQUFJLE1BQU0sU0FBUyxZQUFZO0FBQzdCLFVBQUk7QUFDSixVQUFJLE1BQU0sT0FBTyxXQUFXLEdBQUc7QUFDN0IsY0FBTSxRQUFRLE1BQU0sT0FBTztBQUMzQixrQkFBVSxpQkFBaUIsS0FBSztBQUFBLE1BQ2xDLE9BQU87QUFDTCxjQUFNLHFCQUErQixDQUFDO0FBQ3RDLG1CQUFXLFNBQVMsTUFBTSxRQUFRO0FBQ2hDLDZCQUFtQixLQUFLLGlCQUFpQixLQUFLLENBQUM7QUFBQSxRQUNqRDtBQUNBLGtCQUNFLEdBQUcsTUFBTSxPQUFPLDBCQUNoQixtQkFBbUIsS0FBSyxJQUFJO0FBQUEsTUFDaEM7QUFFQSxZQUFNLElBQUksdURBQW9CO0FBQUEsUUFDNUIsTUFBTTtBQUFBLFFBQ047QUFBQSxRQUNBLG1CQUFtQixNQUFNLE9BQU87QUFBQSxNQUNsQyxDQUFDO0FBQUEsSUFDSDtBQUVBLFVBQU0sSUFBSSx1REFBb0I7QUFBQSxNQUM1QixNQUFNO0FBQUEsTUFDTixTQUFTO0FBQUEsSUFDWCxDQUFDO0FBQUEsRUFDSDtBQUtBLE1BQUksTUFBTSx5QkFBeUI7QUFDakMseUJBQXFCLE1BQU0sY0FBYyxHQUFHO0FBQUEsRUFDOUM7QUFFQSxTQUFPLEtBQUssS0FBSyxHQUFHO0FBQ3RCO0FBRUYsSUFBTywwQkFBUTsiLAogICJuYW1lcyI6IFtdCn0K
|