@energica-city/shared-amplify-utils
Version:
Shared utilities for AWS Amplify projects
270 lines • 31.5 kB
JavaScript
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==