UNPKG

@energica-city/shared-amplify-utils

Version:

Shared utilities for AWS Amplify projects

270 lines 31.5 kB
import { logger } from '../../log'; /** * Builds standardized log context for REST operations * @param input - REST input containing event and context * @param additionalContext - Additional context to merge * @returns Combined context object with REST operation details */ export function buildRestContext(input, additionalContext = {}) { const { event, context } = input; const { requestContext } = event; return { ...additionalContext, httpMethod: event.httpMethod, path: event.path, resource: event.resource, requestId: context.awsRequestId, functionName: context.functionName, functionVersion: context.functionVersion, stage: requestContext.stage, sourceIp: requestContext.identity?.sourceIp, userAgent: requestContext.identity?.userAgent, }; } /** * Extracts basic event information for logging purposes * @param event - API Gateway REST event * @returns Object containing essential event information */ export function extractEventInfo(event) { const { requestContext, body } = event; return { httpMethod: event.httpMethod, path: event.path, resource: event.resource, hasBody: !!body, bodyLength: body?.length || 0, hasQueryParams: Object.keys(event.queryStringParameters || {}).length > 0, hasPathParams: Object.keys(event.pathParameters || {}).length > 0, sourceIp: requestContext.identity?.sourceIp, userAgent: requestContext.identity?.userAgent, }; } /** * Safely parses JSON body with error handling and logging * @param body - Raw request body string * @param context - Logging context for error reporting * @returns Parsed JSON object or null if parsing fails */ export function parseJsonBody(body, context) { if (!body) return null; try { return JSON.parse(body); } catch (error) { logger.warn('Failed to parse REST request body', { ...context, bodyLength: body.length, error: error instanceof Error ? error.message : String(error), }); return null; } } /** * Parses JSON body with fallback value for error cases * @param body - Raw request body string * @param fallback - Value to return if parsing fails * @returns Parsed JSON object or fallback value */ export function parseJsonBodyWithFallback(body, fallback) { if (!body) return fallback; try { return JSON.parse(body); } catch { return fallback; } } /** * Configures structured logging for REST middleware operations * @param input - REST input containing event and context * @param forceStructuredLogging - Whether to force structured logging mode * @param defaultContext - Default context to include in all logs */ export function setupStructuredLogging(input, forceStructuredLogging = true, defaultContext = {}) { if (forceStructuredLogging && !logger.isStructuredLoggingEnabled()) { logger.setStructuredLogging(true); } logger.setContext({ ...buildRestContext(input, defaultContext), }); } /** * Safely extracts error message from unknown error types * @param error - Error of unknown type * @returns String representation of the error message */ export function getErrorMessage(error) { return error instanceof Error ? error.message : String(error); } /** * Extracts stack trace from error if available * @param error - Error of unknown type * @returns Stack trace string or undefined if not available */ export function getErrorStack(error) { return error instanceof Error ? error.stack : undefined; } /** * Builds validation error context with REST event information * @param event - REST event that caused the validation error * @param errorCode - Error code identifier (defaults to 'VALIDATION_ERROR') * @param statusCode - HTTP status code (defaults to 400) * @param additionalContext - Additional context to include * @returns Context object with REST event details and error information */ export function buildValidationErrorContext(event, errorCode = 'VALIDATION_ERROR', statusCode = 400, additionalContext = {}) { return { ...extractEventInfo(event), code: errorCode, statusCode, ...additionalContext, }; } /** * Validates and extracts basic request information with error context * @param input - REST input containing event and context * @param operation - Operation name for logging context * @returns Object containing event, context, and request ID */ export function validateBasicRequestInfo(input, operation) { const { event } = input; const requestId = getRequestId(event, input.context); const context = buildRestContext(input, { operation }); return { event, context, requestId, }; } /** * Creates standardized validation errors with REST context * @param config - Validation error configuration * @returns Error object with code, statusCode, and context properties */ export function createValidationError(config) { const { message, event, errorCode = 'VALIDATION_ERROR', statusCode = 400, additionalContext = {}, } = config; const error = new Error(message); error.code = errorCode; error.statusCode = statusCode; error.context = buildValidationErrorContext(event, errorCode, statusCode, additionalContext); return error; } /** * Creates standardized error response in API Gateway format * @param config - Error response configuration * @returns API Gateway response object with error details */ export function createErrorResponse(config) { const { statusCode, code, message, requestId = 'unknown', additionalData = {}, } = config; return { statusCode, headers: { 'Content-Type': 'application/json', 'X-Request-ID': requestId, }, body: JSON.stringify({ success: false, error: { code, message, timestamp: new Date().toISOString(), requestId, ...additionalData, }, }), }; } /** * Extracts request ID from multiple possible sources * @param event - REST event * @param context - Lambda context (optional) * @returns Request ID string or generated fallback */ export function getRequestId(event, context) { return (context?.awsRequestId || event.requestContext?.requestId || `unknown-${Date.now()}`); } /** * Creates standardized success response in API Gateway format * @param data - Response data * @param statusCode - HTTP status code (defaults to 200) * @param requestId - Request ID for tracking * @param meta - Additional metadata * @returns API Gateway response object with success data */ export function createSuccessResponse(data, statusCode = 200, requestId = 'unknown', meta = {}) { return { statusCode, headers: { 'Content-Type': 'application/json', 'X-Request-ID': requestId, }, body: JSON.stringify({ success: true, data, meta: { timestamp: new Date().toISOString(), requestId, ...meta, }, }), }; } /** * Common HTTP status codes for REST APIs */ export const HTTP_STATUS = { OK: 200, CREATED: 201, NO_CONTENT: 204, BAD_REQUEST: 400, UNAUTHORIZED: 401, FORBIDDEN: 403, NOT_FOUND: 404, METHOD_NOT_ALLOWED: 405, CONFLICT: 409, UNPROCESSABLE_ENTITY: 422, INTERNAL_SERVER_ERROR: 500, SERVICE_UNAVAILABLE: 503, }; /** * Comprehensive error codes for REST API responses */ export const ERROR_CODES = { BAD_REQUEST: 'BAD_REQUEST', VALIDATION_ERROR: 'VALIDATION_ERROR', UNPROCESSABLE_ENTITY: 'UNPROCESSABLE_ENTITY', UNAUTHORIZED: 'UNAUTHORIZED', AUTHENTICATION_ERROR: 'AUTHENTICATION_ERROR', FORBIDDEN: 'FORBIDDEN', AUTHORIZATION_ERROR: 'AUTHORIZATION_ERROR', NOT_FOUND: 'NOT_FOUND', CONFLICT: 'CONFLICT', METHOD_NOT_ALLOWED: 'METHOD_NOT_ALLOWED', INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR', SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE', }; /** Environment detection helper */ export const isDevelopment = process.env.NODE_ENV === 'development'; /** * Common middleware initialization helper that sets up logging and context * @param input - REST input with event and context * @param config - Configuration options for initialization * @returns Initialized input, context, and request ID */ export function initializeRestMiddleware(input, config = {}) { const { defaultContext = {}, forceStructuredLogging = true, operation = 'middleware', } = config; const typedInput = input; setupStructuredLogging(typedInput, forceStructuredLogging, defaultContext); const { context, requestId } = validateBasicRequestInfo(typedInput, operation); return { input: typedInput, context, requestId, }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9taWRkbGV3YXJlL3Jlc3QvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUduQzs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxnQkFBZ0IsQ0FDOUIsS0FBMEIsRUFDMUIsb0JBQTZDLEVBQUU7SUFFL0MsTUFBTSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFDakMsTUFBTSxFQUFFLGNBQWMsRUFBRSxHQUFHLEtBQUssQ0FBQztJQUVqQyxPQUFPO1FBQ0wsR0FBRyxpQkFBaUI7UUFDcEIsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO1FBQzVCLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtRQUNoQixRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVE7UUFDeEIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxZQUFZO1FBQy9CLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtRQUNsQyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWU7UUFDeEMsS0FBSyxFQUFFLGNBQWMsQ0FBQyxLQUFLO1FBQzNCLFFBQVEsRUFBRSxjQUFjLENBQUMsUUFBUSxFQUFFLFFBQVE7UUFDM0MsU0FBUyxFQUFFLGNBQWMsQ0FBQyxRQUFRLEVBQUUsU0FBUztLQUM5QyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsS0FBZ0I7SUFDL0MsTUFBTSxFQUFFLGNBQWMsRUFBRSxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFFdkMsT0FBTztRQUNMLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVTtRQUM1QixJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7UUFDaEIsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRO1FBQ3hCLE9BQU8sRUFBRSxDQUFDLENBQUMsSUFBSTtRQUNm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RixPQUFPO1FBQ0wsS0FBSyxFQUFFLFVBQVU7UUFDakIsT0FBTztRQUNQLFNBQVM7S0FDVixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uLy4uL2xvZyc7XG5pbXBvcnQgdHlwZSB7IFJlc3RJbnB1dFdpdGhNb2RlbHMsIFJlc3RFdmVudCB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIEJ1aWxkcyBzdGFuZGFyZGl6ZWQgbG9nIGNvbnRleHQgZm9yIFJFU1Qgb3BlcmF0aW9uc1xuICogQHBhcmFtIGlucHV0IC0gUkVTVCBpbnB1dCBjb250YWluaW5nIGV2ZW50IGFuZCBjb250ZXh0XG4gKiBAcGFyYW0gYWRkaXRpb25hbENvbnRleHQgLSBBZGRpdGlvbmFsIGNvbnRleHQgdG8gbWVyZ2VcbiAqIEByZXR1cm5zIENvbWJpbmVkIGNvbnRleHQgb2JqZWN0IHdpdGggUkVTVCBvcGVyYXRpb24gZGV0YWlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRSZXN0Q29udGV4dChcbiAgaW5wdXQ6IFJlc3RJbnB1dFdpdGhNb2RlbHMsXG4gIGFkZGl0aW9uYWxDb250ZXh0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9LFxuKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICBjb25zdCB7IGV2ZW50LCBjb250ZXh0IH0gPSBpbnB1dDtcbiAgY29uc3QgeyByZXF1ZXN0Q29udGV4dCB9ID0gZXZlbnQ7XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5hZGRpdGlvbmFsQ29udGV4dCxcbiAgICBodHRwTWV0aG9kOiBldmVudC5odHRwTWV0aG9kLFxuICAgIHBhdGg6IGV2ZW50LnBhdGgsXG4gICAgcmVzb3VyY2U6IGV2ZW50LnJlc291cmNlLFxuICAgIHJlcXVlc3RJZDogY29udGV4dC5hd3NSZXF1ZXN0SWQsXG4gICAgZnVuY3Rpb25OYW1lOiBjb250ZXh0LmZ1bmN0aW9uTmFtZSxcbiAgICBmdW5jdGlvblZlcnNpb246IGNvbnRleHQuZnVuY3Rpb25WZXJzaW9uLFxuICAgIHN0YWdlOiByZXF1ZXN0Q29udGV4dC5zdGFnZSxcbiAgICBzb3VyY2VJcDogcmVxdWVzdENvbnRleHQuaWRlbnRpdHk/LnNvdXJjZUlwLFxuICAgIHVzZXJBZ2VudDogcmVxdWVzdENvbnRleHQuaWRlbnRpdHk/LnVzZXJBZ2VudCxcbiAgfTtcbn1cblxuLyoqXG4gKiBFeHRyYWN0cyBiYXNpYyBldmVudCBpbmZvcm1hdGlvbiBmb3IgbG9nZ2luZyBwdXJwb3Nlc1xuICogQHBhcmFtIGV2ZW50IC0gQVBJIEdhdGV3YXkgUkVTVCBldmVudFxuICogQHJldHVybnMgT2JqZWN0IGNvbnRhaW5pbmcgZXNzZW50aWFsIGV2ZW50IGluZm9ybWF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0RXZlbnRJbmZvKGV2ZW50OiBSZXN0RXZlbnQpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGNvbnN0IHsgcmVxdWVzdENvbnRleHQsIGJvZHkgfSA9IGV2ZW50O1xuXG4gIHJldHVybiB7XG4gICAgaHR0cE1ldGhvZDogZXZlbnQuaHR0cE1ldGhvZCxcbiAgICBwYXRoOiBldmVudC5wYXRoLFxuICAgIHJlc291cmNlOiBldmVudC5yZXNvdXJjZSxcbiAgICBoYXNCb2R5OiAhIWJvZHksXG4gICAgYm9keUxlbmd0aDogYm9keT8ubGVuZ3RoIHx8IDAsXG4gICAgaGFzUXVlcnlQYXJhbXM6IE9iamVjdC5rZXlzKGV2ZW50LnF1ZXJ5U3RyaW5nUGFyYW1ldGVycyB8fCB7fSkubGVuZ3RoID4gMCxcbiAgICBoYXNQYXRoUGFyYW1zOiBPYmplY3Qua2V5cyhldmVudC5wYXRoUGFyYW1ldGVycyB8fCB7fSkubGVuZ3RoID4gMCxcbiAgICBzb3VyY2VJcDogcmVxdWVzdENvbnRleHQuaWRlbnRpdHk/LnNvdXJjZUlwLFxuICAgIHVzZXJBZ2VudDogcmVxdWVzdENvbnRleHQuaWRlbnRpdHk/LnVzZXJBZ2VudCxcbiAgfTtcbn1cblxuLyoqXG4gKiBTYWZlbHkgcGFyc2VzIEpTT04gYm9keSB3aXRoIGVycm9yIGhhbmRsaW5nIGFuZCBsb2dnaW5nXG4gKiBAcGFyYW0gYm9keSAtIFJhdyByZXF1ZXN0IGJvZHkgc3RyaW5nXG4gKiBAcGFyYW0gY29udGV4dCAtIExvZ2dpbmcgY29udGV4dCBmb3IgZXJyb3IgcmVwb3J0aW5nXG4gKiBAcmV0dXJucyBQYXJzZWQgSlNPTiBvYmplY3Qgb3IgbnVsbCBpZiBwYXJzaW5nIGZhaWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUpzb25Cb2R5KFxuICBib2R5OiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuKTogdW5rbm93biB7XG4gIGlmICghYm9keSkgcmV0dXJuIG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShib2R5KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2dnZXIud2FybignRmFpbGVkIHRvIHBhcnNlIFJFU1QgcmVxdWVzdCBib2R5Jywge1xuICAgICAgLi4uY29udGV4dCxcbiAgICAgIGJvZHlMZW5ndGg6IGJvZHkubGVuZ3RoLFxuICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKSxcbiAgICB9KTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vKipcbiAqIFBhcnNlcyBKU09OIGJvZHkgd2l0aCBmYWxsYmFjayB2YWx1ZSBmb3IgZXJyb3IgY2FzZXNcbiAqIEBwYXJhbSBib2R5IC0gUmF3IHJlcXVlc3QgYm9keSBzdHJpbmdcbiAqIEBwYXJhbSBmYWxsYmFjayAtIFZhbHVlIHRvIHJldHVybiBpZiBwYXJzaW5nIGZhaWxzXG4gKiBAcmV0dXJucyBQYXJzZWQgSlNPTiBvYmplY3Qgb3IgZmFsbGJhY2sgdmFsdWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlSnNvbkJvZHlXaXRoRmFsbGJhY2s8VCA9IHVua25vd24+KFxuICBib2R5OiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIGZhbGxiYWNrOiBULFxuKTogdW5rbm93biB8IFQge1xuICBpZiAoIWJvZHkpIHJldHVybiBmYWxsYmFjaztcblxuICB0cnkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKGJvZHkpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsbGJhY2s7XG4gIH1cbn1cblxuLyoqXG4gKiBDb25maWd1cmVzIHN0cnVjdHVyZWQgbG9nZ2luZyBmb3IgUkVTVCBtaWRkbGV3YXJlIG9wZXJhdGlvbnNcbiAqIEBwYXJhbSBpbnB1dCAtIFJFU1QgaW5wdXQgY29udGFpbmluZyBldmVudCBhbmQgY29udGV4dFxuICogQHBhcmFtIGZvcmNlU3RydWN0dXJlZExvZ2dpbmcgLSBXaGV0aGVyIHRvIGZvcmNlIHN0cnVjdHVyZWQgbG9nZ2luZyBtb2RlXG4gKiBAcGFyYW0gZGVmYXVsdENvbnRleHQgLSBEZWZhdWx0IGNvbnRleHQgdG8gaW5jbHVkZSBpbiBhbGwgbG9nc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBTdHJ1Y3R1cmVkTG9nZ2luZyhcbiAgaW5wdXQ6IFJlc3RJbnB1dFdpdGhNb2RlbHMsXG4gIGZvcmNlU3RydWN0dXJlZExvZ2dpbmc6IGJvb2xlYW4gPSB0cnVlLFxuICBkZWZhdWx0Q29udGV4dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fSxcbik6IHZvaWQge1xuICBpZiAoZm9yY2VTdHJ1Y3R1cmVkTG9nZ2luZyAmJiAhbG9nZ2VyLmlzU3RydWN0dXJlZExvZ2dpbmdFbmFibGVkKCkpIHtcbiAgICBsb2dnZXIuc2V0U3RydWN0dXJlZExvZ2dpbmcodHJ1ZSk7XG4gIH1cblxuICBsb2dnZXIuc2V0Q29udGV4dCh7XG4gICAgLi4uYnVpbGRSZXN0Q29udGV4dChpbnB1dCwgZGVmYXVsdENvbnRleHQpLFxuICB9KTtcbn1cblxuLyoqXG4gKiBTYWZlbHkgZXh0cmFjdHMgZXJyb3IgbWVzc2FnZSBmcm9tIHVua25vd24gZXJyb3IgdHlwZXNcbiAqIEBwYXJhbSBlcnJvciAtIEVycm9yIG9mIHVua25vd24gdHlwZVxuICogQHJldHVybnMgU3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBlcnJvciBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRFcnJvck1lc3NhZ2UoZXJyb3I6IHVua25vd24pOiBzdHJpbmcge1xuICByZXR1cm4gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIHN0YWNrIHRyYWNlIGZyb20gZXJyb3IgaWYgYXZhaWxhYmxlXG4gKiBAcGFyYW0gZXJyb3IgLSBFcnJvciBvZiB1bmtub3duIHR5cGVcbiAqIEByZXR1cm5zIFN0YWNrIHRyYWNlIHN0cmluZyBvciB1bmRlZmluZWQgaWYgbm90IGF2YWlsYWJsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RXJyb3JTdGFjayhlcnJvcjogdW5rbm93bik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3Iuc3RhY2sgOiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogQnVpbGRzIHZhbGlkYXRpb24gZXJyb3IgY29udGV4dCB3aXRoIFJFU1QgZXZlbnQgaW5mb3JtYXRpb25cbiAqIEBwYXJhbSBldmVudCAtIFJFU1QgZXZlbnQgdGhhdCBjYXVzZWQgdGhlIHZhbGlkYXRpb24gZXJyb3JcbiAqIEBwYXJhbSBlcnJvckNvZGUgLSBFcnJvciBjb2RlIGlkZW50aWZpZXIgKGRlZmF1bHRzIHRvICdWQUxJREFUSU9OX0VSUk9SJylcbiAqIEBwYXJhbSBzdGF0dXNDb2RlIC0gSFRUUCBzdGF0dXMgY29kZSAoZGVmYXVsdHMgdG8gNDAwKVxuICogQHBhcmFtIGFkZGl0aW9uYWxDb250ZXh0IC0gQWRkaXRpb25hbCBjb250ZXh0IHRvIGluY2x1ZGVcbiAqIEByZXR1cm5zIENvbnRleHQgb2JqZWN0IHdpdGggUkVTVCBldmVudCBkZXRhaWxzIGFuZCBlcnJvciBpbmZvcm1hdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRWYWxpZGF0aW9uRXJyb3JDb250ZXh0KFxuICBldmVudDogUmVzdEV2ZW50LFxuICBlcnJvckNvZGU6IHN0cmluZyA9ICdWQUxJREFUSU9OX0VSUk9SJyxcbiAgc3RhdHVzQ29kZTogbnVtYmVyID0gNDAwLFxuICBhZGRpdGlvbmFsQ29udGV4dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fSxcbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIHtcbiAgICAuLi5leHRyYWN0RXZlbnRJbmZvKGV2ZW50KSxcbiAgICBjb2RlOiBlcnJvckNvZGUsXG4gICAgc3RhdHVzQ29kZSxcbiAgICAuLi5hZGRpdGlvbmFsQ29udGV4dCxcbiAgfTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYW5kIGV4dHJhY3RzIGJhc2ljIHJlcXVlc3QgaW5mb3JtYXRpb24gd2l0aCBlcnJvciBjb250ZXh0XG4gKiBAcGFyYW0gaW5wdXQgLSBSRVNUIGlucHV0IGNvbnRhaW5pbmcgZXZlbnQgYW5kIGNvbnRleHRcbiAqIEBwYXJhbSBvcGVyYXRpb24gLSBPcGVyYXRpb24gbmFtZSBmb3IgbG9nZ2luZyBjb250ZXh0XG4gKiBAcmV0dXJucyBPYmplY3QgY29udGFpbmluZyBldmVudCwgY29udGV4dCwgYW5kIHJlcXVlc3QgSURcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlQmFzaWNSZXF1ZXN0SW5mbyhcbiAgaW5wdXQ6IFJlc3RJbnB1dFdpdGhNb2RlbHMsXG4gIG9wZXJhdGlvbjogc3RyaW5nLFxuKToge1xuICBldmVudDogUmVzdEV2ZW50O1xuICBjb250ZXh0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgcmVxdWVzdElkOiBzdHJpbmc7XG59IHtcbiAgY29uc3QgeyBldmVudCB9ID0gaW5wdXQ7XG4gIGNvbnN0IHJlcXVlc3RJZCA9IGdldFJlcXVlc3RJZChldmVudCwgaW5wdXQuY29udGV4dCk7XG4gIGNvbnN0IGNvbnRleHQgPSBidWlsZFJlc3RDb250ZXh0KGlucHV0LCB7IG9wZXJhdGlvbiB9KTtcblxuICByZXR1cm4ge1xuICAgIGV2ZW50LFxuICAgIGNvbnRleHQsXG4gICAgcmVxdWVzdElkLFxuICB9O1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gaW50ZXJmYWNlIGZvciB2YWxpZGF0aW9uIGVycm9yIGNyZWF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmFsaWRhdGlvbkVycm9yQ29uZmlnIHtcbiAgLyoqIEVycm9yIG1lc3NhZ2UgKi9cbiAgbWVzc2FnZTogc3RyaW5nO1xuICAvKiogUkVTVCBldmVudCB0aGF0IGNhdXNlZCB0aGUgdmFsaWRhdGlvbiBlcnJvciAqL1xuICBldmVudDogUmVzdEV2ZW50O1xuICAvKiogRXJyb3IgY29kZSBpZGVudGlmaWVyIChkZWZhdWx0cyB0byAnVkFMSURBVElPTl9FUlJPUicpICovXG4gIGVycm9yQ29kZT86IHN0cmluZztcbiAgLyoqIEhUVFAgc3RhdHVzIGNvZGUgKGRlZmF1bHRzIHRvIDQwMCkgKi9cbiAgc3RhdHVzQ29kZT86IG51bWJlcjtcbiAgLyoqIEFkZGl0aW9uYWwgY29udGV4dCB0byBpbmNsdWRlICovXG4gIGFkZGl0aW9uYWxDb250ZXh0PzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8qKlxuICogQ3JlYXRlcyBzdGFuZGFyZGl6ZWQgdmFsaWRhdGlvbiBlcnJvcnMgd2l0aCBSRVNUIGNvbnRleHRcbiAqIEBwYXJhbSBjb25maWcgLSBWYWxpZGF0aW9uIGVycm9yIGNvbmZpZ3VyYXRpb25cbiAqIEByZXR1cm5zIEVycm9yIG9iamVjdCB3aXRoIGNvZGUsIHN0YXR1c0NvZGUsIGFuZCBjb250ZXh0IHByb3BlcnRpZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVZhbGlkYXRpb25FcnJvcihcbiAgY29uZmlnOiBWYWxpZGF0aW9uRXJyb3JDb25maWcsXG4pOiBFcnJvciAmIHsgY29kZTogc3RyaW5nOyBzdGF0dXNDb2RlOiBudW1iZXIgfSB7XG4gIGNvbnN0IHtcbiAgICBtZXNzYWdlLFxuICAgIGV2ZW50LFxuICAgIGVycm9yQ29kZSA9ICdWQUxJREFUSU9OX0VSUk9SJyxcbiAgICBzdGF0dXNDb2RlID0gNDAwLFxuICAgIGFkZGl0aW9uYWxDb250ZXh0ID0ge30sXG4gIH0gPSBjb25maWc7XG5cbiAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IobWVzc2FnZSkgYXMgRXJyb3IgJiB7XG4gICAgY29kZTogc3RyaW5nO1xuICAgIHN0YXR1c0NvZGU6IG51bWJlcjtcbiAgICBjb250ZXh0PzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH07XG5cbiAgZXJyb3IuY29kZSA9IGVycm9yQ29kZTtcbiAgZXJyb3Iuc3RhdHVzQ29kZSA9IHN0YXR1c0NvZGU7XG4gIGVycm9yLmNvbnRleHQgPSBidWlsZFZhbGlkYXRpb25FcnJvckNvbnRleHQoXG4gICAgZXZlbnQsXG4gICAgZXJyb3JDb2RlLFxuICAgIHN0YXR1c0NvZGUsXG4gICAgYWRkaXRpb25hbENvbnRleHQsXG4gICk7XG5cbiAgcmV0dXJuIGVycm9yO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gaW50ZXJmYWNlIGZvciBlcnJvciByZXNwb25zZSBjcmVhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVycm9yUmVzcG9uc2VDb25maWcge1xuICAvKiogSFRUUCBzdGF0dXMgY29kZSAqL1xuICBzdGF0dXNDb2RlOiBudW1iZXI7XG4gIC8qKiBFcnJvciBjb2RlIGlkZW50aWZpZXIgKi9cbiAgY29kZTogc3RyaW5nO1xuICAvKiogRXJyb3IgbWVzc2FnZSAqL1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIC8qKiBSZXF1ZXN0IElEIGZvciB0cmFja2luZyAob3B0aW9uYWwpICovXG4gIHJlcXVlc3RJZD86IHN0cmluZztcbiAgLyoqIEFkZGl0aW9uYWwgZGF0YSB0byBpbmNsdWRlIGluIHJlc3BvbnNlICovXG4gIGFkZGl0aW9uYWxEYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8qKlxuICogQ3JlYXRlcyBzdGFuZGFyZGl6ZWQgZXJyb3IgcmVzcG9uc2UgaW4gQVBJIEdhdGV3YXkgZm9ybWF0XG4gKiBAcGFyYW0gY29uZmlnIC0gRXJyb3IgcmVzcG9uc2UgY29uZmlndXJhdGlvblxuICogQHJldHVybnMgQVBJIEdhdGV3YXkgcmVzcG9uc2Ugb2JqZWN0IHdpdGggZXJyb3IgZGV0YWlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRXJyb3JSZXNwb25zZShjb25maWc6IEVycm9yUmVzcG9uc2VDb25maWcpOiB7XG4gIHN0YXR1c0NvZGU6IG51bWJlcjtcbiAgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgYm9keTogc3RyaW5nO1xufSB7XG4gIGNvbnN0IHtcbiAgICBzdGF0dXNDb2RlLFxuICAgIGNvZGUsXG4gICAgbWVzc2FnZSxcbiAgICByZXF1ZXN0SWQgPSAndW5rbm93bicsXG4gICAgYWRkaXRpb25hbERhdGEgPSB7fSxcbiAgfSA9IGNvbmZpZztcblxuICByZXR1cm4ge1xuICAgIHN0YXR1c0NvZGUsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICdYLVJlcXVlc3QtSUQnOiByZXF1ZXN0SWQsXG4gICAgfSxcbiAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgIGVycm9yOiB7XG4gICAgICAgIGNvZGUsXG4gICAgICAgIG1lc3NhZ2UsXG4gICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgIC4uLmFkZGl0aW9uYWxEYXRhLFxuICAgICAgfSxcbiAgICB9KSxcbiAgfTtcbn1cblxuLyoqXG4gKiBFeHRyYWN0cyByZXF1ZXN0IElEIGZyb20gbXVsdGlwbGUgcG9zc2libGUgc291cmNlc1xuICogQHBhcmFtIGV2ZW50IC0gUkVTVCBldmVudFxuICogQHBhcmFtIGNvbnRleHQgLSBMYW1iZGEgY29udGV4dCAob3B0aW9uYWwpXG4gKiBAcmV0dXJucyBSZXF1ZXN0IElEIHN0cmluZyBvciBnZW5lcmF0ZWQgZmFsbGJhY2tcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFJlcXVlc3RJZChcbiAgZXZlbnQ6IFJlc3RFdmVudCxcbiAgY29udGV4dD86IHsgYXdzUmVxdWVzdElkPzogc3RyaW5nIH0sXG4pOiBzdHJpbmcge1xuICByZXR1cm4gKFxuICAgIGNvbnRleHQ/LmF3c1JlcXVlc3RJZCB8fFxuICAgIGV2ZW50LnJlcXVlc3RDb250ZXh0Py5yZXF1ZXN0SWQgfHxcbiAgICBgdW5rbm93bi0ke0RhdGUubm93KCl9YFxuICApO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgc3RhbmRhcmRpemVkIHN1Y2Nlc3MgcmVzcG9uc2UgaW4gQVBJIEdhdGV3YXkgZm9ybWF0XG4gKiBAcGFyYW0gZGF0YSAtIFJlc3BvbnNlIGRhdGFcbiAqIEBwYXJhbSBzdGF0dXNDb2RlIC0gSFRUUCBzdGF0dXMgY29kZSAoZGVmYXVsdHMgdG8gMjAwKVxuICogQHBhcmFtIHJlcXVlc3RJZCAtIFJlcXVlc3QgSUQgZm9yIHRyYWNraW5nXG4gKiBAcGFyYW0gbWV0YSAtIEFkZGl0aW9uYWwgbWV0YWRhdGFcbiAqIEByZXR1cm5zIEFQSSBHYXRld2F5IHJlc3BvbnNlIG9iamVjdCB3aXRoIHN1Y2Nlc3MgZGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlPFQgPSB1bmtub3duPihcbiAgZGF0YTogVCxcbiAgc3RhdHVzQ29kZTogbnVtYmVyID0gMjAwLFxuICByZXF1ZXN0SWQ6IHN0cmluZyA9ICd1bmtub3duJyxcbiAgbWV0YTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fSxcbik6IHtcbiAgc3RhdHVzQ29kZTogbnVtYmVyO1xuICBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBib2R5OiBzdHJpbmc7XG59IHtcbiAgcmV0dXJuIHtcbiAgICBzdGF0dXNDb2RlLFxuICAgIGhlYWRlcnM6IHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAnWC1SZXF1ZXN0LUlEJzogcmVxdWVzdElkLFxuICAgIH0sXG4gICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgIGRhdGEsXG4gICAgICBtZXRhOiB7XG4gICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgIC4uLm1ldGEsXG4gICAgICB9LFxuICAgIH0pLFxuICB9O1xufVxuXG4vKipcbiAqIENvbW1vbiBIVFRQIHN0YXR1cyBjb2RlcyBmb3IgUkVTVCBBUElzXG4gKi9cbmV4cG9ydCBjb25zdCBIVFRQX1NUQVRVUyA9IHtcbiAgT0s6IDIwMCxcbiAgQ1JFQVRFRDogMjAxLFxuICBOT19DT05URU5UOiAyMDQsXG4gIEJBRF9SRVFVRVNUOiA0MDAsXG4gIFVOQVVUSE9SSVpFRDogNDAxLFxuICBGT1JCSURERU46IDQwMyxcbiAgTk9UX0ZPVU5EOiA0MDQsXG4gIE1FVEhPRF9OT1RfQUxMT1dFRDogNDA1LFxuICBDT05GTElDVDogNDA5LFxuICBVTlBST0NFU1NBQkxFX0VOVElUWTogNDIyLFxuICBJTlRFUk5BTF9TRVJWRVJfRVJST1I6IDUwMCxcbiAgU0VSVklDRV9VTkFWQUlMQUJMRTogNTAzLFxufSBhcyBjb25zdDtcblxuLyoqXG4gKiBDb21wcmVoZW5zaXZlIGVycm9yIGNvZGVzIGZvciBSRVNUIEFQSSByZXNwb25zZXNcbiAqL1xuZXhwb3J0IGNvbnN0IEVSUk9SX0NPREVTID0ge1xuICBCQURfUkVRVUVTVDogJ0JBRF9SRVFVRVNUJyxcbiAgVkFMSURBVElPTl9FUlJPUjogJ1ZBTElEQVRJT05fRVJST1InLFxuICBVTlBST0NFU1NBQkxFX0VOVElUWTogJ1VOUFJPQ0VTU0FCTEVfRU5USVRZJyxcbiAgVU5BVVRIT1JJWkVEOiAnVU5BVVRIT1JJWkVEJyxcbiAgQVVUSEVOVElDQVRJT05fRVJST1I6ICdBVVRIRU5USUNBVElPTl9FUlJPUicsXG4gIEZPUkJJRERFTjogJ0ZPUkJJRERFTicsXG4gIEFVVEhPUklaQVRJT05fRVJST1I6ICdBVVRIT1JJWkFUSU9OX0VSUk9SJyxcbiAgTk9UX0ZPVU5EOiAnTk9UX0ZPVU5EJyxcbiAgQ09ORkxJQ1Q6ICdDT05GTElDVCcsXG4gIE1FVEhPRF9OT1RfQUxMT1dFRDogJ01FVEhPRF9OT1RfQUxMT1dFRCcsXG4gIElOVEVSTkFMX1NFUlZFUl9FUlJPUjogJ0lOVEVSTkFMX1NFUlZFUl9FUlJPUicsXG4gIFNFUlZJQ0VfVU5BVkFJTEFCTEU6ICdTRVJWSUNFX1VOQVZBSUxBQkxFJyxcbn0gYXMgY29uc3Q7XG5cbi8qKiBFbnZpcm9ubWVudCBkZXRlY3Rpb24gaGVscGVyICovXG5leHBvcnQgY29uc3QgaXNEZXZlbG9wbWVudCA9IHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAnZGV2ZWxvcG1lbnQnO1xuXG4vKipcbiAqIENvbW1vbiBtaWRkbGV3YXJlIGluaXRpYWxpemF0aW9uIGhlbHBlciB0aGF0IHNldHMgdXAgbG9nZ2luZyBhbmQgY29udGV4dFxuICogQHBhcmFtIGlucHV0IC0gUkVTVCBpbnB1dCB3aXRoIGV2ZW50IGFuZCBjb250ZXh0XG4gKiBAcGFyYW0gY29uZmlnIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBpbml0aWFsaXphdGlvblxuICogQHJldHVybnMgSW5pdGlhbGl6ZWQgaW5wdXQsIGNvbnRleHQsIGFuZCByZXF1ZXN0IElEXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplUmVzdE1pZGRsZXdhcmU8VCBleHRlbmRzIFJlc3RJbnB1dFdpdGhNb2RlbHM+KFxuICBpbnB1dDogVCxcbiAgY29uZmlnOiB7XG4gICAgZGVmYXVsdENvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBmb3JjZVN0cnVjdHVyZWRMb2dnaW5nPzogYm9vbGVhbjtcbiAgICBvcGVyYXRpb24/OiBzdHJpbmc7XG4gIH0gPSB7fSxcbik6IHtcbiAgaW5wdXQ6IFJlc3RJbnB1dFdpdGhNb2RlbHM7XG4gIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICByZXF1ZXN0SWQ6IHN0cmluZztcbn0ge1xuICBjb25zdCB7XG4gICAgZGVmYXVsdENvbnRleHQgPSB7fSxcbiAgICBmb3JjZVN0cnVjdHVyZWRMb2dnaW5nID0gdHJ1ZSxcbiAgICBvcGVyYXRpb24gPSAnbWlkZGxld2FyZScsXG4gIH0gPSBjb25maWc7XG5cbiAgY29uc3QgdHlwZWRJbnB1dCA9IGlucHV0IGFzIFJlc3RJbnB1dFdpdGhNb2RlbHM7XG4gIHNldHVwU3RydWN0dXJlZExvZ2dpbmcodHlwZWRJbnB1dCwgZm9yY2VTdHJ1Y3R1cmVkTG9nZ2luZywgZGVmYXVsdENvbnRleHQpO1xuXG4gIGNvbnN0IHsgY29udGV4dCwgcmVxdWVzdElkIH0gPSB2YWxpZGF0ZUJhc2ljUmVxdWVzdEluZm8oXG4gICAgdHlwZWRJbnB1dCxcbiAgICBvcGVyYXRpb24sXG4gICk7XG5cbiAgcmV0dXJuIHtcbiAgICBpbnB1dDogdHlwZWRJbnB1dCxcbiAgICBjb250ZXh0LFxuICAgIHJlcXVlc3RJZCxcbiAgfTtcbn1cbiJdfQ==