@energica-city/shared-amplify-utils
Version:
Shared utilities for AWS Amplify projects
291 lines • 32.5 kB
JavaScript
import { logger } from '../log';
/**
* Helper to process string messages with optional context.
*/
function processStringMessage(message, originalErrorOrContext) {
if (originalErrorOrContext === undefined) {
return {
finalMessage: message,
originalError: undefined,
errorContext: {},
};
}
if (originalErrorOrContext instanceof Error) {
return {
finalMessage: `${message}: ${originalErrorOrContext.message}`,
originalError: originalErrorOrContext,
errorContext: {
originalError: {
name: originalErrorOrContext.name,
message: originalErrorOrContext.message,
stack: originalErrorOrContext.stack,
},
},
};
}
if (typeof originalErrorOrContext === 'object' &&
originalErrorOrContext !== null) {
return {
finalMessage: message,
originalError: originalErrorOrContext,
errorContext: originalErrorOrContext,
};
}
return {
finalMessage: `${message}: ${String(originalErrorOrContext)}`,
originalError: originalErrorOrContext,
errorContext: { originalError: originalErrorOrContext },
};
}
/**
* Helper to process Error objects.
*/
function processErrorObject(error) {
return {
finalMessage: error.message,
originalError: error,
errorContext: {
originalError: {
name: error.name,
message: error.message,
stack: error.stack,
},
},
};
}
/**
* Helper to process arrays of errors.
*/
function processErrorArray(errors) {
const errorMessages = errors.map(err => {
if (err instanceof Error)
return err.message;
if (typeof err === 'object' && err !== null && 'message' in err) {
return String(err.message);
}
return String(err);
});
const finalMessage = errorMessages.length > 1
? `Multiple errors occurred: ${errorMessages.join('; ')}`
: errorMessages[0] || 'Unknown error occurred';
return {
finalMessage,
originalError: errors,
errorContext: { errors },
};
}
/**
* Helper to process unknown values.
*/
function processUnknownValue(unknownError) {
const errorObj = unknownError;
if (typeof errorObj === 'object' &&
errorObj !== null &&
'message' in errorObj) {
return {
finalMessage: String(errorObj.message),
originalError: unknownError,
errorContext: { originalError: unknownError },
};
}
return {
finalMessage: `Unexpected error: ${String(unknownError)}`,
originalError: unknownError,
errorContext: { originalError: unknownError },
};
}
/**
* Helper to create and configure the error object using ES2022 standards.
*/
function createErrorObject(finalMessage, originalError, errorContext) {
let error;
// Use modern Error constructor with cause (ES2022 standard) when originalError exists
if (originalError !== undefined) {
try {
// Modern approach - supported in Node.js 16.9+ and modern browsers
error = new Error(finalMessage, { cause: originalError });
}
catch {
// Fallback for older environments that don't support cause parameter
error = new Error(finalMessage);
Object.defineProperty(error, 'cause', {
value: originalError,
writable: true,
enumerable: false,
configurable: true,
});
}
// Backward compatibility: also set originalError property
if (!('originalError' in error)) {
Object.defineProperty(error, 'originalError', {
value: originalError,
writable: true,
enumerable: false,
configurable: true,
});
}
}
else {
error = new Error(finalMessage);
}
// Enhanced stack trace chaining for better debugging
if (originalError instanceof Error && originalError.stack) {
error.stack = `${error.stack}\n\nCaused by: ${originalError.stack}`;
}
// Always add a marker to identify errors from our library
Object.defineProperty(error, '__fromErrorLibrary', {
value: true,
writable: false,
enumerable: false,
configurable: false,
});
// Assign context properties as non-enumerable properties
if (errorContext && typeof errorContext === 'object') {
for (const [key, value] of Object.entries(errorContext)) {
// Skip system properties that are already handled
if (!['originalError', 'cause', 'stack', '__fromErrorLibrary'].includes(key)) {
Object.defineProperty(error, key, {
value,
writable: true,
enumerable: false,
configurable: true,
});
}
}
}
return error;
}
/**
* Enhanced error throwing function that ensures consistent error handling and logging
* across the application. It automatically logs errors with structured data and creates
* properly formatted Error objects with additional context.
*
* @param messageOrError - The primary error message (string) or Error object to throw
* @param originalErrorOrContext - Optional: original error object or additional context
* @throws {Error} Always throws a properly formatted Error with enhanced context
*
* @example
* ```typescript
* // Simple message
* throwError('Database connection failed');
*
* // Message with context
* throwError('User not found', { userId: '123', operation: 'getUser' });
*
* // Message with original error
* throwError('Failed to process request', originalError);
*
* // Error object (will extract message)
* throwError(new Error('Something went wrong'));
*
* // Array of errors (will combine messages)
* throwError([error1, error2, 'Additional info']);
* ```
*/
export function throwError(messageOrError, originalErrorOrContext) {
let result;
if (typeof messageOrError === 'string') {
result = processStringMessage(messageOrError, originalErrorOrContext);
}
else if (messageOrError instanceof Error) {
result = processErrorObject(messageOrError);
}
else if (Array.isArray(messageOrError)) {
result = processErrorArray(messageOrError);
}
else {
result = processUnknownValue(messageOrError);
}
const { finalMessage, originalError, errorContext } = result;
// Enhanced logging with structured data (CloudWatch handles timestamps)
logger.error(finalMessage, {
...errorContext,
errorType: typeof originalError,
stack: new Error().stack, // Capture current stack trace for debugging
});
// Create and throw the error
const error = createErrorObject(finalMessage, originalError, errorContext);
throw error;
}
/**
* Utility function to safely extract an error message from an unknown error type.
* It handles various types of error objects, strings, and other values to produce a consistent
* string representation of the error, which is useful for displaying error messages to users.
*
* @param error - The error from which to extract the message. It can be of any type.
* @returns A string representing the error message.
* @example
* try {
* // some operation
* } catch (error) {
* const message = extractErrorMessage(error);
* console.log('Error occurred:', message);
* }
*/
export function extractErrorMessage(error) {
if (error instanceof Error) {
return error.message;
}
if (typeof error === 'string') {
return error;
}
if (Array.isArray(error)) {
if (error.length === 0) {
return '';
}
// Recursively flatten and extract messages from arrays
const messages = [];
function flattenAndExtract(item) {
if (Array.isArray(item)) {
item.forEach(flattenAndExtract);
}
else {
const message = extractErrorMessage(item);
if (message) {
messages.push(message);
}
}
}
error.forEach(flattenAndExtract);
return messages.join('; ');
}
if (typeof error === 'object' && error !== null) {
if ('message' in error &&
typeof error.message === 'string') {
return error.message;
}
if ('error' in error &&
typeof error.error === 'string') {
return error.error;
}
if ('details' in error &&
typeof error.details === 'string') {
return error.details;
}
if ('description' in error &&
typeof error.description === 'string') {
return error.description;
}
}
return String(error);
}
/**
* Utility function to create error context objects with proper filtering.
* This ensures consistent context structure while removing undefined values
* that could clutter logs or cause serialization issues.
*
* @param context - Raw context object that may contain undefined values
* @returns Filtered context object with undefined values removed
* @example
* const context = createErrorContext({
* userId: user?.id, // might be undefined
* operation: 'deleteUser', // always defined
* requestId: req.id // always defined
* });
* // Result: { operation: 'deleteUser', requestId: 'abc123' }
* // (userId omitted because it was undefined)
*/
export function createErrorContext(context) {
return Object.fromEntries(Object.entries(context).filter(([, value]) => value !== undefined));
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9lcnJvci9lcnJvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBUWhDOztHQUVHO0FBQ0gsU0FBUyxvQkFBb0IsQ0FDM0IsT0FBZSxFQUNmLHNCQUFnQztJQU1oQyxJQUFJLHNCQUFzQixLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3pDLE9BQU87WUFDTCxZQUFZLEVBQUUsT0FBTztZQUNyQixhQUFhLEVBQUUsU0FBUztZQUN4QixZQUFZLEVBQUUsRUFBRTtTQUNqQixDQUFDO0lBQ0osQ0FBQztJQUVELElBQUksc0JBQXNCLFlBQVksS0FBSyxFQUFFLENBQUM7UUFDNUMsT0FBTztZQUNMLFlBQVksRUFBRSxHQUFHLE9BQU8sS0FBSyxzQkFBc0IsQ0FBQyxPQUFPLEVBQUU7WUFDN0QsYUFBYSxFQUFFLHNCQUFzQjtZQUNyQyxZQUFZLEVBQUU7Z0JBQ1osYUFBYSxFQUFFO29CQUNiLElBQUksRUFBRSxzQkFBc0IsQ0FBQyxJQUFJO29CQUNqQyxPQUFPLEVBQUUsc0JBQXNCLENBQUMsT0FBTztvQkFDdkMsS0FBSyxFQUFFLHNCQUFzQixDQUFDLEtBQUs7aUJBQ3BDO2FBQ0Y7U0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELElBQ0UsT0FBTyxzQkFBc0IsS0FBSyxRQUFRO1FBQzFDLHNCQUFzQixLQUFLLElBQUksRUFDL0IsQ0FBQztRQUNELE9BQU87WUFDTCxZQUFZLEVBQUUsT0FBTztZQUNyQixhQUFhLEVBQUUsc0JBQXNCO1lBQ3JDLFlBQVksRUFBRSxzQkFBc0M7U0FDckQsQ0FBQztJQUNKLENBQUM7SUFFRCxPQUFPO1FBQ0wsWUFBWSxFQUFFLEdBQUcsT0FBTyxLQUFLLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFO1FBQzdELGFBQWEsRUFBRSxzQkFBc0I7UUFDckMsWUFBWSxFQUFFLEVBQUUsYUFBYSxFQUFF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SUFDRSxTQUFTLElBQUksS0FBSztZQUNsQixPQUFRLEtBQThCLENBQUMsT0FBTyxLQUFLLFFBQVEsRUFDM0QsQ0FBQztZQUNELE9BQVEsS0FBNkIsQ0FBQyxPQUFPLENBQUM7UUFDaEQsQ0FBQztRQUVELElBQ0UsT0FBTyxJQUFJLEtBQUs7WUFDaEIsT0FBUSxLQUE0QixDQUFDLEtBQUssS0FBSyxRQUFRLEVBQ3ZELENBQUM7WUFDRCxPQUFRLEtBQTJCLENBQUMsS0FBSyxDQUFDO1FBQzVDLENBQUM7UUFFRCxJQUNFLFNBQVMsSUFBSSxLQUFLO1lBQ2xCLE9BQVEsS0FBOEIsQ0FBQyxPQUFPLEtBQUssUUFBUSxFQUMzRCxDQUFDO1lBQ0QsT0FBUSxLQUE2QixDQUFDLE9BQU8sQ0FBQztRQUNoRCxDQUFDO1FBRUQsSUFDRSxhQUFhLElBQUksS0FBSztZQUN0QixPQUFRLEtBQWtDLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFDbkUsQ0FBQztZQUNELE9BQVEsS0FBaUMsQ0FBQyxXQUFXLENBQUM7UUFDeEQsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN2QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxPQUFnQztJQUVoQyxPQUFPLE1BQU0sQ0FBQyxXQUFXLENBQ3ZCLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQ25FLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vbG9nJztcblxuLyoqXG4gKiBUeXBlIGRlZmluaXRpb24gZm9yIGVycm9yIGNvbnRleHQgb2JqZWN0cyB0aGF0IGNhbiBiZSBwYXNzZWQgdG8gdGhyb3dFcnJvci5cbiAqIFRoaXMgYWxsb3dzIGZvciBzdHJ1Y3R1cmVkIGVycm9yIGluZm9ybWF0aW9uIHdoaWxlIG1haW50YWluaW5nIHR5cGUgc2FmZXR5LlxuICovXG5leHBvcnQgdHlwZSBFcnJvckNvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuLyoqXG4gKiBIZWxwZXIgdG8gcHJvY2VzcyBzdHJpbmcgbWVzc2FnZXMgd2l0aCBvcHRpb25hbCBjb250ZXh0LlxuICovXG5mdW5jdGlvbiBwcm9jZXNzU3RyaW5nTWVzc2FnZShcbiAgbWVzc2FnZTogc3RyaW5nLFxuICBvcmlnaW5hbEVycm9yT3JDb250ZXh0PzogdW5rbm93bixcbik6IHtcbiAgZmluYWxNZXNzYWdlOiBzdHJpbmc7XG4gIG9yaWdpbmFsRXJyb3I6IHVua25vd247XG4gIGVycm9yQ29udGV4dDogRXJyb3JDb250ZXh0O1xufSB7XG4gIGlmIChvcmlnaW5hbEVycm9yT3JDb250ZXh0ID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZmluYWxNZXNzYWdlOiBtZXNzYWdlLFxuICAgICAgb3JpZ2luYWxFcnJvcjogdW5kZWZpbmVkLFxuICAgICAgZXJyb3JDb250ZXh0OiB7fSxcbiAgICB9O1xuICB9XG5cbiAgaWYgKG9yaWdpbmFsRXJyb3JPckNvbnRleHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHJldHVybiB7XG4gICAgICBmaW5hbE1lc3NhZ2U6IGAke21lc3NhZ2V9OiAke29yaWdpbmFsRXJyb3JPckNvbnRleHQubWVzc2FnZX1gLFxuICAgICAgb3JpZ2luYWxFcnJvcjogb3JpZ2luYWxFcnJvck9yQ29udGV4dCxcbiAgICAgIGVycm9yQ29udGV4dDoge1xuICAgICAgICBvcmlnaW5hbEVycm9yOiB7XG4gICAgICAgICAgbmFtZTogb3JpZ2luYWxFcnJvck9yQ29udGV4dC5uYW1lLFxuICAgICAgICAgIG1lc3NhZ2U6IG9yaWdpbmFsRXJyb3JPckNvbnRleHQubWVzc2FnZSxcbiAgICAgICAgICBzdGFjazogb3JpZ2luYWxFcnJvck9yQ29udGV4dC5zdGFjayxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIGlmIChcbiAgICB0eXBlb2Ygb3JpZ2luYWxFcnJvck9yQ29udGV4dCA9PT0gJ29iamVjdCcgJiZcbiAgICBvcmlnaW5hbEVycm9yT3JDb250ZXh0ICE9PSBudWxsXG4gICkge1xuICAgIHJldHVybiB7XG4gICAgICBmaW5hbE1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICBvcmlnaW5hbEVycm9yOiBvcmlnaW5hbEVycm9yT3JDb250ZXh0LFxuICAgICAgZXJyb3JDb250ZXh0OiBvcmlnaW5hbEVycm9yT3JDb250ZXh0IGFzIEVycm9yQ29udGV4dCxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBmaW5hbE1lc3NhZ2U6IGAke21lc3NhZ2V9OiAke1N0cmluZyhvcmlnaW5hbEVycm9yT3JDb250ZXh0KX1gLFxuICAgIG9yaWdpbmFsRXJyb3I6IG9yaWdpbmFsRXJyb3JPckNvbnRleHQsXG4gICAgZXJyb3JDb250ZXh0OiB7IG9yaWdpbmFsRXJyb3I6IG9yaWdpbmFsRXJyb3JPckNvbnRleHQgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBIZWxwZXIgdG8gcHJvY2VzcyBFcnJvciBvYmplY3RzLlxuICovXG5mdW5jdGlvbiBwcm9jZXNzRXJyb3JPYmplY3QoZXJyb3I6IEVycm9yKToge1xuICBmaW5hbE1lc3NhZ2U6IHN0cmluZztcbiAgb3JpZ2luYWxFcnJvcjogRXJyb3I7XG4gIGVycm9yQ29udGV4dDogRXJyb3JDb250ZXh0O1xufSB7XG4gIHJldHVybiB7XG4gICAgZmluYWxNZXNzYWdlOiBlcnJvci5tZXNzYWdlLFxuICAgIG9yaWdpbmFsRXJyb3I6IGVycm9yLFxuICAgIGVycm9yQ29udGV4dDoge1xuICAgICAgb3JpZ2luYWxFcnJvcjoge1xuICAgICAgICBuYW1lOiBlcnJvci5uYW1lLFxuICAgICAgICBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLFxuICAgICAgICBzdGFjazogZXJyb3Iuc3RhY2ssXG4gICAgICB9LFxuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogSGVscGVyIHRvIHByb2Nlc3MgYXJyYXlzIG9mIGVycm9ycy5cbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0Vycm9yQXJyYXkoZXJyb3JzOiB1bmtub3duW10pOiB7XG4gIGZpbmFsTWVzc2FnZTogc3RyaW5nO1xuICBvcmlnaW5hbEVycm9yOiB1bmtub3duW107XG4gIGVycm9yQ29udGV4dDogRXJyb3JDb250ZXh0O1xufSB7XG4gIGNvbnN0IGVycm9yTWVzc2FnZXMgPSBlcnJvcnMubWFwKGVyciA9PiB7XG4gICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yKSByZXR1cm4gZXJyLm1lc3NhZ2U7XG4gICAgaWYgKHR5cGVvZiBlcnIgPT09ICdvYmplY3QnICYmIGVyciAhPT0gbnVsbCAmJiAnbWVzc2FnZScgaW4gZXJyKSB7XG4gICAgICByZXR1cm4gU3RyaW5nKChlcnIgYXMgeyBtZXNzYWdlOiB1bmtub3duIH0pLm1lc3NhZ2UpO1xuICAgIH1cbiAgICByZXR1cm4gU3RyaW5nKGVycik7XG4gIH0pO1xuXG4gIGNvbnN0IGZpbmFsTWVzc2FnZSA9XG4gICAgZXJyb3JNZXNzYWdlcy5sZW5ndGggPiAxXG4gICAgICA/IGBNdWx0aXBsZSBlcnJvcnMgb2NjdXJyZWQ6ICR7ZXJyb3JNZXNzYWdlcy5qb2luKCc7ICcpfWBcbiAgICAgIDogZXJyb3JNZXNzYWdlc1swXSB8fCAnVW5rbm93biBlcnJvciBvY2N1cnJlZCc7XG5cbiAgcmV0dXJuIHtcbiAgICBmaW5hbE1lc3NhZ2UsXG4gICAgb3JpZ2luYWxFcnJvcjogZXJyb3JzLFxuICAgIGVycm9yQ29udGV4dDogeyBlcnJvcnMgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBIZWxwZXIgdG8gcHJvY2VzcyB1bmtub3duIHZhbHVlcy5cbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc1Vua25vd25WYWx1ZSh1bmtub3duRXJyb3I6IHVua25vd24pOiB7XG4gIGZpbmFsTWVzc2FnZTogc3RyaW5nO1xuICBvcmlnaW5hbEVycm9yOiB1bmtub3duO1xuICBlcnJvckNvbnRleHQ6IEVycm9yQ29udGV4dDtcbn0ge1xuICBjb25zdCBlcnJvck9iaiA9IHVua25vd25FcnJvciBhcyB7IG1lc3NhZ2U/OiB1bmtub3duIH07XG5cbiAgaWYgKFxuICAgIHR5cGVvZiBlcnJvck9iaiA9PT0gJ29iamVjdCcgJiZcbiAgICBlcnJvck9iaiAhPT0gbnVsbCAmJlxuICAgICdtZXNzYWdlJyBpbiBlcnJvck9ialxuICApIHtcbiAgICByZXR1cm4ge1xuICAgICAgZmluYWxNZXNzYWdlOiBTdHJpbmcoZXJyb3JPYmoubWVzc2FnZSksXG4gICAgICBvcmlnaW5hbEVycm9yOiB1bmtub3duRXJyb3IsXG4gICAgICBlcnJvckNvbnRleHQ6IHsgb3JpZ2luYWxFcnJvcjogdW5rbm93bkVycm9yIH0sXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZmluYWxNZXNzYWdlOiBgVW5leHBlY3RlZCBlcnJvcjogJHtTdHJpbmcodW5rbm93bkVycm9yKX1gLFxuICAgIG9yaWdpbmFsRXJyb3I6IHVua25vd25FcnJvcixcbiAgICBlcnJvckNvbnRleHQ6IHsgb3JpZ2luYWxFcnJvcjogdW5rbm93bkVycm9yIH0sXG4gIH07XG59XG5cbi8qKlxuICogSGVscGVyIHRvIGNyZWF0ZSBhbmQgY29uZmlndXJlIHRoZSBlcnJvciBvYmplY3QgdXNpbmcgRVMyMDIyIHN0YW5kYXJkcy5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlRXJyb3JPYmplY3QoXG4gIGZpbmFsTWVzc2FnZTogc3RyaW5nLFxuICBvcmlnaW5hbEVycm9yOiB1bmtub3duLFxuICBlcnJvckNvbnRleHQ6IEVycm9yQ29udGV4dCxcbik6IEVycm9yIHtcbiAgbGV0IGVycm9yOiBFcnJvcjtcblxuICAvLyBVc2UgbW9kZXJuIEVycm9yIGNvbnN0cnVjdG9yIHdpdGggY2F1c2UgKEVTMjAyMiBzdGFuZGFyZCkgd2hlbiBvcmlnaW5hbEVycm9yIGV4aXN0c1xuICBpZiAob3JpZ2luYWxFcnJvciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIE1vZGVybiBhcHByb2FjaCAtIHN1cHBvcnRlZCBpbiBOb2RlLmpzIDE2LjkrIGFuZCBtb2Rlcm4gYnJvd3NlcnNcbiAgICAgIGVycm9yID0gbmV3IEVycm9yKGZpbmFsTWVzc2FnZSwgeyBjYXVzZTogb3JpZ2luYWxFcnJvciB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIEZhbGxiYWNrIGZvciBvbGRlciBlbnZpcm9ubWVudHMgdGhhdCBkb24ndCBzdXBwb3J0IGNhdXNlIHBhcmFtZXRlclxuICAgICAgZXJyb3IgPSBuZXcgRXJyb3IoZmluYWxNZXNzYWdlKTtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvciwgJ2NhdXNlJywge1xuICAgICAgICB2YWx1ZTogb3JpZ2luYWxFcnJvcixcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBCYWNrd2FyZCBjb21wYXRpYmlsaXR5OiBhbHNvIHNldCBvcmlnaW5hbEVycm9yIHByb3BlcnR5XG4gICAgaWYgKCEoJ29yaWdpbmFsRXJyb3InIGluIGVycm9yKSkge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGVycm9yLCAnb3JpZ2luYWxFcnJvcicsIHtcbiAgICAgICAgdmFsdWU6IG9yaWdpbmFsRXJyb3IsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGVycm9yID0gbmV3IEVycm9yKGZpbmFsTWVzc2FnZSk7XG4gIH1cblxuICAvLyBFbmhhbmNlZCBzdGFjayB0cmFjZSBjaGFpbmluZyBmb3IgYmV0dGVyIGRlYnVnZ2luZ1xuICBpZiAob3JpZ2luYWxFcnJvciBpbnN0YW5jZW9mIEVycm9yICYmIG9yaWdpbmFsRXJyb3Iuc3RhY2spIHtcbiAgICBlcnJvci5zdGFjayA9IGAke2Vycm9yLnN0YWNrfVxcblxcbkNhdXNlZCBieTogJHtvcmlnaW5hbEVycm9yLnN0YWNrfWA7XG4gIH1cblxuICAvLyBBbHdheXMgYWRkIGEgbWFya2VyIHRvIGlkZW50aWZ5IGVycm9ycyBmcm9tIG91ciBsaWJyYXJ5XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvciwgJ19fZnJvbUVycm9yTGlicmFyeScsIHtcbiAgICB2YWx1ZTogdHJ1ZSxcbiAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgfSk7XG5cbiAgLy8gQXNzaWduIGNvbnRleHQgcHJvcGVydGllcyBhcyBub24tZW51bWVyYWJsZSBwcm9wZXJ0aWVzXG4gIGlmIChlcnJvckNvbnRleHQgJiYgdHlwZW9mIGVycm9yQ29udGV4dCA9PT0gJ29iamVjdCcpIHtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhlcnJvckNvbnRleHQpKSB7XG4gICAgICAvLyBTa2lwIHN5c3RlbSBwcm9wZXJ0aWVzIHRoYXQgYXJlIGFscmVhZHkgaGFuZGxlZFxuICAgICAgaWYgKFxuICAgICAgICAhWydvcmlnaW5hbEVycm9yJywgJ2NhdXNlJywgJ3N0YWNrJywgJ19fZnJvbUVycm9yTGlicmFyeSddLmluY2x1ZGVzKGtleSlcbiAgICAgICkge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXJyb3IsIGtleSwge1xuICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGVycm9yO1xufVxuXG4vKipcbiAqIEVuaGFuY2VkIGVycm9yIHRocm93aW5nIGZ1bmN0aW9uIHRoYXQgZW5zdXJlcyBjb25zaXN0ZW50IGVycm9yIGhhbmRsaW5nIGFuZCBsb2dnaW5nXG4gKiBhY3Jvc3MgdGhlIGFwcGxpY2F0aW9uLiBJdCBhdXRvbWF0aWNhbGx5IGxvZ3MgZXJyb3JzIHdpdGggc3RydWN0dXJlZCBkYXRhIGFuZCBjcmVhdGVzXG4gKiBwcm9wZXJseSBmb3JtYXR0ZWQgRXJyb3Igb2JqZWN0cyB3aXRoIGFkZGl0aW9uYWwgY29udGV4dC5cbiAqXG4gKiBAcGFyYW0gbWVzc2FnZU9yRXJyb3IgLSBUaGUgcHJpbWFyeSBlcnJvciBtZXNzYWdlIChzdHJpbmcpIG9yIEVycm9yIG9iamVjdCB0byB0aHJvd1xuICogQHBhcmFtIG9yaWdpbmFsRXJyb3JPckNvbnRleHQgLSBPcHRpb25hbDogb3JpZ2luYWwgZXJyb3Igb2JqZWN0IG9yIGFkZGl0aW9uYWwgY29udGV4dFxuICogQHRocm93cyB7RXJyb3J9IEFsd2F5cyB0aHJvd3MgYSBwcm9wZXJseSBmb3JtYXR0ZWQgRXJyb3Igd2l0aCBlbmhhbmNlZCBjb250ZXh0XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIFNpbXBsZSBtZXNzYWdlXG4gKiB0aHJvd0Vycm9yKCdEYXRhYmFzZSBjb25uZWN0aW9uIGZhaWxlZCcpO1xuICpcbiAqIC8vIE1lc3NhZ2Ugd2l0aCBjb250ZXh0XG4gKiB0aHJvd0Vycm9yKCdVc2VyIG5vdCBmb3VuZCcsIHsgdXNlcklkOiAnMTIzJywgb3BlcmF0aW9uOiAnZ2V0VXNlcicgfSk7XG4gKlxuICogLy8gTWVzc2FnZSB3aXRoIG9yaWdpbmFsIGVycm9yXG4gKiB0aHJvd0Vycm9yKCdGYWlsZWQgdG8gcHJvY2VzcyByZXF1ZXN0Jywgb3JpZ2luYWxFcnJvcik7XG4gKlxuICogLy8gRXJyb3Igb2JqZWN0ICh3aWxsIGV4dHJhY3QgbWVzc2FnZSlcbiAqIHRocm93RXJyb3IobmV3IEVycm9yKCdTb21ldGhpbmcgd2VudCB3cm9uZycpKTtcbiAqXG4gKiAvLyBBcnJheSBvZiBlcnJvcnMgKHdpbGwgY29tYmluZSBtZXNzYWdlcylcbiAqIHRocm93RXJyb3IoW2Vycm9yMSwgZXJyb3IyLCAnQWRkaXRpb25hbCBpbmZvJ10pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aHJvd0Vycm9yKFxuICBtZXNzYWdlT3JFcnJvcjogc3RyaW5nIHwgRXJyb3IgfCB1bmtub3duW10sXG4gIG9yaWdpbmFsRXJyb3JPckNvbnRleHQ/OiB1bmtub3duLFxuKTogbmV2ZXIge1xuICBsZXQgcmVzdWx0OiB7XG4gICAgZmluYWxNZXNzYWdlOiBzdHJpbmc7XG4gICAgb3JpZ2luYWxFcnJvcjogdW5rbm93bjtcbiAgICBlcnJvckNvbnRleHQ6IEVycm9yQ29udGV4dDtcbiAgfTtcblxuICBpZiAodHlwZW9mIG1lc3NhZ2VPckVycm9yID09PSAnc3RyaW5nJykge1xuICAgIHJlc3VsdCA9IHByb2Nlc3NTdHJpbmdNZXNzYWdlKG1lc3NhZ2VPckVycm9yLCBvcmlnaW5hbEVycm9yT3JDb250ZXh0KTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlT3JFcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgcmVzdWx0ID0gcHJvY2Vzc0Vycm9yT2JqZWN0KG1lc3NhZ2VPckVycm9yKTtcbiAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG1lc3NhZ2VPckVycm9yKSkge1xuICAgIHJlc3VsdCA9IHByb2Nlc3NFcnJvckFycmF5KG1lc3NhZ2VPckVycm9yKTtcbiAgfSBlbHNlIHtcbiAgICByZXN1bHQgPSBwcm9jZXNzVW5rbm93blZhbHVlKG1lc3NhZ2VPckVycm9yKTtcbiAgfVxuXG4gIGNvbnN0IHsgZmluYWxNZXNzYWdlLCBvcmlnaW5hbEVycm9yLCBlcnJvckNvbnRleHQgfSA9IHJlc3VsdDtcblxuICAvLyBFbmhhbmNlZCBsb2dnaW5nIHdpdGggc3RydWN0dXJlZCBkYXRhIChDbG91ZFdhdGNoIGhhbmRsZXMgdGltZXN0YW1wcylcbiAgbG9nZ2VyLmVycm9yKGZpbmFsTWVzc2FnZSwge1xuICAgIC4uLmVycm9yQ29udGV4dCxcbiAgICBlcnJvclR5cGU6IHR5cGVvZiBvcmlnaW5hbEVycm9yLFxuICAgIHN0YWNrOiBuZXcgRXJyb3IoKS5zdGFjaywgLy8gQ2FwdHVyZSBjdXJyZW50IHN0YWNrIHRyYWNlIGZvciBkZWJ1Z2dpbmdcbiAgfSk7XG5cbiAgLy8gQ3JlYXRlIGFuZCB0aHJvdyB0aGUgZXJyb3JcbiAgY29uc3QgZXJyb3IgPSBjcmVhdGVFcnJvck9iamVjdChmaW5hbE1lc3NhZ2UsIG9yaWdpbmFsRXJyb3IsIGVycm9yQ29udGV4dCk7XG4gIHRocm93IGVycm9yO1xufVxuXG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb24gdG8gc2FmZWx5IGV4dHJhY3QgYW4gZXJyb3IgbWVzc2FnZSBmcm9tIGFuIHVua25vd24gZXJyb3IgdHlwZS5cbiAqIEl0IGhhbmRsZXMgdmFyaW91cyB0eXBlcyBvZiBlcnJvciBvYmplY3RzLCBzdHJpbmdzLCBhbmQgb3RoZXIgdmFsdWVzIHRvIHByb2R1Y2UgYSBjb25zaXN0ZW50XG4gKiBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGVycm9yLCB3aGljaCBpcyB1c2VmdWwgZm9yIGRpc3BsYXlpbmcgZXJyb3IgbWVzc2FnZXMgdG8gdXNlcnMuXG4gKlxuICogQHBhcmFtIGVycm9yIC0gVGhlIGVycm9yIGZyb20gd2hpY2ggdG8gZXh0cmFjdCB0aGUgbWVzc2FnZS4gSXQgY2FuIGJlIG9mIGFueSB0eXBlLlxuICogQHJldHVybnMgQSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBlcnJvciBtZXNzYWdlLlxuICogQGV4YW1wbGVcbiAqIHRyeSB7XG4gKiAgIC8vIHNvbWUgb3BlcmF0aW9uXG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogICBjb25zdCBtZXNzYWdlID0gZXh0cmFjdEVycm9yTWVzc2FnZShlcnJvcik7XG4gKiAgIGNvbnNvbGUubG9nKCdFcnJvciBvY2N1cnJlZDonLCBtZXNzYWdlKTtcbiAqIH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3RFcnJvck1lc3NhZ2UoZXJyb3I6IHVua25vd24pOiBzdHJpbmcge1xuICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHJldHVybiBlcnJvci5tZXNzYWdlO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBlcnJvciA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZXJyb3I7XG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheShlcnJvcikpIHtcbiAgICBpZiAoZXJyb3IubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgLy8gUmVjdXJzaXZlbHkgZmxhdHRlbiBhbmQgZXh0cmFjdCBtZXNzYWdlcyBmcm9tIGFycmF5c1xuICAgIGNvbnN0IG1lc3NhZ2VzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgZnVuY3Rpb24gZmxhdHRlbkFuZEV4dHJhY3QoaXRlbTogdW5rbm93bik6IHZvaWQge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaXRlbSkpIHtcbiAgICAgICAgaXRlbS5mb3JFYWNoKGZsYXR0ZW5BbmRFeHRyYWN0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBleHRyYWN0RXJyb3JNZXNzYWdlKGl0ZW0pO1xuICAgICAgICBpZiAobWVzc2FnZSkge1xuICAgICAgICAgIG1lc3NhZ2VzLnB1c2gobWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBlcnJvci5mb3JFYWNoKGZsYXR0ZW5BbmRFeHRyYWN0KTtcbiAgICByZXR1cm4gbWVzc2FnZXMuam9pbignOyAnKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgZXJyb3IgPT09ICdvYmplY3QnICYmIGVycm9yICE9PSBudWxsKSB7XG4gICAgaWYgKFxuICAgICAgJ21lc3NhZ2UnIGluIGVycm9yICYmXG4gICAgICB0eXBlb2YgKGVycm9yIGFzIHsgbWVzc2FnZTogdW5rbm93biB9KS5tZXNzYWdlID09PSAnc3RyaW5nJ1xuICAgICkge1xuICAgICAgcmV0dXJuIChlcnJvciBhcyB7IG1lc3NhZ2U6IHN0cmluZyB9KS5tZXNzYWdlO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgICdlcnJvcicgaW4gZXJyb3IgJiZcbiAgICAgIHR5cGVvZiAoZXJyb3IgYXMgeyBlcnJvcjogdW5rbm93biB9KS5lcnJvciA9PT0gJ3N0cmluZydcbiAgICApIHtcbiAgICAgIHJldHVybiAoZXJyb3IgYXMgeyBlcnJvcjogc3RyaW5nIH0pLmVycm9yO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgICdkZXRhaWxzJyBpbiBlcnJvciAmJlxuICAgICAgdHlwZW9mIChlcnJvciBhcyB7IGRldGFpbHM6IHVua25vd24gfSkuZGV0YWlscyA9PT0gJ3N0cmluZydcbiAgICApIHtcbiAgICAgIHJldHVybiAoZXJyb3IgYXMgeyBkZXRhaWxzOiBzdHJpbmcgfSkuZGV0YWlscztcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICAnZGVzY3JpcHRpb24nIGluIGVycm9yICYmXG4gICAgICB0eXBlb2YgKGVycm9yIGFzIHsgZGVzY3JpcHRpb246IHVua25vd24gfSkuZGVzY3JpcHRpb24gPT09ICdzdHJpbmcnXG4gICAgKSB7XG4gICAgICByZXR1cm4gKGVycm9yIGFzIHsgZGVzY3JpcHRpb246IHN0cmluZyB9KS5kZXNjcmlwdGlvbjtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3RyaW5nKGVycm9yKTtcbn1cblxuLyoqXG4gKiBVdGlsaXR5IGZ1bmN0aW9uIHRvIGNyZWF0ZSBlcnJvciBjb250ZXh0IG9iamVjdHMgd2l0aCBwcm9wZXIgZmlsdGVyaW5nLlxuICogVGhpcyBlbnN1cmVzIGNvbnNpc3RlbnQgY29udGV4dCBzdHJ1Y3R1cmUgd2hpbGUgcmVtb3ZpbmcgdW5kZWZpbmVkIHZhbHVlc1xuICogdGhhdCBjb3VsZCBjbHV0dGVyIGxvZ3Mgb3IgY2F1c2Ugc2VyaWFsaXphdGlvbiBpc3N1ZXMuXG4gKlxuICogQHBhcmFtIGNvbnRleHQgLSBSYXcgY29udGV4dCBvYmplY3QgdGhhdCBtYXkgY29udGFpbiB1bmRlZmluZWQgdmFsdWVzXG4gKiBAcmV0dXJucyBGaWx0ZXJlZCBjb250ZXh0IG9iamVjdCB3aXRoIHVuZGVmaW5lZCB2YWx1ZXMgcmVtb3ZlZFxuICogQGV4YW1wbGVcbiAqIGNvbnN0IGNvbnRleHQgPSBjcmVhdGVFcnJvckNvbnRleHQoe1xuICogICB1c2VySWQ6IHVzZXI/LmlkLCAgICAgICAgLy8gbWlnaHQgYmUgdW5kZWZpbmVkXG4gKiAgIG9wZXJhdGlvbjogJ2RlbGV0ZVVzZXInLCAvLyBhbHdheXMgZGVmaW5lZFxuICogICByZXF1ZXN0SWQ6IHJlcS5pZCAgICAgICAgLy8gYWx3YXlzIGRlZmluZWRcbiAqIH0pO1xuICogLy8gUmVzdWx0OiB7IG9wZXJhdGlvbjogJ2RlbGV0ZVVzZXInLCByZXF1ZXN0SWQ6ICdhYmMxMjMnIH1cbiAqIC8vICh1c2VySWQgb21pdHRlZCBiZWNhdXNlIGl0IHdhcyB1bmRlZmluZWQpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFcnJvckNvbnRleHQoXG4gIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgIE9iamVjdC5lbnRyaWVzKGNvbnRleHQpLmZpbHRlcigoWywgdmFsdWVdKSA9PiB2YWx1ZSAhPT0gdW5kZWZpbmVkKSxcbiAgKTtcbn1cbiJdfQ==