UNPKG

@energica-city/shared-amplify-utils

Version:

Shared utilities for AWS Amplify projects

247 lines 43 kB
// @ts-nocheck import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; // Mock console methods const mockConsole = { log: vi.fn(), error: vi.fn(), info: vi.fn(), warn: vi.fn(), debug: vi.fn(), }; // Mock process.env const originalEnv = process.env; describe('Logger', () => { beforeEach(() => { vi.clearAllMocks(); vi.resetModules(); // Mock console global.console = mockConsole; // Reset environment process.env = { ...originalEnv }; }); afterEach(() => { vi.clearAllMocks(); vi.resetModules(); process.env = originalEnv; }); describe('LogLevel', () => { it('should have correct log level values', async () => { const { LogLevel } = await import('./index'); expect(LogLevel.NONE).toBe(0); expect(LogLevel.ERROR).toBe(1); expect(LogLevel.WARN).toBe(2); expect(LogLevel.INFO).toBe(3); expect(LogLevel.DEBUG).toBe(4); }); }); describe('Logger Instance', () => { it('should return singleton instance', async () => { const { logger } = await import('./index'); const { logger: logger2 } = await import('./index'); expect(logger).toBe(logger2); }); it('should have default log level of INFO', async () => { const { logger } = await import('./index'); expect(logger.getLevel()).toBe(3); // INFO expect(logger.getLevelName()).toBe('INFO'); }); }); describe('Environment Detection', () => { it('should detect development environment by default', async () => { const { logger } = await import('./index'); expect(logger.getEnvironment()).toBe('development'); }); it('should detect production environment from NODE_ENV', async () => { process.env.NODE_ENV = 'production'; const { logger } = await import('./index'); expect(logger.getEnvironment()).toBe('production'); }); it('should detect AWS Lambda environment', async () => { process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_nodejs22.x'; const { logger } = await import('./index'); expect(logger.getEnvironment()).toBe('aws-lambda'); }); it('should detect production from AWS function name', async () => { process.env.AWS_LAMBDA_FUNCTION_NAME = 'myapp-main-userFunction'; const { logger } = await import('./index'); expect(logger.getEnvironment()).toBe('production'); }); }); describe('Log Level Management', () => { it('should set and get log level', async () => { const { logger, LogLevel } = await import('./index'); logger.setLevel(LogLevel.DEBUG); expect(logger.getLevel()).toBe(LogLevel.DEBUG); expect(logger.getLevelName()).toBe('DEBUG'); }); it('should not log messages below current level', async () => { const { logger, LogLevel } = await import('./index'); logger.setLevel(LogLevel.WARN); logger.debug('This should not be logged'); expect(mockConsole.debug).not.toHaveBeenCalled(); }); }); describe('Context Management', () => { it('should set and get context', async () => { const { logger } = await import('./index'); const context = { userId: '123', operation: 'create' }; logger.setContext(context); expect(logger.getContext()).toEqual(context); }); it('should merge context', async () => { const { logger } = await import('./index'); logger.setContext({ userId: '123' }); logger.setContext({ operation: 'create' }); expect(logger.getContext()).toEqual({ userId: '123', operation: 'create', }); }); it('should clear context', async () => { const { logger } = await import('./index'); logger.setContext({ userId: '123' }); logger.clearContext(); expect(logger.getContext()).toEqual({}); }); }); describe('Structured Logging', () => { it('should enable structured logging in production', async () => { process.env.NODE_ENV = 'production'; const { logger } = await import('./index'); expect(logger.isStructuredLoggingEnabled()).toBe(true); }); it('should enable structured logging in AWS Lambda', async () => { process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_nodejs22.x'; const { logger } = await import('./index'); expect(logger.isStructuredLoggingEnabled()).toBe(true); }); it('should respect STRUCTURED_LOGGING environment variable', async () => { process.env.STRUCTURED_LOGGING = 'true'; const { logger } = await import('./index'); expect(logger.isStructuredLoggingEnabled()).toBe(true); }); it('should disable structured logging when explicitly set to false', async () => { process.env.STRUCTURED_LOGGING = 'false'; const { logger } = await import('./index'); expect(logger.isStructuredLoggingEnabled()).toBe(false); }); }); describe('Logging Methods', () => { it('should log error messages', async () => { const { logger } = await import('./index'); logger.error('Test error message'); expect(mockConsole.error).toHaveBeenCalledWith(expect.stringContaining('[ERROR] Test error message')); }); it('should log warning messages', async () => { const { logger } = await import('./index'); logger.warn('Test warning message'); expect(mockConsole.warn).toHaveBeenCalledWith(expect.stringContaining('[WARN] Test warning message')); }); it('should log info messages', async () => { const { logger } = await import('./index'); logger.info('Test info message'); expect(mockConsole.info).toHaveBeenCalledWith(expect.stringContaining('[INFO] Test info message')); }); it('should log debug messages', async () => { const { logger, LogLevel } = await import('./index'); logger.setLevel(LogLevel.DEBUG); logger.debug('Test debug message'); expect(mockConsole.debug).toHaveBeenCalledWith(expect.stringContaining('[DEBUG] Test debug message')); }); it('should log with context', async () => { const { logger } = await import('./index'); logger.setContext({ userId: '123' }); logger.info('User action'); expect(mockConsole.info).toHaveBeenCalledWith(expect.stringContaining('{"userId":"123"}')); }); it('should log multiple arguments', async () => { const { logger } = await import('./index'); logger.info('User created', { id: '123', name: 'John' }); expect(mockConsole.info).toHaveBeenCalledWith(expect.stringContaining('User created')); }); }); describe('Structured Logging Output', () => { it('should output JSON in structured mode', async () => { process.env.STRUCTURED_LOGGING = 'true'; const { logger } = await import('./index'); logger.info('Test message', { data: 'value' }); expect(mockConsole.info).toHaveBeenCalledWith(expect.stringMatching(/^\{.*"level":"INFO".*"message":"Test message".*"data":"value".*\}$/)); }); it('should include AWS context in structured logs', async () => { process.env.STRUCTURED_LOGGING = 'true'; process.env.AWS_REQUEST_ID = 'req-123'; process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-function'; process.env._X_AMZN_TRACE_ID = 'trace-456'; const { logger } = await import('./index'); logger.info('Test message'); const logCall = mockConsole.info.mock.calls[0][0]; const logData = JSON.parse(logCall); expect(logData.awsRequestId).toBe('req-123'); expect(logData.functionName).toBe('test-function'); expect(logData.xrayTraceId).toBe('trace-456'); }); it('should include environment in structured logs', async () => { process.env.STRUCTURED_LOGGING = 'true'; process.env.NODE_ENV = 'production'; const { logger } = await import('./index'); logger.info('Test message'); const logCall = mockConsole.info.mock.calls[0][0]; const logData = JSON.parse(logCall); expect(logData.environment).toBe('production'); }); }); describe('Error Handling', () => { it('should handle circular references in objects', async () => { const { logger } = await import('./index'); const circularObj = { name: 'test' }; circularObj.self = circularObj; logger.info('Circular object', circularObj); expect(mockConsole.info).toHaveBeenCalledWith(expect.stringContaining('[INFO] Circular object')); }); it('should handle undefined and null values', async () => { const { logger } = await import('./index'); logger.info('Test', undefined, null); expect(mockConsole.info).toHaveBeenCalledWith(expect.stringContaining('[INFO] Test')); }); }); describe('Direct Log Method', () => { it('should log directly without level checking', async () => { const { logger, LogLevel } = await import('./index'); logger.setLevel(LogLevel.ERROR); // Only errors should be logged logger.log('Direct message'); // This should still work expect(mockConsole.log).toHaveBeenCalledWith('Direct message'); }); it('should stringify objects in direct log', async () => { const { logger } = await import('./index'); const obj = { name: 'test', value: 123 }; logger.log('Object:', obj); expect(mockConsole.log).toHaveBeenCalledWith('Object:', '{"name":"test","value":123}'); }); }); describe('Integration Tests', () => { it('should work with typical QueryFactory logging pattern', async () => { const { logger } = await import('./index'); logger.setContext({ userId: '123', operation: 'create' }); logger.info('Creating User', { data: { name: 'John' } }); logger.info('User created successfully'); expect(mockConsole.info).toHaveBeenCalledTimes(2); expect(mockConsole.info).toHaveBeenCalledWith(expect.stringContaining('Creating User')); expect(mockConsole.info).toHaveBeenCalledWith(expect.stringContaining('User created successfully')); }); it('should handle AWS Lambda context properly', async () => { process.env.AWS_REQUEST_ID = 'req-123'; process.env.AWS_LAMBDA_FUNCTION_NAME = 'user-function'; process.env.STRUCTURED_LOGGING = 'true'; const { logger } = await import('./index'); logger.setContext({ userId: '123' }); logger.info('Function started'); const logCall = mockConsole.info.mock.calls[0][0]; const logData = JSON.parse(logCall); expect(logData.awsRequestId).toBe('req-123'); expect(logData.functionName).toBe('user-function'); expect(logData.context.userId).toBe('123'); expect(logData.message).toBe('Function started'); }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXgudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL2xvZy9pbmRleC50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWM7QUFDZCxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFekUsdUJBQXVCO0FBQ3ZCLE1BQU0sV0FBVyxHQUFHO0lBQ2xCLEdBQUcsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ1osS0FBSyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDZCxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNiLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ2IsS0FBSyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Q0FDZixDQUFDO0FBRUYsbUJBQW1CO0FBQ25CLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUM7QUFFaEMsUUFBUSxDQUFDLFFBQVEsRUFBRSxHQUFHLEVBQUU7SUFDdEIsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUNkLEVBQUUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNuQixFQUFFLENBQUMsWUFBWSxFQUFFLENBQUM7UUFFbEIsZUFBZTtRQUNmLE1BQU0sQ0FBQyxPQUFPLEdBQUcsV0FBVyxDQUFDO1FBRTdCLG9CQUFvQjtRQUNwQixPQUFPLENBQUMsR0FBRyxHQUFHLEVBQUUsR0FBRyxXQUFXLEVBQUUsQ0FBQztJQUNuQyxDQUFDLENBQUMsQ0FBQztJQUVILFNBQVMsQ0FBQyxHQUFHLEVBQUU7UUFDYixFQUFFLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDbkIsRUFBRSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ2xCLE9BQU8sQ0FBQyxHQUFHLEdBQUcsV0FBVyxDQUFDO0lBQzVCLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLFVB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QyxNQUFNLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUNuRCxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUNuRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtbm9jaGVja1xuaW1wb3J0IHsgZGVzY3JpYmUsIGl0LCBleHBlY3QsIGJlZm9yZUVhY2gsIGFmdGVyRWFjaCwgdmkgfSBmcm9tICd2aXRlc3QnO1xuXG4vLyBNb2NrIGNvbnNvbGUgbWV0aG9kc1xuY29uc3QgbW9ja0NvbnNvbGUgPSB7XG4gIGxvZzogdmkuZm4oKSxcbiAgZXJyb3I6IHZpLmZuKCksXG4gIGluZm86IHZpLmZuKCksXG4gIHdhcm46IHZpLmZuKCksXG4gIGRlYnVnOiB2aS5mbigpLFxufTtcblxuLy8gTW9jayBwcm9jZXNzLmVudlxuY29uc3Qgb3JpZ2luYWxFbnYgPSBwcm9jZXNzLmVudjtcblxuZGVzY3JpYmUoJ0xvZ2dlcicsICgpID0+IHtcbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgdmkuY2xlYXJBbGxNb2NrcygpO1xuICAgIHZpLnJlc2V0TW9kdWxlcygpO1xuXG4gICAgLy8gTW9jayBjb25zb2xlXG4gICAgZ2xvYmFsLmNvbnNvbGUgPSBtb2NrQ29uc29sZTtcblxuICAgIC8vIFJlc2V0IGVudmlyb25tZW50XG4gICAgcHJvY2Vzcy5lbnYgPSB7IC4uLm9yaWdpbmFsRW52IH07XG4gIH0pO1xuXG4gIGFmdGVyRWFjaCgoKSA9PiB7XG4gICAgdmkuY2xlYXJBbGxNb2NrcygpO1xuICAgIHZpLnJlc2V0TW9kdWxlcygpO1xuICAgIHByb2Nlc3MuZW52ID0gb3JpZ2luYWxFbnY7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdMb2dMZXZlbCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGhhdmUgY29ycmVjdCBsb2cgbGV2ZWwgdmFsdWVzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgeyBMb2dMZXZlbCB9ID0gYXdhaXQgaW1wb3J0KCcuL2luZGV4Jyk7XG5cbiAgICAgIGV4cGVjdChMb2dMZXZlbC5OT05FKS50b0JlKDApO1xuICAgICAgZXhwZWN0KExvZ0xldmVsLkVSUk9SKS50b0JlKDEpO1xuICAgICAgZXhwZWN0KExvZ0xldmVsLldBUk4pLnRvQmUoMik7XG4gICAgICBleHBlY3QoTG9nTGV2ZWwuSU5GTykudG9CZSgzKTtcbiAgICAgIGV4cGVjdChMb2dMZXZlbC5ERUJVRykudG9CZSg0KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0xvZ2dlciBJbnN0YW5jZScsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBzaW5nbGV0b24gaW5zdGFuY2UnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB7IGxvZ2dlciB9ID0gYXdhaXQgaW1wb3J0KCcuL2luZGV4Jyk7XG4gICAgICBjb25zdCB7IGxvZ2dlcjogbG9nZ2VyMiB9ID0gYXdhaXQgaW1wb3J0KCcuL2luZGV4Jyk7XG5cbiAgICAgIGV4cGVjdChsb2dnZXIpLnRvQmUobG9nZ2VyMik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhdmUgZGVmYXVsdCBsb2cgbGV2ZWwgb2YgSU5GTycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgZXhwZWN0KGxvZ2dlci5nZXRMZXZlbCgpKS50b0JlKDMpOyAvLyBJTkZPXG4gICAgICBleHBlY3QobG9nZ2VyLmdldExldmVsTmFtZSgpKS50b0JlKCdJTkZPJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFbnZpcm9ubWVudCBEZXRlY3Rpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBkZXRlY3QgZGV2ZWxvcG1lbnQgZW52aXJvbm1lbnQgYnkgZGVmYXVsdCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgZXhwZWN0KGxvZ2dlci5nZXRFbnZpcm9ubWVudCgpKS50b0JlKCdkZXZlbG9wbWVudCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBkZXRlY3QgcHJvZHVjdGlvbiBlbnZpcm9ubWVudCBmcm9tIE5PREVfRU5WJywgYXN5bmMgKCkgPT4ge1xuICAgICAgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPSAncHJvZHVjdGlvbic7XG4gICAgICBjb25zdCB7IGxvZ2dlciB9ID0gYXdhaXQgaW1wb3J0KCcuL2luZGV4Jyk7XG5cbiAgICAgIGV4cGVjdChsb2dnZXIuZ2V0RW52aXJvbm1lbnQoKSkudG9CZSgncHJvZHVjdGlvbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBkZXRlY3QgQVdTIExhbWJkYSBlbnZpcm9ubWVudCcsIGFzeW5jICgpID0+IHtcbiAgICAgIHByb2Nlc3MuZW52LkFXU19FWEVDVVRJT05fRU5WID0gJ0FXU19MYW1iZGFfbm9kZWpzMjIueCc7XG4gICAgICBjb25zdCB7IGxvZ2dlciB9ID0gYXdhaXQgaW1wb3J0KCcuL2luZGV4Jyk7XG5cbiAgICAgIGV4cGVjdChsb2dnZXIuZ2V0RW52aXJvbm1lbnQoKSkudG9CZSgnYXdzLWxhbWJkYScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBkZXRlY3QgcHJvZHVjdGlvbiBmcm9tIEFXUyBmdW5jdGlvbiBuYW1lJywgYXN5bmMgKCkgPT4ge1xuICAgICAgcHJvY2Vzcy5lbnYuQVdTX0xBTUJEQV9GVU5DVElPTl9OQU1FID0gJ215YXBwLW1haW4tdXNlckZ1bmN0aW9uJztcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgZXhwZWN0KGxvZ2dlci5nZXRFbnZpcm9ubWVudCgpKS50b0JlKCdwcm9kdWN0aW9uJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdMb2cgTGV2ZWwgTWFuYWdlbWVudCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHNldCBhbmQgZ2V0IGxvZyBsZXZlbCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgbG9nZ2VyLCBMb2dMZXZlbCB9ID0gYXdhaXQgaW1wb3J0KCcuL2luZGV4Jyk7XG5cbiAgICAgIGxvZ2dlci5zZXRMZXZlbChMb2dMZXZlbC5ERUJVRyk7XG4gICAgICBleHBlY3QobG9nZ2VyLmdldExldmVsKCkpLnRvQmUoTG9nTGV2ZWwuREVCVUcpO1xuICAgICAgZXhwZWN0KGxvZ2dlci5nZXRMZXZlbE5hbWUoKSkudG9CZSgnREVCVUcnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IGxvZyBtZXNzYWdlcyBiZWxvdyBjdXJyZW50IGxldmVsJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgeyBsb2dnZXIsIExvZ0xldmVsIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLnNldExldmVsKExvZ0xldmVsLldBUk4pO1xuICAgICAgbG9nZ2VyLmRlYnVnKCdUaGlzIHNob3VsZCBub3QgYmUgbG9nZ2VkJyk7XG5cbiAgICAgIGV4cGVjdChtb2NrQ29uc29sZS5kZWJ1Zykubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0NvbnRleHQgTWFuYWdlbWVudCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHNldCBhbmQgZ2V0IGNvbnRleHQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB7IGxvZ2dlciB9ID0gYXdhaXQgaW1wb3J0KCcuL2luZGV4Jyk7XG5cbiAgICAgIGNvbnN0IGNvbnRleHQgPSB7IHVzZXJJZDogJzEyMycsIG9wZXJhdGlvbjogJ2NyZWF0ZScgfTtcbiAgICAgIGxvZ2dlci5zZXRDb250ZXh0KGNvbnRleHQpO1xuXG4gICAgICBleHBlY3QobG9nZ2VyLmdldENvbnRleHQoKSkudG9FcXVhbChjb250ZXh0KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbWVyZ2UgY29udGV4dCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLnNldENvbnRleHQoeyB1c2VySWQ6ICcxMjMnIH0pO1xuICAgICAgbG9nZ2VyLnNldENvbnRleHQoeyBvcGVyYXRpb246ICdjcmVhdGUnIH0pO1xuXG4gICAgICBleHBlY3QobG9nZ2VyLmdldENvbnRleHQoKSkudG9FcXVhbCh7XG4gICAgICAgIHVzZXJJZDogJzEyMycsXG4gICAgICAgIG9wZXJhdGlvbjogJ2NyZWF0ZScsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2xlYXIgY29udGV4dCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLnNldENvbnRleHQoeyB1c2VySWQ6ICcxMjMnIH0pO1xuICAgICAgbG9nZ2VyLmNsZWFyQ29udGV4dCgpO1xuXG4gICAgICBleHBlY3QobG9nZ2VyLmdldENvbnRleHQoKSkudG9FcXVhbCh7fSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdTdHJ1Y3R1cmVkIExvZ2dpbmcnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBlbmFibGUgc3RydWN0dXJlZCBsb2dnaW5nIGluIHByb2R1Y3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBwcm9jZXNzLmVudi5OT0RFX0VOViA9ICdwcm9kdWN0aW9uJztcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgZXhwZWN0KGxvZ2dlci5pc1N0cnVjdHVyZWRMb2dnaW5nRW5hYmxlZCgpKS50b0JlKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBlbmFibGUgc3RydWN0dXJlZCBsb2dnaW5nIGluIEFXUyBMYW1iZGEnLCBhc3luYyAoKSA9PiB7XG4gICAgICBwcm9jZXNzLmVudi5BV1NfRVhFQ1VUSU9OX0VOViA9ICdBV1NfTGFtYmRhX25vZGVqczIyLngnO1xuICAgICAgY29uc3QgeyBsb2dnZXIgfSA9IGF3YWl0IGltcG9ydCgnLi9pbmRleCcpO1xuXG4gICAgICBleHBlY3QobG9nZ2VyLmlzU3RydWN0dXJlZExvZ2dpbmdFbmFibGVkKCkpLnRvQmUodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlc3BlY3QgU1RSVUNUVVJFRF9MT0dHSU5HIGVudmlyb25tZW50IHZhcmlhYmxlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgcHJvY2Vzcy5lbnYuU1RSVUNUVVJFRF9MT0dHSU5HID0gJ3RydWUnO1xuICAgICAgY29uc3QgeyBsb2dnZXIgfSA9IGF3YWl0IGltcG9ydCgnLi9pbmRleCcpO1xuXG4gICAgICBleHBlY3QobG9nZ2VyLmlzU3RydWN0dXJlZExvZ2dpbmdFbmFibGVkKCkpLnRvQmUodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGRpc2FibGUgc3RydWN0dXJlZCBsb2dnaW5nIHdoZW4gZXhwbGljaXRseSBzZXQgdG8gZmFsc2UnLCBhc3luYyAoKSA9PiB7XG4gICAgICBwcm9jZXNzLmVudi5TVFJVQ1RVUkVEX0xPR0dJTkcgPSAnZmFsc2UnO1xuICAgICAgY29uc3QgeyBsb2dnZXIgfSA9IGF3YWl0IGltcG9ydCgnLi9pbmRleCcpO1xuXG4gICAgICBleHBlY3QobG9nZ2VyLmlzU3RydWN0dXJlZExvZ2dpbmdFbmFibGVkKCkpLnRvQmUoZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnTG9nZ2luZyBNZXRob2RzJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgbG9nIGVycm9yIG1lc3NhZ2VzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgeyBsb2dnZXIgfSA9IGF3YWl0IGltcG9ydCgnLi9pbmRleCcpO1xuXG4gICAgICBsb2dnZXIuZXJyb3IoJ1Rlc3QgZXJyb3IgbWVzc2FnZScpO1xuXG4gICAgICBleHBlY3QobW9ja0NvbnNvbGUuZXJyb3IpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBleHBlY3Quc3RyaW5nQ29udGFpbmluZygnW0VSUk9SXSBUZXN0IGVycm9yIG1lc3NhZ2UnKSxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGxvZyB3YXJuaW5nIG1lc3NhZ2VzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgeyBsb2dnZXIgfSA9IGF3YWl0IGltcG9ydCgnLi9pbmRleCcpO1xuXG4gICAgICBsb2dnZXIud2FybignVGVzdCB3YXJuaW5nIG1lc3NhZ2UnKTtcblxuICAgICAgZXhwZWN0KG1vY2tDb25zb2xlLndhcm4pLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBleHBlY3Quc3RyaW5nQ29udGFpbmluZygnW1dBUk5dIFRlc3Qgd2FybmluZyBtZXNzYWdlJyksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBsb2cgaW5mbyBtZXNzYWdlcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLmluZm8oJ1Rlc3QgaW5mbyBtZXNzYWdlJyk7XG5cbiAgICAgIGV4cGVjdChtb2NrQ29uc29sZS5pbmZvKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcbiAgICAgICAgZXhwZWN0LnN0cmluZ0NvbnRhaW5pbmcoJ1tJTkZPXSBUZXN0IGluZm8gbWVzc2FnZScpLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbG9nIGRlYnVnIG1lc3NhZ2VzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgeyBsb2dnZXIsIExvZ0xldmVsIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLnNldExldmVsKExvZ0xldmVsLkRFQlVHKTtcbiAgICAgIGxvZ2dlci5kZWJ1ZygnVGVzdCBkZWJ1ZyBtZXNzYWdlJyk7XG5cbiAgICAgIGV4cGVjdChtb2NrQ29uc29sZS5kZWJ1ZykudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgIGV4cGVjdC5zdHJpbmdDb250YWluaW5nKCdbREVCVUddIFRlc3QgZGVidWcgbWVzc2FnZScpLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbG9nIHdpdGggY29udGV4dCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLnNldENvbnRleHQoeyB1c2VySWQ6ICcxMjMnIH0pO1xuICAgICAgbG9nZ2VyLmluZm8oJ1VzZXIgYWN0aW9uJyk7XG5cbiAgICAgIGV4cGVjdChtb2NrQ29uc29sZS5pbmZvKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcbiAgICAgICAgZXhwZWN0LnN0cmluZ0NvbnRhaW5pbmcoJ3tcInVzZXJJZFwiOlwiMTIzXCJ9JyksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBsb2cgbXVsdGlwbGUgYXJndW1lbnRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgeyBsb2dnZXIgfSA9IGF3YWl0IGltcG9ydCgnLi9pbmRleCcpO1xuXG4gICAgICBsb2dnZXIuaW5mbygnVXNlciBjcmVhdGVkJywgeyBpZDogJzEyMycsIG5hbWU6ICdKb2huJyB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tDb25zb2xlLmluZm8pLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBleHBlY3Quc3RyaW5nQ29udGFpbmluZygnVXNlciBjcmVhdGVkJyksXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU3RydWN0dXJlZCBMb2dnaW5nIE91dHB1dCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIG91dHB1dCBKU09OIGluIHN0cnVjdHVyZWQgbW9kZScsIGFzeW5jICgpID0+IHtcbiAgICAgIHByb2Nlc3MuZW52LlNUUlVDVFVSRURfTE9HR0lORyA9ICd0cnVlJztcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLmluZm8oJ1Rlc3QgbWVzc2FnZScsIHsgZGF0YTogJ3ZhbHVlJyB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tDb25zb2xlLmluZm8pLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBleHBlY3Quc3RyaW5nTWF0Y2hpbmcoXG4gICAgICAgICAgL15cXHsuKlwibGV2ZWxcIjpcIklORk9cIi4qXCJtZXNzYWdlXCI6XCJUZXN0IG1lc3NhZ2VcIi4qXCJkYXRhXCI6XCJ2YWx1ZVwiLipcXH0kLyxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGluY2x1ZGUgQVdTIGNvbnRleHQgaW4gc3RydWN0dXJlZCBsb2dzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgcHJvY2Vzcy5lbnYuU1RSVUNUVVJFRF9MT0dHSU5HID0gJ3RydWUnO1xuICAgICAgcHJvY2Vzcy5lbnYuQVdTX1JFUVVFU1RfSUQgPSAncmVxLTEyMyc7XG4gICAgICBwcm9jZXNzLmVudi5BV1NfTEFNQkRBX0ZVTkNUSU9OX05BTUUgPSAndGVzdC1mdW5jdGlvbic7XG4gICAgICBwcm9jZXNzLmVudi5fWF9BTVpOX1RSQUNFX0lEID0gJ3RyYWNlLTQ1Nic7XG5cbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLmluZm8oJ1Rlc3QgbWVzc2FnZScpO1xuXG4gICAgICBjb25zdCBsb2dDYWxsID0gbW9ja0NvbnNvbGUuaW5mby5tb2NrLmNhbGxzWzBdWzBdO1xuICAgICAgY29uc3QgbG9nRGF0YSA9IEpTT04ucGFyc2UobG9nQ2FsbCk7XG5cbiAgICAgIGV4cGVjdChsb2dEYXRhLmF3c1JlcXVlc3RJZCkudG9CZSgncmVxLTEyMycpO1xuICAgICAgZXhwZWN0KGxvZ0RhdGEuZnVuY3Rpb25OYW1lKS50b0JlKCd0ZXN0LWZ1bmN0aW9uJyk7XG4gICAgICBleHBlY3QobG9nRGF0YS54cmF5VHJhY2VJZCkudG9CZSgndHJhY2UtNDU2Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGluY2x1ZGUgZW52aXJvbm1lbnQgaW4gc3RydWN0dXJlZCBsb2dzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgcHJvY2Vzcy5lbnYuU1RSVUNUVVJFRF9MT0dHSU5HID0gJ3RydWUnO1xuICAgICAgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPSAncHJvZHVjdGlvbic7XG5cbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLmluZm8oJ1Rlc3QgbWVzc2FnZScpO1xuXG4gICAgICBjb25zdCBsb2dDYWxsID0gbW9ja0NvbnNvbGUuaW5mby5tb2NrLmNhbGxzWzBdWzBdO1xuICAgICAgY29uc3QgbG9nRGF0YSA9IEpTT04ucGFyc2UobG9nQ2FsbCk7XG5cbiAgICAgIGV4cGVjdChsb2dEYXRhLmVudmlyb25tZW50KS50b0JlKCdwcm9kdWN0aW9uJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFcnJvciBIYW5kbGluZycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBjaXJjdWxhciByZWZlcmVuY2VzIGluIG9iamVjdHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB7IGxvZ2dlciB9ID0gYXdhaXQgaW1wb3J0KCcuL2luZGV4Jyk7XG5cbiAgICAgIGNvbnN0IGNpcmN1bGFyT2JqOiBhbnkgPSB7IG5hbWU6ICd0ZXN0JyB9O1xuICAgICAgY2lyY3VsYXJPYmouc2VsZiA9IGNpcmN1bGFyT2JqO1xuXG4gICAgICBsb2dnZXIuaW5mbygnQ2lyY3VsYXIgb2JqZWN0JywgY2lyY3VsYXJPYmopO1xuXG4gICAgICBleHBlY3QobW9ja0NvbnNvbGUuaW5mbykudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgIGV4cGVjdC5zdHJpbmdDb250YWluaW5nKCdbSU5GT10gQ2lyY3VsYXIgb2JqZWN0JyksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgdW5kZWZpbmVkIGFuZCBudWxsIHZhbHVlcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLmluZm8oJ1Rlc3QnLCB1bmRlZmluZWQsIG51bGwpO1xuXG4gICAgICBleHBlY3QobW9ja0NvbnNvbGUuaW5mbykudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgIGV4cGVjdC5zdHJpbmdDb250YWluaW5nKCdbSU5GT10gVGVzdCcpLFxuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0RpcmVjdCBMb2cgTWV0aG9kJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgbG9nIGRpcmVjdGx5IHdpdGhvdXQgbGV2ZWwgY2hlY2tpbmcnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB7IGxvZ2dlciwgTG9nTGV2ZWwgfSA9IGF3YWl0IGltcG9ydCgnLi9pbmRleCcpO1xuXG4gICAgICBsb2dnZXIuc2V0TGV2ZWwoTG9nTGV2ZWwuRVJST1IpOyAvLyBPbmx5IGVycm9ycyBzaG91bGQgYmUgbG9nZ2VkXG4gICAgICBsb2dnZXIubG9nKCdEaXJlY3QgbWVzc2FnZScpOyAvLyBUaGlzIHNob3VsZCBzdGlsbCB3b3JrXG5cbiAgICAgIGV4cGVjdChtb2NrQ29uc29sZS5sb2cpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCdEaXJlY3QgbWVzc2FnZScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzdHJpbmdpZnkgb2JqZWN0cyBpbiBkaXJlY3QgbG9nJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgeyBsb2dnZXIgfSA9IGF3YWl0IGltcG9ydCgnLi9pbmRleCcpO1xuXG4gICAgICBjb25zdCBvYmogPSB7IG5hbWU6ICd0ZXN0JywgdmFsdWU6IDEyMyB9O1xuICAgICAgbG9nZ2VyLmxvZygnT2JqZWN0OicsIG9iaik7XG5cbiAgICAgIGV4cGVjdChtb2NrQ29uc29sZS5sb2cpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICAnT2JqZWN0OicsXG4gICAgICAgICd7XCJuYW1lXCI6XCJ0ZXN0XCIsXCJ2YWx1ZVwiOjEyM30nLFxuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0ludGVncmF0aW9uIFRlc3RzJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgd29yayB3aXRoIHR5cGljYWwgUXVlcnlGYWN0b3J5IGxvZ2dpbmcgcGF0dGVybicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoJy4vaW5kZXgnKTtcblxuICAgICAgbG9nZ2VyLnNldENvbnRleHQoeyB1c2VySWQ6ICcxMjMnLCBvcGVyYXRpb246ICdjcmVhdGUnIH0pO1xuICAgICAgbG9nZ2VyLmluZm8oJ0NyZWF0aW5nIFVzZXInLCB7IGRhdGE6IHsgbmFtZTogJ0pvaG4nIH0gfSk7XG4gICAgICBsb2dnZXIuaW5mbygnVXNlciBjcmVhdGVkIHN1Y2Nlc3NmdWxseScpO1xuXG4gICAgICBleHBlY3QobW9ja0NvbnNvbGUuaW5mbykudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDIpO1xuICAgICAgZXhwZWN0KG1vY2tDb25zb2xlLmluZm8pLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBleHBlY3Quc3RyaW5nQ29udGFpbmluZygnQ3JlYXRpbmcgVXNlcicpLFxuICAgICAgKTtcbiAgICAgIGV4cGVjdChtb2NrQ29uc29sZS5pbmZvKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcbiAgICAgICAgZXhwZWN0LnN0cmluZ0NvbnRhaW5pbmcoJ1VzZXIgY3JlYXRlZCBzdWNjZXNzZnVsbHknKSxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBBV1MgTGFtYmRhIGNvbnRleHQgcHJvcGVybHknLCBhc3luYyAoKSA9PiB7XG4gICAgICBwcm9jZXNzLmVudi5BV1NfUkVRVUVTVF9JRCA9ICdyZXEtMTIzJztcbiAgICAgIHByb2Nlc3MuZW52LkFXU19MQU1CREFfRlVOQ1RJT05fTkFNRSA9ICd1c2VyLWZ1bmN0aW9uJztcbiAgICAgIHByb2Nlc3MuZW52LlNUUlVDVFVSRURfTE9HR0lORyA9ICd0cnVlJztcblxuICAgICAgY29uc3QgeyBsb2dnZXIgfSA9IGF3YWl0IGltcG9ydCgnLi9pbmRleCcpO1xuXG4gICAgICBsb2dnZXIuc2V0Q29udGV4dCh7IHVzZXJJZDogJzEyMycgfSk7XG4gICAgICBsb2dnZXIuaW5mbygnRnVuY3Rpb24gc3RhcnRlZCcpO1xuXG4gICAgICBjb25zdCBsb2dDYWxsID0gbW9ja0NvbnNvbGUuaW5mby5tb2NrLmNhbGxzWzBdWzBdO1xuICAgICAgY29uc3QgbG9nRGF0YSA9IEpTT04ucGFyc2UobG9nQ2FsbCk7XG5cbiAgICAgIGV4cGVjdChsb2dEYXRhLmF3c1JlcXVlc3RJZCkudG9CZSgncmVxLTEyMycpO1xuICAgICAgZXhwZWN0KGxvZ0RhdGEuZnVuY3Rpb25OYW1lKS50b0JlKCd1c2VyLWZ1bmN0aW9uJyk7XG4gICAgICBleHBlY3QobG9nRGF0YS5jb250ZXh0LnVzZXJJZCkudG9CZSgnMTIzJyk7XG4gICAgICBleHBlY3QobG9nRGF0YS5tZXNzYWdlKS50b0JlKCdGdW5jdGlvbiBzdGFydGVkJyk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=