UNPKG

@energica-city/shared-amplify-utils

Version:

Shared utilities for AWS Amplify projects

209 lines 25.8 kB
import { logger } from '../../log'; import { throwError } from '../../error'; import { ERROR_CODES, initializeRestMiddleware, isDevelopment, getErrorMessage, getErrorStack, } from './utils'; /** * Type guard to check if an error is a middleware error * @param error - Error of unknown type * @returns True if error is a MiddlewareError with middlewareName property */ function isMiddlewareError(error) { return (error instanceof Error && typeof error.middlewareName === 'string'); } /** * Extracts middleware information from a MiddlewareError * @param error - Middleware error object * @returns Object containing middleware name, index, total count, and chain */ function getMiddlewareInfo(error) { return { name: error.middlewareName || 'unknown', index: error.middlewareIndex ?? -1, total: error.totalMiddlewares ?? 0, chain: error.middlewareChain || [], }; } /** * Type guard to check if an error has our custom context structure * @param error - Error of unknown type * @returns True if error has a context property of object type */ function isOurError(error) { return (error instanceof Error && 'context' in error && typeof error.context === 'object'); } /** * Creates a standardized error response for middleware errors * @param error - Error object with optional statusCode and context * @param options - Configuration for error response formatting * @param options.includeStackTrace - Whether to include stack trace in response * @param options.includeDetails - Whether to include detailed error information * @param options.productionErrorMessage - Generic message for production environments * @returns REST API response object with error details */ function createMiddlewareErrorResponse(error, options) { const { includeStackTrace, includeDetails, productionErrorMessage } = options; return { statusCode: error.statusCode || 500, headers: { 'Content-Type': 'application/json', 'X-Request-ID': error.context?.requestId || 'unknown', }, body: JSON.stringify({ error: { code: error.context?.code || 'INTERNAL_SERVER_ERROR', message: includeDetails ? error.message : productionErrorMessage, timestamp: error.context?.timestamp || new Date().toISOString(), requestId: error.context?.requestId || 'unknown', ...(includeStackTrace && { stack: error.stack }), ...(includeDetails && error.context && { context: error.context }), }, }), }; } /** * Creates REST error handler middleware for standardized error processing * @param config - Configuration options for error handling behavior * @returns Middleware function that catches and processes errors * * @example * ```typescript * chain.use('errorHandler', createRestErrorHandler({ * includeStackTrace: true, * defaultContext: { service: 'my-api' } * })); * ``` */ export function createRestErrorHandler(config = {}) { const { includeStackTrace = isDevelopment, defaultContext = {}, forceStructuredLogging = true, } = config; const includeDetails = isDevelopment; const productionErrorMessage = 'Internal Server Error'; return async (input, next) => { const { context: baseContext } = initializeRestMiddleware(input, { defaultContext, forceStructuredLogging, operation: 'errorHandler', }); try { return await next(input); } catch (error) { const errorMessage = getErrorMessage(error); const stack = includeStackTrace ? getErrorStack(error) : undefined; let enhancedError; if (!isOurError(error)) { logger.warn('Non-standard error thrown, wrapping with throwError', { error: typeof error === 'object' ? error : { message: String(error) }, }); enhancedError = throwError(`Non-standard error thrown to error handler: ${errorMessage}`, error); const lambdaContext = input.context; if (lambdaContext && enhancedError.context) { enhancedError.context.requestId = lambdaContext.awsRequestId; } } else { enhancedError = error; } const errorContext = {}; if (enhancedError && typeof enhancedError === 'object') { if ('code' in enhancedError && typeof enhancedError.code === 'string') { errorContext.errorCode = enhancedError.code; } if ('statusCode' in enhancedError && typeof enhancedError.statusCode === 'number') { errorContext.statusCode = enhancedError.statusCode; } } const logContext = { ...baseContext, ...errorContext, }; if (isMiddlewareError(error)) { const middlewareInfo = getMiddlewareInfo(error); logger.error(`Middleware error in ${middlewareInfo.name}`, { ...logContext, middlewareError: middlewareInfo, stack, }); } else { logger.error(`REST error: ${errorMessage}`, { ...logContext, stack, }); } const errorWithStatusCode = enhancedError; const errorResponse = createMiddlewareErrorResponse(errorWithStatusCode, { includeStackTrace, includeDetails, productionErrorMessage, }); return errorResponse; } }; } /** * HTTP error helper functions for creating standardized error objects */ export const HttpErrors = { badRequest: (message) => ({ statusCode: 400, code: ERROR_CODES.BAD_REQUEST, message, }), unauthorized: (message) => ({ statusCode: 401, code: ERROR_CODES.UNAUTHORIZED, message, }), forbidden: (message) => ({ statusCode: 403, code: ERROR_CODES.FORBIDDEN, message, }), notFound: (message) => ({ statusCode: 404, code: ERROR_CODES.NOT_FOUND, message, }), methodNotAllowed: (message) => ({ statusCode: 405, code: ERROR_CODES.METHOD_NOT_ALLOWED, message, }), conflict: (message) => ({ statusCode: 409, code: ERROR_CODES.CONFLICT, message, }), unprocessableEntity: (message) => ({ statusCode: 422, code: ERROR_CODES.UNPROCESSABLE_ENTITY, message, }), internalServerError: (message) => ({ statusCode: 500, code: ERROR_CODES.INTERNAL_SERVER_ERROR, message, }), serviceUnavailable: (message) => ({ statusCode: 503, code: ERROR_CODES.SERVICE_UNAVAILABLE, message, }), }; /** * Creates an HTTP error object with status code and error code * @param statusCode - HTTP status code * @param code - Error code identifier * @param message - Error message * @returns Error object with statusCode and code properties */ export function createHttpError(statusCode, code, message) { const error = new Error(message); error.statusCode = statusCode; error.code = code; return error; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVzdEVycm9ySGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL21pZGRsZXdhcmUvcmVzdC9SZXN0RXJyb3JIYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbkMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN6QyxPQUFPLEVBQ0wsV0FBVyxFQUNYLHdCQUF3QixFQUN4QixhQUFhLEVBQ2IsZUFBZSxFQUNmLGFBQWEsR0FDZCxNQUFNLFNBQVMsQ0FBQztBQVNqQjs7OztHQUlHO0FBQ0gsU0FBUyxpQkFBaUIsQ0FBQyxLQUFjO0lBQ3ZDLE9BQU8sQ0FDTCxLQUFLLFlBQVksS0FBSztRQUN0QixPQUFRLEtBQXlCLENBQUMsY0FBYyxLQUFLLFFBQVEsQ0FDOUQsQ0FBQztBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxpQkFBaUIsQ0FBQyxLQUFzQjtJQUMvQyxPQUFPO1FBQ0wsSUFBSSxFQUFFLEtBQUssQ0FBQyxjQUFjLElBQUksU0FBUztRQUN2QyxLQUFLLEVBQUUsS0FBSyxDQUFDLGVBQWUsSUFBSSxDQUFDLENBQUM7UUFDbEMsS0FBSyxFQUFFLEtBQUssQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDO1FBQ2xDLEtBQUssRUFBRSxLQUFLLENBQUMsZUFBZSxJQUFJLEVBQUU7S0FDbkMsQ0FBQztBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxVQUFVLENBQ2pCLEtBQWM7SUFFZCxPQUFPLENBQ0wsS0FBSyxZQUFZLEtBQUs7UUFDdEIsU0FBUyxJQUFJLEtBQUs7UUFDbEIsT0FBUSxLQUErQixDQUFDLE9BQU8sS0FBSyxRQUFRLENBQzdELENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxTQUFTLDZCQUE2QixDQUNwQyxLQUF5RSxFQUN6RSxPQUlDO0lBRUQsTUFBTSxFQUFFLGlC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LElBQUksRUFBRSxXQUFXLENBQUMsb0JBQW9CO1FBQ3RDLE9BQU87S0FDUixDQUFDO0lBQ0YsbUJBQW1CLEVBQUUsQ0FBQyxPQUFlLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDekMsVUFBVSxFQUFFLEdBQUc7UUFDZixJQUFJLEVBQUUsV0FBVyxDQUFDLHFCQUFxQjtRQUN2QyxPQUFPO0tBQ1IsQ0FBQztJQUNGLGtCQUFrQixFQUFFLENBQUMsT0FBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3hDLFVBQVUsRUFBRSxHQUFHO1FBQ2YsSUFBSSxFQUFFLFdBQVcsQ0FBQyxtQkFBbUI7UUFDckMsT0FBTztLQUNSLENBQUM7Q0FDTSxDQUFDO0FBRVg7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FDN0IsVUFBa0IsRUFDbEIsSUFBWSxFQUNaLE9BQWU7SUFFZixNQUFNLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBRzlCLENBQUM7SUFDRixLQUFLLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztJQUM5QixLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztJQUNsQixPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi8uLi9sb2cnO1xuaW1wb3J0IHsgdGhyb3dFcnJvciB9IGZyb20gJy4uLy4uL2Vycm9yJztcbmltcG9ydCB7XG4gIEVSUk9SX0NPREVTLFxuICBpbml0aWFsaXplUmVzdE1pZGRsZXdhcmUsXG4gIGlzRGV2ZWxvcG1lbnQsXG4gIGdldEVycm9yTWVzc2FnZSxcbiAgZ2V0RXJyb3JTdGFjayxcbn0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgdHlwZSB7IE1pZGRsZXdhcmUsIE1pZGRsZXdhcmVFcnJvciB9IGZyb20gJy4uL21pZGRsZXdhcmVDaGFpbic7XG5pbXBvcnQgdHlwZSB7XG4gIFJlc3RSZXNwb25zZSxcbiAgUmVzdElucHV0V2l0aE1vZGVscyxcbiAgUmVzdEVycm9ySGFuZGxlckNvbmZpZyxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgdHlwZSB7IEFtcGxpZnlNb2RlbFR5cGUgfSBmcm9tICcuLi8uLi9xdWVyaWVzL3R5cGVzJztcblxuLyoqXG4gKiBUeXBlIGd1YXJkIHRvIGNoZWNrIGlmIGFuIGVycm9yIGlzIGEgbWlkZGxld2FyZSBlcnJvclxuICogQHBhcmFtIGVycm9yIC0gRXJyb3Igb2YgdW5rbm93biB0eXBlXG4gKiBAcmV0dXJucyBUcnVlIGlmIGVycm9yIGlzIGEgTWlkZGxld2FyZUVycm9yIHdpdGggbWlkZGxld2FyZU5hbWUgcHJvcGVydHlcbiAqL1xuZnVuY3Rpb24gaXNNaWRkbGV3YXJlRXJyb3IoZXJyb3I6IHVua25vd24pOiBlcnJvciBpcyBNaWRkbGV3YXJlRXJyb3Ige1xuICByZXR1cm4gKFxuICAgIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgJiZcbiAgICB0eXBlb2YgKGVycm9yIGFzIE1pZGRsZXdhcmVFcnJvcikubWlkZGxld2FyZU5hbWUgPT09ICdzdHJpbmcnXG4gICk7XG59XG5cbi8qKlxuICogRXh0cmFjdHMgbWlkZGxld2FyZSBpbmZvcm1hdGlvbiBmcm9tIGEgTWlkZGxld2FyZUVycm9yXG4gKiBAcGFyYW0gZXJyb3IgLSBNaWRkbGV3YXJlIGVycm9yIG9iamVjdFxuICogQHJldHVybnMgT2JqZWN0IGNvbnRhaW5pbmcgbWlkZGxld2FyZSBuYW1lLCBpbmRleCwgdG90YWwgY291bnQsIGFuZCBjaGFpblxuICovXG5mdW5jdGlvbiBnZXRNaWRkbGV3YXJlSW5mbyhlcnJvcjogTWlkZGxld2FyZUVycm9yKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogZXJyb3IubWlkZGxld2FyZU5hbWUgfHwgJ3Vua25vd24nLFxuICAgIGluZGV4OiBlcnJvci5taWRkbGV3YXJlSW5kZXggPz8gLTEsXG4gICAgdG90YWw6IGVycm9yLnRvdGFsTWlkZGxld2FyZXMgPz8gMCxcbiAgICBjaGFpbjogZXJyb3IubWlkZGxld2FyZUNoYWluIHx8IFtdLFxuICB9O1xufVxuXG4vKipcbiAqIFR5cGUgZ3VhcmQgdG8gY2hlY2sgaWYgYW4gZXJyb3IgaGFzIG91ciBjdXN0b20gY29udGV4dCBzdHJ1Y3R1cmVcbiAqIEBwYXJhbSBlcnJvciAtIEVycm9yIG9mIHVua25vd24gdHlwZVxuICogQHJldHVybnMgVHJ1ZSBpZiBlcnJvciBoYXMgYSBjb250ZXh0IHByb3BlcnR5IG9mIG9iamVjdCB0eXBlXG4gKi9cbmZ1bmN0aW9uIGlzT3VyRXJyb3IoXG4gIGVycm9yOiB1bmtub3duLFxuKTogZXJyb3IgaXMgRXJyb3IgJiB7IGNvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9IHtcbiAgcmV0dXJuIChcbiAgICBlcnJvciBpbnN0YW5jZW9mIEVycm9yICYmXG4gICAgJ2NvbnRleHQnIGluIGVycm9yICYmXG4gICAgdHlwZW9mIChlcnJvciBhcyB7IGNvbnRleHQ/OiB1bmtub3duIH0pLmNvbnRleHQgPT09ICdvYmplY3QnXG4gICk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIHN0YW5kYXJkaXplZCBlcnJvciByZXNwb25zZSBmb3IgbWlkZGxld2FyZSBlcnJvcnNcbiAqIEBwYXJhbSBlcnJvciAtIEVycm9yIG9iamVjdCB3aXRoIG9wdGlvbmFsIHN0YXR1c0NvZGUgYW5kIGNvbnRleHRcbiAqIEBwYXJhbSBvcHRpb25zIC0gQ29uZmlndXJhdGlvbiBmb3IgZXJyb3IgcmVzcG9uc2UgZm9ybWF0dGluZ1xuICogQHBhcmFtIG9wdGlvbnMuaW5jbHVkZVN0YWNrVHJhY2UgLSBXaGV0aGVyIHRvIGluY2x1ZGUgc3RhY2sgdHJhY2UgaW4gcmVzcG9uc2VcbiAqIEBwYXJhbSBvcHRpb25zLmluY2x1ZGVEZXRhaWxzIC0gV2hldGhlciB0byBpbmNsdWRlIGRldGFpbGVkIGVycm9yIGluZm9ybWF0aW9uXG4gKiBAcGFyYW0gb3B0aW9ucy5wcm9kdWN0aW9uRXJyb3JNZXNzYWdlIC0gR2VuZXJpYyBtZXNzYWdlIGZvciBwcm9kdWN0aW9uIGVudmlyb25tZW50c1xuICogQHJldHVybnMgUkVTVCBBUEkgcmVzcG9uc2Ugb2JqZWN0IHdpdGggZXJyb3IgZGV0YWlsc1xuICovXG5mdW5jdGlvbiBjcmVhdGVNaWRkbGV3YXJlRXJyb3JSZXNwb25zZShcbiAgZXJyb3I6IEVycm9yICYgeyBzdGF0dXNDb2RlPzogbnVtYmVyOyBjb250ZXh0PzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfSxcbiAgb3B0aW9uczoge1xuICAgIGluY2x1ZGVTdGFja1RyYWNlOiBib29sZWFuO1xuICAgIGluY2x1ZGVEZXRhaWxzOiBib29sZWFuO1xuICAgIHByb2R1Y3Rpb25FcnJvck1lc3NhZ2U6IHN0cmluZztcbiAgfSxcbik6IFJlc3RSZXNwb25zZSB7XG4gIGNvbnN0IHsgaW5jbHVkZVN0YWNrVHJhY2UsIGluY2x1ZGVEZXRhaWxzLCBwcm9kdWN0aW9uRXJyb3JNZXNzYWdlIH0gPSBvcHRpb25zO1xuXG4gIHJldHVybiB7XG4gICAgc3RhdHVzQ29kZTogZXJyb3Iuc3RhdHVzQ29kZSB8fCA1MDAsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICdYLVJlcXVlc3QtSUQnOiAoZXJyb3IuY29udGV4dD8ucmVxdWVzdElkIGFzIHN0cmluZykgfHwgJ3Vua25vd24nLFxuICAgIH0sXG4gICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgZXJyb3I6IHtcbiAgICAgICAgY29kZTogKGVycm9yLmNvbnRleHQ/LmNvZGUgYXMgc3RyaW5nKSB8fCAnSU5URVJOQUxfU0VSVkVSX0VSUk9SJyxcbiAgICAgICAgbWVzc2FnZTogaW5jbHVkZURldGFpbHMgPyBlcnJvci5tZXNzYWdlIDogcHJvZHVjdGlvbkVycm9yTWVzc2FnZSxcbiAgICAgICAgdGltZXN0YW1wOlxuICAgICAgICAgIChlcnJvci5jb250ZXh0Py50aW1lc3RhbXAgYXMgc3RyaW5nKSB8fCBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIHJlcXVlc3RJZDogKGVycm9yLmNvbnRleHQ/LnJlcXVlc3RJZCBhcyBzdHJpbmcpIHx8ICd1bmtub3duJyxcbiAgICAgICAgLi4uKGluY2x1ZGVTdGFja1RyYWNlICYmIHsgc3RhY2s6IGVycm9yLnN0YWNrIH0pLFxuICAgICAgICAuLi4oaW5jbHVkZURldGFpbHMgJiYgZXJyb3IuY29udGV4dCAmJiB7IGNvbnRleHQ6IGVycm9yLmNvbnRleHQgfSksXG4gICAgICB9LFxuICAgIH0pLFxuICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgUkVTVCBlcnJvciBoYW5kbGVyIG1pZGRsZXdhcmUgZm9yIHN0YW5kYXJkaXplZCBlcnJvciBwcm9jZXNzaW5nXG4gKiBAcGFyYW0gY29uZmlnIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBlcnJvciBoYW5kbGluZyBiZWhhdmlvclxuICogQHJldHVybnMgTWlkZGxld2FyZSBmdW5jdGlvbiB0aGF0IGNhdGNoZXMgYW5kIHByb2Nlc3NlcyBlcnJvcnNcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY2hhaW4udXNlKCdlcnJvckhhbmRsZXInLCBjcmVhdGVSZXN0RXJyb3JIYW5kbGVyKHtcbiAqICAgaW5jbHVkZVN0YWNrVHJhY2U6IHRydWUsXG4gKiAgIGRlZmF1bHRDb250ZXh0OiB7IHNlcnZpY2U6ICdteS1hcGknIH1cbiAqIH0pKTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVzdEVycm9ySGFuZGxlcjxcbiAgVFR5cGVzIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgQW1wbGlmeU1vZGVsVHlwZT4gPSBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIEFtcGxpZnlNb2RlbFR5cGVcbiAgPixcbiAgVE91dHB1dCA9IFJlc3RSZXNwb25zZSxcbj4oXG4gIGNvbmZpZzogUmVzdEVycm9ySGFuZGxlckNvbmZpZyA9IHt9LFxuKTogTWlkZGxld2FyZTxSZXN0SW5wdXRXaXRoTW9kZWxzPFRUeXBlcz4sIFRPdXRwdXQ+IHtcbiAgY29uc3Qge1xuICAgIGluY2x1ZGVTdGFja1RyYWNlID0gaXNEZXZlbG9wbWVudCxcbiAgICBkZWZhdWx0Q29udGV4dCA9IHt9LFxuICAgIGZvcmNlU3RydWN0dXJlZExvZ2dpbmcgPSB0cnVlLFxuICB9ID0gY29uZmlnO1xuXG4gIGNvbnN0IGluY2x1ZGVEZXRhaWxzID0gaXNEZXZlbG9wbWVudDtcbiAgY29uc3QgcHJvZHVjdGlvbkVycm9yTWVzc2FnZSA9ICdJbnRlcm5hbCBTZXJ2ZXIgRXJyb3InO1xuXG4gIHJldHVybiBhc3luYyAoXG4gICAgaW5wdXQ6IFJlc3RJbnB1dFdpdGhNb2RlbHM8VFR5cGVzPixcbiAgICBuZXh0OiAoaW5wdXQ/OiBSZXN0SW5wdXRXaXRoTW9kZWxzPFRUeXBlcz4pID0+IFByb21pc2U8VE91dHB1dD4sXG4gICk6IFByb21pc2U8VE91dHB1dD4gPT4ge1xuICAgIGNvbnN0IHsgY29udGV4dDogYmFzZUNvbnRleHQgfSA9IGluaXRpYWxpemVSZXN0TWlkZGxld2FyZShcbiAgICAgIGlucHV0IGFzIFJlc3RJbnB1dFdpdGhNb2RlbHMsXG4gICAgICB7XG4gICAgICAgIGRlZmF1bHRDb250ZXh0LFxuICAgICAgICBmb3JjZVN0cnVjdHVyZWRMb2dnaW5nLFxuICAgICAgICBvcGVyYXRpb246ICdlcnJvckhhbmRsZXInLFxuICAgICAgfSxcbiAgICApO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBuZXh0KGlucHV0KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZ2V0RXJyb3JNZXNzYWdlKGVycm9yKTtcbiAgICAgIGNvbnN0IHN0YWNrID0gaW5jbHVkZVN0YWNrVHJhY2UgPyBnZXRFcnJvclN0YWNrKGVycm9yKSA6IHVuZGVmaW5lZDtcblxuICAgICAgbGV0IGVuaGFuY2VkRXJyb3I6IEVycm9yICYgeyBjb250ZXh0PzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfTtcblxuICAgICAgaWYgKCFpc091ckVycm9yKGVycm9yKSkge1xuICAgICAgICBsb2dnZXIud2FybignTm9uLXN0YW5kYXJkIGVycm9yIHRocm93biwgd3JhcHBpbmcgd2l0aCB0aHJvd0Vycm9yJywge1xuICAgICAgICAgIGVycm9yOiB0eXBlb2YgZXJyb3IgPT09ICdvYmplY3QnID8gZXJyb3IgOiB7IG1lc3NhZ2U6IFN0cmluZyhlcnJvcikgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZW5oYW5jZWRFcnJvciA9IHRocm93RXJyb3IoXG4gICAgICAgICAgYE5vbi1zdGFuZGFyZCBlcnJvciB0aHJvd24gdG8gZXJyb3IgaGFuZGxlcjogJHtlcnJvck1lc3NhZ2V9YCxcbiAgICAgICAgICBlcnJvcixcbiAgICAgICAgKSBhcyBFcnJvciAmIHsgY29udGV4dD86IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH07XG5cbiAgICAgICAgY29uc3QgbGFtYmRhQ29udGV4dCA9IGlucHV0LmNvbnRleHQ7XG4gICAgICAgIGlmIChsYW1iZGFDb250ZXh0ICYmIGVuaGFuY2VkRXJyb3IuY29udGV4dCkge1xuICAgICAgICAgIGVuaGFuY2VkRXJyb3IuY29udGV4dC5yZXF1ZXN0SWQgPSBsYW1iZGFDb250ZXh0LmF3c1JlcXVlc3RJZDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZW5oYW5jZWRFcnJvciA9IGVycm9yO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvckNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gICAgICBpZiAoZW5oYW5jZWRFcnJvciAmJiB0eXBlb2YgZW5oYW5jZWRFcnJvciA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgaWYgKCdjb2RlJyBpbiBlbmhhbmNlZEVycm9yICYmIHR5cGVvZiBlbmhhbmNlZEVycm9yLmNvZGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgZXJyb3JDb250ZXh0LmVycm9yQ29kZSA9IGVuaGFuY2VkRXJyb3IuY29kZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoXG4gICAgICAgICAgJ3N0YXR1c0NvZGUnIGluIGVuaGFuY2VkRXJyb3IgJiZcbiAgICAgICAgICB0eXBlb2YgZW5oYW5jZWRFcnJvci5zdGF0dXNDb2RlID09PSAnbnVtYmVyJ1xuICAgICAgICApIHtcbiAgICAgICAgICBlcnJvckNvbnRleHQuc3RhdHVzQ29kZSA9IGVuaGFuY2VkRXJyb3Iuc3RhdHVzQ29kZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBsb2dDb250ZXh0ID0ge1xuICAgICAgICAuLi5iYXNlQ29udGV4dCxcbiAgICAgICAgLi4uZXJyb3JDb250ZXh0LFxuICAgICAgfTtcblxuICAgICAgaWYgKGlzTWlkZGxld2FyZUVycm9yKGVycm9yKSkge1xuICAgICAgICBjb25zdCBtaWRkbGV3YXJlSW5mbyA9IGdldE1pZGRsZXdhcmVJbmZvKGVycm9yKTtcbiAgICAgICAgbG9nZ2VyLmVycm9yKGBNaWRkbGV3YXJlIGVycm9yIGluICR7bWlkZGxld2FyZUluZm8ubmFtZX1gLCB7XG4gICAgICAgICAgLi4ubG9nQ29udGV4dCxcbiAgICAgICAgICBtaWRkbGV3YXJlRXJyb3I6IG1pZGRsZXdhcmVJbmZvLFxuICAgICAgICAgIHN0YWNrLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihgUkVTVCBlcnJvcjogJHtlcnJvck1lc3NhZ2V9YCwge1xuICAgICAgICAgIC4uLmxvZ0NvbnRleHQsXG4gICAgICAgICAgc3RhY2ssXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcldpdGhTdGF0dXNDb2RlID0gZW5oYW5jZWRFcnJvciBhcyBFcnJvciAmIHtcbiAgICAgICAgc3RhdHVzQ29kZT86IG51bWJlcjtcbiAgICAgICAgY29udGV4dD86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgfTtcblxuICAgICAgY29uc3QgZXJyb3JSZXNwb25zZSA9IGNyZWF0ZU1pZGRsZXdhcmVFcnJvclJlc3BvbnNlKGVycm9yV2l0aFN0YXR1c0NvZGUsIHtcbiAgICAgICAgaW5jbHVkZVN0YWNrVHJhY2UsXG4gICAgICAgIGluY2x1ZGVEZXRhaWxzLFxuICAgICAgICBwcm9kdWN0aW9uRXJyb3JNZXNzYWdlLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBlcnJvclJlc3BvbnNlIGFzIFRPdXRwdXQ7XG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIEhUVFAgZXJyb3IgaGVscGVyIGZ1bmN0aW9ucyBmb3IgY3JlYXRpbmcgc3RhbmRhcmRpemVkIGVycm9yIG9iamVjdHNcbiAqL1xuZXhwb3J0IGNvbnN0IEh0dHBFcnJvcnMgPSB7XG4gIGJhZFJlcXVlc3Q6IChtZXNzYWdlOiBzdHJpbmcpID0+ICh7XG4gICAgc3RhdHVzQ29kZTogNDAwLFxuICAgIGNvZGU6IEVSUk9SX0NPREVTLkJBRF9SRVFVRVNULFxuICAgIG1lc3NhZ2UsXG4gIH0pLFxuICB1bmF1dGhvcml6ZWQ6IChtZXNzYWdlOiBzdHJpbmcpID0+ICh7XG4gICAgc3RhdHVzQ29kZTogNDAxLFxuICAgIGNvZGU6IEVSUk9SX0NPREVTLlVOQVVUSE9SSVpFRCxcbiAgICBtZXNzYWdlLFxuICB9KSxcbiAgZm9yYmlkZGVuOiAobWVzc2FnZTogc3RyaW5nKSA9PiAoe1xuICAgIHN0YXR1c0NvZGU6IDQwMyxcbiAgICBjb2RlOiBFUlJPUl9DT0RFUy5GT1JCSURERU4sXG4gICAgbWVzc2FnZSxcbiAgfSksXG4gIG5vdEZvdW5kOiAobWVzc2FnZTogc3RyaW5nKSA9PiAoe1xuICAgIHN0YXR1c0NvZGU6IDQwNCxcbiAgICBjb2RlOiBFUlJPUl9DT0RFUy5OT1RfRk9VTkQsXG4gICAgbWVzc2FnZSxcbiAgfSksXG4gIG1ldGhvZE5vdEFsbG93ZWQ6IChtZXNzYWdlOiBzdHJpbmcpID0+ICh7XG4gICAgc3RhdHVzQ29kZTogNDA1LFxuICAgIGNvZGU6IEVSUk9SX0NPREVTLk1FVEhPRF9OT1RfQUxMT1dFRCxcbiAgICBtZXNzYWdlLFxuICB9KSxcbiAgY29uZmxpY3Q6IChtZXNzYWdlOiBzdHJpbmcpID0+ICh7XG4gICAgc3RhdHVzQ29kZTogNDA5LFxuICAgIGNvZGU6IEVSUk9SX0NPREVTLkNPTkZMSUNULFxuICAgIG1lc3NhZ2UsXG4gIH0pLFxuICB1bnByb2Nlc3NhYmxlRW50aXR5OiAobWVzc2FnZTogc3RyaW5nKSA9PiAoe1xuICAgIHN0YXR1c0NvZGU6IDQyMixcbiAgICBjb2RlOiBFUlJPUl9DT0RFUy5VTlBST0NFU1NBQkxFX0VOVElUWSxcbiAgICBtZXNzYWdlLFxuICB9KSxcbiAgaW50ZXJuYWxTZXJ2ZXJFcnJvcjogKG1lc3NhZ2U6IHN0cmluZykgPT4gKHtcbiAgICBzdGF0dXNDb2RlOiA1MDAsXG4gICAgY29kZTogRVJST1JfQ09ERVMuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgIG1lc3NhZ2UsXG4gIH0pLFxuICBzZXJ2aWNlVW5hdmFpbGFibGU6IChtZXNzYWdlOiBzdHJpbmcpID0+ICh7XG4gICAgc3RhdHVzQ29kZTogNTAzLFxuICAgIGNvZGU6IEVSUk9SX0NPREVTLlNFUlZJQ0VfVU5BVkFJTEFCTEUsXG4gICAgbWVzc2FnZSxcbiAgfSksXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gSFRUUCBlcnJvciBvYmplY3Qgd2l0aCBzdGF0dXMgY29kZSBhbmQgZXJyb3IgY29kZVxuICogQHBhcmFtIHN0YXR1c0NvZGUgLSBIVFRQIHN0YXR1cyBjb2RlXG4gKiBAcGFyYW0gY29kZSAtIEVycm9yIGNvZGUgaWRlbnRpZmllclxuICogQHBhcmFtIG1lc3NhZ2UgLSBFcnJvciBtZXNzYWdlXG4gKiBAcmV0dXJucyBFcnJvciBvYmplY3Qgd2l0aCBzdGF0dXNDb2RlIGFuZCBjb2RlIHByb3BlcnRpZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUh0dHBFcnJvcihcbiAgc3RhdHVzQ29kZTogbnVtYmVyLFxuICBjb2RlOiBzdHJpbmcsXG4gIG1lc3NhZ2U6IHN0cmluZyxcbikge1xuICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihtZXNzYWdlKSBhcyBFcnJvciAmIHtcbiAgICBzdGF0dXNDb2RlOiBudW1iZXI7XG4gICAgY29kZTogc3RyaW5nO1xuICB9O1xuICBlcnJvci5zdGF0dXNDb2RlID0gc3RhdHVzQ29kZTtcbiAgZXJyb3IuY29kZSA9IGNvZGU7XG4gIHJldHVybiBlcnJvcjtcbn1cbiJdfQ==