cdk-serverless 3.4.0 → 3.5.1
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/docs/constructs/assets/hierarchy.js +1 -1
- package/docs/constructs/assets/navigation.js +1 -1
- package/docs/constructs/assets/search.js +1 -1
- package/docs/constructs/classes/GraphQlApi.html +4 -3
- package/docs/constructs/classes/McpAuth.html +1 -1
- package/docs/constructs/classes/McpCognitoAuth.html +1 -1
- package/docs/constructs/classes/RestApi.html +1 -1
- package/docs/constructs/classes/SingleTableDatastore.html +1 -1
- package/docs/constructs/classes/Workflow.html +1 -1
- package/docs/constructs/hierarchy.html +5 -5
- package/docs/constructs/interfaces/GraphQlApiProps.html +7 -3
- package/docs/constructs/interfaces/LambdaResolverOptions.html +72 -0
- package/docs/constructs/interfaces/RestApiProps.html +1 -1
- package/docs/constructs/modules.html +2 -2
- package/docs/lambda/assets/hierarchy.js +1 -1
- package/docs/lambda/assets/navigation.js +1 -1
- package/docs/lambda/assets/search.js +1 -1
- package/docs/lambda/classes/errors.BadRequestError.html +1 -1
- package/docs/lambda/classes/errors.ForbiddenError.html +1 -1
- package/docs/lambda/classes/errors.HttpError.html +1 -1
- package/docs/lambda/classes/errors.NotFoundError.html +1 -1
- package/docs/lambda/classes/errors.UnauthenticatedError.html +1 -1
- package/docs/lambda/classes/errors.appsync.AppSyncError.html +1 -1
- package/docs/lambda/classes/errors.appsync.ConflictError.html +1 -1
- package/docs/lambda/classes/errors.appsync.ForbiddenError.html +1 -1
- package/docs/lambda/classes/errors.appsync.NotFoundError.html +1 -1
- package/docs/lambda/classes/errors.appsync.ValidationError.html +1 -1
- package/docs/lambda/functions/api.createAppSyncBatchHandler.html +57 -0
- package/docs/lambda/hierarchy.html +14 -10
- package/docs/lambda/interfaces/api.AppSyncBatchHandlerContext.html +89 -0
- package/docs/lambda/interfaces/api.AppSyncHandlerContext.html +6 -0
- package/docs/lambda/modules/api.html +6 -6
- package/docs/lambda/types/api.AppSyncBatchHandler.html +53 -0
- package/lib/constructs/graphql.d.ts +31 -4
- package/lib/constructs/graphql.js +38 -8
- package/lib/lambda/handler.d.ts +28 -0
- package/lib/lambda/handler.js +101 -38
- package/llm.md +13 -1
- package/package.json +1 -1
package/lib/lambda/handler.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.createAppSyncHandler = exports.createHttpHandler = exports.createOpenApiHandler = exports.createOpenApiHandlerWithRequestBodyNoResponse = exports.createOpenApiHandlerWithRequestBody = void 0;
|
|
39
|
+
exports.createAppSyncBatchHandler = exports.createAppSyncHandler = exports.createHttpHandler = exports.createOpenApiHandler = exports.createOpenApiHandlerWithRequestBodyNoResponse = exports.createOpenApiHandlerWithRequestBody = void 0;
|
|
40
40
|
const process_1 = require("process");
|
|
41
41
|
const lambda_log_1 = __importDefault(require("lambda-log"));
|
|
42
42
|
const appsyncErrors = __importStar(require("./appsync-errors"));
|
|
@@ -221,6 +221,48 @@ function httpStatusToErrorType(statusCode) {
|
|
|
221
221
|
return 'Error';
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Normalises the two recognised typed-error shapes to a common
|
|
226
|
+
* { errorType, message, errorInfo } so the gate, envelope and rethrow are a
|
|
227
|
+
* single code path across the single and batch handlers. Returns undefined for
|
|
228
|
+
* anything that is neither (plain Error, Boom), which the callers rethrow.
|
|
229
|
+
*
|
|
230
|
+
* - appsyncErrors.AppSyncError carries its own GraphQL errorType and an optional
|
|
231
|
+
* errorInfo, which flow through unchanged.
|
|
232
|
+
* - errors.HttpError (the HTTP base thrown by the shared JwtAuthorizer via
|
|
233
|
+
* assertAuthenticated/assertGroup/assertAdmin, and by resolver code directly)
|
|
234
|
+
* has no GraphQL errorType, so map its statusCode with httpStatusToErrorType.
|
|
235
|
+
* HttpError carries no errorInfo, so errorInfo is undefined.
|
|
236
|
+
*
|
|
237
|
+
* The two instanceof checks are disjoint: HttpError and AppSyncError share no
|
|
238
|
+
* ancestry, so an appsync.ForbiddenError takes the AppSyncError branch and an
|
|
239
|
+
* errors.ForbiddenError the HttpError branch.
|
|
240
|
+
*/
|
|
241
|
+
function toTypedError(error) {
|
|
242
|
+
if (error instanceof appsyncErrors.AppSyncError) {
|
|
243
|
+
return { errorType: error.errorType, message: error.message, errorInfo: error.errorInfo };
|
|
244
|
+
}
|
|
245
|
+
else if (error instanceof errors.HttpError) {
|
|
246
|
+
return { errorType: httpStatusToErrorType(error.statusCode), message: error.message, errorInfo: undefined };
|
|
247
|
+
}
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Builds the direct-Lambda error envelope AppSync surfaces as a typed GraphQL
|
|
252
|
+
* error. __appSyncError is a reserved sentinel key the resolver response handler
|
|
253
|
+
* keys on to recognise this envelope. Branching on the sentinel (rather than on
|
|
254
|
+
* a bare errorMessage) means a legitimate resolver result that merely contains
|
|
255
|
+
* an errorMessage field is not misclassified as a typed error.
|
|
256
|
+
*/
|
|
257
|
+
function buildErrorEnvelope(typed) {
|
|
258
|
+
return {
|
|
259
|
+
__appSyncError: true,
|
|
260
|
+
data: null,
|
|
261
|
+
errorType: typed.errorType,
|
|
262
|
+
errorMessage: typed.message,
|
|
263
|
+
errorInfo: typed.errorInfo,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
224
266
|
/**
|
|
225
267
|
* Creates an AppSync resolver handler from the given AppSyncHandler.
|
|
226
268
|
* Returns a function that can be used as an AppSync resolver.
|
|
@@ -248,29 +290,7 @@ const createAppSyncHandler = (handler) => {
|
|
|
248
290
|
return await handler(ctx);
|
|
249
291
|
}
|
|
250
292
|
catch (error) {
|
|
251
|
-
|
|
252
|
-
// { errorType, message, errorInfo } so the gate, envelope and rethrow
|
|
253
|
-
// below are a single code path.
|
|
254
|
-
//
|
|
255
|
-
// - appsyncErrors.AppSyncError carries its own GraphQL errorType and an
|
|
256
|
-
// optional errorInfo, which flow through unchanged.
|
|
257
|
-
// - errors.HttpError (the HTTP base thrown by the shared JwtAuthorizer
|
|
258
|
-
// via assertAuthenticated/assertGroup/assertAdmin, and by resolver
|
|
259
|
-
// code directly) has no GraphQL errorType, so map its statusCode with
|
|
260
|
-
// httpStatusToErrorType. HttpError carries no errorInfo, so errorInfo
|
|
261
|
-
// is undefined.
|
|
262
|
-
//
|
|
263
|
-
// The two instanceof checks are disjoint: HttpError and AppSyncError
|
|
264
|
-
// share no ancestry, so an appsync.ForbiddenError takes the AppSyncError
|
|
265
|
-
// branch and an errors.ForbiddenError the HttpError branch. Anything that
|
|
266
|
-
// is neither (plain Error, Boom) leaves typed undefined and rethrows.
|
|
267
|
-
let typed;
|
|
268
|
-
if (error instanceof appsyncErrors.AppSyncError) {
|
|
269
|
-
typed = { errorType: error.errorType, message: error.message, errorInfo: error.errorInfo };
|
|
270
|
-
}
|
|
271
|
-
else if (error instanceof errors.HttpError) {
|
|
272
|
-
typed = { errorType: httpStatusToErrorType(error.statusCode), message: error.message, errorInfo: undefined };
|
|
273
|
-
}
|
|
293
|
+
const typed = toTypedError(error);
|
|
274
294
|
if (typed && process.env.APPSYNC_TYPED_ERRORS === 'true') {
|
|
275
295
|
// The envelope-return is gated on APPSYNC_TYPED_ERRORS === 'true'.
|
|
276
296
|
// GraphQlApi.addLambdaResolver injects that env var only on its
|
|
@@ -287,20 +307,8 @@ const createAppSyncHandler = (handler) => {
|
|
|
287
307
|
// exact string 'true' means rethrow. This is why a default UNIT
|
|
288
308
|
// resolver whose handler hits an auth assertion (an HttpError) still
|
|
289
309
|
// fails loudly unless typedErrors is active.
|
|
290
|
-
//
|
|
291
|
-
// __appSyncError is a reserved sentinel key the resolver response
|
|
292
|
-
// handler keys on to recognise this envelope. Branching on the sentinel
|
|
293
|
-
// (rather than on a bare errorMessage) means a legitimate resolver result
|
|
294
|
-
// that merely contains an errorMessage field is not misclassified as a
|
|
295
|
-
// typed error.
|
|
296
310
|
ctx.logger.warn(typed.message, { errorType: typed.errorType, errorInfo: typed.errorInfo });
|
|
297
|
-
return
|
|
298
|
-
__appSyncError: true,
|
|
299
|
-
data: null,
|
|
300
|
-
errorType: typed.errorType,
|
|
301
|
-
errorMessage: typed.message,
|
|
302
|
-
errorInfo: typed.errorInfo,
|
|
303
|
-
};
|
|
311
|
+
return buildErrorEnvelope(typed);
|
|
304
312
|
}
|
|
305
313
|
// log the error and throw it again
|
|
306
314
|
ctx.logger.error(error);
|
|
@@ -309,4 +317,59 @@ const createAppSyncHandler = (handler) => {
|
|
|
309
317
|
};
|
|
310
318
|
};
|
|
311
319
|
exports.createAppSyncHandler = createAppSyncHandler;
|
|
312
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sYW1iZGEvaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxQ0FBOEI7QUFDOUIsNERBQStDO0FBQy9DLGdFQUFrRDtBQUNsRCxpQ0FNZ0I7QUFDaEIsaURBQW1DO0FBNkRuQzs7R0FFRztBQUNJLE1BQU0sbUNBQW1DLEdBQUcsQ0FBK0QsT0FBMEgsRUFBdUIsRUFBRTtJQUNuUSxPQUFPLElBQUEseUJBQWlCLEVBQUMsT0FBTyxDQUFDLENBQUM7QUFDcEMsQ0FBQyxDQUFDO0FBRlcsUUFBQSxtQ0FBbUMsdUNBRTlDO0FBRUY7O0dBRUc7QUFDSSxNQUFNLDZDQUE2QyxHQUFHLENBQXNDLE9BQTRFLEVBQXVCLEVBQUU7SUFDdE0sT0FBTyxJQUFBLHlCQUFpQixFQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ3BDLENBQUMsQ0FBQztBQUZXLFFBQUEsNkNBQTZDLGlEQUV4RDtBQUVGOztHQUVHO0FBQ0ksTUFBTSxvQkFBb0IsR0FBRyxDQUFnRCxPQUE2RSxFQUF1QixFQUFFO0lBQ3hMLE9BQU8sSUFBQSx5QkFBaUIsRUFBQyxPQUFPLENBQUMsQ0FBQztBQUNwQyxDQUFDLENBQUM7QUFGVyxRQUFBLG9CQUFvQix3QkFFL0I7QUFFRjs7R0FFRztBQUNILE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUFxRixFQUFFLEdBQWMsRUFBRSxFQUFFO0lBQ2pJLGlIQUFpSDtJQUNqSCxJQUFJLGFBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNyQixPQUFPLElBQUksb0NBQTZCLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7U0FBTSxDQUFDO1FBQ04sZ0dBQWdHO1FBQ2hHLE9BQU8sSUFBSSxnQ0FBeUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lB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RSxJQUFJO29CQUNWLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUztvQkFDMUIsWUFBWSxFQUFFLEtBQUssQ0FBQyxPQUFPO29CQUMzQixTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7aUJBQ1gsQ0FBQztZQUNwQixDQUFDO1lBQ0QsbUNBQW1DO1lBQ25DLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3hCLE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUMsQ0FBQztBQUNKLENBQUMsQ0FBQztBQW5GUyxRQUFBLG9CQUFvQix3QkFtRjdCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZW52IH0gZnJvbSAncHJvY2Vzcyc7XG5pbXBvcnQgbG9nZ2VyLCB7IExhbWJkYUxvZyB9IGZyb20gJ2xhbWJkYS1sb2cnO1xuaW1wb3J0ICogYXMgYXBwc3luY0Vycm9ycyBmcm9tICcuL2FwcHN5bmMtZXJyb3JzJztcbmltcG9ydCB7XG4gIEFwaUdhdGV3YXl2MUNvZ25pdG9BdXRob3JpemVyLFxuICBBcGlHYXRld2F5djFKd3RBdXRob3JpemVyLFxuICBBcHBTeW5jQ29nbml0b0F1dGhvcml6ZXIsXG4gIENvZ25pdG9BdXRob3JpemVyLFxuICBKd3RBdXRob3JpemVyLFxufSBmcm9tICcuL2F1dGgnO1xuaW1wb3J0ICogYXMgZXJyb3JzIGZyb20gJy4vZXJyb3JzJztcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbi8vLyBIVFRQIEFwaVxuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbi8qKlxuICogQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHByb3BlcnRpZXMgZm9yIGFuIEhUVFAgcmVzcG9uc2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSHR0cFJlc3BvbnNlQ29udGV4dCB7XG4gIHN0YXR1c0NvZGU/OiBudW1iZXI7XG4gIGhlYWRlcnM6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9O1xuICBqc29uOiBib29sZWFuO1xufVxuXG4vKipcbiAqIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBwcm9wZXJ0aWVzIGZvciBhbiBIVFRQIHJlcXVlc3QgaGFuZGxlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBIdHRwSGFuZGxlckNvbnRleHQge1xuICBldmVudDogQVdTTGFtYmRhLkFQSUdhdGV3YXlQcm94eVdpdGhDb2duaXRvQXV0aG9yaXplckV2ZW50O1xuICBsYW1iZGFDb250ZXh0OiBBV1NMYW1iZGEuQ29udGV4dDtcbiAgbG9nZ2VyOiBsb2dnZXIuTGFtYmRhTG9nO1xuICByZXNwb25zZTogSHR0cFJlc3BvbnNlQ29udGV4dDtcbiAgYXV0aDogSnd0QXV0aG9yaXplcjtcbn1cblxuLyoqXG4gKiBBIHR5cGUgZGVmaW5pdGlvbiBmb3IgYW4gSFRUUCBoYW5kbGVyLlxuICovXG5leHBvcnQgdHlwZSBIdHRwSGFuZGxlcjxULCBSPiA9IChcbiAgY29udGV4dDogSHR0cEhhbmRsZXJDb250ZXh0LFxuICBib2R5OiBULFxuKSA9PiBQcm9taXNlPFI+O1xuXG4vKipcbiAqIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBwcm9wZXJ0aWVzIGZvciBhbiBPcGVuQVBJIG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcGVyYXRpb24ge1xuICByZXNwb25zZXM6IHtcbiAgICBbc3RhdHVzQ29kZTogbnVtYmVyXToge1xuICAgICAgY29udGVudDoge1xuICAgICAgICAnYXBwbGljYXRpb24vanNvbic6IGFueTtcbiAgICAgIH07XG4gICAgfSB8IGFueTtcbiAgfTtcbn1cblxuLyoqXG4gKiBBIHR5cGUgZGVmaW5pdGlvbiBmb3IgYW4gQVBJIEdhdGV3YXkgdjEgcmVxdWVzdCBoYW5kbGVyLlxuICovXG5leHBvcnQgdHlwZSBBUElHYXRld2F5djFIYW5kbGVyID1cbiAgQVdTTGFtYmRhLkhhbmRsZXI8QVdTTGFtYmRhLkFQSUdhdGV3YXlQcm94eVdpdGhDb2duaXRvQXV0aG9yaXplckV2ZW50LCBBV1NMYW1iZGEuQVBJR2F0ZXdheVByb3h5UmVzdWx0IHwgdW5kZWZpbmVkPjtcblxuLyoqXG4gKiBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgcHJvcGVydGllcyBmb3IgYW4gT3BlbkFQSSBvcGVyYXRpb24gd2l0aCBhIHJlcXVlc3QgYm9keS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcGVyYXRpb25XaXRoUmVxdWVzdEJvZHkgZXh0ZW5kcyBPcGVyYXRpb24ge1xuICByZXF1ZXN0Qm9keTogeyBjb250ZW50OiB7ICdhcHBsaWNhdGlvbi9qc29uJzogYW55IH0gfTtcbn1cblxuLyoqXG4gKiBBIGZhY3RvcnkgZnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIEhUVFAgcmVxdWVzdCBoYW5kbGVyIGZvciBhbiBPcGVuQVBJIG9wZXJhdGlvbiB3aXRoIGEgcmVxdWVzdCBib2R5LlxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlT3BlbkFwaUhhbmRsZXJXaXRoUmVxdWVzdEJvZHkgPSA8T1AgZXh0ZW5kcyBPcGVyYXRpb25XaXRoUmVxdWVzdEJvZHksIFNDIGV4dGVuZHMgbnVtYmVyID0gMjAwPihoYW5kbGVyOiBIdHRwSGFuZGxlcjxPUFsncmVxdWVzdEJvZHknXVsnY29udGVudCddWydhcHBsaWNhdGlvbi9qc29uJ10sIE9QWydyZXNwb25zZXMnXVtTQ11bJ2NvbnRlbnQnXVsnYXBwbGljYXRpb24vanNvbiddPik6IEFQSUdhdGV3YXl2MUhhbmRsZXIgPT4ge1xuICByZXR1cm4gY3JlYXRlSHR0cEhhbmRsZXIoaGFuZGxlcik7XG59O1xuXG4vKipcbiAqIEEgZmFjdG9yeSBmdW5jdGlvbiB0aGF0IGNyZWF0ZXMgYW4gSFRUUCByZXF1ZXN0IGhhbmRsZXIgZm9yIGFuIE9wZW5BUEkgb3BlcmF0aW9uIHdpdGggYSByZXF1ZXN0IGJvZHkgYW5kIG5vIHJlc3BvbnNlLlxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlT3BlbkFwaUhhbmRsZXJXaXRoUmVxdWVzdEJvZHlOb1Jlc3BvbnNlID0gPE9QIGV4dGVuZHMgT3BlcmF0aW9uV2l0aFJlcXVlc3RCb2R5PihoYW5kbGVyOiBIdHRwSGFuZGxlcjxPUFsncmVxdWVzdEJvZHknXVsnY29udGVudCddWydhcHBsaWNhdGlvbi9qc29uJ10sIHZvaWQ+KTogQVBJR2F0ZXdheXYxSGFuZGxlciA9PiB7XG4gIHJldHVybiBjcmVhdGVIdHRwSGFuZGxlcihoYW5kbGVyKTtcbn07XG5cbi8qKlxuICogQSBmYWN0b3J5IGZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBhbiBIVFRQIHJlcXVlc3QgaGFuZGxlciBmb3IgYW4gT3BlbkFQSSBvcGVyYXRpb24uXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVPcGVuQXBpSGFuZGxlciA9IDxPUCBleHRlbmRzIE9wZXJhdGlvbiwgU0MgZXh0ZW5kcyBudW1iZXIgPSAyMDA+KGhhbmRsZXI6IEh0dHBIYW5kbGVyPGFueSwgT1BbJ3Jlc3BvbnNlcyddW1NDXVsnY29udGVudCddWydhcHBsaWNhdGlvbi9qc29uJ10+KTogQVBJR2F0ZXdheXYxSGFuZGxlciA9PiB7XG4gIHJldHVybiBjcmVhdGVIdHRwSGFuZGxlcihoYW5kbGVyKTtcbn07XG5cbi8qKlxuICogQ3JlYXRlIGFuIGF1dGhvcml6ZXIgZm9yIHRoZSBhdXRoZW50aWNhdGlvbiBtZXRob2QgY2hvc2VuIChKV1Qgb3IgQ29nbml0bykuXG4gKi9cbmNvbnN0IGNyZWF0ZUF1dGhvcml6ZXIgPSAoZXZlbnQ6IEFXU0xhbWJkYS5BUElHYXRld2F5UHJveHlFdmVudEJhc2U8QVdTTGFtYmRhLkFQSUdhdGV3YXlQcm94eUNvZ25pdG9BdXRob3JpemVyPiwgbG9nOiBMYW1iZGFMb2cpID0+IHtcbiAgLy8gSWYgQ29nbml0byBpcyB1c2VkLCBVU0VSX1BPT0xfSUQgaXMgaW5qZWN0ZWQgaW50byB0aGUgZnVuY3Rpb24ncyBlbnZpcm9ubWVudC4gQ3VycmVudGx5IGFzc3VtZXMgSldUIG90aGVyd2lzZS5cbiAgaWYgKGVudi5VU0VSX1BPT0xfSUQpIHtcbiAgICByZXR1cm4gbmV3IEFwaUdhdGV3YXl2MUNvZ25pdG9BdXRob3JpemVyKGV2ZW50LCBsb2cpO1xuICB9IGVsc2Uge1xuICAgIC8vIFRoaXMgbWlnaHQgbmVlZCB0byBnZXQgbW9yZSBzb3BoaXN0aWNhdGVkIGlmIG1vcmUgYXV0aG9yaXphdGlvbiBtZXRob2RzIG5lZWQgdG8gYmUgc3VwcG9ydGVkLlxuICAgIHJldHVybiBuZXcgQXBpR2F0ZXdheXYxSnd0QXV0aG9yaXplcihldmVudCwgJ2FkbWluJywgbG9nKTtcbiAgfVxufTtcblxuLyoqXG4gKiBBIGZhY3RvcnkgZnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIEhUVFAgcmVxdWVzdCBoYW5kbGVyLlxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlSHR0cEhhbmRsZXIgPVxuICA8VCwgUj4oaGFuZGxlcjogSHR0cEhhbmRsZXI8VCwgUj4pOiBBUElHYXRld2F5djFIYW5kbGVyID0+IHtcbiAgICByZXR1cm4gYXN5bmMgKGV2ZW50LCBjb250ZXh0KSA9PiB7XG4gICAgICAvLyBDcmVhdGUgYW4gb2JqZWN0IHRvIGhvbGQgdGhlIGNvbnRleHQgZm9yIHRoaXMgSFRUUCByZXF1ZXN0XG4gICAgICBjb25zdCBhdXRoID0gY3JlYXRlQXV0aG9yaXplcihldmVudCwgbG9nZ2VyIGFzIHVua25vd24gYXMgbG9nZ2VyLkxhbWJkYUxvZyk7XG4gICAgICBjb25zdCBjdHg6IEh0dHBIYW5kbGVyQ29udGV4dCA9IHtcbiAgICAgICAgZXZlbnQsXG4gICAgICAgIGF1dGgsXG4gICAgICAgIGxhbWJkYUNvbnRleHQ6IGNvbnRleHQsXG4gICAgICAgIGxvZ2dlcjogbG9nZ2VyIGFzIHVua25vd24gYXMgbG9nZ2VyLkxhbWJkYUxvZyxcbiAgICAgICAgcmVzcG9uc2U6IHsgaGVhZGVyczoge30sIGpzb246IHRydWUgfSxcbiAgICAgIH07XG4gICAgICAvLyBBZGQgdGhlIHJlcXVlc3QgSUQgdG8gdGhlIGxvZ2dpbmcgbWV0YWRhdGEsIGFuZCBlbmFibGUgZGVidWcgbG9nZ2luZyBpZiB0aGUgREVCVUcgZW52aXJvbm1lbnQgdmFyaWFibGUgaXMgc2V0IHRvIFwidHJ1ZVwiXG4gICAgICBjdHgubG9nZ2VyLm9wdGlvbnMubWV0YS5yZXF1ZXN0SWQgPSBjb250ZXh0LmF3c1JlcXVlc3RJZDtcbiAgICAgIGN0eC5sb2dnZXIub3B0aW9ucy5kZWJ1ZyA9IHByb2Nlc3MuZW52LkRFQlVHID09PSAndHJ1ZSc7XG5cbiAgICAgIC8vIExvZyB0aGUgZXZlbnQgb2JqZWN0IGZvciBkZWJ1Z2dpbmcgcHVycG9zZXNcbiAgICAgIGN0eC5sb2dnZXIuZGVidWcoSlNPTi5zdHJpbmdpZnkoZXZlbnQpKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gQXV0aGVudGljYXRlIHRoZSB1c2VyIHVzaW5nIHRoZSBDb2duaXRvIGF1dGhvcml6ZXJcbiAgICAgICAgYXdhaXQgY3R4LmF1dGguYXV0aGVudGljYXRlKCk7XG5cbiAgICAgICAgLy8gQ2FsbCB0aGUgdXNlci1kZWZpbmVkIGhhbmRsZXIgZnVuY3Rpb24sIHBhc3NpbmcgaW4gdGhlIHJlcXVlc3QgY29udGV4dCBvYmplY3QgYW5kIHRoZSBwYXJzZWQgcmVxdWVzdCBib2R5XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGhhbmRsZXIoY3R4LCBwYXJzZUJvZHkoZXZlbnQpKTtcblxuICAgICAgICAvLyBDb25zdHJ1Y3QgYW5kIHJldHVybiB0aGUgSFRUUCByZXNwb25zZVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN0YXR1c0NvZGU6IGN0eC5yZXNwb25zZS5zdGF0dXNDb2RlID8/IChyZXMgPyAyMDAgOiAyMDQpLFxuICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAuLi5jb3JzSGVhZGVyKGV2ZW50KSxcbiAgICAgICAgICAgIC4uLmN0eC5yZXNwb25zZS5oZWFkZXJzLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYm9keTogcmVzID8gKGN0eC5yZXNwb25zZS5qc29uID8gSlNPTi5zdHJpbmdpZnkocmVzKSA6IHJlcykgOiAnJyxcbiAgICAgICAgfTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgLy8gSGFuZGxlIGFueSBlcnJvcnMgdGhhdCBvY2N1ciBkdXJpbmcgcmVxdWVzdCBwcm9jZXNzaW5nXG5cbiAgICAgICAgLy8gSWYgdGhlIGVycm9yIGlzIGFuIGluc3RhbmNlIG9mIEh0dHBFcnJvciwgcmV0dXJuIGFuIEhUVFAgcmVzcG9uc2Ugd2l0aCB0aGUgZXJyb3Igc3RhdHVzIGNvZGUgYW5kIG1lc3NhZ2VcbiAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgZXJyb3JzLkh0dHBFcnJvcikge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdGF0dXNDb2RlOiBlcnJvci5zdGF0dXNDb2RlLFxuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgICAuLi5jb3JzSGVhZGVyKGV2ZW50KSxcbiAgICAgICAgICAgICAgLi4uY3R4LnJlc3BvbnNlLmhlYWRlcnMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYm9keTogZXJyb3IubWVzc2FnZSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIHRoZSBlcnJvciBpcyBhIEJvb20gZXJyb3IgKGZyb20gdGhlIGhhcGkuanMgZnJhbWV3b3JrKSwgcmV0dXJuIGFuIEhUVFAgcmVzcG9uc2Ugd2l0aCB0aGUgZXJyb3Igc3RhdHVzIGNvZGUgYW5kIHBheWxvYWRcbiAgICAgICAgaWYgKGVycm9yLmlzQm9vbSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdGF0dXNDb2RlOiBlcnJvci5vdXRwdXQuc3RhdHVzQ29kZSxcbiAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgLi4uZXJyb3Iub3V0cHV0LmhlYWRlcnMsXG4gICAgICAgICAgICAgIC4uLmNvcnNIZWFkZXIoZXZlbnQpLFxuICAgICAgICAgICAgICAuLi5jdHgucmVzcG9uc2UuaGVhZGVycyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShlcnJvci5vdXRwdXQucGF5bG9hZCksXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICAvLyBGb3IgYWxsIG90aGVyIHR5cGVzIG9mIGVycm9ycywgbG9nIHRoZSBlcnJvciBhbmQgcmV0dXJuIGEgNTAwIHN0YXR1cyBjb2RlIHdpdGggdGhlIGVycm9yIG1lc3NhZ2VcbiAgICAgICAgY3R4LmxvZ2dlci5lcnJvcihlcnJvcik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc3RhdHVzQ29kZTogY3R4LnJlc3BvbnNlLnN0YXR1c0NvZGUgPz8gNTAwLFxuICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAuLi5jb3JzSGVhZGVyKGV2ZW50KSxcbiAgICAgICAgICAgIC4uLmN0eC5yZXNwb25zZS5oZWFkZXJzLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYm9keTogZXJyb3IudG9TdHJpbmcoKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9O1xuICB9O1xuXG4vKipcbiAqIExvb2tzIHVwIGEgaGVhZGVyIHZhbHVlIGNhc2UtaW5zZW5zaXRpdmVseS5cbiAqIEhUVFAgaGVhZGVyIG5hbWVzIGFyZSBjYXNlLWluc2Vuc2l0aXZlIHBlciBSRkMgOTExMCDCpzUuMS5cbiAqL1xuZnVuY3Rpb24gaGVhZGVyVmFsdWUoaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPiB8IG51bGwgfCB1bmRlZmluZWQsIG5hbWU6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghaGVhZGVycykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3Qga2V5ID0gT2JqZWN0LmtleXMoaGVhZGVycykuZmluZChrID0+IGsudG9Mb3dlckNhc2UoKSA9PT0gbmFtZS50b0xvd2VyQ2FzZSgpKTtcbiAgcmV0dXJuIGtleSA/IGhlYWRlcnNba2V5XSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGFuIGV2ZW50IG9iamVjdCByZXByZXNlbnRpbmcgYW4gQVBJIEdhdGV3YXkgUHJveHkgZXZlbnRcbiAqIHdpdGggYSBDb2duaXRvIGF1dGhvcml6ZXIsIGFuZCBleHRyYWN0cyBhbmQgcGFyc2VzIHRoZSByZXF1ZXN0IGJvZHksIGlmIHByZXNlbnQuXG4gKlxuICogQHBhcmFtIGV2ZW50IFRoZSBBUEkgR2F0ZXdheSBQcm94eSBldmVudCB3aXRoIGEgQ29nbml0byBhdXRob3JpemVyXG4gKiBAcmV0dXJucyBUaGUgcGFyc2VkIHJlcXVlc3QgYm9keVxuICovXG5mdW5jdGlvbiBwYXJzZUJvZHk8VD4oZXZlbnQ6IEFXU0xhbWJkYS5BUElHYXRld2F5UHJveHlXaXRoQ29nbml0b0F1dGhvcml6ZXJFdmVudCk6IFQge1xuICBsZXQgYm9keSA9IGV2ZW50LmJvZHk7XG5cbiAgLy8gSWYgdGhlIHJlcXVlc3QgYm9keSBpcyBiYXNlNjQtZW5jb2RlZCwgZGVjb2RlIGl0XG4gIGlmIChldmVudC5ib2R5ICYmIGV2ZW50LmlzQmFzZTY0RW5jb2RlZCkge1xuICAgIGNvbnN0IGJ1ZmYgPSBCdWZmZXIuZnJvbShldmVudC5ib2R5ISwgJ2Jhc2U2NCcpO1xuICAgIGJvZHkgPSBidWZmLnRvU3RyaW5nKCd1dGY4Jyk7XG4gIH1cblxuICAvLyBJZiB0aGUgcmVxdWVzdCBib2R5IGlzIGluIEpTT04gZm9ybWF0LCBwYXJzZSBpdCBpbnRvIGEgSmF2YVNjcmlwdCBvYmplY3RcbiAgaWYgKGhlYWRlclZhbHVlKGV2ZW50LmhlYWRlcnMsICdjb250ZW50LXR5cGUnKT8uaW5jbHVkZXMoJ2FwcGxpY2F0aW9uL2pzb24nKSkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKGJvZHkgPz8gJ3t9Jyk7XG4gIH1cblxuICAvLyBJZiB0aGUgcmVxdWVzdCBib2R5IGlzIG5vdCBwcmVzZW50IG9yIG5vdCBpbiBKU09OIGZvcm1hdCwgcmV0dXJuIGl0IGFzLWlzXG4gIHJldHVybiBib2R5IGFzIGFueTtcbn1cblxuXG4vKipcbiAqIFJldHVybnMgdGhlIENPUlMgaGVhZGVycyB0byBiZSBpbmNsdWRlZCBpbiB0aGUgQVBJIEdhdGV3YXkgcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIGV2ZW50IC0gVGhlIEFQSSBHYXRld2F5IGV2ZW50IG9iamVjdC5cbiAqIEByZXR1cm5zIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBDT1JTIGhlYWRlcnMuXG4gKi9cbmZ1bmN0aW9uIGNvcnNIZWFkZXIoZXZlbnQ6IEFXU0xhbWJkYS5BUElHYXRld2F5UHJveHlXaXRoQ29nbml0b0F1dGhvcml6ZXJFdmVudCk6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9IHtcbiAgY29uc3Qgb3JpZ2luID0gaGVhZGVyVmFsdWUoZXZlbnQ/LmhlYWRlcnMsICdvcmlnaW4nKTtcbiAgcmV0dXJuIHtcbiAgICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJzogb3JpZ2luID8/ICcqJywgLy8gQWxsb3cgcmVxdWVzdHMgZnJvbSB0aGUgb3JpZ2luIGhlYWRlciwgb3IgYWxsb3cgYW55IG9yaWdpbiBpZiBub3QgcHJlc2VudFxuICAgICdBY2Nlc3MtQ29udHJvbC1BbGxvdy1DcmVkZW50aWFscyc6IG9yaWdpbiA/ICd0cnVlJyA6ICdmYWxzZScsIC8vIEluY2x1ZGUgY29va2llcyBpbiBjcm9zcy1vcmlnaW4gcmVxdWVzdHMgaWYgdGhlIG9yaWdpbiBoZWFkZXIgaXMgcHJlc2VudFxuICAgICdBY2Nlc3MtQ29udHJvbC1BbGxvdy1NZXRob2RzJzogJyonLCAvLyBBbGxvdyBhbnkgSFRUUCBtZXRob2RcbiAgICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctSGVhZGVycyc6ICdBdXRob3JpemF0aW9uLCAqJywgLy8gQWxsb3cgdGhlIEF1dGhvcml6YXRpb24gaGVhZGVyIGFuZCBhbnkgb3RoZXIgaGVhZGVyc1xuICB9O1xufVxuXG4vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbi8vLyBBcHBTeW5jXG4vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuLyoqXG4gKiBUaGUgY29udGV4dCBmb3IgdGhlIEFwcFN5bmMgcmVzb2x2ZXIgZnVuY3Rpb24uXG4gKiBDb250YWlucyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZXZlbnQsIGxhbWJkYSBjb250ZXh0LCBsb2dnZXIsIGFuZCBDb2duaXRvIGF1dGhvcml6ZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXBwU3luY0hhbmRsZXJDb250ZXh0PFQ+IHtcbiAgZXZlbnQ6IEFXU0xhbWJkYS5BcHBTeW5jUmVzb2x2ZXJFdmVudDxUPjtcbiAgbGFtYmRhQ29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQ7XG4gIGxvZ2dlcjogbG9nZ2VyLkxhbWJkYUxvZztcbiAgY29nbml0b0F1dGg6IENvZ25pdG9BdXRob3JpemVyO1xufVxuXG4vKipcbiAqIEEgZnVuY3Rpb24gdGhhdCBoYW5kbGVzIGFuIEFwcFN5bmMgcmVzb2x2ZXIgZXZlbnQuXG4gKiBSZWNlaXZlcyB0aGUgY29udGV4dCBvYmplY3QgYW5kIHJldHVybnMgdGhlIHJlc3BvbnNlLlxuICovXG5leHBvcnQgdHlwZSBBcHBTeW5jSGFuZGxlcjxULCBSPiA9IChcbiAgY29udGV4dDogQXBwU3luY0hhbmRsZXJDb250ZXh0PFQ+LFxuKSA9PiBQcm9taXNlPFI+O1xuXG4vKipcbiAqIE1hcHMgYW4gSFRUUCBzdGF0dXMgY29kZSB0byB0aGUgR3JhcGhRTCBlcnJvclR5cGUgcmVwb3J0ZWQgdG8gQXBwU3luYy5cbiAqXG4gKiBMb2NhbCAobm9uLWV4cG9ydGVkKSBoZWxwZXIgdXNlZCBvbmx5IGJ5IGNyZWF0ZUFwcFN5bmNIYW5kbGVyIHdoZW4gaXRcbiAqIHRyYW5zbGF0ZXMgYW4gZXJyb3JzLkh0dHBFcnJvciBpbnRvIGEgdHlwZWQgQXBwU3luYyBlcnJvci4gVGhlIGV4cGxpY2l0XG4gKiBkZWZhdWx0IGtlZXBzIGFueSB1bm1hcHBlZCBzdGF0dXMgKGZvciBleGFtcGxlIGEgNDE4IG9yIGEgNXh4KSByZXBvcnRlZCBhc1xuICogdGhlIGdlbmVyaWMgJ0Vycm9yJyBlcnJvclR5cGUgcmF0aGVyIHRoYW4gbGVha2luZyB0aGUgcmF3IHN0YXR1cyBjb2RlLlxuICovXG5mdW5jdGlvbiBodHRwU3RhdHVzVG9FcnJvclR5cGUoc3RhdHVzQ29kZTogbnVtYmVyKTogc3RyaW5nIHtcbiAgc3dpdGNoIChzdGF0dXNDb2RlKSB7XG4gICAgY2FzZSA0MDA6XG4gICAgICByZXR1cm4gJ0JhZFJlcXVlc3QnO1xuICAgIGNhc2UgNDAxOlxuICAgICAgcmV0dXJuICdVbmF1dGhvcml6ZWQnO1xuICAgIGNhc2UgNDAzOlxuICAgICAgcmV0dXJuICdGb3JiaWRkZW4nO1xuICAgIGNhc2UgNDA0OlxuICAgICAgcmV0dXJuICdOb3RGb3VuZCc7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiAnRXJyb3InO1xuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBBcHBTeW5jIHJlc29sdmVyIGhhbmRsZXIgZnJvbSB0aGUgZ2l2ZW4gQXBwU3luY0hhbmRsZXIuXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCBhcyBhbiBBcHBTeW5jIHJlc29sdmVyLlxuICpcbiAqIEBwYXJhbSBoYW5kbGVyIFRoZSBBcHBTeW5jSGFuZGxlciB0byB1c2UgYXMgdGhlIHJlc29sdmVyLlxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlQXBwU3luY0hhbmRsZXIgPVxuICA8VCwgUj4oaGFuZGxlcjogQXBwU3luY0hhbmRsZXI8VCwgUj4pOiBBV1NMYW1iZGEuQXBwU3luY1Jlc29sdmVySGFuZGxlcjxULCBSPiA9PiB7XG4gICAgcmV0dXJuIGFzeW5jIChldmVudCwgY29udGV4dCkgPT4ge1xuICAgICAgY29uc3QgY3R4OiBBcHBTeW5jSGFuZGxlckNvbnRleHQ8VD4gPSB7XG4gICAgICAgIGV2ZW50LFxuICAgICAgICBsYW1iZGFDb250ZXh0OiBjb250ZXh0LFxuICAgICAgICBsb2dnZXI6IGxvZ2dlciBhcyB1bmtub3duIGFzIGxvZ2dlci5MYW1iZGFMb2csXG4gICAgICAgIGNvZ25pdG9BdXRoOiBuZXcgQXBwU3luY0NvZ25pdG9BdXRob3JpemVyKGV2ZW50KSxcbiAgICAgIH07XG5cbiAgICAgIC8vIHNldCB0aGUgbWV0YSBpbmZvcm1hdGlvbiBpbiBsb2dnZXJcbiAgICAgIGN0eC5sb2dnZXIub3B0aW9ucy5tZXRhLnJlcXVlc3RJZCA9IGNvbnRleHQuYXdzUmVxdWVzdElkO1xuICAgICAgLy8gc2V0IHRoZSBkZWJ1ZyBmbGFnIGZvciBsb2dnZXJcbiAgICAgIGN0eC5sb2dnZXIub3B0aW9ucy5kZWJ1ZyA9IHByb2Nlc3MuZW52LkRFQlVHID09PSAndHJ1ZSc7XG5cbiAgICAgIC8vIGxvZyB0aGUgcmVjZWl2ZWQgZXZlbnRcbiAgICAgIGN0eC5sb2dnZXIuZGVidWcoSlNPTi5zdHJpbmdpZnkoZXZlbnQpKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gYXV0aGVudGljYXRlIHRoZSBpbmNvbWluZyByZXF1ZXN0XG4gICAgICAgIGF3YWl0IGN0eC5jb2duaXRvQXV0aC5hdXRoZW50aWNhdGUoKTtcbiAgICAgICAgLy8gaW52b2tlIHRoZSBoYW5kbGVyIGZ1bmN0aW9uIHdpdGggdGhlIGNvbnRleHRcbiAgICAgICAgcmV0dXJuIGF3YWl0IGhhbmRsZXIoY3R4KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgLy8gTm9ybWFsaXNlIHRoZSB0d28gcmVjb2duaXNlZCB0eXBlZC1lcnJvciBzaGFwZXMgdG8gYSBjb21tb25cbiAgICAgICAgLy8geyBlcnJvclR5cGUsIG1lc3NhZ2UsIGVycm9ySW5mbyB9IHNvIHRoZSBnYXRlLCBlbnZlbG9wZSBhbmQgcmV0aHJvd1xuICAgICAgICAvLyBiZWxvdyBhcmUgYSBzaW5nbGUgY29kZSBwYXRoLlxuICAgICAgICAvL1xuICAgICAgICAvLyAtIGFwcHN5bmNFcnJvcnMuQXBwU3luY0Vycm9yIGNhcnJpZXMgaXRzIG93biBHcmFwaFFMIGVycm9yVHlwZSBhbmQgYW5cbiAgICAgICAgLy8gICBvcHRpb25hbCBlcnJvckluZm8sIHdoaWNoIGZsb3cgdGhyb3VnaCB1bmNoYW5nZWQuXG4gICAgICAgIC8vIC0gZXJyb3JzLkh0dHBFcnJvciAodGhlIEhUVFAgYmFzZSB0aHJvd24gYnkgdGhlIHNoYXJlZCBKd3RBdXRob3JpemVyXG4gICAgICAgIC8vICAgdmlhIGFzc2VydEF1dGhlbnRpY2F0ZWQvYXNzZXJ0R3JvdXAvYXNzZXJ0QWRtaW4sIGFuZCBieSByZXNvbHZlclxuICAgICAgICAvLyAgIGNvZGUgZGlyZWN0bHkpIGhhcyBubyBHcmFwaFFMIGVycm9yVHlwZSwgc28gbWFwIGl0cyBzdGF0dXNDb2RlIHdpdGhcbiAgICAgICAgLy8gICBodHRwU3RhdHVzVG9FcnJvclR5cGUuIEh0dHBFcnJvciBjYXJyaWVzIG5vIGVycm9ySW5mbywgc28gZXJyb3JJbmZvXG4gICAgICAgIC8vICAgaXMgdW5kZWZpbmVkLlxuICAgICAgICAvL1xuICAgICAgICAvLyBUaGUgdHdvIGluc3RhbmNlb2YgY2hlY2tzIGFyZSBkaXNqb2ludDogSHR0cEVycm9yIGFuZCBBcHBTeW5jRXJyb3JcbiAgICAgICAgLy8gc2hhcmUgbm8gYW5jZXN0cnksIHNvIGFuIGFwcHN5bmMuRm9yYmlkZGVuRXJyb3IgdGFrZXMgdGhlIEFwcFN5bmNFcnJvclxuICAgICAgICAvLyBicmFuY2ggYW5kIGFuIGVycm9ycy5Gb3JiaWRkZW5FcnJvciB0aGUgSHR0cEVycm9yIGJyYW5jaC4gQW55dGhpbmcgdGhhdFxuICAgICAgICAvLyBpcyBuZWl0aGVyIChwbGFpbiBFcnJvciwgQm9vbSkgbGVhdmVzIHR5cGVkIHVuZGVmaW5lZCBhbmQgcmV0aHJvd3MuXG4gICAgICAgIGxldCB0eXBlZDogeyBlcnJvclR5cGU6IHN0cmluZzsgbWVzc2FnZTogc3RyaW5nOyBlcnJvckluZm8/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+IH0gfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIGFwcHN5bmNFcnJvcnMuQXBwU3luY0Vycm9yKSB7XG4gICAgICAgICAgdHlwZWQgPSB7IGVycm9yVHlwZTogZXJyb3IuZXJyb3JUeXBlLCBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLCBlcnJvckluZm86IGVycm9yLmVycm9ySW5mbyB9O1xuICAgICAgICB9IGVsc2UgaWYgKGVycm9yIGluc3RhbmNlb2YgZXJyb3JzLkh0dHBFcnJvcikge1xuICAgICAgICAgIHR5cGVkID0geyBlcnJvclR5cGU6IGh0dHBTdGF0dXNUb0Vycm9yVHlwZShlcnJvci5zdGF0dXNDb2RlKSwgbWVzc2FnZTogZXJyb3IubWVzc2FnZSwgZXJyb3JJbmZvOiB1bmRlZmluZWQgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlZCAmJiBwcm9jZXNzLmVudi5BUFBTWU5DX1RZUEVEX0VSUk9SUyA9PT0gJ3RydWUnKSB7XG4gICAgICAgICAgLy8gVGhlIGVudmVsb3BlLXJldHVybiBpcyBnYXRlZCBvbiBBUFBTWU5DX1RZUEVEX0VSUk9SUyA9PT0gJ3RydWUnLlxuICAgICAgICAgIC8vIEdyYXBoUWxBcGkuYWRkTGFtYmRhUmVzb2x2ZXIgaW5qZWN0cyB0aGF0IGVudiB2YXIgb25seSBvbiBpdHNcbiAgICAgICAgICAvLyB0eXBlZEVycm9yczogdHJ1ZSBwYXRoLCB3aG9zZSBBUFBTWU5DX0pTIHJlc29sdmVyIGhhcyBhIHJlc3BvbnNlXG4gICAgICAgICAgLy8gaGFuZGxlciB0aGF0IHJlYWRzIHRoaXMgZW52ZWxvcGUgYW5kIGNhbGxzXG4gICAgICAgICAgLy8gdXRpbC5lcnJvcihlcnJvck1lc3NhZ2UsIGVycm9yVHlwZSwgbnVsbCwgZXJyb3JJbmZvKSwgdHVybmluZyBpdCBpbnRvXG4gICAgICAgICAgLy8gYSBHcmFwaFFMIGVycm9yIG9uIGEgc3VjY2Vzc2Z1bCBpbnZvY2F0aW9uLiBSZXR1cm5pbmcgKG5vdCB0aHJvd2luZylcbiAgICAgICAgICAvLyBrZWVwcyB0aGUgaW52b2NhdGlvbiBvZmYgdGhlIExhbWJkYSBFcnJvcnMgbWV0cmljLlxuICAgICAgICAgIC8vXG4gICAgICAgICAgLy8gV2hlbiB0aGUgZW52IHZhciBpcyBhYnNlbnQgKHRoZSBkZWZhdWx0IFVOSVQgcmVzb2x2ZXIgcGF0aCwgb3IgYVxuICAgICAgICAgIC8vIGhhbmQtd2lyZWQgaGFuZGxlciB1c2VkIHdpdGhvdXQgR3JhcGhRbEFwaSkgdGhlIHR5cGVkIGVycm9yIGZhbGxzXG4gICAgICAgICAgLy8gdGhyb3VnaCB0byB0aGUgcmV0aHJvdyBiZWxvdywgc28gdGhlIGludm9jYXRpb24gZmFpbHMgbG91ZGx5IGluc3RlYWRcbiAgICAgICAgICAvLyBvZiBzdXJmYWNpbmcgdGhlIGVudmVsb3BlIGFzIGZpZWxkIGRhdGEuIEFueSB2YWx1ZSBvdGhlciB0aGFuIHRoZVxuICAgICAgICAgIC8vIGV4YWN0IHN0cmluZyAndHJ1ZScgbWVhbnMgcmV0aHJvdy4gVGhpcyBpcyB3aHkgYSBkZWZhdWx0IFVOSVRcbiAgICAgICAgICAvLyByZXNvbHZlciB3aG9zZSBoYW5kbGVyIGhpdHMgYW4gYXV0aCBhc3NlcnRpb24gKGFuIEh0dHBFcnJvcikgc3RpbGxcbiAgICAgICAgICAvLyBmYWlscyBsb3VkbHkgdW5sZXNzIHR5cGVkRXJyb3JzIGlzIGFjdGl2ZS5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIF9fYXBwU3luY0Vycm9yIGlzIGEgcmVzZXJ2ZWQgc2VudGluZWwga2V5IHRoZSByZXNvbHZlciByZXNwb25zZVxuICAgICAgICAgIC8vIGhhbmRsZXIga2V5cyBvbiB0byByZWNvZ25pc2UgdGhpcyBlbnZlbG9wZS4gQnJhbmNoaW5nIG9uIHRoZSBzZW50aW5lbFxuICAgICAgICAgIC8vIChyYXRoZXIgdGhhbiBvbiBhIGJhcmUgZXJyb3JNZXNzYWdlKSBtZWFucyBhIGxlZ2l0aW1hdGUgcmVzb2x2ZXIgcmVzdWx0XG4gICAgICAgICAgLy8gdGhhdCBtZXJlbHkgY29udGFpbnMgYW4gZXJyb3JNZXNzYWdlIGZpZWxkIGlzIG5vdCBtaXNjbGFzc2lmaWVkIGFzIGFcbiAgICAgICAgICAvLyB0eXBlZCBlcnJvci5cbiAgICAgICAgICBjdHgubG9nZ2VyLndhcm4odHlwZWQubWVzc2FnZSwgeyBlcnJvclR5cGU6IHR5cGVkLmVycm9yVHlwZSwgZXJyb3JJbmZvOiB0eXBlZC5lcnJvckluZm8gfSk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIF9fYXBwU3luY0Vycm9yOiB0cnVlLFxuICAgICAgICAgICAgZGF0YTogbnVsbCxcbiAgICAgICAgICAgIGVycm9yVHlwZTogdHlwZWQuZXJyb3JUeXBlLFxuICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiB0eXBlZC5tZXNzYWdlLFxuICAgICAgICAgICAgZXJyb3JJbmZvOiB0eXBlZC5lcnJvckluZm8sXG4gICAgICAgICAgfSBhcyB1bmtub3duIGFzIFI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbG9nIHRoZSBlcnJvciBhbmQgdGhyb3cgaXQgYWdhaW5cbiAgICAgICAgY3R4LmxvZ2dlci5lcnJvcihlcnJvcik7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgIH07XG4gIH07XG5cbiJdfQ==
|
|
320
|
+
/**
|
|
321
|
+
* Creates a batched AppSync resolver handler from the given AppSyncBatchHandler.
|
|
322
|
+
* Returns a function that can be used as an AppSync BatchInvoke resolver: array
|
|
323
|
+
* in, array out, order preserved.
|
|
324
|
+
*
|
|
325
|
+
* It mirrors createAppSyncHandler's context and auth plumbing but operates on an
|
|
326
|
+
* array of events. Authentication runs once per batch off the first event, and
|
|
327
|
+
* the context carries both the first event (ctx.event = events[0]) and the full
|
|
328
|
+
* ctx.events array. The handler returns R[] in the same order as the input events.
|
|
329
|
+
*
|
|
330
|
+
* @param handler The AppSyncBatchHandler to use as the resolver.
|
|
331
|
+
*/
|
|
332
|
+
const createAppSyncBatchHandler = (handler) => {
|
|
333
|
+
return async (events, context) => {
|
|
334
|
+
// BatchInvoke always delivers a non-empty array; authenticate and build
|
|
335
|
+
// the context off the first event, exactly like createAppSyncHandler.
|
|
336
|
+
const first = events[0];
|
|
337
|
+
const ctx = {
|
|
338
|
+
event: first,
|
|
339
|
+
events,
|
|
340
|
+
lambdaContext: context,
|
|
341
|
+
logger: lambda_log_1.default,
|
|
342
|
+
cognitoAuth: new auth_1.AppSyncCognitoAuthorizer(first),
|
|
343
|
+
};
|
|
344
|
+
// set the meta information in logger
|
|
345
|
+
ctx.logger.options.meta.requestId = context.awsRequestId;
|
|
346
|
+
// set the debug flag for logger
|
|
347
|
+
ctx.logger.options.debug = process.env.DEBUG === 'true';
|
|
348
|
+
// log the received batch of events
|
|
349
|
+
ctx.logger.debug(JSON.stringify(events));
|
|
350
|
+
try {
|
|
351
|
+
// authenticate once per batch off the first event
|
|
352
|
+
await ctx.cognitoAuth.authenticate();
|
|
353
|
+
// invoke the handler function with the batch context; it returns R[] in source order
|
|
354
|
+
return await handler(ctx);
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
const typed = toTypedError(error);
|
|
358
|
+
if (typed && process.env.APPSYNC_TYPED_ERRORS === 'true') {
|
|
359
|
+
// Same gate and envelope as createAppSyncHandler. AppSync expects one
|
|
360
|
+
// result per event in a BatchInvoke response, so a batch-level typed
|
|
361
|
+
// error returns an array of envelopes aligned to the batch length;
|
|
362
|
+
// each item surfaces the same typed error. Returning (not throwing)
|
|
363
|
+
// keeps the invocation off the Lambda Errors metric. Without the flag
|
|
364
|
+
// the typed error falls through to the rethrow below.
|
|
365
|
+
ctx.logger.warn(typed.message, { errorType: typed.errorType, errorInfo: typed.errorInfo });
|
|
366
|
+
return events.map(() => buildErrorEnvelope(typed));
|
|
367
|
+
}
|
|
368
|
+
// log the error and throw it again
|
|
369
|
+
ctx.logger.error(error);
|
|
370
|
+
throw error;
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
};
|
|
374
|
+
exports.createAppSyncBatchHandler = createAppSyncBatchHandler;
|
|
375
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sYW1iZGEvaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxQ0FBOEI7QUFDOUIsNERBQStDO0FBQy9DLGdFQUFrRDtBQUNsRCxpQ0FNZ0I7QUFDaEIsaURBQW1DO0FBNkRuQzs7R0FFRztBQUNJLE1BQU0sbUNBQW1DLEdBQUcsQ0FBK0QsT0FBMEgsRUFBdUIsRUFBRTtJQUNuUSxPQUFPLElBQUEseUJBQWlCLEVBQUMsT0FBTyxDQUFDLENBQUM7QUFDcEMsQ0FBQyxDQUFDO0FBRlcsUUFBQSxtQ0FBbUMsdUNBRTlDO0FBRUY7O0dBRUc7QUFDSSxNQUFNLDZDQUE2QyxHQUFHLENBQXNDLE9BQTRFLEVBQXVCLEVBQUU7SUFDdE0sT0FBTyxJQUFBLHlCQUFpQixFQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ3BDLENBQUMsQ0FBQztBQUZXLFFBQUEsNkNBQTZDLGlEQUV4RDtBQUVGOztHQUVHO0FBQ0ksTUFBTSxvQkFBb0IsR0FBRyxDQUFnRCxPQUE2RSxFQUF1QixFQUFFO0lBQ3hMLE9BQU8sSUFBQSx5QkFBaUIsRUFBQyxPQUFPLENBQUMsQ0FBQztBQUNwQyxDQUFDLENBQUM7QUFGVyxRQUFBLG9CQUFvQix3QkFFL0I7QUFFRjs7R0FFRztBQUNILE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUFxRixFQUFFLEdBQWMsRUFBRSxFQUFFO0lBQ2pJLGlIQUFpSDtJQUNqSCxJQUFJLGFBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNyQixPQUFPLElBQUksb0NBQTZCLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7U0FBTSxDQUFDO1FBQ04sZ0dBQWdHO1FBQ2hHLE9BQU8sSUFBSSxnQ0FBeUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lB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LENBQUMsQ0FBQztRQUM1QixDQUFDO1FBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQixNQUFNLEtBQUssR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFbEMsSUFBSSxLQUFLLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsS0FBSyxNQUFNLEVBQUUsQ0FBQztnQkFDekQsc0VBQXNFO2dCQUN0RSxxRUFBcUU7Z0JBQ3JFLG1FQUFtRTtnQkFDbkUsb0VBQW9FO2dCQUNwRSxzRUFBc0U7Z0JBQ3RFLHNEQUFzRDtnQkFDdEQsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztnQkFDM0YsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLGtCQUFrQixDQUFJLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDeEQsQ0FBQztZQUNELG1DQUFtQztZQUNuQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN4QixNQUFNLEtBQUssQ0FBQztRQUNkLENBQUM7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDLENBQUM7QUEvQ1MsUUFBQSx5QkFBeUIsNkJBK0NsQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGVudiB9IGZyb20gJ3Byb2Nlc3MnO1xuaW1wb3J0IGxvZ2dlciwgeyBMYW1iZGFMb2cgfSBmcm9tICdsYW1iZGEtbG9nJztcbmltcG9ydCAqIGFzIGFwcHN5bmNFcnJvcnMgZnJvbSAnLi9hcHBzeW5jLWVycm9ycyc7XG5pbXBvcnQge1xuICBBcGlHYXRld2F5djFDb2duaXRvQXV0aG9yaXplcixcbiAgQXBpR2F0ZXdheXYxSnd0QXV0aG9yaXplcixcbiAgQXBwU3luY0NvZ25pdG9BdXRob3JpemVyLFxuICBDb2duaXRvQXV0aG9yaXplcixcbiAgSnd0QXV0aG9yaXplcixcbn0gZnJvbSAnLi9hdXRoJztcbmltcG9ydCAqIGFzIGVycm9ycyBmcm9tICcuL2Vycm9ycyc7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4vLy8gSFRUUCBBcGlcbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4vKipcbiAqIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBwcm9wZXJ0aWVzIGZvciBhbiBIVFRQIHJlc3BvbnNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEh0dHBSZXNwb25zZUNvbnRleHQge1xuICBzdGF0dXNDb2RlPzogbnVtYmVyO1xuICBoZWFkZXJzOiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfTtcbiAganNvbjogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgcHJvcGVydGllcyBmb3IgYW4gSFRUUCByZXF1ZXN0IGhhbmRsZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSHR0cEhhbmRsZXJDb250ZXh0IHtcbiAgZXZlbnQ6IEFXU0xhbWJkYS5BUElHYXRld2F5UHJveHlXaXRoQ29nbml0b0F1dGhvcml6ZXJFdmVudDtcbiAgbGFtYmRhQ29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQ7XG4gIGxvZ2dlcjogbG9nZ2VyLkxhbWJkYUxvZztcbiAgcmVzcG9uc2U6IEh0dHBSZXNwb25zZUNvbnRleHQ7XG4gIGF1dGg6IEp3dEF1dGhvcml6ZXI7XG59XG5cbi8qKlxuICogQSB0eXBlIGRlZmluaXRpb24gZm9yIGFuIEhUVFAgaGFuZGxlci5cbiAqL1xuZXhwb3J0IHR5cGUgSHR0cEhhbmRsZXI8VCwgUj4gPSAoXG4gIGNvbnRleHQ6IEh0dHBIYW5kbGVyQ29udGV4dCxcbiAgYm9keTogVCxcbikgPT4gUHJvbWlzZTxSPjtcblxuLyoqXG4gKiBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgcHJvcGVydGllcyBmb3IgYW4gT3BlbkFQSSBvcGVyYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3BlcmF0aW9uIHtcbiAgcmVzcG9uc2VzOiB7XG4gICAgW3N0YXR1c0NvZGU6IG51bWJlcl06IHtcbiAgICAgIGNvbnRlbnQ6IHtcbiAgICAgICAgJ2FwcGxpY2F0aW9uL2pzb24nOiBhbnk7XG4gICAgICB9O1xuICAgIH0gfCBhbnk7XG4gIH07XG59XG5cbi8qKlxuICogQSB0eXBlIGRlZmluaXRpb24gZm9yIGFuIEFQSSBHYXRld2F5IHYxIHJlcXVlc3QgaGFuZGxlci5cbiAqL1xuZXhwb3J0IHR5cGUgQVBJR2F0ZXdheXYxSGFuZGxlciA9XG4gIEFXU0xhbWJkYS5IYW5kbGVyPEFXU0xhbWJkYS5BUElHYXRld2F5UHJveHlXaXRoQ29nbml0b0F1dGhvcml6ZXJFdmVudCwgQVdTTGFtYmRhLkFQSUdhdGV3YXlQcm94eVJlc3VsdCB8IHVuZGVmaW5lZD47XG5cbi8qKlxuICogQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHByb3BlcnRpZXMgZm9yIGFuIE9wZW5BUEkgb3BlcmF0aW9uIHdpdGggYSByZXF1ZXN0IGJvZHkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3BlcmF0aW9uV2l0aFJlcXVlc3RCb2R5IGV4dGVuZHMgT3BlcmF0aW9uIHtcbiAgcmVxdWVzdEJvZHk6IHsgY29udGVudDogeyAnYXBwbGljYXRpb24vanNvbic6IGFueSB9IH07XG59XG5cbi8qKlxuICogQSBmYWN0b3J5IGZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBhbiBIVFRQIHJlcXVlc3QgaGFuZGxlciBmb3IgYW4gT3BlbkFQSSBvcGVyYXRpb24gd2l0aCBhIHJlcXVlc3QgYm9keS5cbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZU9wZW5BcGlIYW5kbGVyV2l0aFJlcXVlc3RCb2R5ID0gPE9QIGV4dGVuZHMgT3BlcmF0aW9uV2l0aFJlcXVlc3RCb2R5LCBTQyBleHRlbmRzIG51bWJlciA9IDIwMD4oaGFuZGxlcjogSHR0cEhhbmRsZXI8T1BbJ3JlcXVlc3RCb2R5J11bJ2NvbnRlbnQnXVsnYXBwbGljYXRpb24vanNvbiddLCBPUFsncmVzcG9uc2VzJ11bU0NdWydjb250ZW50J11bJ2FwcGxpY2F0aW9uL2pzb24nXT4pOiBBUElHYXRld2F5djFIYW5kbGVyID0+IHtcbiAgcmV0dXJuIGNyZWF0ZUh0dHBIYW5kbGVyKGhhbmRsZXIpO1xufTtcblxuLyoqXG4gKiBBIGZhY3RvcnkgZnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIEhUVFAgcmVxdWVzdCBoYW5kbGVyIGZvciBhbiBPcGVuQVBJIG9wZXJhdGlvbiB3aXRoIGEgcmVxdWVzdCBib2R5IGFuZCBubyByZXNwb25zZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZU9wZW5BcGlIYW5kbGVyV2l0aFJlcXVlc3RCb2R5Tm9SZXNwb25zZSA9IDxPUCBleHRlbmRzIE9wZXJhdGlvbldpdGhSZXF1ZXN0Qm9keT4oaGFuZGxlcjogSHR0cEhhbmRsZXI8T1BbJ3JlcXVlc3RCb2R5J11bJ2NvbnRlbnQnXVsnYXBwbGljYXRpb24vanNvbiddLCB2b2lkPik6IEFQSUdhdGV3YXl2MUhhbmRsZXIgPT4ge1xuICByZXR1cm4gY3JlYXRlSHR0cEhhbmRsZXIoaGFuZGxlcik7XG59O1xuXG4vKipcbiAqIEEgZmFjdG9yeSBmdW5jdGlvbiB0aGF0IGNyZWF0ZXMgYW4gSFRUUCByZXF1ZXN0IGhhbmRsZXIgZm9yIGFuIE9wZW5BUEkgb3BlcmF0aW9uLlxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlT3BlbkFwaUhhbmRsZXIgPSA8T1AgZXh0ZW5kcyBPcGVyYXRpb24sIFNDIGV4dGVuZHMgbnVtYmVyID0gMjAwPihoYW5kbGVyOiBIdHRwSGFuZGxlcjxhbnksIE9QWydyZXNwb25zZXMnXVtTQ11bJ2NvbnRlbnQnXVsnYXBwbGljYXRpb24vanNvbiddPik6IEFQSUdhdGV3YXl2MUhhbmRsZXIgPT4ge1xuICByZXR1cm4gY3JlYXRlSHR0cEhhbmRsZXIoaGFuZGxlcik7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhbiBhdXRob3JpemVyIGZvciB0aGUgYXV0aGVudGljYXRpb24gbWV0aG9kIGNob3NlbiAoSldUIG9yIENvZ25pdG8pLlxuICovXG5jb25zdCBjcmVhdGVBdXRob3JpemVyID0gKGV2ZW50OiBBV1NMYW1iZGEuQVBJR2F0ZXdheVByb3h5RXZlbnRCYXNlPEFXU0xhbWJkYS5BUElHYXRld2F5UHJveHlDb2duaXRvQXV0aG9yaXplcj4sIGxvZzogTGFtYmRhTG9nKSA9PiB7XG4gIC8vIElmIENvZ25pdG8gaXMgdXNlZCwgVVNFUl9QT09MX0lEIGlzIGluamVjdGVkIGludG8gdGhlIGZ1bmN0aW9uJ3MgZW52aXJvbm1lbnQuIEN1cnJlbnRseSBhc3N1bWVzIEpXVCBvdGhlcndpc2UuXG4gIGlmIChlbnYuVVNFUl9QT09MX0lEKSB7XG4gICAgcmV0dXJuIG5ldyBBcGlHYXRld2F5djFDb2duaXRvQXV0aG9yaXplcihldmVudCwgbG9nKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBUaGlzIG1pZ2h0IG5lZWQgdG8gZ2V0IG1vcmUgc29waGlzdGljYXRlZCBpZiBtb3JlIGF1dGhvcml6YXRpb24gbWV0aG9kcyBuZWVkIHRvIGJlIHN1cHBvcnRlZC5cbiAgICByZXR1cm4gbmV3IEFwaUdhdGV3YXl2MUp3dEF1dGhvcml6ZXIoZXZlbnQsICdhZG1pbicsIGxvZyk7XG4gIH1cbn07XG5cbi8qKlxuICogQSBmYWN0b3J5IGZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBhbiBIVFRQIHJlcXVlc3QgaGFuZGxlci5cbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZUh0dHBIYW5kbGVyID1cbiAgPFQsIFI+KGhhbmRsZXI6IEh0dHBIYW5kbGVyPFQsIFI+KTogQVBJR2F0ZXdheXYxSGFuZGxlciA9PiB7XG4gICAgcmV0dXJuIGFzeW5jIChldmVudCwgY29udGV4dCkgPT4ge1xuICAgICAgLy8gQ3JlYXRlIGFuIG9iamVjdCB0byBob2xkIHRoZSBjb250ZXh0IGZvciB0aGlzIEhUVFAgcmVxdWVzdFxuICAgICAgY29uc3QgYXV0aCA9IGNyZWF0ZUF1dGhvcml6ZXIoZXZlbnQsIGxvZ2dlciBhcyB1bmtub3duIGFzIGxvZ2dlci5MYW1iZGFMb2cpO1xuICAgICAgY29uc3QgY3R4OiBIdHRwSGFuZGxlckNvbnRleHQgPSB7XG4gICAgICAgIGV2ZW50LFxuICAgICAgICBhdXRoLFxuICAgICAgICBsYW1iZGFDb250ZXh0OiBjb250ZXh0LFxuICAgICAgICBsb2dnZXI6IGxvZ2dlciBhcyB1bmtub3duIGFzIGxvZ2dlci5MYW1iZGFMb2csXG4gICAgICAgIHJlc3BvbnNlOiB7IGhlYWRlcnM6IHt9LCBqc29uOiB0cnVlIH0sXG4gICAgICB9O1xuICAgICAgLy8gQWRkIHRoZSByZXF1ZXN0IElEIHRvIHRoZSBsb2dnaW5nIG1ldGFkYXRhLCBhbmQgZW5hYmxlIGRlYnVnIGxvZ2dpbmcgaWYgdGhlIERFQlVHIGVudmlyb25tZW50IHZhcmlhYmxlIGlzIHNldCB0byBcInRydWVcIlxuICAgICAgY3R4LmxvZ2dlci5vcHRpb25zLm1ldGEucmVxdWVzdElkID0gY29udGV4dC5hd3NSZXF1ZXN0SWQ7XG4gICAgICBjdHgubG9nZ2VyLm9wdGlvbnMuZGVidWcgPSBwcm9jZXNzLmVudi5ERUJVRyA9PT0gJ3RydWUnO1xuXG4gICAgICAvLyBMb2cgdGhlIGV2ZW50IG9iamVjdCBmb3IgZGVidWdnaW5nIHB1cnBvc2VzXG4gICAgICBjdHgubG9nZ2VyLmRlYnVnKEpTT04uc3RyaW5naWZ5KGV2ZW50KSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIEF1dGhlbnRpY2F0ZSB0aGUgdXNlciB1c2luZyB0aGUgQ29nbml0byBhdXRob3JpemVyXG4gICAgICAgIGF3YWl0IGN0eC5hdXRoLmF1dGhlbnRpY2F0ZSgpO1xuXG4gICAgICAgIC8vIENhbGwgdGhlIHVzZXItZGVmaW5lZCBoYW5kbGVyIGZ1bmN0aW9uLCBwYXNzaW5nIGluIHRoZSByZXF1ZXN0IGNvbnRleHQgb2JqZWN0IGFuZCB0aGUgcGFyc2VkIHJlcXVlc3QgYm9keVxuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBoYW5kbGVyKGN0eCwgcGFyc2VCb2R5KGV2ZW50KSk7XG5cbiAgICAgICAgLy8gQ29uc3RydWN0IGFuZCByZXR1cm4gdGhlIEhUVFAgcmVzcG9uc2VcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdGF0dXNDb2RlOiBjdHgucmVzcG9uc2Uuc3RhdHVzQ29kZSA/PyAocmVzID8gMjAwIDogMjA0KSxcbiAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgLi4uY29yc0hlYWRlcihldmVudCksXG4gICAgICAgICAgICAuLi5jdHgucmVzcG9uc2UuaGVhZGVycyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGJvZHk6IHJlcyA/IChjdHgucmVzcG9uc2UuanNvbiA/IEpTT04uc3RyaW5naWZ5KHJlcykgOiByZXMpIDogJycsXG4gICAgICAgIH07XG4gICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAgIC8vIEhhbmRsZSBhbnkgZXJyb3JzIHRoYXQgb2NjdXIgZHVyaW5nIHJlcXVlc3QgcHJvY2Vzc2luZ1xuXG4gICAgICAgIC8vIElmIHRoZSBlcnJvciBpcyBhbiBpbnN0YW5jZSBvZiBIdHRwRXJyb3IsIHJldHVybiBhbiBIVFRQIHJlc3BvbnNlIHdpdGggdGhlIGVycm9yIHN0YXR1cyBjb2RlIGFuZCBtZXNzYWdlXG4gICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIGVycm9ycy5IdHRwRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RhdHVzQ29kZTogZXJyb3Iuc3RhdHVzQ29kZSxcbiAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgLi4uY29yc0hlYWRlcihldmVudCksXG4gICAgICAgICAgICAgIC4uLmN0eC5yZXNwb25zZS5oZWFkZXJzLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGJvZHk6IGVycm9yLm1lc3NhZ2UsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICAvLyBJZiB0aGUgZXJyb3IgaXMgYSBCb29tIGVycm9yIChmcm9tIHRoZSBoYXBpLmpzIGZyYW1ld29yayksIHJldHVybiBhbiBIVFRQIHJlc3BvbnNlIHdpdGggdGhlIGVycm9yIHN0YXR1cyBjb2RlIGFuZCBwYXlsb2FkXG4gICAgICAgIGlmIChlcnJvci5pc0Jvb20pIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RhdHVzQ29kZTogZXJyb3Iub3V0cHV0LnN0YXR1c0NvZGUsXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAgIC4uLmVycm9yLm91dHB1dC5oZWFkZXJzLFxuICAgICAgICAgICAgICAuLi5jb3JzSGVhZGVyKGV2ZW50KSxcbiAgICAgICAgICAgICAgLi4uY3R4LnJlc3BvbnNlLmhlYWRlcnMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoZXJyb3Iub3V0cHV0LnBheWxvYWQpLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgLy8gRm9yIGFsbCBvdGhlciB0eXBlcyBvZiBlcnJvcnMsIGxvZyB0aGUgZXJyb3IgYW5kIHJldHVybiBhIDUwMCBzdGF0dXMgY29kZSB3aXRoIHRoZSBlcnJvciBtZXNzYWdlXG4gICAgICAgIGN0eC5sb2dnZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN0YXR1c0NvZGU6IGN0eC5yZXNwb25zZS5zdGF0dXNDb2RlID8/IDUwMCxcbiAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgLi4uY29yc0hlYWRlcihldmVudCksXG4gICAgICAgICAgICAuLi5jdHgucmVzcG9uc2UuaGVhZGVycyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGJvZHk6IGVycm9yLnRvU3RyaW5nKCksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuLyoqXG4gKiBMb29rcyB1cCBhIGhlYWRlciB2YWx1ZSBjYXNlLWluc2Vuc2l0aXZlbHkuXG4gKiBIVFRQIGhlYWRlciBuYW1lcyBhcmUgY2FzZS1pbnNlbnNpdGl2ZSBwZXIgUkZDIDkxMTAgwqc1LjEuXG4gKi9cbmZ1bmN0aW9uIGhlYWRlclZhbHVlKGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD4gfCBudWxsIHwgdW5kZWZpbmVkLCBuYW1lOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIWhlYWRlcnMpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IGtleSA9IE9iamVjdC5rZXlzKGhlYWRlcnMpLmZpbmQoayA9PiBrLnRvTG93ZXJDYXNlKCkgPT09IG5hbWUudG9Mb3dlckNhc2UoKSk7XG4gIHJldHVybiBrZXkgPyBoZWFkZXJzW2tleV0gOiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiB0YWtlcyBhbiBldmVudCBvYmplY3QgcmVwcmVzZW50aW5nIGFuIEFQSSBHYXRld2F5IFByb3h5IGV2ZW50XG4gKiB3aXRoIGEgQ29nbml0byBhdXRob3JpemVyLCBhbmQgZXh0cmFjdHMgYW5kIHBhcnNlcyB0aGUgcmVxdWVzdCBib2R5LCBpZiBwcmVzZW50LlxuICpcbiAqIEBwYXJhbSBldmVudCBUaGUgQVBJIEdhdGV3YXkgUHJveHkgZXZlbnQgd2l0aCBhIENvZ25pdG8gYXV0aG9yaXplclxuICogQHJldHVybnMgVGhlIHBhcnNlZCByZXF1ZXN0IGJvZHlcbiAqL1xuZnVuY3Rpb24gcGFyc2VCb2R5PFQ+KGV2ZW50OiBBV1NMYW1iZGEuQVBJR2F0ZXdheVByb3h5V2l0aENvZ25pdG9BdXRob3JpemVyRXZlbnQpOiBUIHtcbiAgbGV0IGJvZHkgPSBldmVudC5ib2R5O1xuXG4gIC8vIElmIHRoZSByZXF1ZXN0IGJvZHkgaXMgYmFzZTY0LWVuY29kZWQsIGRlY29kZSBpdFxuICBpZiAoZXZlbnQuYm9keSAmJiBldmVudC5pc0Jhc2U2NEVuY29kZWQpIHtcbiAgICBjb25zdCBidWZmID0gQnVmZmVyLmZyb20oZXZlbnQuYm9keSEsICdiYXNlNjQnKTtcbiAgICBib2R5ID0gYnVmZi50b1N0cmluZygndXRmOCcpO1xuICB9XG5cbiAgLy8gSWYgdGhlIHJlcXVlc3QgYm9keSBpcyBpbiBKU09OIGZvcm1hdCwgcGFyc2UgaXQgaW50byBhIEphdmFTY3JpcHQgb2JqZWN0XG4gIGlmIChoZWFkZXJWYWx1ZShldmVudC5oZWFkZXJzLCAnY29udGVudC10eXBlJyk/LmluY2x1ZGVzKCdhcHBsaWNhdGlvbi9qc29uJykpIHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShib2R5ID8/ICd7fScpO1xuICB9XG5cbiAgLy8gSWYgdGhlIHJlcXVlc3QgYm9keSBpcyBub3QgcHJlc2VudCBvciBub3QgaW4gSlNPTiBmb3JtYXQsIHJldHVybiBpdCBhcy1pc1xuICByZXR1cm4gYm9keSBhcyBhbnk7XG59XG5cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBDT1JTIGhlYWRlcnMgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIEFQSSBHYXRld2F5IHJlc3BvbnNlLlxuICpcbiAqIEBwYXJhbSBldmVudCAtIFRoZSBBUEkgR2F0ZXdheSBldmVudCBvYmplY3QuXG4gKiBAcmV0dXJucyBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgQ09SUyBoZWFkZXJzLlxuICovXG5mdW5jdGlvbiBjb3JzSGVhZGVyKGV2ZW50OiBBV1NMYW1iZGEuQVBJR2F0ZXdheVByb3h5V2l0aENvZ25pdG9BdXRob3JpemVyRXZlbnQpOiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfSB7XG4gIGNvbnN0IG9yaWdpbiA9IGhlYWRlclZhbHVlKGV2ZW50Py5oZWFkZXJzLCAnb3JpZ2luJyk7XG4gIHJldHVybiB7XG4gICAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbic6IG9yaWdpbiA/PyAnKicsIC8vIEFsbG93IHJlcXVlc3RzIGZyb20gdGhlIG9yaWdpbiBoZWFkZXIsIG9yIGFsbG93IGFueSBvcmlnaW4gaWYgbm90IHByZXNlbnRcbiAgICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctQ3JlZGVudGlhbHMnOiBvcmlnaW4gPyAndHJ1ZScgOiAnZmFsc2UnLCAvLyBJbmNsdWRlIGNvb2tpZXMgaW4gY3Jvc3Mtb3JpZ2luIHJlcXVlc3RzIGlmIHRoZSBvcmlnaW4gaGVhZGVyIGlzIHByZXNlbnRcbiAgICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcyc6ICcqJywgLy8gQWxsb3cgYW55IEhUVFAgbWV0aG9kXG4gICAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMnOiAnQXV0aG9yaXphdGlvbiwgKicsIC8vIEFsbG93IHRoZSBBdXRob3JpemF0aW9uIGhlYWRlciBhbmQgYW55IG90aGVyIGhlYWRlcnNcbiAgfTtcbn1cblxuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4vLy8gQXBwU3luY1xuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbi8qKlxuICogVGhlIGNvbnRleHQgZm9yIHRoZSBBcHBTeW5jIHJlc29sdmVyIGZ1bmN0aW9uLlxuICogQ29udGFpbnMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGV2ZW50LCBsYW1iZGEgY29udGV4dCwgbG9nZ2VyLCBhbmQgQ29nbml0byBhdXRob3JpemVyLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFwcFN5bmNIYW5kbGVyQ29udGV4dDxUPiB7XG4gIGV2ZW50OiBBV1NMYW1iZGEuQXBwU3luY1Jlc29sdmVyRXZlbnQ8VD47XG4gIGxhbWJkYUNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0O1xuICBsb2dnZXI6IGxvZ2dlci5MYW1iZGFMb2c7XG4gIGNvZ25pdG9BdXRoOiBDb2duaXRvQXV0aG9yaXplcjtcbn1cblxuLyoqXG4gKiBBIGZ1bmN0aW9uIHRoYXQgaGFuZGxlcyBhbiBBcHBTeW5jIHJlc29sdmVyIGV2ZW50LlxuICogUmVjZWl2ZXMgdGhlIGNvbnRleHQgb2JqZWN0IGFuZCByZXR1cm5zIHRoZSByZXNwb25zZS5cbiAqL1xuZXhwb3J0IHR5cGUgQXBwU3luY0hhbmRsZXI8VCwgUj4gPSAoXG4gIGNvbnRleHQ6IEFwcFN5bmNIYW5kbGVyQ29udGV4dDxUPixcbikgPT4gUHJvbWlzZTxSPjtcblxuLyoqXG4gKiBNYXBzIGFuIEhUVFAgc3RhdHVzIGNvZGUgdG8gdGhlIEdyYXBoUUwgZXJyb3JUeXBlIHJlcG9ydGVkIHRvIEFwcFN5bmMuXG4gKlxuICogTG9jYWwgKG5vbi1leHBvcnRlZCkgaGVscGVyIHVzZWQgb25seSBieSBjcmVhdGVBcHBTeW5jSGFuZGxlciB3aGVuIGl0XG4gKiB0cmFuc2xhdGVzIGFuIGVycm9ycy5IdHRwRXJyb3IgaW50byBhIHR5cGVkIEFwcFN5bmMgZXJyb3IuIFRoZSBleHBsaWNpdFxuICogZGVmYXVsdCBrZWVwcyBhbnkgdW5tYXBwZWQgc3RhdHVzIChmb3IgZXhhbXBsZSBhIDQxOCBvciBhIDV4eCkgcmVwb3J0ZWQgYXNcbiAqIHRoZSBnZW5lcmljICdFcnJvcicgZXJyb3JUeXBlIHJhdGhlciB0aGFuIGxlYWtpbmcgdGhlIHJhdyBzdGF0dXMgY29kZS5cbiAqL1xuZnVuY3Rpb24gaHR0cFN0YXR1c1RvRXJyb3JUeXBlKHN0YXR1c0NvZGU6IG51bWJlcik6IHN0cmluZyB7XG4gIHN3aXRjaCAoc3RhdHVzQ29kZSkge1xuICAgIGNhc2UgNDAwOlxuICAgICAgcmV0dXJuICdCYWRSZXF1ZXN0JztcbiAgICBjYXNlIDQwMTpcbiAgICAgIHJldHVybiAnVW5hdXRob3JpemVkJztcbiAgICBjYXNlIDQwMzpcbiAgICAgIHJldHVybiAnRm9yYmlkZGVuJztcbiAgICBjYXNlIDQwNDpcbiAgICAgIHJldHVybiAnTm90Rm91bmQnO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gJ0Vycm9yJztcbiAgfVxufVxuXG4vKipcbiAqIFRoZSB0eXBlZC1lcnJvciBzaGFwZSBzaGFyZWQgYnkgY3JlYXRlQXBwU3luY0hhbmRsZXIgYW5kIGNyZWF0ZUFwcFN5bmNCYXRjaEhhbmRsZXIuXG4gKi9cbmludGVyZmFjZSBUeXBlZEFwcFN5bmNFcnJvciB7XG4gIGVycm9yVHlwZTogc3RyaW5nO1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIGVycm9ySW5mbz86IFJlY29yZDxzdHJpbmcsIGFueT47XG59XG5cbi8qKlxuICogTm9ybWFsaXNlcyB0aGUgdHdvIHJlY29nbmlzZWQgdHlwZWQtZXJyb3Igc2hhcGVzIHRvIGEgY29tbW9uXG4gKiB7IGVycm9yVHlwZSwgbWVzc2FnZSwgZXJyb3JJbmZvIH0gc28gdGhlIGdhdGUsIGVudmVsb3BlIGFuZCByZXRocm93IGFyZSBhXG4gKiBzaW5nbGUgY29kZSBwYXRoIGFjcm9zcyB0aGUgc2luZ2xlIGFuZCBiYXRjaCBoYW5kbGVycy4gUmV0dXJucyB1bmRlZmluZWQgZm9yXG4gKiBhbnl0aGluZyB0aGF0IGlzIG5laXRoZXIgKHBsYWluIEVycm9yLCBCb29tKSwgd2hpY2ggdGhlIGNhbGxlcnMgcmV0aHJvdy5cbiAqXG4gKiAtIGFwcHN5bmNFcnJvcnMuQXBwU3luY0Vycm9yIGNhcnJpZXMgaXRzIG93biBHcmFwaFFMIGVycm9yVHlwZSBhbmQgYW4gb3B0aW9uYWxcbiAqICAgZXJyb3JJbmZvLCB3aGljaCBmbG93IHRocm91Z2ggdW5jaGFuZ2VkLlxuICogLSBlcnJvcnMuSHR0cEVycm9yICh0aGUgSFRUUCBiYXNlIHRocm93biBieSB0aGUgc2hhcmVkIEp3dEF1dGhvcml6ZXIgdmlhXG4gKiAgIGFzc2VydEF1dGhlbnRpY2F0ZWQvYXNzZXJ0R3JvdXAvYXNzZXJ0QWRtaW4sIGFuZCBieSByZXNvbHZlciBjb2RlIGRpcmVjdGx5KVxuICogICBoYXMgbm8gR3JhcGhRTCBlcnJvclR5cGUsIHNvIG1hcCBpdHMgc3RhdHVzQ29kZSB3aXRoIGh0dHBTdGF0dXNUb0Vycm9yVHlwZS5cbiAqICAgSHR0cEVycm9yIGNhcnJpZXMgbm8gZXJyb3JJbmZvLCBzbyBlcnJvckluZm8gaXMgdW5kZWZpbmVkLlxuICpcbiAqIFRoZSB0d28gaW5zdGFuY2VvZiBjaGVja3MgYXJlIGRpc2pvaW50OiBIdHRwRXJyb3IgYW5kIEFwcFN5bmNFcnJvciBzaGFyZSBub1xuICogYW5jZXN0cnksIHNvIGFuIGFwcHN5bmMuRm9yYmlkZGVuRXJyb3IgdGFrZXMgdGhlIEFwcFN5bmNFcnJvciBicmFuY2ggYW5kIGFuXG4gKiBlcnJvcnMuRm9yYmlkZGVuRXJyb3IgdGhlIEh0dHBFcnJvciBicmFuY2guXG4gKi9cbmZ1bmN0aW9uIHRvVHlwZWRFcnJvcihlcnJvcjogYW55KTogVHlwZWRBcHBTeW5jRXJyb3IgfCB1bmRlZmluZWQge1xuICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBhcHBzeW5jRXJyb3JzLkFwcFN5bmNFcnJvcikge1xuICAgIHJldHVybiB7IGVycm9yVHlwZTogZXJyb3IuZXJyb3JUeXBlLCBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLCBlcnJvckluZm86IGVycm9yLmVycm9ySW5mbyB9O1xuICB9IGVsc2UgaWYgKGVycm9yIGluc3RhbmNlb2YgZXJyb3JzLkh0dHBFcnJvcikge1xuICAgIHJldHVybiB7IGVycm9yVHlwZTogaHR0cFN0YXR1c1RvRXJyb3JUeXBlKGVycm9yLnN0YXR1c0NvZGUpLCBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLCBlcnJvckluZm86IHVuZGVmaW5lZCB9O1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogQnVpbGRzIHRoZSBkaXJlY3QtTGFtYmRhIGVycm9yIGVudmVsb3BlIEFwcFN5bmMgc3VyZmFjZXMgYXMgYSB0eXBlZCBHcmFwaFFMXG4gKiBlcnJvci4gX19hcHBTeW5jRXJyb3IgaXMgYSByZXNlcnZlZCBzZW50aW5lbCBrZXkgdGhlIHJlc29sdmVyIHJlc3BvbnNlIGhhbmRsZXJcbiAqIGtleXMgb24gdG8gcmVjb2duaXNlIHRoaXMgZW52ZWxvcGUuIEJyYW5jaGluZyBvbiB0aGUgc2VudGluZWwgKHJhdGhlciB0aGFuIG9uXG4gKiBhIGJhcmUgZXJyb3JNZXNzYWdlKSBtZWFucyBhIGxlZ2l0aW1hdGUgcmVzb2x2ZXIgcmVzdWx0IHRoYXQgbWVyZWx5IGNvbnRhaW5zXG4gKiBhbiBlcnJvck1lc3NhZ2UgZmllbGQgaXMgbm90IG1pc2NsYXNzaWZpZWQgYXMgYSB0eXBlZCBlcnJvci5cbiAqL1xuZnVuY3Rpb24gYnVpbGRFcnJvckVudmVsb3BlPFI+KHR5cGVkOiBUeXBlZEFwcFN5bmNFcnJvcik6IFIge1xuICByZXR1cm4ge1xuICAgIF9fYXBwU3luY0Vycm9yOiB0cnVlLFxuICAgIGRhdGE6IG51bGwsXG4gICAgZXJyb3JUeXBlOiB0eXBlZC5lcnJvclR5cGUsXG4gICAgZXJyb3JNZXNzYWdlOiB0eXBlZC5tZXNzYWdlLFxuICAgIGVycm9ySW5mbzogdHlwZWQuZXJyb3JJbmZvLFxuICB9IGFzIHVua25vd24gYXMgUjtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIEFwcFN5bmMgcmVzb2x2ZXIgaGFuZGxlciBmcm9tIHRoZSBnaXZlbiBBcHBTeW5jSGFuZGxlci5cbiAqIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IGNhbiBiZSB1c2VkIGFzIGFuIEFwcFN5bmMgcmVzb2x2ZXIuXG4gKlxuICogQHBhcmFtIGhhbmRsZXIgVGhlIEFwcFN5bmNIYW5kbGVyIHRvIHVzZSBhcyB0aGUgcmVzb2x2ZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVBcHBTeW5jSGFuZGxlciA9XG4gIDxULCBSPihoYW5kbGVyOiBBcHBTeW5jSGFuZGxlcjxULCBSPik6IEFXU0xhbWJkYS5BcHBTeW5jUmVzb2x2ZXJIYW5kbGVyPFQsIFI+ID0+IHtcbiAgICByZXR1cm4gYXN5bmMgKGV2ZW50LCBjb250ZXh0KSA9PiB7XG4gICAgICBjb25zdCBjdHg6IEFwcFN5bmNIYW5kbGVyQ29udGV4dDxUPiA9IHtcbiAgICAgICAgZXZlbnQsXG4gICAgICAgIGxhbWJkYUNvbnRleHQ6IGNvbnRleHQsXG4gICAgICAgIGxvZ2dlcjogbG9nZ2VyIGFzIHVua25vd24gYXMgbG9nZ2VyLkxhbWJkYUxvZyxcbiAgICAgICAgY29nbml0b0F1dGg6IG5ldyBBcHBTeW5jQ29nbml0b0F1dGhvcml6ZXIoZXZlbnQpLFxuICAgICAgfTtcblxuICAgICAgLy8gc2V0IHRoZSBtZXRhIGluZm9ybWF0aW9uIGluIGxvZ2dlclxuICAgICAgY3R4LmxvZ2dlci5vcHRpb25zLm1ldGEucmVxdWVzdElkID0gY29udGV4dC5hd3NSZXF1ZXN0SWQ7XG4gICAgICAvLyBzZXQgdGhlIGRlYnVnIGZsYWcgZm9yIGxvZ2dlclxuICAgICAgY3R4LmxvZ2dlci5vcHRpb25zLmRlYnVnID0gcHJvY2Vzcy5lbnYuREVCVUcgPT09ICd0cnVlJztcblxuICAgICAgLy8gbG9nIHRoZSByZWNlaXZlZCBldmVudFxuICAgICAgY3R4LmxvZ2dlci5kZWJ1ZyhKU09OLnN0cmluZ2lmeShldmVudCkpO1xuXG4gICAgICB0cnkge1xuICAgICAgICAvLyBhdXRoZW50aWNhdGUgdGhlIGluY29taW5nIHJlcXVlc3RcbiAgICAgICAgYXdhaXQgY3R4LmNvZ25pdG9BdXRoLmF1dGhlbnRpY2F0ZSgpO1xuICAgICAgICAvLyBpbnZva2UgdGhlIGhhbmRsZXIgZnVuY3Rpb24gd2l0aCB0aGUgY29udGV4dFxuICAgICAgICByZXR1cm4gYXdhaXQgaGFuZGxlcihjdHgpO1xuICAgICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgICBjb25zdCB0eXBlZCA9IHRvVHlwZWRFcnJvcihlcnJvcik7XG5cbiAgICAgICAgaWYgKHR5cGVkICYmIHByb2Nlc3MuZW52LkFQUFNZTkNfVFlQRURfRVJST1JTID09PSAndHJ1ZScpIHtcbiAgICAgICAgICAvLyBUaGUgZW52ZWxvcGUtcmV0dXJuIGlzIGdhdGVkIG9uIEFQUFNZTkNfVFlQRURfRVJST1JTID09PSAndHJ1ZScuXG4gICAgICAgICAgLy8gR3JhcGhRbEFwaS5hZGRMYW1iZGFSZXNvbHZlciBpbmplY3RzIHRoYXQgZW52IHZhciBvbmx5IG9uIGl0c1xuICAgICAgICAgIC8vIHR5cGVkRXJyb3JzOiB0cnVlIHBhdGgsIHdob3NlIEFQUFNZTkNfSlMgcmVzb2x2ZXIgaGFzIGEgcmVzcG9uc2VcbiAgICAgICAgICAvLyBoYW5kbGVyIHRoYXQgcmVhZHMgdGhpcyBlbnZlbG9wZSBhbmQgY2FsbHNcbiAgICAgICAgICAvLyB1dGlsLmVycm9yKGVycm9yTWVzc2FnZSwgZXJyb3JUeXBlLCBudWxsLCBlcnJvckluZm8pLCB0dXJuaW5nIGl0IGludG9cbiAgICAgICAgICAvLyBhIEdyYXBoUUwgZXJyb3Igb24gYSBzdWNjZXNzZnVsIGludm9jYXRpb24uIFJldHVybmluZyAobm90IHRocm93aW5nKVxuICAgICAgICAgIC8vIGtlZXBzIHRoZSBpbnZvY2F0aW9uIG9mZiB0aGUgTGFtYmRhIEVycm9ycyBtZXRyaWMuXG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyBXaGVuIHRoZSBlbnYgdmFyIGlzIGFic2VudCAodGhlIGRlZmF1bHQgVU5JVCByZXNvbHZlciBwYXRoLCBvciBhXG4gICAgICAgICAgLy8gaGFuZC13aXJlZCBoYW5kbGVyIHVzZWQgd2l0aG91dCBHcmFwaFFsQXBpKSB0aGUgdHlwZWQgZXJyb3IgZmFsbHNcbiAgICAgICAgICAvLyB0aHJvdWdoIHRvIHRoZSByZXRocm93IGJlbG93LCBzbyB0aGUgaW52b2NhdGlvbiBmYWlscyBsb3VkbHkgaW5zdGVhZFxuICAgICAgICAgIC8vIG9mIHN1cmZhY2luZyB0aGUgZW52ZWxvcGUgYXMgZmllbGQgZGF0YS4gQW55IHZhbHVlIG90aGVyIHRoYW4gdGhlXG4gICAgICAgICAgLy8gZXhhY3Qgc3RyaW5nICd0cnVlJyBtZWFucyByZXRocm93LiBUaGlzIGlzIHdoeSBhIGRlZmF1bHQgVU5JVFxuICAgICAgICAgIC8vIHJlc29sdmVyIHdob3NlIGhhbmRsZXIgaGl0cyBhbiBhdXRoIGFzc2VydGlvbiAoYW4gSHR0cEVycm9yKSBzdGlsbFxuICAgICAgICAgIC8vIGZhaWxzIGxvdWRseSB1bmxlc3MgdHlwZWRFcnJvcnMgaXMgYWN0aXZlLlxuICAgICAgICAgIGN0eC5sb2dnZXIud2Fybih0eXBlZC5tZXNzYWdlLCB7IGVycm9yVHlwZTogdHlwZWQuZXJyb3JUeXBlLCBlcnJvckluZm86IHR5cGVkLmVycm9ySW5mbyB9KTtcbiAgICAgICAgICByZXR1cm4gYnVpbGRFcnJvckVudmVsb3BlPFI+KHR5cGVkKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBsb2cgdGhlIGVycm9yIGFuZCB0aHJvdyBpdCBhZ2FpblxuICAgICAgICBjdHgubG9nZ2VyLmVycm9yKGVycm9yKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuLyoqXG4gKiBUaGUgY29udGV4dCBmb3IgYSBiYXRjaGVkIEFwcFN5bmMgcmVzb2x2ZXIgZnVuY3Rpb24uXG4gKiBFeHRlbmRzIEFwcFN5bmNIYW5kbGVyQ29udGV4dCBzbyBoYW5kbGVyIGNvZGUgdGhhdCByZWFkcyBjdHguZXZlbnQuYXJndW1lbnRzIC9cbiAqIGN0eC5ldmVudC5pZGVudGl0eSBrZWVwcyB3b3JraW5nIGFnYWluc3QgdGhlIGZpcnN0IGV2ZW50LCBhbmQgYWRkaXRpb25hbGx5XG4gKiBleHBvc2VzIHRoZSBmdWxsIGJhdGNoIG9mIGV2ZW50cyBzbyB0aGUgaGFuZGxlciBjYW4gbWFwIG92ZXIgaXQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXBwU3luY0JhdGNoSGFuZGxlckNvbnRleHQ8VCwgUyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gfCBudWxsID0gUmVjb3JkPHN0cmluZywgYW55PiB8IG51bGw+IGV4dGVuZHMgQXBwU3luY0hhbmRsZXJDb250ZXh0PFQ+IHtcbiAgZXZlbnQ6IEFXU0xhbWJkYS5BcHBTeW5jUmVzb2x2ZXJFdmVudDxULCBTPjtcbiAgZXZlbnRzOiBBV1NMYW1iZGEuQXBwU3luY1Jlc29sdmVyRXZlbnQ8VCwgUz5bXTtcbn1cblxuLyoqXG4gKiBBIGZ1bmN0aW9uIHRoYXQgaGFuZGxlcyBhbiBBcHBTeW5jIEJhdGNoSW52b2tlIGV2ZW50LlxuICogUmVjZWl2ZXMgdGhlIGJhdGNoIGNvbnRleHQgYW5kIHJldHVybnMgdGhlIHJlc3BvbnNlcyBpbiBzb3VyY2Ugb3JkZXIuXG4gKi9cbmV4cG9ydCB0eXBlIEFwcFN5bmNCYXRjaEhhbmRsZXI8VCwgUiwgUyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gfCBudWxsID0gUmVjb3JkPHN0cmluZywgYW55PiB8IG51bGw+ID0gKFxuICBjb250ZXh0OiBBcHBTeW5jQmF0Y2hIYW5kbGVyQ29udGV4dDxULCBTPixcbikgPT4gUHJvbWlzZTxSW10+O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBiYXRjaGVkIEFwcFN5bmMgcmVzb2x2ZXIgaGFuZGxlciBmcm9tIHRoZSBnaXZlbiBBcHBTeW5jQmF0Y2hIYW5kbGVyLlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgY2FuIGJlIHVzZWQgYXMgYW4gQXBwU3luYyBCYXRjaEludm9rZSByZXNvbHZlcjogYXJyYXlcbiAqIGluLCBhcnJheSBvdXQsIG9yZGVyIHByZXNlcnZlZC5cbiAqXG4gKiBJdCBtaXJyb3JzIGNyZWF0ZUFwcFN5bmNIYW5kbGVyJ3MgY29udGV4dCBhbmQgYXV0aCBwbHVtYmluZyBidXQgb3BlcmF0ZXMgb24gYW5cbiAqIGFycmF5IG9mIGV2ZW50cy4gQXV0aGVudGljYXRpb24gcnVucyBvbmNlIHBlciBiYXRjaCBvZmYgdGhlIGZpcnN0IGV2ZW50LCBhbmRcbiAqIHRoZSBjb250ZXh0IGNhcnJpZXMgYm90aCB0aGUgZmlyc3QgZXZlbnQgKGN0eC5ldmVudCA9IGV2ZW50c1swXSkgYW5kIHRoZSBmdWxsXG4gKiBjdHguZXZlbnRzIGFycmF5LiBUaGUgaGFuZGxlciByZXR1cm5zIFJbXSBpbiB0aGUgc2FtZSBvcmRlciBhcyB0aGUgaW5wdXQgZXZlbnRzLlxuICpcbiAqIEBwYXJhbSBoYW5kbGVyIFRoZSBBcHBTeW5jQmF0Y2hIYW5kbGVyIHRvIHVzZSBhcyB0aGUgcmVzb2x2ZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVBcHBTeW5jQmF0Y2hIYW5kbGVyID1cbiAgPFQsIFIsIFMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgbnVsbCA9IFJlY29yZDxzdHJpbmcsIGFueT4gfCBudWxsPihcbiAgICBoYW5kbGVyOiBBcHBTeW5jQmF0Y2hIYW5kbGVyPFQsIFIsIFM+LFxuICApOiBBV1NMYW1iZGEuQXBwU3luY0JhdGNoUmVzb2x2ZXJIYW5kbGVyPFQsIFIsIFM+ID0+IHtcbiAgICByZXR1cm4gYXN5bmMgKGV2ZW50cywgY29udGV4dCkgPT4ge1xuICAgICAgLy8gQmF0Y2hJbnZva2UgYWx3YXlzIGRlbGl2ZXJzIGEgbm9uLWVtcHR5IGFycmF5OyBhdXRoZW50aWNhdGUgYW5kIGJ1aWxkXG4gICAgICAvLyB0aGUgY29udGV4dCBvZmYgdGhlIGZpcnN0IGV2ZW50LCBleGFjdGx5IGxpa2UgY3JlYXRlQXBwU3luY0hhbmRsZXIuXG4gICAgICBjb25zdCBmaXJzdCA9IGV2ZW50c1swXTtcbiAgICAgIGNvbnN0IGN0eDogQXBwU3luY0JhdGNoSGFuZGxlckNvbnRleHQ8VCwgUz4gPSB7XG4gICAgICAgIGV2ZW50OiBmaXJzdCxcbiAgICAgICAgZXZlbnRzLFxuICAgICAgICBsYW1iZGFDb250ZXh0OiBjb250ZXh0LFxuICAgICAgICBsb2dnZXI6IGxvZ2dlciBhcyB1bmtub3duIGFzIGxvZ2dlci5MYW1iZGFMb2csXG4gICAgICAgIGNvZ25pdG9BdXRoOiBuZXcgQXBwU3luY0NvZ25pdG9BdXRob3JpemVyKGZpcnN0KSxcbiAgICAgIH07XG5cbiAgICAgIC8vIHNldCB0aGUgbWV0YSBpbmZvcm1hdGlvbiBpbiBsb2dnZXJcbiAgICAgIGN0eC5sb2dnZXIub3B0aW9ucy5tZXRhLnJlcXVlc3RJZCA9IGNvbnRleHQuYXdzUmVxdWVzdElkO1xuICAgICAgLy8gc2V0IHRoZSBkZWJ1ZyBmbGFnIGZvciBsb2dnZXJcbiAgICAgIGN0eC5sb2dnZXIub3B0aW9ucy5kZWJ1ZyA9IHByb2Nlc3MuZW52LkRFQlVHID09PSAndHJ1ZSc7XG5cbiAgICAgIC8vIGxvZyB0aGUgcmVjZWl2ZWQgYmF0Y2ggb2YgZXZlbnRzXG4gICAgICBjdHgubG9nZ2VyLmRlYnVnKEpTT04uc3RyaW5naWZ5KGV2ZW50cykpO1xuXG4gICAgICB0cnkge1xuICAgICAgICAvLyBhdXRoZW50aWNhdGUgb25jZSBwZXIgYmF0Y2ggb2ZmIHRoZSBmaXJzdCBldmVudFxuICAgICAgICBhd2FpdCBjdHguY29nbml0b0F1dGguYXV0aGVudGljYXRlKCk7XG4gICAgICAgIC8vIGludm9rZSB0aGUgaGFuZGxlciBmdW5jdGlvbiB3aXRoIHRoZSBiYXRjaCBjb250ZXh0OyBpdCByZXR1cm5zIFJbXSBpbiBzb3VyY2Ugb3JkZXJcbiAgICAgICAgcmV0dXJuIGF3YWl0IGhhbmRsZXIoY3R4KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgY29uc3QgdHlwZWQgPSB0b1R5cGVkRXJyb3IoZXJyb3IpO1xuXG4gICAgICAgIGlmICh0eXBlZCAmJiBwcm9jZXNzLmVudi5BUFBTWU5DX1RZUEVEX0VSUk9SUyA9PT0gJ3RydWUnKSB7XG4gICAgICAgICAgLy8gU2FtZSBnYXRlIGFuZCBlbnZlbG9wZSBhcyBjcmVhdGVBcHBTeW5jSGFuZGxlci4gQXBwU3luYyBleHBlY3RzIG9uZVxuICAgICAgICAgIC8vIHJlc3VsdCBwZXIgZXZlbnQgaW4gYSBCYXRjaEludm9rZSByZXNwb25zZSwgc28gYSBiYXRjaC1sZXZlbCB0eXBlZFxuICAgICAgICAgIC8vIGVycm9yIHJldHVybnMgYW4gYXJyYXkgb2YgZW52ZWxvcGVzIGFsaWduZWQgdG8gdGhlIGJhdGNoIGxlbmd0aDtcbiAgICAgICAgICAvLyBlYWNoIGl0ZW0gc3VyZmFjZXMgdGhlIHNhbWUgdHlwZWQgZXJyb3IuIFJldHVybmluZyAobm90IHRocm93aW5nKVxuICAgICAgICAgIC8vIGtlZXBzIHRoZSBpbnZvY2F0aW9uIG9mZiB0aGUgTGFtYmRhIEVycm9ycyBtZXRyaWMuIFdpdGhvdXQgdGhlIGZsYWdcbiAgICAgICAgICAvLyB0aGUgdHlwZWQgZXJyb3IgZmFsbHMgdGhyb3VnaCB0byB0aGUgcmV0aHJvdyBiZWxvdy5cbiAgICAgICAgICBjdHgubG9nZ2VyLndhcm4odHlwZWQubWVzc2FnZSwgeyBlcnJvclR5cGU6IHR5cGVkLmVycm9yVHlwZSwgZXJyb3JJbmZvOiB0eXBlZC5lcnJvckluZm8gfSk7XG4gICAgICAgICAgcmV0dXJuIGV2ZW50cy5tYXAoKCkgPT4gYnVpbGRFcnJvckVudmVsb3BlPFI+KHR5cGVkKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbG9nIHRoZSBlcnJvciBhbmQgdGhyb3cgaXQgYWdhaW5cbiAgICAgICAgY3R4LmxvZ2dlci5lcnJvcihlcnJvcik7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgIH07XG4gIH07XG5cbiJdfQ==
|
package/llm.md
CHANGED
|
@@ -182,6 +182,16 @@ export const handler = createAppSyncHandler<GetItemsQuery, GetItemsResult>(async
|
|
|
182
182
|
});
|
|
183
183
|
```
|
|
184
184
|
|
|
185
|
+
For AppSync BatchInvoke, use `createAppSyncBatchHandler`. It takes an array of resolver events and returns an array of results in the same order (array in, array out, order preserved). It uses the same context as `createAppSyncHandler`, with the logger and the Cognito authorizer resolved once per batch off the first event. The context exposes both the first event as `ctx.event` (so handler code that reads `ctx.event.arguments` / `ctx.event.identity` keeps working) and the full batch as `ctx.events`. The typed-error model is identical to `createAppSyncHandler`: with `APPSYNC_TYPED_ERRORS === 'true'` a thrown `errors.appsync.*` or `errors.HttpError` returns an array of error envelopes aligned to the batch length, and otherwise rethrows. A plain `Error` always fails the invocation.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import { createAppSyncBatchHandler } from 'cdk-serverless/lambda';
|
|
189
|
+
|
|
190
|
+
export const handler = createAppSyncBatchHandler<GetItemQuery, Item>(async (ctx) => {
|
|
191
|
+
return Promise.all(ctx.events.map((event) => getItem(event.arguments.id)));
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
185
195
|
AppSync resolvers can throw typed errors from the `errors.appsync` namespace. `createAppSyncHandler` catches them and logs at `warn`. Whether it returns a `{ data, errorType, errorMessage, errorInfo }` envelope or rethrows is gated on the `APPSYNC_TYPED_ERRORS` environment variable. When `APPSYNC_TYPED_ERRORS === 'true'` the handler returns the envelope so the invocation stays off the Lambda Errors metric. Otherwise it rethrows the typed error, logging at `error`, so the invocation fails. A plain `Error` always fails the invocation regardless of the flag.
|
|
186
196
|
|
|
187
197
|
```typescript
|
|
@@ -200,12 +210,14 @@ export const handler = createAppSyncHandler<GetItemQuery, Item>(async (ctx) => {
|
|
|
200
210
|
|
|
201
211
|
HTTP errors from the shared authorizer are translated the same way. The shared `JwtAuthorizer` base throws `errors.UnauthenticatedError` (401) and `errors.ForbiddenError` (403) from `assertAuthenticated`/`assertGroup`/`assertAdmin`, and `AppSyncCognitoAuthorizer` extends that base, so these reach `createAppSyncHandler`'s catch. `createAppSyncHandler` treats any `errors.HttpError` like a typed error and maps its `statusCode` to an `errorType`: 400 `BadRequest`, 401 `Unauthorized`, 403 `Forbidden`, 404 `NotFound`, any other status `Error`. The mapped error goes through the same `APPSYNC_TYPED_ERRORS` gate and `{ __appSyncError: true, ... }` envelope as `errors.appsync.*` (with `errorInfo` undefined, since `HttpError` carries none). `src/lambda/auth.ts` and the HTTP handler `createHttpHandler` are unchanged. The same rethrow-when-not-activated rule applies, so a default UNIT resolver whose handler hits an auth assertion still fails loudly unless `typedErrors` is active.
|
|
202
212
|
|
|
203
|
-
The envelope only becomes a GraphQL error when the resolver is wired via `GraphQlApi.addLambdaResolver` and the API opts in with `typedErrors: true`. On that path the method creates an `APPSYNC_JS` pipeline resolver whose response handler reads the envelope and calls `util.error(errorMessage, errorType, null, errorInfo)
|
|
213
|
+
The envelope only becomes a GraphQL error when the resolver is wired via `GraphQlApi.addLambdaResolver` and the API opts in with `typedErrors: true`. On that path the method creates an `APPSYNC_JS` pipeline resolver whose response handler reads the envelope and calls `util.error(errorMessage, errorType, null, errorInfo)`, turning the typed error into a GraphQL error with the matching `errorType` and `errorInfo`. Invoke-level errors (an untyped error the handler rethrows, a timeout) are raised by the pipeline function's own response handler with `util.error(ctx.error.message, ctx.error.type)`, because AppSync drops an error left in a pipeline function's `ctx.error` and the field would resolve to `null` with no GraphQL error. Without `typedErrors: true`, `addLambdaResolver` creates a plain direct-Lambda UNIT resolver with no response handler and sets no `APPSYNC_TYPED_ERRORS` flag, so typed errors rethrow and surface as `Lambda:Unhandled`. If you build the pipeline yourself, replicate both response handlers.
|
|
204
214
|
|
|
205
215
|
The response handler recognises the envelope by a reserved `__appSyncError` sentinel key that `createAppSyncHandler` stamps, not by the presence of an `errorMessage` field. A resolver whose real return type happens to include an `errorMessage` field is therefore passed through unchanged.
|
|
206
216
|
|
|
207
217
|
Opting in with `typedErrors`: by default `addLambdaResolver` synthesizes a plain direct-Lambda UNIT resolver (the pre-#385 shape), so upgrading consumers who do not opt in see no resolver topology change and no `cdk diff` surprise. Set `typedErrors: true` on the `GraphQlApi` to get the typed `errors.appsync.*` behavior. With the flag enabled, each Lambda-backed field gains a new `AWS::AppSync::FunctionConfiguration` (`LambdaFn${type}.${field}`), and the resolver flips from a `dataSource` UNIT resolver to a `pipelineConfig` + `code` PIPELINE resolver with the response handler described above. The data source and resolver logical IDs are unchanged, so the resolver updates in place rather than being replaced, while the new per-field function resource is additive. The flag applies to all Lambda resolvers on the API, so run `cdk diff` after enabling it to review the topology change.
|
|
208
218
|
|
|
219
|
+
`maxBatchSize` wins over `typedErrors` per field. When a field passes `maxBatchSize` to `addLambdaResolver`, that field always gets the UNIT BatchInvoke resolver (MaxBatchSize plus the BatchInvoke request template and the `lambdaResult` response template), even when the API has `typedErrors: true`. The batch field gets no APPSYNC_JS pipeline, no `AWS::AppSync::FunctionConfiguration`, and no `APPSYNC_TYPED_ERRORS` env var on its Lambda, so it synthesizes identically whether or not the API enables `typedErrors`. The trade-off is that typed errors thrown by a batch handler are not converted to GraphQL errors. They rethrow and fail the invocation, so do not rely on the typed-error-to-GraphQL-error conversion in a batch handler. Non-batch fields on the same API keep the `typedErrors` pipeline behavior described above.
|
|
220
|
+
|
|
209
221
|
`APPSYNC_TYPED_ERRORS` is the coupling mechanism between the handler and the pipeline. `createAppSyncHandler` returns the `{ __appSyncError: true, ... }` sentinel envelope only when `APPSYNC_TYPED_ERRORS === 'true'` is set in the Lambda environment, and rethrows the `errors.appsync.*` error otherwise. `GraphQlApi.addLambdaResolver` injects `APPSYNC_TYPED_ERRORS=true` automatically on the `typedErrors: true` path, the same path that carries the response handler to translate the envelope. On the default UNIT path the flag is left unset, so a handler that throws an `errors.appsync.*` error fails the invocation loudly (rethrow) instead of returning a broken envelope as field data. If you wire `createAppSyncHandler` yourself without `GraphQlApi`, set `APPSYNC_TYPED_ERRORS=true` on the Lambda yourself to get envelope behavior and replicate the response handler. Without it, typed errors rethrow.
|
|
210
222
|
|
|
211
223
|
Two classes share the short names `ForbiddenError` and `NotFoundError`, so pick the namespace deliberately:
|