diff --git a/backend/src/.jest-cache/haste-map-60cab15b743c6776f41d29bcac696b99-0ca4a1d6e3dfec1d63b61b0119442391-1908b04cd11e739233ee8977de00dc57 b/backend/src/.jest-cache/haste-map-60cab15b743c6776f41d29bcac696b99-0ca4a1d6e3dfec1d63b61b0119442391-1908b04cd11e739233ee8977de00dc57 index ec1cc2d..cfda3f1 100644 Binary files a/backend/src/.jest-cache/haste-map-60cab15b743c6776f41d29bcac696b99-0ca4a1d6e3dfec1d63b61b0119442391-1908b04cd11e739233ee8977de00dc57 and b/backend/src/.jest-cache/haste-map-60cab15b743c6776f41d29bcac696b99-0ca4a1d6e3dfec1d63b61b0119442391-1908b04cd11e739233ee8977de00dc57 differ diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/09/correspondenceservicespec_09d46a7193361a4ca1873205694e5f3c b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/09/correspondenceservicespec_09d46a7193361a4ca1873205694e5f3c new file mode 100644 index 0000000..c1beb8e --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/09/correspondenceservicespec_09d46a7193361a4ca1873205694e5f3c @@ -0,0 +1,612 @@ +06552354a957108ee83cb3dbcabadd19 +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const testing_1 = require("@nestjs/testing"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +const common_1 = require("@nestjs/common"); +const correspondence_service_1 = require("./correspondence.service"); +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +describe('CorrespondenceService', () => { + let service; + let numberingService; + let correspondenceRepo; + let revisionRepo; + let testingModule; + let _dataSource; + const createMockRepository = () => ({ + find: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + save: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + softDelete: jest.fn(), + createQueryBuilder: jest.fn(() => ({ + leftJoinAndSelect: jest.fn().mockReturnThis(), + where: jest.fn().mockReturnThis(), + andWhere: jest.fn().mockReturnThis(), + orderBy: jest.fn().mockReturnThis(), + skip: jest.fn().mockReturnThis(), + take: jest.fn().mockReturnThis(), + getOne: jest.fn().mockResolvedValue(null), + getMany: jest.fn().mockResolvedValue([]), + getManyAndCount: jest.fn().mockResolvedValue([[], 0]), + })), + }); + const mockDataSource = { + createQueryRunner: jest.fn(() => ({ + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn(), + save: jest.fn(), + findOne: jest.fn(), + }, + })), + getRepository: jest.fn(() => createMockRepository()), + manager: { + findOne: jest.fn(), + }, + }; + beforeEach(async () => { + testingModule = await testing_1.Test.createTestingModule({ + providers: [ + correspondence_service_1.CorrespondenceService, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_reference_entity_1.CorrespondenceReference), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_tag_entity_1.CorrespondenceTag), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(organization_entity_1.Organization), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_recipient_entity_1.CorrespondenceRecipient), + useValue: createMockRepository(), + }, + { + provide: document_numbering_service_1.DocumentNumberingService, + useValue: { + generateNextNumber: jest.fn(), + updateNumberForDraft: jest.fn(), + previewNextNumber: jest.fn(), + }, + }, + { + provide: json_schema_service_1.JsonSchemaService, + useValue: { validate: jest.fn() }, + }, + { + provide: workflow_engine_service_1.WorkflowEngineService, + useValue: { createInstance: jest.fn() }, + }, + { + provide: user_service_1.UserService, + useValue: { + findOne: jest.fn(), + getUserPermissions: jest.fn().mockResolvedValue([]), + }, + }, + { + provide: typeorm_2.DataSource, + useValue: mockDataSource, + }, + { + provide: search_service_1.SearchService, + useValue: { indexDocument: jest.fn() }, + }, + { + provide: file_storage_service_1.FileStorageService, + useValue: { commit: jest.fn().mockResolvedValue([]) }, + }, + { + provide: uuid_resolver_service_1.UuidResolverService, + useValue: { + resolveProjectId: jest.fn().mockResolvedValue(1), + resolveOrganizationId: jest.fn().mockResolvedValue(1), + }, + }, + { + provide: notification_service_1.NotificationService, + useValue: { send: jest.fn().mockResolvedValue(undefined) }, + }, + ], + }).compile(); + service = testingModule.get(correspondence_service_1.CorrespondenceService); + numberingService = testingModule.get(document_numbering_service_1.DocumentNumberingService); + correspondenceRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence)); + revisionRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision)); + _dataSource = testingModule.get(typeorm_2.DataSource); + }); + it('should be defined', () => { + expect(service).toBeDefined(); + }); + describe('update', () => { + it('should allow non-draft update for org-admin+ permissions', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 23, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + statusRepo.findOne.mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + const userService = testingModule.get(user_service_1.UserService); + userService.getUserPermissions.mockResolvedValue([ + 'correspondence.cancel', + ]); + await expect(service.update(1, { subject: 'Updated Subject' }, mockUser)).resolves.toBeDefined(); + }); + it('should reject non-draft update for non-admin permissions', async () => { + const mockUser = { + user_id: 2, + primaryOrganizationId: 10, + }; + const mockRevision = { + id: 101, + correspondenceId: 2, + isCurrent: true, + statusId: 23, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + statusRepo.findOne.mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + const userService = testingModule.get(user_service_1.UserService); + userService.getUserPermissions.mockResolvedValue([ + 'correspondence.edit', + ]); + await expect(service.update(2, { subject: 'Should Fail' }, mockUser)).rejects.toThrow(common_1.ForbiddenException); + }); + it('should NOT regenerate number if critical fields unchanged', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 1, + disciplineId: 3, + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).not.toHaveBeenCalled(); + }); + it('should regenerate number if Project ID changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 2, + }; + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(2); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Document Type changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + typeId: 999, + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + typeRepo.findOne.mockResolvedValue({ + id: 999, + typeCode: 'NEW-TYPE', + }); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Recipient Organization changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + // Access DataSource manager for mocking + mockDataSource.manager.findOne.mockResolvedValue({ + id: 88, + organizationCode: 'NEW-ORG', + }); + const updateDto = { + recipients: [{ type: 'TO', organizationId: 88 }], + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + }); + describe('create', () => { + it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: null, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + originatorId: 'originator-uuid', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const userService = testingModule.get(user_service_1.UserService); + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + userService.findOne.mockResolvedValue({ + user_id: 1, + primaryOrganizationId: null, + }); + userService.getUserPermissions.mockResolvedValue([ + 'system.manage_all', + ]); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockImplementation((value) => { + if (value === 'originator-uuid') + return 10; + if (value === 'recipient-uuid') + return 20; + return 0; + }); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LTR', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_entity_1.Correspondence, expect.objectContaining({ originatorId: 10 })); + }); + it('should set revisionLabel to "A" for RFA type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'RFA', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: 'A' })); + }); + it('should set revisionLabel to "A" for RFI type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'RFI', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: 'A' })); + }); + it('should set revisionLabel to null for LETTER type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LETTER', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: undefined })); + }); + it('should set revisionLabel to undefined for MEMO type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'MEMO', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: undefined })); + }); + }); +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyIsIm1hcHBpbmdzIjoiOztBQUFBLDZDQUFzRDtBQUN0RCw2Q0FBcUQ7QUFDckQscUNBQWlEO0FBQ2pELDJDQUFvRDtBQUNwRCxxRUFBaUU7QUFDakUsNEVBQWtFO0FBQ2xFLDhGQUFtRjtBQUNuRixzRkFBMkU7QUFDM0UsMEZBQStFO0FBQy9FLGdHQUFxRjtBQUNyRixvRkFBeUU7QUFDekUsc0ZBQTRFO0FBQzVFLGdHQUFxRjtBQUNyRiwwR0FBcUc7QUFDckcsNEVBQXVFO0FBQ3ZFLHdGQUFtRjtBQUNuRix1REFBbUQ7QUFDbkQsNkRBQXlEO0FBQ3pELHlGQUFvRjtBQUNwRix1RkFBa0Y7QUFDbEYsK0VBQTJFO0FBSzNFLFFBQVEsQ0FBQyx1QkFBdUIsRUFBRSxHQUFHLEVBQUU7SUFDckMsSUFBSSxPQUE4QixDQUFDO0lBQ25DLElBQUksZ0JBQTBDLENBQUM7SUFDL0MsSUFBSSxrQkFBOEMsQ0FBQztJQUNuRCxJQUFJLFlBQWdELENBQUM7SUFDckQsSUFBSSxhQUE0QixDQUFDO0lBQ2pDLElBQUksV0FBdUIsQ0FBQztJQUU1QixNQUFNLG9CQUFvQixHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDbEMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDZixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNsQixNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNqQixJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNmLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLFVBQVUsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ3JCLGtCQUFrQixFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENB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bmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUZXN0LCBUZXN0aW5nTW9kdWxlIH0gZnJvbSAnQG5lc3Rqcy90ZXN0aW5nJztcclxuaW1wb3J0IHsgZ2V0UmVwb3NpdG9yeVRva2VuIH0gZnJvbSAnQG5lc3Rqcy90eXBlb3JtJztcclxuaW1wb3J0IHsgRGF0YVNvdXJjZSwgUmVwb3NpdG9yeSB9IGZyb20gJ3R5cGVvcm0nO1xyXG5pbXBvcnQgeyBGb3JiaWRkZW5FeGNlcHRpb24gfSBmcm9tICdAbmVzdGpzL2NvbW1vbic7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlU2VydmljZSB9IGZyb20gJy4vY29ycmVzcG9uZGVuY2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJldmlzaW9uIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZXZpc2lvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVR5cGUgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXR5cGUuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VTdGF0dXMgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXN0YXR1cy5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlZmVyZW5jZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVmZXJlbmNlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVGFnIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS10YWcuZW50aXR5JztcclxuaW1wb3J0IHsgT3JnYW5pemF0aW9uIH0gZnJvbSAnLi4vb3JnYW5pemF0aW9uL2VudGl0aWVzL29yZ2FuaXphdGlvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlY2lwaWVudCB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVjaXBpZW50LmVudGl0eSc7XHJcbmltcG9ydCB7IERvY3VtZW50TnVtYmVyaW5nU2VydmljZSB9IGZyb20gJy4uL2RvY3VtZW50LW51bWJlcmluZy9zZXJ2aWNlcy9kb2N1bWVudC1udW1iZXJpbmcuc2VydmljZSc7XHJcbmltcG9ydCB7IEpzb25TY2hlbWFTZXJ2aWNlIH0gZnJvbSAnLi4vanNvbi1zY2hlbWEvanNvbi1zY2hlbWEuc2VydmljZSc7XHJcbmltcG9ydCB7IFdvcmtmbG93RW5naW5lU2VydmljZSB9IGZyb20gJy4uL3dvcmtmbG93LWVuZ2luZS93b3JrZmxvdy1lbmdpbmUuc2VydmljZSc7XHJcbmltcG9ydCB7IFVzZXJTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlci91c2VyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTZWFyY2hTZXJ2aWNlIH0gZnJvbSAnLi4vc2VhcmNoL3NlYXJjaC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRmlsZVN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL2ZpbGUtc3RvcmFnZS9maWxlLXN0b3JhZ2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IFV1aWRSZXNvbHZlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vc2VydmljZXMvdXVpZC1yZXNvbHZlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi9ub3RpZmljYXRpb24uc2VydmljZSc7XHJcbmltcG9ydCB7IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vdXBkYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vY3JlYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi91c2VyL2VudGl0aWVzL3VzZXIuZW50aXR5JztcclxuXHJcbmRlc2NyaWJlKCdDb3JyZXNwb25kZW5jZVNlcnZpY2UnLCAoKSA9PiB7XHJcbiAgbGV0IHNlcnZpY2U6IENvcnJlc3BvbmRlbmNlU2VydmljZTtcclxuICBsZXQgbnVtYmVyaW5nU2VydmljZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlO1xyXG4gIGxldCBjb3JyZXNwb25kZW5jZVJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2U+O1xyXG4gIGxldCByZXZpc2lvblJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VSZXZpc2lvbj47XHJcbiAgbGV0IHRlc3RpbmdNb2R1bGU6IFRlc3RpbmdNb2R1bGU7XHJcbiAgbGV0IF9kYXRhU291cmNlOiBEYXRhU291cmNlO1xyXG5cclxuICBjb25zdCBjcmVhdGVNb2NrUmVwb3NpdG9yeSA9ICgpID0+ICh7XHJcbiAgICBmaW5kOiBqZXN0LmZuKCksXHJcbiAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGU6IGplc3QuZm4oKSxcclxuICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgIHVwZGF0ZTogamVzdC5mbigpLFxyXG4gICAgZGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBzb2Z0RGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGVRdWVyeUJ1aWxkZXI6IGplc3QuZm4oKCkgPT4gKHtcclxuICAgICAgbGVmdEpvaW5BbmRTZWxlY3Q6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB3aGVyZTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIGFuZFdoZXJlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgb3JkZXJCeTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIHNraXA6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB0YWtlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgZ2V0T25lOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUobnVsbCksXHJcbiAgICAgIGdldE1hbnk6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSksXHJcbiAgICAgIGdldE1hbnlBbmRDb3VudDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKFtbXSwgMF0pLFxyXG4gICAgfSkpLFxyXG4gIH0pO1xyXG5cclxuICBjb25zdCBtb2NrRGF0YVNvdXJjZSA9IHtcclxuICAgIGNyZWF0ZVF1ZXJ5UnVubmVyOiBqZXN0LmZuKCgpID0+ICh7XHJcbiAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgIGNyZWF0ZTogamVzdC5mbigpLFxyXG4gICAgICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgIH0sXHJcbiAgICB9KSksXHJcbiAgICBnZXRSZXBvc2l0b3J5OiBqZXN0LmZuKCgpID0+IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCkpLFxyXG4gICAgbWFuYWdlcjoge1xyXG4gICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICB9LFxyXG4gIH07XHJcblxyXG4gIGJlZm9yZUVhY2goYXN5bmMgKCkgPT4ge1xyXG4gICAgdGVzdGluZ01vZHVsZSA9IGF3YWl0IFRlc3QuY3JlYXRlVGVzdGluZ01vZHVsZSh7XHJcbiAgICAgIHByb3ZpZGVyczogW1xyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlU2VydmljZSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZXZpc2lvbiksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZWZlcmVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUYWcpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oT3JnYW5pemF0aW9uKSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmVjaXBpZW50KSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHtcclxuICAgICAgICAgICAgZ2VuZXJhdGVOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHVwZGF0ZU51bWJlckZvckRyYWZ0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHByZXZpZXdOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogSnNvblNjaGVtYVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyB2YWxpZGF0ZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBXb3JrZmxvd0VuZ2luZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjcmVhdGVJbnN0YW5jZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBVc2VyU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7XHJcbiAgICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICAgICAgZ2V0VXNlclBlcm1pc3Npb25zOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoW10pLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IERhdGFTb3VyY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogbW9ja0RhdGFTb3VyY2UsXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBTZWFyY2hTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHsgaW5kZXhEb2N1bWVudDogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBGaWxlU3RvcmFnZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjb21taXQ6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFV1aWRSZXNvbHZlclNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZToge1xyXG4gICAgICAgICAgICByZXNvbHZlUHJvamVjdElkOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoMSksXHJcbiAgICAgICAgICAgIHJlc29sdmVPcmdhbml6YXRpb25JZDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKDEpLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IE5vdGlmaWNhdGlvblNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBzZW5kOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUodW5kZWZpbmVkKSB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgIF0sXHJcbiAgICB9KS5jb21waWxlKCk7XHJcblxyXG4gICAgc2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PENvcnJlc3BvbmRlbmNlU2VydmljZT4oQ29ycmVzcG9uZGVuY2VTZXJ2aWNlKTtcclxuICAgIG51bWJlcmluZ1NlcnZpY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEb2N1bWVudE51bWJlcmluZ1NlcnZpY2U+KFxyXG4gICAgICBEb2N1bWVudE51bWJlcmluZ1NlcnZpY2VcclxuICAgICk7XHJcbiAgICBjb3JyZXNwb25kZW5jZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlPj4oXHJcbiAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZSlcclxuICAgICk7XHJcbiAgICByZXZpc2lvblJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlUmV2aXNpb24+PihcclxuICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmV2aXNpb24pXHJcbiAgICApO1xyXG4gICAgX2RhdGFTb3VyY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEYXRhU291cmNlPihEYXRhU291cmNlKTtcclxuICB9KTtcclxuXHJcbiAgaXQoJ3Nob3VsZCBiZSBkZWZpbmVkJywgKCkgPT4ge1xyXG4gICAgZXhwZWN0KHNlcnZpY2UpLnRvQmVEZWZpbmVkKCk7XHJcbiAgfSk7XHJcblxyXG4gIGRlc2NyaWJlKCd1cGRhdGUnLCAoKSA9PiB7XHJcbiAgICBpdCgnc2hvdWxkIGFsbG93IG5vbi1kcmFmdCB1cGRhdGUgZm9yIG9yZy1hZG1pbisgcGVybWlzc2lvbnMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiAyMyxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3Qgc3RhdHVzUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VTdGF0dXM+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpXHJcbiAgICAgICk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDIzLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdTVUJPV04nLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHVzZXJTZXJ2aWNlID0gdGVzdGluZ01vZHVsZS5nZXQ8VXNlclNlcnZpY2U+KFVzZXJTZXJ2aWNlKTtcclxuICAgICAgKHVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKFtcclxuICAgICAgICAnY29ycmVzcG9uZGVuY2UuY2FuY2VsJyxcclxuICAgICAgXSk7XHJcblxyXG4gICAgICBhd2FpdCBleHBlY3QoXHJcbiAgICAgICAgc2VydmljZS51cGRhdGUoMSwgeyBzdWJqZWN0OiAnVXBkYXRlZCBTdWJqZWN0JyB9LCBtb2NrVXNlcilcclxuICAgICAgKS5yZXNvbHZlcy50b0JlRGVmaW5lZCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCByZWplY3Qgbm9uLWRyYWZ0IHVwZGF0ZSBmb3Igbm9uLWFkbWluIHBlcm1pc3Npb25zJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAyLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAyLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogMjMsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAyMyxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnU1VCT1dOJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBjb25zdCB1c2VyU2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PFVzZXJTZXJ2aWNlPihVc2VyU2VydmljZSk7XHJcbiAgICAgICh1c2VyU2VydmljZS5nZXRVc2VyUGVybWlzc2lvbnMgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXHJcbiAgICAgICAgJ2NvcnJlc3BvbmRlbmNlLmVkaXQnLFxyXG4gICAgICBdKTtcclxuXHJcbiAgICAgIGF3YWl0IGV4cGVjdChcclxuICAgICAgICBzZXJ2aWNlLnVwZGF0ZSgyLCB7IHN1YmplY3Q6ICdTaG91bGQgRmFpbCcgfSwgbW9ja1VzZXIpXHJcbiAgICAgICkucmVqZWN0cy50b1Rocm93KEZvcmJpZGRlbkV4Y2VwdGlvbik7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIE5PVCByZWdlbmVyYXRlIG51bWJlciBpZiBjcml0aWNhbCBmaWVsZHMgdW5jaGFuZ2VkJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCByZWdlbmVyYXRlIG51bWJlciBpZiBQcm9qZWN0IElEIGNoYW5nZXMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0geyBpZDogMSwgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMSxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDUsXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3QgbW9ja0NvcnIgPSB7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiAyLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6IDEwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiAnT0xELU5VTScsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgcmVjaXBpZW50VHlwZTogJ1RPJywgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IDk5IH1dLFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrQ29yciBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUR0bzogVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcHJvamVjdElkOiAyLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMik7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgcmVnZW5lcmF0ZSBudW1iZXIgaWYgRG9jdW1lbnQgVHlwZSBjaGFuZ2VzJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IG1vY2tDb3JyID0ge1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZVR5cGVJZDogMixcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAxMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogJ09MRC1OVU0nLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHJlY2lwaWVudFR5cGU6ICdUTycsIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiA5OSB9XSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihjb3JyZXNwb25kZW5jZVJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja0NvcnIgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHR5cGVJZDogOTk5LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgICh0eXBlUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiA5OTksXHJcbiAgICAgICAgdHlwZUNvZGU6ICdORVctVFlQRScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS50b0hhdmVCZWVuQ2FsbGVkKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHJlZ2VuZXJhdGUgbnVtYmVyIGlmIFJlY2lwaWVudCBPcmdhbml6YXRpb24gY2hhbmdlcycsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7IGlkOiAxLCBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAxLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogNSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgLy8gQWNjZXNzIERhdGFTb3VyY2UgbWFuYWdlciBmb3IgbW9ja2luZ1xyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiA4OCxcclxuICAgICAgICBvcmdhbml6YXRpb25Db2RlOiAnTkVXLU9SRycsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBPcmdhbml6YXRpb24pO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICByZWNpcGllbnRzOiBbeyB0eXBlOiAnVE8nLCBvcmdhbml6YXRpb25JZDogODggfV0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG4gIH0pO1xyXG5cclxuICBkZXNjcmliZSgnY3JlYXRlJywgKCkgPT4ge1xyXG4gICAgaXQoJ3Nob3VsZCBhbGxvdyBzeXN0ZW0ubWFuYWdlX2FsbCB1c2VyIHdpdGhvdXQgcHJpbWFyeU9yZ2FuaXphdGlvbklkIHdoZW4gb3JpZ2luYXRvcklkIGlzIHByb3ZpZGVkJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogbnVsbCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogJ29yaWdpbmF0b3ItdXVpZCcsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgb3JnYW5pemF0aW9uSWQ6ICdyZWNpcGllbnQtdXVpZCcsIHR5cGU6ICdUTycgfV0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCB1c2VyU2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PFVzZXJTZXJ2aWNlPihVc2VyU2VydmljZSk7XHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuXHJcbiAgICAgICh1c2VyU2VydmljZS5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiBudWxsLFxyXG4gICAgICB9KTtcclxuICAgICAgKHVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKFtcclxuICAgICAgICAnc3lzdGVtLm1hbmFnZV9hbGwnLFxyXG4gICAgICBdKTtcclxuXHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDEwMCk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkIGFzIGplc3QuTW9jaykubW9ja0ltcGxlbWVudGF0aW9uKFxyXG4gICAgICAgICh2YWx1ZTogbnVtYmVyIHwgc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICBpZiAodmFsdWUgPT09ICdvcmlnaW5hdG9yLXV1aWQnKSByZXR1cm4gMTA7XHJcbiAgICAgICAgICBpZiAodmFsdWUgPT09ICdyZWNpcGllbnQtdXVpZCcpIHJldHVybiAyMDtcclxuICAgICAgICAgIHJldHVybiAwO1xyXG4gICAgICAgIH1cclxuICAgICAgKTtcclxuXHJcbiAgICAgICh0eXBlUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHR5cGVDb2RlOiAnTFRSJyxcclxuICAgICAgfSk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgc3RhdHVzQ29kZTogJ0RSQUZUJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAobnVtYmVyaW5nU2VydmljZS5nZW5lcmF0ZU5leHROdW1iZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgbnVtYmVyOiAnRE9DLTAwMScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgbW9ja0RhdGFTb3VyY2UubWFuYWdlci5maW5kT25lXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMCwgb3JnYW5pemF0aW9uQ29kZTogJ09SRycgfSlcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDIwLCBvcmdhbml6YXRpb25Db2RlOiAnUkVDJyB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHF1ZXJ5UnVubmVyID0ge1xyXG4gICAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgICBzdGFydFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgY29tbWl0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcmVsZWFzZTogamVzdC5mbigpLFxyXG4gICAgICAgIG1hbmFnZXI6IHtcclxuICAgICAgICAgIGNyZWF0ZTogamVzdC5mbihcclxuICAgICAgICAgICAgKF9lbnRpdHk6IHVua25vd24sIHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBwYXlsb2FkXHJcbiAgICAgICAgICApLFxyXG4gICAgICAgICAgc2F2ZTogamVzdFxyXG4gICAgICAgICAgICAuZm4oKVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDk5OSwgcHVibGljSWQ6ICdjb3JyLXV1aWQnIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAwMCB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKFtdKSxcclxuICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICB9LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgKG1vY2tEYXRhU291cmNlLmNyZWF0ZVF1ZXJ5UnVubmVyIGFzIGplc3QuTW9jaykubW9ja1JldHVyblZhbHVlKFxyXG4gICAgICAgIHF1ZXJ5UnVubmVyXHJcbiAgICAgICk7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLmNyZWF0ZShjcmVhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2UsXHJcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyBvcmlnaW5hdG9ySWQ6IDEwIH0pXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHNldCByZXZpc2lvbkxhYmVsIHRvIFwiQVwiIGZvciBSRkEgdHlwZScsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7XHJcbiAgICAgICAgdXNlcl9pZDogMSxcclxuICAgICAgICBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuXHJcbiAgICAgIGNvbnN0IGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcHJvamVjdElkOiAncHJvamVjdC11dWlkJyxcclxuICAgICAgICB0eXBlSWQ6IDEsXHJcbiAgICAgICAgc3ViamVjdDogJ1Rlc3QgU3ViamVjdCcsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgb3JnYW5pemF0aW9uSWQ6ICdyZWNpcGllbnQtdXVpZCcsIHR5cGU6ICdUTycgfV0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCB0eXBlUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VUeXBlPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlVHlwZSlcclxuICAgICAgKTtcclxuICAgICAgY29uc3Qgc3RhdHVzUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VTdGF0dXM+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHV1aWRSZXNvbHZlciA9XHJcbiAgICAgICAgdGVzdGluZ01vZHVsZS5nZXQ8VXVpZFJlc29sdmVyU2VydmljZT4oVXVpZFJlc29sdmVyU2VydmljZSk7XHJcblxyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgxMDApO1xyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDIwKTtcclxuXHJcbiAgICAgICh0eXBlUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHR5cGVDb2RlOiAnUkZBJyxcclxuICAgICAgfSk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgc3RhdHVzQ29kZTogJ0RSQUZUJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAobnVtYmVyaW5nU2VydmljZS5nZW5lcmF0ZU5leHROdW1iZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgbnVtYmVyOiAnRE9DLTAwMScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgbW9ja0RhdGFTb3VyY2UubWFuYWdlci5maW5kT25lXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMCwgb3JnYW5pemF0aW9uQ29kZTogJ09SRycgfSlcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDIwLCBvcmdhbml6YXRpb25Db2RlOiAnUkVDJyB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHF1ZXJ5UnVubmVyID0ge1xyXG4gICAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgICBzdGFydFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgY29tbWl0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcmVsZWFzZTogamVzdC5mbigpLFxyXG4gICAgICAgIG1hbmFnZXI6IHtcclxuICAgICAgICAgIGNyZWF0ZTogamVzdC5mbihcclxuICAgICAgICAgICAgKF9lbnRpdHk6IHVua25vd24sIHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBwYXlsb2FkXHJcbiAgICAgICAgICApLFxyXG4gICAgICAgICAgc2F2ZTogamVzdFxyXG4gICAgICAgICAgICAuZm4oKVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDk5OSwgcHVibGljSWQ6ICdjb3JyLXV1aWQnIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAwMCB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKFtdKSxcclxuICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICB9LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgKG1vY2tEYXRhU291cmNlLmNyZWF0ZVF1ZXJ5UnVubmVyIGFzIGplc3QuTW9jaykubW9ja1JldHVyblZhbHVlKFxyXG4gICAgICAgIHF1ZXJ5UnVubmVyXHJcbiAgICAgICk7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLmNyZWF0ZShjcmVhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbixcclxuICAgICAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7IHJldmlzaW9uTGFiZWw6ICdBJyB9KVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCBzZXQgcmV2aXNpb25MYWJlbCB0byBcIkFcIiBmb3IgUkZJIHR5cGUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyMCk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ1JGSScsXHJcbiAgICAgIH0pO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdEUkFGVCcsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgKG51bWJlcmluZ1NlcnZpY2UuZ2VuZXJhdGVOZXh0TnVtYmVyIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIG51bWJlcjogJ0RPQy0wMDEnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAsIG9yZ2FuaXphdGlvbkNvZGU6ICdPUkcnIH0pXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAyMCwgb3JnYW5pemF0aW9uQ29kZTogJ1JFQycgfSk7XHJcblxyXG4gICAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHtcclxuICAgICAgICBjb25uZWN0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcm9sbGJhY2tUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgICBjcmVhdGU6IGplc3QuZm4oXHJcbiAgICAgICAgICAgIChfZW50aXR5OiB1bmtub3duLCBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gcGF5bG9hZFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIHNhdmU6IGplc3RcclxuICAgICAgICAgICAgLmZuKClcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiA5OTksIHB1YmxpY0lkOiAnY29yci11dWlkJyB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwMDAgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZShbXSksXHJcbiAgICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgICAgfSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIChtb2NrRGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lciBhcyBqZXN0Lk1vY2spLm1vY2tSZXR1cm5WYWx1ZShcclxuICAgICAgICBxdWVyeVJ1bm5lclxyXG4gICAgICApO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS5jcmVhdGUoY3JlYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QocXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmV2aXNpb24sXHJcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyByZXZpc2lvbkxhYmVsOiAnQScgfSlcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgc2V0IHJldmlzaW9uTGFiZWwgdG8gbnVsbCBmb3IgTEVUVEVSIHR5cGUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyMCk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ0xFVFRFUicsXHJcbiAgICAgIH0pO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdEUkFGVCcsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgKG51bWJlcmluZ1NlcnZpY2UuZ2VuZXJhdGVOZXh0TnVtYmVyIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIG51bWJlcjogJ0RPQy0wMDEnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAsIG9yZ2FuaXphdGlvbkNvZGU6ICdPUkcnIH0pXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAyMCwgb3JnYW5pemF0aW9uQ29kZTogJ1JFQycgfSk7XHJcblxyXG4gICAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHtcclxuICAgICAgICBjb25uZWN0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcm9sbGJhY2tUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgICBjcmVhdGU6IGplc3QuZm4oXHJcbiAgICAgICAgICAgIChfZW50aXR5OiB1bmtub3duLCBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gcGF5bG9hZFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIHNhdmU6IGplc3RcclxuICAgICAgICAgICAgLmZuKClcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiA5OTksIHB1YmxpY0lkOiAnY29yci11dWlkJyB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwMDAgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZShbXSksXHJcbiAgICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgICAgfSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIChtb2NrRGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lciBhcyBqZXN0Lk1vY2spLm1vY2tSZXR1cm5WYWx1ZShcclxuICAgICAgICBxdWVyeVJ1bm5lclxyXG4gICAgICApO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS5jcmVhdGUoY3JlYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QocXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmV2aXNpb24sXHJcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyByZXZpc2lvbkxhYmVsOiB1bmRlZmluZWQgfSlcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgc2V0IHJldmlzaW9uTGFiZWwgdG8gdW5kZWZpbmVkIGZvciBNRU1PIHR5cGUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyMCk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ01FTU8nLFxyXG4gICAgICB9KTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnRFJBRlQnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIChudW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlciBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBudW1iZXI6ICdET0MtMDAxJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmVcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwLCBvcmdhbml6YXRpb25Db2RlOiAnT1JHJyB9KVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMjAsIG9yZ2FuaXphdGlvbkNvZGU6ICdSRUMnIH0pO1xyXG5cclxuICAgICAgY29uc3QgcXVlcnlSdW5uZXIgPSB7XHJcbiAgICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICAgIHN0YXJ0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByZWxlYXNlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgICAgY3JlYXRlOiBqZXN0LmZuKFxyXG4gICAgICAgICAgICAoX2VudGl0eTogdW5rbm93biwgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHBheWxvYWRcclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBzYXZlOiBqZXN0XHJcbiAgICAgICAgICAgIC5mbigpXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogOTk5LCBwdWJsaWNJZDogJ2NvcnItdXVpZCcgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMDAwIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoW10pLFxyXG4gICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICAobW9ja0RhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmV0dXJuVmFsdWUoXHJcbiAgICAgICAgcXVlcnlSdW5uZXJcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UuY3JlYXRlKGNyZWF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcclxuICAgICAgICBDb3JyZXNwb25kZW5jZVJldmlzaW9uLFxyXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgcmV2aXNpb25MYWJlbDogdW5kZWZpbmVkIH0pXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuICB9KTtcclxufSk7XHJcbiJdLCJ2ZXJzaW9uIjozfQ== \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/09/correspondenceservicespec_09d46a7193361a4ca1873205694e5f3c.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/09/correspondenceservicespec_09d46a7193361a4ca1873205694e5f3c.map new file mode 100644 index 0000000..fd72b17 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/09/correspondenceservicespec_09d46a7193361a4ca1873205694e5f3c.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts"],"sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\r\nimport { getRepositoryToken } from '@nestjs/typeorm';\r\nimport { DataSource, Repository } from 'typeorm';\r\nimport { ForbiddenException } from '@nestjs/common';\r\nimport { CorrespondenceService } from './correspondence.service';\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { User } from '../user/entities/user.entity';\r\n\r\ndescribe('CorrespondenceService', () => {\r\n let service: CorrespondenceService;\r\n let numberingService: DocumentNumberingService;\r\n let correspondenceRepo: Repository;\r\n let revisionRepo: Repository;\r\n let testingModule: TestingModule;\r\n let _dataSource: DataSource;\r\n\r\n const createMockRepository = () => ({\r\n find: jest.fn(),\r\n findOne: jest.fn(),\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n update: jest.fn(),\r\n delete: jest.fn(),\r\n softDelete: jest.fn(),\r\n createQueryBuilder: jest.fn(() => ({\r\n leftJoinAndSelect: jest.fn().mockReturnThis(),\r\n where: jest.fn().mockReturnThis(),\r\n andWhere: jest.fn().mockReturnThis(),\r\n orderBy: jest.fn().mockReturnThis(),\r\n skip: jest.fn().mockReturnThis(),\r\n take: jest.fn().mockReturnThis(),\r\n getOne: jest.fn().mockResolvedValue(null),\r\n getMany: jest.fn().mockResolvedValue([]),\r\n getManyAndCount: jest.fn().mockResolvedValue([[], 0]),\r\n })),\r\n });\r\n\r\n const mockDataSource = {\r\n createQueryRunner: jest.fn(() => ({\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n findOne: jest.fn(),\r\n },\r\n })),\r\n getRepository: jest.fn(() => createMockRepository()),\r\n manager: {\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n beforeEach(async () => {\r\n testingModule = await Test.createTestingModule({\r\n providers: [\r\n CorrespondenceService,\r\n {\r\n provide: getRepositoryToken(Correspondence),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRevision),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceType),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceStatus),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceReference),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceTag),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(Organization),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRecipient),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: DocumentNumberingService,\r\n useValue: {\r\n generateNextNumber: jest.fn(),\r\n updateNumberForDraft: jest.fn(),\r\n previewNextNumber: jest.fn(),\r\n },\r\n },\r\n {\r\n provide: JsonSchemaService,\r\n useValue: { validate: jest.fn() },\r\n },\r\n {\r\n provide: WorkflowEngineService,\r\n useValue: { createInstance: jest.fn() },\r\n },\r\n {\r\n provide: UserService,\r\n useValue: {\r\n findOne: jest.fn(),\r\n getUserPermissions: jest.fn().mockResolvedValue([]),\r\n },\r\n },\r\n {\r\n provide: DataSource,\r\n useValue: mockDataSource,\r\n },\r\n {\r\n provide: SearchService,\r\n useValue: { indexDocument: jest.fn() },\r\n },\r\n {\r\n provide: FileStorageService,\r\n useValue: { commit: jest.fn().mockResolvedValue([]) },\r\n },\r\n {\r\n provide: UuidResolverService,\r\n useValue: {\r\n resolveProjectId: jest.fn().mockResolvedValue(1),\r\n resolveOrganizationId: jest.fn().mockResolvedValue(1),\r\n },\r\n },\r\n {\r\n provide: NotificationService,\r\n useValue: { send: jest.fn().mockResolvedValue(undefined) },\r\n },\r\n ],\r\n }).compile();\r\n\r\n service = testingModule.get(CorrespondenceService);\r\n numberingService = testingModule.get(\r\n DocumentNumberingService\r\n );\r\n correspondenceRepo = testingModule.get>(\r\n getRepositoryToken(Correspondence)\r\n );\r\n revisionRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceRevision)\r\n );\r\n _dataSource = testingModule.get(DataSource);\r\n });\r\n\r\n it('should be defined', () => {\r\n expect(service).toBeDefined();\r\n });\r\n\r\n describe('update', () => {\r\n it('should allow non-draft update for org-admin+ permissions', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 23,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 23,\r\n statusCode: 'SUBOWN',\r\n });\r\n\r\n const userService = testingModule.get(UserService);\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'correspondence.cancel',\r\n ]);\r\n\r\n await expect(\r\n service.update(1, { subject: 'Updated Subject' }, mockUser)\r\n ).resolves.toBeDefined();\r\n });\r\n\r\n it('should reject non-draft update for non-admin permissions', async () => {\r\n const mockUser = {\r\n user_id: 2,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n const mockRevision = {\r\n id: 101,\r\n correspondenceId: 2,\r\n isCurrent: true,\r\n statusId: 23,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 23,\r\n statusCode: 'SUBOWN',\r\n });\r\n\r\n const userService = testingModule.get(UserService);\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'correspondence.edit',\r\n ]);\r\n\r\n await expect(\r\n service.update(2, { subject: 'Should Fail' }, mockUser)\r\n ).rejects.toThrow(ForbiddenException);\r\n });\r\n\r\n it('should NOT regenerate number if critical fields unchanged', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 1,\r\n disciplineId: 3,\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).not.toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Project ID changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 2,\r\n };\r\n\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(2);\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Document Type changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n typeId: 999,\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 999,\r\n typeCode: 'NEW-TYPE',\r\n });\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Recipient Organization changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n // Access DataSource manager for mocking\r\n mockDataSource.manager.findOne.mockResolvedValue({\r\n id: 88,\r\n organizationCode: 'NEW-ORG',\r\n } as unknown as Organization);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n recipients: [{ type: 'TO', organizationId: 88 }],\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n });\r\n\r\n describe('create', () => {\r\n it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n originatorId: 'originator-uuid',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const userService = testingModule.get(UserService);\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (userService.findOne as jest.Mock).mockResolvedValue({\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n });\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'system.manage_all',\r\n ]);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockImplementation(\r\n (value: number | string) => {\r\n if (value === 'originator-uuid') return 10;\r\n if (value === 'recipient-uuid') return 20;\r\n return 0;\r\n }\r\n );\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LTR',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n Correspondence,\r\n expect.objectContaining({ originatorId: 10 })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to \"A\" for RFA type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'RFA',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: 'A' })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to \"A\" for RFI type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'RFI',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: 'A' })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to null for LETTER type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LETTER',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: undefined })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to undefined for MEMO type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'MEMO',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: undefined })\r\n );\r\n });\r\n });\r\n});\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/36/correspondenceservice_362c2d40da9948c1683321c46a0347aa b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/36/correspondenceservice_362c2d40da9948c1683321c46a0347aa new file mode 100644 index 0000000..99adf3a --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/36/correspondenceservice_362c2d40da9948c1683321c46a0347aa @@ -0,0 +1,898 @@ +d7f107a395b1164986917664600a90ce +"use strict"; +// File: src/modules/correspondence/correspondence.service.ts +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var CorrespondenceService_1; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CorrespondenceService = void 0; +const common_1 = require("@nestjs/common"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +// Entities +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const tag_entity_1 = require("../master/entities/tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +// Services +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +let CorrespondenceService = CorrespondenceService_1 = class CorrespondenceService { + async hasSystemManageAllPermission(userId) { + const permissions = await this.userService.getUserPermissions(userId); + return permissions.includes('system.manage_all'); + } + /** + * Business Rule: Revision Label Strategy + * - RFA, RFI: Use alphabet starting with 'A' (A, B, C...) + * - Other types (LETTER, MEMO, etc.): Use numeric (null for first, then 1, 2, 3...) + */ + getInitialRevisionLabel(typeCode) { + const alphabetTypes = ['RFA', 'RFI']; + if (alphabetTypes.includes(typeCode.toUpperCase())) { + return 'A'; // Alphabet for RFA, RFI + } + return undefined; // Numeric (no label for revision 0) + } + constructor(correspondenceRepo, revisionRepo, typeRepo, statusRepo, referenceRepo, tagRepo, numberingService, jsonSchemaService, workflowEngine, userService, dataSource, searchService, fileStorageService, uuidResolver, notificationService) { + this.correspondenceRepo = correspondenceRepo; + this.revisionRepo = revisionRepo; + this.typeRepo = typeRepo; + this.statusRepo = statusRepo; + this.referenceRepo = referenceRepo; + this.tagRepo = tagRepo; + this.numberingService = numberingService; + this.jsonSchemaService = jsonSchemaService; + this.workflowEngine = workflowEngine; + this.userService = userService; + this.dataSource = dataSource; + this.searchService = searchService; + this.fileStorageService = fileStorageService; + this.uuidResolver = uuidResolver; + this.notificationService = notificationService; + this.logger = new common_1.Logger(CorrespondenceService_1.name); + } + /** + * Business Rule Validation: EC-CORR-003 - Correspondence to Self + * Prevent external correspondence to same organization + */ + async validateCorrespondenceRecipients(createDto, user) { + // Get user's organization + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + if (!userOrgId) { + if (createDto.originatorId) { + const canManageAll = await this.hasSystemManageAllPermission(user.user_id); + if (canManageAll) { + userOrgId = await this.uuidResolver.resolveOrganizationId(createDto.originatorId); + } + } + if (!userOrgId) { + throw new common_1.BadRequestException('User must belong to an organization to create documents'); + } + } + // For impersonation, use the specified originator + const originatorOrgId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : userOrgId; + // Check if it's internal communication + if (createDto.isInternal) { + // Internal communications should use Circulation instead + throw new common_1.BadRequestException('Internal communications should use Circulation Sheet instead of Correspondence'); + } + // Validate recipients + if (!createDto.recipients || createDto.recipients.length === 0) { + throw new common_1.BadRequestException('At least one recipient (TO or CC) is required'); + } + const toRecipients = createDto.recipients.filter((r) => r.type === 'TO'); + const ccRecipients = createDto.recipients.filter((r) => r.type === 'CC'); + if (toRecipients.length === 0 && ccRecipients.length === 0) { + throw new common_1.BadRequestException('At least one TO or CC recipient is required'); + } + // Check for same organization correspondence + for (const recipient of createDto.recipients) { + const recipientOrgId = await this.uuidResolver.resolveOrganizationId(recipient.organizationId); + if (recipientOrgId === originatorOrgId) { + throw new common_1.BadRequestException('Cannot send correspondence to your own organization. Use Circulation Sheet for internal communication.'); + } + } + } + async create(createDto, user) { + // Business Rule Validation: EC-CORR-003 - Correspondence to Self + await this.validateCorrespondenceRecipients(createDto, user); + // ADR-019: Resolve UUID references to internal INT IDs + const resolvedProjectId = await this.uuidResolver.resolveProjectId(createDto.projectId); + const resolvedOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + const resolvedRecipients = createDto.recipients + ? await Promise.all(createDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + const type = await this.typeRepo.findOne({ + where: { id: createDto.typeId }, + }); + if (!type) + throw new common_1.NotFoundException('Document Type not found'); + const statusDraft = await this.statusRepo.findOne({ + where: { statusCode: 'DRAFT' }, + }); + if (!statusDraft) { + throw new common_1.InternalServerErrorException('Status DRAFT not found in Master Data'); + } + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + // Impersonation Logic + if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) { + const canManageAll = await this.hasSystemManageAllPermission(user.user_id); + if (!canManageAll) { + throw new common_1.ForbiddenException('You do not have permission to create documents on behalf of other organizations.'); + } + userOrgId = resolvedOriginatorId; + } + if (!userOrgId) { + throw new common_1.BadRequestException('User must belong to an organization to create documents'); + } + if (createDto.details) { + try { + await this.jsonSchemaService.validate(type.typeCode, createDto.details); + } + catch (error) { + this.logger.warn(`Schema validation warning for ${type.typeCode}: ${error.message}`); + } + } + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + try { + // [Fix #6] Fetch real ORG Code from Organization entity + const originatorOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: userOrgId }, + }); + const orgCode = originatorOrg?.organizationCode ?? 'UNK'; + // [v1.5.1] Extract recipient organization from recipients array (Primary TO) + const toRecipient = resolvedRecipients?.find((r) => r.type === 'TO'); + const recipientOrganizationId = toRecipient?.organizationId; + let recipientCode = ''; + if (recipientOrganizationId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: recipientOrganizationId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + const docNumber = await this.numberingService.generateNextNumber({ + projectId: resolvedProjectId, + originatorOrganizationId: userOrgId, + typeId: createDto.typeId, + disciplineId: createDto.disciplineId, + subTypeId: createDto.subTypeId, + recipientOrganizationId, // [v1.5.1] Pass recipient for document number format + year: new Date().getFullYear(), + customTokens: { + TYPE_CODE: type.typeCode, + ORG_CODE: orgCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }); + const correspondence = queryRunner.manager.create(correspondence_entity_1.Correspondence, { + correspondenceNumber: docNumber.number, + correspondenceTypeId: createDto.typeId, + disciplineId: createDto.disciplineId, + projectId: resolvedProjectId, + originatorId: userOrgId, + isInternal: createDto.isInternal || false, + createdBy: user.user_id, + }); + const savedCorr = await queryRunner.manager.save(correspondence); + const revision = queryRunner.manager.create(correspondence_revision_entity_1.CorrespondenceRevision, { + correspondenceId: savedCorr.id, + revisionNumber: 0, + revisionLabel: this.getInitialRevisionLabel(type.typeCode), + isCurrent: true, + statusId: statusDraft.id, + subject: createDto.subject, + body: createDto.body, + remarks: createDto.remarks, + dueDate: createDto.dueDate ? new Date(createDto.dueDate) : undefined, + documentDate: createDto.documentDate + ? new Date(createDto.documentDate) + : undefined, + issuedDate: createDto.issuedDate + ? new Date(createDto.issuedDate) + : undefined, + receivedDate: createDto.receivedDate + ? new Date(createDto.receivedDate) + : undefined, + description: createDto.description, + details: createDto.details, + createdBy: user.user_id, + schemaVersion: 1, + }); + await queryRunner.manager.save(revision); + // Save Recipients (using resolved INT IDs) + if (resolvedRecipients && resolvedRecipients.length > 0) { + const recipients = resolvedRecipients.map((r) => queryRunner.manager.create(correspondence_recipient_entity_1.CorrespondenceRecipient, { + correspondenceId: savedCorr.id, + recipientOrganizationId: r.organizationId, + recipientType: r.type, + })); + await queryRunner.manager.save(recipients); + } + // Commit attachments from Temp → Permanent (Two-Phase Storage) + if (createDto.attachmentTempIds?.length) { + const issueDate = createDto.issuedDate + ? new Date(createDto.issuedDate) + : createDto.documentDate + ? new Date(createDto.documentDate) + : undefined; + await this.fileStorageService.commit(createDto.attachmentTempIds, { + issueDate, + documentType: 'Correspondence', + }); + } + await queryRunner.commitTransaction(); + // Start Workflow Instance (non-blocking) + try { + const workflowCode = `CORRESPONDENCE_${type.typeCode}`; + await this.workflowEngine.createInstance(workflowCode, 'correspondence', savedCorr.id.toString(), { + projectId: resolvedProjectId, + originatorId: userOrgId, + disciplineId: createDto.disciplineId, + initiatorId: user.user_id, + }); + } + catch (error) { + this.logger.warn(`Workflow not started for ${docNumber.number} (Code: CORRESPONDENCE_${type.typeCode}): ${error.message}`); + } + // Fire-and-forget search indexing (non-blocking, void intentional) + void this.searchService.indexDocument({ + id: savedCorr.id, + publicId: savedCorr.publicId, + type: 'correspondence', + docNumber: docNumber.number, + title: createDto.subject, + description: createDto.description, + status: 'DRAFT', + projectId: resolvedProjectId, + createdAt: new Date(), + }); + return { + ...savedCorr, + currentRevision: revision, + }; + } + catch (err) { + await queryRunner.rollbackTransaction(); + this.logger.error(`Failed to create correspondence: ${err.message}`); + throw err; + } + finally { + await queryRunner.release(); + } + } + async findAll(searchDto = {}) { + const { search, typeId, projectId, statusId, status, page = 1, limit = 10, } = searchDto; + const skip = (page - 1) * limit; + // Change: Query from Revision Repo + const query = this.revisionRepo + .createQueryBuilder('rev') + .leftJoinAndSelect('rev.correspondence', 'corr') + .leftJoinAndSelect('corr.type', 'type') + .leftJoinAndSelect('corr.project', 'project') + .leftJoinAndSelect('corr.originator', 'org') + .leftJoinAndSelect('rev.status', 'status'); + // Filter by Revision Status + const revStatus = searchDto.revisionStatus || 'CURRENT'; + if (revStatus === 'CURRENT') { + query.where('rev.isCurrent = :isCurrent', { isCurrent: true }); + } + else if (revStatus === 'OLD') { + query.where('rev.isCurrent = :isCurrent', { isCurrent: false }); + } + // If 'ALL', no filter needed on isCurrent + if (projectId) { + query.andWhere('corr.projectId = :projectId', { projectId }); + } + if (typeId) { + query.andWhere('corr.correspondenceTypeId = :typeId', { typeId }); + } + if (statusId) { + query.andWhere('rev.statusId = :statusId', { statusId }); + } + if (status) { + query.andWhere('status.statusCode = :status', { status }); + } + if (search) { + query.andWhere('(corr.correspondenceNumber LIKE :search OR rev.subject LIKE :search)', { search: `%${search}%` }); + } + // Default Sort: Latest Created + query.orderBy('rev.createdAt', 'DESC').skip(skip).take(limit); + const [items, total] = await query.getManyAndCount(); + return { + data: items, + meta: { + total, + page, + limit, + totalPages: Math.ceil(total / limit), + }, + }; + } + async findOne(id) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { id }, + relations: [ + 'revisions', + 'revisions.status', + 'type', + 'project', + 'originator', + 'recipients', + 'recipients.recipientOrganization', // [v1.5.1] Fixed relation name + ], + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence with ID ${id} not found`); + } + return correspondence; + } + async findOneByUuid(publicId) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { publicId }, + relations: [ + 'revisions', + 'revisions.status', + 'type', + 'project', + 'originator', + 'recipients', + 'recipients.recipientOrganization', + ], + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence with UUID ${publicId} not found`); + } + return correspondence; + } + async addReference(id, dto) { + const source = await this.correspondenceRepo.findOne({ where: { id } }); + // ADR-019: Resolve target publicId → internal INT id + const target = await this.correspondenceRepo.findOne({ + where: { publicId: dto.targetUuid }, + }); + if (!source || !target) { + throw new common_1.NotFoundException('Source or Target correspondence not found'); + } + if (source.id === target.id) { + throw new common_1.BadRequestException('Cannot reference self'); + } + const exists = await this.referenceRepo.findOne({ + where: { + sourceId: id, + targetId: target.id, + }, + }); + if (exists) { + return exists; + } + const ref = this.referenceRepo.create({ + sourceId: id, + targetId: target.id, + }); + return this.referenceRepo.save(ref); + } + async removeReference(id, targetId) { + const result = await this.referenceRepo.delete({ + sourceId: id, + targetId: targetId, + }); + if (result.affected === 0) { + throw new common_1.NotFoundException('Reference not found'); + } + } + async getTags(id) { + const rows = await this.tagRepo.find({ + where: { correspondenceId: id }, + relations: ['tag'], + }); + return rows.map((r) => r.tag).filter(Boolean); + } + async addTag(id, tagId) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { id }, + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence ${id} not found`); + } + const tag = await this.dataSource.manager.findOne(tag_entity_1.Tag, { + where: { id: tagId }, + }); + if (!tag) { + throw new common_1.NotFoundException(`Tag ${tagId} not found`); + } + const exists = await this.tagRepo.findOne({ + where: { correspondenceId: id, tagId }, + }); + if (exists) + return exists; + const row = this.tagRepo.create({ correspondenceId: id, tagId }); + return this.tagRepo.save(row); + } + async removeTag(id, tagId) { + const result = await this.tagRepo.delete({ correspondenceId: id, tagId }); + if (result.affected === 0) { + throw new common_1.NotFoundException('Tag assignment not found'); + } + } + async getReferences(id) { + const outgoing = await this.referenceRepo.find({ + where: { sourceId: id }, + relations: ['target', 'target.type'], + }); + const incoming = await this.referenceRepo.find({ + where: { targetId: id }, + relations: ['source', 'source.type'], + }); + return { outgoing, incoming }; + } + async update(id, updateDto, user) { + // 1. Find Current Revision + const revision = await this.revisionRepo.findOne({ + where: { + correspondenceId: id, + isCurrent: true, + }, + relations: ['correspondence'], + }); + if (!revision) { + throw new common_1.NotFoundException(`Current revision for correspondence ${id} not found`); + } + // 2. Check Permission + if (revision.statusId) { + const status = await this.statusRepo.findOne({ + where: { id: revision.statusId }, + }); + if (status && status.statusCode !== 'DRAFT') { + const permissions = await this.userService.getUserPermissions(user.user_id); + const canEditSubmittedOrLater = permissions.includes('correspondence.cancel') || + permissions.includes('system.manage_all'); + if (!canEditSubmittedOrLater) { + throw new common_1.ForbiddenException('Only Org Admin or Superadmin can edit non-draft correspondences'); + } + } + } + // ADR-019: Resolve UUID references in update DTO + const updResolvedProjectId = updateDto.projectId + ? await this.uuidResolver.resolveProjectId(updateDto.projectId) + : undefined; + const updResolvedOriginatorId = updateDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(updateDto.originatorId) + : undefined; + const updResolvedRecipients = updateDto.recipients + ? await Promise.all(updateDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + // 3. Update Correspondence Entity if needed + const correspondenceUpdate = {}; + if (updateDto.disciplineId) + correspondenceUpdate.disciplineId = updateDto.disciplineId; + if (updResolvedProjectId) + correspondenceUpdate.projectId = updResolvedProjectId; + if (updResolvedOriginatorId) + correspondenceUpdate.originatorId = updResolvedOriginatorId; + if (Object.keys(correspondenceUpdate).length > 0) { + await this.correspondenceRepo.update(id, correspondenceUpdate); + } + // 4. Update Revision Entity + const revisionUpdate = {}; + if (updateDto.subject) + revisionUpdate.subject = updateDto.subject; + if (updateDto.body) + revisionUpdate.body = updateDto.body; + if (updateDto.remarks) + revisionUpdate.remarks = updateDto.remarks; + // Format Date correctly if string + if (updateDto.dueDate) + revisionUpdate.dueDate = new Date(updateDto.dueDate); + if (updateDto.documentDate) + revisionUpdate.documentDate = new Date(updateDto.documentDate); + if (updateDto.issuedDate) + revisionUpdate.issuedDate = new Date(updateDto.issuedDate); + if (updateDto.receivedDate) + revisionUpdate.receivedDate = new Date(updateDto.receivedDate); + if (updateDto.description) + revisionUpdate.description = updateDto.description; + if (updateDto.details) + revisionUpdate.details = updateDto.details; + if (Object.keys(revisionUpdate).length > 0) { + await this.revisionRepo.update(revision.id, revisionUpdate); + } + // 4.5 Commit new attachments from Temp → Permanent (Two-Phase Storage) + if (updateDto.attachmentTempIds?.length) { + const issueDate = updateDto.issuedDate + ? new Date(updateDto.issuedDate) + : updateDto.documentDate + ? new Date(updateDto.documentDate) + : revision.issuedDate || revision.documentDate || undefined; + await this.fileStorageService.commit(updateDto.attachmentTempIds, { + issueDate: issueDate ? new Date(issueDate) : undefined, + documentType: 'Correspondence', + }); + } + // 5. Update Recipients if provided + if (updResolvedRecipients) { + const recipientRepo = this.dataSource.getRepository(correspondence_recipient_entity_1.CorrespondenceRecipient); + await recipientRepo.delete({ correspondenceId: id }); + const newRecipients = updResolvedRecipients.map((r) => recipientRepo.create({ + correspondenceId: id, + recipientOrganizationId: r.organizationId, + recipientType: r.type, + })); + await recipientRepo.save(newRecipients); + } + // 6. Regenerate Document Number if structural fields changed (Recipient, Discipline, Type, Project) + // AND it is a DRAFT. + // Fetch fresh data for context and comparison + const currentCorr = await this.correspondenceRepo.findOne({ + where: { id }, + relations: ['type', 'recipients', 'recipients.recipientOrganization'], + }); + if (currentCorr) { + const currentToRecipient = currentCorr.recipients?.find((r) => r.recipientType === 'TO'); + const currentRecipientId = currentToRecipient?.recipientOrganizationId; + // Check for ACTUAL value changes + const isProjectChanged = updResolvedProjectId !== undefined && + updResolvedProjectId !== currentCorr.projectId; + const isOriginatorChanged = updResolvedOriginatorId !== undefined && + updResolvedOriginatorId !== currentCorr.originatorId; + const isDisciplineChanged = updateDto.disciplineId !== undefined && + updateDto.disciplineId !== currentCorr.disciplineId; + const isTypeChanged = updateDto.typeId !== undefined && + updateDto.typeId !== currentCorr.correspondenceTypeId; + let isRecipientChanged = false; + let newRecipientId; + if (updResolvedRecipients) { + const newToRecipient = updResolvedRecipients.find((r) => r.type === 'TO'); + newRecipientId = newToRecipient?.organizationId; + if (newRecipientId !== currentRecipientId) { + isRecipientChanged = true; + } + } + if (isProjectChanged || + isDisciplineChanged || + isTypeChanged || + isRecipientChanged || + isOriginatorChanged) { + const targetRecipientId = isRecipientChanged + ? newRecipientId + : currentRecipientId; + // Resolve Recipient Code for the NEW context + let recipientCode = ''; + if (targetRecipientId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: targetRecipientId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + // [Fix #6] Fetch real ORG Code from originator organization + const originatorOrgForUpdate = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { + id: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0, + }, + }); + const orgCode = originatorOrgForUpdate?.organizationCode ?? 'UNK'; + // Prepare Contexts + const oldCtx = { + projectId: currentCorr.projectId, + originatorOrganizationId: currentCorr.originatorId ?? 0, + typeId: currentCorr.correspondenceTypeId, + disciplineId: currentCorr.disciplineId, + recipientOrganizationId: currentRecipientId, + year: new Date().getFullYear(), + }; + const newCtx = { + projectId: updResolvedProjectId ?? currentCorr.projectId, + originatorOrganizationId: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0, + typeId: updateDto.typeId ?? currentCorr.correspondenceTypeId, + disciplineId: updateDto.disciplineId ?? currentCorr.disciplineId, + recipientOrganizationId: targetRecipientId, + year: new Date().getFullYear(), + userId: user.user_id, // Pass User ID for Audit + customTokens: { + TYPE_CODE: currentCorr.type?.typeCode || '', + ORG_CODE: orgCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }; + // If Type Changed, need NEW Type Code + if (isTypeChanged) { + const newType = await this.typeRepo.findOne({ + where: { id: newCtx.typeId }, + }); + if (newType) + newCtx.customTokens.TYPE_CODE = newType.typeCode; + } + const newDocNumber = await this.numberingService.updateNumberForDraft(currentCorr.correspondenceNumber, oldCtx, newCtx); + await this.correspondenceRepo.update(id, { + correspondenceNumber: newDocNumber, + }); + } + } + const updated = await this.findOne(id); + // Re-index updated document in Elasticsearch (fire-and-forget) + void this.searchService.indexDocument({ + id: updated.id, + publicId: updated.publicId, + type: 'correspondence', + docNumber: updated.correspondenceNumber, + title: updateDto.subject ?? updated.revisions?.[0]?.subject, + description: updateDto.description ?? updated.revisions?.[0]?.description, + status: 'DRAFT', + projectId: updated.projectId, + createdAt: updated.createdAt, + }); + return updated; + } + async previewDocumentNumber(createDto, user) { + // ADR-019: Resolve UUID references + const previewProjectId = await this.uuidResolver.resolveProjectId(createDto.projectId); + const previewOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + const previewRecipients = createDto.recipients + ? await Promise.all(createDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + const type = await this.typeRepo.findOne({ + where: { id: createDto.typeId }, + }); + if (!type) + throw new common_1.NotFoundException('Document Type not found'); + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) + userOrgId = fullUser.primaryOrganizationId; + } + if (previewOriginatorId && previewOriginatorId !== userOrgId) { + // Allow impersonation for preview + userOrgId = previewOriginatorId; + } + // Extract recipient from recipients array + const toRecipient = previewRecipients?.find((r) => r.type === 'TO'); + const recipientOrganizationId = toRecipient?.organizationId; + let recipientCode = ''; + if (recipientOrganizationId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: recipientOrganizationId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + return this.numberingService.previewNumber({ + projectId: previewProjectId, + originatorOrganizationId: userOrgId, + typeId: createDto.typeId, + disciplineId: createDto.disciplineId, + subTypeId: createDto.subTypeId, + recipientOrganizationId, + year: new Date().getFullYear(), + customTokens: { + TYPE_CODE: type.typeCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }); + } + /** + * Business Rule Implementation: EC-CORR-001 - Cancel Correspondence with Downstream Circulation + * Cancel correspondence and handle related circulations + */ + async cancel(publicId, reason, user) { + const correspondence = await this.findOneByUuid(publicId); + // Check if user has permission to cancel (Org Admin or Superadmin only) + const permissions = await this.userService.getUserPermissions(user.user_id); + const canCancel = permissions.includes('correspondence.cancel') || + permissions.includes('system.manage_all'); + if (!canCancel) { + throw new common_1.ForbiddenException('Only administrators can cancel correspondences'); + } + // Check if there are any active circulations + const circulationRepo = this.dataSource.getRepository('Circulation'); + const activeCirculations = await circulationRepo.find({ + where: { + correspondenceId: correspondence.id, + status: 'OPEN', + }, + }); + const warningMessage = activeCirculations.length > 0 + ? `There are ${activeCirculations.length} active circulation(s) for this correspondence. Canceling will force close all related circulations.` + : ''; + // Get the current revision to update status + const currentRevision = await this.revisionRepo.findOne({ + where: { + correspondenceId: correspondence.id, + isCurrent: true, + }, + }); + if (!currentRevision) { + throw new common_1.NotFoundException('Current revision not found'); + } + // Get cancelled status + const cancelledStatus = await this.statusRepo.findOne({ + where: { statusCode: 'CANCELLED' }, + }); + if (!cancelledStatus) { + throw new common_1.InternalServerErrorException('CANCELLED status not found'); + } + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + try { + // Update correspondence revision status to CANCELLED + await queryRunner.manager.update(correspondence_revision_entity_1.CorrespondenceRevision, currentRevision.id, { + statusId: cancelledStatus.id, + remarks: `Cancelled: ${reason}`, + }); + // Force close all active circulations + if (activeCirculations.length > 0) { + await queryRunner.manager.update('Circulation', { + correspondenceId: correspondence.id, + status: 'OPEN', + }, { + status: 'FORCE_CLOSED', + closedAt: new Date(), + closedBy: user.user_id, + closeReason: `Correspondence cancelled: ${reason}`, + }); + } + await queryRunner.commitTransaction(); + // Re-index cancelled status in Elasticsearch (fire-and-forget) + void this.searchService.indexDocument({ + id: correspondence.id, + publicId: correspondence.publicId, + type: 'correspondence', + docNumber: correspondence.correspondenceNumber, + title: currentRevision.subject, + status: 'CANCELLED', + projectId: correspondence.projectId, + createdAt: correspondence.createdAt, + }); + // Notify originator's doc-control user about cancellation (fire-and-forget) + if (correspondence.originatorId) { + void this.userService + .findDocControlIdByOrg(correspondence.originatorId) + .then((targetUserId) => { + if (targetUserId) { + void this.notificationService.send({ + userId: targetUserId, + title: 'Correspondence Cancelled', + message: `${correspondence.correspondenceNumber} — ${currentRevision.subject} has been cancelled. Reason: ${reason}`, + type: 'EMAIL', + entityType: 'correspondence', + entityId: correspondence.id, + link: `/correspondences/${correspondence.publicId}`, + }); + } + }) + .catch((err) => this.logger.warn(`Cancel notification failed: ${err.message}`)); + } + return { + success: true, + message: warningMessage || 'Correspondence cancelled successfully', + activeCirculationsCount: activeCirculations.length, + }; + } + catch (error) { + await queryRunner.rollbackTransaction(); + this.logger.error(`Failed to cancel correspondence: ${error.message}`); + throw error; + } + finally { + await queryRunner.release(); + } + } + async bulkCancel(publicIds, reason, user) { + const succeeded = []; + const failed = []; + for (const publicId of publicIds) { + try { + await this.cancel(publicId, reason, user); + succeeded.push(publicId); + } + catch { + failed.push(publicId); + } + } + return { succeeded, failed }; + } + async exportCsv(searchDto) { + const { data } = await this.findAll(searchDto); + const header = [ + 'Document No.', + 'Rev', + 'Subject', + 'Type', + 'Status', + 'Project', + 'From', + 'Due Date', + 'Created At', + ]; + const rows = data.map((rev) => { + const corr = rev.correspondence ?? rev; + return [ + this.escapeCsv(corr.correspondenceNumber ?? ''), + this.escapeCsv(rev.revisionLabel ?? String(rev.revisionNumber ?? 0)), + this.escapeCsv(rev.subject ?? ''), + this.escapeCsv(corr.type?.typeCode ?? ''), + this.escapeCsv(rev.status?.statusCode ?? ''), + this.escapeCsv(corr.project?.projectCode ?? ''), + this.escapeCsv(corr.originator?.organizationCode ?? ''), + rev.dueDate ? new Date(rev.dueDate).toISOString().split('T')[0] : '', + new Date(rev.createdAt).toISOString().split('T')[0], + ].join(','); + }); + return [header.join(','), ...rows].join('\n'); + } + escapeCsv(value) { + if (value.includes(',') || value.includes('"') || value.includes('\n')) { + return `"${value.replace(/"/g, '""')}"`; + } + return value; + } +}; +exports.CorrespondenceService = CorrespondenceService; +exports.CorrespondenceService = CorrespondenceService = CorrespondenceService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(correspondence_entity_1.Correspondence)), + __param(1, (0, typeorm_1.InjectRepository)(correspondence_revision_entity_1.CorrespondenceRevision)), + __param(2, (0, typeorm_1.InjectRepository)(correspondence_type_entity_1.CorrespondenceType)), + __param(3, (0, typeorm_1.InjectRepository)(correspondence_status_entity_1.CorrespondenceStatus)), + __param(4, (0, typeorm_1.InjectRepository)(correspondence_reference_entity_1.CorrespondenceReference)), + __param(5, (0, typeorm_1.InjectRepository)(correspondence_tag_entity_1.CorrespondenceTag)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object, typeof (_e = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _e : Object, typeof (_f = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _f : Object, typeof (_g = typeof document_numbering_service_1.DocumentNumberingService !== "undefined" && document_numbering_service_1.DocumentNumberingService) === "function" ? _g : Object, typeof (_h = typeof json_schema_service_1.JsonSchemaService !== "undefined" && json_schema_service_1.JsonSchemaService) === "function" ? _h : Object, typeof (_j = typeof workflow_engine_service_1.WorkflowEngineService !== "undefined" && workflow_engine_service_1.WorkflowEngineService) === "function" ? _j : Object, typeof (_k = typeof user_service_1.UserService !== "undefined" && user_service_1.UserService) === "function" ? _k : Object, typeof (_l = typeof typeorm_2.DataSource !== "undefined" && typeorm_2.DataSource) === "function" ? _l : Object, typeof (_m = typeof search_service_1.SearchService !== "undefined" && search_service_1.SearchService) === "function" ? _m : Object, typeof (_o = typeof file_storage_service_1.FileStorageService !== "undefined" && file_storage_service_1.FileStorageService) === "function" ? _o : Object, typeof (_p = typeof uuid_resolver_service_1.UuidResolverService !== "undefined" && uuid_resolver_service_1.UuidResolverService) === "function" ? _p : Object, typeof (_q = typeof notification_service_1.NotificationService !== "undefined" && notification_service_1.NotificationService) === "function" ? _q : Object]) +], CorrespondenceService); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2UudHMiLCJtYXBwaW5ncyI6IjtBQUFBLDZEQUE2RDs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFN0QsMkNBT3dCO0FBQ3hCLDZDQUFtRDtBQUNuRCxxQ0FBaUQ7QUFFakQsV0FBVztBQUNYLDRFQUFrRTtBQUNsRSw4RkFBbUY7QUFDbkYsc0ZBQTJFO0FBQzNFLDBGQUErRTtBQUMvRSxnR0FBcUY7QUFDckYsZ0dBQXFGO0FBQ3JGLG9GQUF5RTtBQUN6RSw4REFBb0Q7QUFFcEQsc0ZBQTRFO0FBUTVFLFdBQVc7QUFDWCwwR0FBcUc7QUFDckcsNEVBQXVFO0FBQ3ZFLHdGQUFtRjtBQUNuRix1REFBbUQ7QUFDbkQsNkRBQXlEO0FBQ3pELHlGQUFvRjtBQUNwRix1RkFBa0Y7QUFDbEYsK0VBQTJFO0FBVXBFLElBQU0scUJBQXFCLDZCQUEzQixNQUFNLHFCQUFxQjtJQUd4QixLQUFLLENBQUMsNEJBQTRCLENBQUMsTUFBYztRQUN2RCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEUsT0FBTyxXQUFXLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyx1QkFBdUIsQ0FBQyxRQUFnQjtRQUM5QyxNQUFNLGFBQWEsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNyQyxJQUFJLGFBQWEsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUNuRCxPQUFPLEdBQUcsQ0FBQyxDQUFDLHdCQUF3QjtRQUN0QyxDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUMsQ0FBQyxvQ0FBb0M7SUFDeEQsQ0FBQztJQUVELFlBRUUsa0JBQXNELEVBRXRELFlBQXdELEVBRXhELFFBQWdELEVB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cC1kbXNcXGxjYnAzXFxiYWNrZW5kXFxzcmNcXG1vZHVsZXNcXGNvcnJlc3BvbmRlbmNlXFxjb3JyZXNwb25kZW5jZS5zZXJ2aWNlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIEZpbGU6IHNyYy9tb2R1bGVzL2NvcnJlc3BvbmRlbmNlL2NvcnJlc3BvbmRlbmNlLnNlcnZpY2UudHNcclxuXHJcbmltcG9ydCB7XHJcbiAgSW5qZWN0YWJsZSxcclxuICBOb3RGb3VuZEV4Y2VwdGlvbixcclxuICBCYWRSZXF1ZXN0RXhjZXB0aW9uLFxyXG4gIEludGVybmFsU2VydmVyRXJyb3JFeGNlcHRpb24sXHJcbiAgRm9yYmlkZGVuRXhjZXB0aW9uLFxyXG4gIExvZ2dlcixcclxufSBmcm9tICdAbmVzdGpzL2NvbW1vbic7XHJcbmltcG9ydCB7IEluamVjdFJlcG9zaXRvcnkgfSBmcm9tICdAbmVzdGpzL3R5cGVvcm0nO1xyXG5pbXBvcnQgeyBSZXBvc2l0b3J5LCBEYXRhU291cmNlIH0gZnJvbSAndHlwZW9ybSc7XHJcblxyXG4vLyBFbnRpdGllc1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbiB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmV2aXNpb24uZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VUeXBlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS10eXBlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlU3RhdHVzIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1zdGF0dXMuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VSZWZlcmVuY2UgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXJlZmVyZW5jZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlY2lwaWVudCB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVjaXBpZW50LmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVGFnIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS10YWcuZW50aXR5JztcclxuaW1wb3J0IHsgVGFnIH0gZnJvbSAnLi4vbWFzdGVyL2VudGl0aWVzL3RhZy5lbnRpdHknO1xyXG5pbXBvcnQgeyBVc2VyIH0gZnJvbSAnLi4vdXNlci9lbnRpdGllcy91c2VyLmVudGl0eSc7XHJcbmltcG9ydCB7IE9yZ2FuaXphdGlvbiB9IGZyb20gJy4uL29yZ2FuaXphdGlvbi9lbnRpdGllcy9vcmdhbml6YXRpb24uZW50aXR5JztcclxuXHJcbi8vIERUT3NcclxuaW1wb3J0IHsgQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by9jcmVhdGUtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuaW1wb3J0IHsgVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by91cGRhdGUtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuaW1wb3J0IHsgQWRkUmVmZXJlbmNlRHRvIH0gZnJvbSAnLi9kdG8vYWRkLXJlZmVyZW5jZS5kdG8nO1xyXG5pbXBvcnQgeyBTZWFyY2hDb3JyZXNwb25kZW5jZUR0byB9IGZyb20gJy4vZHRvL3NlYXJjaC1jb3JyZXNwb25kZW5jZS5kdG8nO1xyXG5cclxuLy8gU2VydmljZXNcclxuaW1wb3J0IHsgRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlIH0gZnJvbSAnLi4vZG9jdW1lbnQtbnVtYmVyaW5nL3NlcnZpY2VzL2RvY3VtZW50LW51bWJlcmluZy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgSnNvblNjaGVtYVNlcnZpY2UgfSBmcm9tICcuLi9qc29uLXNjaGVtYS9qc29uLXNjaGVtYS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgV29ya2Zsb3dFbmdpbmVTZXJ2aWNlIH0gZnJvbSAnLi4vd29ya2Zsb3ctZW5naW5lL3dvcmtmbG93LWVuZ2luZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXNlclNlcnZpY2UgfSBmcm9tICcuLi91c2VyL3VzZXIuc2VydmljZSc7XHJcbmltcG9ydCB7IFNlYXJjaFNlcnZpY2UgfSBmcm9tICcuLi9zZWFyY2gvc2VhcmNoLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBGaWxlU3RvcmFnZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vZmlsZS1zdG9yYWdlL2ZpbGUtc3RvcmFnZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXVpZFJlc29sdmVyU2VydmljZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9zZXJ2aWNlcy91dWlkLXJlc29sdmVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBOb3RpZmljYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vbm90aWZpY2F0aW9uL25vdGlmaWNhdGlvbi5zZXJ2aWNlJztcclxuXHJcbi8qKlxyXG4gKiBDb3JyZXNwb25kZW5jZVNlcnZpY2UgLSBEb2N1bWVudCBtYW5hZ2VtZW50IChDUlVEKVxyXG4gKi9cclxuaW50ZXJmYWNlIFJlc29sdmVkUmVjaXBpZW50IHtcclxuICBvcmdhbml6YXRpb25JZDogbnVtYmVyO1xyXG4gIHR5cGU6ICdUTycgfCAnQ0MnO1xyXG59XHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIENvcnJlc3BvbmRlbmNlU2VydmljZSB7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXIgPSBuZXcgTG9nZ2VyKENvcnJlc3BvbmRlbmNlU2VydmljZS5uYW1lKTtcclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBoYXNTeXN0ZW1NYW5hZ2VBbGxQZXJtaXNzaW9uKHVzZXJJZDogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XHJcbiAgICBjb25zdCBwZXJtaXNzaW9ucyA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZ2V0VXNlclBlcm1pc3Npb25zKHVzZXJJZCk7XHJcbiAgICByZXR1cm4gcGVybWlzc2lvbnMuaW5jbHVkZXMoJ3N5c3RlbS5tYW5hZ2VfYWxsJyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBCdXNpbmVzcyBSdWxlOiBSZXZpc2lvbiBMYWJlbCBTdHJhdGVneVxyXG4gICAqIC0gUkZBLCBSRkk6IFVzZSBhbHBoYWJldCBzdGFydGluZyB3aXRoICdBJyAoQSwgQiwgQy4uLilcclxuICAgKiAtIE90aGVyIHR5cGVzIChMRVRURVIsIE1FTU8sIGV0Yy4pOiBVc2UgbnVtZXJpYyAobnVsbCBmb3IgZmlyc3QsIHRoZW4gMSwgMiwgMy4uLilcclxuICAgKi9cclxuICBwcml2YXRlIGdldEluaXRpYWxSZXZpc2lvbkxhYmVsKHR5cGVDb2RlOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xyXG4gICAgY29uc3QgYWxwaGFiZXRUeXBlcyA9IFsnUkZBJywgJ1JGSSddO1xyXG4gICAgaWYgKGFscGhhYmV0VHlwZXMuaW5jbHVkZXModHlwZUNvZGUudG9VcHBlckNhc2UoKSkpIHtcclxuICAgICAgcmV0dXJuICdBJzsgLy8gQWxwaGFiZXQgZm9yIFJGQSwgUkZJXHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkOyAvLyBOdW1lcmljIChubyBsYWJlbCBmb3IgcmV2aXNpb24gMClcclxuICB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgQEluamVjdFJlcG9zaXRvcnkoQ29ycmVzcG9uZGVuY2UpXHJcbiAgICBwcml2YXRlIGNvcnJlc3BvbmRlbmNlUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZT4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVJldmlzaW9uKVxyXG4gICAgcHJpdmF0ZSByZXZpc2lvblJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VSZXZpc2lvbj4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICBwcml2YXRlIHR5cGVSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgIHByaXZhdGUgc3RhdHVzUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVJlZmVyZW5jZSlcclxuICAgIHByaXZhdGUgcmVmZXJlbmNlUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVJlZmVyZW5jZT4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVRhZylcclxuICAgIHByaXZhdGUgdGFnUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVRhZz4sXHJcbiAgICBwcml2YXRlIG51bWJlcmluZ1NlcnZpY2U6IERvY3VtZW50TnVtYmVyaW5nU2VydmljZSxcclxuICAgIHByaXZhdGUganNvblNjaGVtYVNlcnZpY2U6IEpzb25TY2hlbWFTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB3b3JrZmxvd0VuZ2luZTogV29ya2Zsb3dFbmdpbmVTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB1c2VyU2VydmljZTogVXNlclNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGRhdGFTb3VyY2U6IERhdGFTb3VyY2UsXHJcbiAgICBwcml2YXRlIHNlYXJjaFNlcnZpY2U6IFNlYXJjaFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGZpbGVTdG9yYWdlU2VydmljZTogRmlsZVN0b3JhZ2VTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB1dWlkUmVzb2x2ZXI6IFV1aWRSZXNvbHZlclNlcnZpY2UsXHJcbiAgICBwcml2YXRlIG5vdGlmaWNhdGlvblNlcnZpY2U6IE5vdGlmaWNhdGlvblNlcnZpY2VcclxuICApIHt9XHJcblxyXG4gIC8qKlxyXG4gICAqIEJ1c2luZXNzIFJ1bGUgVmFsaWRhdGlvbjogRUMtQ09SUi0wMDMgLSBDb3JyZXNwb25kZW5jZSB0byBTZWxmXHJcbiAgICogUHJldmVudCBleHRlcm5hbCBjb3JyZXNwb25kZW5jZSB0byBzYW1lIG9yZ2FuaXphdGlvblxyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgdmFsaWRhdGVDb3JyZXNwb25kZW5jZVJlY2lwaWVudHMoXHJcbiAgICBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvLFxyXG4gICAgdXNlcjogVXNlclxyXG4gICk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgLy8gR2V0IHVzZXIncyBvcmdhbml6YXRpb25cclxuICAgIGxldCB1c2VyT3JnSWQgPSB1c2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgIGNvbnN0IGZ1bGxVc2VyID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS5maW5kT25lKHVzZXIudXNlcl9pZCk7XHJcbiAgICAgIGlmIChmdWxsVXNlcikge1xyXG4gICAgICAgIHVzZXJPcmdJZCA9IGZ1bGxVc2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgIGlmIChjcmVhdGVEdG8ub3JpZ2luYXRvcklkKSB7XHJcbiAgICAgICAgY29uc3QgY2FuTWFuYWdlQWxsID0gYXdhaXQgdGhpcy5oYXNTeXN0ZW1NYW5hZ2VBbGxQZXJtaXNzaW9uKFxyXG4gICAgICAgICAgdXNlci51c2VyX2lkXHJcbiAgICAgICAgKTtcclxuICAgICAgICBpZiAoY2FuTWFuYWdlQWxsKSB7XHJcbiAgICAgICAgICB1c2VyT3JnSWQgPSBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoXHJcbiAgICAgICAgICAgIGNyZWF0ZUR0by5vcmlnaW5hdG9ySWRcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoIXVzZXJPcmdJZCkge1xyXG4gICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxyXG4gICAgICAgICAgJ1VzZXIgbXVzdCBiZWxvbmcgdG8gYW4gb3JnYW5pemF0aW9uIHRvIGNyZWF0ZSBkb2N1bWVudHMnXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIEZvciBpbXBlcnNvbmF0aW9uLCB1c2UgdGhlIHNwZWNpZmllZCBvcmlnaW5hdG9yXHJcbiAgICBjb25zdCBvcmlnaW5hdG9yT3JnSWQgPSBjcmVhdGVEdG8ub3JpZ2luYXRvcklkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKGNyZWF0ZUR0by5vcmlnaW5hdG9ySWQpXHJcbiAgICAgIDogdXNlck9yZ0lkO1xyXG5cclxuICAgIC8vIENoZWNrIGlmIGl0J3MgaW50ZXJuYWwgY29tbXVuaWNhdGlvblxyXG4gICAgaWYgKGNyZWF0ZUR0by5pc0ludGVybmFsKSB7XHJcbiAgICAgIC8vIEludGVybmFsIGNvbW11bmljYXRpb25zIHNob3VsZCB1c2UgQ2lyY3VsYXRpb24gaW5zdGVhZFxyXG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcclxuICAgICAgICAnSW50ZXJuYWwgY29tbXVuaWNhdGlvbnMgc2hvdWxkIHVzZSBDaXJjdWxhdGlvbiBTaGVldCBpbnN0ZWFkIG9mIENvcnJlc3BvbmRlbmNlJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFZhbGlkYXRlIHJlY2lwaWVudHNcclxuICAgIGlmICghY3JlYXRlRHRvLnJlY2lwaWVudHMgfHwgY3JlYXRlRHRvLnJlY2lwaWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxyXG4gICAgICAgICdBdCBsZWFzdCBvbmUgcmVjaXBpZW50IChUTyBvciBDQykgaXMgcmVxdWlyZWQnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgdG9SZWNpcGllbnRzID0gY3JlYXRlRHRvLnJlY2lwaWVudHMuZmlsdGVyKChyKSA9PiByLnR5cGUgPT09ICdUTycpO1xyXG4gICAgY29uc3QgY2NSZWNpcGllbnRzID0gY3JlYXRlRHRvLnJlY2lwaWVudHMuZmlsdGVyKChyKSA9PiByLnR5cGUgPT09ICdDQycpO1xyXG5cclxuICAgIGlmICh0b1JlY2lwaWVudHMubGVuZ3RoID09PSAwICYmIGNjUmVjaXBpZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgJ0F0IGxlYXN0IG9uZSBUTyBvciBDQyByZWNpcGllbnQgaXMgcmVxdWlyZWQnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgZm9yIHNhbWUgb3JnYW5pemF0aW9uIGNvcnJlc3BvbmRlbmNlXHJcbiAgICBmb3IgKGNvbnN0IHJlY2lwaWVudCBvZiBjcmVhdGVEdG8ucmVjaXBpZW50cykge1xyXG4gICAgICBjb25zdCByZWNpcGllbnRPcmdJZCA9IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChcclxuICAgICAgICByZWNpcGllbnQub3JnYW5pemF0aW9uSWRcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGlmIChyZWNpcGllbnRPcmdJZCA9PT0gb3JpZ2luYXRvck9yZ0lkKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgICAnQ2Fubm90IHNlbmQgY29ycmVzcG9uZGVuY2UgdG8geW91ciBvd24gb3JnYW5pemF0aW9uLiBVc2UgQ2lyY3VsYXRpb24gU2hlZXQgZm9yIGludGVybmFsIGNvbW11bmljYXRpb24uJ1xyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGNyZWF0ZShjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvLCB1c2VyOiBVc2VyKSB7XHJcbiAgICAvLyBCdXNpbmVzcyBSdWxlIFZhbGlkYXRpb246IEVDLUNPUlItMDAzIC0gQ29ycmVzcG9uZGVuY2UgdG8gU2VsZlxyXG4gICAgYXdhaXQgdGhpcy52YWxpZGF0ZUNvcnJlc3BvbmRlbmNlUmVjaXBpZW50cyhjcmVhdGVEdG8sIHVzZXIpO1xyXG4gICAgLy8gQURSLTAxOTogUmVzb2x2ZSBVVUlEIHJlZmVyZW5jZXMgdG8gaW50ZXJuYWwgSU5UIElEc1xyXG4gICAgY29uc3QgcmVzb2x2ZWRQcm9qZWN0SWQgPSBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkKFxyXG4gICAgICBjcmVhdGVEdG8ucHJvamVjdElkXHJcbiAgICApO1xyXG4gICAgY29uc3QgcmVzb2x2ZWRPcmlnaW5hdG9ySWQgPSBjcmVhdGVEdG8ub3JpZ2luYXRvcklkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKGNyZWF0ZUR0by5vcmlnaW5hdG9ySWQpXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgcmVzb2x2ZWRSZWNpcGllbnRzID0gY3JlYXRlRHRvLnJlY2lwaWVudHNcclxuICAgICAgPyBhd2FpdCBQcm9taXNlLmFsbChcclxuICAgICAgICAgIGNyZWF0ZUR0by5yZWNpcGllbnRzLm1hcChcclxuICAgICAgICAgICAgYXN5bmMgKHIpOiBQcm9taXNlPFJlc29sdmVkUmVjaXBpZW50PiA9PiAoe1xyXG4gICAgICAgICAgICAgIG9yZ2FuaXphdGlvbklkOiBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoXHJcbiAgICAgICAgICAgICAgICByLm9yZ2FuaXphdGlvbklkXHJcbiAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICB0eXBlOiByLnR5cGUsXHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICApXHJcbiAgICAgICAgKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuICAgIGNvbnN0IHR5cGUgPSBhd2FpdCB0aGlzLnR5cGVSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZDogY3JlYXRlRHRvLnR5cGVJZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIXR5cGUpIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignRG9jdW1lbnQgVHlwZSBub3QgZm91bmQnKTtcclxuXHJcbiAgICBjb25zdCBzdGF0dXNEcmFmdCA9IGF3YWl0IHRoaXMuc3RhdHVzUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgc3RhdHVzQ29kZTogJ0RSQUZUJyB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIXN0YXR1c0RyYWZ0KSB7XHJcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbFNlcnZlckVycm9yRXhjZXB0aW9uKFxyXG4gICAgICAgICdTdGF0dXMgRFJBRlQgbm90IGZvdW5kIGluIE1hc3RlciBEYXRhJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCB1c2VyT3JnSWQgPSB1c2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICBpZiAoIXVzZXJPcmdJZCkge1xyXG4gICAgICBjb25zdCBmdWxsVXNlciA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZmluZE9uZSh1c2VyLnVzZXJfaWQpO1xyXG4gICAgICBpZiAoZnVsbFVzZXIpIHtcclxuICAgICAgICB1c2VyT3JnSWQgPSBmdWxsVXNlci5wcmltYXJ5T3JnYW5pemF0aW9uSWQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBJbXBlcnNvbmF0aW9uIExvZ2ljXHJcbiAgICBpZiAocmVzb2x2ZWRPcmlnaW5hdG9ySWQgJiYgcmVzb2x2ZWRPcmlnaW5hdG9ySWQgIT09IHVzZXJPcmdJZCkge1xyXG4gICAgICBjb25zdCBjYW5NYW5hZ2VBbGwgPSBhd2FpdCB0aGlzLmhhc1N5c3RlbU1hbmFnZUFsbFBlcm1pc3Npb24oXHJcbiAgICAgICAgdXNlci51c2VyX2lkXHJcbiAgICAgICk7XHJcbiAgICAgIGlmICghY2FuTWFuYWdlQWxsKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEZvcmJpZGRlbkV4Y2VwdGlvbihcclxuICAgICAgICAgICdZb3UgZG8gbm90IGhhdmUgcGVybWlzc2lvbiB0byBjcmVhdGUgZG9jdW1lbnRzIG9uIGJlaGFsZiBvZiBvdGhlciBvcmdhbml6YXRpb25zLidcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICAgIHVzZXJPcmdJZCA9IHJlc29sdmVkT3JpZ2luYXRvcklkO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxyXG4gICAgICAgICdVc2VyIG11c3QgYmVsb25nIHRvIGFuIG9yZ2FuaXphdGlvbiB0byBjcmVhdGUgZG9jdW1lbnRzJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChjcmVhdGVEdG8uZGV0YWlscykge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGF3YWl0IHRoaXMuanNvblNjaGVtYVNlcnZpY2UudmFsaWRhdGUodHlwZS50eXBlQ29kZSwgY3JlYXRlRHRvLmRldGFpbHMpO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xyXG4gICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXHJcbiAgICAgICAgICBgU2NoZW1hIHZhbGlkYXRpb24gd2FybmluZyBmb3IgJHt0eXBlLnR5cGVDb2RlfTogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YFxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHRoaXMuZGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lcigpO1xyXG4gICAgYXdhaXQgcXVlcnlSdW5uZXIuY29ubmVjdCgpO1xyXG4gICAgYXdhaXQgcXVlcnlSdW5uZXIuc3RhcnRUcmFuc2FjdGlvbigpO1xyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIC8vIFtGaXggIzZdIEZldGNoIHJlYWwgT1JHIENvZGUgZnJvbSBPcmdhbml6YXRpb24gZW50aXR5XHJcbiAgICAgIGNvbnN0IG9yaWdpbmF0b3JPcmcgPSBhd2FpdCB0aGlzLmRhdGFTb3VyY2UubWFuYWdlci5maW5kT25lKFxyXG4gICAgICAgIE9yZ2FuaXphdGlvbixcclxuICAgICAgICB7XHJcbiAgICAgICAgICB3aGVyZTogeyBpZDogdXNlck9yZ0lkIH0sXHJcbiAgICAgICAgfVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBvcmdDb2RlID0gb3JpZ2luYXRvck9yZz8ub3JnYW5pemF0aW9uQ29kZSA/PyAnVU5LJztcclxuXHJcbiAgICAgIC8vIFt2MS41LjFdIEV4dHJhY3QgcmVjaXBpZW50IG9yZ2FuaXphdGlvbiBmcm9tIHJlY2lwaWVudHMgYXJyYXkgKFByaW1hcnkgVE8pXHJcbiAgICAgIGNvbnN0IHRvUmVjaXBpZW50ID0gcmVzb2x2ZWRSZWNpcGllbnRzPy5maW5kKChyKSA9PiByLnR5cGUgPT09ICdUTycpO1xyXG4gICAgICBjb25zdCByZWNpcGllbnRPcmdhbml6YXRpb25JZCA9IHRvUmVjaXBpZW50Py5vcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICAgIGxldCByZWNpcGllbnRDb2RlID0gJyc7XHJcbiAgICAgIGlmIChyZWNpcGllbnRPcmdhbml6YXRpb25JZCkge1xyXG4gICAgICAgIGNvbnN0IHJlY09yZyA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoT3JnYW5pemF0aW9uLCB7XHJcbiAgICAgICAgICB3aGVyZTogeyBpZDogcmVjaXBpZW50T3JnYW5pemF0aW9uSWQgfSxcclxuICAgICAgICB9KTtcclxuICAgICAgICBpZiAocmVjT3JnKSByZWNpcGllbnRDb2RlID0gcmVjT3JnLm9yZ2FuaXphdGlvbkNvZGU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGRvY051bWJlciA9IGF3YWl0IHRoaXMubnVtYmVyaW5nU2VydmljZS5nZW5lcmF0ZU5leHROdW1iZXIoe1xyXG4gICAgICAgIHByb2plY3RJZDogcmVzb2x2ZWRQcm9qZWN0SWQsXHJcbiAgICAgICAgb3JpZ2luYXRvck9yZ2FuaXphdGlvbklkOiB1c2VyT3JnSWQsXHJcbiAgICAgICAgdHlwZUlkOiBjcmVhdGVEdG8udHlwZUlkLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogY3JlYXRlRHRvLmRpc2NpcGxpbmVJZCxcclxuICAgICAgICBzdWJUeXBlSWQ6IGNyZWF0ZUR0by5zdWJUeXBlSWQsXHJcbiAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQsIC8vIFt2MS41LjFdIFBhc3MgcmVjaXBpZW50IGZvciBkb2N1bWVudCBudW1iZXIgZm9ybWF0XHJcbiAgICAgICAgeWVhcjogbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpLFxyXG4gICAgICAgIGN1c3RvbVRva2Vuczoge1xyXG4gICAgICAgICAgVFlQRV9DT0RFOiB0eXBlLnR5cGVDb2RlLFxyXG4gICAgICAgICAgT1JHX0NPREU6IG9yZ0NvZGUsXHJcbiAgICAgICAgICBSRUNJUElFTlRfQ09ERTogcmVjaXBpZW50Q29kZSxcclxuICAgICAgICAgIFJFQ19DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgY29uc3QgY29ycmVzcG9uZGVuY2UgPSBxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZShDb3JyZXNwb25kZW5jZSwge1xyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiBkb2NOdW1iZXIubnVtYmVyLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiBjcmVhdGVEdG8udHlwZUlkLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogY3JlYXRlRHRvLmRpc2NpcGxpbmVJZCxcclxuICAgICAgICBwcm9qZWN0SWQ6IHJlc29sdmVkUHJvamVjdElkLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogdXNlck9yZ0lkLFxyXG4gICAgICAgIGlzSW50ZXJuYWw6IGNyZWF0ZUR0by5pc0ludGVybmFsIHx8IGZhbHNlLFxyXG4gICAgICAgIGNyZWF0ZWRCeTogdXNlci51c2VyX2lkLFxyXG4gICAgICB9KTtcclxuICAgICAgY29uc3Qgc2F2ZWRDb3JyID0gYXdhaXQgcXVlcnlSdW5uZXIubWFuYWdlci5zYXZlKGNvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIGNvbnN0IHJldmlzaW9uID0gcXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUoQ29ycmVzcG9uZGVuY2VSZXZpc2lvbiwge1xyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IHNhdmVkQ29yci5pZCxcclxuICAgICAgICByZXZpc2lvbk51bWJlcjogMCxcclxuICAgICAgICByZXZpc2lvbkxhYmVsOiB0aGlzLmdldEluaXRpYWxSZXZpc2lvbkxhYmVsKHR5cGUudHlwZUNvZGUpLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogc3RhdHVzRHJhZnQuaWQsXHJcbiAgICAgICAgc3ViamVjdDogY3JlYXRlRHRvLnN1YmplY3QsXHJcbiAgICAgICAgYm9keTogY3JlYXRlRHRvLmJvZHksXHJcbiAgICAgICAgcmVtYXJrczogY3JlYXRlRHRvLnJlbWFya3MsXHJcbiAgICAgICAgZHVlRGF0ZTogY3JlYXRlRHRvLmR1ZURhdGUgPyBuZXcgRGF0ZShjcmVhdGVEdG8uZHVlRGF0ZSkgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgZG9jdW1lbnREYXRlOiBjcmVhdGVEdG8uZG9jdW1lbnREYXRlXHJcbiAgICAgICAgICA/IG5ldyBEYXRlKGNyZWF0ZUR0by5kb2N1bWVudERhdGUpXHJcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcclxuICAgICAgICBpc3N1ZWREYXRlOiBjcmVhdGVEdG8uaXNzdWVkRGF0ZVxyXG4gICAgICAgICAgPyBuZXcgRGF0ZShjcmVhdGVEdG8uaXNzdWVkRGF0ZSlcclxuICAgICAgICAgIDogdW5kZWZpbmVkLFxyXG4gICAgICAgIHJlY2VpdmVkRGF0ZTogY3JlYXRlRHRvLnJlY2VpdmVkRGF0ZVxyXG4gICAgICAgICAgPyBuZXcgRGF0ZShjcmVhdGVEdG8ucmVjZWl2ZWREYXRlKVxyXG4gICAgICAgICAgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgZGVzY3JpcHRpb246IGNyZWF0ZUR0by5kZXNjcmlwdGlvbixcclxuICAgICAgICBkZXRhaWxzOiBjcmVhdGVEdG8uZGV0YWlscyxcclxuICAgICAgICBjcmVhdGVkQnk6IHVzZXIudXNlcl9pZCxcclxuICAgICAgICBzY2hlbWFWZXJzaW9uOiAxLFxyXG4gICAgICB9KTtcclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIubWFuYWdlci5zYXZlKHJldmlzaW9uKTtcclxuXHJcbiAgICAgIC8vIFNhdmUgUmVjaXBpZW50cyAodXNpbmcgcmVzb2x2ZWQgSU5UIElEcylcclxuICAgICAgaWYgKHJlc29sdmVkUmVjaXBpZW50cyAmJiByZXNvbHZlZFJlY2lwaWVudHMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSByZXNvbHZlZFJlY2lwaWVudHMubWFwKChyKSA9PlxyXG4gICAgICAgICAgcXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUoQ29ycmVzcG9uZGVuY2VSZWNpcGllbnQsIHtcclxuICAgICAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogc2F2ZWRDb3JyLmlkLFxyXG4gICAgICAgICAgICByZWNpcGllbnRPcmdhbml6YXRpb25JZDogci5vcmdhbml6YXRpb25JZCxcclxuICAgICAgICAgICAgcmVjaXBpZW50VHlwZTogci50eXBlLFxyXG4gICAgICAgICAgfSlcclxuICAgICAgICApO1xyXG4gICAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLm1hbmFnZXIuc2F2ZShyZWNpcGllbnRzKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gQ29tbWl0IGF0dGFjaG1lbnRzIGZyb20gVGVtcCDihpIgUGVybWFuZW50IChUd28tUGhhc2UgU3RvcmFnZSlcclxuICAgICAgaWYgKGNyZWF0ZUR0by5hdHRhY2htZW50VGVtcElkcz8ubGVuZ3RoKSB7XHJcbiAgICAgICAgY29uc3QgaXNzdWVEYXRlID0gY3JlYXRlRHRvLmlzc3VlZERhdGVcclxuICAgICAgICAgID8gbmV3IERhdGUoY3JlYXRlRHRvLmlzc3VlZERhdGUpXHJcbiAgICAgICAgICA6IGNyZWF0ZUR0by5kb2N1bWVudERhdGVcclxuICAgICAgICAgICAgPyBuZXcgRGF0ZShjcmVhdGVEdG8uZG9jdW1lbnREYXRlKVxyXG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgICAgYXdhaXQgdGhpcy5maWxlU3RvcmFnZVNlcnZpY2UuY29tbWl0KGNyZWF0ZUR0by5hdHRhY2htZW50VGVtcElkcywge1xyXG4gICAgICAgICAgaXNzdWVEYXRlLFxyXG4gICAgICAgICAgZG9jdW1lbnRUeXBlOiAnQ29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBhd2FpdCBxdWVyeVJ1bm5lci5jb21taXRUcmFuc2FjdGlvbigpO1xyXG5cclxuICAgICAgLy8gU3RhcnQgV29ya2Zsb3cgSW5zdGFuY2UgKG5vbi1ibG9ja2luZylcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCB3b3JrZmxvd0NvZGUgPSBgQ09SUkVTUE9OREVOQ0VfJHt0eXBlLnR5cGVDb2RlfWA7XHJcbiAgICAgICAgYXdhaXQgdGhpcy53b3JrZmxvd0VuZ2luZS5jcmVhdGVJbnN0YW5jZShcclxuICAgICAgICAgIHdvcmtmbG93Q29kZSxcclxuICAgICAgICAgICdjb3JyZXNwb25kZW5jZScsXHJcbiAgICAgICAgICBzYXZlZENvcnIuaWQudG9TdHJpbmcoKSxcclxuICAgICAgICAgIHtcclxuICAgICAgICAgICAgcHJvamVjdElkOiByZXNvbHZlZFByb2plY3RJZCxcclxuICAgICAgICAgICAgb3JpZ2luYXRvcklkOiB1c2VyT3JnSWQsXHJcbiAgICAgICAgICAgIGRpc2NpcGxpbmVJZDogY3JlYXRlRHRvLmRpc2NpcGxpbmVJZCxcclxuICAgICAgICAgICAgaW5pdGlhdG9ySWQ6IHVzZXIudXNlcl9pZCxcclxuICAgICAgICAgIH0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj5cclxuICAgICAgICApO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xyXG4gICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXHJcbiAgICAgICAgICBgV29ya2Zsb3cgbm90IHN0YXJ0ZWQgZm9yICR7ZG9jTnVtYmVyLm51bWJlcn0gKENvZGU6IENPUlJFU1BPTkRFTkNFXyR7dHlwZS50eXBlQ29kZX0pOiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gRmlyZS1hbmQtZm9yZ2V0IHNlYXJjaCBpbmRleGluZyAobm9uLWJsb2NraW5nLCB2b2lkIGludGVudGlvbmFsKVxyXG4gICAgICB2b2lkIHRoaXMuc2VhcmNoU2VydmljZS5pbmRleERvY3VtZW50KHtcclxuICAgICAgICBpZDogc2F2ZWRDb3JyLmlkLFxyXG4gICAgICAgIHB1YmxpY0lkOiBzYXZlZENvcnIucHVibGljSWQsXHJcbiAgICAgICAgdHlwZTogJ2NvcnJlc3BvbmRlbmNlJyxcclxuICAgICAgICBkb2NOdW1iZXI6IGRvY051bWJlci5udW1iZXIsXHJcbiAgICAgICAgdGl0bGU6IGNyZWF0ZUR0by5zdWJqZWN0LFxyXG4gICAgICAgIGRlc2NyaXB0aW9uOiBjcmVhdGVEdG8uZGVzY3JpcHRpb24sXHJcbiAgICAgICAgc3RhdHVzOiAnRFJBRlQnLFxyXG4gICAgICAgIHByb2plY3RJZDogcmVzb2x2ZWRQcm9qZWN0SWQsXHJcbiAgICAgICAgY3JlYXRlZEF0OiBuZXcgRGF0ZSgpLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAgLi4uc2F2ZWRDb3JyLFxyXG4gICAgICAgIGN1cnJlbnRSZXZpc2lvbjogcmV2aXNpb24sXHJcbiAgICAgIH07XHJcbiAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIucm9sbGJhY2tUcmFuc2FjdGlvbigpO1xyXG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcclxuICAgICAgICBgRmFpbGVkIHRvIGNyZWF0ZSBjb3JyZXNwb25kZW5jZTogJHsoZXJyIGFzIEVycm9yKS5tZXNzYWdlfWBcclxuICAgICAgKTtcclxuICAgICAgdGhyb3cgZXJyO1xyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIucmVsZWFzZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgZmluZEFsbChzZWFyY2hEdG86IFNlYXJjaENvcnJlc3BvbmRlbmNlRHRvID0ge30pIHtcclxuICAgIGNvbnN0IHtcclxuICAgICAgc2VhcmNoLFxyXG4gICAgICB0eXBlSWQsXHJcbiAgICAgIHByb2plY3RJZCxcclxuICAgICAgc3RhdHVzSWQsXHJcbiAgICAgIHN0YXR1cyxcclxuICAgICAgcGFnZSA9IDEsXHJcbiAgICAgIGxpbWl0ID0gMTAsXHJcbiAgICB9ID0gc2VhcmNoRHRvO1xyXG4gICAgY29uc3Qgc2tpcCA9IChwYWdlIC0gMSkgKiBsaW1pdDtcclxuXHJcbiAgICAvLyBDaGFuZ2U6IFF1ZXJ5IGZyb20gUmV2aXNpb24gUmVwb1xyXG4gICAgY29uc3QgcXVlcnkgPSB0aGlzLnJldmlzaW9uUmVwb1xyXG4gICAgICAuY3JlYXRlUXVlcnlCdWlsZGVyKCdyZXYnKVxyXG4gICAgICAubGVmdEpvaW5BbmRTZWxlY3QoJ3Jldi5jb3JyZXNwb25kZW5jZScsICdjb3JyJylcclxuICAgICAgLmxlZnRKb2luQW5kU2VsZWN0KCdjb3JyLnR5cGUnLCAndHlwZScpXHJcbiAgICAgIC5sZWZ0Sm9pbkFuZFNlbGVjdCgnY29yci5wcm9qZWN0JywgJ3Byb2plY3QnKVxyXG4gICAgICAubGVmdEpvaW5BbmRTZWxlY3QoJ2NvcnIub3JpZ2luYXRvcicsICdvcmcnKVxyXG4gICAgICAubGVmdEpvaW5BbmRTZWxlY3QoJ3Jldi5zdGF0dXMnLCAnc3RhdHVzJyk7XHJcblxyXG4gICAgLy8gRmlsdGVyIGJ5IFJldmlzaW9uIFN0YXR1c1xyXG4gICAgY29uc3QgcmV2U3RhdHVzID0gc2VhcmNoRHRvLnJldmlzaW9uU3RhdHVzIHx8ICdDVVJSRU5UJztcclxuXHJcbiAgICBpZiAocmV2U3RhdHVzID09PSAnQ1VSUkVOVCcpIHtcclxuICAgICAgcXVlcnkud2hlcmUoJ3Jldi5pc0N1cnJlbnQgPSA6aXNDdXJyZW50JywgeyBpc0N1cnJlbnQ6IHRydWUgfSk7XHJcbiAgICB9IGVsc2UgaWYgKHJldlN0YXR1cyA9PT0gJ09MRCcpIHtcclxuICAgICAgcXVlcnkud2hlcmUoJ3Jldi5pc0N1cnJlbnQgPSA6aXNDdXJyZW50JywgeyBpc0N1cnJlbnQ6IGZhbHNlIH0pO1xyXG4gICAgfVxyXG4gICAgLy8gSWYgJ0FMTCcsIG5vIGZpbHRlciBuZWVkZWQgb24gaXNDdXJyZW50XHJcblxyXG4gICAgaWYgKHByb2plY3RJZCkge1xyXG4gICAgICBxdWVyeS5hbmRXaGVyZSgnY29yci5wcm9qZWN0SWQgPSA6cHJvamVjdElkJywgeyBwcm9qZWN0SWQgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGVJZCkge1xyXG4gICAgICBxdWVyeS5hbmRXaGVyZSgnY29yci5jb3JyZXNwb25kZW5jZVR5cGVJZCA9IDp0eXBlSWQnLCB7IHR5cGVJZCB9KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoc3RhdHVzSWQpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoJ3Jldi5zdGF0dXNJZCA9IDpzdGF0dXNJZCcsIHsgc3RhdHVzSWQgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHN0YXR1cykge1xyXG4gICAgICBxdWVyeS5hbmRXaGVyZSgnc3RhdHVzLnN0YXR1c0NvZGUgPSA6c3RhdHVzJywgeyBzdGF0dXMgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHNlYXJjaCkge1xyXG4gICAgICBxdWVyeS5hbmRXaGVyZShcclxuICAgICAgICAnKGNvcnIuY29ycmVzcG9uZGVuY2VOdW1iZXIgTElLRSA6c2VhcmNoIE9SIHJldi5zdWJqZWN0IExJS0UgOnNlYXJjaCknLFxyXG4gICAgICAgIHsgc2VhcmNoOiBgJSR7c2VhcmNofSVgIH1cclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBEZWZhdWx0IFNvcnQ6IExhdGVzdCBDcmVhdGVkXHJcbiAgICBxdWVyeS5vcmRlckJ5KCdyZXYuY3JlYXRlZEF0JywgJ0RFU0MnKS5za2lwKHNraXApLnRha2UobGltaXQpO1xyXG5cclxuICAgIGNvbnN0IFtpdGVtcywgdG90YWxdID0gYXdhaXQgcXVlcnkuZ2V0TWFueUFuZENvdW50KCk7XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgZGF0YTogaXRlbXMsXHJcbiAgICAgIG1ldGE6IHtcclxuICAgICAgICB0b3RhbCxcclxuICAgICAgICBwYWdlLFxyXG4gICAgICAgIGxpbWl0LFxyXG4gICAgICAgIHRvdGFsUGFnZXM6IE1hdGguY2VpbCh0b3RhbCAvIGxpbWl0KSxcclxuICAgICAgfSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBhc3luYyBmaW5kT25lKGlkOiBudW1iZXIpIHtcclxuICAgIGNvbnN0IGNvcnJlc3BvbmRlbmNlID0gYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IGlkIH0sXHJcbiAgICAgIHJlbGF0aW9uczogW1xyXG4gICAgICAgICdyZXZpc2lvbnMnLFxyXG4gICAgICAgICdyZXZpc2lvbnMuc3RhdHVzJyxcclxuICAgICAgICAndHlwZScsXHJcbiAgICAgICAgJ3Byb2plY3QnLFxyXG4gICAgICAgICdvcmlnaW5hdG9yJyxcclxuICAgICAgICAncmVjaXBpZW50cycsXHJcbiAgICAgICAgJ3JlY2lwaWVudHMucmVjaXBpZW50T3JnYW5pemF0aW9uJywgLy8gW3YxLjUuMV0gRml4ZWQgcmVsYXRpb24gbmFtZVxyXG4gICAgICBdLFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKCFjb3JyZXNwb25kZW5jZSkge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oYENvcnJlc3BvbmRlbmNlIHdpdGggSUQgJHtpZH0gbm90IGZvdW5kYCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gY29ycmVzcG9uZGVuY2U7XHJcbiAgfVxyXG5cclxuICBhc3luYyBmaW5kT25lQnlVdWlkKHB1YmxpY0lkOiBzdHJpbmcpIHtcclxuICAgIGNvbnN0IGNvcnJlc3BvbmRlbmNlID0gYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IHB1YmxpY0lkIH0sXHJcbiAgICAgIHJlbGF0aW9uczogW1xyXG4gICAgICAgICdyZXZpc2lvbnMnLFxyXG4gICAgICAgICdyZXZpc2lvbnMuc3RhdHVzJyxcclxuICAgICAgICAndHlwZScsXHJcbiAgICAgICAgJ3Byb2plY3QnLFxyXG4gICAgICAgICdvcmlnaW5hdG9yJyxcclxuICAgICAgICAncmVjaXBpZW50cycsXHJcbiAgICAgICAgJ3JlY2lwaWVudHMucmVjaXBpZW50T3JnYW5pemF0aW9uJyxcclxuICAgICAgXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghY29ycmVzcG9uZGVuY2UpIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFxyXG4gICAgICAgIGBDb3JyZXNwb25kZW5jZSB3aXRoIFVVSUQgJHtwdWJsaWNJZH0gbm90IGZvdW5kYFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGNvcnJlc3BvbmRlbmNlO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgYWRkUmVmZXJlbmNlKGlkOiBudW1iZXIsIGR0bzogQWRkUmVmZXJlbmNlRHRvKSB7XHJcbiAgICBjb25zdCBzb3VyY2UgPSBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby5maW5kT25lKHsgd2hlcmU6IHsgaWQgfSB9KTtcclxuICAgIC8vIEFEUi0wMTk6IFJlc29sdmUgdGFyZ2V0IHB1YmxpY0lkIOKGkiBpbnRlcm5hbCBJTlQgaWRcclxuICAgIGNvbnN0IHRhcmdldCA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBwdWJsaWNJZDogZHRvLnRhcmdldFV1aWQgfSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghc291cmNlIHx8ICF0YXJnZXQpIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdTb3VyY2Ugb3IgVGFyZ2V0IGNvcnJlc3BvbmRlbmNlIG5vdCBmb3VuZCcpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChzb3VyY2UuaWQgPT09IHRhcmdldC5pZCkge1xyXG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbignQ2Fubm90IHJlZmVyZW5jZSBzZWxmJyk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgZXhpc3RzID0gYXdhaXQgdGhpcy5yZWZlcmVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZToge1xyXG4gICAgICAgIHNvdXJjZUlkOiBpZCxcclxuICAgICAgICB0YXJnZXRJZDogdGFyZ2V0LmlkLFxyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKGV4aXN0cykge1xyXG4gICAgICByZXR1cm4gZXhpc3RzO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHJlZiA9IHRoaXMucmVmZXJlbmNlUmVwby5jcmVhdGUoe1xyXG4gICAgICBzb3VyY2VJZDogaWQsXHJcbiAgICAgIHRhcmdldElkOiB0YXJnZXQuaWQsXHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gdGhpcy5yZWZlcmVuY2VSZXBvLnNhdmUocmVmKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHJlbW92ZVJlZmVyZW5jZShpZDogbnVtYmVyLCB0YXJnZXRJZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJlZmVyZW5jZVJlcG8uZGVsZXRlKHtcclxuICAgICAgc291cmNlSWQ6IGlkLFxyXG4gICAgICB0YXJnZXRJZDogdGFyZ2V0SWQsXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAocmVzdWx0LmFmZmVjdGVkID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignUmVmZXJlbmNlIG5vdCBmb3VuZCcpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgZ2V0VGFncyhpZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCByb3dzID0gYXdhaXQgdGhpcy50YWdSZXBvLmZpbmQoe1xyXG4gICAgICB3aGVyZTogeyBjb3JyZXNwb25kZW5jZUlkOiBpZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFsndGFnJ10sXHJcbiAgICB9KTtcclxuICAgIHJldHVybiByb3dzLm1hcCgocikgPT4gci50YWcpLmZpbHRlcihCb29sZWFuKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGFkZFRhZyhpZDogbnVtYmVyLCB0YWdJZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCBjb3JyZXNwb25kZW5jZSA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIWNvcnJlc3BvbmRlbmNlKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihgQ29ycmVzcG9uZGVuY2UgJHtpZH0gbm90IGZvdW5kYCk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgdGFnID0gYXdhaXQgdGhpcy5kYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZShUYWcsIHtcclxuICAgICAgd2hlcmU6IHsgaWQ6IHRhZ0lkIH0sXHJcbiAgICB9KTtcclxuICAgIGlmICghdGFnKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihgVGFnICR7dGFnSWR9IG5vdCBmb3VuZGApO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGV4aXN0cyA9IGF3YWl0IHRoaXMudGFnUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgY29ycmVzcG9uZGVuY2VJZDogaWQsIHRhZ0lkIH0sXHJcbiAgICB9KTtcclxuICAgIGlmIChleGlzdHMpIHJldHVybiBleGlzdHM7XHJcblxyXG4gICAgY29uc3Qgcm93ID0gdGhpcy50YWdSZXBvLmNyZWF0ZSh7IGNvcnJlc3BvbmRlbmNlSWQ6IGlkLCB0YWdJZCB9KTtcclxuICAgIHJldHVybiB0aGlzLnRhZ1JlcG8uc2F2ZShyb3cpO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgcmVtb3ZlVGFnKGlkOiBudW1iZXIsIHRhZ0lkOiBudW1iZXIpIHtcclxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMudGFnUmVwby5kZWxldGUoeyBjb3JyZXNwb25kZW5jZUlkOiBpZCwgdGFnSWQgfSk7XHJcbiAgICBpZiAocmVzdWx0LmFmZmVjdGVkID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignVGFnIGFzc2lnbm1lbnQgbm90IGZvdW5kJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBnZXRSZWZlcmVuY2VzKGlkOiBudW1iZXIpIHtcclxuICAgIGNvbnN0IG91dGdvaW5nID0gYXdhaXQgdGhpcy5yZWZlcmVuY2VSZXBvLmZpbmQoe1xyXG4gICAgICB3aGVyZTogeyBzb3VyY2VJZDogaWQgfSxcclxuICAgICAgcmVsYXRpb25zOiBbJ3RhcmdldCcsICd0YXJnZXQudHlwZSddLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgaW5jb21pbmcgPSBhd2FpdCB0aGlzLnJlZmVyZW5jZVJlcG8uZmluZCh7XHJcbiAgICAgIHdoZXJlOiB7IHRhcmdldElkOiBpZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFsnc291cmNlJywgJ3NvdXJjZS50eXBlJ10sXHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4geyBvdXRnb2luZywgaW5jb21pbmcgfTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHVwZGF0ZShpZDogbnVtYmVyLCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvLCB1c2VyOiBVc2VyKSB7XHJcbiAgICAvLyAxLiBGaW5kIEN1cnJlbnQgUmV2aXNpb25cclxuICAgIGNvbnN0IHJldmlzaW9uID0gYXdhaXQgdGhpcy5yZXZpc2lvblJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogaWQsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICB9LFxyXG4gICAgICByZWxhdGlvbnM6IFsnY29ycmVzcG9uZGVuY2UnXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghcmV2aXNpb24pIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFxyXG4gICAgICAgIGBDdXJyZW50IHJldmlzaW9uIGZvciBjb3JyZXNwb25kZW5jZSAke2lkfSBub3QgZm91bmRgXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gMi4gQ2hlY2sgUGVybWlzc2lvblxyXG4gICAgaWYgKHJldmlzaW9uLnN0YXR1c0lkKSB7XHJcbiAgICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IHRoaXMuc3RhdHVzUmVwby5maW5kT25lKHtcclxuICAgICAgICB3aGVyZTogeyBpZDogcmV2aXNpb24uc3RhdHVzSWQgfSxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBpZiAoc3RhdHVzICYmIHN0YXR1cy5zdGF0dXNDb2RlICE9PSAnRFJBRlQnKSB7XHJcbiAgICAgICAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyhcclxuICAgICAgICAgIHVzZXIudXNlcl9pZFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgY29uc3QgY2FuRWRpdFN1Ym1pdHRlZE9yTGF0ZXIgPVxyXG4gICAgICAgICAgcGVybWlzc2lvbnMuaW5jbHVkZXMoJ2NvcnJlc3BvbmRlbmNlLmNhbmNlbCcpIHx8XHJcbiAgICAgICAgICBwZXJtaXNzaW9ucy5pbmNsdWRlcygnc3lzdGVtLm1hbmFnZV9hbGwnKTtcclxuXHJcbiAgICAgICAgaWYgKCFjYW5FZGl0U3VibWl0dGVkT3JMYXRlcikge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IEZvcmJpZGRlbkV4Y2VwdGlvbihcclxuICAgICAgICAgICAgJ09ubHkgT3JnIEFkbWluIG9yIFN1cGVyYWRtaW4gY2FuIGVkaXQgbm9uLWRyYWZ0IGNvcnJlc3BvbmRlbmNlcydcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQURSLTAxOTogUmVzb2x2ZSBVVUlEIHJlZmVyZW5jZXMgaW4gdXBkYXRlIERUT1xyXG4gICAgY29uc3QgdXBkUmVzb2x2ZWRQcm9qZWN0SWQgPSB1cGRhdGVEdG8ucHJvamVjdElkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCh1cGRhdGVEdG8ucHJvamVjdElkKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuICAgIGNvbnN0IHVwZFJlc29sdmVkT3JpZ2luYXRvcklkID0gdXBkYXRlRHRvLm9yaWdpbmF0b3JJZFxyXG4gICAgICA/IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZCh1cGRhdGVEdG8ub3JpZ2luYXRvcklkKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuICAgIGNvbnN0IHVwZFJlc29sdmVkUmVjaXBpZW50cyA9IHVwZGF0ZUR0by5yZWNpcGllbnRzXHJcbiAgICAgID8gYXdhaXQgUHJvbWlzZS5hbGwoXHJcbiAgICAgICAgICB1cGRhdGVEdG8ucmVjaXBpZW50cy5tYXAoXHJcbiAgICAgICAgICAgIGFzeW5jIChyKTogUHJvbWlzZTxSZXNvbHZlZFJlY2lwaWVudD4gPT4gKHtcclxuICAgICAgICAgICAgICBvcmdhbml6YXRpb25JZDogYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKFxyXG4gICAgICAgICAgICAgICAgci5vcmdhbml6YXRpb25JZFxyXG4gICAgICAgICAgICAgICksXHJcbiAgICAgICAgICAgICAgdHlwZTogci50eXBlLFxyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICAgKVxyXG4gICAgICAgIClcclxuICAgICAgOiB1bmRlZmluZWQ7XHJcblxyXG4gICAgLy8gMy4gVXBkYXRlIENvcnJlc3BvbmRlbmNlIEVudGl0eSBpZiBuZWVkZWRcclxuICAgIGNvbnN0IGNvcnJlc3BvbmRlbmNlVXBkYXRlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xyXG4gICAgaWYgKHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQpXHJcbiAgICAgIGNvcnJlc3BvbmRlbmNlVXBkYXRlLmRpc2NpcGxpbmVJZCA9IHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQ7XHJcbiAgICBpZiAodXBkUmVzb2x2ZWRQcm9qZWN0SWQpXHJcbiAgICAgIGNvcnJlc3BvbmRlbmNlVXBkYXRlLnByb2plY3RJZCA9IHVwZFJlc29sdmVkUHJvamVjdElkO1xyXG4gICAgaWYgKHVwZFJlc29sdmVkT3JpZ2luYXRvcklkKVxyXG4gICAgICBjb3JyZXNwb25kZW5jZVVwZGF0ZS5vcmlnaW5hdG9ySWQgPSB1cGRSZXNvbHZlZE9yaWdpbmF0b3JJZDtcclxuXHJcbiAgICBpZiAoT2JqZWN0LmtleXMoY29ycmVzcG9uZGVuY2VVcGRhdGUpLmxlbmd0aCA+IDApIHtcclxuICAgICAgYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8udXBkYXRlKGlkLCBjb3JyZXNwb25kZW5jZVVwZGF0ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gNC4gVXBkYXRlIFJldmlzaW9uIEVudGl0eVxyXG4gICAgY29uc3QgcmV2aXNpb25VcGRhdGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XHJcbiAgICBpZiAodXBkYXRlRHRvLnN1YmplY3QpIHJldmlzaW9uVXBkYXRlLnN1YmplY3QgPSB1cGRhdGVEdG8uc3ViamVjdDtcclxuICAgIGlmICh1cGRhdGVEdG8uYm9keSkgcmV2aXNpb25VcGRhdGUuYm9keSA9IHVwZGF0ZUR0by5ib2R5O1xyXG4gICAgaWYgKHVwZGF0ZUR0by5yZW1hcmtzKSByZXZpc2lvblVwZGF0ZS5yZW1hcmtzID0gdXBkYXRlRHRvLnJlbWFya3M7XHJcbiAgICAvLyBGb3JtYXQgRGF0ZSBjb3JyZWN0bHkgaWYgc3RyaW5nXHJcbiAgICBpZiAodXBkYXRlRHRvLmR1ZURhdGUpIHJldmlzaW9uVXBkYXRlLmR1ZURhdGUgPSBuZXcgRGF0ZSh1cGRhdGVEdG8uZHVlRGF0ZSk7XHJcbiAgICBpZiAodXBkYXRlRHRvLmRvY3VtZW50RGF0ZSlcclxuICAgICAgcmV2aXNpb25VcGRhdGUuZG9jdW1lbnREYXRlID0gbmV3IERhdGUodXBkYXRlRHRvLmRvY3VtZW50RGF0ZSk7XHJcbiAgICBpZiAodXBkYXRlRHRvLmlzc3VlZERhdGUpXHJcbiAgICAgIHJldmlzaW9uVXBkYXRlLmlzc3VlZERhdGUgPSBuZXcgRGF0ZSh1cGRhdGVEdG8uaXNzdWVkRGF0ZSk7XHJcbiAgICBpZiAodXBkYXRlRHRvLnJlY2VpdmVkRGF0ZSlcclxuICAgICAgcmV2aXNpb25VcGRhdGUucmVjZWl2ZWREYXRlID0gbmV3IERhdGUodXBkYXRlRHRvLnJlY2VpdmVkRGF0ZSk7XHJcbiAgICBpZiAodXBkYXRlRHRvLmRlc2NyaXB0aW9uKVxyXG4gICAgICByZXZpc2lvblVwZGF0ZS5kZXNjcmlwdGlvbiA9IHVwZGF0ZUR0by5kZXNjcmlwdGlvbjtcclxuICAgIGlmICh1cGRhdGVEdG8uZGV0YWlscykgcmV2aXNpb25VcGRhdGUuZGV0YWlscyA9IHVwZGF0ZUR0by5kZXRhaWxzO1xyXG5cclxuICAgIGlmIChPYmplY3Qua2V5cyhyZXZpc2lvblVwZGF0ZSkubGVuZ3RoID4gMCkge1xyXG4gICAgICBhd2FpdCB0aGlzLnJldmlzaW9uUmVwby51cGRhdGUocmV2aXNpb24uaWQsIHJldmlzaW9uVXBkYXRlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA0LjUgQ29tbWl0IG5ldyBhdHRhY2htZW50cyBmcm9tIFRlbXAg4oaSIFBlcm1hbmVudCAoVHdvLVBoYXNlIFN0b3JhZ2UpXHJcbiAgICBpZiAodXBkYXRlRHRvLmF0dGFjaG1lbnRUZW1wSWRzPy5sZW5ndGgpIHtcclxuICAgICAgY29uc3QgaXNzdWVEYXRlID0gdXBkYXRlRHRvLmlzc3VlZERhdGVcclxuICAgICAgICA/IG5ldyBEYXRlKHVwZGF0ZUR0by5pc3N1ZWREYXRlKVxyXG4gICAgICAgIDogdXBkYXRlRHRvLmRvY3VtZW50RGF0ZVxyXG4gICAgICAgICAgPyBuZXcgRGF0ZSh1cGRhdGVEdG8uZG9jdW1lbnREYXRlKVxyXG4gICAgICAgICAgOiByZXZpc2lvbi5pc3N1ZWREYXRlIHx8IHJldmlzaW9uLmRvY3VtZW50RGF0ZSB8fCB1bmRlZmluZWQ7XHJcblxyXG4gICAgICBhd2FpdCB0aGlzLmZpbGVTdG9yYWdlU2VydmljZS5jb21taXQodXBkYXRlRHRvLmF0dGFjaG1lbnRUZW1wSWRzLCB7XHJcbiAgICAgICAgaXNzdWVEYXRlOiBpc3N1ZURhdGUgPyBuZXcgRGF0ZShpc3N1ZURhdGUpIDogdW5kZWZpbmVkLFxyXG4gICAgICAgIGRvY3VtZW50VHlwZTogJ0NvcnJlc3BvbmRlbmNlJyxcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gNS4gVXBkYXRlIFJlY2lwaWVudHMgaWYgcHJvdmlkZWRcclxuICAgIGlmICh1cGRSZXNvbHZlZFJlY2lwaWVudHMpIHtcclxuICAgICAgY29uc3QgcmVjaXBpZW50UmVwbyA9IHRoaXMuZGF0YVNvdXJjZS5nZXRSZXBvc2l0b3J5KFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmVjaXBpZW50XHJcbiAgICAgICk7XHJcbiAgICAgIGF3YWl0IHJlY2lwaWVudFJlcG8uZGVsZXRlKHsgY29ycmVzcG9uZGVuY2VJZDogaWQgfSk7XHJcblxyXG4gICAgICBjb25zdCBuZXdSZWNpcGllbnRzID0gdXBkUmVzb2x2ZWRSZWNpcGllbnRzLm1hcCgocikgPT5cclxuICAgICAgICByZWNpcGllbnRSZXBvLmNyZWF0ZSh7XHJcbiAgICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiBpZCxcclxuICAgICAgICAgIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiByLm9yZ2FuaXphdGlvbklkLFxyXG4gICAgICAgICAgcmVjaXBpZW50VHlwZTogci50eXBlLFxyXG4gICAgICAgIH0pXHJcbiAgICAgICk7XHJcbiAgICAgIGF3YWl0IHJlY2lwaWVudFJlcG8uc2F2ZShuZXdSZWNpcGllbnRzKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA2LiBSZWdlbmVyYXRlIERvY3VtZW50IE51bWJlciBpZiBzdHJ1Y3R1cmFsIGZpZWxkcyBjaGFuZ2VkIChSZWNpcGllbnQsIERpc2NpcGxpbmUsIFR5cGUsIFByb2plY3QpXHJcbiAgICAvLyBBTkQgaXQgaXMgYSBEUkFGVC5cclxuXHJcbiAgICAvLyBGZXRjaCBmcmVzaCBkYXRhIGZvciBjb250ZXh0IGFuZCBjb21wYXJpc29uXHJcbiAgICBjb25zdCBjdXJyZW50Q29yciA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFsndHlwZScsICdyZWNpcGllbnRzJywgJ3JlY2lwaWVudHMucmVjaXBpZW50T3JnYW5pemF0aW9uJ10sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoY3VycmVudENvcnIpIHtcclxuICAgICAgY29uc3QgY3VycmVudFRvUmVjaXBpZW50ID0gY3VycmVudENvcnIucmVjaXBpZW50cz8uZmluZChcclxuICAgICAgICAocikgPT4gci5yZWNpcGllbnRUeXBlID09PSAnVE8nXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRSZWNpcGllbnRJZCA9IGN1cnJlbnRUb1JlY2lwaWVudD8ucmVjaXBpZW50T3JnYW5pemF0aW9uSWQ7XHJcblxyXG4gICAgICAvLyBDaGVjayBmb3IgQUNUVUFMIHZhbHVlIGNoYW5nZXNcclxuICAgICAgY29uc3QgaXNQcm9qZWN0Q2hhbmdlZCA9XHJcbiAgICAgICAgdXBkUmVzb2x2ZWRQcm9qZWN0SWQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHVwZFJlc29sdmVkUHJvamVjdElkICE9PSBjdXJyZW50Q29yci5wcm9qZWN0SWQ7XHJcbiAgICAgIGNvbnN0IGlzT3JpZ2luYXRvckNoYW5nZWQgPVxyXG4gICAgICAgIHVwZFJlc29sdmVkT3JpZ2luYXRvcklkICE9PSB1bmRlZmluZWQgJiZcclxuICAgICAgICB1cGRSZXNvbHZlZE9yaWdpbmF0b3JJZCAhPT0gY3VycmVudENvcnIub3JpZ2luYXRvcklkO1xyXG4gICAgICBjb25zdCBpc0Rpc2NpcGxpbmVDaGFuZ2VkID1cclxuICAgICAgICB1cGRhdGVEdG8uZGlzY2lwbGluZUlkICE9PSB1bmRlZmluZWQgJiZcclxuICAgICAgICB1cGRhdGVEdG8uZGlzY2lwbGluZUlkICE9PSBjdXJyZW50Q29yci5kaXNjaXBsaW5lSWQ7XHJcbiAgICAgIGNvbnN0IGlzVHlwZUNoYW5nZWQgPVxyXG4gICAgICAgIHVwZGF0ZUR0by50eXBlSWQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHVwZGF0ZUR0by50eXBlSWQgIT09IGN1cnJlbnRDb3JyLmNvcnJlc3BvbmRlbmNlVHlwZUlkO1xyXG5cclxuICAgICAgbGV0IGlzUmVjaXBpZW50Q2hhbmdlZCA9IGZhbHNlO1xyXG4gICAgICBsZXQgbmV3UmVjaXBpZW50SWQ6IG51bWJlciB8IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgIGlmICh1cGRSZXNvbHZlZFJlY2lwaWVudHMpIHtcclxuICAgICAgICBjb25zdCBuZXdUb1JlY2lwaWVudCA9IHVwZFJlc29sdmVkUmVjaXBpZW50cy5maW5kKFxyXG4gICAgICAgICAgKHIpID0+IHIudHlwZSA9PT0gJ1RPJ1xyXG4gICAgICAgICk7XHJcbiAgICAgICAgbmV3UmVjaXBpZW50SWQgPSBuZXdUb1JlY2lwaWVudD8ub3JnYW5pemF0aW9uSWQ7XHJcblxyXG4gICAgICAgIGlmIChuZXdSZWNpcGllbnRJZCAhPT0gY3VycmVudFJlY2lwaWVudElkKSB7XHJcbiAgICAgICAgICBpc1JlY2lwaWVudENoYW5nZWQgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKFxyXG4gICAgICAgIGlzUHJvamVjdENoYW5nZWQgfHxcclxuICAgICAgICBpc0Rpc2NpcGxpbmVDaGFuZ2VkIHx8XHJcbiAgICAgICAgaXNUeXBlQ2hhbmdlZCB8fFxyXG4gICAgICAgIGlzUmVjaXBpZW50Q2hhbmdlZCB8fFxyXG4gICAgICAgIGlzT3JpZ2luYXRvckNoYW5nZWRcclxuICAgICAgKSB7XHJcbiAgICAgICAgY29uc3QgdGFyZ2V0UmVjaXBpZW50SWQgPSBpc1JlY2lwaWVudENoYW5nZWRcclxuICAgICAgICAgID8gbmV3UmVjaXBpZW50SWRcclxuICAgICAgICAgIDogY3VycmVudFJlY2lwaWVudElkO1xyXG5cclxuICAgICAgICAvLyBSZXNvbHZlIFJlY2lwaWVudCBDb2RlIGZvciB0aGUgTkVXIGNvbnRleHRcclxuICAgICAgICBsZXQgcmVjaXBpZW50Q29kZSA9ICcnO1xyXG4gICAgICAgIGlmICh0YXJnZXRSZWNpcGllbnRJZCkge1xyXG4gICAgICAgICAgY29uc3QgcmVjT3JnID0gYXdhaXQgdGhpcy5kYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZShPcmdhbml6YXRpb24sIHtcclxuICAgICAgICAgICAgd2hlcmU6IHsgaWQ6IHRhcmdldFJlY2lwaWVudElkIH0sXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICAgIGlmIChyZWNPcmcpIHJlY2lwaWVudENvZGUgPSByZWNPcmcub3JnYW5pemF0aW9uQ29kZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFtGaXggIzZdIEZldGNoIHJlYWwgT1JHIENvZGUgZnJvbSBvcmlnaW5hdG9yIG9yZ2FuaXphdGlvblxyXG4gICAgICAgIGNvbnN0IG9yaWdpbmF0b3JPcmdGb3JVcGRhdGUgPSBhd2FpdCB0aGlzLmRhdGFTb3VyY2UubWFuYWdlci5maW5kT25lKFxyXG4gICAgICAgICAgT3JnYW5pemF0aW9uLFxyXG4gICAgICAgICAge1xyXG4gICAgICAgICAgICB3aGVyZToge1xyXG4gICAgICAgICAgICAgIGlkOiB1cGRSZXNvbHZlZE9yaWdpbmF0b3JJZCA/PyBjdXJyZW50Q29yci5vcmlnaW5hdG9ySWQgPz8gMCxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgIH1cclxuICAgICAgICApO1xyXG4gICAgICAgIGNvbnN0IG9yZ0NvZGUgPSBvcmlnaW5hdG9yT3JnRm9yVXBkYXRlPy5vcmdhbml6YXRpb25Db2RlID8/ICdVTksnO1xyXG5cclxuICAgICAgICAvLyBQcmVwYXJlIENvbnRleHRzXHJcbiAgICAgICAgY29uc3Qgb2xkQ3R4ID0ge1xyXG4gICAgICAgICAgcHJvamVjdElkOiBjdXJyZW50Q29yci5wcm9qZWN0SWQsXHJcbiAgICAgICAgICBvcmlnaW5hdG9yT3JnYW5pemF0aW9uSWQ6IGN1cnJlbnRDb3JyLm9yaWdpbmF0b3JJZCA/PyAwLFxyXG4gICAgICAgICAgdHlwZUlkOiBjdXJyZW50Q29yci5jb3JyZXNwb25kZW5jZVR5cGVJZCxcclxuICAgICAgICAgIGRpc2NpcGxpbmVJZDogY3VycmVudENvcnIuZGlzY2lwbGluZUlkLFxyXG4gICAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IGN1cnJlbnRSZWNpcGllbnRJZCxcclxuICAgICAgICAgIHllYXI6IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKSxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBuZXdDdHggPSB7XHJcbiAgICAgICAgICBwcm9qZWN0SWQ6IHVwZFJlc29sdmVkUHJvamVjdElkID8/IGN1cnJlbnRDb3JyLnByb2plY3RJZCxcclxuICAgICAgICAgIG9yaWdpbmF0b3JPcmdhbml6YXRpb25JZDpcclxuICAgICAgICAgICAgdXBkUmVzb2x2ZWRPcmlnaW5hdG9ySWQgPz8gY3VycmVudENvcnIub3JpZ2luYXRvcklkID8/IDAsXHJcbiAgICAgICAgICB0eXBlSWQ6IHVwZGF0ZUR0by50eXBlSWQgPz8gY3VycmVudENvcnIuY29ycmVzcG9uZGVuY2VUeXBlSWQsXHJcbiAgICAgICAgICBkaXNjaXBsaW5lSWQ6IHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQgPz8gY3VycmVudENvcnIuZGlzY2lwbGluZUlkLFxyXG4gICAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IHRhcmdldFJlY2lwaWVudElkLFxyXG4gICAgICAgICAgeWVhcjogbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpLFxyXG4gICAgICAgICAgdXNlcklkOiB1c2VyLnVzZXJfaWQsIC8vIFBhc3MgVXNlciBJRCBmb3IgQXVkaXRcclxuICAgICAgICAgIGN1c3RvbVRva2Vuczoge1xyXG4gICAgICAgICAgICBUWVBFX0NPREU6IGN1cnJlbnRDb3JyLnR5cGU/LnR5cGVDb2RlIHx8ICcnLFxyXG4gICAgICAgICAgICBPUkdfQ09ERTogb3JnQ29kZSxcclxuICAgICAgICAgICAgUkVDSVBJRU5UX0NPREU6IHJlY2lwaWVudENvZGUsXHJcbiAgICAgICAgICAgIFJFQ19DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvLyBJZiBUeXBlIENoYW5nZWQsIG5lZWQgTkVXIFR5cGUgQ29kZVxyXG4gICAgICAgIGlmIChpc1R5cGVDaGFuZ2VkKSB7XHJcbiAgICAgICAgICBjb25zdCBuZXdUeXBlID0gYXdhaXQgdGhpcy50eXBlUmVwby5maW5kT25lKHtcclxuICAgICAgICAgICAgd2hlcmU6IHsgaWQ6IG5ld0N0eC50eXBlSWQgfSxcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgaWYgKG5ld1R5cGUpIG5ld0N0eC5jdXN0b21Ub2tlbnMuVFlQRV9DT0RFID0gbmV3VHlwZS50eXBlQ29kZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld0RvY051bWJlciA9IGF3YWl0IHRoaXMubnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdChcclxuICAgICAgICAgIGN1cnJlbnRDb3JyLmNvcnJlc3BvbmRlbmNlTnVtYmVyLFxyXG4gICAgICAgICAgb2xkQ3R4LFxyXG4gICAgICAgICAgbmV3Q3R4XHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8udXBkYXRlKGlkLCB7XHJcbiAgICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogbmV3RG9jTnVtYmVyLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgdXBkYXRlZCA9IGF3YWl0IHRoaXMuZmluZE9uZShpZCk7XHJcblxyXG4gICAgLy8gUmUtaW5kZXggdXBkYXRlZCBkb2N1bWVudCBpbiBFbGFzdGljc2VhcmNoIChmaXJlLWFuZC1mb3JnZXQpXHJcbiAgICB2b2lkIHRoaXMuc2VhcmNoU2VydmljZS5pbmRleERvY3VtZW50KHtcclxuICAgICAgaWQ6IHVwZGF0ZWQuaWQsXHJcbiAgICAgIHB1YmxpY0lkOiB1cGRhdGVkLnB1YmxpY0lkLFxyXG4gICAgICB0eXBlOiAnY29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICBkb2NOdW1iZXI6IHVwZGF0ZWQuY29ycmVzcG9uZGVuY2VOdW1iZXIsXHJcbiAgICAgIHRpdGxlOiB1cGRhdGVEdG8uc3ViamVjdCA/PyB1cGRhdGVkLnJldmlzaW9ucz8uWzBdPy5zdWJqZWN0LFxyXG4gICAgICBkZXNjcmlwdGlvbjogdXBkYXRlRHRvLmRlc2NyaXB0aW9uID8/IHVwZGF0ZWQucmV2aXNpb25zPy5bMF0/LmRlc2NyaXB0aW9uLFxyXG4gICAgICBzdGF0dXM6ICdEUkFGVCcsXHJcbiAgICAgIHByb2plY3RJZDogdXBkYXRlZC5wcm9qZWN0SWQsXHJcbiAgICAgIGNyZWF0ZWRBdDogdXBkYXRlZC5jcmVhdGVkQXQsXHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gdXBkYXRlZDtcclxuICB9XHJcblxyXG4gIGFzeW5jIHByZXZpZXdEb2N1bWVudE51bWJlcihjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvLCB1c2VyOiBVc2VyKSB7XHJcbiAgICAvLyBBRFItMDE5OiBSZXNvbHZlIFVVSUQgcmVmZXJlbmNlc1xyXG4gICAgY29uc3QgcHJldmlld1Byb2plY3RJZCA9IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQoXHJcbiAgICAgIGNyZWF0ZUR0by5wcm9qZWN0SWRcclxuICAgICk7XHJcbiAgICBjb25zdCBwcmV2aWV3T3JpZ2luYXRvcklkID0gY3JlYXRlRHRvLm9yaWdpbmF0b3JJZFxyXG4gICAgICA/IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChjcmVhdGVEdG8ub3JpZ2luYXRvcklkKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuICAgIGNvbnN0IHByZXZpZXdSZWNpcGllbnRzID0gY3JlYXRlRHRvLnJlY2lwaWVudHNcclxuICAgICAgPyBhd2FpdCBQcm9taXNlLmFsbChcclxuICAgICAgICAgIGNyZWF0ZUR0by5yZWNpcGllbnRzLm1hcChcclxuICAgICAgICAgICAgYXN5bmMgKHIpOiBQcm9taXNlPFJlc29sdmVkUmVjaXBpZW50PiA9PiAoe1xyXG4gICAgICAgICAgICAgIG9yZ2FuaXphdGlvbklkOiBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoXHJcbiAgICAgICAgICAgICAgICByLm9yZ2FuaXphdGlvbklkXHJcbiAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICB0eXBlOiByLnR5cGUsXHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICApXHJcbiAgICAgICAgKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuXHJcbiAgICBjb25zdCB0eXBlID0gYXdhaXQgdGhpcy50eXBlUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgaWQ6IGNyZWF0ZUR0by50eXBlSWQgfSxcclxuICAgIH0pO1xyXG4gICAgaWYgKCF0eXBlKSB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oJ0RvY3VtZW50IFR5cGUgbm90IGZvdW5kJyk7XHJcblxyXG4gICAgbGV0IHVzZXJPcmdJZCA9IHVzZXIucHJpbWFyeU9yZ2FuaXphdGlvbklkO1xyXG4gICAgaWYgKCF1c2VyT3JnSWQpIHtcclxuICAgICAgY29uc3QgZnVsbFVzZXIgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmZpbmRPbmUodXNlci51c2VyX2lkKTtcclxuICAgICAgaWYgKGZ1bGxVc2VyKSB1c2VyT3JnSWQgPSBmdWxsVXNlci5wcmltYXJ5T3JnYW5pemF0aW9uSWQ7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHByZXZpZXdPcmlnaW5hdG9ySWQgJiYgcHJldmlld09yaWdpbmF0b3JJZCAhPT0gdXNlck9yZ0lkKSB7XHJcbiAgICAgIC8vIEFsbG93IGltcGVyc29uYXRpb24gZm9yIHByZXZpZXdcclxuICAgICAgdXNlck9yZ0lkID0gcHJldmlld09yaWdpbmF0b3JJZDtcclxuICAgIH1cclxuXHJcbiAgICAvLyBFeHRyYWN0IHJlY2lwaWVudCBmcm9tIHJlY2lwaWVudHMgYXJyYXlcclxuICAgIGNvbnN0IHRvUmVjaXBpZW50ID0gcHJldmlld1JlY2lwaWVudHM/LmZpbmQoKHIpID0+IHIudHlwZSA9PT0gJ1RPJyk7XHJcbiAgICBjb25zdCByZWNpcGllbnRPcmdhbml6YXRpb25JZCA9IHRvUmVjaXBpZW50Py5vcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICBsZXQgcmVjaXBpZW50Q29kZSA9ICcnO1xyXG4gICAgaWYgKHJlY2lwaWVudE9yZ2FuaXphdGlvbklkKSB7XHJcbiAgICAgIGNvbnN0IHJlY09yZyA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoT3JnYW5pemF0aW9uLCB7XHJcbiAgICAgICAgd2hlcmU6IHsgaWQ6IHJlY2lwaWVudE9yZ2FuaXphdGlvbklkIH0sXHJcbiAgICAgIH0pO1xyXG4gICAgICBpZiAocmVjT3JnKSByZWNpcGllbnRDb2RlID0gcmVjT3JnLm9yZ2FuaXphdGlvbkNvZGU7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMubnVtYmVyaW5nU2VydmljZS5wcmV2aWV3TnVtYmVyKHtcclxuICAgICAgcHJvamVjdElkOiBwcmV2aWV3UHJvamVjdElkLFxyXG4gICAgICBvcmlnaW5hdG9yT3JnYW5pemF0aW9uSWQ6IHVzZXJPcmdJZCEsXHJcbiAgICAgIHR5cGVJZDogY3JlYXRlRHRvLnR5cGVJZCxcclxuICAgICAgZGlzY2lwbGluZUlkOiBjcmVhdGVEdG8uZGlzY2lwbGluZUlkLFxyXG4gICAgICBzdWJUeXBlSWQ6IGNyZWF0ZUR0by5zdWJUeXBlSWQsXHJcbiAgICAgIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkLFxyXG4gICAgICB5ZWFyOiBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCksXHJcbiAgICAgIGN1c3RvbVRva2Vuczoge1xyXG4gICAgICAgIFRZUEVfQ09ERTogdHlwZS50eXBlQ29kZSxcclxuICAgICAgICBSRUNJUElFTlRfQ09ERTogcmVjaXBpZW50Q29kZSxcclxuICAgICAgICBSRUNfQ09ERTogcmVjaXBpZW50Q29kZSxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQnVzaW5lc3MgUnVsZSBJbXBsZW1lbnRhdGlvbjogRUMtQ09SUi0wMDEgLSBDYW5jZWwgQ29ycmVzcG9uZGVuY2Ugd2l0aCBEb3duc3RyZWFtIENpcmN1bGF0aW9uXHJcbiAgICogQ2FuY2VsIGNvcnJlc3BvbmRlbmNlIGFuZCBoYW5kbGUgcmVsYXRlZCBjaXJjdWxhdGlvbnNcclxuICAgKi9cclxuICBhc3luYyBjYW5jZWwocHVibGljSWQ6IHN0cmluZywgcmVhc29uOiBzdHJpbmcsIHVzZXI6IFVzZXIpIHtcclxuICAgIGNvbnN0IGNvcnJlc3BvbmRlbmNlID0gYXdhaXQgdGhpcy5maW5kT25lQnlVdWlkKHB1YmxpY0lkKTtcclxuXHJcbiAgICAvLyBDaGVjayBpZiB1c2VyIGhhcyBwZXJtaXNzaW9uIHRvIGNhbmNlbCAoT3JnIEFkbWluIG9yIFN1cGVyYWRtaW4gb25seSlcclxuICAgIGNvbnN0IHBlcm1pc3Npb25zID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS5nZXRVc2VyUGVybWlzc2lvbnModXNlci51c2VyX2lkKTtcclxuICAgIGNvbnN0IGNhbkNhbmNlbCA9XHJcbiAgICAgIHBlcm1pc3Npb25zLmluY2x1ZGVzKCdjb3JyZXNwb25kZW5jZS5jYW5jZWwnKSB8fFxyXG4gICAgICBwZXJtaXNzaW9ucy5pbmNsdWRlcygnc3lzdGVtLm1hbmFnZV9hbGwnKTtcclxuXHJcbiAgICBpZiAoIWNhbkNhbmNlbCkge1xyXG4gICAgICB0aHJvdyBuZXcgRm9yYmlkZGVuRXhjZXB0aW9uKFxyXG4gICAgICAgICdPbmx5IGFkbWluaXN0cmF0b3JzIGNhbiBjYW5jZWwgY29ycmVzcG9uZGVuY2VzJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENoZWNrIGlmIHRoZXJlIGFyZSBhbnkgYWN0aXZlIGNpcmN1bGF0aW9uc1xyXG4gICAgY29uc3QgY2lyY3VsYXRpb25SZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkoJ0NpcmN1bGF0aW9uJyk7XHJcbiAgICBjb25zdCBhY3RpdmVDaXJjdWxhdGlvbnMgPSBhd2FpdCBjaXJjdWxhdGlvblJlcG8uZmluZCh7XHJcbiAgICAgIHdoZXJlOiB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogY29ycmVzcG9uZGVuY2UuaWQsXHJcbiAgICAgICAgc3RhdHVzOiAnT1BFTicsXHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCB3YXJuaW5nTWVzc2FnZSA9XHJcbiAgICAgIGFjdGl2ZUNpcmN1bGF0aW9ucy5sZW5ndGggPiAwXHJcbiAgICAgICAgPyBgVGhlcmUgYXJlICR7YWN0aXZlQ2lyY3VsYXRpb25zLmxlbmd0aH0gYWN0aXZlIGNpcmN1bGF0aW9uKHMpIGZvciB0aGlzIGNvcnJlc3BvbmRlbmNlLiBDYW5jZWxpbmcgd2lsbCBmb3JjZSBjbG9zZSBhbGwgcmVsYXRlZCBjaXJjdWxhdGlvbnMuYFxyXG4gICAgICAgIDogJyc7XHJcblxyXG4gICAgLy8gR2V0IHRoZSBjdXJyZW50IHJldmlzaW9uIHRvIHVwZGF0ZSBzdGF0dXNcclxuICAgIGNvbnN0IGN1cnJlbnRSZXZpc2lvbiA9IGF3YWl0IHRoaXMucmV2aXNpb25SZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZToge1xyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IGNvcnJlc3BvbmRlbmNlLmlkLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghY3VycmVudFJldmlzaW9uKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignQ3VycmVudCByZXZpc2lvbiBub3QgZm91bmQnKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBHZXQgY2FuY2VsbGVkIHN0YXR1c1xyXG4gICAgY29uc3QgY2FuY2VsbGVkU3RhdHVzID0gYXdhaXQgdGhpcy5zdGF0dXNSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBzdGF0dXNDb2RlOiAnQ0FOQ0VMTEVEJyB9LFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKCFjYW5jZWxsZWRTdGF0dXMpIHtcclxuICAgICAgdGhyb3cgbmV3IEludGVybmFsU2VydmVyRXJyb3JFeGNlcHRpb24oJ0NBTkNFTExFRCBzdGF0dXMgbm90IGZvdW5kJyk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgcXVlcnlSdW5uZXIgPSB0aGlzLmRhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIoKTtcclxuICAgIGF3YWl0IHF1ZXJ5UnVubmVyLmNvbm5lY3QoKTtcclxuICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnN0YXJ0VHJhbnNhY3Rpb24oKTtcclxuXHJcbiAgICB0cnkge1xyXG4gICAgICAvLyBVcGRhdGUgY29ycmVzcG9uZGVuY2UgcmV2aXNpb24gc3RhdHVzIHRvIENBTkNFTExFRFxyXG4gICAgICBhd2FpdCBxdWVyeVJ1bm5lci5tYW5hZ2VyLnVwZGF0ZShcclxuICAgICAgICBDb3JyZXNwb25kZW5jZVJldmlzaW9uLFxyXG4gICAgICAgIGN1cnJlbnRSZXZpc2lvbi5pZCxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBzdGF0dXNJZDogY2FuY2VsbGVkU3RhdHVzLmlkLFxyXG4gICAgICAgICAgcmVtYXJrczogYENhbmNlbGxlZDogJHtyZWFzb259YCxcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcblxyXG4gICAgICAvLyBGb3JjZSBjbG9zZSBhbGwgYWN0aXZlIGNpcmN1bGF0aW9uc1xyXG4gICAgICBpZiAoYWN0aXZlQ2lyY3VsYXRpb25zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBhd2FpdCBxdWVyeVJ1bm5lci5tYW5hZ2VyLnVwZGF0ZShcclxuICAgICAgICAgICdDaXJjdWxhdGlvbicsXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IGNvcnJlc3BvbmRlbmNlLmlkLFxyXG4gICAgICAgICAgICBzdGF0dXM6ICdPUEVOJyxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHN0YXR1czogJ0ZPUkNFX0NMT1NFRCcsXHJcbiAgICAgICAgICAgIGNsb3NlZEF0OiBuZXcgRGF0ZSgpLFxyXG4gICAgICAgICAgICBjbG9zZWRCeTogdXNlci51c2VyX2lkLFxyXG4gICAgICAgICAgICBjbG9zZVJlYXNvbjogYENvcnJlc3BvbmRlbmNlIGNhbmNlbGxlZDogJHtyZWFzb259YCxcclxuICAgICAgICAgIH1cclxuICAgICAgICApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBhd2FpdCBxdWVyeVJ1bm5lci5jb21taXRUcmFuc2FjdGlvbigpO1xyXG5cclxuICAgICAgLy8gUmUtaW5kZXggY2FuY2VsbGVkIHN0YXR1cyBpbiBFbGFzdGljc2VhcmNoIChmaXJlLWFuZC1mb3JnZXQpXHJcbiAgICAgIHZvaWQgdGhpcy5zZWFyY2hTZXJ2aWNlLmluZGV4RG9jdW1lbnQoe1xyXG4gICAgICAgIGlkOiBjb3JyZXNwb25kZW5jZS5pZCxcclxuICAgICAgICBwdWJsaWNJZDogY29ycmVzcG9uZGVuY2UucHVibGljSWQsXHJcbiAgICAgICAgdHlwZTogJ2NvcnJlc3BvbmRlbmNlJyxcclxuICAgICAgICBkb2NOdW1iZXI6IGNvcnJlc3BvbmRlbmNlLmNvcnJlc3BvbmRlbmNlTnVtYmVyLFxyXG4gICAgICAgIHRpdGxlOiBjdXJyZW50UmV2aXNpb24uc3ViamVjdCxcclxuICAgICAgICBzdGF0dXM6ICdDQU5DRUxMRUQnLFxyXG4gICAgICAgIHByb2plY3RJZDogY29ycmVzcG9uZGVuY2UucHJvamVjdElkLFxyXG4gICAgICAgIGNyZWF0ZWRBdDogY29ycmVzcG9uZGVuY2UuY3JlYXRlZEF0LFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vIE5vdGlmeSBvcmlnaW5hdG9yJ3MgZG9jLWNvbnRyb2wgdXNlciBhYm91dCBjYW5jZWxsYXRpb24gKGZpcmUtYW5kLWZvcmdldClcclxuICAgICAgaWYgKGNvcnJlc3BvbmRlbmNlLm9yaWdpbmF0b3JJZCkge1xyXG4gICAgICAgIHZvaWQgdGhpcy51c2VyU2VydmljZVxyXG4gICAgICAgICAgLmZpbmREb2NDb250cm9sSWRCeU9yZyhjb3JyZXNwb25kZW5jZS5vcmlnaW5hdG9ySWQpXHJcbiAgICAgICAgICAudGhlbigodGFyZ2V0VXNlcklkKSA9PiB7XHJcbiAgICAgICAgICAgIGlmICh0YXJnZXRVc2VySWQpIHtcclxuICAgICAgICAgICAgICB2b2lkIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5zZW5kKHtcclxuICAgICAgICAgICAgICAgIHVzZXJJZDogdGFyZ2V0VXNlcklkLFxyXG4gICAgICAgICAgICAgICAgdGl0bGU6ICdDb3JyZXNwb25kZW5jZSBDYW5jZWxsZWQnLFxyXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYCR7Y29ycmVzcG9uZGVuY2UuY29ycmVzcG9uZGVuY2VOdW1iZXJ9IOKAlCAke2N1cnJlbnRSZXZpc2lvbi5zdWJqZWN0fSBoYXMgYmVlbiBjYW5jZWxsZWQuIFJlYXNvbjogJHtyZWFzb259YCxcclxuICAgICAgICAgICAgICAgIHR5cGU6ICdFTUFJTCcsXHJcbiAgICAgICAgICAgICAgICBlbnRpdHlUeXBlOiAnY29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICAgICAgICAgICAgZW50aXR5SWQ6IGNvcnJlc3BvbmRlbmNlLmlkLFxyXG4gICAgICAgICAgICAgICAgbGluazogYC9jb3JyZXNwb25kZW5jZXMvJHtjb3JyZXNwb25kZW5jZS5wdWJsaWNJZH1gLFxyXG4gICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KVxyXG4gICAgICAgICAgLmNhdGNoKChlcnI6IEVycm9yKSA9PlxyXG4gICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKGBDYW5jZWwgbm90aWZpY2F0aW9uIGZhaWxlZDogJHtlcnIubWVzc2FnZX1gKVxyXG4gICAgICAgICAgKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBzdWNjZXNzOiB0cnVlLFxyXG4gICAgICAgIG1lc3NhZ2U6IHdhcm5pbmdNZXNzYWdlIHx8ICdDb3JyZXNwb25kZW5jZSBjYW5jZWxsZWQgc3VjY2Vzc2Z1bGx5JyxcclxuICAgICAgICBhY3RpdmVDaXJjdWxhdGlvbnNDb3VudDogYWN0aXZlQ2lyY3VsYXRpb25zLmxlbmd0aCxcclxuICAgICAgfTtcclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJvbGxiYWNrVHJhbnNhY3Rpb24oKTtcclxuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXHJcbiAgICAgICAgYEZhaWxlZCB0byBjYW5jZWwgY29ycmVzcG9uZGVuY2U6ICR7KGVycm9yIGFzIEVycm9yKS5tZXNzYWdlfWBcclxuICAgICAgKTtcclxuICAgICAgdGhyb3cgZXJyb3I7XHJcbiAgICB9IGZpbmFsbHkge1xyXG4gICAgICBhd2FpdCBxdWVyeVJ1bm5lci5yZWxlYXNlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBidWxrQ2FuY2VsKFxyXG4gICAgcHVibGljSWRzOiBzdHJpbmdbXSxcclxuICAgIHJlYXNvbjogc3RyaW5nLFxyXG4gICAgdXNlcjogVXNlclxyXG4gICk6IFByb21pc2U8eyBzdWNjZWVkZWQ6IHN0cmluZ1tdOyBmYWlsZWQ6IHN0cmluZ1tdIH0+IHtcclxuICAgIGNvbnN0IHN1Y2NlZWRlZDogc3RyaW5nW10gPSBbXTtcclxuICAgIGNvbnN0IGZhaWxlZDogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IHB1YmxpY0lkIG9mIHB1YmxpY0lkcykge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGF3YWl0IHRoaXMuY2FuY2VsKHB1YmxpY0lkLCByZWFzb24sIHVzZXIpO1xyXG4gICAgICAgIHN1Y2NlZWRlZC5wdXNoKHB1YmxpY0lkKTtcclxuICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgZmFpbGVkLnB1c2gocHVibGljSWQpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHsgc3VjY2VlZGVkLCBmYWlsZWQgfTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGV4cG9ydENzdihzZWFyY2hEdG86IFNlYXJjaENvcnJlc3BvbmRlbmNlRHRvKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuICAgIGNvbnN0IHsgZGF0YSB9ID0gYXdhaXQgdGhpcy5maW5kQWxsKHNlYXJjaER0byk7XHJcblxyXG4gICAgY29uc3QgaGVhZGVyID0gW1xyXG4gICAgICAnRG9jdW1lbnQgTm8uJyxcclxuICAgICAgJ1JldicsXHJcbiAgICAgICdTdWJqZWN0JyxcclxuICAgICAgJ1R5cGUnLFxyXG4gICAgICAnU3RhdHVzJyxcclxuICAgICAgJ1Byb2plY3QnLFxyXG4gICAgICAnRnJvbScsXHJcbiAgICAgICdEdWUgRGF0ZScsXHJcbiAgICAgICdDcmVhdGVkIEF0JyxcclxuICAgIF07XHJcbiAgICBjb25zdCByb3dzID0gZGF0YS5tYXAoKHJldikgPT4ge1xyXG4gICAgICBjb25zdCBjb3JyID0gcmV2LmNvcnJlc3BvbmRlbmNlID8/IChyZXYgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcbiAgICAgIHJldHVybiBbXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YoY29yci5jb3JyZXNwb25kZW5jZU51bWJlciA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YocmV2LnJldmlzaW9uTGFiZWwgPz8gU3RyaW5nKHJldi5yZXZpc2lvbk51bWJlciA/PyAwKSksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YocmV2LnN1YmplY3QgPz8gJycpLFxyXG4gICAgICAgIHRoaXMuZXNjYXBlQ3N2KGNvcnIudHlwZT8udHlwZUNvZGUgPz8gJycpLFxyXG4gICAgICAgIHRoaXMuZXNjYXBlQ3N2KHJldi5zdGF0dXM/LnN0YXR1c0NvZGUgPz8gJycpLFxyXG4gICAgICAgIHRoaXMuZXNjYXBlQ3N2KGNvcnIucHJvamVjdD8ucHJvamVjdENvZGUgPz8gJycpLFxyXG4gICAgICAgIHRoaXMuZXNjYXBlQ3N2KGNvcnIub3JpZ2luYXRvcj8ub3JnYW5pemF0aW9uQ29kZSA/PyAnJyksXHJcbiAgICAgICAgcmV2LmR1ZURhdGUgPyBuZXcgRGF0ZShyZXYuZHVlRGF0ZSkudG9JU09TdHJpbmcoKS5zcGxpdCgnVCcpWzBdIDogJycsXHJcbiAgICAgICAgbmV3IERhdGUocmV2LmNyZWF0ZWRBdCkudG9JU09TdHJpbmcoKS5zcGxpdCgnVCcpWzBdLFxyXG4gICAgICBdLmpvaW4oJywnKTtcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiBbaGVhZGVyLmpvaW4oJywnKSwgLi4ucm93c10uam9pbignXFxuJyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGVzY2FwZUNzdih2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGlmICh2YWx1ZS5pbmNsdWRlcygnLCcpIHx8IHZhbHVlLmluY2x1ZGVzKCdcIicpIHx8IHZhbHVlLmluY2x1ZGVzKCdcXG4nKSkge1xyXG4gICAgICByZXR1cm4gYFwiJHt2YWx1ZS5yZXBsYWNlKC9cIi9nLCAnXCJcIicpfVwiYDtcclxuICAgIH1cclxuICAgIHJldHVybiB2YWx1ZTtcclxuICB9XHJcbn1cclxuIl0sInZlcnNpb24iOjN9 \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/36/correspondenceservice_362c2d40da9948c1683321c46a0347aa.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/36/correspondenceservice_362c2d40da9948c1683321c46a0347aa.map new file mode 100644 index 0000000..aca1ac8 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/36/correspondenceservice_362c2d40da9948c1683321c46a0347aa.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.ts","mappings":";AAAA,6DAA6D;;;;;;;;;;;;;;;;;AAE7D,2CAOwB;AACxB,6CAAmD;AACnD,qCAAiD;AAEjD,WAAW;AACX,4EAAkE;AAClE,8FAAmF;AACnF,sFAA2E;AAC3E,0FAA+E;AAC/E,gGAAqF;AACrF,gGAAqF;AACrF,oFAAyE;AACzE,8DAAoD;AAEpD,sFAA4E;AAQ5E,WAAW;AACX,0GAAqG;AACrG,4EAAuE;AACvE,wFAAmF;AACnF,uDAAmD;AACnD,6DAAyD;AACzD,yFAAoF;AACpF,uFAAkF;AAClF,+EAA2E;AAUpE,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IAGxB,KAAK,CAAC,4BAA4B,CAAC,MAAc;QACvD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACtE,OAAO,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IACnD,CAAC;IAED;;;;OAIG;IACK,uBAAuB,CAAC,QAAgB;QAC9C,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YACnD,OAAO,GAAG,CAAC,CAAC,wBAAwB;QACtC,CAAC;QACD,OAAO,SAAS,CAAC,CAAC,oCAAoC;IACxD,CAAC;IAED,YAEE,kBAAsD,EAEtD,YAAwD,EAExD,QAAgD,EAEhD,UAAoD,EAEpD,aAA0D,EAE1D,OAA8C,EACtC,gBAA0C,EAC1C,iBAAoC,EACpC,cAAqC,EACrC,WAAwB,EACxB,UAAsB,EACtB,aAA4B,EAC5B,kBAAsC,EACtC,YAAiC,EACjC,mBAAwC;QAnBxC,uBAAkB,GAAlB,kBAAkB,CAA4B;QAE9C,iBAAY,GAAZ,YAAY,CAAoC;QAEhD,aAAQ,GAAR,QAAQ,CAAgC;QAExC,eAAU,GAAV,UAAU,CAAkC;QAE5C,kBAAa,GAAb,aAAa,CAAqC;QAElD,YAAO,GAAP,OAAO,CAA+B;QACtC,qBAAgB,GAAhB,gBAAgB,CAA0B;QAC1C,sBAAiB,GAAjB,iBAAiB,CAAmB;QACpC,mBAAc,GAAd,cAAc,CAAuB;QACrC,gBAAW,GAAX,WAAW,CAAa;QACxB,eAAU,GAAV,UAAU,CAAY;QACtB,kBAAa,GAAb,aAAa,CAAe;QAC5B,uBAAkB,GAAlB,kBAAkB,CAAoB;QACtC,iBAAY,GAAZ,YAAY,CAAqB;QACjC,wBAAmB,GAAnB,mBAAmB,CAAqB;QAzCjC,WAAM,GAAG,IAAI,eAAM,CAAC,uBAAqB,CAAC,IAAI,CAAC,CAAC;IA0C9D,CAAC;IAEJ;;;OAGG;IACK,KAAK,CAAC,gCAAgC,CAC5C,SAAkC,EAClC,IAAU;QAEV,0BAA0B;QAC1B,IAAI,SAAS,GAAG,IAAI,CAAC,qBAAqB,CAAC;QAC3C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC9D,IAAI,QAAQ,EAAE,CAAC;gBACb,SAAS,GAAG,QAAQ,CAAC,qBAAqB,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,SAAS,CAAC,YAAY,EAAE,CAAC;gBAC3B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,4BAA4B,CAC1D,IAAI,CAAC,OAAO,CACb,CAAC;gBACF,IAAI,YAAY,EAAE,CAAC;oBACjB,SAAS,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CACvD,SAAS,CAAC,YAAY,CACvB,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,4BAAmB,CAC3B,yDAAyD,CAC1D,CAAC;YACJ,CAAC;QACH,CAAC;QAED,kDAAkD;QAClD,MAAM,eAAe,GAAG,SAAS,CAAC,YAAY;YAC5C,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC,SAAS,CAAC,YAAY,CAAC;YACvE,CAAC,CAAC,SAAS,CAAC;QAEd,uCAAuC;QACvC,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;YACzB,yDAAyD;YACzD,MAAM,IAAI,4BAAmB,CAC3B,gFAAgF,CACjF,CAAC;QACJ,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC,SAAS,CAAC,UAAU,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,4BAAmB,CAC3B,+CAA+C,CAChD,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAAG,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACzE,MAAM,YAAY,GAAG,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAEzE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,4BAAmB,CAC3B,6CAA6C,CAC9C,CAAC;QACJ,CAAC;QAED,6CAA6C;QAC7C,KAAK,MAAM,SAAS,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;YAC7C,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAClE,SAAS,CAAC,cAAc,CACzB,CAAC;YAEF,IAAI,cAAc,KAAK,eAAe,EAAE,CAAC;gBACvC,MAAM,IAAI,4BAAmB,CAC3B,wGAAwG,CACzG,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAkC,EAAE,IAAU;QACzD,iEAAiE;QACjE,MAAM,IAAI,CAAC,gCAAgC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC7D,uDAAuD;QACvD,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAChE,SAAS,CAAC,SAAS,CACpB,CAAC;QACF,MAAM,oBAAoB,GAAG,SAAS,CAAC,YAAY;YACjD,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC,SAAS,CAAC,YAAY,CAAC;YACvE,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,kBAAkB,GAAG,SAAS,CAAC,UAAU;YAC7C,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,CAAC,UAAU,CAAC,GAAG,CACtB,KAAK,EAAE,CAAC,EAA8B,EAAE,CAAC,CAAC;gBACxC,cAAc,EAAE,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAC3D,CAAC,CAAC,cAAc,CACjB;gBACD,IAAI,EAAE,CAAC,CAAC,IAAI;aACb,CAAC,CACH,CACF;YACH,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YACvC,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,0BAAiB,CAAC,yBAAyB,CAAC,CAAC;QAElE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAChD,KAAK,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,qCAA4B,CACpC,uCAAuC,CACxC,CAAC;QACJ,CAAC;QAED,IAAI,SAAS,GAAG,IAAI,CAAC,qBAAqB,CAAC;QAE3C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC9D,IAAI,QAAQ,EAAE,CAAC;gBACb,SAAS,GAAG,QAAQ,CAAC,qBAAqB,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,IAAI,oBAAoB,IAAI,oBAAoB,KAAK,SAAS,EAAE,CAAC;YAC/D,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,4BAA4B,CAC1D,IAAI,CAAC,OAAO,CACb,CAAC;YACF,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,MAAM,IAAI,2BAAkB,CAC1B,kFAAkF,CACnF,CAAC;YACJ,CAAC;YACD,SAAS,GAAG,oBAAoB,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,4BAAmB,CAC3B,yDAAyD,CAC1D,CAAC;QACJ,CAAC;QAED,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;YAC1E,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,iCAAiC,IAAI,CAAC,QAAQ,KAAM,KAAe,CAAC,OAAO,EAAE,CAC9E,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC;QACxD,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;QAC5B,MAAM,WAAW,CAAC,gBAAgB,EAAE,CAAC;QAErC,IAAI,CAAC;YACH,wDAAwD;YACxD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CACzD,kCAAY,EACZ;gBACE,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;aACzB,CACF,CAAC;YACF,MAAM,OAAO,GAAG,aAAa,EAAE,gBAAgB,IAAI,KAAK,CAAC;YAEzD,6EAA6E;YAC7E,MAAM,WAAW,GAAG,kBAAkB,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YACrE,MAAM,uBAAuB,GAAG,WAAW,EAAE,cAAc,CAAC;YAE5D,IAAI,aAAa,GAAG,EAAE,CAAC;YACvB,IAAI,uBAAuB,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,kCAAY,EAAE;oBACjE,KAAK,EAAE,EAAE,EAAE,EAAE,uBAAuB,EAAE;iBACvC,CAAC,CAAC;gBACH,IAAI,MAAM;oBAAE,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;YACtD,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,CAAC;gBAC/D,SAAS,EAAE,iBAAiB;gBAC5B,wBAAwB,EAAE,SAAS;gBACnC,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,YAAY,EAAE,SAAS,CAAC,YAAY;gBACpC,SAAS,EAAE,SAAS,CAAC,SAAS;gBAC9B,uBAAuB,EAAE,qDAAqD;gBAC9E,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC9B,YAAY,EAAE;oBACZ,SAAS,EAAE,IAAI,CAAC,QAAQ;oBACxB,QAAQ,EAAE,OAAO;oBACjB,cAAc,EAAE,aAAa;oBAC7B,QAAQ,EAAE,aAAa;iBACxB;aACF,CAAC,CAAC;YAEH,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,sCAAc,EAAE;gBAChE,oBAAoB,EAAE,SAAS,CAAC,MAAM;gBACtC,oBAAoB,EAAE,SAAS,CAAC,MAAM;gBACtC,YAAY,EAAE,SAAS,CAAC,YAAY;gBACpC,SAAS,EAAE,iBAAiB;gBAC5B,YAAY,EAAE,SAAS;gBACvB,UAAU,EAAE,SAAS,CAAC,UAAU,IAAI,KAAK;gBACzC,SAAS,EAAE,IAAI,CAAC,OAAO;aACxB,CAAC,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAEjE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,uDAAsB,EAAE;gBAClE,gBAAgB,EAAE,SAAS,CAAC,EAAE;gBAC9B,cAAc,EAAE,CAAC;gBACjB,aAAa,EAAE,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAC1D,SAAS,EAAE,IAAI;gBACf,QAAQ,EAAE,WAAW,CAAC,EAAE;gBACxB,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;gBACpE,YAAY,EAAE,SAAS,CAAC,YAAY;oBAClC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;oBAClC,CAAC,CAAC,SAAS;gBACb,UAAU,EAAE,SAAS,CAAC,UAAU;oBAC9B,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;oBAChC,CAAC,CAAC,SAAS;gBACb,YAAY,EAAE,SAAS,CAAC,YAAY;oBAClC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;oBAClC,CAAC,CAAC,SAAS;gBACb,WAAW,EAAE,SAAS,CAAC,WAAW;gBAClC,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,SAAS,EAAE,IAAI,CAAC,OAAO;gBACvB,aAAa,EAAE,CAAC;aACjB,CAAC,CAAC;YACH,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEzC,2CAA2C;YAC3C,IAAI,kBAAkB,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxD,MAAM,UAAU,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9C,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,yDAAuB,EAAE;oBAClD,gBAAgB,EAAE,SAAS,CAAC,EAAE;oBAC9B,uBAAuB,EAAE,CAAC,CAAC,cAAc;oBACzC,aAAa,EAAE,CAAC,CAAC,IAAI;iBACtB,CAAC,CACH,CAAC;gBACF,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7C,CAAC;YAED,+DAA+D;YAC/D,IAAI,SAAS,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;gBACxC,MAAM,SAAS,GAAG,SAAS,CAAC,UAAU;oBACpC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;oBAChC,CAAC,CAAC,SAAS,CAAC,YAAY;wBACtB,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;wBAClC,CAAC,CAAC,SAAS,CAAC;gBAEhB,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,iBAAiB,EAAE;oBAChE,SAAS;oBACT,YAAY,EAAE,gBAAgB;iBAC/B,CAAC,CAAC;YACL,CAAC;YAED,MAAM,WAAW,CAAC,iBAAiB,EAAE,CAAC;YAEtC,yCAAyC;YACzC,IAAI,CAAC;gBACH,MAAM,YAAY,GAAG,kBAAkB,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACvD,MAAM,IAAI,CAAC,cAAc,CAAC,cAAc,CACtC,YAAY,EACZ,gBAAgB,EAChB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,EACvB;oBACE,SAAS,EAAE,iBAAiB;oBAC5B,YAAY,EAAE,SAAS;oBACvB,YAAY,EAAE,SAAS,CAAC,YAAY;oBACpC,WAAW,EAAE,IAAI,CAAC,OAAO;iBACC,CAC7B,CAAC;YACJ,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,4BAA4B,SAAS,CAAC,MAAM,0BAA0B,IAAI,CAAC,QAAQ,MAAO,KAAe,CAAC,OAAO,EAAE,CACpH,CAAC;YACJ,CAAC;YAED,mEAAmE;YACnE,KAAK,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC;gBACpC,EAAE,EAAE,SAAS,CAAC,EAAE;gBAChB,QAAQ,EAAE,SAAS,CAAC,QAAQ;gBAC5B,IAAI,EAAE,gBAAgB;gBACtB,SAAS,EAAE,SAAS,CAAC,MAAM;gBAC3B,KAAK,EAAE,SAAS,CAAC,OAAO;gBACxB,WAAW,EAAE,SAAS,CAAC,WAAW;gBAClC,MAAM,EAAE,OAAO;gBACf,SAAS,EAAE,iBAAiB;gBAC5B,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC,CAAC;YAEH,OAAO;gBACL,GAAG,SAAS;gBACZ,eAAe,EAAE,QAAQ;aAC1B,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,WAAW,CAAC,mBAAmB,EAAE,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,oCAAqC,GAAa,CAAC,OAAO,EAAE,CAC7D,CAAC;YACF,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,YAAqC,EAAE;QACnD,MAAM,EACJ,MAAM,EACN,MAAM,EACN,SAAS,EACT,QAAQ,EACR,MAAM,EACN,IAAI,GAAG,CAAC,EACR,KAAK,GAAG,EAAE,GACX,GAAG,SAAS,CAAC;QACd,MAAM,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QAEhC,mCAAmC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY;aAC5B,kBAAkB,CAAC,KAAK,CAAC;aACzB,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,CAAC;aAC/C,iBAAiB,CAAC,WAAW,EAAE,MAAM,CAAC;aACtC,iBAAiB,CAAC,cAAc,EAAE,SAAS,CAAC;aAC5C,iBAAiB,CAAC,iBAAiB,EAAE,KAAK,CAAC;aAC3C,iBAAiB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAE7C,4BAA4B;QAC5B,MAAM,SAAS,GAAG,SAAS,CAAC,cAAc,IAAI,SAAS,CAAC;QAExD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,KAAK,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC;aAAM,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;YAC/B,KAAK,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,CAAC;QACD,0CAA0C;QAE1C,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,CAAC,QAAQ,CAAC,6BAA6B,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,QAAQ,CAAC,qCAAqC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,CAAC,QAAQ,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,QAAQ,CAAC,6BAA6B,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,QAAQ,CACZ,sEAAsE,EACtE,EAAE,MAAM,EAAE,IAAI,MAAM,GAAG,EAAE,CAC1B,CAAC;QACJ,CAAC;QAED,+BAA+B;QAC/B,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE9D,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,eAAe,EAAE,CAAC;QAErD,OAAO;YACL,IAAI,EAAE,KAAK;YACX,IAAI,EAAE;gBACJ,KAAK;gBACL,IAAI;gBACJ,KAAK;gBACL,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;aACrC;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;YAC3D,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,SAAS,EAAE;gBACT,WAAW;gBACX,kBAAkB;gBAClB,MAAM;gBACN,SAAS;gBACT,YAAY;gBACZ,YAAY;gBACZ,kCAAkC,EAAE,+BAA+B;aACpE;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,0BAAiB,CAAC,0BAA0B,EAAE,YAAY,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAgB;QAClC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;YAC3D,KAAK,EAAE,EAAE,QAAQ,EAAE;YACnB,SAAS,EAAE;gBACT,WAAW;gBACX,kBAAkB;gBAClB,MAAM;gBACN,SAAS;gBACT,YAAY;gBACZ,YAAY;gBACZ,kCAAkC;aACnC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,0BAAiB,CACzB,4BAA4B,QAAQ,YAAY,CACjD,CAAC;QACJ,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAU,EAAE,GAAoB;QACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACxE,qDAAqD;QACrD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;YACnD,KAAK,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,UAAU,EAAE;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACvB,MAAM,IAAI,0BAAiB,CAAC,2CAA2C,CAAC,CAAC;QAC3E,CAAC;QAED,IAAI,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,4BAAmB,CAAC,uBAAuB,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YAC9C,KAAK,EAAE;gBACL,QAAQ,EAAE,EAAE;gBACZ,QAAQ,EAAE,MAAM,CAAC,EAAE;aACpB;SACF,CAAC,CAAC;QAEH,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;YACpC,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,MAAM,CAAC,EAAE;SACpB,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,EAAU,EAAE,QAAgB;QAChD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;YAC7C,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,0BAAiB,CAAC,qBAAqB,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACnC,KAAK,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE;YAC/B,SAAS,EAAE,CAAC,KAAK,CAAC;SACnB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,KAAa;QACpC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;YAC3D,KAAK,EAAE,EAAE,EAAE,EAAE;SACd,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,0BAAiB,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAG,EAAE;YACrD,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE;SACrB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,0BAAiB,CAAC,OAAO,KAAK,YAAY,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YACxC,KAAK,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,EAAE;SACvC,CAAC,CAAC;QACH,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAU,EAAE,KAAa;QACvC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1E,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,0BAAiB,CAAC,0BAA0B,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAC7C,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;YACvB,SAAS,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC;SACrC,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAC7C,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;YACvB,SAAS,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC;SACrC,CAAC,CAAC;QAEH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,SAAkC,EAAE,IAAU;QACrE,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;YAC/C,KAAK,EAAE;gBACL,gBAAgB,EAAE,EAAE;gBACpB,SAAS,EAAE,IAAI;aAChB;YACD,SAAS,EAAE,CAAC,gBAAgB,CAAC;SAC9B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,0BAAiB,CACzB,uCAAuC,EAAE,YAAY,CACtD,CAAC;QACJ,CAAC;QAED,sBAAsB;QACtB,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;gBAC3C,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE;aACjC,CAAC,CAAC;YAEH,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBAC5C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAC3D,IAAI,CAAC,OAAO,CACb,CAAC;gBACF,MAAM,uBAAuB,GAC3B,WAAW,CAAC,QAAQ,CAAC,uBAAuB,CAAC;oBAC7C,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;gBAE5C,IAAI,CAAC,uBAAuB,EAAE,CAAC;oBAC7B,MAAM,IAAI,2BAAkB,CAC1B,iEAAiE,CAClE,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,iDAAiD;QACjD,MAAM,oBAAoB,GAAG,SAAS,CAAC,SAAS;YAC9C,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,SAAS,CAAC,SAAS,CAAC;YAC/D,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,uBAAuB,GAAG,SAAS,CAAC,YAAY;YACpD,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC,SAAS,CAAC,YAAY,CAAC;YACvE,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,qBAAqB,GAAG,SAAS,CAAC,UAAU;YAChD,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,CAAC,UAAU,CAAC,GAAG,CACtB,KAAK,EAAE,CAAC,EAA8B,EAAE,CAAC,CAAC;gBACxC,cAAc,EAAE,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAC3D,CAAC,CAAC,cAAc,CACjB;gBACD,IAAI,EAAE,CAAC,CAAC,IAAI;aACb,CAAC,CACH,CACF;YACH,CAAC,CAAC,SAAS,CAAC;QAEd,4CAA4C;QAC5C,MAAM,oBAAoB,GAA4B,EAAE,CAAC;QACzD,IAAI,SAAS,CAAC,YAAY;YACxB,oBAAoB,CAAC,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC;QAC7D,IAAI,oBAAoB;YACtB,oBAAoB,CAAC,SAAS,GAAG,oBAAoB,CAAC;QACxD,IAAI,uBAAuB;YACzB,oBAAoB,CAAC,YAAY,GAAG,uBAAuB,CAAC;QAE9D,IAAI,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC;QACjE,CAAC;QAED,4BAA4B;QAC5B,MAAM,cAAc,GAA4B,EAAE,CAAC;QACnD,IAAI,SAAS,CAAC,OAAO;YAAE,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;QAClE,IAAI,SAAS,CAAC,IAAI;YAAE,cAAc,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;QACzD,IAAI,SAAS,CAAC,OAAO;YAAE,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;QAClE,kCAAkC;QAClC,IAAI,SAAS,CAAC,OAAO;YAAE,cAAc,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC5E,IAAI,SAAS,CAAC,YAAY;YACxB,cAAc,CAAC,YAAY,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACjE,IAAI,SAAS,CAAC,UAAU;YACtB,cAAc,CAAC,UAAU,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC7D,IAAI,SAAS,CAAC,YAAY;YACxB,cAAc,CAAC,YAAY,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACjE,IAAI,SAAS,CAAC,WAAW;YACvB,cAAc,CAAC,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;QACrD,IAAI,SAAS,CAAC,OAAO;YAAE,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;QAElE,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;QAC9D,CAAC;QAED,uEAAuE;QACvE,IAAI,SAAS,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;YACxC,MAAM,SAAS,GAAG,SAAS,CAAC,UAAU;gBACpC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;gBAChC,CAAC,CAAC,SAAS,CAAC,YAAY;oBACtB,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;oBAClC,CAAC,CAAC,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,YAAY,IAAI,SAAS,CAAC;YAEhE,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,iBAAiB,EAAE;gBAChE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;gBACtD,YAAY,EAAE,gBAAgB;aAC/B,CAAC,CAAC;QACL,CAAC;QAED,mCAAmC;QACnC,IAAI,qBAAqB,EAAE,CAAC;YAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CACjD,yDAAuB,CACxB,CAAC;YACF,MAAM,aAAa,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC,CAAC;YAErD,MAAM,aAAa,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACpD,aAAa,CAAC,MAAM,CAAC;gBACnB,gBAAgB,EAAE,EAAE;gBACpB,uBAAuB,EAAE,CAAC,CAAC,cAAc;gBACzC,aAAa,EAAE,CAAC,CAAC,IAAI;aACtB,CAAC,CACH,CAAC;YACF,MAAM,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1C,CAAC;QAED,oGAAoG;QACpG,qBAAqB;QAErB,8CAA8C;QAC9C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;YACxD,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,SAAS,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,kCAAkC,CAAC;SACtE,CAAC,CAAC;QAEH,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,kBAAkB,GAAG,WAAW,CAAC,UAAU,EAAE,IAAI,CACrD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,IAAI,CAChC,CAAC;YACF,MAAM,kBAAkB,GAAG,kBAAkB,EAAE,uBAAuB,CAAC;YAEvE,iCAAiC;YACjC,MAAM,gBAAgB,GACpB,oBAAoB,KAAK,SAAS;gBAClC,oBAAoB,KAAK,WAAW,CAAC,SAAS,CAAC;YACjD,MAAM,mBAAmB,GACvB,uBAAuB,KAAK,SAAS;gBACrC,uBAAuB,KAAK,WAAW,CAAC,YAAY,CAAC;YACvD,MAAM,mBAAmB,GACvB,SAAS,CAAC,YAAY,KAAK,SAAS;gBACpC,SAAS,CAAC,YAAY,KAAK,WAAW,CAAC,YAAY,CAAC;YACtD,MAAM,aAAa,GACjB,SAAS,CAAC,MAAM,KAAK,SAAS;gBAC9B,SAAS,CAAC,MAAM,KAAK,WAAW,CAAC,oBAAoB,CAAC;YAExD,IAAI,kBAAkB,GAAG,KAAK,CAAC;YAC/B,IAAI,cAAkC,CAAC;YAEvC,IAAI,qBAAqB,EAAE,CAAC;gBAC1B,MAAM,cAAc,GAAG,qBAAqB,CAAC,IAAI,CAC/C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CACvB,CAAC;gBACF,cAAc,GAAG,cAAc,EAAE,cAAc,CAAC;gBAEhD,IAAI,cAAc,KAAK,kBAAkB,EAAE,CAAC;oBAC1C,kBAAkB,GAAG,IAAI,CAAC;gBAC5B,CAAC;YACH,CAAC;YAED,IACE,gBAAgB;gBAChB,mBAAmB;gBACnB,aAAa;gBACb,kBAAkB;gBAClB,mBAAmB,EACnB,CAAC;gBACD,MAAM,iBAAiB,GAAG,kBAAkB;oBAC1C,CAAC,CAAC,cAAc;oBAChB,CAAC,CAAC,kBAAkB,CAAC;gBAEvB,6CAA6C;gBAC7C,IAAI,aAAa,GAAG,EAAE,CAAC;gBACvB,IAAI,iBAAiB,EAAE,CAAC;oBACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,kCAAY,EAAE;wBACjE,KAAK,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE;qBACjC,CAAC,CAAC;oBACH,IAAI,MAAM;wBAAE,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;gBACtD,CAAC;gBAED,4DAA4D;gBAC5D,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAClE,kCAAY,EACZ;oBACE,KAAK,EAAE;wBACL,EAAE,EAAE,uBAAuB,IAAI,WAAW,CAAC,YAAY,IAAI,CAAC;qBAC7D;iBACF,CACF,CAAC;gBACF,MAAM,OAAO,GAAG,sBAAsB,EAAE,gBAAgB,IAAI,KAAK,CAAC;gBAElE,mBAAmB;gBACnB,MAAM,MAAM,GAAG;oBACb,SAAS,EAAE,WAAW,CAAC,SAAS;oBAChC,wBAAwB,EAAE,WAAW,CAAC,YAAY,IAAI,CAAC;oBACvD,MAAM,EAAE,WAAW,CAAC,oBAAoB;oBACxC,YAAY,EAAE,WAAW,CAAC,YAAY;oBACtC,uBAAuB,EAAE,kBAAkB;oBAC3C,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBAC/B,CAAC;gBAEF,MAAM,MAAM,GAAG;oBACb,SAAS,EAAE,oBAAoB,IAAI,WAAW,CAAC,SAAS;oBACxD,wBAAwB,EACtB,uBAAuB,IAAI,WAAW,CAAC,YAAY,IAAI,CAAC;oBAC1D,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,WAAW,CAAC,oBAAoB;oBAC5D,YAAY,EAAE,SAAS,CAAC,YAAY,IAAI,WAAW,CAAC,YAAY;oBAChE,uBAAuB,EAAE,iBAAiB;oBAC1C,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBAC9B,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,yBAAyB;oBAC/C,YAAY,EAAE;wBACZ,SAAS,EAAE,WAAW,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAE;wBAC3C,QAAQ,EAAE,OAAO;wBACjB,cAAc,EAAE,aAAa;wBAC7B,QAAQ,EAAE,aAAa;qBACxB;iBACF,CAAC;gBAEF,sCAAsC;gBACtC,IAAI,aAAa,EAAE,CAAC;oBAClB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;wBAC1C,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE;qBAC7B,CAAC,CAAC;oBACH,IAAI,OAAO;wBAAE,MAAM,CAAC,YAAY,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;gBAChE,CAAC;gBAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,CACnE,WAAW,CAAC,oBAAoB,EAChC,MAAM,EACN,MAAM,CACP,CAAC;gBAEF,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE;oBACvC,oBAAoB,EAAE,YAAY;iBACnC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAEvC,+DAA+D;QAC/D,KAAK,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC;YACpC,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,IAAI,EAAE,gBAAgB;YACtB,SAAS,EAAE,OAAO,CAAC,oBAAoB;YACvC,KAAK,EAAE,SAAS,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO;YAC3D,WAAW,EAAE,SAAS,CAAC,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW;YACzE,MAAM,EAAE,OAAO;YACf,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,SAAkC,EAAE,IAAU;QACxE,mCAAmC;QACnC,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAC/D,SAAS,CAAC,SAAS,CACpB,CAAC;QACF,MAAM,mBAAmB,GAAG,SAAS,CAAC,YAAY;YAChD,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC,SAAS,CAAC,YAAY,CAAC;YACvE,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,iBAAiB,GAAG,SAAS,CAAC,UAAU;YAC5C,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,CAAC,UAAU,CAAC,GAAG,CACtB,KAAK,EAAE,CAAC,EAA8B,EAAE,CAAC,CAAC;gBACxC,cAAc,EAAE,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAC3D,CAAC,CAAC,cAAc,CACjB;gBACD,IAAI,EAAE,CAAC,CAAC,IAAI;aACb,CAAC,CACH,CACF;YACH,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YACvC,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,0BAAiB,CAAC,yBAAyB,CAAC,CAAC;QAElE,IAAI,SAAS,GAAG,IAAI,CAAC,qBAAqB,CAAC;QAC3C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC9D,IAAI,QAAQ;gBAAE,SAAS,GAAG,QAAQ,CAAC,qBAAqB,CAAC;QAC3D,CAAC;QAED,IAAI,mBAAmB,IAAI,mBAAmB,KAAK,SAAS,EAAE,CAAC;YAC7D,kCAAkC;YAClC,SAAS,GAAG,mBAAmB,CAAC;QAClC,CAAC;QAED,0CAA0C;QAC1C,MAAM,WAAW,GAAG,iBAAiB,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACpE,MAAM,uBAAuB,GAAG,WAAW,EAAE,cAAc,CAAC;QAE5D,IAAI,aAAa,GAAG,EAAE,CAAC;QACvB,IAAI,uBAAuB,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,kCAAY,EAAE;gBACjE,KAAK,EAAE,EAAE,EAAE,EAAE,uBAAuB,EAAE;aACvC,CAAC,CAAC;YACH,IAAI,MAAM;gBAAE,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;QACtD,CAAC;QAED,OAAO,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC;YACzC,SAAS,EAAE,gBAAgB;YAC3B,wBAAwB,EAAE,SAAU;YACpC,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,uBAAuB;YACvB,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC9B,YAAY,EAAE;gBACZ,SAAS,EAAE,IAAI,CAAC,QAAQ;gBACxB,cAAc,EAAE,aAAa;gBAC7B,QAAQ,EAAE,aAAa;aACxB;SACF,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,CAAC,QAAgB,EAAE,MAAc,EAAE,IAAU;QACvD,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAE1D,wEAAwE;QACxE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5E,MAAM,SAAS,GACb,WAAW,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YAC7C,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QAE5C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,2BAAkB,CAC1B,gDAAgD,CACjD,CAAC;QACJ,CAAC;QAED,6CAA6C;QAC7C,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;QACrE,MAAM,kBAAkB,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC;YACpD,KAAK,EAAE;gBACL,gBAAgB,EAAE,cAAc,CAAC,EAAE;gBACnC,MAAM,EAAE,MAAM;aACf;SACF,CAAC,CAAC;QAEH,MAAM,cAAc,GAClB,kBAAkB,CAAC,MAAM,GAAG,CAAC;YAC3B,CAAC,CAAC,aAAa,kBAAkB,CAAC,MAAM,sGAAsG;YAC9I,CAAC,CAAC,EAAE,CAAC;QAET,4CAA4C;QAC5C,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;YACtD,KAAK,EAAE;gBACL,gBAAgB,EAAE,cAAc,CAAC,EAAE;gBACnC,SAAS,EAAE,IAAI;aAChB;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,0BAAiB,CAAC,4BAA4B,CAAC,CAAC;QAC5D,CAAC;QAED,uBAAuB;QACvB,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YACpD,KAAK,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE;SACnC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,qCAA4B,CAAC,4BAA4B,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC;QACxD,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;QAC5B,MAAM,WAAW,CAAC,gBAAgB,EAAE,CAAC;QAErC,IAAI,CAAC;YACH,qDAAqD;YACrD,MAAM,WAAW,CAAC,OAAO,CAAC,MAAM,CAC9B,uDAAsB,EACtB,eAAe,CAAC,EAAE,EAClB;gBACE,QAAQ,EAAE,eAAe,CAAC,EAAE;gBAC5B,OAAO,EAAE,cAAc,MAAM,EAAE;aAChC,CACF,CAAC;YAEF,sCAAsC;YACtC,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClC,MAAM,WAAW,CAAC,OAAO,CAAC,MAAM,CAC9B,aAAa,EACb;oBACE,gBAAgB,EAAE,cAAc,CAAC,EAAE;oBACnC,MAAM,EAAE,MAAM;iBACf,EACD;oBACE,MAAM,EAAE,cAAc;oBACtB,QAAQ,EAAE,IAAI,IAAI,EAAE;oBACpB,QAAQ,EAAE,IAAI,CAAC,OAAO;oBACtB,WAAW,EAAE,6BAA6B,MAAM,EAAE;iBACnD,CACF,CAAC;YACJ,CAAC;YAED,MAAM,WAAW,CAAC,iBAAiB,EAAE,CAAC;YAEtC,+DAA+D;YAC/D,KAAK,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC;gBACpC,EAAE,EAAE,cAAc,CAAC,EAAE;gBACrB,QAAQ,EAAE,cAAc,CAAC,QAAQ;gBACjC,IAAI,EAAE,gBAAgB;gBACtB,SAAS,EAAE,cAAc,CAAC,oBAAoB;gBAC9C,KAAK,EAAE,eAAe,CAAC,OAAO;gBAC9B,MAAM,EAAE,WAAW;gBACnB,SAAS,EAAE,cAAc,CAAC,SAAS;gBACnC,SAAS,EAAE,cAAc,CAAC,SAAS;aACpC,CAAC,CAAC;YAEH,4EAA4E;YAC5E,IAAI,cAAc,CAAC,YAAY,EAAE,CAAC;gBAChC,KAAK,IAAI,CAAC,WAAW;qBAClB,qBAAqB,CAAC,cAAc,CAAC,YAAY,CAAC;qBAClD,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE;oBACrB,IAAI,YAAY,EAAE,CAAC;wBACjB,KAAK,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;4BACjC,MAAM,EAAE,YAAY;4BACpB,KAAK,EAAE,0BAA0B;4BACjC,OAAO,EAAE,GAAG,cAAc,CAAC,oBAAoB,MAAM,eAAe,CAAC,OAAO,gCAAgC,MAAM,EAAE;4BACpH,IAAI,EAAE,OAAO;4BACb,UAAU,EAAE,gBAAgB;4BAC5B,QAAQ,EAAE,cAAc,CAAC,EAAE;4BAC3B,IAAI,EAAE,oBAAoB,cAAc,CAAC,QAAQ,EAAE;yBACpD,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC,CAAC;qBACD,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE,CACpB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAC/D,CAAC;YACN,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,cAAc,IAAI,uCAAuC;gBAClE,uBAAuB,EAAE,kBAAkB,CAAC,MAAM;aACnD,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,WAAW,CAAC,mBAAmB,EAAE,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,oCAAqC,KAAe,CAAC,OAAO,EAAE,CAC/D,CAAC;YACF,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CACd,SAAmB,EACnB,MAAc,EACd,IAAU;QAEV,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC1C,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC3B,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,SAAkC;QAChD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAE/C,MAAM,MAAM,GAAG;YACb,cAAc;YACd,KAAK;YACL,SAAS;YACT,MAAM;YACN,QAAQ;YACR,SAAS;YACT,MAAM;YACN,UAAU;YACV,YAAY;SACb,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,cAAc,IAAK,GAAiC,CAAC;YACtE,OAAO;gBACL,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,IAAI,EAAE,CAAC;gBAC/C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,IAAI,MAAM,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,CAAC,CAAC;gBACpE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;gBACjC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,IAAI,EAAE,CAAC;gBAC5C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,IAAI,EAAE,CAAC;gBAC/C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,IAAI,EAAE,CAAC;gBACvD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;gBACpE,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;aACpD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC;IAEO,SAAS,CAAC,KAAa;QAC7B,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACvE,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;QAC1C,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAA;AA9jCY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;IAuBR,WAAA,IAAA,0BAAgB,EAAC,sCAAc,CAAC,CAAA;IAEhC,WAAA,IAAA,0BAAgB,EAAC,uDAAsB,CAAC,CAAA;IAExC,WAAA,IAAA,0BAAgB,EAAC,+CAAkB,CAAC,CAAA;IAEpC,WAAA,IAAA,0BAAgB,EAAC,mDAAoB,CAAC,CAAA;IAEtC,WAAA,IAAA,0BAAgB,EAAC,yDAAuB,CAAC,CAAA;IAEzC,WAAA,IAAA,0BAAgB,EAAC,6CAAiB,CAAC,CAAA;yDATR,oBAAU,oBAAV,oBAAU,oDAEhB,oBAAU,oBAAV,oBAAU,oDAEd,oBAAU,oBAAV,oBAAU,oDAER,oBAAU,oBAAV,oBAAU,oDAEP,oBAAU,oBAAV,oBAAU,oDAEhB,oBAAU,oBAAV,oBAAU,oDACD,qDAAwB,oBAAxB,qDAAwB,oDACvB,uCAAiB,oBAAjB,uCAAiB,oDACpB,+CAAqB,oBAArB,+CAAqB,oDACxB,0BAAW,oBAAX,0BAAW,oDACZ,oBAAU,oBAAV,oBAAU,oDACP,8BAAa,oBAAb,8BAAa,oDACR,yCAAkB,oBAAlB,yCAAkB,oDACxB,2CAAmB,oBAAnB,2CAAmB,oDACZ,0CAAmB,oBAAnB,0CAAmB;GA1CvC,qBAAqB,CA8jCjC","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.ts"],"sourcesContent":["// File: src/modules/correspondence/correspondence.service.ts\r\n\r\nimport {\r\n Injectable,\r\n NotFoundException,\r\n BadRequestException,\r\n InternalServerErrorException,\r\n ForbiddenException,\r\n Logger,\r\n} from '@nestjs/common';\r\nimport { InjectRepository } from '@nestjs/typeorm';\r\nimport { Repository, DataSource } from 'typeorm';\r\n\r\n// Entities\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Tag } from '../master/entities/tag.entity';\r\nimport { User } from '../user/entities/user.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\n\r\n// DTOs\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { AddReferenceDto } from './dto/add-reference.dto';\r\nimport { SearchCorrespondenceDto } from './dto/search-correspondence.dto';\r\n\r\n// Services\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\n\r\n/**\r\n * CorrespondenceService - Document management (CRUD)\r\n */\r\ninterface ResolvedRecipient {\r\n organizationId: number;\r\n type: 'TO' | 'CC';\r\n}\r\n@Injectable()\r\nexport class CorrespondenceService {\r\n private readonly logger = new Logger(CorrespondenceService.name);\r\n\r\n private async hasSystemManageAllPermission(userId: number): Promise {\r\n const permissions = await this.userService.getUserPermissions(userId);\r\n return permissions.includes('system.manage_all');\r\n }\r\n\r\n /**\r\n * Business Rule: Revision Label Strategy\r\n * - RFA, RFI: Use alphabet starting with 'A' (A, B, C...)\r\n * - Other types (LETTER, MEMO, etc.): Use numeric (null for first, then 1, 2, 3...)\r\n */\r\n private getInitialRevisionLabel(typeCode: string): string | undefined {\r\n const alphabetTypes = ['RFA', 'RFI'];\r\n if (alphabetTypes.includes(typeCode.toUpperCase())) {\r\n return 'A'; // Alphabet for RFA, RFI\r\n }\r\n return undefined; // Numeric (no label for revision 0)\r\n }\r\n\r\n constructor(\r\n @InjectRepository(Correspondence)\r\n private correspondenceRepo: Repository,\r\n @InjectRepository(CorrespondenceRevision)\r\n private revisionRepo: Repository,\r\n @InjectRepository(CorrespondenceType)\r\n private typeRepo: Repository,\r\n @InjectRepository(CorrespondenceStatus)\r\n private statusRepo: Repository,\r\n @InjectRepository(CorrespondenceReference)\r\n private referenceRepo: Repository,\r\n @InjectRepository(CorrespondenceTag)\r\n private tagRepo: Repository,\r\n private numberingService: DocumentNumberingService,\r\n private jsonSchemaService: JsonSchemaService,\r\n private workflowEngine: WorkflowEngineService,\r\n private userService: UserService,\r\n private dataSource: DataSource,\r\n private searchService: SearchService,\r\n private fileStorageService: FileStorageService,\r\n private uuidResolver: UuidResolverService,\r\n private notificationService: NotificationService\r\n ) {}\r\n\r\n /**\r\n * Business Rule Validation: EC-CORR-003 - Correspondence to Self\r\n * Prevent external correspondence to same organization\r\n */\r\n private async validateCorrespondenceRecipients(\r\n createDto: CreateCorrespondenceDto,\r\n user: User\r\n ): Promise {\r\n // Get user's organization\r\n let userOrgId = user.primaryOrganizationId;\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) {\r\n userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n }\r\n\r\n if (!userOrgId) {\r\n if (createDto.originatorId) {\r\n const canManageAll = await this.hasSystemManageAllPermission(\r\n user.user_id\r\n );\r\n if (canManageAll) {\r\n userOrgId = await this.uuidResolver.resolveOrganizationId(\r\n createDto.originatorId\r\n );\r\n }\r\n }\r\n\r\n if (!userOrgId) {\r\n throw new BadRequestException(\r\n 'User must belong to an organization to create documents'\r\n );\r\n }\r\n }\r\n\r\n // For impersonation, use the specified originator\r\n const originatorOrgId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : userOrgId;\r\n\r\n // Check if it's internal communication\r\n if (createDto.isInternal) {\r\n // Internal communications should use Circulation instead\r\n throw new BadRequestException(\r\n 'Internal communications should use Circulation Sheet instead of Correspondence'\r\n );\r\n }\r\n\r\n // Validate recipients\r\n if (!createDto.recipients || createDto.recipients.length === 0) {\r\n throw new BadRequestException(\r\n 'At least one recipient (TO or CC) is required'\r\n );\r\n }\r\n\r\n const toRecipients = createDto.recipients.filter((r) => r.type === 'TO');\r\n const ccRecipients = createDto.recipients.filter((r) => r.type === 'CC');\r\n\r\n if (toRecipients.length === 0 && ccRecipients.length === 0) {\r\n throw new BadRequestException(\r\n 'At least one TO or CC recipient is required'\r\n );\r\n }\r\n\r\n // Check for same organization correspondence\r\n for (const recipient of createDto.recipients) {\r\n const recipientOrgId = await this.uuidResolver.resolveOrganizationId(\r\n recipient.organizationId\r\n );\r\n\r\n if (recipientOrgId === originatorOrgId) {\r\n throw new BadRequestException(\r\n 'Cannot send correspondence to your own organization. Use Circulation Sheet for internal communication.'\r\n );\r\n }\r\n }\r\n }\r\n\r\n async create(createDto: CreateCorrespondenceDto, user: User) {\r\n // Business Rule Validation: EC-CORR-003 - Correspondence to Self\r\n await this.validateCorrespondenceRecipients(createDto, user);\r\n // ADR-019: Resolve UUID references to internal INT IDs\r\n const resolvedProjectId = await this.uuidResolver.resolveProjectId(\r\n createDto.projectId\r\n );\r\n const resolvedOriginatorId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : undefined;\r\n const resolvedRecipients = createDto.recipients\r\n ? await Promise.all(\r\n createDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n const type = await this.typeRepo.findOne({\r\n where: { id: createDto.typeId },\r\n });\r\n if (!type) throw new NotFoundException('Document Type not found');\r\n\r\n const statusDraft = await this.statusRepo.findOne({\r\n where: { statusCode: 'DRAFT' },\r\n });\r\n if (!statusDraft) {\r\n throw new InternalServerErrorException(\r\n 'Status DRAFT not found in Master Data'\r\n );\r\n }\r\n\r\n let userOrgId = user.primaryOrganizationId;\r\n\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) {\r\n userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n }\r\n\r\n // Impersonation Logic\r\n if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {\r\n const canManageAll = await this.hasSystemManageAllPermission(\r\n user.user_id\r\n );\r\n if (!canManageAll) {\r\n throw new ForbiddenException(\r\n 'You do not have permission to create documents on behalf of other organizations.'\r\n );\r\n }\r\n userOrgId = resolvedOriginatorId;\r\n }\r\n\r\n if (!userOrgId) {\r\n throw new BadRequestException(\r\n 'User must belong to an organization to create documents'\r\n );\r\n }\r\n\r\n if (createDto.details) {\r\n try {\r\n await this.jsonSchemaService.validate(type.typeCode, createDto.details);\r\n } catch (error: unknown) {\r\n this.logger.warn(\r\n `Schema validation warning for ${type.typeCode}: ${(error as Error).message}`\r\n );\r\n }\r\n }\r\n\r\n const queryRunner = this.dataSource.createQueryRunner();\r\n await queryRunner.connect();\r\n await queryRunner.startTransaction();\r\n\r\n try {\r\n // [Fix #6] Fetch real ORG Code from Organization entity\r\n const originatorOrg = await this.dataSource.manager.findOne(\r\n Organization,\r\n {\r\n where: { id: userOrgId },\r\n }\r\n );\r\n const orgCode = originatorOrg?.organizationCode ?? 'UNK';\r\n\r\n // [v1.5.1] Extract recipient organization from recipients array (Primary TO)\r\n const toRecipient = resolvedRecipients?.find((r) => r.type === 'TO');\r\n const recipientOrganizationId = toRecipient?.organizationId;\r\n\r\n let recipientCode = '';\r\n if (recipientOrganizationId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: recipientOrganizationId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n const docNumber = await this.numberingService.generateNextNumber({\r\n projectId: resolvedProjectId,\r\n originatorOrganizationId: userOrgId,\r\n typeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n subTypeId: createDto.subTypeId,\r\n recipientOrganizationId, // [v1.5.1] Pass recipient for document number format\r\n year: new Date().getFullYear(),\r\n customTokens: {\r\n TYPE_CODE: type.typeCode,\r\n ORG_CODE: orgCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n });\r\n\r\n const correspondence = queryRunner.manager.create(Correspondence, {\r\n correspondenceNumber: docNumber.number,\r\n correspondenceTypeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n projectId: resolvedProjectId,\r\n originatorId: userOrgId,\r\n isInternal: createDto.isInternal || false,\r\n createdBy: user.user_id,\r\n });\r\n const savedCorr = await queryRunner.manager.save(correspondence);\r\n\r\n const revision = queryRunner.manager.create(CorrespondenceRevision, {\r\n correspondenceId: savedCorr.id,\r\n revisionNumber: 0,\r\n revisionLabel: this.getInitialRevisionLabel(type.typeCode),\r\n isCurrent: true,\r\n statusId: statusDraft.id,\r\n subject: createDto.subject,\r\n body: createDto.body,\r\n remarks: createDto.remarks,\r\n dueDate: createDto.dueDate ? new Date(createDto.dueDate) : undefined,\r\n documentDate: createDto.documentDate\r\n ? new Date(createDto.documentDate)\r\n : undefined,\r\n issuedDate: createDto.issuedDate\r\n ? new Date(createDto.issuedDate)\r\n : undefined,\r\n receivedDate: createDto.receivedDate\r\n ? new Date(createDto.receivedDate)\r\n : undefined,\r\n description: createDto.description,\r\n details: createDto.details,\r\n createdBy: user.user_id,\r\n schemaVersion: 1,\r\n });\r\n await queryRunner.manager.save(revision);\r\n\r\n // Save Recipients (using resolved INT IDs)\r\n if (resolvedRecipients && resolvedRecipients.length > 0) {\r\n const recipients = resolvedRecipients.map((r) =>\r\n queryRunner.manager.create(CorrespondenceRecipient, {\r\n correspondenceId: savedCorr.id,\r\n recipientOrganizationId: r.organizationId,\r\n recipientType: r.type,\r\n })\r\n );\r\n await queryRunner.manager.save(recipients);\r\n }\r\n\r\n // Commit attachments from Temp → Permanent (Two-Phase Storage)\r\n if (createDto.attachmentTempIds?.length) {\r\n const issueDate = createDto.issuedDate\r\n ? new Date(createDto.issuedDate)\r\n : createDto.documentDate\r\n ? new Date(createDto.documentDate)\r\n : undefined;\r\n\r\n await this.fileStorageService.commit(createDto.attachmentTempIds, {\r\n issueDate,\r\n documentType: 'Correspondence',\r\n });\r\n }\r\n\r\n await queryRunner.commitTransaction();\r\n\r\n // Start Workflow Instance (non-blocking)\r\n try {\r\n const workflowCode = `CORRESPONDENCE_${type.typeCode}`;\r\n await this.workflowEngine.createInstance(\r\n workflowCode,\r\n 'correspondence',\r\n savedCorr.id.toString(),\r\n {\r\n projectId: resolvedProjectId,\r\n originatorId: userOrgId,\r\n disciplineId: createDto.disciplineId,\r\n initiatorId: user.user_id,\r\n } as Record\r\n );\r\n } catch (error: unknown) {\r\n this.logger.warn(\r\n `Workflow not started for ${docNumber.number} (Code: CORRESPONDENCE_${type.typeCode}): ${(error as Error).message}`\r\n );\r\n }\r\n\r\n // Fire-and-forget search indexing (non-blocking, void intentional)\r\n void this.searchService.indexDocument({\r\n id: savedCorr.id,\r\n publicId: savedCorr.publicId,\r\n type: 'correspondence',\r\n docNumber: docNumber.number,\r\n title: createDto.subject,\r\n description: createDto.description,\r\n status: 'DRAFT',\r\n projectId: resolvedProjectId,\r\n createdAt: new Date(),\r\n });\r\n\r\n return {\r\n ...savedCorr,\r\n currentRevision: revision,\r\n };\r\n } catch (err) {\r\n await queryRunner.rollbackTransaction();\r\n this.logger.error(\r\n `Failed to create correspondence: ${(err as Error).message}`\r\n );\r\n throw err;\r\n } finally {\r\n await queryRunner.release();\r\n }\r\n }\r\n\r\n async findAll(searchDto: SearchCorrespondenceDto = {}) {\r\n const {\r\n search,\r\n typeId,\r\n projectId,\r\n statusId,\r\n status,\r\n page = 1,\r\n limit = 10,\r\n } = searchDto;\r\n const skip = (page - 1) * limit;\r\n\r\n // Change: Query from Revision Repo\r\n const query = this.revisionRepo\r\n .createQueryBuilder('rev')\r\n .leftJoinAndSelect('rev.correspondence', 'corr')\r\n .leftJoinAndSelect('corr.type', 'type')\r\n .leftJoinAndSelect('corr.project', 'project')\r\n .leftJoinAndSelect('corr.originator', 'org')\r\n .leftJoinAndSelect('rev.status', 'status');\r\n\r\n // Filter by Revision Status\r\n const revStatus = searchDto.revisionStatus || 'CURRENT';\r\n\r\n if (revStatus === 'CURRENT') {\r\n query.where('rev.isCurrent = :isCurrent', { isCurrent: true });\r\n } else if (revStatus === 'OLD') {\r\n query.where('rev.isCurrent = :isCurrent', { isCurrent: false });\r\n }\r\n // If 'ALL', no filter needed on isCurrent\r\n\r\n if (projectId) {\r\n query.andWhere('corr.projectId = :projectId', { projectId });\r\n }\r\n\r\n if (typeId) {\r\n query.andWhere('corr.correspondenceTypeId = :typeId', { typeId });\r\n }\r\n\r\n if (statusId) {\r\n query.andWhere('rev.statusId = :statusId', { statusId });\r\n }\r\n\r\n if (status) {\r\n query.andWhere('status.statusCode = :status', { status });\r\n }\r\n\r\n if (search) {\r\n query.andWhere(\r\n '(corr.correspondenceNumber LIKE :search OR rev.subject LIKE :search)',\r\n { search: `%${search}%` }\r\n );\r\n }\r\n\r\n // Default Sort: Latest Created\r\n query.orderBy('rev.createdAt', 'DESC').skip(skip).take(limit);\r\n\r\n const [items, total] = await query.getManyAndCount();\r\n\r\n return {\r\n data: items,\r\n meta: {\r\n total,\r\n page,\r\n limit,\r\n totalPages: Math.ceil(total / limit),\r\n },\r\n };\r\n }\r\n\r\n async findOne(id: number) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n relations: [\r\n 'revisions',\r\n 'revisions.status',\r\n 'type',\r\n 'project',\r\n 'originator',\r\n 'recipients',\r\n 'recipients.recipientOrganization', // [v1.5.1] Fixed relation name\r\n ],\r\n });\r\n\r\n if (!correspondence) {\r\n throw new NotFoundException(`Correspondence with ID ${id} not found`);\r\n }\r\n return correspondence;\r\n }\r\n\r\n async findOneByUuid(publicId: string) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { publicId },\r\n relations: [\r\n 'revisions',\r\n 'revisions.status',\r\n 'type',\r\n 'project',\r\n 'originator',\r\n 'recipients',\r\n 'recipients.recipientOrganization',\r\n ],\r\n });\r\n\r\n if (!correspondence) {\r\n throw new NotFoundException(\r\n `Correspondence with UUID ${publicId} not found`\r\n );\r\n }\r\n return correspondence;\r\n }\r\n\r\n async addReference(id: number, dto: AddReferenceDto) {\r\n const source = await this.correspondenceRepo.findOne({ where: { id } });\r\n // ADR-019: Resolve target publicId → internal INT id\r\n const target = await this.correspondenceRepo.findOne({\r\n where: { publicId: dto.targetUuid },\r\n });\r\n\r\n if (!source || !target) {\r\n throw new NotFoundException('Source or Target correspondence not found');\r\n }\r\n\r\n if (source.id === target.id) {\r\n throw new BadRequestException('Cannot reference self');\r\n }\r\n\r\n const exists = await this.referenceRepo.findOne({\r\n where: {\r\n sourceId: id,\r\n targetId: target.id,\r\n },\r\n });\r\n\r\n if (exists) {\r\n return exists;\r\n }\r\n\r\n const ref = this.referenceRepo.create({\r\n sourceId: id,\r\n targetId: target.id,\r\n });\r\n\r\n return this.referenceRepo.save(ref);\r\n }\r\n\r\n async removeReference(id: number, targetId: number) {\r\n const result = await this.referenceRepo.delete({\r\n sourceId: id,\r\n targetId: targetId,\r\n });\r\n\r\n if (result.affected === 0) {\r\n throw new NotFoundException('Reference not found');\r\n }\r\n }\r\n\r\n async getTags(id: number) {\r\n const rows = await this.tagRepo.find({\r\n where: { correspondenceId: id },\r\n relations: ['tag'],\r\n });\r\n return rows.map((r) => r.tag).filter(Boolean);\r\n }\r\n\r\n async addTag(id: number, tagId: number) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n });\r\n if (!correspondence) {\r\n throw new NotFoundException(`Correspondence ${id} not found`);\r\n }\r\n\r\n const tag = await this.dataSource.manager.findOne(Tag, {\r\n where: { id: tagId },\r\n });\r\n if (!tag) {\r\n throw new NotFoundException(`Tag ${tagId} not found`);\r\n }\r\n\r\n const exists = await this.tagRepo.findOne({\r\n where: { correspondenceId: id, tagId },\r\n });\r\n if (exists) return exists;\r\n\r\n const row = this.tagRepo.create({ correspondenceId: id, tagId });\r\n return this.tagRepo.save(row);\r\n }\r\n\r\n async removeTag(id: number, tagId: number) {\r\n const result = await this.tagRepo.delete({ correspondenceId: id, tagId });\r\n if (result.affected === 0) {\r\n throw new NotFoundException('Tag assignment not found');\r\n }\r\n }\r\n\r\n async getReferences(id: number) {\r\n const outgoing = await this.referenceRepo.find({\r\n where: { sourceId: id },\r\n relations: ['target', 'target.type'],\r\n });\r\n\r\n const incoming = await this.referenceRepo.find({\r\n where: { targetId: id },\r\n relations: ['source', 'source.type'],\r\n });\r\n\r\n return { outgoing, incoming };\r\n }\r\n\r\n async update(id: number, updateDto: UpdateCorrespondenceDto, user: User) {\r\n // 1. Find Current Revision\r\n const revision = await this.revisionRepo.findOne({\r\n where: {\r\n correspondenceId: id,\r\n isCurrent: true,\r\n },\r\n relations: ['correspondence'],\r\n });\r\n\r\n if (!revision) {\r\n throw new NotFoundException(\r\n `Current revision for correspondence ${id} not found`\r\n );\r\n }\r\n\r\n // 2. Check Permission\r\n if (revision.statusId) {\r\n const status = await this.statusRepo.findOne({\r\n where: { id: revision.statusId },\r\n });\r\n\r\n if (status && status.statusCode !== 'DRAFT') {\r\n const permissions = await this.userService.getUserPermissions(\r\n user.user_id\r\n );\r\n const canEditSubmittedOrLater =\r\n permissions.includes('correspondence.cancel') ||\r\n permissions.includes('system.manage_all');\r\n\r\n if (!canEditSubmittedOrLater) {\r\n throw new ForbiddenException(\r\n 'Only Org Admin or Superadmin can edit non-draft correspondences'\r\n );\r\n }\r\n }\r\n }\r\n\r\n // ADR-019: Resolve UUID references in update DTO\r\n const updResolvedProjectId = updateDto.projectId\r\n ? await this.uuidResolver.resolveProjectId(updateDto.projectId)\r\n : undefined;\r\n const updResolvedOriginatorId = updateDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(updateDto.originatorId)\r\n : undefined;\r\n const updResolvedRecipients = updateDto.recipients\r\n ? await Promise.all(\r\n updateDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n\r\n // 3. Update Correspondence Entity if needed\r\n const correspondenceUpdate: Record = {};\r\n if (updateDto.disciplineId)\r\n correspondenceUpdate.disciplineId = updateDto.disciplineId;\r\n if (updResolvedProjectId)\r\n correspondenceUpdate.projectId = updResolvedProjectId;\r\n if (updResolvedOriginatorId)\r\n correspondenceUpdate.originatorId = updResolvedOriginatorId;\r\n\r\n if (Object.keys(correspondenceUpdate).length > 0) {\r\n await this.correspondenceRepo.update(id, correspondenceUpdate);\r\n }\r\n\r\n // 4. Update Revision Entity\r\n const revisionUpdate: Record = {};\r\n if (updateDto.subject) revisionUpdate.subject = updateDto.subject;\r\n if (updateDto.body) revisionUpdate.body = updateDto.body;\r\n if (updateDto.remarks) revisionUpdate.remarks = updateDto.remarks;\r\n // Format Date correctly if string\r\n if (updateDto.dueDate) revisionUpdate.dueDate = new Date(updateDto.dueDate);\r\n if (updateDto.documentDate)\r\n revisionUpdate.documentDate = new Date(updateDto.documentDate);\r\n if (updateDto.issuedDate)\r\n revisionUpdate.issuedDate = new Date(updateDto.issuedDate);\r\n if (updateDto.receivedDate)\r\n revisionUpdate.receivedDate = new Date(updateDto.receivedDate);\r\n if (updateDto.description)\r\n revisionUpdate.description = updateDto.description;\r\n if (updateDto.details) revisionUpdate.details = updateDto.details;\r\n\r\n if (Object.keys(revisionUpdate).length > 0) {\r\n await this.revisionRepo.update(revision.id, revisionUpdate);\r\n }\r\n\r\n // 4.5 Commit new attachments from Temp → Permanent (Two-Phase Storage)\r\n if (updateDto.attachmentTempIds?.length) {\r\n const issueDate = updateDto.issuedDate\r\n ? new Date(updateDto.issuedDate)\r\n : updateDto.documentDate\r\n ? new Date(updateDto.documentDate)\r\n : revision.issuedDate || revision.documentDate || undefined;\r\n\r\n await this.fileStorageService.commit(updateDto.attachmentTempIds, {\r\n issueDate: issueDate ? new Date(issueDate) : undefined,\r\n documentType: 'Correspondence',\r\n });\r\n }\r\n\r\n // 5. Update Recipients if provided\r\n if (updResolvedRecipients) {\r\n const recipientRepo = this.dataSource.getRepository(\r\n CorrespondenceRecipient\r\n );\r\n await recipientRepo.delete({ correspondenceId: id });\r\n\r\n const newRecipients = updResolvedRecipients.map((r) =>\r\n recipientRepo.create({\r\n correspondenceId: id,\r\n recipientOrganizationId: r.organizationId,\r\n recipientType: r.type,\r\n })\r\n );\r\n await recipientRepo.save(newRecipients);\r\n }\r\n\r\n // 6. Regenerate Document Number if structural fields changed (Recipient, Discipline, Type, Project)\r\n // AND it is a DRAFT.\r\n\r\n // Fetch fresh data for context and comparison\r\n const currentCorr = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n relations: ['type', 'recipients', 'recipients.recipientOrganization'],\r\n });\r\n\r\n if (currentCorr) {\r\n const currentToRecipient = currentCorr.recipients?.find(\r\n (r) => r.recipientType === 'TO'\r\n );\r\n const currentRecipientId = currentToRecipient?.recipientOrganizationId;\r\n\r\n // Check for ACTUAL value changes\r\n const isProjectChanged =\r\n updResolvedProjectId !== undefined &&\r\n updResolvedProjectId !== currentCorr.projectId;\r\n const isOriginatorChanged =\r\n updResolvedOriginatorId !== undefined &&\r\n updResolvedOriginatorId !== currentCorr.originatorId;\r\n const isDisciplineChanged =\r\n updateDto.disciplineId !== undefined &&\r\n updateDto.disciplineId !== currentCorr.disciplineId;\r\n const isTypeChanged =\r\n updateDto.typeId !== undefined &&\r\n updateDto.typeId !== currentCorr.correspondenceTypeId;\r\n\r\n let isRecipientChanged = false;\r\n let newRecipientId: number | undefined;\r\n\r\n if (updResolvedRecipients) {\r\n const newToRecipient = updResolvedRecipients.find(\r\n (r) => r.type === 'TO'\r\n );\r\n newRecipientId = newToRecipient?.organizationId;\r\n\r\n if (newRecipientId !== currentRecipientId) {\r\n isRecipientChanged = true;\r\n }\r\n }\r\n\r\n if (\r\n isProjectChanged ||\r\n isDisciplineChanged ||\r\n isTypeChanged ||\r\n isRecipientChanged ||\r\n isOriginatorChanged\r\n ) {\r\n const targetRecipientId = isRecipientChanged\r\n ? newRecipientId\r\n : currentRecipientId;\r\n\r\n // Resolve Recipient Code for the NEW context\r\n let recipientCode = '';\r\n if (targetRecipientId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: targetRecipientId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n // [Fix #6] Fetch real ORG Code from originator organization\r\n const originatorOrgForUpdate = await this.dataSource.manager.findOne(\r\n Organization,\r\n {\r\n where: {\r\n id: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0,\r\n },\r\n }\r\n );\r\n const orgCode = originatorOrgForUpdate?.organizationCode ?? 'UNK';\r\n\r\n // Prepare Contexts\r\n const oldCtx = {\r\n projectId: currentCorr.projectId,\r\n originatorOrganizationId: currentCorr.originatorId ?? 0,\r\n typeId: currentCorr.correspondenceTypeId,\r\n disciplineId: currentCorr.disciplineId,\r\n recipientOrganizationId: currentRecipientId,\r\n year: new Date().getFullYear(),\r\n };\r\n\r\n const newCtx = {\r\n projectId: updResolvedProjectId ?? currentCorr.projectId,\r\n originatorOrganizationId:\r\n updResolvedOriginatorId ?? currentCorr.originatorId ?? 0,\r\n typeId: updateDto.typeId ?? currentCorr.correspondenceTypeId,\r\n disciplineId: updateDto.disciplineId ?? currentCorr.disciplineId,\r\n recipientOrganizationId: targetRecipientId,\r\n year: new Date().getFullYear(),\r\n userId: user.user_id, // Pass User ID for Audit\r\n customTokens: {\r\n TYPE_CODE: currentCorr.type?.typeCode || '',\r\n ORG_CODE: orgCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n };\r\n\r\n // If Type Changed, need NEW Type Code\r\n if (isTypeChanged) {\r\n const newType = await this.typeRepo.findOne({\r\n where: { id: newCtx.typeId },\r\n });\r\n if (newType) newCtx.customTokens.TYPE_CODE = newType.typeCode;\r\n }\r\n\r\n const newDocNumber = await this.numberingService.updateNumberForDraft(\r\n currentCorr.correspondenceNumber,\r\n oldCtx,\r\n newCtx\r\n );\r\n\r\n await this.correspondenceRepo.update(id, {\r\n correspondenceNumber: newDocNumber,\r\n });\r\n }\r\n }\r\n\r\n const updated = await this.findOne(id);\r\n\r\n // Re-index updated document in Elasticsearch (fire-and-forget)\r\n void this.searchService.indexDocument({\r\n id: updated.id,\r\n publicId: updated.publicId,\r\n type: 'correspondence',\r\n docNumber: updated.correspondenceNumber,\r\n title: updateDto.subject ?? updated.revisions?.[0]?.subject,\r\n description: updateDto.description ?? updated.revisions?.[0]?.description,\r\n status: 'DRAFT',\r\n projectId: updated.projectId,\r\n createdAt: updated.createdAt,\r\n });\r\n\r\n return updated;\r\n }\r\n\r\n async previewDocumentNumber(createDto: CreateCorrespondenceDto, user: User) {\r\n // ADR-019: Resolve UUID references\r\n const previewProjectId = await this.uuidResolver.resolveProjectId(\r\n createDto.projectId\r\n );\r\n const previewOriginatorId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : undefined;\r\n const previewRecipients = createDto.recipients\r\n ? await Promise.all(\r\n createDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n\r\n const type = await this.typeRepo.findOne({\r\n where: { id: createDto.typeId },\r\n });\r\n if (!type) throw new NotFoundException('Document Type not found');\r\n\r\n let userOrgId = user.primaryOrganizationId;\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n\r\n if (previewOriginatorId && previewOriginatorId !== userOrgId) {\r\n // Allow impersonation for preview\r\n userOrgId = previewOriginatorId;\r\n }\r\n\r\n // Extract recipient from recipients array\r\n const toRecipient = previewRecipients?.find((r) => r.type === 'TO');\r\n const recipientOrganizationId = toRecipient?.organizationId;\r\n\r\n let recipientCode = '';\r\n if (recipientOrganizationId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: recipientOrganizationId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n return this.numberingService.previewNumber({\r\n projectId: previewProjectId,\r\n originatorOrganizationId: userOrgId!,\r\n typeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n subTypeId: createDto.subTypeId,\r\n recipientOrganizationId,\r\n year: new Date().getFullYear(),\r\n customTokens: {\r\n TYPE_CODE: type.typeCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Business Rule Implementation: EC-CORR-001 - Cancel Correspondence with Downstream Circulation\r\n * Cancel correspondence and handle related circulations\r\n */\r\n async cancel(publicId: string, reason: string, user: User) {\r\n const correspondence = await this.findOneByUuid(publicId);\r\n\r\n // Check if user has permission to cancel (Org Admin or Superadmin only)\r\n const permissions = await this.userService.getUserPermissions(user.user_id);\r\n const canCancel =\r\n permissions.includes('correspondence.cancel') ||\r\n permissions.includes('system.manage_all');\r\n\r\n if (!canCancel) {\r\n throw new ForbiddenException(\r\n 'Only administrators can cancel correspondences'\r\n );\r\n }\r\n\r\n // Check if there are any active circulations\r\n const circulationRepo = this.dataSource.getRepository('Circulation');\r\n const activeCirculations = await circulationRepo.find({\r\n where: {\r\n correspondenceId: correspondence.id,\r\n status: 'OPEN',\r\n },\r\n });\r\n\r\n const warningMessage =\r\n activeCirculations.length > 0\r\n ? `There are ${activeCirculations.length} active circulation(s) for this correspondence. Canceling will force close all related circulations.`\r\n : '';\r\n\r\n // Get the current revision to update status\r\n const currentRevision = await this.revisionRepo.findOne({\r\n where: {\r\n correspondenceId: correspondence.id,\r\n isCurrent: true,\r\n },\r\n });\r\n\r\n if (!currentRevision) {\r\n throw new NotFoundException('Current revision not found');\r\n }\r\n\r\n // Get cancelled status\r\n const cancelledStatus = await this.statusRepo.findOne({\r\n where: { statusCode: 'CANCELLED' },\r\n });\r\n\r\n if (!cancelledStatus) {\r\n throw new InternalServerErrorException('CANCELLED status not found');\r\n }\r\n\r\n const queryRunner = this.dataSource.createQueryRunner();\r\n await queryRunner.connect();\r\n await queryRunner.startTransaction();\r\n\r\n try {\r\n // Update correspondence revision status to CANCELLED\r\n await queryRunner.manager.update(\r\n CorrespondenceRevision,\r\n currentRevision.id,\r\n {\r\n statusId: cancelledStatus.id,\r\n remarks: `Cancelled: ${reason}`,\r\n }\r\n );\r\n\r\n // Force close all active circulations\r\n if (activeCirculations.length > 0) {\r\n await queryRunner.manager.update(\r\n 'Circulation',\r\n {\r\n correspondenceId: correspondence.id,\r\n status: 'OPEN',\r\n },\r\n {\r\n status: 'FORCE_CLOSED',\r\n closedAt: new Date(),\r\n closedBy: user.user_id,\r\n closeReason: `Correspondence cancelled: ${reason}`,\r\n }\r\n );\r\n }\r\n\r\n await queryRunner.commitTransaction();\r\n\r\n // Re-index cancelled status in Elasticsearch (fire-and-forget)\r\n void this.searchService.indexDocument({\r\n id: correspondence.id,\r\n publicId: correspondence.publicId,\r\n type: 'correspondence',\r\n docNumber: correspondence.correspondenceNumber,\r\n title: currentRevision.subject,\r\n status: 'CANCELLED',\r\n projectId: correspondence.projectId,\r\n createdAt: correspondence.createdAt,\r\n });\r\n\r\n // Notify originator's doc-control user about cancellation (fire-and-forget)\r\n if (correspondence.originatorId) {\r\n void this.userService\r\n .findDocControlIdByOrg(correspondence.originatorId)\r\n .then((targetUserId) => {\r\n if (targetUserId) {\r\n void this.notificationService.send({\r\n userId: targetUserId,\r\n title: 'Correspondence Cancelled',\r\n message: `${correspondence.correspondenceNumber} — ${currentRevision.subject} has been cancelled. Reason: ${reason}`,\r\n type: 'EMAIL',\r\n entityType: 'correspondence',\r\n entityId: correspondence.id,\r\n link: `/correspondences/${correspondence.publicId}`,\r\n });\r\n }\r\n })\r\n .catch((err: Error) =>\r\n this.logger.warn(`Cancel notification failed: ${err.message}`)\r\n );\r\n }\r\n\r\n return {\r\n success: true,\r\n message: warningMessage || 'Correspondence cancelled successfully',\r\n activeCirculationsCount: activeCirculations.length,\r\n };\r\n } catch (error) {\r\n await queryRunner.rollbackTransaction();\r\n this.logger.error(\r\n `Failed to cancel correspondence: ${(error as Error).message}`\r\n );\r\n throw error;\r\n } finally {\r\n await queryRunner.release();\r\n }\r\n }\r\n\r\n async bulkCancel(\r\n publicIds: string[],\r\n reason: string,\r\n user: User\r\n ): Promise<{ succeeded: string[]; failed: string[] }> {\r\n const succeeded: string[] = [];\r\n const failed: string[] = [];\r\n\r\n for (const publicId of publicIds) {\r\n try {\r\n await this.cancel(publicId, reason, user);\r\n succeeded.push(publicId);\r\n } catch {\r\n failed.push(publicId);\r\n }\r\n }\r\n\r\n return { succeeded, failed };\r\n }\r\n\r\n async exportCsv(searchDto: SearchCorrespondenceDto): Promise {\r\n const { data } = await this.findAll(searchDto);\r\n\r\n const header = [\r\n 'Document No.',\r\n 'Rev',\r\n 'Subject',\r\n 'Type',\r\n 'Status',\r\n 'Project',\r\n 'From',\r\n 'Due Date',\r\n 'Created At',\r\n ];\r\n const rows = data.map((rev) => {\r\n const corr = rev.correspondence ?? (rev as unknown as Correspondence);\r\n return [\r\n this.escapeCsv(corr.correspondenceNumber ?? ''),\r\n this.escapeCsv(rev.revisionLabel ?? String(rev.revisionNumber ?? 0)),\r\n this.escapeCsv(rev.subject ?? ''),\r\n this.escapeCsv(corr.type?.typeCode ?? ''),\r\n this.escapeCsv(rev.status?.statusCode ?? ''),\r\n this.escapeCsv(corr.project?.projectCode ?? ''),\r\n this.escapeCsv(corr.originator?.organizationCode ?? ''),\r\n rev.dueDate ? new Date(rev.dueDate).toISOString().split('T')[0] : '',\r\n new Date(rev.createdAt).toISOString().split('T')[0],\r\n ].join(',');\r\n });\r\n\r\n return [header.join(','), ...rows].join('\\n');\r\n }\r\n\r\n private escapeCsv(value: string): string {\r\n if (value.includes(',') || value.includes('\"') || value.includes('\\n')) {\r\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\r\n }\r\n return value;\r\n }\r\n}\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservicespec_3f7211ae92062110b101dfbceef7d587 b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservicespec_3f7211ae92062110b101dfbceef7d587 new file mode 100644 index 0000000..c702f39 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservicespec_3f7211ae92062110b101dfbceef7d587 @@ -0,0 +1,620 @@ +83ec657cd9abe1b1e47afa8108649605 +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const testing_1 = require("@nestjs/testing"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +const common_1 = require("@nestjs/common"); +const correspondence_service_1 = require("./correspondence.service"); +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +describe('CorrespondenceService', () => { + let service; + let numberingService; + let correspondenceRepo; + let revisionRepo; + let testingModule; + let _dataSource; + const createMockRepository = () => ({ + find: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + save: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + softDelete: jest.fn(), + createQueryBuilder: jest.fn(() => ({ + leftJoinAndSelect: jest.fn().mockReturnThis(), + where: jest.fn().mockReturnThis(), + andWhere: jest.fn().mockReturnThis(), + orderBy: jest.fn().mockReturnThis(), + skip: jest.fn().mockReturnThis(), + take: jest.fn().mockReturnThis(), + getOne: jest.fn().mockResolvedValue(null), + getMany: jest.fn().mockResolvedValue([]), + getManyAndCount: jest.fn().mockResolvedValue([[], 0]), + })), + }); + const mockDataSource = { + createQueryRunner: jest.fn(() => ({ + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn(), + save: jest.fn(), + findOne: jest.fn(), + }, + })), + getRepository: jest.fn(() => createMockRepository()), + manager: { + findOne: jest.fn(), + }, + }; + beforeEach(async () => { + testingModule = await testing_1.Test.createTestingModule({ + providers: [ + correspondence_service_1.CorrespondenceService, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_reference_entity_1.CorrespondenceReference), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_tag_entity_1.CorrespondenceTag), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(organization_entity_1.Organization), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_recipient_entity_1.CorrespondenceRecipient), + useValue: createMockRepository(), + }, + { + provide: document_numbering_service_1.DocumentNumberingService, + useValue: { + generateNextNumber: jest.fn(), + updateNumberForDraft: jest.fn(), + previewNextNumber: jest.fn(), + }, + }, + { + provide: json_schema_service_1.JsonSchemaService, + useValue: { validate: jest.fn() }, + }, + { + provide: workflow_engine_service_1.WorkflowEngineService, + useValue: { createInstance: jest.fn() }, + }, + { + provide: user_service_1.UserService, + useValue: { + findOne: jest.fn(), + getUserPermissions: jest.fn().mockResolvedValue([]), + }, + }, + { + provide: typeorm_2.DataSource, + useValue: mockDataSource, + }, + { + provide: search_service_1.SearchService, + useValue: { indexDocument: jest.fn() }, + }, + { + provide: file_storage_service_1.FileStorageService, + useValue: { commit: jest.fn().mockResolvedValue([]) }, + }, + { + provide: uuid_resolver_service_1.UuidResolverService, + useValue: { + resolveProjectId: jest.fn().mockResolvedValue(1), + resolveOrganizationId: jest.fn().mockResolvedValue(1), + }, + }, + { + provide: notification_service_1.NotificationService, + useValue: { send: jest.fn().mockResolvedValue(undefined) }, + }, + ], + }).compile(); + service = testingModule.get(correspondence_service_1.CorrespondenceService); + numberingService = testingModule.get(document_numbering_service_1.DocumentNumberingService); + correspondenceRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence)); + revisionRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision)); + _dataSource = testingModule.get(typeorm_2.DataSource); + }); + it('should be defined', () => { + expect(service).toBeDefined(); + }); + describe('update', () => { + it('should allow non-draft update for org-admin+ permissions', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 23, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + statusRepo.findOne.mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + const userService = testingModule.get(user_service_1.UserService); + userService.getUserPermissions.mockResolvedValue([ + 'correspondence.cancel', + ]); + jest.spyOn(correspondenceRepo, 'findOne').mockResolvedValue({ + id: 1, + publicId: 'corr-uuid-1', + correspondenceNumber: 'CORR-001', + projectId: 1, + createdAt: new Date(), + revisions: [], + }); + await expect(service.update(1, { subject: 'Updated Subject' }, mockUser)).resolves.toBeDefined(); + }); + it('should reject non-draft update for non-admin permissions', async () => { + const mockUser = { + user_id: 2, + primaryOrganizationId: 10, + }; + const mockRevision = { + id: 101, + correspondenceId: 2, + isCurrent: true, + statusId: 23, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + statusRepo.findOne.mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + const userService = testingModule.get(user_service_1.UserService); + userService.getUserPermissions.mockResolvedValue([ + 'correspondence.edit', + ]); + await expect(service.update(2, { subject: 'Should Fail' }, mockUser)).rejects.toThrow(common_1.ForbiddenException); + }); + it('should NOT regenerate number if critical fields unchanged', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 1, + disciplineId: 3, + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).not.toHaveBeenCalled(); + }); + it('should regenerate number if Project ID changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 2, + }; + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(2); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Document Type changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + typeId: 999, + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + typeRepo.findOne.mockResolvedValue({ + id: 999, + typeCode: 'NEW-TYPE', + }); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Recipient Organization changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + // Access DataSource manager for mocking + mockDataSource.manager.findOne.mockResolvedValue({ + id: 88, + organizationCode: 'NEW-ORG', + }); + const updateDto = { + recipients: [{ type: 'TO', organizationId: 88 }], + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + }); + describe('create', () => { + it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: null, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + originatorId: 'originator-uuid', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const userService = testingModule.get(user_service_1.UserService); + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + userService.findOne.mockResolvedValue({ + user_id: 1, + primaryOrganizationId: null, + }); + userService.getUserPermissions.mockResolvedValue([ + 'system.manage_all', + ]); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockImplementation((value) => { + if (value === 'originator-uuid') + return 10; + if (value === 'recipient-uuid') + return 20; + return 0; + }); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LTR', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_entity_1.Correspondence, expect.objectContaining({ originatorId: 10 })); + }); + it('should set revisionLabel to "A" for RFA type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'RFA', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: 'A' })); + }); + it('should set revisionLabel to "A" for RFI type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'RFI', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: 'A' })); + }); + it('should set revisionLabel to null for LETTER type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LETTER', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: undefined })); + }); + it('should set revisionLabel to undefined for MEMO type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'MEMO', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: undefined })); + }); + }); +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyIsIm1hcHBpbmdzIjoiOztBQUFBLDZDQUFzRDtBQUN0RCw2Q0FBcUQ7QUFDckQscUNBQWlEO0FBQ2pELDJDQUFvRDtBQUNwRCxxRUFBaUU7QUFDakUsNEVBQWtFO0FBQ2xFLDhGQUFtRjtBQUNuRixzRkFBMkU7QUFDM0UsMEZBQStFO0FBQy9FLGdHQUFxRjtBQUNyRixvRkFBeUU7QUFDekUsc0ZBQTRFO0FBQzVFLGdHQUFxRjtBQUNyRiwwR0FBcUc7QUFDckcsNEVBQXVFO0FBQ3ZFLHdGQUFtRjtBQUNuRix1REFBbUQ7QUFDbkQsNkRBQXlEO0FBQ3pELHlGQUFvRjtBQUNwRix1RkFBa0Y7QUFDbEYsK0VBQTJFO0FBSzNFLFFBQVEsQ0FBQyx1QkFBdUIsRUFBRSxHQUFHLEVBQUU7SUFDckMsSUFBSSxPQUE4QixDQUFDO0lBQ25DLElBQUksZ0JBQTBDLENBQUM7SUFDL0MsSUFBSSxrQkFBOEMsQ0FBQztJQUNuRCxJQUFJLFlBQWdELENBQUM7SUFDckQsSUFBSSxhQUE0QixDQUFDO0lBQ2pDLElBQUksV0FBdUIsQ0FBQztJQUU1QixNQUFNLG9CQUFvQixHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDbEMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDZixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNsQixNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNqQixJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNmLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLFVBQVUsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ3JCLGtCQUFrQixFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENB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T0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLG9CQUFvQixDQUNyRCx1REFBc0IsRUFDdEIsTUFBTSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQ3RELENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUZXN0LCBUZXN0aW5nTW9kdWxlIH0gZnJvbSAnQG5lc3Rqcy90ZXN0aW5nJztcclxuaW1wb3J0IHsgZ2V0UmVwb3NpdG9yeVRva2VuIH0gZnJvbSAnQG5lc3Rqcy90eXBlb3JtJztcclxuaW1wb3J0IHsgRGF0YVNvdXJjZSwgUmVwb3NpdG9yeSB9IGZyb20gJ3R5cGVvcm0nO1xyXG5pbXBvcnQgeyBGb3JiaWRkZW5FeGNlcHRpb24gfSBmcm9tICdAbmVzdGpzL2NvbW1vbic7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlU2VydmljZSB9IGZyb20gJy4vY29ycmVzcG9uZGVuY2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJldmlzaW9uIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZXZpc2lvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVR5cGUgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXR5cGUuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VTdGF0dXMgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXN0YXR1cy5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlZmVyZW5jZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVmZXJlbmNlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVGFnIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS10YWcuZW50aXR5JztcclxuaW1wb3J0IHsgT3JnYW5pemF0aW9uIH0gZnJvbSAnLi4vb3JnYW5pemF0aW9uL2VudGl0aWVzL29yZ2FuaXphdGlvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlY2lwaWVudCB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVjaXBpZW50LmVudGl0eSc7XHJcbmltcG9ydCB7IERvY3VtZW50TnVtYmVyaW5nU2VydmljZSB9IGZyb20gJy4uL2RvY3VtZW50LW51bWJlcmluZy9zZXJ2aWNlcy9kb2N1bWVudC1udW1iZXJpbmcuc2VydmljZSc7XHJcbmltcG9ydCB7IEpzb25TY2hlbWFTZXJ2aWNlIH0gZnJvbSAnLi4vanNvbi1zY2hlbWEvanNvbi1zY2hlbWEuc2VydmljZSc7XHJcbmltcG9ydCB7IFdvcmtmbG93RW5naW5lU2VydmljZSB9IGZyb20gJy4uL3dvcmtmbG93LWVuZ2luZS93b3JrZmxvdy1lbmdpbmUuc2VydmljZSc7XHJcbmltcG9ydCB7IFVzZXJTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlci91c2VyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTZWFyY2hTZXJ2aWNlIH0gZnJvbSAnLi4vc2VhcmNoL3NlYXJjaC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRmlsZVN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL2ZpbGUtc3RvcmFnZS9maWxlLXN0b3JhZ2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IFV1aWRSZXNvbHZlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vc2VydmljZXMvdXVpZC1yZXNvbHZlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi9ub3RpZmljYXRpb24uc2VydmljZSc7XHJcbmltcG9ydCB7IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vdXBkYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vY3JlYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi91c2VyL2VudGl0aWVzL3VzZXIuZW50aXR5JztcclxuXHJcbmRlc2NyaWJlKCdDb3JyZXNwb25kZW5jZVNlcnZpY2UnLCAoKSA9PiB7XHJcbiAgbGV0IHNlcnZpY2U6IENvcnJlc3BvbmRlbmNlU2VydmljZTtcclxuICBsZXQgbnVtYmVyaW5nU2VydmljZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlO1xyXG4gIGxldCBjb3JyZXNwb25kZW5jZVJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2U+O1xyXG4gIGxldCByZXZpc2lvblJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VSZXZpc2lvbj47XHJcbiAgbGV0IHRlc3RpbmdNb2R1bGU6IFRlc3RpbmdNb2R1bGU7XHJcbiAgbGV0IF9kYXRhU291cmNlOiBEYXRhU291cmNlO1xyXG5cclxuICBjb25zdCBjcmVhdGVNb2NrUmVwb3NpdG9yeSA9ICgpID0+ICh7XHJcbiAgICBmaW5kOiBqZXN0LmZuKCksXHJcbiAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGU6IGplc3QuZm4oKSxcclxuICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgIHVwZGF0ZTogamVzdC5mbigpLFxyXG4gICAgZGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBzb2Z0RGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGVRdWVyeUJ1aWxkZXI6IGplc3QuZm4oKCkgPT4gKHtcclxuICAgICAgbGVmdEpvaW5BbmRTZWxlY3Q6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB3aGVyZTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIGFuZFdoZXJlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgb3JkZXJCeTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIHNraXA6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB0YWtlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgZ2V0T25lOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUobnVsbCksXHJcbiAgICAgIGdldE1hbnk6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSksXHJcbiAgICAgIGdldE1hbnlBbmRDb3VudDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKFtbXSwgMF0pLFxyXG4gICAgfSkpLFxyXG4gIH0pO1xyXG5cclxuICBjb25zdCBtb2NrRGF0YVNvdXJjZSA9IHtcclxuICAgIGNyZWF0ZVF1ZXJ5UnVubmVyOiBqZXN0LmZuKCgpID0+ICh7XHJcbiAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgIGNyZWF0ZTogamVzdC5mbigpLFxyXG4gICAgICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgIH0sXHJcbiAgICB9KSksXHJcbiAgICBnZXRSZXBvc2l0b3J5OiBqZXN0LmZuKCgpID0+IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCkpLFxyXG4gICAgbWFuYWdlcjoge1xyXG4gICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICB9LFxyXG4gIH07XHJcblxyXG4gIGJlZm9yZUVhY2goYXN5bmMgKCkgPT4ge1xyXG4gICAgdGVzdGluZ01vZHVsZSA9IGF3YWl0IFRlc3QuY3JlYXRlVGVzdGluZ01vZHVsZSh7XHJcbiAgICAgIHByb3ZpZGVyczogW1xyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlU2VydmljZSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZXZpc2lvbiksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZWZlcmVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUYWcpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oT3JnYW5pemF0aW9uKSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmVjaXBpZW50KSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHtcclxuICAgICAgICAgICAgZ2VuZXJhdGVOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHVwZGF0ZU51bWJlckZvckRyYWZ0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHByZXZpZXdOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogSnNvblNjaGVtYVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyB2YWxpZGF0ZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBXb3JrZmxvd0VuZ2luZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjcmVhdGVJbnN0YW5jZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBVc2VyU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7XHJcbiAgICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICAgICAgZ2V0VXNlclBlcm1pc3Npb25zOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoW10pLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IERhdGFTb3VyY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogbW9ja0RhdGFTb3VyY2UsXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBTZWFyY2hTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHsgaW5kZXhEb2N1bWVudDogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBGaWxlU3RvcmFnZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjb21taXQ6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFV1aWRSZXNvbHZlclNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZToge1xyXG4gICAgICAgICAgICByZXNvbHZlUHJvamVjdElkOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoMSksXHJcbiAgICAgICAgICAgIHJlc29sdmVPcmdhbml6YXRpb25JZDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKDEpLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IE5vdGlmaWNhdGlvblNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBzZW5kOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUodW5kZWZpbmVkKSB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgIF0sXHJcbiAgICB9KS5jb21waWxlKCk7XHJcblxyXG4gICAgc2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PENvcnJlc3BvbmRlbmNlU2VydmljZT4oQ29ycmVzcG9uZGVuY2VTZXJ2aWNlKTtcclxuICAgIG51bWJlcmluZ1NlcnZpY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEb2N1bWVudE51bWJlcmluZ1NlcnZpY2U+KFxyXG4gICAgICBEb2N1bWVudE51bWJlcmluZ1NlcnZpY2VcclxuICAgICk7XHJcbiAgICBjb3JyZXNwb25kZW5jZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlPj4oXHJcbiAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZSlcclxuICAgICk7XHJcbiAgICByZXZpc2lvblJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlUmV2aXNpb24+PihcclxuICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmV2aXNpb24pXHJcbiAgICApO1xyXG4gICAgX2RhdGFTb3VyY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEYXRhU291cmNlPihEYXRhU291cmNlKTtcclxuICB9KTtcclxuXHJcbiAgaXQoJ3Nob3VsZCBiZSBkZWZpbmVkJywgKCkgPT4ge1xyXG4gICAgZXhwZWN0KHNlcnZpY2UpLnRvQmVEZWZpbmVkKCk7XHJcbiAgfSk7XHJcblxyXG4gIGRlc2NyaWJlKCd1cGRhdGUnLCAoKSA9PiB7XHJcbiAgICBpdCgnc2hvdWxkIGFsbG93IG5vbi1kcmFmdCB1cGRhdGUgZm9yIG9yZy1hZG1pbisgcGVybWlzc2lvbnMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiAyMyxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3Qgc3RhdHVzUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VTdGF0dXM+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpXHJcbiAgICAgICk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDIzLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdTVUJPV04nLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHVzZXJTZXJ2aWNlID0gdGVzdGluZ01vZHVsZS5nZXQ8VXNlclNlcnZpY2U+KFVzZXJTZXJ2aWNlKTtcclxuICAgICAgKHVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKFtcclxuICAgICAgICAnY29ycmVzcG9uZGVuY2UuY2FuY2VsJyxcclxuICAgICAgXSk7XHJcblxyXG4gICAgICBqZXN0LnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHVibGljSWQ6ICdjb3JyLXV1aWQtMScsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdDT1JSLTAwMScsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKSxcclxuICAgICAgICByZXZpc2lvbnM6IFtdLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgYXdhaXQgZXhwZWN0KFxyXG4gICAgICAgIHNlcnZpY2UudXBkYXRlKDEsIHsgc3ViamVjdDogJ1VwZGF0ZWQgU3ViamVjdCcgfSwgbW9ja1VzZXIpXHJcbiAgICAgICkucmVzb2x2ZXMudG9CZURlZmluZWQoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgcmVqZWN0IG5vbi1kcmFmdCB1cGRhdGUgZm9yIG5vbi1hZG1pbiBwZXJtaXNzaW9ucycsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7XHJcbiAgICAgICAgdXNlcl9pZDogMixcclxuICAgICAgICBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMixcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDIzLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMjMsXHJcbiAgICAgICAgc3RhdHVzQ29kZTogJ1NVQk9XTicsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgY29uc3QgdXNlclNlcnZpY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxVc2VyU2VydmljZT4oVXNlclNlcnZpY2UpO1xyXG4gICAgICAodXNlclNlcnZpY2UuZ2V0VXNlclBlcm1pc3Npb25zIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoW1xyXG4gICAgICAgICdjb3JyZXNwb25kZW5jZS5lZGl0JyxcclxuICAgICAgXSk7XHJcblxyXG4gICAgICBhd2FpdCBleHBlY3QoXHJcbiAgICAgICAgc2VydmljZS51cGRhdGUoMiwgeyBzdWJqZWN0OiAnU2hvdWxkIEZhaWwnIH0sIG1vY2tVc2VyKVxyXG4gICAgICApLnJlamVjdHMudG9UaHJvdyhGb3JiaWRkZW5FeGNlcHRpb24pO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCBOT1QgcmVnZW5lcmF0ZSBudW1iZXIgaWYgY3JpdGljYWwgZmllbGRzIHVuY2hhbmdlZCcsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7IGlkOiAxLCBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAxLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogNSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3QgbW9ja0NvcnIgPSB7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiAyLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6IDEwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiAnT0xELU5VTScsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgcmVjaXBpZW50VHlwZTogJ1RPJywgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IDk5IH1dLFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrQ29yciBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUR0bzogVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UudXBkYXRlKDEsIHVwZGF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KFxyXG4gICAgICAgIG51bWJlcmluZ1NlcnZpY2UudXBkYXRlTnVtYmVyRm9yRHJhZnQgYXMgamVzdC5Nb2NrXHJcbiAgICAgICkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgcmVnZW5lcmF0ZSBudW1iZXIgaWYgUHJvamVjdCBJRCBjaGFuZ2VzJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IG1vY2tDb3JyID0ge1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZVR5cGVJZDogMixcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAxMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogJ09MRC1OVU0nLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHJlY2lwaWVudFR5cGU6ICdUTycsIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiA5OSB9XSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihjb3JyZXNwb25kZW5jZVJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja0NvcnIgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogMixcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHV1aWRSZXNvbHZlciA9XHJcbiAgICAgICAgdGVzdGluZ01vZHVsZS5nZXQ8VXVpZFJlc29sdmVyU2VydmljZT4oVXVpZFJlc29sdmVyU2VydmljZSk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDIpO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS50b0hhdmVCZWVuQ2FsbGVkKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHJlZ2VuZXJhdGUgbnVtYmVyIGlmIERvY3VtZW50IFR5cGUgY2hhbmdlcycsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7IGlkOiAxLCBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAxLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogNSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICB0eXBlSWQ6IDk5OSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogOTk5LFxyXG4gICAgICAgIHR5cGVDb2RlOiAnTkVXLVRZUEUnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UudXBkYXRlKDEsIHVwZGF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KFxyXG4gICAgICAgIG51bWJlcmluZ1NlcnZpY2UudXBkYXRlTnVtYmVyRm9yRHJhZnQgYXMgamVzdC5Nb2NrXHJcbiAgICAgICkudG9IYXZlQmVlbkNhbGxlZCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCByZWdlbmVyYXRlIG51bWJlciBpZiBSZWNpcGllbnQgT3JnYW5pemF0aW9uIGNoYW5nZXMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0geyBpZDogMSwgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMSxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDUsXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3QgbW9ja0NvcnIgPSB7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiAyLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6IDEwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiAnT0xELU5VTScsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgcmVjaXBpZW50VHlwZTogJ1RPJywgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IDk5IH1dLFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrQ29yciBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIC8vIEFjY2VzcyBEYXRhU291cmNlIG1hbmFnZXIgZm9yIG1vY2tpbmdcclxuICAgICAgbW9ja0RhdGFTb3VyY2UubWFuYWdlci5maW5kT25lLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogODgsXHJcbiAgICAgICAgb3JnYW5pemF0aW9uQ29kZTogJ05FVy1PUkcnLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgT3JnYW5pemF0aW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUR0bzogVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgdHlwZTogJ1RPJywgb3JnYW5pemF0aW9uSWQ6IDg4IH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS50b0hhdmVCZWVuQ2FsbGVkKCk7XHJcbiAgICB9KTtcclxuICB9KTtcclxuXHJcbiAgZGVzY3JpYmUoJ2NyZWF0ZScsICgpID0+IHtcclxuICAgIGl0KCdzaG91bGQgYWxsb3cgc3lzdGVtLm1hbmFnZV9hbGwgdXNlciB3aXRob3V0IHByaW1hcnlPcmdhbml6YXRpb25JZCB3aGVuIG9yaWdpbmF0b3JJZCBpcyBwcm92aWRlZCcsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7XHJcbiAgICAgICAgdXNlcl9pZDogMSxcclxuICAgICAgICBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IG51bGwsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG5cclxuICAgICAgY29uc3QgY3JlYXRlRHRvOiBDcmVhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6ICdwcm9qZWN0LXV1aWQnLFxyXG4gICAgICAgIHR5cGVJZDogMSxcclxuICAgICAgICBzdWJqZWN0OiAnVGVzdCBTdWJqZWN0JyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6ICdvcmlnaW5hdG9yLXV1aWQnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdXNlclNlcnZpY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxVc2VyU2VydmljZT4oVXNlclNlcnZpY2UpO1xyXG4gICAgICBjb25zdCB0eXBlUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VUeXBlPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlVHlwZSlcclxuICAgICAgKTtcclxuICAgICAgY29uc3Qgc3RhdHVzUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VTdGF0dXM+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHV1aWRSZXNvbHZlciA9XHJcbiAgICAgICAgdGVzdGluZ01vZHVsZS5nZXQ8VXVpZFJlc29sdmVyU2VydmljZT4oVXVpZFJlc29sdmVyU2VydmljZSk7XHJcblxyXG4gICAgICAodXNlclNlcnZpY2UuZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogbnVsbCxcclxuICAgICAgfSk7XHJcbiAgICAgICh1c2VyU2VydmljZS5nZXRVc2VyUGVybWlzc2lvbnMgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXHJcbiAgICAgICAgJ3N5c3RlbS5tYW5hZ2VfYWxsJyxcclxuICAgICAgXSk7XHJcblxyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgxMDApO1xyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZCBhcyBqZXN0Lk1vY2spLm1vY2tJbXBsZW1lbnRhdGlvbihcclxuICAgICAgICAodmFsdWU6IG51bWJlciB8IHN0cmluZykgPT4ge1xyXG4gICAgICAgICAgaWYgKHZhbHVlID09PSAnb3JpZ2luYXRvci11dWlkJykgcmV0dXJuIDEwO1xyXG4gICAgICAgICAgaWYgKHZhbHVlID09PSAncmVjaXBpZW50LXV1aWQnKSByZXR1cm4gMjA7XHJcbiAgICAgICAgICByZXR1cm4gMDtcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ0xUUicsXHJcbiAgICAgIH0pO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdEUkFGVCcsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgKG51bWJlcmluZ1NlcnZpY2UuZ2VuZXJhdGVOZXh0TnVtYmVyIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIG51bWJlcjogJ0RPQy0wMDEnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAsIG9yZ2FuaXphdGlvbkNvZGU6ICdPUkcnIH0pXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAyMCwgb3JnYW5pemF0aW9uQ29kZTogJ1JFQycgfSk7XHJcblxyXG4gICAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHtcclxuICAgICAgICBjb25uZWN0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcm9sbGJhY2tUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgICBjcmVhdGU6IGplc3QuZm4oXHJcbiAgICAgICAgICAgIChfZW50aXR5OiB1bmtub3duLCBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gcGF5bG9hZFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIHNhdmU6IGplc3RcclxuICAgICAgICAgICAgLmZuKClcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiA5OTksIHB1YmxpY0lkOiAnY29yci11dWlkJyB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwMDAgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZShbXSksXHJcbiAgICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgICAgfSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIChtb2NrRGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lciBhcyBqZXN0Lk1vY2spLm1vY2tSZXR1cm5WYWx1ZShcclxuICAgICAgICBxdWVyeVJ1bm5lclxyXG4gICAgICApO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS5jcmVhdGUoY3JlYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QocXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlLFxyXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgb3JpZ2luYXRvcklkOiAxMCB9KVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCBzZXQgcmV2aXNpb25MYWJlbCB0byBcIkFcIiBmb3IgUkZBIHR5cGUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyMCk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ1JGQScsXHJcbiAgICAgIH0pO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdEUkFGVCcsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgKG51bWJlcmluZ1NlcnZpY2UuZ2VuZXJhdGVOZXh0TnVtYmVyIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIG51bWJlcjogJ0RPQy0wMDEnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAsIG9yZ2FuaXphdGlvbkNvZGU6ICdPUkcnIH0pXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAyMCwgb3JnYW5pemF0aW9uQ29kZTogJ1JFQycgfSk7XHJcblxyXG4gICAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHtcclxuICAgICAgICBjb25uZWN0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcm9sbGJhY2tUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgICBjcmVhdGU6IGplc3QuZm4oXHJcbiAgICAgICAgICAgIChfZW50aXR5OiB1bmtub3duLCBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gcGF5bG9hZFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIHNhdmU6IGplc3RcclxuICAgICAgICAgICAgLmZuKClcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiA5OTksIHB1YmxpY0lkOiAnY29yci11dWlkJyB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwMDAgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZShbXSksXHJcbiAgICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgICAgfSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIChtb2NrRGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lciBhcyBqZXN0Lk1vY2spLm1vY2tSZXR1cm5WYWx1ZShcclxuICAgICAgICBxdWVyeVJ1bm5lclxyXG4gICAgICApO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS5jcmVhdGUoY3JlYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QocXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmV2aXNpb24sXHJcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyByZXZpc2lvbkxhYmVsOiAnQScgfSlcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgc2V0IHJldmlzaW9uTGFiZWwgdG8gXCJBXCIgZm9yIFJGSSB0eXBlJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG5cclxuICAgICAgY29uc3QgY3JlYXRlRHRvOiBDcmVhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6ICdwcm9qZWN0LXV1aWQnLFxyXG4gICAgICAgIHR5cGVJZDogMSxcclxuICAgICAgICBzdWJqZWN0OiAnVGVzdCBTdWJqZWN0JyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyBvcmdhbml6YXRpb25JZDogJ3JlY2lwaWVudC11dWlkJywgdHlwZTogJ1RPJyB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuXHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDEwMCk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMjApO1xyXG5cclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgdHlwZUNvZGU6ICdSRkknLFxyXG4gICAgICB9KTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnRFJBRlQnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIChudW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlciBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBudW1iZXI6ICdET0MtMDAxJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmVcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwLCBvcmdhbml6YXRpb25Db2RlOiAnT1JHJyB9KVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMjAsIG9yZ2FuaXphdGlvbkNvZGU6ICdSRUMnIH0pO1xyXG5cclxuICAgICAgY29uc3QgcXVlcnlSdW5uZXIgPSB7XHJcbiAgICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICAgIHN0YXJ0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByZWxlYXNlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgICAgY3JlYXRlOiBqZXN0LmZuKFxyXG4gICAgICAgICAgICAoX2VudGl0eTogdW5rbm93biwgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHBheWxvYWRcclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBzYXZlOiBqZXN0XHJcbiAgICAgICAgICAgIC5mbigpXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogOTk5LCBwdWJsaWNJZDogJ2NvcnItdXVpZCcgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMDAwIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoW10pLFxyXG4gICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICAobW9ja0RhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmV0dXJuVmFsdWUoXHJcbiAgICAgICAgcXVlcnlSdW5uZXJcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UuY3JlYXRlKGNyZWF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcclxuICAgICAgICBDb3JyZXNwb25kZW5jZVJldmlzaW9uLFxyXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgcmV2aXNpb25MYWJlbDogJ0EnIH0pXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHNldCByZXZpc2lvbkxhYmVsIHRvIG51bGwgZm9yIExFVFRFUiB0eXBlJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG5cclxuICAgICAgY29uc3QgY3JlYXRlRHRvOiBDcmVhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6ICdwcm9qZWN0LXV1aWQnLFxyXG4gICAgICAgIHR5cGVJZDogMSxcclxuICAgICAgICBzdWJqZWN0OiAnVGVzdCBTdWJqZWN0JyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyBvcmdhbml6YXRpb25JZDogJ3JlY2lwaWVudC11dWlkJywgdHlwZTogJ1RPJyB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuXHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDEwMCk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMjApO1xyXG5cclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgdHlwZUNvZGU6ICdMRVRURVInLFxyXG4gICAgICB9KTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnRFJBRlQnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIChudW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlciBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBudW1iZXI6ICdET0MtMDAxJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmVcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwLCBvcmdhbml6YXRpb25Db2RlOiAnT1JHJyB9KVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMjAsIG9yZ2FuaXphdGlvbkNvZGU6ICdSRUMnIH0pO1xyXG5cclxuICAgICAgY29uc3QgcXVlcnlSdW5uZXIgPSB7XHJcbiAgICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICAgIHN0YXJ0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByZWxlYXNlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgICAgY3JlYXRlOiBqZXN0LmZuKFxyXG4gICAgICAgICAgICAoX2VudGl0eTogdW5rbm93biwgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHBheWxvYWRcclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBzYXZlOiBqZXN0XHJcbiAgICAgICAgICAgIC5mbigpXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogOTk5LCBwdWJsaWNJZDogJ2NvcnItdXVpZCcgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMDAwIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoW10pLFxyXG4gICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICAobW9ja0RhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmV0dXJuVmFsdWUoXHJcbiAgICAgICAgcXVlcnlSdW5uZXJcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UuY3JlYXRlKGNyZWF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcclxuICAgICAgICBDb3JyZXNwb25kZW5jZVJldmlzaW9uLFxyXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgcmV2aXNpb25MYWJlbDogdW5kZWZpbmVkIH0pXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHNldCByZXZpc2lvbkxhYmVsIHRvIHVuZGVmaW5lZCBmb3IgTUVNTyB0eXBlJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG5cclxuICAgICAgY29uc3QgY3JlYXRlRHRvOiBDcmVhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6ICdwcm9qZWN0LXV1aWQnLFxyXG4gICAgICAgIHR5cGVJZDogMSxcclxuICAgICAgICBzdWJqZWN0OiAnVGVzdCBTdWJqZWN0JyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyBvcmdhbml6YXRpb25JZDogJ3JlY2lwaWVudC11dWlkJywgdHlwZTogJ1RPJyB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuXHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDEwMCk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMjApO1xyXG5cclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgdHlwZUNvZGU6ICdNRU1PJyxcclxuICAgICAgfSk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgc3RhdHVzQ29kZTogJ0RSQUZUJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAobnVtYmVyaW5nU2VydmljZS5nZW5lcmF0ZU5leHROdW1iZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgbnVtYmVyOiAnRE9DLTAwMScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgbW9ja0RhdGFTb3VyY2UubWFuYWdlci5maW5kT25lXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMCwgb3JnYW5pemF0aW9uQ29kZTogJ09SRycgfSlcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDIwLCBvcmdhbml6YXRpb25Db2RlOiAnUkVDJyB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHF1ZXJ5UnVubmVyID0ge1xyXG4gICAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgICBzdGFydFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgY29tbWl0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcmVsZWFzZTogamVzdC5mbigpLFxyXG4gICAgICAgIG1hbmFnZXI6IHtcclxuICAgICAgICAgIGNyZWF0ZTogamVzdC5mbihcclxuICAgICAgICAgICAgKF9lbnRpdHk6IHVua25vd24sIHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBwYXlsb2FkXHJcbiAgICAgICAgICApLFxyXG4gICAgICAgICAgc2F2ZTogamVzdFxyXG4gICAgICAgICAgICAuZm4oKVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDk5OSwgcHVibGljSWQ6ICdjb3JyLXV1aWQnIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAwMCB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKFtdKSxcclxuICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICB9LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgKG1vY2tEYXRhU291cmNlLmNyZWF0ZVF1ZXJ5UnVubmVyIGFzIGplc3QuTW9jaykubW9ja1JldHVyblZhbHVlKFxyXG4gICAgICAgIHF1ZXJ5UnVubmVyXHJcbiAgICAgICk7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLmNyZWF0ZShjcmVhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbixcclxuICAgICAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7IHJldmlzaW9uTGFiZWw6IHVuZGVmaW5lZCB9KVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgfSk7XHJcbn0pO1xyXG4iXSwidmVyc2lvbiI6M30= \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservicespec_3f7211ae92062110b101dfbceef7d587.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservicespec_3f7211ae92062110b101dfbceef7d587.map new file mode 100644 index 0000000..25463aa --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservicespec_3f7211ae92062110b101dfbceef7d587.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts"],"sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\r\nimport { getRepositoryToken } from '@nestjs/typeorm';\r\nimport { DataSource, Repository } from 'typeorm';\r\nimport { ForbiddenException } from '@nestjs/common';\r\nimport { CorrespondenceService } from './correspondence.service';\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { User } from '../user/entities/user.entity';\r\n\r\ndescribe('CorrespondenceService', () => {\r\n let service: CorrespondenceService;\r\n let numberingService: DocumentNumberingService;\r\n let correspondenceRepo: Repository;\r\n let revisionRepo: Repository;\r\n let testingModule: TestingModule;\r\n let _dataSource: DataSource;\r\n\r\n const createMockRepository = () => ({\r\n find: jest.fn(),\r\n findOne: jest.fn(),\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n update: jest.fn(),\r\n delete: jest.fn(),\r\n softDelete: jest.fn(),\r\n createQueryBuilder: jest.fn(() => ({\r\n leftJoinAndSelect: jest.fn().mockReturnThis(),\r\n where: jest.fn().mockReturnThis(),\r\n andWhere: jest.fn().mockReturnThis(),\r\n orderBy: jest.fn().mockReturnThis(),\r\n skip: jest.fn().mockReturnThis(),\r\n take: jest.fn().mockReturnThis(),\r\n getOne: jest.fn().mockResolvedValue(null),\r\n getMany: jest.fn().mockResolvedValue([]),\r\n getManyAndCount: jest.fn().mockResolvedValue([[], 0]),\r\n })),\r\n });\r\n\r\n const mockDataSource = {\r\n createQueryRunner: jest.fn(() => ({\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n findOne: jest.fn(),\r\n },\r\n })),\r\n getRepository: jest.fn(() => createMockRepository()),\r\n manager: {\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n beforeEach(async () => {\r\n testingModule = await Test.createTestingModule({\r\n providers: [\r\n CorrespondenceService,\r\n {\r\n provide: getRepositoryToken(Correspondence),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRevision),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceType),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceStatus),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceReference),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceTag),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(Organization),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRecipient),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: DocumentNumberingService,\r\n useValue: {\r\n generateNextNumber: jest.fn(),\r\n updateNumberForDraft: jest.fn(),\r\n previewNextNumber: jest.fn(),\r\n },\r\n },\r\n {\r\n provide: JsonSchemaService,\r\n useValue: { validate: jest.fn() },\r\n },\r\n {\r\n provide: WorkflowEngineService,\r\n useValue: { createInstance: jest.fn() },\r\n },\r\n {\r\n provide: UserService,\r\n useValue: {\r\n findOne: jest.fn(),\r\n getUserPermissions: jest.fn().mockResolvedValue([]),\r\n },\r\n },\r\n {\r\n provide: DataSource,\r\n useValue: mockDataSource,\r\n },\r\n {\r\n provide: SearchService,\r\n useValue: { indexDocument: jest.fn() },\r\n },\r\n {\r\n provide: FileStorageService,\r\n useValue: { commit: jest.fn().mockResolvedValue([]) },\r\n },\r\n {\r\n provide: UuidResolverService,\r\n useValue: {\r\n resolveProjectId: jest.fn().mockResolvedValue(1),\r\n resolveOrganizationId: jest.fn().mockResolvedValue(1),\r\n },\r\n },\r\n {\r\n provide: NotificationService,\r\n useValue: { send: jest.fn().mockResolvedValue(undefined) },\r\n },\r\n ],\r\n }).compile();\r\n\r\n service = testingModule.get(CorrespondenceService);\r\n numberingService = testingModule.get(\r\n DocumentNumberingService\r\n );\r\n correspondenceRepo = testingModule.get>(\r\n getRepositoryToken(Correspondence)\r\n );\r\n revisionRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceRevision)\r\n );\r\n _dataSource = testingModule.get(DataSource);\r\n });\r\n\r\n it('should be defined', () => {\r\n expect(service).toBeDefined();\r\n });\r\n\r\n describe('update', () => {\r\n it('should allow non-draft update for org-admin+ permissions', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 23,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 23,\r\n statusCode: 'SUBOWN',\r\n });\r\n\r\n const userService = testingModule.get(UserService);\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'correspondence.cancel',\r\n ]);\r\n\r\n jest.spyOn(correspondenceRepo, 'findOne').mockResolvedValue({\r\n id: 1,\r\n publicId: 'corr-uuid-1',\r\n correspondenceNumber: 'CORR-001',\r\n projectId: 1,\r\n createdAt: new Date(),\r\n revisions: [],\r\n } as unknown as Correspondence);\r\n\r\n await expect(\r\n service.update(1, { subject: 'Updated Subject' }, mockUser)\r\n ).resolves.toBeDefined();\r\n });\r\n\r\n it('should reject non-draft update for non-admin permissions', async () => {\r\n const mockUser = {\r\n user_id: 2,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n const mockRevision = {\r\n id: 101,\r\n correspondenceId: 2,\r\n isCurrent: true,\r\n statusId: 23,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 23,\r\n statusCode: 'SUBOWN',\r\n });\r\n\r\n const userService = testingModule.get(UserService);\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'correspondence.edit',\r\n ]);\r\n\r\n await expect(\r\n service.update(2, { subject: 'Should Fail' }, mockUser)\r\n ).rejects.toThrow(ForbiddenException);\r\n });\r\n\r\n it('should NOT regenerate number if critical fields unchanged', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 1,\r\n disciplineId: 3,\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).not.toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Project ID changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 2,\r\n };\r\n\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(2);\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Document Type changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n typeId: 999,\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 999,\r\n typeCode: 'NEW-TYPE',\r\n });\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Recipient Organization changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n // Access DataSource manager for mocking\r\n mockDataSource.manager.findOne.mockResolvedValue({\r\n id: 88,\r\n organizationCode: 'NEW-ORG',\r\n } as unknown as Organization);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n recipients: [{ type: 'TO', organizationId: 88 }],\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n });\r\n\r\n describe('create', () => {\r\n it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n originatorId: 'originator-uuid',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const userService = testingModule.get(UserService);\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (userService.findOne as jest.Mock).mockResolvedValue({\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n });\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'system.manage_all',\r\n ]);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockImplementation(\r\n (value: number | string) => {\r\n if (value === 'originator-uuid') return 10;\r\n if (value === 'recipient-uuid') return 20;\r\n return 0;\r\n }\r\n );\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LTR',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n Correspondence,\r\n expect.objectContaining({ originatorId: 10 })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to \"A\" for RFA type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'RFA',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: 'A' })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to \"A\" for RFI type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'RFI',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: 'A' })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to null for LETTER type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LETTER',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: undefined })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to undefined for MEMO type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'MEMO',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: undefined })\r\n );\r\n });\r\n });\r\n});\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/58/correspondenceservicespec_586a629fcc7afcef7cda907c465dd491 b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/58/correspondenceservicespec_586a629fcc7afcef7cda907c465dd491 new file mode 100644 index 0000000..c1beb8e --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/58/correspondenceservicespec_586a629fcc7afcef7cda907c465dd491 @@ -0,0 +1,612 @@ +06552354a957108ee83cb3dbcabadd19 +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const testing_1 = require("@nestjs/testing"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +const common_1 = require("@nestjs/common"); +const correspondence_service_1 = require("./correspondence.service"); +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +describe('CorrespondenceService', () => { + let service; + let numberingService; + let correspondenceRepo; + let revisionRepo; + let testingModule; + let _dataSource; + const createMockRepository = () => ({ + find: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + save: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + softDelete: jest.fn(), + createQueryBuilder: jest.fn(() => ({ + leftJoinAndSelect: jest.fn().mockReturnThis(), + where: jest.fn().mockReturnThis(), + andWhere: jest.fn().mockReturnThis(), + orderBy: jest.fn().mockReturnThis(), + skip: jest.fn().mockReturnThis(), + take: jest.fn().mockReturnThis(), + getOne: jest.fn().mockResolvedValue(null), + getMany: jest.fn().mockResolvedValue([]), + getManyAndCount: jest.fn().mockResolvedValue([[], 0]), + })), + }); + const mockDataSource = { + createQueryRunner: jest.fn(() => ({ + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn(), + save: jest.fn(), + findOne: jest.fn(), + }, + })), + getRepository: jest.fn(() => createMockRepository()), + manager: { + findOne: jest.fn(), + }, + }; + beforeEach(async () => { + testingModule = await testing_1.Test.createTestingModule({ + providers: [ + correspondence_service_1.CorrespondenceService, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_reference_entity_1.CorrespondenceReference), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_tag_entity_1.CorrespondenceTag), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(organization_entity_1.Organization), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_recipient_entity_1.CorrespondenceRecipient), + useValue: createMockRepository(), + }, + { + provide: document_numbering_service_1.DocumentNumberingService, + useValue: { + generateNextNumber: jest.fn(), + updateNumberForDraft: jest.fn(), + previewNextNumber: jest.fn(), + }, + }, + { + provide: json_schema_service_1.JsonSchemaService, + useValue: { validate: jest.fn() }, + }, + { + provide: workflow_engine_service_1.WorkflowEngineService, + useValue: { createInstance: jest.fn() }, + }, + { + provide: user_service_1.UserService, + useValue: { + findOne: jest.fn(), + getUserPermissions: jest.fn().mockResolvedValue([]), + }, + }, + { + provide: typeorm_2.DataSource, + useValue: mockDataSource, + }, + { + provide: search_service_1.SearchService, + useValue: { indexDocument: jest.fn() }, + }, + { + provide: file_storage_service_1.FileStorageService, + useValue: { commit: jest.fn().mockResolvedValue([]) }, + }, + { + provide: uuid_resolver_service_1.UuidResolverService, + useValue: { + resolveProjectId: jest.fn().mockResolvedValue(1), + resolveOrganizationId: jest.fn().mockResolvedValue(1), + }, + }, + { + provide: notification_service_1.NotificationService, + useValue: { send: jest.fn().mockResolvedValue(undefined) }, + }, + ], + }).compile(); + service = testingModule.get(correspondence_service_1.CorrespondenceService); + numberingService = testingModule.get(document_numbering_service_1.DocumentNumberingService); + correspondenceRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence)); + revisionRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision)); + _dataSource = testingModule.get(typeorm_2.DataSource); + }); + it('should be defined', () => { + expect(service).toBeDefined(); + }); + describe('update', () => { + it('should allow non-draft update for org-admin+ permissions', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 23, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + statusRepo.findOne.mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + const userService = testingModule.get(user_service_1.UserService); + userService.getUserPermissions.mockResolvedValue([ + 'correspondence.cancel', + ]); + await expect(service.update(1, { subject: 'Updated Subject' }, mockUser)).resolves.toBeDefined(); + }); + it('should reject non-draft update for non-admin permissions', async () => { + const mockUser = { + user_id: 2, + primaryOrganizationId: 10, + }; + const mockRevision = { + id: 101, + correspondenceId: 2, + isCurrent: true, + statusId: 23, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + statusRepo.findOne.mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + const userService = testingModule.get(user_service_1.UserService); + userService.getUserPermissions.mockResolvedValue([ + 'correspondence.edit', + ]); + await expect(service.update(2, { subject: 'Should Fail' }, mockUser)).rejects.toThrow(common_1.ForbiddenException); + }); + it('should NOT regenerate number if critical fields unchanged', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 1, + disciplineId: 3, + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).not.toHaveBeenCalled(); + }); + it('should regenerate number if Project ID changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 2, + }; + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(2); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Document Type changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + typeId: 999, + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + typeRepo.findOne.mockResolvedValue({ + id: 999, + typeCode: 'NEW-TYPE', + }); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Recipient Organization changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + // Access DataSource manager for mocking + mockDataSource.manager.findOne.mockResolvedValue({ + id: 88, + organizationCode: 'NEW-ORG', + }); + const updateDto = { + recipients: [{ type: 'TO', organizationId: 88 }], + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + }); + describe('create', () => { + it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: null, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + originatorId: 'originator-uuid', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const userService = testingModule.get(user_service_1.UserService); + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + userService.findOne.mockResolvedValue({ + user_id: 1, + primaryOrganizationId: null, + }); + userService.getUserPermissions.mockResolvedValue([ + 'system.manage_all', + ]); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockImplementation((value) => { + if (value === 'originator-uuid') + return 10; + if (value === 'recipient-uuid') + return 20; + return 0; + }); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LTR', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_entity_1.Correspondence, expect.objectContaining({ originatorId: 10 })); + }); + it('should set revisionLabel to "A" for RFA type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'RFA', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: 'A' })); + }); + it('should set revisionLabel to "A" for RFI type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'RFI', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: 'A' })); + }); + it('should set revisionLabel to null for LETTER type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LETTER', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: undefined })); + }); + it('should set revisionLabel to undefined for MEMO type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'MEMO', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: undefined })); + }); + }); +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyIsIm1hcHBpbmdzIjoiOztBQUFBLDZDQUFzRDtBQUN0RCw2Q0FBcUQ7QUFDckQscUNBQWlEO0FBQ2pELDJDQUFvRDtBQUNwRCxxRUFBaUU7QUFDakUsNEVBQWtFO0FBQ2xFLDhGQUFtRjtBQUNuRixzRkFBMkU7QUFDM0UsMEZBQStFO0FBQy9FLGdHQUFxRjtBQUNyRixvRkFBeUU7QUFDekUsc0ZBQTRFO0FBQzVFLGdHQUFxRjtBQUNyRiwwR0FBcUc7QUFDckcsNEVBQXVFO0FBQ3ZFLHdGQUFtRjtBQUNuRix1REFBbUQ7QUFDbkQsNkRBQXlEO0FBQ3pELHlGQUFvRjtBQUNwRix1RkFBa0Y7QUFDbEYsK0VBQTJFO0FBSzNFLFFBQVEsQ0FBQyx1QkFBdUIsRUFBRSxHQUFHLEVBQUU7SUFDckMsSUFBSSxPQUE4QixDQUFDO0lBQ25DLElBQUksZ0JBQTBDLENBQUM7SUFDL0MsSUFBSSxrQkFBOEMsQ0FBQztJQUNuRCxJQUFJLFlBQWdELENBQUM7SUFDckQsSUFBSSxhQUE0QixDQUFDO0lBQ2pDLElBQUksV0FBdUIsQ0FBQztJQUU1QixNQUFNLG9CQUFvQixHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDbEMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDZixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNsQixNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNqQixJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNmLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLFVBQVUsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ3JCLGtCQUFrQixFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENB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bmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUZXN0LCBUZXN0aW5nTW9kdWxlIH0gZnJvbSAnQG5lc3Rqcy90ZXN0aW5nJztcclxuaW1wb3J0IHsgZ2V0UmVwb3NpdG9yeVRva2VuIH0gZnJvbSAnQG5lc3Rqcy90eXBlb3JtJztcclxuaW1wb3J0IHsgRGF0YVNvdXJjZSwgUmVwb3NpdG9yeSB9IGZyb20gJ3R5cGVvcm0nO1xyXG5pbXBvcnQgeyBGb3JiaWRkZW5FeGNlcHRpb24gfSBmcm9tICdAbmVzdGpzL2NvbW1vbic7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlU2VydmljZSB9IGZyb20gJy4vY29ycmVzcG9uZGVuY2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJldmlzaW9uIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZXZpc2lvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVR5cGUgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXR5cGUuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VTdGF0dXMgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXN0YXR1cy5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlZmVyZW5jZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVmZXJlbmNlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVGFnIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS10YWcuZW50aXR5JztcclxuaW1wb3J0IHsgT3JnYW5pemF0aW9uIH0gZnJvbSAnLi4vb3JnYW5pemF0aW9uL2VudGl0aWVzL29yZ2FuaXphdGlvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlY2lwaWVudCB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVjaXBpZW50LmVudGl0eSc7XHJcbmltcG9ydCB7IERvY3VtZW50TnVtYmVyaW5nU2VydmljZSB9IGZyb20gJy4uL2RvY3VtZW50LW51bWJlcmluZy9zZXJ2aWNlcy9kb2N1bWVudC1udW1iZXJpbmcuc2VydmljZSc7XHJcbmltcG9ydCB7IEpzb25TY2hlbWFTZXJ2aWNlIH0gZnJvbSAnLi4vanNvbi1zY2hlbWEvanNvbi1zY2hlbWEuc2VydmljZSc7XHJcbmltcG9ydCB7IFdvcmtmbG93RW5naW5lU2VydmljZSB9IGZyb20gJy4uL3dvcmtmbG93LWVuZ2luZS93b3JrZmxvdy1lbmdpbmUuc2VydmljZSc7XHJcbmltcG9ydCB7IFVzZXJTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlci91c2VyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTZWFyY2hTZXJ2aWNlIH0gZnJvbSAnLi4vc2VhcmNoL3NlYXJjaC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRmlsZVN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL2ZpbGUtc3RvcmFnZS9maWxlLXN0b3JhZ2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IFV1aWRSZXNvbHZlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vc2VydmljZXMvdXVpZC1yZXNvbHZlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi9ub3RpZmljYXRpb24uc2VydmljZSc7XHJcbmltcG9ydCB7IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vdXBkYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vY3JlYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi91c2VyL2VudGl0aWVzL3VzZXIuZW50aXR5JztcclxuXHJcbmRlc2NyaWJlKCdDb3JyZXNwb25kZW5jZVNlcnZpY2UnLCAoKSA9PiB7XHJcbiAgbGV0IHNlcnZpY2U6IENvcnJlc3BvbmRlbmNlU2VydmljZTtcclxuICBsZXQgbnVtYmVyaW5nU2VydmljZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlO1xyXG4gIGxldCBjb3JyZXNwb25kZW5jZVJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2U+O1xyXG4gIGxldCByZXZpc2lvblJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VSZXZpc2lvbj47XHJcbiAgbGV0IHRlc3RpbmdNb2R1bGU6IFRlc3RpbmdNb2R1bGU7XHJcbiAgbGV0IF9kYXRhU291cmNlOiBEYXRhU291cmNlO1xyXG5cclxuICBjb25zdCBjcmVhdGVNb2NrUmVwb3NpdG9yeSA9ICgpID0+ICh7XHJcbiAgICBmaW5kOiBqZXN0LmZuKCksXHJcbiAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGU6IGplc3QuZm4oKSxcclxuICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgIHVwZGF0ZTogamVzdC5mbigpLFxyXG4gICAgZGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBzb2Z0RGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGVRdWVyeUJ1aWxkZXI6IGplc3QuZm4oKCkgPT4gKHtcclxuICAgICAgbGVmdEpvaW5BbmRTZWxlY3Q6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB3aGVyZTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIGFuZFdoZXJlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgb3JkZXJCeTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIHNraXA6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB0YWtlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgZ2V0T25lOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUobnVsbCksXHJcbiAgICAgIGdldE1hbnk6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSksXHJcbiAgICAgIGdldE1hbnlBbmRDb3VudDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKFtbXSwgMF0pLFxyXG4gICAgfSkpLFxyXG4gIH0pO1xyXG5cclxuICBjb25zdCBtb2NrRGF0YVNvdXJjZSA9IHtcclxuICAgIGNyZWF0ZVF1ZXJ5UnVubmVyOiBqZXN0LmZuKCgpID0+ICh7XHJcbiAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgIGNyZWF0ZTogamVzdC5mbigpLFxyXG4gICAgICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgIH0sXHJcbiAgICB9KSksXHJcbiAgICBnZXRSZXBvc2l0b3J5OiBqZXN0LmZuKCgpID0+IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCkpLFxyXG4gICAgbWFuYWdlcjoge1xyXG4gICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICB9LFxyXG4gIH07XHJcblxyXG4gIGJlZm9yZUVhY2goYXN5bmMgKCkgPT4ge1xyXG4gICAgdGVzdGluZ01vZHVsZSA9IGF3YWl0IFRlc3QuY3JlYXRlVGVzdGluZ01vZHVsZSh7XHJcbiAgICAgIHByb3ZpZGVyczogW1xyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlU2VydmljZSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZXZpc2lvbiksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZWZlcmVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUYWcpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oT3JnYW5pemF0aW9uKSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmVjaXBpZW50KSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHtcclxuICAgICAgICAgICAgZ2VuZXJhdGVOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHVwZGF0ZU51bWJlckZvckRyYWZ0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHByZXZpZXdOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogSnNvblNjaGVtYVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyB2YWxpZGF0ZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBXb3JrZmxvd0VuZ2luZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjcmVhdGVJbnN0YW5jZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBVc2VyU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7XHJcbiAgICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICAgICAgZ2V0VXNlclBlcm1pc3Npb25zOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoW10pLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IERhdGFTb3VyY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogbW9ja0RhdGFTb3VyY2UsXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBTZWFyY2hTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHsgaW5kZXhEb2N1bWVudDogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBGaWxlU3RvcmFnZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjb21taXQ6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFV1aWRSZXNvbHZlclNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZToge1xyXG4gICAgICAgICAgICByZXNvbHZlUHJvamVjdElkOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoMSksXHJcbiAgICAgICAgICAgIHJlc29sdmVPcmdhbml6YXRpb25JZDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKDEpLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IE5vdGlmaWNhdGlvblNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBzZW5kOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUodW5kZWZpbmVkKSB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgIF0sXHJcbiAgICB9KS5jb21waWxlKCk7XHJcblxyXG4gICAgc2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PENvcnJlc3BvbmRlbmNlU2VydmljZT4oQ29ycmVzcG9uZGVuY2VTZXJ2aWNlKTtcclxuICAgIG51bWJlcmluZ1NlcnZpY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEb2N1bWVudE51bWJlcmluZ1NlcnZpY2U+KFxyXG4gICAgICBEb2N1bWVudE51bWJlcmluZ1NlcnZpY2VcclxuICAgICk7XHJcbiAgICBjb3JyZXNwb25kZW5jZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlPj4oXHJcbiAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZSlcclxuICAgICk7XHJcbiAgICByZXZpc2lvblJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlUmV2aXNpb24+PihcclxuICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmV2aXNpb24pXHJcbiAgICApO1xyXG4gICAgX2RhdGFTb3VyY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEYXRhU291cmNlPihEYXRhU291cmNlKTtcclxuICB9KTtcclxuXHJcbiAgaXQoJ3Nob3VsZCBiZSBkZWZpbmVkJywgKCkgPT4ge1xyXG4gICAgZXhwZWN0KHNlcnZpY2UpLnRvQmVEZWZpbmVkKCk7XHJcbiAgfSk7XHJcblxyXG4gIGRlc2NyaWJlKCd1cGRhdGUnLCAoKSA9PiB7XHJcbiAgICBpdCgnc2hvdWxkIGFsbG93IG5vbi1kcmFmdCB1cGRhdGUgZm9yIG9yZy1hZG1pbisgcGVybWlzc2lvbnMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiAyMyxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3Qgc3RhdHVzUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VTdGF0dXM+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpXHJcbiAgICAgICk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDIzLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdTVUJPV04nLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHVzZXJTZXJ2aWNlID0gdGVzdGluZ01vZHVsZS5nZXQ8VXNlclNlcnZpY2U+KFVzZXJTZXJ2aWNlKTtcclxuICAgICAgKHVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKFtcclxuICAgICAgICAnY29ycmVzcG9uZGVuY2UuY2FuY2VsJyxcclxuICAgICAgXSk7XHJcblxyXG4gICAgICBhd2FpdCBleHBlY3QoXHJcbiAgICAgICAgc2VydmljZS51cGRhdGUoMSwgeyBzdWJqZWN0OiAnVXBkYXRlZCBTdWJqZWN0JyB9LCBtb2NrVXNlcilcclxuICAgICAgKS5yZXNvbHZlcy50b0JlRGVmaW5lZCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCByZWplY3Qgbm9uLWRyYWZ0IHVwZGF0ZSBmb3Igbm9uLWFkbWluIHBlcm1pc3Npb25zJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAyLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAyLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogMjMsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAyMyxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnU1VCT1dOJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBjb25zdCB1c2VyU2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PFVzZXJTZXJ2aWNlPihVc2VyU2VydmljZSk7XHJcbiAgICAgICh1c2VyU2VydmljZS5nZXRVc2VyUGVybWlzc2lvbnMgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXHJcbiAgICAgICAgJ2NvcnJlc3BvbmRlbmNlLmVkaXQnLFxyXG4gICAgICBdKTtcclxuXHJcbiAgICAgIGF3YWl0IGV4cGVjdChcclxuICAgICAgICBzZXJ2aWNlLnVwZGF0ZSgyLCB7IHN1YmplY3Q6ICdTaG91bGQgRmFpbCcgfSwgbW9ja1VzZXIpXHJcbiAgICAgICkucmVqZWN0cy50b1Rocm93KEZvcmJpZGRlbkV4Y2VwdGlvbik7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIE5PVCByZWdlbmVyYXRlIG51bWJlciBpZiBjcml0aWNhbCBmaWVsZHMgdW5jaGFuZ2VkJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCByZWdlbmVyYXRlIG51bWJlciBpZiBQcm9qZWN0IElEIGNoYW5nZXMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0geyBpZDogMSwgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMSxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDUsXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3QgbW9ja0NvcnIgPSB7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiAyLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6IDEwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiAnT0xELU5VTScsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgcmVjaXBpZW50VHlwZTogJ1RPJywgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IDk5IH1dLFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrQ29yciBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUR0bzogVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcHJvamVjdElkOiAyLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMik7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgcmVnZW5lcmF0ZSBudW1iZXIgaWYgRG9jdW1lbnQgVHlwZSBjaGFuZ2VzJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IG1vY2tDb3JyID0ge1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZVR5cGVJZDogMixcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAxMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogJ09MRC1OVU0nLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHJlY2lwaWVudFR5cGU6ICdUTycsIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiA5OSB9XSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihjb3JyZXNwb25kZW5jZVJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja0NvcnIgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHR5cGVJZDogOTk5LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgICh0eXBlUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiA5OTksXHJcbiAgICAgICAgdHlwZUNvZGU6ICdORVctVFlQRScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS50b0hhdmVCZWVuQ2FsbGVkKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHJlZ2VuZXJhdGUgbnVtYmVyIGlmIFJlY2lwaWVudCBPcmdhbml6YXRpb24gY2hhbmdlcycsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7IGlkOiAxLCBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAxLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogNSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgLy8gQWNjZXNzIERhdGFTb3VyY2UgbWFuYWdlciBmb3IgbW9ja2luZ1xyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiA4OCxcclxuICAgICAgICBvcmdhbml6YXRpb25Db2RlOiAnTkVXLU9SRycsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBPcmdhbml6YXRpb24pO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICByZWNpcGllbnRzOiBbeyB0eXBlOiAnVE8nLCBvcmdhbml6YXRpb25JZDogODggfV0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG4gIH0pO1xyXG5cclxuICBkZXNjcmliZSgnY3JlYXRlJywgKCkgPT4ge1xyXG4gICAgaXQoJ3Nob3VsZCBhbGxvdyBzeXN0ZW0ubWFuYWdlX2FsbCB1c2VyIHdpdGhvdXQgcHJpbWFyeU9yZ2FuaXphdGlvbklkIHdoZW4gb3JpZ2luYXRvcklkIGlzIHByb3ZpZGVkJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogbnVsbCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogJ29yaWdpbmF0b3ItdXVpZCcsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgb3JnYW5pemF0aW9uSWQ6ICdyZWNpcGllbnQtdXVpZCcsIHR5cGU6ICdUTycgfV0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCB1c2VyU2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PFVzZXJTZXJ2aWNlPihVc2VyU2VydmljZSk7XHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuXHJcbiAgICAgICh1c2VyU2VydmljZS5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiBudWxsLFxyXG4gICAgICB9KTtcclxuICAgICAgKHVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKFtcclxuICAgICAgICAnc3lzdGVtLm1hbmFnZV9hbGwnLFxyXG4gICAgICBdKTtcclxuXHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDEwMCk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkIGFzIGplc3QuTW9jaykubW9ja0ltcGxlbWVudGF0aW9uKFxyXG4gICAgICAgICh2YWx1ZTogbnVtYmVyIHwgc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICBpZiAodmFsdWUgPT09ICdvcmlnaW5hdG9yLXV1aWQnKSByZXR1cm4gMTA7XHJcbiAgICAgICAgICBpZiAodmFsdWUgPT09ICdyZWNpcGllbnQtdXVpZCcpIHJldHVybiAyMDtcclxuICAgICAgICAgIHJldHVybiAwO1xyXG4gICAgICAgIH1cclxuICAgICAgKTtcclxuXHJcbiAgICAgICh0eXBlUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHR5cGVDb2RlOiAnTFRSJyxcclxuICAgICAgfSk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgc3RhdHVzQ29kZTogJ0RSQUZUJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAobnVtYmVyaW5nU2VydmljZS5nZW5lcmF0ZU5leHROdW1iZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgbnVtYmVyOiAnRE9DLTAwMScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgbW9ja0RhdGFTb3VyY2UubWFuYWdlci5maW5kT25lXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMCwgb3JnYW5pemF0aW9uQ29kZTogJ09SRycgfSlcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDIwLCBvcmdhbml6YXRpb25Db2RlOiAnUkVDJyB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHF1ZXJ5UnVubmVyID0ge1xyXG4gICAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgICBzdGFydFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgY29tbWl0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcmVsZWFzZTogamVzdC5mbigpLFxyXG4gICAgICAgIG1hbmFnZXI6IHtcclxuICAgICAgICAgIGNyZWF0ZTogamVzdC5mbihcclxuICAgICAgICAgICAgKF9lbnRpdHk6IHVua25vd24sIHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBwYXlsb2FkXHJcbiAgICAgICAgICApLFxyXG4gICAgICAgICAgc2F2ZTogamVzdFxyXG4gICAgICAgICAgICAuZm4oKVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDk5OSwgcHVibGljSWQ6ICdjb3JyLXV1aWQnIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAwMCB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKFtdKSxcclxuICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICB9LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgKG1vY2tEYXRhU291cmNlLmNyZWF0ZVF1ZXJ5UnVubmVyIGFzIGplc3QuTW9jaykubW9ja1JldHVyblZhbHVlKFxyXG4gICAgICAgIHF1ZXJ5UnVubmVyXHJcbiAgICAgICk7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLmNyZWF0ZShjcmVhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2UsXHJcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyBvcmlnaW5hdG9ySWQ6IDEwIH0pXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHNldCByZXZpc2lvbkxhYmVsIHRvIFwiQVwiIGZvciBSRkEgdHlwZScsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7XHJcbiAgICAgICAgdXNlcl9pZDogMSxcclxuICAgICAgICBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuXHJcbiAgICAgIGNvbnN0IGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcHJvamVjdElkOiAncHJvamVjdC11dWlkJyxcclxuICAgICAgICB0eXBlSWQ6IDEsXHJcbiAgICAgICAgc3ViamVjdDogJ1Rlc3QgU3ViamVjdCcsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgb3JnYW5pemF0aW9uSWQ6ICdyZWNpcGllbnQtdXVpZCcsIHR5cGU6ICdUTycgfV0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCB0eXBlUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VUeXBlPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlVHlwZSlcclxuICAgICAgKTtcclxuICAgICAgY29uc3Qgc3RhdHVzUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VTdGF0dXM+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHV1aWRSZXNvbHZlciA9XHJcbiAgICAgICAgdGVzdGluZ01vZHVsZS5nZXQ8VXVpZFJlc29sdmVyU2VydmljZT4oVXVpZFJlc29sdmVyU2VydmljZSk7XHJcblxyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgxMDApO1xyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDIwKTtcclxuXHJcbiAgICAgICh0eXBlUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHR5cGVDb2RlOiAnUkZBJyxcclxuICAgICAgfSk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgc3RhdHVzQ29kZTogJ0RSQUZUJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAobnVtYmVyaW5nU2VydmljZS5nZW5lcmF0ZU5leHROdW1iZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgbnVtYmVyOiAnRE9DLTAwMScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgbW9ja0RhdGFTb3VyY2UubWFuYWdlci5maW5kT25lXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMCwgb3JnYW5pemF0aW9uQ29kZTogJ09SRycgfSlcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDIwLCBvcmdhbml6YXRpb25Db2RlOiAnUkVDJyB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHF1ZXJ5UnVubmVyID0ge1xyXG4gICAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgICBzdGFydFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgY29tbWl0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcmVsZWFzZTogamVzdC5mbigpLFxyXG4gICAgICAgIG1hbmFnZXI6IHtcclxuICAgICAgICAgIGNyZWF0ZTogamVzdC5mbihcclxuICAgICAgICAgICAgKF9lbnRpdHk6IHVua25vd24sIHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBwYXlsb2FkXHJcbiAgICAgICAgICApLFxyXG4gICAgICAgICAgc2F2ZTogamVzdFxyXG4gICAgICAgICAgICAuZm4oKVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDk5OSwgcHVibGljSWQ6ICdjb3JyLXV1aWQnIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAwMCB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKFtdKSxcclxuICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICB9LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgKG1vY2tEYXRhU291cmNlLmNyZWF0ZVF1ZXJ5UnVubmVyIGFzIGplc3QuTW9jaykubW9ja1JldHVyblZhbHVlKFxyXG4gICAgICAgIHF1ZXJ5UnVubmVyXHJcbiAgICAgICk7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLmNyZWF0ZShjcmVhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbixcclxuICAgICAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7IHJldmlzaW9uTGFiZWw6ICdBJyB9KVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCBzZXQgcmV2aXNpb25MYWJlbCB0byBcIkFcIiBmb3IgUkZJIHR5cGUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyMCk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ1JGSScsXHJcbiAgICAgIH0pO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdEUkFGVCcsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgKG51bWJlcmluZ1NlcnZpY2UuZ2VuZXJhdGVOZXh0TnVtYmVyIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIG51bWJlcjogJ0RPQy0wMDEnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAsIG9yZ2FuaXphdGlvbkNvZGU6ICdPUkcnIH0pXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAyMCwgb3JnYW5pemF0aW9uQ29kZTogJ1JFQycgfSk7XHJcblxyXG4gICAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHtcclxuICAgICAgICBjb25uZWN0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcm9sbGJhY2tUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgICBjcmVhdGU6IGplc3QuZm4oXHJcbiAgICAgICAgICAgIChfZW50aXR5OiB1bmtub3duLCBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gcGF5bG9hZFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIHNhdmU6IGplc3RcclxuICAgICAgICAgICAgLmZuKClcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiA5OTksIHB1YmxpY0lkOiAnY29yci11dWlkJyB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwMDAgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZShbXSksXHJcbiAgICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgICAgfSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIChtb2NrRGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lciBhcyBqZXN0Lk1vY2spLm1vY2tSZXR1cm5WYWx1ZShcclxuICAgICAgICBxdWVyeVJ1bm5lclxyXG4gICAgICApO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS5jcmVhdGUoY3JlYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QocXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmV2aXNpb24sXHJcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyByZXZpc2lvbkxhYmVsOiAnQScgfSlcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgc2V0IHJldmlzaW9uTGFiZWwgdG8gbnVsbCBmb3IgTEVUVEVSIHR5cGUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyMCk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ0xFVFRFUicsXHJcbiAgICAgIH0pO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdEUkFGVCcsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgKG51bWJlcmluZ1NlcnZpY2UuZ2VuZXJhdGVOZXh0TnVtYmVyIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIG51bWJlcjogJ0RPQy0wMDEnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAsIG9yZ2FuaXphdGlvbkNvZGU6ICdPUkcnIH0pXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAyMCwgb3JnYW5pemF0aW9uQ29kZTogJ1JFQycgfSk7XHJcblxyXG4gICAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHtcclxuICAgICAgICBjb25uZWN0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcm9sbGJhY2tUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgICBjcmVhdGU6IGplc3QuZm4oXHJcbiAgICAgICAgICAgIChfZW50aXR5OiB1bmtub3duLCBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gcGF5bG9hZFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIHNhdmU6IGplc3RcclxuICAgICAgICAgICAgLmZuKClcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiA5OTksIHB1YmxpY0lkOiAnY29yci11dWlkJyB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwMDAgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZShbXSksXHJcbiAgICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgICAgfSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIChtb2NrRGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lciBhcyBqZXN0Lk1vY2spLm1vY2tSZXR1cm5WYWx1ZShcclxuICAgICAgICBxdWVyeVJ1bm5lclxyXG4gICAgICApO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS5jcmVhdGUoY3JlYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QocXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmV2aXNpb24sXHJcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyByZXZpc2lvbkxhYmVsOiB1bmRlZmluZWQgfSlcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgc2V0IHJldmlzaW9uTGFiZWwgdG8gdW5kZWZpbmVkIGZvciBNRU1PIHR5cGUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyMCk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ01FTU8nLFxyXG4gICAgICB9KTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnRFJBRlQnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIChudW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlciBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBudW1iZXI6ICdET0MtMDAxJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmVcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwLCBvcmdhbml6YXRpb25Db2RlOiAnT1JHJyB9KVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMjAsIG9yZ2FuaXphdGlvbkNvZGU6ICdSRUMnIH0pO1xyXG5cclxuICAgICAgY29uc3QgcXVlcnlSdW5uZXIgPSB7XHJcbiAgICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICAgIHN0YXJ0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByZWxlYXNlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgICAgY3JlYXRlOiBqZXN0LmZuKFxyXG4gICAgICAgICAgICAoX2VudGl0eTogdW5rbm93biwgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHBheWxvYWRcclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBzYXZlOiBqZXN0XHJcbiAgICAgICAgICAgIC5mbigpXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogOTk5LCBwdWJsaWNJZDogJ2NvcnItdXVpZCcgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMDAwIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoW10pLFxyXG4gICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICAobW9ja0RhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmV0dXJuVmFsdWUoXHJcbiAgICAgICAgcXVlcnlSdW5uZXJcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UuY3JlYXRlKGNyZWF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcclxuICAgICAgICBDb3JyZXNwb25kZW5jZVJldmlzaW9uLFxyXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgcmV2aXNpb25MYWJlbDogdW5kZWZpbmVkIH0pXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuICB9KTtcclxufSk7XHJcbiJdLCJ2ZXJzaW9uIjozfQ== \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/58/correspondenceservicespec_586a629fcc7afcef7cda907c465dd491.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/58/correspondenceservicespec_586a629fcc7afcef7cda907c465dd491.map new file mode 100644 index 0000000..fd72b17 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/58/correspondenceservicespec_586a629fcc7afcef7cda907c465dd491.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts"],"sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\r\nimport { getRepositoryToken } from '@nestjs/typeorm';\r\nimport { DataSource, Repository } from 'typeorm';\r\nimport { ForbiddenException } from '@nestjs/common';\r\nimport { CorrespondenceService } from './correspondence.service';\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { User } from '../user/entities/user.entity';\r\n\r\ndescribe('CorrespondenceService', () => {\r\n let service: CorrespondenceService;\r\n let numberingService: DocumentNumberingService;\r\n let correspondenceRepo: Repository;\r\n let revisionRepo: Repository;\r\n let testingModule: TestingModule;\r\n let _dataSource: DataSource;\r\n\r\n const createMockRepository = () => ({\r\n find: jest.fn(),\r\n findOne: jest.fn(),\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n update: jest.fn(),\r\n delete: jest.fn(),\r\n softDelete: jest.fn(),\r\n createQueryBuilder: jest.fn(() => ({\r\n leftJoinAndSelect: jest.fn().mockReturnThis(),\r\n where: jest.fn().mockReturnThis(),\r\n andWhere: jest.fn().mockReturnThis(),\r\n orderBy: jest.fn().mockReturnThis(),\r\n skip: jest.fn().mockReturnThis(),\r\n take: jest.fn().mockReturnThis(),\r\n getOne: jest.fn().mockResolvedValue(null),\r\n getMany: jest.fn().mockResolvedValue([]),\r\n getManyAndCount: jest.fn().mockResolvedValue([[], 0]),\r\n })),\r\n });\r\n\r\n const mockDataSource = {\r\n createQueryRunner: jest.fn(() => ({\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n findOne: jest.fn(),\r\n },\r\n })),\r\n getRepository: jest.fn(() => createMockRepository()),\r\n manager: {\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n beforeEach(async () => {\r\n testingModule = await Test.createTestingModule({\r\n providers: [\r\n CorrespondenceService,\r\n {\r\n provide: getRepositoryToken(Correspondence),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRevision),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceType),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceStatus),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceReference),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceTag),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(Organization),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRecipient),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: DocumentNumberingService,\r\n useValue: {\r\n generateNextNumber: jest.fn(),\r\n updateNumberForDraft: jest.fn(),\r\n previewNextNumber: jest.fn(),\r\n },\r\n },\r\n {\r\n provide: JsonSchemaService,\r\n useValue: { validate: jest.fn() },\r\n },\r\n {\r\n provide: WorkflowEngineService,\r\n useValue: { createInstance: jest.fn() },\r\n },\r\n {\r\n provide: UserService,\r\n useValue: {\r\n findOne: jest.fn(),\r\n getUserPermissions: jest.fn().mockResolvedValue([]),\r\n },\r\n },\r\n {\r\n provide: DataSource,\r\n useValue: mockDataSource,\r\n },\r\n {\r\n provide: SearchService,\r\n useValue: { indexDocument: jest.fn() },\r\n },\r\n {\r\n provide: FileStorageService,\r\n useValue: { commit: jest.fn().mockResolvedValue([]) },\r\n },\r\n {\r\n provide: UuidResolverService,\r\n useValue: {\r\n resolveProjectId: jest.fn().mockResolvedValue(1),\r\n resolveOrganizationId: jest.fn().mockResolvedValue(1),\r\n },\r\n },\r\n {\r\n provide: NotificationService,\r\n useValue: { send: jest.fn().mockResolvedValue(undefined) },\r\n },\r\n ],\r\n }).compile();\r\n\r\n service = testingModule.get(CorrespondenceService);\r\n numberingService = testingModule.get(\r\n DocumentNumberingService\r\n );\r\n correspondenceRepo = testingModule.get>(\r\n getRepositoryToken(Correspondence)\r\n );\r\n revisionRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceRevision)\r\n );\r\n _dataSource = testingModule.get(DataSource);\r\n });\r\n\r\n it('should be defined', () => {\r\n expect(service).toBeDefined();\r\n });\r\n\r\n describe('update', () => {\r\n it('should allow non-draft update for org-admin+ permissions', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 23,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 23,\r\n statusCode: 'SUBOWN',\r\n });\r\n\r\n const userService = testingModule.get(UserService);\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'correspondence.cancel',\r\n ]);\r\n\r\n await expect(\r\n service.update(1, { subject: 'Updated Subject' }, mockUser)\r\n ).resolves.toBeDefined();\r\n });\r\n\r\n it('should reject non-draft update for non-admin permissions', async () => {\r\n const mockUser = {\r\n user_id: 2,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n const mockRevision = {\r\n id: 101,\r\n correspondenceId: 2,\r\n isCurrent: true,\r\n statusId: 23,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 23,\r\n statusCode: 'SUBOWN',\r\n });\r\n\r\n const userService = testingModule.get(UserService);\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'correspondence.edit',\r\n ]);\r\n\r\n await expect(\r\n service.update(2, { subject: 'Should Fail' }, mockUser)\r\n ).rejects.toThrow(ForbiddenException);\r\n });\r\n\r\n it('should NOT regenerate number if critical fields unchanged', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 1,\r\n disciplineId: 3,\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).not.toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Project ID changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 2,\r\n };\r\n\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(2);\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Document Type changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n typeId: 999,\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 999,\r\n typeCode: 'NEW-TYPE',\r\n });\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Recipient Organization changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n // Access DataSource manager for mocking\r\n mockDataSource.manager.findOne.mockResolvedValue({\r\n id: 88,\r\n organizationCode: 'NEW-ORG',\r\n } as unknown as Organization);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n recipients: [{ type: 'TO', organizationId: 88 }],\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n });\r\n\r\n describe('create', () => {\r\n it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n originatorId: 'originator-uuid',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const userService = testingModule.get(UserService);\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (userService.findOne as jest.Mock).mockResolvedValue({\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n });\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'system.manage_all',\r\n ]);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockImplementation(\r\n (value: number | string) => {\r\n if (value === 'originator-uuid') return 10;\r\n if (value === 'recipient-uuid') return 20;\r\n return 0;\r\n }\r\n );\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LTR',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n Correspondence,\r\n expect.objectContaining({ originatorId: 10 })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to \"A\" for RFA type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'RFA',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: 'A' })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to \"A\" for RFI type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'RFI',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: 'A' })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to null for LETTER type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LETTER',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: undefined })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to undefined for MEMO type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'MEMO',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: undefined })\r\n );\r\n });\r\n });\r\n});\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/82/correspondenceservicespec_82e6df7890187e79e1a13a269c1041ae b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/82/correspondenceservicespec_82e6df7890187e79e1a13a269c1041ae new file mode 100644 index 0000000..c702f39 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/82/correspondenceservicespec_82e6df7890187e79e1a13a269c1041ae @@ -0,0 +1,620 @@ +83ec657cd9abe1b1e47afa8108649605 +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const testing_1 = require("@nestjs/testing"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +const common_1 = require("@nestjs/common"); +const correspondence_service_1 = require("./correspondence.service"); +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +describe('CorrespondenceService', () => { + let service; + let numberingService; + let correspondenceRepo; + let revisionRepo; + let testingModule; + let _dataSource; + const createMockRepository = () => ({ + find: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + save: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + softDelete: jest.fn(), + createQueryBuilder: jest.fn(() => ({ + leftJoinAndSelect: jest.fn().mockReturnThis(), + where: jest.fn().mockReturnThis(), + andWhere: jest.fn().mockReturnThis(), + orderBy: jest.fn().mockReturnThis(), + skip: jest.fn().mockReturnThis(), + take: jest.fn().mockReturnThis(), + getOne: jest.fn().mockResolvedValue(null), + getMany: jest.fn().mockResolvedValue([]), + getManyAndCount: jest.fn().mockResolvedValue([[], 0]), + })), + }); + const mockDataSource = { + createQueryRunner: jest.fn(() => ({ + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn(), + save: jest.fn(), + findOne: jest.fn(), + }, + })), + getRepository: jest.fn(() => createMockRepository()), + manager: { + findOne: jest.fn(), + }, + }; + beforeEach(async () => { + testingModule = await testing_1.Test.createTestingModule({ + providers: [ + correspondence_service_1.CorrespondenceService, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_reference_entity_1.CorrespondenceReference), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_tag_entity_1.CorrespondenceTag), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(organization_entity_1.Organization), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_recipient_entity_1.CorrespondenceRecipient), + useValue: createMockRepository(), + }, + { + provide: document_numbering_service_1.DocumentNumberingService, + useValue: { + generateNextNumber: jest.fn(), + updateNumberForDraft: jest.fn(), + previewNextNumber: jest.fn(), + }, + }, + { + provide: json_schema_service_1.JsonSchemaService, + useValue: { validate: jest.fn() }, + }, + { + provide: workflow_engine_service_1.WorkflowEngineService, + useValue: { createInstance: jest.fn() }, + }, + { + provide: user_service_1.UserService, + useValue: { + findOne: jest.fn(), + getUserPermissions: jest.fn().mockResolvedValue([]), + }, + }, + { + provide: typeorm_2.DataSource, + useValue: mockDataSource, + }, + { + provide: search_service_1.SearchService, + useValue: { indexDocument: jest.fn() }, + }, + { + provide: file_storage_service_1.FileStorageService, + useValue: { commit: jest.fn().mockResolvedValue([]) }, + }, + { + provide: uuid_resolver_service_1.UuidResolverService, + useValue: { + resolveProjectId: jest.fn().mockResolvedValue(1), + resolveOrganizationId: jest.fn().mockResolvedValue(1), + }, + }, + { + provide: notification_service_1.NotificationService, + useValue: { send: jest.fn().mockResolvedValue(undefined) }, + }, + ], + }).compile(); + service = testingModule.get(correspondence_service_1.CorrespondenceService); + numberingService = testingModule.get(document_numbering_service_1.DocumentNumberingService); + correspondenceRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence)); + revisionRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision)); + _dataSource = testingModule.get(typeorm_2.DataSource); + }); + it('should be defined', () => { + expect(service).toBeDefined(); + }); + describe('update', () => { + it('should allow non-draft update for org-admin+ permissions', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 23, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + statusRepo.findOne.mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + const userService = testingModule.get(user_service_1.UserService); + userService.getUserPermissions.mockResolvedValue([ + 'correspondence.cancel', + ]); + jest.spyOn(correspondenceRepo, 'findOne').mockResolvedValue({ + id: 1, + publicId: 'corr-uuid-1', + correspondenceNumber: 'CORR-001', + projectId: 1, + createdAt: new Date(), + revisions: [], + }); + await expect(service.update(1, { subject: 'Updated Subject' }, mockUser)).resolves.toBeDefined(); + }); + it('should reject non-draft update for non-admin permissions', async () => { + const mockUser = { + user_id: 2, + primaryOrganizationId: 10, + }; + const mockRevision = { + id: 101, + correspondenceId: 2, + isCurrent: true, + statusId: 23, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + statusRepo.findOne.mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + const userService = testingModule.get(user_service_1.UserService); + userService.getUserPermissions.mockResolvedValue([ + 'correspondence.edit', + ]); + await expect(service.update(2, { subject: 'Should Fail' }, mockUser)).rejects.toThrow(common_1.ForbiddenException); + }); + it('should NOT regenerate number if critical fields unchanged', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 1, + disciplineId: 3, + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).not.toHaveBeenCalled(); + }); + it('should regenerate number if Project ID changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 2, + }; + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(2); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Document Type changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + typeId: 999, + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + typeRepo.findOne.mockResolvedValue({ + id: 999, + typeCode: 'NEW-TYPE', + }); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Recipient Organization changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + // Access DataSource manager for mocking + mockDataSource.manager.findOne.mockResolvedValue({ + id: 88, + organizationCode: 'NEW-ORG', + }); + const updateDto = { + recipients: [{ type: 'TO', organizationId: 88 }], + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + }); + describe('create', () => { + it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: null, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + originatorId: 'originator-uuid', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const userService = testingModule.get(user_service_1.UserService); + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + userService.findOne.mockResolvedValue({ + user_id: 1, + primaryOrganizationId: null, + }); + userService.getUserPermissions.mockResolvedValue([ + 'system.manage_all', + ]); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockImplementation((value) => { + if (value === 'originator-uuid') + return 10; + if (value === 'recipient-uuid') + return 20; + return 0; + }); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LTR', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_entity_1.Correspondence, expect.objectContaining({ originatorId: 10 })); + }); + it('should set revisionLabel to "A" for RFA type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'RFA', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: 'A' })); + }); + it('should set revisionLabel to "A" for RFI type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'RFI', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: 'A' })); + }); + it('should set revisionLabel to null for LETTER type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LETTER', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: undefined })); + }); + it('should set revisionLabel to undefined for MEMO type', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockResolvedValue(20); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'MEMO', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_revision_entity_1.CorrespondenceRevision, expect.objectContaining({ revisionLabel: undefined })); + }); + }); +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyIsIm1hcHBpbmdzIjoiOztBQUFBLDZDQUFzRDtBQUN0RCw2Q0FBcUQ7QUFDckQscUNBQWlEO0FBQ2pELDJDQUFvRDtBQUNwRCxxRUFBaUU7QUFDakUsNEVBQWtFO0FBQ2xFLDhGQUFtRjtBQUNuRixzRkFBMkU7QUFDM0UsMEZBQStFO0FBQy9FLGdHQUFxRjtBQUNyRixvRkFBeUU7QUFDekUsc0ZBQTRFO0FBQzVFLGdHQUFxRjtBQUNyRiwwR0FBcUc7QUFDckcsNEVBQXVFO0FBQ3ZFLHdGQUFtRjtBQUNuRix1REFBbUQ7QUFDbkQsNkRBQXlEO0FBQ3pELHlGQUFvRjtBQUNwRix1RkFBa0Y7QUFDbEYsK0VBQTJFO0FBSzNFLFFBQVEsQ0FBQyx1QkFBdUIsRUFBRSxHQUFHLEVBQUU7SUFDckMsSUFBSSxPQUE4QixDQUFDO0lBQ25DLElBQUksZ0JBQTBDLENBQUM7SUFDL0MsSUFBSSxrQkFBOEMsQ0FBQztJQUNuRCxJQUFJLFlBQWdELENBQUM7SUFDckQsSUFBSSxhQUE0QixDQUFDO0lBQ2pDLElBQUksV0FBdUIsQ0FBQztJQUU1QixNQUFNLG9CQUFvQixHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDbEMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDZixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNsQixNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNqQixJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNmLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLFVBQVUsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ3JCLGtCQUFrQixFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENB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T0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLG9CQUFvQixDQUNyRCx1REFBc0IsRUFDdEIsTUFBTSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQ3RELENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUZXN0LCBUZXN0aW5nTW9kdWxlIH0gZnJvbSAnQG5lc3Rqcy90ZXN0aW5nJztcclxuaW1wb3J0IHsgZ2V0UmVwb3NpdG9yeVRva2VuIH0gZnJvbSAnQG5lc3Rqcy90eXBlb3JtJztcclxuaW1wb3J0IHsgRGF0YVNvdXJjZSwgUmVwb3NpdG9yeSB9IGZyb20gJ3R5cGVvcm0nO1xyXG5pbXBvcnQgeyBGb3JiaWRkZW5FeGNlcHRpb24gfSBmcm9tICdAbmVzdGpzL2NvbW1vbic7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlU2VydmljZSB9IGZyb20gJy4vY29ycmVzcG9uZGVuY2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJldmlzaW9uIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZXZpc2lvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVR5cGUgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXR5cGUuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VTdGF0dXMgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXN0YXR1cy5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlZmVyZW5jZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVmZXJlbmNlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVGFnIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS10YWcuZW50aXR5JztcclxuaW1wb3J0IHsgT3JnYW5pemF0aW9uIH0gZnJvbSAnLi4vb3JnYW5pemF0aW9uL2VudGl0aWVzL29yZ2FuaXphdGlvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlY2lwaWVudCB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVjaXBpZW50LmVudGl0eSc7XHJcbmltcG9ydCB7IERvY3VtZW50TnVtYmVyaW5nU2VydmljZSB9IGZyb20gJy4uL2RvY3VtZW50LW51bWJlcmluZy9zZXJ2aWNlcy9kb2N1bWVudC1udW1iZXJpbmcuc2VydmljZSc7XHJcbmltcG9ydCB7IEpzb25TY2hlbWFTZXJ2aWNlIH0gZnJvbSAnLi4vanNvbi1zY2hlbWEvanNvbi1zY2hlbWEuc2VydmljZSc7XHJcbmltcG9ydCB7IFdvcmtmbG93RW5naW5lU2VydmljZSB9IGZyb20gJy4uL3dvcmtmbG93LWVuZ2luZS93b3JrZmxvdy1lbmdpbmUuc2VydmljZSc7XHJcbmltcG9ydCB7IFVzZXJTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlci91c2VyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTZWFyY2hTZXJ2aWNlIH0gZnJvbSAnLi4vc2VhcmNoL3NlYXJjaC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRmlsZVN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL2ZpbGUtc3RvcmFnZS9maWxlLXN0b3JhZ2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IFV1aWRSZXNvbHZlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vc2VydmljZXMvdXVpZC1yZXNvbHZlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi9ub3RpZmljYXRpb24uc2VydmljZSc7XHJcbmltcG9ydCB7IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vdXBkYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vY3JlYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi91c2VyL2VudGl0aWVzL3VzZXIuZW50aXR5JztcclxuXHJcbmRlc2NyaWJlKCdDb3JyZXNwb25kZW5jZVNlcnZpY2UnLCAoKSA9PiB7XHJcbiAgbGV0IHNlcnZpY2U6IENvcnJlc3BvbmRlbmNlU2VydmljZTtcclxuICBsZXQgbnVtYmVyaW5nU2VydmljZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlO1xyXG4gIGxldCBjb3JyZXNwb25kZW5jZVJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2U+O1xyXG4gIGxldCByZXZpc2lvblJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VSZXZpc2lvbj47XHJcbiAgbGV0IHRlc3RpbmdNb2R1bGU6IFRlc3RpbmdNb2R1bGU7XHJcbiAgbGV0IF9kYXRhU291cmNlOiBEYXRhU291cmNlO1xyXG5cclxuICBjb25zdCBjcmVhdGVNb2NrUmVwb3NpdG9yeSA9ICgpID0+ICh7XHJcbiAgICBmaW5kOiBqZXN0LmZuKCksXHJcbiAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGU6IGplc3QuZm4oKSxcclxuICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgIHVwZGF0ZTogamVzdC5mbigpLFxyXG4gICAgZGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBzb2Z0RGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGVRdWVyeUJ1aWxkZXI6IGplc3QuZm4oKCkgPT4gKHtcclxuICAgICAgbGVmdEpvaW5BbmRTZWxlY3Q6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB3aGVyZTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIGFuZFdoZXJlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgb3JkZXJCeTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIHNraXA6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB0YWtlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgZ2V0T25lOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUobnVsbCksXHJcbiAgICAgIGdldE1hbnk6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSksXHJcbiAgICAgIGdldE1hbnlBbmRDb3VudDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKFtbXSwgMF0pLFxyXG4gICAgfSkpLFxyXG4gIH0pO1xyXG5cclxuICBjb25zdCBtb2NrRGF0YVNvdXJjZSA9IHtcclxuICAgIGNyZWF0ZVF1ZXJ5UnVubmVyOiBqZXN0LmZuKCgpID0+ICh7XHJcbiAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgIGNyZWF0ZTogamVzdC5mbigpLFxyXG4gICAgICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgIH0sXHJcbiAgICB9KSksXHJcbiAgICBnZXRSZXBvc2l0b3J5OiBqZXN0LmZuKCgpID0+IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCkpLFxyXG4gICAgbWFuYWdlcjoge1xyXG4gICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICB9LFxyXG4gIH07XHJcblxyXG4gIGJlZm9yZUVhY2goYXN5bmMgKCkgPT4ge1xyXG4gICAgdGVzdGluZ01vZHVsZSA9IGF3YWl0IFRlc3QuY3JlYXRlVGVzdGluZ01vZHVsZSh7XHJcbiAgICAgIHByb3ZpZGVyczogW1xyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlU2VydmljZSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZXZpc2lvbiksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZWZlcmVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUYWcpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oT3JnYW5pemF0aW9uKSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmVjaXBpZW50KSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHtcclxuICAgICAgICAgICAgZ2VuZXJhdGVOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHVwZGF0ZU51bWJlckZvckRyYWZ0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHByZXZpZXdOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogSnNvblNjaGVtYVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyB2YWxpZGF0ZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBXb3JrZmxvd0VuZ2luZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjcmVhdGVJbnN0YW5jZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBVc2VyU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7XHJcbiAgICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICAgICAgZ2V0VXNlclBlcm1pc3Npb25zOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoW10pLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IERhdGFTb3VyY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogbW9ja0RhdGFTb3VyY2UsXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBTZWFyY2hTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHsgaW5kZXhEb2N1bWVudDogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBGaWxlU3RvcmFnZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjb21taXQ6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFV1aWRSZXNvbHZlclNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZToge1xyXG4gICAgICAgICAgICByZXNvbHZlUHJvamVjdElkOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoMSksXHJcbiAgICAgICAgICAgIHJlc29sdmVPcmdhbml6YXRpb25JZDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKDEpLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IE5vdGlmaWNhdGlvblNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBzZW5kOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUodW5kZWZpbmVkKSB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgIF0sXHJcbiAgICB9KS5jb21waWxlKCk7XHJcblxyXG4gICAgc2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PENvcnJlc3BvbmRlbmNlU2VydmljZT4oQ29ycmVzcG9uZGVuY2VTZXJ2aWNlKTtcclxuICAgIG51bWJlcmluZ1NlcnZpY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEb2N1bWVudE51bWJlcmluZ1NlcnZpY2U+KFxyXG4gICAgICBEb2N1bWVudE51bWJlcmluZ1NlcnZpY2VcclxuICAgICk7XHJcbiAgICBjb3JyZXNwb25kZW5jZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlPj4oXHJcbiAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZSlcclxuICAgICk7XHJcbiAgICByZXZpc2lvblJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlUmV2aXNpb24+PihcclxuICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmV2aXNpb24pXHJcbiAgICApO1xyXG4gICAgX2RhdGFTb3VyY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEYXRhU291cmNlPihEYXRhU291cmNlKTtcclxuICB9KTtcclxuXHJcbiAgaXQoJ3Nob3VsZCBiZSBkZWZpbmVkJywgKCkgPT4ge1xyXG4gICAgZXhwZWN0KHNlcnZpY2UpLnRvQmVEZWZpbmVkKCk7XHJcbiAgfSk7XHJcblxyXG4gIGRlc2NyaWJlKCd1cGRhdGUnLCAoKSA9PiB7XHJcbiAgICBpdCgnc2hvdWxkIGFsbG93IG5vbi1kcmFmdCB1cGRhdGUgZm9yIG9yZy1hZG1pbisgcGVybWlzc2lvbnMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiAyMyxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3Qgc3RhdHVzUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VTdGF0dXM+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpXHJcbiAgICAgICk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDIzLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdTVUJPV04nLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHVzZXJTZXJ2aWNlID0gdGVzdGluZ01vZHVsZS5nZXQ8VXNlclNlcnZpY2U+KFVzZXJTZXJ2aWNlKTtcclxuICAgICAgKHVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKFtcclxuICAgICAgICAnY29ycmVzcG9uZGVuY2UuY2FuY2VsJyxcclxuICAgICAgXSk7XHJcblxyXG4gICAgICBqZXN0LnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHVibGljSWQ6ICdjb3JyLXV1aWQtMScsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdDT1JSLTAwMScsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKSxcclxuICAgICAgICByZXZpc2lvbnM6IFtdLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgYXdhaXQgZXhwZWN0KFxyXG4gICAgICAgIHNlcnZpY2UudXBkYXRlKDEsIHsgc3ViamVjdDogJ1VwZGF0ZWQgU3ViamVjdCcgfSwgbW9ja1VzZXIpXHJcbiAgICAgICkucmVzb2x2ZXMudG9CZURlZmluZWQoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgcmVqZWN0IG5vbi1kcmFmdCB1cGRhdGUgZm9yIG5vbi1hZG1pbiBwZXJtaXNzaW9ucycsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7XHJcbiAgICAgICAgdXNlcl9pZDogMixcclxuICAgICAgICBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMixcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDIzLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMjMsXHJcbiAgICAgICAgc3RhdHVzQ29kZTogJ1NVQk9XTicsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgY29uc3QgdXNlclNlcnZpY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxVc2VyU2VydmljZT4oVXNlclNlcnZpY2UpO1xyXG4gICAgICAodXNlclNlcnZpY2UuZ2V0VXNlclBlcm1pc3Npb25zIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoW1xyXG4gICAgICAgICdjb3JyZXNwb25kZW5jZS5lZGl0JyxcclxuICAgICAgXSk7XHJcblxyXG4gICAgICBhd2FpdCBleHBlY3QoXHJcbiAgICAgICAgc2VydmljZS51cGRhdGUoMiwgeyBzdWJqZWN0OiAnU2hvdWxkIEZhaWwnIH0sIG1vY2tVc2VyKVxyXG4gICAgICApLnJlamVjdHMudG9UaHJvdyhGb3JiaWRkZW5FeGNlcHRpb24pO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCBOT1QgcmVnZW5lcmF0ZSBudW1iZXIgaWYgY3JpdGljYWwgZmllbGRzIHVuY2hhbmdlZCcsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7IGlkOiAxLCBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAxLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogNSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3QgbW9ja0NvcnIgPSB7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiAyLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6IDEwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiAnT0xELU5VTScsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgcmVjaXBpZW50VHlwZTogJ1RPJywgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IDk5IH1dLFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrQ29yciBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUR0bzogVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UudXBkYXRlKDEsIHVwZGF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KFxyXG4gICAgICAgIG51bWJlcmluZ1NlcnZpY2UudXBkYXRlTnVtYmVyRm9yRHJhZnQgYXMgamVzdC5Nb2NrXHJcbiAgICAgICkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgcmVnZW5lcmF0ZSBudW1iZXIgaWYgUHJvamVjdCBJRCBjaGFuZ2VzJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IG1vY2tDb3JyID0ge1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZVR5cGVJZDogMixcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAxMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogJ09MRC1OVU0nLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHJlY2lwaWVudFR5cGU6ICdUTycsIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiA5OSB9XSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihjb3JyZXNwb25kZW5jZVJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja0NvcnIgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogMixcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHV1aWRSZXNvbHZlciA9XHJcbiAgICAgICAgdGVzdGluZ01vZHVsZS5nZXQ8VXVpZFJlc29sdmVyU2VydmljZT4oVXVpZFJlc29sdmVyU2VydmljZSk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDIpO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS50b0hhdmVCZWVuQ2FsbGVkKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHJlZ2VuZXJhdGUgbnVtYmVyIGlmIERvY3VtZW50IFR5cGUgY2hhbmdlcycsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7IGlkOiAxLCBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAxLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogNSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICB0eXBlSWQ6IDk5OSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogOTk5LFxyXG4gICAgICAgIHR5cGVDb2RlOiAnTkVXLVRZUEUnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UudXBkYXRlKDEsIHVwZGF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KFxyXG4gICAgICAgIG51bWJlcmluZ1NlcnZpY2UudXBkYXRlTnVtYmVyRm9yRHJhZnQgYXMgamVzdC5Nb2NrXHJcbiAgICAgICkudG9IYXZlQmVlbkNhbGxlZCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCByZWdlbmVyYXRlIG51bWJlciBpZiBSZWNpcGllbnQgT3JnYW5pemF0aW9uIGNoYW5nZXMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0geyBpZDogMSwgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMSxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDUsXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3QgbW9ja0NvcnIgPSB7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiAyLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6IDEwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiAnT0xELU5VTScsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgcmVjaXBpZW50VHlwZTogJ1RPJywgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IDk5IH1dLFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrQ29yciBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIC8vIEFjY2VzcyBEYXRhU291cmNlIG1hbmFnZXIgZm9yIG1vY2tpbmdcclxuICAgICAgbW9ja0RhdGFTb3VyY2UubWFuYWdlci5maW5kT25lLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogODgsXHJcbiAgICAgICAgb3JnYW5pemF0aW9uQ29kZTogJ05FVy1PUkcnLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgT3JnYW5pemF0aW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUR0bzogVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgdHlwZTogJ1RPJywgb3JnYW5pemF0aW9uSWQ6IDg4IH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS50b0hhdmVCZWVuQ2FsbGVkKCk7XHJcbiAgICB9KTtcclxuICB9KTtcclxuXHJcbiAgZGVzY3JpYmUoJ2NyZWF0ZScsICgpID0+IHtcclxuICAgIGl0KCdzaG91bGQgYWxsb3cgc3lzdGVtLm1hbmFnZV9hbGwgdXNlciB3aXRob3V0IHByaW1hcnlPcmdhbml6YXRpb25JZCB3aGVuIG9yaWdpbmF0b3JJZCBpcyBwcm92aWRlZCcsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7XHJcbiAgICAgICAgdXNlcl9pZDogMSxcclxuICAgICAgICBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IG51bGwsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG5cclxuICAgICAgY29uc3QgY3JlYXRlRHRvOiBDcmVhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6ICdwcm9qZWN0LXV1aWQnLFxyXG4gICAgICAgIHR5cGVJZDogMSxcclxuICAgICAgICBzdWJqZWN0OiAnVGVzdCBTdWJqZWN0JyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6ICdvcmlnaW5hdG9yLXV1aWQnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdXNlclNlcnZpY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxVc2VyU2VydmljZT4oVXNlclNlcnZpY2UpO1xyXG4gICAgICBjb25zdCB0eXBlUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VUeXBlPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlVHlwZSlcclxuICAgICAgKTtcclxuICAgICAgY29uc3Qgc3RhdHVzUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VTdGF0dXM+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHV1aWRSZXNvbHZlciA9XHJcbiAgICAgICAgdGVzdGluZ01vZHVsZS5nZXQ8VXVpZFJlc29sdmVyU2VydmljZT4oVXVpZFJlc29sdmVyU2VydmljZSk7XHJcblxyXG4gICAgICAodXNlclNlcnZpY2UuZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogbnVsbCxcclxuICAgICAgfSk7XHJcbiAgICAgICh1c2VyU2VydmljZS5nZXRVc2VyUGVybWlzc2lvbnMgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXHJcbiAgICAgICAgJ3N5c3RlbS5tYW5hZ2VfYWxsJyxcclxuICAgICAgXSk7XHJcblxyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgxMDApO1xyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZCBhcyBqZXN0Lk1vY2spLm1vY2tJbXBsZW1lbnRhdGlvbihcclxuICAgICAgICAodmFsdWU6IG51bWJlciB8IHN0cmluZykgPT4ge1xyXG4gICAgICAgICAgaWYgKHZhbHVlID09PSAnb3JpZ2luYXRvci11dWlkJykgcmV0dXJuIDEwO1xyXG4gICAgICAgICAgaWYgKHZhbHVlID09PSAncmVjaXBpZW50LXV1aWQnKSByZXR1cm4gMjA7XHJcbiAgICAgICAgICByZXR1cm4gMDtcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ0xUUicsXHJcbiAgICAgIH0pO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdEUkFGVCcsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgKG51bWJlcmluZ1NlcnZpY2UuZ2VuZXJhdGVOZXh0TnVtYmVyIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIG51bWJlcjogJ0RPQy0wMDEnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAsIG9yZ2FuaXphdGlvbkNvZGU6ICdPUkcnIH0pXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAyMCwgb3JnYW5pemF0aW9uQ29kZTogJ1JFQycgfSk7XHJcblxyXG4gICAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHtcclxuICAgICAgICBjb25uZWN0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcm9sbGJhY2tUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgICBjcmVhdGU6IGplc3QuZm4oXHJcbiAgICAgICAgICAgIChfZW50aXR5OiB1bmtub3duLCBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gcGF5bG9hZFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIHNhdmU6IGplc3RcclxuICAgICAgICAgICAgLmZuKClcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiA5OTksIHB1YmxpY0lkOiAnY29yci11dWlkJyB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwMDAgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZShbXSksXHJcbiAgICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgICAgfSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIChtb2NrRGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lciBhcyBqZXN0Lk1vY2spLm1vY2tSZXR1cm5WYWx1ZShcclxuICAgICAgICBxdWVyeVJ1bm5lclxyXG4gICAgICApO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS5jcmVhdGUoY3JlYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QocXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlLFxyXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgb3JpZ2luYXRvcklkOiAxMCB9KVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCBzZXQgcmV2aXNpb25MYWJlbCB0byBcIkFcIiBmb3IgUkZBIHR5cGUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IG9yZ2FuaXphdGlvbklkOiAncmVjaXBpZW50LXV1aWQnLCB0eXBlOiAnVE8nIH1dLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyMCk7XHJcblxyXG4gICAgICAodHlwZVJlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICB0eXBlQ29kZTogJ1JGQScsXHJcbiAgICAgIH0pO1xyXG4gICAgICAoc3RhdHVzUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICdEUkFGVCcsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgKG51bWJlcmluZ1NlcnZpY2UuZ2VuZXJhdGVOZXh0TnVtYmVyIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIG51bWJlcjogJ0RPQy0wMDEnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAsIG9yZ2FuaXphdGlvbkNvZGU6ICdPUkcnIH0pXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAyMCwgb3JnYW5pemF0aW9uQ29kZTogJ1JFQycgfSk7XHJcblxyXG4gICAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHtcclxuICAgICAgICBjb25uZWN0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcm9sbGJhY2tUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgICBjcmVhdGU6IGplc3QuZm4oXHJcbiAgICAgICAgICAgIChfZW50aXR5OiB1bmtub3duLCBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gcGF5bG9hZFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIHNhdmU6IGplc3RcclxuICAgICAgICAgICAgLmZuKClcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiA5OTksIHB1YmxpY0lkOiAnY29yci11dWlkJyB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwMDAgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZShbXSksXHJcbiAgICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgICAgfSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIChtb2NrRGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lciBhcyBqZXN0Lk1vY2spLm1vY2tSZXR1cm5WYWx1ZShcclxuICAgICAgICBxdWVyeVJ1bm5lclxyXG4gICAgICApO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS5jcmVhdGUoY3JlYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QocXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmV2aXNpb24sXHJcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyByZXZpc2lvbkxhYmVsOiAnQScgfSlcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgc2V0IHJldmlzaW9uTGFiZWwgdG8gXCJBXCIgZm9yIFJGSSB0eXBlJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG5cclxuICAgICAgY29uc3QgY3JlYXRlRHRvOiBDcmVhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6ICdwcm9qZWN0LXV1aWQnLFxyXG4gICAgICAgIHR5cGVJZDogMSxcclxuICAgICAgICBzdWJqZWN0OiAnVGVzdCBTdWJqZWN0JyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyBvcmdhbml6YXRpb25JZDogJ3JlY2lwaWVudC11dWlkJywgdHlwZTogJ1RPJyB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuXHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDEwMCk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMjApO1xyXG5cclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgdHlwZUNvZGU6ICdSRkknLFxyXG4gICAgICB9KTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnRFJBRlQnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIChudW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlciBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBudW1iZXI6ICdET0MtMDAxJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmVcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwLCBvcmdhbml6YXRpb25Db2RlOiAnT1JHJyB9KVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMjAsIG9yZ2FuaXphdGlvbkNvZGU6ICdSRUMnIH0pO1xyXG5cclxuICAgICAgY29uc3QgcXVlcnlSdW5uZXIgPSB7XHJcbiAgICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICAgIHN0YXJ0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByZWxlYXNlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgICAgY3JlYXRlOiBqZXN0LmZuKFxyXG4gICAgICAgICAgICAoX2VudGl0eTogdW5rbm93biwgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHBheWxvYWRcclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBzYXZlOiBqZXN0XHJcbiAgICAgICAgICAgIC5mbigpXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogOTk5LCBwdWJsaWNJZDogJ2NvcnItdXVpZCcgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMDAwIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoW10pLFxyXG4gICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICAobW9ja0RhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmV0dXJuVmFsdWUoXHJcbiAgICAgICAgcXVlcnlSdW5uZXJcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UuY3JlYXRlKGNyZWF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcclxuICAgICAgICBDb3JyZXNwb25kZW5jZVJldmlzaW9uLFxyXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgcmV2aXNpb25MYWJlbDogJ0EnIH0pXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHNldCByZXZpc2lvbkxhYmVsIHRvIG51bGwgZm9yIExFVFRFUiB0eXBlJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG5cclxuICAgICAgY29uc3QgY3JlYXRlRHRvOiBDcmVhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6ICdwcm9qZWN0LXV1aWQnLFxyXG4gICAgICAgIHR5cGVJZDogMSxcclxuICAgICAgICBzdWJqZWN0OiAnVGVzdCBTdWJqZWN0JyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyBvcmdhbml6YXRpb25JZDogJ3JlY2lwaWVudC11dWlkJywgdHlwZTogJ1RPJyB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuXHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDEwMCk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMjApO1xyXG5cclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgdHlwZUNvZGU6ICdMRVRURVInLFxyXG4gICAgICB9KTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnRFJBRlQnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIChudW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlciBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBudW1iZXI6ICdET0MtMDAxJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmVcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwLCBvcmdhbml6YXRpb25Db2RlOiAnT1JHJyB9KVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMjAsIG9yZ2FuaXphdGlvbkNvZGU6ICdSRUMnIH0pO1xyXG5cclxuICAgICAgY29uc3QgcXVlcnlSdW5uZXIgPSB7XHJcbiAgICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICAgIHN0YXJ0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByZWxlYXNlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgICAgY3JlYXRlOiBqZXN0LmZuKFxyXG4gICAgICAgICAgICAoX2VudGl0eTogdW5rbm93biwgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHBheWxvYWRcclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBzYXZlOiBqZXN0XHJcbiAgICAgICAgICAgIC5mbigpXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogOTk5LCBwdWJsaWNJZDogJ2NvcnItdXVpZCcgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMDAwIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoW10pLFxyXG4gICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICAobW9ja0RhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmV0dXJuVmFsdWUoXHJcbiAgICAgICAgcXVlcnlSdW5uZXJcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UuY3JlYXRlKGNyZWF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcclxuICAgICAgICBDb3JyZXNwb25kZW5jZVJldmlzaW9uLFxyXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgcmV2aXNpb25MYWJlbDogdW5kZWZpbmVkIH0pXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHNldCByZXZpc2lvbkxhYmVsIHRvIHVuZGVmaW5lZCBmb3IgTUVNTyB0eXBlJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG5cclxuICAgICAgY29uc3QgY3JlYXRlRHRvOiBDcmVhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6ICdwcm9qZWN0LXV1aWQnLFxyXG4gICAgICAgIHR5cGVJZDogMSxcclxuICAgICAgICBzdWJqZWN0OiAnVGVzdCBTdWJqZWN0JyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyBvcmdhbml6YXRpb25JZDogJ3JlY2lwaWVudC11dWlkJywgdHlwZTogJ1RPJyB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuXHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDEwMCk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMjApO1xyXG5cclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgdHlwZUNvZGU6ICdNRU1PJyxcclxuICAgICAgfSk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgc3RhdHVzQ29kZTogJ0RSQUZUJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAobnVtYmVyaW5nU2VydmljZS5nZW5lcmF0ZU5leHROdW1iZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgbnVtYmVyOiAnRE9DLTAwMScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgbW9ja0RhdGFTb3VyY2UubWFuYWdlci5maW5kT25lXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMCwgb3JnYW5pemF0aW9uQ29kZTogJ09SRycgfSlcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDIwLCBvcmdhbml6YXRpb25Db2RlOiAnUkVDJyB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHF1ZXJ5UnVubmVyID0ge1xyXG4gICAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgICBzdGFydFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgY29tbWl0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcmVsZWFzZTogamVzdC5mbigpLFxyXG4gICAgICAgIG1hbmFnZXI6IHtcclxuICAgICAgICAgIGNyZWF0ZTogamVzdC5mbihcclxuICAgICAgICAgICAgKF9lbnRpdHk6IHVua25vd24sIHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBwYXlsb2FkXHJcbiAgICAgICAgICApLFxyXG4gICAgICAgICAgc2F2ZTogamVzdFxyXG4gICAgICAgICAgICAuZm4oKVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDk5OSwgcHVibGljSWQ6ICdjb3JyLXV1aWQnIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAwMCB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKFtdKSxcclxuICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICB9LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgKG1vY2tEYXRhU291cmNlLmNyZWF0ZVF1ZXJ5UnVubmVyIGFzIGplc3QuTW9jaykubW9ja1JldHVyblZhbHVlKFxyXG4gICAgICAgIHF1ZXJ5UnVubmVyXHJcbiAgICAgICk7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLmNyZWF0ZShjcmVhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbixcclxuICAgICAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7IHJldmlzaW9uTGFiZWw6IHVuZGVmaW5lZCB9KVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgfSk7XHJcbn0pO1xyXG4iXSwidmVyc2lvbiI6M30= \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/82/correspondenceservicespec_82e6df7890187e79e1a13a269c1041ae.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/82/correspondenceservicespec_82e6df7890187e79e1a13a269c1041ae.map new file mode 100644 index 0000000..25463aa --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/82/correspondenceservicespec_82e6df7890187e79e1a13a269c1041ae.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts"],"sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\r\nimport { getRepositoryToken } from '@nestjs/typeorm';\r\nimport { DataSource, Repository } from 'typeorm';\r\nimport { ForbiddenException } from '@nestjs/common';\r\nimport { CorrespondenceService } from './correspondence.service';\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { User } from '../user/entities/user.entity';\r\n\r\ndescribe('CorrespondenceService', () => {\r\n let service: CorrespondenceService;\r\n let numberingService: DocumentNumberingService;\r\n let correspondenceRepo: Repository;\r\n let revisionRepo: Repository;\r\n let testingModule: TestingModule;\r\n let _dataSource: DataSource;\r\n\r\n const createMockRepository = () => ({\r\n find: jest.fn(),\r\n findOne: jest.fn(),\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n update: jest.fn(),\r\n delete: jest.fn(),\r\n softDelete: jest.fn(),\r\n createQueryBuilder: jest.fn(() => ({\r\n leftJoinAndSelect: jest.fn().mockReturnThis(),\r\n where: jest.fn().mockReturnThis(),\r\n andWhere: jest.fn().mockReturnThis(),\r\n orderBy: jest.fn().mockReturnThis(),\r\n skip: jest.fn().mockReturnThis(),\r\n take: jest.fn().mockReturnThis(),\r\n getOne: jest.fn().mockResolvedValue(null),\r\n getMany: jest.fn().mockResolvedValue([]),\r\n getManyAndCount: jest.fn().mockResolvedValue([[], 0]),\r\n })),\r\n });\r\n\r\n const mockDataSource = {\r\n createQueryRunner: jest.fn(() => ({\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n findOne: jest.fn(),\r\n },\r\n })),\r\n getRepository: jest.fn(() => createMockRepository()),\r\n manager: {\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n beforeEach(async () => {\r\n testingModule = await Test.createTestingModule({\r\n providers: [\r\n CorrespondenceService,\r\n {\r\n provide: getRepositoryToken(Correspondence),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRevision),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceType),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceStatus),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceReference),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceTag),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(Organization),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRecipient),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: DocumentNumberingService,\r\n useValue: {\r\n generateNextNumber: jest.fn(),\r\n updateNumberForDraft: jest.fn(),\r\n previewNextNumber: jest.fn(),\r\n },\r\n },\r\n {\r\n provide: JsonSchemaService,\r\n useValue: { validate: jest.fn() },\r\n },\r\n {\r\n provide: WorkflowEngineService,\r\n useValue: { createInstance: jest.fn() },\r\n },\r\n {\r\n provide: UserService,\r\n useValue: {\r\n findOne: jest.fn(),\r\n getUserPermissions: jest.fn().mockResolvedValue([]),\r\n },\r\n },\r\n {\r\n provide: DataSource,\r\n useValue: mockDataSource,\r\n },\r\n {\r\n provide: SearchService,\r\n useValue: { indexDocument: jest.fn() },\r\n },\r\n {\r\n provide: FileStorageService,\r\n useValue: { commit: jest.fn().mockResolvedValue([]) },\r\n },\r\n {\r\n provide: UuidResolverService,\r\n useValue: {\r\n resolveProjectId: jest.fn().mockResolvedValue(1),\r\n resolveOrganizationId: jest.fn().mockResolvedValue(1),\r\n },\r\n },\r\n {\r\n provide: NotificationService,\r\n useValue: { send: jest.fn().mockResolvedValue(undefined) },\r\n },\r\n ],\r\n }).compile();\r\n\r\n service = testingModule.get(CorrespondenceService);\r\n numberingService = testingModule.get(\r\n DocumentNumberingService\r\n );\r\n correspondenceRepo = testingModule.get>(\r\n getRepositoryToken(Correspondence)\r\n );\r\n revisionRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceRevision)\r\n );\r\n _dataSource = testingModule.get(DataSource);\r\n });\r\n\r\n it('should be defined', () => {\r\n expect(service).toBeDefined();\r\n });\r\n\r\n describe('update', () => {\r\n it('should allow non-draft update for org-admin+ permissions', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 23,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 23,\r\n statusCode: 'SUBOWN',\r\n });\r\n\r\n const userService = testingModule.get(UserService);\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'correspondence.cancel',\r\n ]);\r\n\r\n jest.spyOn(correspondenceRepo, 'findOne').mockResolvedValue({\r\n id: 1,\r\n publicId: 'corr-uuid-1',\r\n correspondenceNumber: 'CORR-001',\r\n projectId: 1,\r\n createdAt: new Date(),\r\n revisions: [],\r\n } as unknown as Correspondence);\r\n\r\n await expect(\r\n service.update(1, { subject: 'Updated Subject' }, mockUser)\r\n ).resolves.toBeDefined();\r\n });\r\n\r\n it('should reject non-draft update for non-admin permissions', async () => {\r\n const mockUser = {\r\n user_id: 2,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n const mockRevision = {\r\n id: 101,\r\n correspondenceId: 2,\r\n isCurrent: true,\r\n statusId: 23,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 23,\r\n statusCode: 'SUBOWN',\r\n });\r\n\r\n const userService = testingModule.get(UserService);\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'correspondence.edit',\r\n ]);\r\n\r\n await expect(\r\n service.update(2, { subject: 'Should Fail' }, mockUser)\r\n ).rejects.toThrow(ForbiddenException);\r\n });\r\n\r\n it('should NOT regenerate number if critical fields unchanged', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 1,\r\n disciplineId: 3,\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).not.toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Project ID changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 2,\r\n };\r\n\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(2);\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Document Type changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n typeId: 999,\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 999,\r\n typeCode: 'NEW-TYPE',\r\n });\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Recipient Organization changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n // Access DataSource manager for mocking\r\n mockDataSource.manager.findOne.mockResolvedValue({\r\n id: 88,\r\n organizationCode: 'NEW-ORG',\r\n } as unknown as Organization);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n recipients: [{ type: 'TO', organizationId: 88 }],\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n });\r\n\r\n describe('create', () => {\r\n it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n originatorId: 'originator-uuid',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const userService = testingModule.get(UserService);\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (userService.findOne as jest.Mock).mockResolvedValue({\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n });\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'system.manage_all',\r\n ]);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockImplementation(\r\n (value: number | string) => {\r\n if (value === 'originator-uuid') return 10;\r\n if (value === 'recipient-uuid') return 20;\r\n return 0;\r\n }\r\n );\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LTR',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n Correspondence,\r\n expect.objectContaining({ originatorId: 10 })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to \"A\" for RFA type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'RFA',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: 'A' })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to \"A\" for RFI type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'RFI',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: 'A' })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to null for LETTER type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LETTER',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: undefined })\r\n );\r\n });\r\n\r\n it('should set revisionLabel to undefined for MEMO type', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: 10,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockResolvedValue(20);\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'MEMO',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n CorrespondenceRevision,\r\n expect.objectContaining({ revisionLabel: undefined })\r\n );\r\n });\r\n });\r\n});\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/e4/correspondenceservice_e4765c13e5e659b2418e3700423a4d1e b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/e4/correspondenceservice_e4765c13e5e659b2418e3700423a4d1e new file mode 100644 index 0000000..99adf3a --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/e4/correspondenceservice_e4765c13e5e659b2418e3700423a4d1e @@ -0,0 +1,898 @@ +d7f107a395b1164986917664600a90ce +"use strict"; +// File: src/modules/correspondence/correspondence.service.ts +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var CorrespondenceService_1; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CorrespondenceService = void 0; +const common_1 = require("@nestjs/common"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +// Entities +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const tag_entity_1 = require("../master/entities/tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +// Services +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +let CorrespondenceService = CorrespondenceService_1 = class CorrespondenceService { + async hasSystemManageAllPermission(userId) { + const permissions = await this.userService.getUserPermissions(userId); + return permissions.includes('system.manage_all'); + } + /** + * Business Rule: Revision Label Strategy + * - RFA, RFI: Use alphabet starting with 'A' (A, B, C...) + * - Other types (LETTER, MEMO, etc.): Use numeric (null for first, then 1, 2, 3...) + */ + getInitialRevisionLabel(typeCode) { + const alphabetTypes = ['RFA', 'RFI']; + if (alphabetTypes.includes(typeCode.toUpperCase())) { + return 'A'; // Alphabet for RFA, RFI + } + return undefined; // Numeric (no label for revision 0) + } + constructor(correspondenceRepo, revisionRepo, typeRepo, statusRepo, referenceRepo, tagRepo, numberingService, jsonSchemaService, workflowEngine, userService, dataSource, searchService, fileStorageService, uuidResolver, notificationService) { + this.correspondenceRepo = correspondenceRepo; + this.revisionRepo = revisionRepo; + this.typeRepo = typeRepo; + this.statusRepo = statusRepo; + this.referenceRepo = referenceRepo; + this.tagRepo = tagRepo; + this.numberingService = numberingService; + this.jsonSchemaService = jsonSchemaService; + this.workflowEngine = workflowEngine; + this.userService = userService; + this.dataSource = dataSource; + this.searchService = searchService; + this.fileStorageService = fileStorageService; + this.uuidResolver = uuidResolver; + this.notificationService = notificationService; + this.logger = new common_1.Logger(CorrespondenceService_1.name); + } + /** + * Business Rule Validation: EC-CORR-003 - Correspondence to Self + * Prevent external correspondence to same organization + */ + async validateCorrespondenceRecipients(createDto, user) { + // Get user's organization + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + if (!userOrgId) { + if (createDto.originatorId) { + const canManageAll = await this.hasSystemManageAllPermission(user.user_id); + if (canManageAll) { + userOrgId = await this.uuidResolver.resolveOrganizationId(createDto.originatorId); + } + } + if (!userOrgId) { + throw new common_1.BadRequestException('User must belong to an organization to create documents'); + } + } + // For impersonation, use the specified originator + const originatorOrgId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : userOrgId; + // Check if it's internal communication + if (createDto.isInternal) { + // Internal communications should use Circulation instead + throw new common_1.BadRequestException('Internal communications should use Circulation Sheet instead of Correspondence'); + } + // Validate recipients + if (!createDto.recipients || createDto.recipients.length === 0) { + throw new common_1.BadRequestException('At least one recipient (TO or CC) is required'); + } + const toRecipients = createDto.recipients.filter((r) => r.type === 'TO'); + const ccRecipients = createDto.recipients.filter((r) => r.type === 'CC'); + if (toRecipients.length === 0 && ccRecipients.length === 0) { + throw new common_1.BadRequestException('At least one TO or CC recipient is required'); + } + // Check for same organization correspondence + for (const recipient of createDto.recipients) { + const recipientOrgId = await this.uuidResolver.resolveOrganizationId(recipient.organizationId); + if (recipientOrgId === originatorOrgId) { + throw new common_1.BadRequestException('Cannot send correspondence to your own organization. Use Circulation Sheet for internal communication.'); + } + } + } + async create(createDto, user) { + // Business Rule Validation: EC-CORR-003 - Correspondence to Self + await this.validateCorrespondenceRecipients(createDto, user); + // ADR-019: Resolve UUID references to internal INT IDs + const resolvedProjectId = await this.uuidResolver.resolveProjectId(createDto.projectId); + const resolvedOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + const resolvedRecipients = createDto.recipients + ? await Promise.all(createDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + const type = await this.typeRepo.findOne({ + where: { id: createDto.typeId }, + }); + if (!type) + throw new common_1.NotFoundException('Document Type not found'); + const statusDraft = await this.statusRepo.findOne({ + where: { statusCode: 'DRAFT' }, + }); + if (!statusDraft) { + throw new common_1.InternalServerErrorException('Status DRAFT not found in Master Data'); + } + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + // Impersonation Logic + if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) { + const canManageAll = await this.hasSystemManageAllPermission(user.user_id); + if (!canManageAll) { + throw new common_1.ForbiddenException('You do not have permission to create documents on behalf of other organizations.'); + } + userOrgId = resolvedOriginatorId; + } + if (!userOrgId) { + throw new common_1.BadRequestException('User must belong to an organization to create documents'); + } + if (createDto.details) { + try { + await this.jsonSchemaService.validate(type.typeCode, createDto.details); + } + catch (error) { + this.logger.warn(`Schema validation warning for ${type.typeCode}: ${error.message}`); + } + } + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + try { + // [Fix #6] Fetch real ORG Code from Organization entity + const originatorOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: userOrgId }, + }); + const orgCode = originatorOrg?.organizationCode ?? 'UNK'; + // [v1.5.1] Extract recipient organization from recipients array (Primary TO) + const toRecipient = resolvedRecipients?.find((r) => r.type === 'TO'); + const recipientOrganizationId = toRecipient?.organizationId; + let recipientCode = ''; + if (recipientOrganizationId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: recipientOrganizationId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + const docNumber = await this.numberingService.generateNextNumber({ + projectId: resolvedProjectId, + originatorOrganizationId: userOrgId, + typeId: createDto.typeId, + disciplineId: createDto.disciplineId, + subTypeId: createDto.subTypeId, + recipientOrganizationId, // [v1.5.1] Pass recipient for document number format + year: new Date().getFullYear(), + customTokens: { + TYPE_CODE: type.typeCode, + ORG_CODE: orgCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }); + const correspondence = queryRunner.manager.create(correspondence_entity_1.Correspondence, { + correspondenceNumber: docNumber.number, + correspondenceTypeId: createDto.typeId, + disciplineId: createDto.disciplineId, + projectId: resolvedProjectId, + originatorId: userOrgId, + isInternal: createDto.isInternal || false, + createdBy: user.user_id, + }); + const savedCorr = await queryRunner.manager.save(correspondence); + const revision = queryRunner.manager.create(correspondence_revision_entity_1.CorrespondenceRevision, { + correspondenceId: savedCorr.id, + revisionNumber: 0, + revisionLabel: this.getInitialRevisionLabel(type.typeCode), + isCurrent: true, + statusId: statusDraft.id, + subject: createDto.subject, + body: createDto.body, + remarks: createDto.remarks, + dueDate: createDto.dueDate ? new Date(createDto.dueDate) : undefined, + documentDate: createDto.documentDate + ? new Date(createDto.documentDate) + : undefined, + issuedDate: createDto.issuedDate + ? new Date(createDto.issuedDate) + : undefined, + receivedDate: createDto.receivedDate + ? new Date(createDto.receivedDate) + : undefined, + description: createDto.description, + details: createDto.details, + createdBy: user.user_id, + schemaVersion: 1, + }); + await queryRunner.manager.save(revision); + // Save Recipients (using resolved INT IDs) + if (resolvedRecipients && resolvedRecipients.length > 0) { + const recipients = resolvedRecipients.map((r) => queryRunner.manager.create(correspondence_recipient_entity_1.CorrespondenceRecipient, { + correspondenceId: savedCorr.id, + recipientOrganizationId: r.organizationId, + recipientType: r.type, + })); + await queryRunner.manager.save(recipients); + } + // Commit attachments from Temp → Permanent (Two-Phase Storage) + if (createDto.attachmentTempIds?.length) { + const issueDate = createDto.issuedDate + ? new Date(createDto.issuedDate) + : createDto.documentDate + ? new Date(createDto.documentDate) + : undefined; + await this.fileStorageService.commit(createDto.attachmentTempIds, { + issueDate, + documentType: 'Correspondence', + }); + } + await queryRunner.commitTransaction(); + // Start Workflow Instance (non-blocking) + try { + const workflowCode = `CORRESPONDENCE_${type.typeCode}`; + await this.workflowEngine.createInstance(workflowCode, 'correspondence', savedCorr.id.toString(), { + projectId: resolvedProjectId, + originatorId: userOrgId, + disciplineId: createDto.disciplineId, + initiatorId: user.user_id, + }); + } + catch (error) { + this.logger.warn(`Workflow not started for ${docNumber.number} (Code: CORRESPONDENCE_${type.typeCode}): ${error.message}`); + } + // Fire-and-forget search indexing (non-blocking, void intentional) + void this.searchService.indexDocument({ + id: savedCorr.id, + publicId: savedCorr.publicId, + type: 'correspondence', + docNumber: docNumber.number, + title: createDto.subject, + description: createDto.description, + status: 'DRAFT', + projectId: resolvedProjectId, + createdAt: new Date(), + }); + return { + ...savedCorr, + currentRevision: revision, + }; + } + catch (err) { + await queryRunner.rollbackTransaction(); + this.logger.error(`Failed to create correspondence: ${err.message}`); + throw err; + } + finally { + await queryRunner.release(); + } + } + async findAll(searchDto = {}) { + const { search, typeId, projectId, statusId, status, page = 1, limit = 10, } = searchDto; + const skip = (page - 1) * limit; + // Change: Query from Revision Repo + const query = this.revisionRepo + .createQueryBuilder('rev') + .leftJoinAndSelect('rev.correspondence', 'corr') + .leftJoinAndSelect('corr.type', 'type') + .leftJoinAndSelect('corr.project', 'project') + .leftJoinAndSelect('corr.originator', 'org') + .leftJoinAndSelect('rev.status', 'status'); + // Filter by Revision Status + const revStatus = searchDto.revisionStatus || 'CURRENT'; + if (revStatus === 'CURRENT') { + query.where('rev.isCurrent = :isCurrent', { isCurrent: true }); + } + else if (revStatus === 'OLD') { + query.where('rev.isCurrent = :isCurrent', { isCurrent: false }); + } + // If 'ALL', no filter needed on isCurrent + if (projectId) { + query.andWhere('corr.projectId = :projectId', { projectId }); + } + if (typeId) { + query.andWhere('corr.correspondenceTypeId = :typeId', { typeId }); + } + if (statusId) { + query.andWhere('rev.statusId = :statusId', { statusId }); + } + if (status) { + query.andWhere('status.statusCode = :status', { status }); + } + if (search) { + query.andWhere('(corr.correspondenceNumber LIKE :search OR rev.subject LIKE :search)', { search: `%${search}%` }); + } + // Default Sort: Latest Created + query.orderBy('rev.createdAt', 'DESC').skip(skip).take(limit); + const [items, total] = await query.getManyAndCount(); + return { + data: items, + meta: { + total, + page, + limit, + totalPages: Math.ceil(total / limit), + }, + }; + } + async findOne(id) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { id }, + relations: [ + 'revisions', + 'revisions.status', + 'type', + 'project', + 'originator', + 'recipients', + 'recipients.recipientOrganization', // [v1.5.1] Fixed relation name + ], + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence with ID ${id} not found`); + } + return correspondence; + } + async findOneByUuid(publicId) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { publicId }, + relations: [ + 'revisions', + 'revisions.status', + 'type', + 'project', + 'originator', + 'recipients', + 'recipients.recipientOrganization', + ], + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence with UUID ${publicId} not found`); + } + return correspondence; + } + async addReference(id, dto) { + const source = await this.correspondenceRepo.findOne({ where: { id } }); + // ADR-019: Resolve target publicId → internal INT id + const target = await this.correspondenceRepo.findOne({ + where: { publicId: dto.targetUuid }, + }); + if (!source || !target) { + throw new common_1.NotFoundException('Source or Target correspondence not found'); + } + if (source.id === target.id) { + throw new common_1.BadRequestException('Cannot reference self'); + } + const exists = await this.referenceRepo.findOne({ + where: { + sourceId: id, + targetId: target.id, + }, + }); + if (exists) { + return exists; + } + const ref = this.referenceRepo.create({ + sourceId: id, + targetId: target.id, + }); + return this.referenceRepo.save(ref); + } + async removeReference(id, targetId) { + const result = await this.referenceRepo.delete({ + sourceId: id, + targetId: targetId, + }); + if (result.affected === 0) { + throw new common_1.NotFoundException('Reference not found'); + } + } + async getTags(id) { + const rows = await this.tagRepo.find({ + where: { correspondenceId: id }, + relations: ['tag'], + }); + return rows.map((r) => r.tag).filter(Boolean); + } + async addTag(id, tagId) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { id }, + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence ${id} not found`); + } + const tag = await this.dataSource.manager.findOne(tag_entity_1.Tag, { + where: { id: tagId }, + }); + if (!tag) { + throw new common_1.NotFoundException(`Tag ${tagId} not found`); + } + const exists = await this.tagRepo.findOne({ + where: { correspondenceId: id, tagId }, + }); + if (exists) + return exists; + const row = this.tagRepo.create({ correspondenceId: id, tagId }); + return this.tagRepo.save(row); + } + async removeTag(id, tagId) { + const result = await this.tagRepo.delete({ correspondenceId: id, tagId }); + if (result.affected === 0) { + throw new common_1.NotFoundException('Tag assignment not found'); + } + } + async getReferences(id) { + const outgoing = await this.referenceRepo.find({ + where: { sourceId: id }, + relations: ['target', 'target.type'], + }); + const incoming = await this.referenceRepo.find({ + where: { targetId: id }, + relations: ['source', 'source.type'], + }); + return { outgoing, incoming }; + } + async update(id, updateDto, user) { + // 1. Find Current Revision + const revision = await this.revisionRepo.findOne({ + where: { + correspondenceId: id, + isCurrent: true, + }, + relations: ['correspondence'], + }); + if (!revision) { + throw new common_1.NotFoundException(`Current revision for correspondence ${id} not found`); + } + // 2. Check Permission + if (revision.statusId) { + const status = await this.statusRepo.findOne({ + where: { id: revision.statusId }, + }); + if (status && status.statusCode !== 'DRAFT') { + const permissions = await this.userService.getUserPermissions(user.user_id); + const canEditSubmittedOrLater = permissions.includes('correspondence.cancel') || + permissions.includes('system.manage_all'); + if (!canEditSubmittedOrLater) { + throw new common_1.ForbiddenException('Only Org Admin or Superadmin can edit non-draft correspondences'); + } + } + } + // ADR-019: Resolve UUID references in update DTO + const updResolvedProjectId = updateDto.projectId + ? await this.uuidResolver.resolveProjectId(updateDto.projectId) + : undefined; + const updResolvedOriginatorId = updateDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(updateDto.originatorId) + : undefined; + const updResolvedRecipients = updateDto.recipients + ? await Promise.all(updateDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + // 3. Update Correspondence Entity if needed + const correspondenceUpdate = {}; + if (updateDto.disciplineId) + correspondenceUpdate.disciplineId = updateDto.disciplineId; + if (updResolvedProjectId) + correspondenceUpdate.projectId = updResolvedProjectId; + if (updResolvedOriginatorId) + correspondenceUpdate.originatorId = updResolvedOriginatorId; + if (Object.keys(correspondenceUpdate).length > 0) { + await this.correspondenceRepo.update(id, correspondenceUpdate); + } + // 4. Update Revision Entity + const revisionUpdate = {}; + if (updateDto.subject) + revisionUpdate.subject = updateDto.subject; + if (updateDto.body) + revisionUpdate.body = updateDto.body; + if (updateDto.remarks) + revisionUpdate.remarks = updateDto.remarks; + // Format Date correctly if string + if (updateDto.dueDate) + revisionUpdate.dueDate = new Date(updateDto.dueDate); + if (updateDto.documentDate) + revisionUpdate.documentDate = new Date(updateDto.documentDate); + if (updateDto.issuedDate) + revisionUpdate.issuedDate = new Date(updateDto.issuedDate); + if (updateDto.receivedDate) + revisionUpdate.receivedDate = new Date(updateDto.receivedDate); + if (updateDto.description) + revisionUpdate.description = updateDto.description; + if (updateDto.details) + revisionUpdate.details = updateDto.details; + if (Object.keys(revisionUpdate).length > 0) { + await this.revisionRepo.update(revision.id, revisionUpdate); + } + // 4.5 Commit new attachments from Temp → Permanent (Two-Phase Storage) + if (updateDto.attachmentTempIds?.length) { + const issueDate = updateDto.issuedDate + ? new Date(updateDto.issuedDate) + : updateDto.documentDate + ? new Date(updateDto.documentDate) + : revision.issuedDate || revision.documentDate || undefined; + await this.fileStorageService.commit(updateDto.attachmentTempIds, { + issueDate: issueDate ? new Date(issueDate) : undefined, + documentType: 'Correspondence', + }); + } + // 5. Update Recipients if provided + if (updResolvedRecipients) { + const recipientRepo = this.dataSource.getRepository(correspondence_recipient_entity_1.CorrespondenceRecipient); + await recipientRepo.delete({ correspondenceId: id }); + const newRecipients = updResolvedRecipients.map((r) => recipientRepo.create({ + correspondenceId: id, + recipientOrganizationId: r.organizationId, + recipientType: r.type, + })); + await recipientRepo.save(newRecipients); + } + // 6. Regenerate Document Number if structural fields changed (Recipient, Discipline, Type, Project) + // AND it is a DRAFT. + // Fetch fresh data for context and comparison + const currentCorr = await this.correspondenceRepo.findOne({ + where: { id }, + relations: ['type', 'recipients', 'recipients.recipientOrganization'], + }); + if (currentCorr) { + const currentToRecipient = currentCorr.recipients?.find((r) => r.recipientType === 'TO'); + const currentRecipientId = currentToRecipient?.recipientOrganizationId; + // Check for ACTUAL value changes + const isProjectChanged = updResolvedProjectId !== undefined && + updResolvedProjectId !== currentCorr.projectId; + const isOriginatorChanged = updResolvedOriginatorId !== undefined && + updResolvedOriginatorId !== currentCorr.originatorId; + const isDisciplineChanged = updateDto.disciplineId !== undefined && + updateDto.disciplineId !== currentCorr.disciplineId; + const isTypeChanged = updateDto.typeId !== undefined && + updateDto.typeId !== currentCorr.correspondenceTypeId; + let isRecipientChanged = false; + let newRecipientId; + if (updResolvedRecipients) { + const newToRecipient = updResolvedRecipients.find((r) => r.type === 'TO'); + newRecipientId = newToRecipient?.organizationId; + if (newRecipientId !== currentRecipientId) { + isRecipientChanged = true; + } + } + if (isProjectChanged || + isDisciplineChanged || + isTypeChanged || + isRecipientChanged || + isOriginatorChanged) { + const targetRecipientId = isRecipientChanged + ? newRecipientId + : currentRecipientId; + // Resolve Recipient Code for the NEW context + let recipientCode = ''; + if (targetRecipientId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: targetRecipientId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + // [Fix #6] Fetch real ORG Code from originator organization + const originatorOrgForUpdate = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { + id: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0, + }, + }); + const orgCode = originatorOrgForUpdate?.organizationCode ?? 'UNK'; + // Prepare Contexts + const oldCtx = { + projectId: currentCorr.projectId, + originatorOrganizationId: currentCorr.originatorId ?? 0, + typeId: currentCorr.correspondenceTypeId, + disciplineId: currentCorr.disciplineId, + recipientOrganizationId: currentRecipientId, + year: new Date().getFullYear(), + }; + const newCtx = { + projectId: updResolvedProjectId ?? currentCorr.projectId, + originatorOrganizationId: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0, + typeId: updateDto.typeId ?? currentCorr.correspondenceTypeId, + disciplineId: updateDto.disciplineId ?? currentCorr.disciplineId, + recipientOrganizationId: targetRecipientId, + year: new Date().getFullYear(), + userId: user.user_id, // Pass User ID for Audit + customTokens: { + TYPE_CODE: currentCorr.type?.typeCode || '', + ORG_CODE: orgCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }; + // If Type Changed, need NEW Type Code + if (isTypeChanged) { + const newType = await this.typeRepo.findOne({ + where: { id: newCtx.typeId }, + }); + if (newType) + newCtx.customTokens.TYPE_CODE = newType.typeCode; + } + const newDocNumber = await this.numberingService.updateNumberForDraft(currentCorr.correspondenceNumber, oldCtx, newCtx); + await this.correspondenceRepo.update(id, { + correspondenceNumber: newDocNumber, + }); + } + } + const updated = await this.findOne(id); + // Re-index updated document in Elasticsearch (fire-and-forget) + void this.searchService.indexDocument({ + id: updated.id, + publicId: updated.publicId, + type: 'correspondence', + docNumber: updated.correspondenceNumber, + title: updateDto.subject ?? updated.revisions?.[0]?.subject, + description: updateDto.description ?? updated.revisions?.[0]?.description, + status: 'DRAFT', + projectId: updated.projectId, + createdAt: updated.createdAt, + }); + return updated; + } + async previewDocumentNumber(createDto, user) { + // ADR-019: Resolve UUID references + const previewProjectId = await this.uuidResolver.resolveProjectId(createDto.projectId); + const previewOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + const previewRecipients = createDto.recipients + ? await Promise.all(createDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + const type = await this.typeRepo.findOne({ + where: { id: createDto.typeId }, + }); + if (!type) + throw new common_1.NotFoundException('Document Type not found'); + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) + userOrgId = fullUser.primaryOrganizationId; + } + if (previewOriginatorId && previewOriginatorId !== userOrgId) { + // Allow impersonation for preview + userOrgId = previewOriginatorId; + } + // Extract recipient from recipients array + const toRecipient = previewRecipients?.find((r) => r.type === 'TO'); + const recipientOrganizationId = toRecipient?.organizationId; + let recipientCode = ''; + if (recipientOrganizationId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: recipientOrganizationId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + return this.numberingService.previewNumber({ + projectId: previewProjectId, + originatorOrganizationId: userOrgId, + typeId: createDto.typeId, + disciplineId: createDto.disciplineId, + subTypeId: createDto.subTypeId, + recipientOrganizationId, + year: new Date().getFullYear(), + customTokens: { + TYPE_CODE: type.typeCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }); + } + /** + * Business Rule Implementation: EC-CORR-001 - Cancel Correspondence with Downstream Circulation + * Cancel correspondence and handle related circulations + */ + async cancel(publicId, reason, user) { + const correspondence = await this.findOneByUuid(publicId); + // Check if user has permission to cancel (Org Admin or Superadmin only) + const permissions = await this.userService.getUserPermissions(user.user_id); + const canCancel = permissions.includes('correspondence.cancel') || + permissions.includes('system.manage_all'); + if (!canCancel) { + throw new common_1.ForbiddenException('Only administrators can cancel correspondences'); + } + // Check if there are any active circulations + const circulationRepo = this.dataSource.getRepository('Circulation'); + const activeCirculations = await circulationRepo.find({ + where: { + correspondenceId: correspondence.id, + status: 'OPEN', + }, + }); + const warningMessage = activeCirculations.length > 0 + ? `There are ${activeCirculations.length} active circulation(s) for this correspondence. Canceling will force close all related circulations.` + : ''; + // Get the current revision to update status + const currentRevision = await this.revisionRepo.findOne({ + where: { + correspondenceId: correspondence.id, + isCurrent: true, + }, + }); + if (!currentRevision) { + throw new common_1.NotFoundException('Current revision not found'); + } + // Get cancelled status + const cancelledStatus = await this.statusRepo.findOne({ + where: { statusCode: 'CANCELLED' }, + }); + if (!cancelledStatus) { + throw new common_1.InternalServerErrorException('CANCELLED status not found'); + } + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + try { + // Update correspondence revision status to CANCELLED + await queryRunner.manager.update(correspondence_revision_entity_1.CorrespondenceRevision, currentRevision.id, { + statusId: cancelledStatus.id, + remarks: `Cancelled: ${reason}`, + }); + // Force close all active circulations + if (activeCirculations.length > 0) { + await queryRunner.manager.update('Circulation', { + correspondenceId: correspondence.id, + status: 'OPEN', + }, { + status: 'FORCE_CLOSED', + closedAt: new Date(), + closedBy: user.user_id, + closeReason: `Correspondence cancelled: ${reason}`, + }); + } + await queryRunner.commitTransaction(); + // Re-index cancelled status in Elasticsearch (fire-and-forget) + void this.searchService.indexDocument({ + id: correspondence.id, + publicId: correspondence.publicId, + type: 'correspondence', + docNumber: correspondence.correspondenceNumber, + title: currentRevision.subject, + status: 'CANCELLED', + projectId: correspondence.projectId, + createdAt: correspondence.createdAt, + }); + // Notify originator's doc-control user about cancellation (fire-and-forget) + if (correspondence.originatorId) { + void this.userService + .findDocControlIdByOrg(correspondence.originatorId) + .then((targetUserId) => { + if (targetUserId) { + void this.notificationService.send({ + userId: targetUserId, + title: 'Correspondence Cancelled', + message: `${correspondence.correspondenceNumber} — ${currentRevision.subject} has been cancelled. Reason: ${reason}`, + type: 'EMAIL', + entityType: 'correspondence', + entityId: correspondence.id, + link: `/correspondences/${correspondence.publicId}`, + }); + } + }) + .catch((err) => this.logger.warn(`Cancel notification failed: ${err.message}`)); + } + return { + success: true, + message: warningMessage || 'Correspondence cancelled successfully', + activeCirculationsCount: activeCirculations.length, + }; + } + catch (error) { + await queryRunner.rollbackTransaction(); + this.logger.error(`Failed to cancel correspondence: ${error.message}`); + throw error; + } + finally { + await queryRunner.release(); + } + } + async bulkCancel(publicIds, reason, user) { + const succeeded = []; + const failed = []; + for (const publicId of publicIds) { + try { + await this.cancel(publicId, reason, user); + succeeded.push(publicId); + } + catch { + failed.push(publicId); + } + } + return { succeeded, failed }; + } + async exportCsv(searchDto) { + const { data } = await this.findAll(searchDto); + const header = [ + 'Document No.', + 'Rev', + 'Subject', + 'Type', + 'Status', + 'Project', + 'From', + 'Due Date', + 'Created At', + ]; + const rows = data.map((rev) => { + const corr = rev.correspondence ?? rev; + return [ + this.escapeCsv(corr.correspondenceNumber ?? ''), + this.escapeCsv(rev.revisionLabel ?? String(rev.revisionNumber ?? 0)), + this.escapeCsv(rev.subject ?? ''), + this.escapeCsv(corr.type?.typeCode ?? ''), + this.escapeCsv(rev.status?.statusCode ?? ''), + this.escapeCsv(corr.project?.projectCode ?? ''), + this.escapeCsv(corr.originator?.organizationCode ?? ''), + rev.dueDate ? new Date(rev.dueDate).toISOString().split('T')[0] : '', + new Date(rev.createdAt).toISOString().split('T')[0], + ].join(','); + }); + return [header.join(','), ...rows].join('\n'); + } + escapeCsv(value) { + if (value.includes(',') || value.includes('"') || value.includes('\n')) { + return `"${value.replace(/"/g, '""')}"`; + } + return value; + } +}; +exports.CorrespondenceService = CorrespondenceService; +exports.CorrespondenceService = CorrespondenceService = CorrespondenceService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(correspondence_entity_1.Correspondence)), + __param(1, (0, typeorm_1.InjectRepository)(correspondence_revision_entity_1.CorrespondenceRevision)), + __param(2, (0, typeorm_1.InjectRepository)(correspondence_type_entity_1.CorrespondenceType)), + __param(3, (0, typeorm_1.InjectRepository)(correspondence_status_entity_1.CorrespondenceStatus)), + __param(4, (0, typeorm_1.InjectRepository)(correspondence_reference_entity_1.CorrespondenceReference)), + __param(5, (0, typeorm_1.InjectRepository)(correspondence_tag_entity_1.CorrespondenceTag)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object, typeof (_e = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _e : Object, typeof (_f = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _f : Object, typeof (_g = typeof document_numbering_service_1.DocumentNumberingService !== "undefined" && document_numbering_service_1.DocumentNumberingService) === "function" ? _g : Object, typeof (_h = typeof json_schema_service_1.JsonSchemaService !== "undefined" && json_schema_service_1.JsonSchemaService) === "function" ? _h : Object, typeof (_j = typeof workflow_engine_service_1.WorkflowEngineService !== "undefined" && workflow_engine_service_1.WorkflowEngineService) === "function" ? _j : Object, typeof (_k = typeof user_service_1.UserService !== "undefined" && user_service_1.UserService) === "function" ? _k : Object, typeof (_l = typeof typeorm_2.DataSource !== "undefined" && typeorm_2.DataSource) === "function" ? _l : Object, typeof (_m = typeof search_service_1.SearchService !== "undefined" && search_service_1.SearchService) === "function" ? _m : Object, typeof (_o = typeof file_storage_service_1.FileStorageService !== "undefined" && file_storage_service_1.FileStorageService) === "function" ? _o : Object, typeof (_p = typeof uuid_resolver_service_1.UuidResolverService !== "undefined" && uuid_resolver_service_1.UuidResolverService) === "function" ? _p : Object, typeof (_q = typeof notification_service_1.NotificationService !== "undefined" && notification_service_1.NotificationService) === "function" ? _q : Object]) +], CorrespondenceService); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2UudHMiLCJtYXBwaW5ncyI6IjtBQUFBLDZEQUE2RDs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFN0QsMkNBT3dCO0FBQ3hCLDZDQUFtRDtBQUNuRCxxQ0FBaUQ7QUFFakQsV0FBVztBQUNYLDRFQUFrRTtBQUNsRSw4RkFBbUY7QUFDbkYsc0ZBQTJFO0FBQzNFLDBGQUErRTtBQUMvRSxnR0FBcUY7QUFDckYsZ0dBQXFGO0FBQ3JGLG9GQUF5RTtBQUN6RSw4REFBb0Q7QUFFcEQsc0ZBQTRFO0FBUTVFLFdBQVc7QUFDWCwwR0FBcUc7QUFDckcsNEVBQXVFO0FBQ3ZFLHdGQUFtRjtBQUNuRix1REFBbUQ7QUFDbkQsNkRBQXlEO0FBQ3pELHlGQUFvRjtBQUNwRix1RkFBa0Y7QUFDbEYsK0VBQTJFO0FBVXBFLElBQU0scUJBQXFCLDZCQUEzQixNQUFNLHFCQUFxQjtJQUd4QixLQUFLLENBQUMsNEJBQTRCLENBQUMsTUFBYztRQUN2RCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEUsT0FBTyxXQUFXLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyx1QkFBdUIsQ0FBQyxRQUFnQjtRQUM5QyxNQUFNLGFBQWEsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNyQyxJQUFJLGFBQWEsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUNuRCxPQUFPLEdBQUcsQ0FBQyxDQUFDLHdCQUF3QjtRQUN0QyxDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUMsQ0FBQyxvQ0FBb0M7SUFDeEQsQ0FBQztJQUVELFlBRUUsa0JBQXNELEVBRXRELFlBQXdELEVBRXhELFFBQWdELEVB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cC1kbXNcXGxjYnAzXFxiYWNrZW5kXFxzcmNcXG1vZHVsZXNcXGNvcnJlc3BvbmRlbmNlXFxjb3JyZXNwb25kZW5jZS5zZXJ2aWNlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIEZpbGU6IHNyYy9tb2R1bGVzL2NvcnJlc3BvbmRlbmNlL2NvcnJlc3BvbmRlbmNlLnNlcnZpY2UudHNcclxuXHJcbmltcG9ydCB7XHJcbiAgSW5qZWN0YWJsZSxcclxuICBOb3RGb3VuZEV4Y2VwdGlvbixcclxuICBCYWRSZXF1ZXN0RXhjZXB0aW9uLFxyXG4gIEludGVybmFsU2VydmVyRXJyb3JFeGNlcHRpb24sXHJcbiAgRm9yYmlkZGVuRXhjZXB0aW9uLFxyXG4gIExvZ2dlcixcclxufSBmcm9tICdAbmVzdGpzL2NvbW1vbic7XHJcbmltcG9ydCB7IEluamVjdFJlcG9zaXRvcnkgfSBmcm9tICdAbmVzdGpzL3R5cGVvcm0nO1xyXG5pbXBvcnQgeyBSZXBvc2l0b3J5LCBEYXRhU291cmNlIH0gZnJvbSAndHlwZW9ybSc7XHJcblxyXG4vLyBFbnRpdGllc1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbiB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmV2aXNpb24uZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VUeXBlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS10eXBlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlU3RhdHVzIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1zdGF0dXMuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VSZWZlcmVuY2UgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXJlZmVyZW5jZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlY2lwaWVudCB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVjaXBpZW50LmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVGFnIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS10YWcuZW50aXR5JztcclxuaW1wb3J0IHsgVGFnIH0gZnJvbSAnLi4vbWFzdGVyL2VudGl0aWVzL3RhZy5lbnRpdHknO1xyXG5pbXBvcnQgeyBVc2VyIH0gZnJvbSAnLi4vdXNlci9lbnRpdGllcy91c2VyLmVudGl0eSc7XHJcbmltcG9ydCB7IE9yZ2FuaXphdGlvbiB9IGZyb20gJy4uL29yZ2FuaXphdGlvbi9lbnRpdGllcy9vcmdhbml6YXRpb24uZW50aXR5JztcclxuXHJcbi8vIERUT3NcclxuaW1wb3J0IHsgQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by9jcmVhdGUtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuaW1wb3J0IHsgVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by91cGRhdGUtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuaW1wb3J0IHsgQWRkUmVmZXJlbmNlRHRvIH0gZnJvbSAnLi9kdG8vYWRkLXJlZmVyZW5jZS5kdG8nO1xyXG5pbXBvcnQgeyBTZWFyY2hDb3JyZXNwb25kZW5jZUR0byB9IGZyb20gJy4vZHRvL3NlYXJjaC1jb3JyZXNwb25kZW5jZS5kdG8nO1xyXG5cclxuLy8gU2VydmljZXNcclxuaW1wb3J0IHsgRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlIH0gZnJvbSAnLi4vZG9jdW1lbnQtbnVtYmVyaW5nL3NlcnZpY2VzL2RvY3VtZW50LW51bWJlcmluZy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgSnNvblNjaGVtYVNlcnZpY2UgfSBmcm9tICcuLi9qc29uLXNjaGVtYS9qc29uLXNjaGVtYS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgV29ya2Zsb3dFbmdpbmVTZXJ2aWNlIH0gZnJvbSAnLi4vd29ya2Zsb3ctZW5naW5lL3dvcmtmbG93LWVuZ2luZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXNlclNlcnZpY2UgfSBmcm9tICcuLi91c2VyL3VzZXIuc2VydmljZSc7XHJcbmltcG9ydCB7IFNlYXJjaFNlcnZpY2UgfSBmcm9tICcuLi9zZWFyY2gvc2VhcmNoLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBGaWxlU3RvcmFnZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vZmlsZS1zdG9yYWdlL2ZpbGUtc3RvcmFnZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXVpZFJlc29sdmVyU2VydmljZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9zZXJ2aWNlcy91dWlkLXJlc29sdmVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBOb3RpZmljYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vbm90aWZpY2F0aW9uL25vdGlmaWNhdGlvbi5zZXJ2aWNlJztcclxuXHJcbi8qKlxyXG4gKiBDb3JyZXNwb25kZW5jZVNlcnZpY2UgLSBEb2N1bWVudCBtYW5hZ2VtZW50IChDUlVEKVxyXG4gKi9cclxuaW50ZXJmYWNlIFJlc29sdmVkUmVjaXBpZW50IHtcclxuICBvcmdhbml6YXRpb25JZDogbnVtYmVyO1xyXG4gIHR5cGU6ICdUTycgfCAnQ0MnO1xyXG59XHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIENvcnJlc3BvbmRlbmNlU2VydmljZSB7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXIgPSBuZXcgTG9nZ2VyKENvcnJlc3BvbmRlbmNlU2VydmljZS5uYW1lKTtcclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBoYXNTeXN0ZW1NYW5hZ2VBbGxQZXJtaXNzaW9uKHVzZXJJZDogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XHJcbiAgICBjb25zdCBwZXJtaXNzaW9ucyA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZ2V0VXNlclBlcm1pc3Npb25zKHVzZXJJZCk7XHJcbiAgICByZXR1cm4gcGVybWlzc2lvbnMuaW5jbHVkZXMoJ3N5c3RlbS5tYW5hZ2VfYWxsJyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBCdXNpbmVzcyBSdWxlOiBSZXZpc2lvbiBMYWJlbCBTdHJhdGVneVxyXG4gICAqIC0gUkZBLCBSRkk6IFVzZSBhbHBoYWJldCBzdGFydGluZyB3aXRoICdBJyAoQSwgQiwgQy4uLilcclxuICAgKiAtIE90aGVyIHR5cGVzIChMRVRURVIsIE1FTU8sIGV0Yy4pOiBVc2UgbnVtZXJpYyAobnVsbCBmb3IgZmlyc3QsIHRoZW4gMSwgMiwgMy4uLilcclxuICAgKi9cclxuICBwcml2YXRlIGdldEluaXRpYWxSZXZpc2lvbkxhYmVsKHR5cGVDb2RlOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xyXG4gICAgY29uc3QgYWxwaGFiZXRUeXBlcyA9IFsnUkZBJywgJ1JGSSddO1xyXG4gICAgaWYgKGFscGhhYmV0VHlwZXMuaW5jbHVkZXModHlwZUNvZGUudG9VcHBlckNhc2UoKSkpIHtcclxuICAgICAgcmV0dXJuICdBJzsgLy8gQWxwaGFiZXQgZm9yIFJGQSwgUkZJXHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkOyAvLyBOdW1lcmljIChubyBsYWJlbCBmb3IgcmV2aXNpb24gMClcclxuICB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgQEluamVjdFJlcG9zaXRvcnkoQ29ycmVzcG9uZGVuY2UpXHJcbiAgICBwcml2YXRlIGNvcnJlc3BvbmRlbmNlUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZT4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVJldmlzaW9uKVxyXG4gICAgcHJpdmF0ZSByZXZpc2lvblJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VSZXZpc2lvbj4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICBwcml2YXRlIHR5cGVSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgIHByaXZhdGUgc3RhdHVzUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVJlZmVyZW5jZSlcclxuICAgIHByaXZhdGUgcmVmZXJlbmNlUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVJlZmVyZW5jZT4sXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZVRhZylcclxuICAgIHByaXZhdGUgdGFnUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVRhZz4sXHJcbiAgICBwcml2YXRlIG51bWJlcmluZ1NlcnZpY2U6IERvY3VtZW50TnVtYmVyaW5nU2VydmljZSxcclxuICAgIHByaXZhdGUganNvblNjaGVtYVNlcnZpY2U6IEpzb25TY2hlbWFTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB3b3JrZmxvd0VuZ2luZTogV29ya2Zsb3dFbmdpbmVTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB1c2VyU2VydmljZTogVXNlclNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGRhdGFTb3VyY2U6IERhdGFTb3VyY2UsXHJcbiAgICBwcml2YXRlIHNlYXJjaFNlcnZpY2U6IFNlYXJjaFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGZpbGVTdG9yYWdlU2VydmljZTogRmlsZVN0b3JhZ2VTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB1dWlkUmVzb2x2ZXI6IFV1aWRSZXNvbHZlclNlcnZpY2UsXHJcbiAgICBwcml2YXRlIG5vdGlmaWNhdGlvblNlcnZpY2U6IE5vdGlmaWNhdGlvblNlcnZpY2VcclxuICApIHt9XHJcblxyXG4gIC8qKlxyXG4gICAqIEJ1c2luZXNzIFJ1bGUgVmFsaWRhdGlvbjogRUMtQ09SUi0wMDMgLSBDb3JyZXNwb25kZW5jZSB0byBTZWxmXHJcbiAgICogUHJldmVudCBleHRlcm5hbCBjb3JyZXNwb25kZW5jZSB0byBzYW1lIG9yZ2FuaXphdGlvblxyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgdmFsaWRhdGVDb3JyZXNwb25kZW5jZVJlY2lwaWVudHMoXHJcbiAgICBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvLFxyXG4gICAgdXNlcjogVXNlclxyXG4gICk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgLy8gR2V0IHVzZXIncyBvcmdhbml6YXRpb25cclxuICAgIGxldCB1c2VyT3JnSWQgPSB1c2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgIGNvbnN0IGZ1bGxVc2VyID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS5maW5kT25lKHVzZXIudXNlcl9pZCk7XHJcbiAgICAgIGlmIChmdWxsVXNlcikge1xyXG4gICAgICAgIHVzZXJPcmdJZCA9IGZ1bGxVc2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgIGlmIChjcmVhdGVEdG8ub3JpZ2luYXRvcklkKSB7XHJcbiAgICAgICAgY29uc3QgY2FuTWFuYWdlQWxsID0gYXdhaXQgdGhpcy5oYXNTeXN0ZW1NYW5hZ2VBbGxQZXJtaXNzaW9uKFxyXG4gICAgICAgICAgdXNlci51c2VyX2lkXHJcbiAgICAgICAgKTtcclxuICAgICAgICBpZiAoY2FuTWFuYWdlQWxsKSB7XHJcbiAgICAgICAgICB1c2VyT3JnSWQgPSBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoXHJcbiAgICAgICAgICAgIGNyZWF0ZUR0by5vcmlnaW5hdG9ySWRcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoIXVzZXJPcmdJZCkge1xyXG4gICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxyXG4gICAgICAgICAgJ1VzZXIgbXVzdCBiZWxvbmcgdG8gYW4gb3JnYW5pemF0aW9uIHRvIGNyZWF0ZSBkb2N1bWVudHMnXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIEZvciBpbXBlcnNvbmF0aW9uLCB1c2UgdGhlIHNwZWNpZmllZCBvcmlnaW5hdG9yXHJcbiAgICBjb25zdCBvcmlnaW5hdG9yT3JnSWQgPSBjcmVhdGVEdG8ub3JpZ2luYXRvcklkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKGNyZWF0ZUR0by5vcmlnaW5hdG9ySWQpXHJcbiAgICAgIDogdXNlck9yZ0lkO1xyXG5cclxuICAgIC8vIENoZWNrIGlmIGl0J3MgaW50ZXJuYWwgY29tbXVuaWNhdGlvblxyXG4gICAgaWYgKGNyZWF0ZUR0by5pc0ludGVybmFsKSB7XHJcbiAgICAgIC8vIEludGVybmFsIGNvbW11bmljYXRpb25zIHNob3VsZCB1c2UgQ2lyY3VsYXRpb24gaW5zdGVhZFxyXG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcclxuICAgICAgICAnSW50ZXJuYWwgY29tbXVuaWNhdGlvbnMgc2hvdWxkIHVzZSBDaXJjdWxhdGlvbiBTaGVldCBpbnN0ZWFkIG9mIENvcnJlc3BvbmRlbmNlJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFZhbGlkYXRlIHJlY2lwaWVudHNcclxuICAgIGlmICghY3JlYXRlRHRvLnJlY2lwaWVudHMgfHwgY3JlYXRlRHRvLnJlY2lwaWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxyXG4gICAgICAgICdBdCBsZWFzdCBvbmUgcmVjaXBpZW50IChUTyBvciBDQykgaXMgcmVxdWlyZWQnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgdG9SZWNpcGllbnRzID0gY3JlYXRlRHRvLnJlY2lwaWVudHMuZmlsdGVyKChyKSA9PiByLnR5cGUgPT09ICdUTycpO1xyXG4gICAgY29uc3QgY2NSZWNpcGllbnRzID0gY3JlYXRlRHRvLnJlY2lwaWVudHMuZmlsdGVyKChyKSA9PiByLnR5cGUgPT09ICdDQycpO1xyXG5cclxuICAgIGlmICh0b1JlY2lwaWVudHMubGVuZ3RoID09PSAwICYmIGNjUmVjaXBpZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgJ0F0IGxlYXN0IG9uZSBUTyBvciBDQyByZWNpcGllbnQgaXMgcmVxdWlyZWQnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgZm9yIHNhbWUgb3JnYW5pemF0aW9uIGNvcnJlc3BvbmRlbmNlXHJcbiAgICBmb3IgKGNvbnN0IHJlY2lwaWVudCBvZiBjcmVhdGVEdG8ucmVjaXBpZW50cykge1xyXG4gICAgICBjb25zdCByZWNpcGllbnRPcmdJZCA9IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChcclxuICAgICAgICByZWNpcGllbnQub3JnYW5pemF0aW9uSWRcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGlmIChyZWNpcGllbnRPcmdJZCA9PT0gb3JpZ2luYXRvck9yZ0lkKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgICAnQ2Fubm90IHNlbmQgY29ycmVzcG9uZGVuY2UgdG8geW91ciBvd24gb3JnYW5pemF0aW9uLiBVc2UgQ2lyY3VsYXRpb24gU2hlZXQgZm9yIGludGVybmFsIGNvbW11bmljYXRpb24uJ1xyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGNyZWF0ZShjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvLCB1c2VyOiBVc2VyKSB7XHJcbiAgICAvLyBCdXNpbmVzcyBSdWxlIFZhbGlkYXRpb246IEVDLUNPUlItMDAzIC0gQ29ycmVzcG9uZGVuY2UgdG8gU2VsZlxyXG4gICAgYXdhaXQgdGhpcy52YWxpZGF0ZUNvcnJlc3BvbmRlbmNlUmVjaXBpZW50cyhjcmVhdGVEdG8sIHVzZXIpO1xyXG4gICAgLy8gQURSLTAxOTogUmVzb2x2ZSBVVUlEIHJlZmVyZW5jZXMgdG8gaW50ZXJuYWwgSU5UIElEc1xyXG4gICAgY29uc3QgcmVzb2x2ZWRQcm9qZWN0SWQgPSBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkKFxyXG4gICAgICBjcmVhdGVEdG8ucHJvamVjdElkXHJcbiAgICApO1xyXG4gICAgY29uc3QgcmVzb2x2ZWRPcmlnaW5hdG9ySWQgPSBjcmVhdGVEdG8ub3JpZ2luYXRvcklkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKGNyZWF0ZUR0by5vcmlnaW5hdG9ySWQpXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgcmVzb2x2ZWRSZWNpcGllbnRzID0gY3JlYXRlRHRvLnJlY2lwaWVudHNcclxuICAgICAgPyBhd2FpdCBQcm9taXNlLmFsbChcclxuICAgICAgICAgIGNyZWF0ZUR0by5yZWNpcGllbnRzLm1hcChcclxuICAgICAgICAgICAgYXN5bmMgKHIpOiBQcm9taXNlPFJlc29sdmVkUmVjaXBpZW50PiA9PiAoe1xyXG4gICAgICAgICAgICAgIG9yZ2FuaXphdGlvbklkOiBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoXHJcbiAgICAgICAgICAgICAgICByLm9yZ2FuaXphdGlvbklkXHJcbiAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICB0eXBlOiByLnR5cGUsXHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICApXHJcbiAgICAgICAgKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuICAgIGNvbnN0IHR5cGUgPSBhd2FpdCB0aGlzLnR5cGVSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZDogY3JlYXRlRHRvLnR5cGVJZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIXR5cGUpIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignRG9jdW1lbnQgVHlwZSBub3QgZm91bmQnKTtcclxuXHJcbiAgICBjb25zdCBzdGF0dXNEcmFmdCA9IGF3YWl0IHRoaXMuc3RhdHVzUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgc3RhdHVzQ29kZTogJ0RSQUZUJyB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIXN0YXR1c0RyYWZ0KSB7XHJcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbFNlcnZlckVycm9yRXhjZXB0aW9uKFxyXG4gICAgICAgICdTdGF0dXMgRFJBRlQgbm90IGZvdW5kIGluIE1hc3RlciBEYXRhJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCB1c2VyT3JnSWQgPSB1c2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICBpZiAoIXVzZXJPcmdJZCkge1xyXG4gICAgICBjb25zdCBmdWxsVXNlciA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZmluZE9uZSh1c2VyLnVzZXJfaWQpO1xyXG4gICAgICBpZiAoZnVsbFVzZXIpIHtcclxuICAgICAgICB1c2VyT3JnSWQgPSBmdWxsVXNlci5wcmltYXJ5T3JnYW5pemF0aW9uSWQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBJbXBlcnNvbmF0aW9uIExvZ2ljXHJcbiAgICBpZiAocmVzb2x2ZWRPcmlnaW5hdG9ySWQgJiYgcmVzb2x2ZWRPcmlnaW5hdG9ySWQgIT09IHVzZXJPcmdJZCkge1xyXG4gICAgICBjb25zdCBjYW5NYW5hZ2VBbGwgPSBhd2FpdCB0aGlzLmhhc1N5c3RlbU1hbmFnZUFsbFBlcm1pc3Npb24oXHJcbiAgICAgICAgdXNlci51c2VyX2lkXHJcbiAgICAgICk7XHJcbiAgICAgIGlmICghY2FuTWFuYWdlQWxsKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEZvcmJpZGRlbkV4Y2VwdGlvbihcclxuICAgICAgICAgICdZb3UgZG8gbm90IGhhdmUgcGVybWlzc2lvbiB0byBjcmVhdGUgZG9jdW1lbnRzIG9uIGJlaGFsZiBvZiBvdGhlciBvcmdhbml6YXRpb25zLidcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICAgIHVzZXJPcmdJZCA9IHJlc29sdmVkT3JpZ2luYXRvcklkO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxyXG4gICAgICAgICdVc2VyIG11c3QgYmVsb25nIHRvIGFuIG9yZ2FuaXphdGlvbiB0byBjcmVhdGUgZG9jdW1lbnRzJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChjcmVhdGVEdG8uZGV0YWlscykge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGF3YWl0IHRoaXMuanNvblNjaGVtYVNlcnZpY2UudmFsaWRhdGUodHlwZS50eXBlQ29kZSwgY3JlYXRlRHRvLmRldGFpbHMpO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xyXG4gICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXHJcbiAgICAgICAgICBgU2NoZW1hIHZhbGlkYXRpb24gd2FybmluZyBmb3IgJHt0eXBlLnR5cGVDb2RlfTogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YFxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHRoaXMuZGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lcigpO1xyXG4gICAgYXdhaXQgcXVlcnlSdW5uZXIuY29ubmVjdCgpO1xyXG4gICAgYXdhaXQgcXVlcnlSdW5uZXIuc3RhcnRUcmFuc2FjdGlvbigpO1xyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIC8vIFtGaXggIzZdIEZldGNoIHJlYWwgT1JHIENvZGUgZnJvbSBPcmdhbml6YXRpb24gZW50aXR5XHJcbiAgICAgIGNvbnN0IG9yaWdpbmF0b3JPcmcgPSBhd2FpdCB0aGlzLmRhdGFTb3VyY2UubWFuYWdlci5maW5kT25lKFxyXG4gICAgICAgIE9yZ2FuaXphdGlvbixcclxuICAgICAgICB7XHJcbiAgICAgICAgICB3aGVyZTogeyBpZDogdXNlck9yZ0lkIH0sXHJcbiAgICAgICAgfVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBvcmdDb2RlID0gb3JpZ2luYXRvck9yZz8ub3JnYW5pemF0aW9uQ29kZSA/PyAnVU5LJztcclxuXHJcbiAgICAgIC8vIFt2MS41LjFdIEV4dHJhY3QgcmVjaXBpZW50IG9yZ2FuaXphdGlvbiBmcm9tIHJlY2lwaWVudHMgYXJyYXkgKFByaW1hcnkgVE8pXHJcbiAgICAgIGNvbnN0IHRvUmVjaXBpZW50ID0gcmVzb2x2ZWRSZWNpcGllbnRzPy5maW5kKChyKSA9PiByLnR5cGUgPT09ICdUTycpO1xyXG4gICAgICBjb25zdCByZWNpcGllbnRPcmdhbml6YXRpb25JZCA9IHRvUmVjaXBpZW50Py5vcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICAgIGxldCByZWNpcGllbnRDb2RlID0gJyc7XHJcbiAgICAgIGlmIChyZWNpcGllbnRPcmdhbml6YXRpb25JZCkge1xyXG4gICAgICAgIGNvbnN0IHJlY09yZyA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoT3JnYW5pemF0aW9uLCB7XHJcbiAgICAgICAgICB3aGVyZTogeyBpZDogcmVjaXBpZW50T3JnYW5pemF0aW9uSWQgfSxcclxuICAgICAgICB9KTtcclxuICAgICAgICBpZiAocmVjT3JnKSByZWNpcGllbnRDb2RlID0gcmVjT3JnLm9yZ2FuaXphdGlvbkNvZGU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGRvY051bWJlciA9IGF3YWl0IHRoaXMubnVtYmVyaW5nU2VydmljZS5nZW5lcmF0ZU5leHROdW1iZXIoe1xyXG4gICAgICAgIHByb2plY3RJZDogcmVzb2x2ZWRQcm9qZWN0SWQsXHJcbiAgICAgICAgb3JpZ2luYXRvck9yZ2FuaXphdGlvbklkOiB1c2VyT3JnSWQsXHJcbiAgICAgICAgdHlwZUlkOiBjcmVhdGVEdG8udHlwZUlkLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogY3JlYXRlRHRvLmRpc2NpcGxpbmVJZCxcclxuICAgICAgICBzdWJUeXBlSWQ6IGNyZWF0ZUR0by5zdWJUeXBlSWQsXHJcbiAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQsIC8vIFt2MS41LjFdIFBhc3MgcmVjaXBpZW50IGZvciBkb2N1bWVudCBudW1iZXIgZm9ybWF0XHJcbiAgICAgICAgeWVhcjogbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpLFxyXG4gICAgICAgIGN1c3RvbVRva2Vuczoge1xyXG4gICAgICAgICAgVFlQRV9DT0RFOiB0eXBlLnR5cGVDb2RlLFxyXG4gICAgICAgICAgT1JHX0NPREU6IG9yZ0NvZGUsXHJcbiAgICAgICAgICBSRUNJUElFTlRfQ09ERTogcmVjaXBpZW50Q29kZSxcclxuICAgICAgICAgIFJFQ19DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgY29uc3QgY29ycmVzcG9uZGVuY2UgPSBxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZShDb3JyZXNwb25kZW5jZSwge1xyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiBkb2NOdW1iZXIubnVtYmVyLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiBjcmVhdGVEdG8udHlwZUlkLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogY3JlYXRlRHRvLmRpc2NpcGxpbmVJZCxcclxuICAgICAgICBwcm9qZWN0SWQ6IHJlc29sdmVkUHJvamVjdElkLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogdXNlck9yZ0lkLFxyXG4gICAgICAgIGlzSW50ZXJuYWw6IGNyZWF0ZUR0by5pc0ludGVybmFsIHx8IGZhbHNlLFxyXG4gICAgICAgIGNyZWF0ZWRCeTogdXNlci51c2VyX2lkLFxyXG4gICAgICB9KTtcclxuICAgICAgY29uc3Qgc2F2ZWRDb3JyID0gYXdhaXQgcXVlcnlSdW5uZXIubWFuYWdlci5zYXZlKGNvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIGNvbnN0IHJldmlzaW9uID0gcXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUoQ29ycmVzcG9uZGVuY2VSZXZpc2lvbiwge1xyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IHNhdmVkQ29yci5pZCxcclxuICAgICAgICByZXZpc2lvbk51bWJlcjogMCxcclxuICAgICAgICByZXZpc2lvbkxhYmVsOiB0aGlzLmdldEluaXRpYWxSZXZpc2lvbkxhYmVsKHR5cGUudHlwZUNvZGUpLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogc3RhdHVzRHJhZnQuaWQsXHJcbiAgICAgICAgc3ViamVjdDogY3JlYXRlRHRvLnN1YmplY3QsXHJcbiAgICAgICAgYm9keTogY3JlYXRlRHRvLmJvZHksXHJcbiAgICAgICAgcmVtYXJrczogY3JlYXRlRHRvLnJlbWFya3MsXHJcbiAgICAgICAgZHVlRGF0ZTogY3JlYXRlRHRvLmR1ZURhdGUgPyBuZXcgRGF0ZShjcmVhdGVEdG8uZHVlRGF0ZSkgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgZG9jdW1lbnREYXRlOiBjcmVhdGVEdG8uZG9jdW1lbnREYXRlXHJcbiAgICAgICAgICA/IG5ldyBEYXRlKGNyZWF0ZUR0by5kb2N1bWVudERhdGUpXHJcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcclxuICAgICAgICBpc3N1ZWREYXRlOiBjcmVhdGVEdG8uaXNzdWVkRGF0ZVxyXG4gICAgICAgICAgPyBuZXcgRGF0ZShjcmVhdGVEdG8uaXNzdWVkRGF0ZSlcclxuICAgICAgICAgIDogdW5kZWZpbmVkLFxyXG4gICAgICAgIHJlY2VpdmVkRGF0ZTogY3JlYXRlRHRvLnJlY2VpdmVkRGF0ZVxyXG4gICAgICAgICAgPyBuZXcgRGF0ZShjcmVhdGVEdG8ucmVjZWl2ZWREYXRlKVxyXG4gICAgICAgICAgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgZGVzY3JpcHRpb246IGNyZWF0ZUR0by5kZXNjcmlwdGlvbixcclxuICAgICAgICBkZXRhaWxzOiBjcmVhdGVEdG8uZGV0YWlscyxcclxuICAgICAgICBjcmVhdGVkQnk6IHVzZXIudXNlcl9pZCxcclxuICAgICAgICBzY2hlbWFWZXJzaW9uOiAxLFxyXG4gICAgICB9KTtcclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIubWFuYWdlci5zYXZlKHJldmlzaW9uKTtcclxuXHJcbiAgICAgIC8vIFNhdmUgUmVjaXBpZW50cyAodXNpbmcgcmVzb2x2ZWQgSU5UIElEcylcclxuICAgICAgaWYgKHJlc29sdmVkUmVjaXBpZW50cyAmJiByZXNvbHZlZFJlY2lwaWVudHMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSByZXNvbHZlZFJlY2lwaWVudHMubWFwKChyKSA9PlxyXG4gICAgICAgICAgcXVlcnlSdW5uZXIubWFuYWdlci5jcmVhdGUoQ29ycmVzcG9uZGVuY2VSZWNpcGllbnQsIHtcclxuICAgICAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogc2F2ZWRDb3JyLmlkLFxyXG4gICAgICAgICAgICByZWNpcGllbnRPcmdhbml6YXRpb25JZDogci5vcmdhbml6YXRpb25JZCxcclxuICAgICAgICAgICAgcmVjaXBpZW50VHlwZTogci50eXBlLFxyXG4gICAgICAgICAgfSlcclxuICAgICAgICApO1xyXG4gICAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLm1hbmFnZXIuc2F2ZShyZWNpcGllbnRzKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gQ29tbWl0IGF0dGFjaG1lbnRzIGZyb20gVGVtcCDihpIgUGVybWFuZW50IChUd28tUGhhc2UgU3RvcmFnZSlcclxuICAgICAgaWYgKGNyZWF0ZUR0by5hdHRhY2htZW50VGVtcElkcz8ubGVuZ3RoKSB7XHJcbiAgICAgICAgY29uc3QgaXNzdWVEYXRlID0gY3JlYXRlRHRvLmlzc3VlZERhdGVcclxuICAgICAgICAgID8gbmV3IERhdGUoY3JlYXRlRHRvLmlzc3VlZERhdGUpXHJcbiAgICAgICAgICA6IGNyZWF0ZUR0by5kb2N1bWVudERhdGVcclxuICAgICAgICAgICAgPyBuZXcgRGF0ZShjcmVhdGVEdG8uZG9jdW1lbnREYXRlKVxyXG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgICAgYXdhaXQgdGhpcy5maWxlU3RvcmFnZVNlcnZpY2UuY29tbWl0KGNyZWF0ZUR0by5hdHRhY2htZW50VGVtcElkcywge1xyXG4gICAgICAgICAgaXNzdWVEYXRlLFxyXG4gICAgICAgICAgZG9jdW1lbnRUeXBlOiAnQ29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBhd2FpdCBxdWVyeVJ1bm5lci5jb21taXRUcmFuc2FjdGlvbigpO1xyXG5cclxuICAgICAgLy8gU3RhcnQgV29ya2Zsb3cgSW5zdGFuY2UgKG5vbi1ibG9ja2luZylcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCB3b3JrZmxvd0NvZGUgPSBgQ09SUkVTUE9OREVOQ0VfJHt0eXBlLnR5cGVDb2RlfWA7XHJcbiAgICAgICAgYXdhaXQgdGhpcy53b3JrZmxvd0VuZ2luZS5jcmVhdGVJbnN0YW5jZShcclxuICAgICAgICAgIHdvcmtmbG93Q29kZSxcclxuICAgICAgICAgICdjb3JyZXNwb25kZW5jZScsXHJcbiAgICAgICAgICBzYXZlZENvcnIuaWQudG9TdHJpbmcoKSxcclxuICAgICAgICAgIHtcclxuICAgICAgICAgICAgcHJvamVjdElkOiByZXNvbHZlZFByb2plY3RJZCxcclxuICAgICAgICAgICAgb3JpZ2luYXRvcklkOiB1c2VyT3JnSWQsXHJcbiAgICAgICAgICAgIGRpc2NpcGxpbmVJZDogY3JlYXRlRHRvLmRpc2NpcGxpbmVJZCxcclxuICAgICAgICAgICAgaW5pdGlhdG9ySWQ6IHVzZXIudXNlcl9pZCxcclxuICAgICAgICAgIH0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj5cclxuICAgICAgICApO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xyXG4gICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXHJcbiAgICAgICAgICBgV29ya2Zsb3cgbm90IHN0YXJ0ZWQgZm9yICR7ZG9jTnVtYmVyLm51bWJlcn0gKENvZGU6IENPUlJFU1BPTkRFTkNFXyR7dHlwZS50eXBlQ29kZX0pOiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gRmlyZS1hbmQtZm9yZ2V0IHNlYXJjaCBpbmRleGluZyAobm9uLWJsb2NraW5nLCB2b2lkIGludGVudGlvbmFsKVxyXG4gICAgICB2b2lkIHRoaXMuc2VhcmNoU2VydmljZS5pbmRleERvY3VtZW50KHtcclxuICAgICAgICBpZDogc2F2ZWRDb3JyLmlkLFxyXG4gICAgICAgIHB1YmxpY0lkOiBzYXZlZENvcnIucHVibGljSWQsXHJcbiAgICAgICAgdHlwZTogJ2NvcnJlc3BvbmRlbmNlJyxcclxuICAgICAgICBkb2NOdW1iZXI6IGRvY051bWJlci5udW1iZXIsXHJcbiAgICAgICAgdGl0bGU6IGNyZWF0ZUR0by5zdWJqZWN0LFxyXG4gICAgICAgIGRlc2NyaXB0aW9uOiBjcmVhdGVEdG8uZGVzY3JpcHRpb24sXHJcbiAgICAgICAgc3RhdHVzOiAnRFJBRlQnLFxyXG4gICAgICAgIHByb2plY3RJZDogcmVzb2x2ZWRQcm9qZWN0SWQsXHJcbiAgICAgICAgY3JlYXRlZEF0OiBuZXcgRGF0ZSgpLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAgLi4uc2F2ZWRDb3JyLFxyXG4gICAgICAgIGN1cnJlbnRSZXZpc2lvbjogcmV2aXNpb24sXHJcbiAgICAgIH07XHJcbiAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIucm9sbGJhY2tUcmFuc2FjdGlvbigpO1xyXG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcclxuICAgICAgICBgRmFpbGVkIHRvIGNyZWF0ZSBjb3JyZXNwb25kZW5jZTogJHsoZXJyIGFzIEVycm9yKS5tZXNzYWdlfWBcclxuICAgICAgKTtcclxuICAgICAgdGhyb3cgZXJyO1xyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIucmVsZWFzZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgZmluZEFsbChzZWFyY2hEdG86IFNlYXJjaENvcnJlc3BvbmRlbmNlRHRvID0ge30pIHtcclxuICAgIGNvbnN0IHtcclxuICAgICAgc2VhcmNoLFxyXG4gICAgICB0eXBlSWQsXHJcbiAgICAgIHByb2plY3RJZCxcclxuICAgICAgc3RhdHVzSWQsXHJcbiAgICAgIHN0YXR1cyxcclxuICAgICAgcGFnZSA9IDEsXHJcbiAgICAgIGxpbWl0ID0gMTAsXHJcbiAgICB9ID0gc2VhcmNoRHRvO1xyXG4gICAgY29uc3Qgc2tpcCA9IChwYWdlIC0gMSkgKiBsaW1pdDtcclxuXHJcbiAgICAvLyBDaGFuZ2U6IFF1ZXJ5IGZyb20gUmV2aXNpb24gUmVwb1xyXG4gICAgY29uc3QgcXVlcnkgPSB0aGlzLnJldmlzaW9uUmVwb1xyXG4gICAgICAuY3JlYXRlUXVlcnlCdWlsZGVyKCdyZXYnKVxyXG4gICAgICAubGVmdEpvaW5BbmRTZWxlY3QoJ3Jldi5jb3JyZXNwb25kZW5jZScsICdjb3JyJylcclxuICAgICAgLmxlZnRKb2luQW5kU2VsZWN0KCdjb3JyLnR5cGUnLCAndHlwZScpXHJcbiAgICAgIC5sZWZ0Sm9pbkFuZFNlbGVjdCgnY29yci5wcm9qZWN0JywgJ3Byb2plY3QnKVxyXG4gICAgICAubGVmdEpvaW5BbmRTZWxlY3QoJ2NvcnIub3JpZ2luYXRvcicsICdvcmcnKVxyXG4gICAgICAubGVmdEpvaW5BbmRTZWxlY3QoJ3Jldi5zdGF0dXMnLCAnc3RhdHVzJyk7XHJcblxyXG4gICAgLy8gRmlsdGVyIGJ5IFJldmlzaW9uIFN0YXR1c1xyXG4gICAgY29uc3QgcmV2U3RhdHVzID0gc2VhcmNoRHRvLnJldmlzaW9uU3RhdHVzIHx8ICdDVVJSRU5UJztcclxuXHJcbiAgICBpZiAocmV2U3RhdHVzID09PSAnQ1VSUkVOVCcpIHtcclxuICAgICAgcXVlcnkud2hlcmUoJ3Jldi5pc0N1cnJlbnQgPSA6aXNDdXJyZW50JywgeyBpc0N1cnJlbnQ6IHRydWUgfSk7XHJcbiAgICB9IGVsc2UgaWYgKHJldlN0YXR1cyA9PT0gJ09MRCcpIHtcclxuICAgICAgcXVlcnkud2hlcmUoJ3Jldi5pc0N1cnJlbnQgPSA6aXNDdXJyZW50JywgeyBpc0N1cnJlbnQ6IGZhbHNlIH0pO1xyXG4gICAgfVxyXG4gICAgLy8gSWYgJ0FMTCcsIG5vIGZpbHRlciBuZWVkZWQgb24gaXNDdXJyZW50XHJcblxyXG4gICAgaWYgKHByb2plY3RJZCkge1xyXG4gICAgICBxdWVyeS5hbmRXaGVyZSgnY29yci5wcm9qZWN0SWQgPSA6cHJvamVjdElkJywgeyBwcm9qZWN0SWQgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGVJZCkge1xyXG4gICAgICBxdWVyeS5hbmRXaGVyZSgnY29yci5jb3JyZXNwb25kZW5jZVR5cGVJZCA9IDp0eXBlSWQnLCB7IHR5cGVJZCB9KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoc3RhdHVzSWQpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoJ3Jldi5zdGF0dXNJZCA9IDpzdGF0dXNJZCcsIHsgc3RhdHVzSWQgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHN0YXR1cykge1xyXG4gICAgICBxdWVyeS5hbmRXaGVyZSgnc3RhdHVzLnN0YXR1c0NvZGUgPSA6c3RhdHVzJywgeyBzdGF0dXMgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHNlYXJjaCkge1xyXG4gICAgICBxdWVyeS5hbmRXaGVyZShcclxuICAgICAgICAnKGNvcnIuY29ycmVzcG9uZGVuY2VOdW1iZXIgTElLRSA6c2VhcmNoIE9SIHJldi5zdWJqZWN0IExJS0UgOnNlYXJjaCknLFxyXG4gICAgICAgIHsgc2VhcmNoOiBgJSR7c2VhcmNofSVgIH1cclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBEZWZhdWx0IFNvcnQ6IExhdGVzdCBDcmVhdGVkXHJcbiAgICBxdWVyeS5vcmRlckJ5KCdyZXYuY3JlYXRlZEF0JywgJ0RFU0MnKS5za2lwKHNraXApLnRha2UobGltaXQpO1xyXG5cclxuICAgIGNvbnN0IFtpdGVtcywgdG90YWxdID0gYXdhaXQgcXVlcnkuZ2V0TWFueUFuZENvdW50KCk7XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgZGF0YTogaXRlbXMsXHJcbiAgICAgIG1ldGE6IHtcclxuICAgICAgICB0b3RhbCxcclxuICAgICAgICBwYWdlLFxyXG4gICAgICAgIGxpbWl0LFxyXG4gICAgICAgIHRvdGFsUGFnZXM6IE1hdGguY2VpbCh0b3RhbCAvIGxpbWl0KSxcclxuICAgICAgfSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBhc3luYyBmaW5kT25lKGlkOiBudW1iZXIpIHtcclxuICAgIGNvbnN0IGNvcnJlc3BvbmRlbmNlID0gYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IGlkIH0sXHJcbiAgICAgIHJlbGF0aW9uczogW1xyXG4gICAgICAgICdyZXZpc2lvbnMnLFxyXG4gICAgICAgICdyZXZpc2lvbnMuc3RhdHVzJyxcclxuICAgICAgICAndHlwZScsXHJcbiAgICAgICAgJ3Byb2plY3QnLFxyXG4gICAgICAgICdvcmlnaW5hdG9yJyxcclxuICAgICAgICAncmVjaXBpZW50cycsXHJcbiAgICAgICAgJ3JlY2lwaWVudHMucmVjaXBpZW50T3JnYW5pemF0aW9uJywgLy8gW3YxLjUuMV0gRml4ZWQgcmVsYXRpb24gbmFtZVxyXG4gICAgICBdLFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKCFjb3JyZXNwb25kZW5jZSkge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oYENvcnJlc3BvbmRlbmNlIHdpdGggSUQgJHtpZH0gbm90IGZvdW5kYCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gY29ycmVzcG9uZGVuY2U7XHJcbiAgfVxyXG5cclxuICBhc3luYyBmaW5kT25lQnlVdWlkKHB1YmxpY0lkOiBzdHJpbmcpIHtcclxuICAgIGNvbnN0IGNvcnJlc3BvbmRlbmNlID0gYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IHB1YmxpY0lkIH0sXHJcbiAgICAgIHJlbGF0aW9uczogW1xyXG4gICAgICAgICdyZXZpc2lvbnMnLFxyXG4gICAgICAgICdyZXZpc2lvbnMuc3RhdHVzJyxcclxuICAgICAgICAndHlwZScsXHJcbiAgICAgICAgJ3Byb2plY3QnLFxyXG4gICAgICAgICdvcmlnaW5hdG9yJyxcclxuICAgICAgICAncmVjaXBpZW50cycsXHJcbiAgICAgICAgJ3JlY2lwaWVudHMucmVjaXBpZW50T3JnYW5pemF0aW9uJyxcclxuICAgICAgXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghY29ycmVzcG9uZGVuY2UpIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFxyXG4gICAgICAgIGBDb3JyZXNwb25kZW5jZSB3aXRoIFVVSUQgJHtwdWJsaWNJZH0gbm90IGZvdW5kYFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGNvcnJlc3BvbmRlbmNlO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgYWRkUmVmZXJlbmNlKGlkOiBudW1iZXIsIGR0bzogQWRkUmVmZXJlbmNlRHRvKSB7XHJcbiAgICBjb25zdCBzb3VyY2UgPSBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby5maW5kT25lKHsgd2hlcmU6IHsgaWQgfSB9KTtcclxuICAgIC8vIEFEUi0wMTk6IFJlc29sdmUgdGFyZ2V0IHB1YmxpY0lkIOKGkiBpbnRlcm5hbCBJTlQgaWRcclxuICAgIGNvbnN0IHRhcmdldCA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBwdWJsaWNJZDogZHRvLnRhcmdldFV1aWQgfSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghc291cmNlIHx8ICF0YXJnZXQpIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdTb3VyY2Ugb3IgVGFyZ2V0IGNvcnJlc3BvbmRlbmNlIG5vdCBmb3VuZCcpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChzb3VyY2UuaWQgPT09IHRhcmdldC5pZCkge1xyXG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbignQ2Fubm90IHJlZmVyZW5jZSBzZWxmJyk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgZXhpc3RzID0gYXdhaXQgdGhpcy5yZWZlcmVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZToge1xyXG4gICAgICAgIHNvdXJjZUlkOiBpZCxcclxuICAgICAgICB0YXJnZXRJZDogdGFyZ2V0LmlkLFxyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKGV4aXN0cykge1xyXG4gICAgICByZXR1cm4gZXhpc3RzO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHJlZiA9IHRoaXMucmVmZXJlbmNlUmVwby5jcmVhdGUoe1xyXG4gICAgICBzb3VyY2VJZDogaWQsXHJcbiAgICAgIHRhcmdldElkOiB0YXJnZXQuaWQsXHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gdGhpcy5yZWZlcmVuY2VSZXBvLnNhdmUocmVmKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHJlbW92ZVJlZmVyZW5jZShpZDogbnVtYmVyLCB0YXJnZXRJZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJlZmVyZW5jZVJlcG8uZGVsZXRlKHtcclxuICAgICAgc291cmNlSWQ6IGlkLFxyXG4gICAgICB0YXJnZXRJZDogdGFyZ2V0SWQsXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAocmVzdWx0LmFmZmVjdGVkID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignUmVmZXJlbmNlIG5vdCBmb3VuZCcpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgZ2V0VGFncyhpZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCByb3dzID0gYXdhaXQgdGhpcy50YWdSZXBvLmZpbmQoe1xyXG4gICAgICB3aGVyZTogeyBjb3JyZXNwb25kZW5jZUlkOiBpZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFsndGFnJ10sXHJcbiAgICB9KTtcclxuICAgIHJldHVybiByb3dzLm1hcCgocikgPT4gci50YWcpLmZpbHRlcihCb29sZWFuKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGFkZFRhZyhpZDogbnVtYmVyLCB0YWdJZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCBjb3JyZXNwb25kZW5jZSA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIWNvcnJlc3BvbmRlbmNlKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihgQ29ycmVzcG9uZGVuY2UgJHtpZH0gbm90IGZvdW5kYCk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgdGFnID0gYXdhaXQgdGhpcy5kYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZShUYWcsIHtcclxuICAgICAgd2hlcmU6IHsgaWQ6IHRhZ0lkIH0sXHJcbiAgICB9KTtcclxuICAgIGlmICghdGFnKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihgVGFnICR7dGFnSWR9IG5vdCBmb3VuZGApO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGV4aXN0cyA9IGF3YWl0IHRoaXMudGFnUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgY29ycmVzcG9uZGVuY2VJZDogaWQsIHRhZ0lkIH0sXHJcbiAgICB9KTtcclxuICAgIGlmIChleGlzdHMpIHJldHVybiBleGlzdHM7XHJcblxyXG4gICAgY29uc3Qgcm93ID0gdGhpcy50YWdSZXBvLmNyZWF0ZSh7IGNvcnJlc3BvbmRlbmNlSWQ6IGlkLCB0YWdJZCB9KTtcclxuICAgIHJldHVybiB0aGlzLnRhZ1JlcG8uc2F2ZShyb3cpO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgcmVtb3ZlVGFnKGlkOiBudW1iZXIsIHRhZ0lkOiBudW1iZXIpIHtcclxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMudGFnUmVwby5kZWxldGUoeyBjb3JyZXNwb25kZW5jZUlkOiBpZCwgdGFnSWQgfSk7XHJcbiAgICBpZiAocmVzdWx0LmFmZmVjdGVkID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignVGFnIGFzc2lnbm1lbnQgbm90IGZvdW5kJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBnZXRSZWZlcmVuY2VzKGlkOiBudW1iZXIpIHtcclxuICAgIGNvbnN0IG91dGdvaW5nID0gYXdhaXQgdGhpcy5yZWZlcmVuY2VSZXBvLmZpbmQoe1xyXG4gICAgICB3aGVyZTogeyBzb3VyY2VJZDogaWQgfSxcclxuICAgICAgcmVsYXRpb25zOiBbJ3RhcmdldCcsICd0YXJnZXQudHlwZSddLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgaW5jb21pbmcgPSBhd2FpdCB0aGlzLnJlZmVyZW5jZVJlcG8uZmluZCh7XHJcbiAgICAgIHdoZXJlOiB7IHRhcmdldElkOiBpZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFsnc291cmNlJywgJ3NvdXJjZS50eXBlJ10sXHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4geyBvdXRnb2luZywgaW5jb21pbmcgfTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHVwZGF0ZShpZDogbnVtYmVyLCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvLCB1c2VyOiBVc2VyKSB7XHJcbiAgICAvLyAxLiBGaW5kIEN1cnJlbnQgUmV2aXNpb25cclxuICAgIGNvbnN0IHJldmlzaW9uID0gYXdhaXQgdGhpcy5yZXZpc2lvblJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogaWQsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICB9LFxyXG4gICAgICByZWxhdGlvbnM6IFsnY29ycmVzcG9uZGVuY2UnXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghcmV2aXNpb24pIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFxyXG4gICAgICAgIGBDdXJyZW50IHJldmlzaW9uIGZvciBjb3JyZXNwb25kZW5jZSAke2lkfSBub3QgZm91bmRgXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gMi4gQ2hlY2sgUGVybWlzc2lvblxyXG4gICAgaWYgKHJldmlzaW9uLnN0YXR1c0lkKSB7XHJcbiAgICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IHRoaXMuc3RhdHVzUmVwby5maW5kT25lKHtcclxuICAgICAgICB3aGVyZTogeyBpZDogcmV2aXNpb24uc3RhdHVzSWQgfSxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBpZiAoc3RhdHVzICYmIHN0YXR1cy5zdGF0dXNDb2RlICE9PSAnRFJBRlQnKSB7XHJcbiAgICAgICAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyhcclxuICAgICAgICAgIHVzZXIudXNlcl9pZFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgY29uc3QgY2FuRWRpdFN1Ym1pdHRlZE9yTGF0ZXIgPVxyXG4gICAgICAgICAgcGVybWlzc2lvbnMuaW5jbHVkZXMoJ2NvcnJlc3BvbmRlbmNlLmNhbmNlbCcpIHx8XHJcbiAgICAgICAgICBwZXJtaXNzaW9ucy5pbmNsdWRlcygnc3lzdGVtLm1hbmFnZV9hbGwnKTtcclxuXHJcbiAgICAgICAgaWYgKCFjYW5FZGl0U3VibWl0dGVkT3JMYXRlcikge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IEZvcmJpZGRlbkV4Y2VwdGlvbihcclxuICAgICAgICAgICAgJ09ubHkgT3JnIEFkbWluIG9yIFN1cGVyYWRtaW4gY2FuIGVkaXQgbm9uLWRyYWZ0IGNvcnJlc3BvbmRlbmNlcydcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQURSLTAxOTogUmVzb2x2ZSBVVUlEIHJlZmVyZW5jZXMgaW4gdXBkYXRlIERUT1xyXG4gICAgY29uc3QgdXBkUmVzb2x2ZWRQcm9qZWN0SWQgPSB1cGRhdGVEdG8ucHJvamVjdElkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCh1cGRhdGVEdG8ucHJvamVjdElkKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuICAgIGNvbnN0IHVwZFJlc29sdmVkT3JpZ2luYXRvcklkID0gdXBkYXRlRHRvLm9yaWdpbmF0b3JJZFxyXG4gICAgICA/IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZCh1cGRhdGVEdG8ub3JpZ2luYXRvcklkKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuICAgIGNvbnN0IHVwZFJlc29sdmVkUmVjaXBpZW50cyA9IHVwZGF0ZUR0by5yZWNpcGllbnRzXHJcbiAgICAgID8gYXdhaXQgUHJvbWlzZS5hbGwoXHJcbiAgICAgICAgICB1cGRhdGVEdG8ucmVjaXBpZW50cy5tYXAoXHJcbiAgICAgICAgICAgIGFzeW5jIChyKTogUHJvbWlzZTxSZXNvbHZlZFJlY2lwaWVudD4gPT4gKHtcclxuICAgICAgICAgICAgICBvcmdhbml6YXRpb25JZDogYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKFxyXG4gICAgICAgICAgICAgICAgci5vcmdhbml6YXRpb25JZFxyXG4gICAgICAgICAgICAgICksXHJcbiAgICAgICAgICAgICAgdHlwZTogci50eXBlLFxyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICAgKVxyXG4gICAgICAgIClcclxuICAgICAgOiB1bmRlZmluZWQ7XHJcblxyXG4gICAgLy8gMy4gVXBkYXRlIENvcnJlc3BvbmRlbmNlIEVudGl0eSBpZiBuZWVkZWRcclxuICAgIGNvbnN0IGNvcnJlc3BvbmRlbmNlVXBkYXRlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xyXG4gICAgaWYgKHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQpXHJcbiAgICAgIGNvcnJlc3BvbmRlbmNlVXBkYXRlLmRpc2NpcGxpbmVJZCA9IHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQ7XHJcbiAgICBpZiAodXBkUmVzb2x2ZWRQcm9qZWN0SWQpXHJcbiAgICAgIGNvcnJlc3BvbmRlbmNlVXBkYXRlLnByb2plY3RJZCA9IHVwZFJlc29sdmVkUHJvamVjdElkO1xyXG4gICAgaWYgKHVwZFJlc29sdmVkT3JpZ2luYXRvcklkKVxyXG4gICAgICBjb3JyZXNwb25kZW5jZVVwZGF0ZS5vcmlnaW5hdG9ySWQgPSB1cGRSZXNvbHZlZE9yaWdpbmF0b3JJZDtcclxuXHJcbiAgICBpZiAoT2JqZWN0LmtleXMoY29ycmVzcG9uZGVuY2VVcGRhdGUpLmxlbmd0aCA+IDApIHtcclxuICAgICAgYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8udXBkYXRlKGlkLCBjb3JyZXNwb25kZW5jZVVwZGF0ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gNC4gVXBkYXRlIFJldmlzaW9uIEVudGl0eVxyXG4gICAgY29uc3QgcmV2aXNpb25VcGRhdGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XHJcbiAgICBpZiAodXBkYXRlRHRvLnN1YmplY3QpIHJldmlzaW9uVXBkYXRlLnN1YmplY3QgPSB1cGRhdGVEdG8uc3ViamVjdDtcclxuICAgIGlmICh1cGRhdGVEdG8uYm9keSkgcmV2aXNpb25VcGRhdGUuYm9keSA9IHVwZGF0ZUR0by5ib2R5O1xyXG4gICAgaWYgKHVwZGF0ZUR0by5yZW1hcmtzKSByZXZpc2lvblVwZGF0ZS5yZW1hcmtzID0gdXBkYXRlRHRvLnJlbWFya3M7XHJcbiAgICAvLyBGb3JtYXQgRGF0ZSBjb3JyZWN0bHkgaWYgc3RyaW5nXHJcbiAgICBpZiAodXBkYXRlRHRvLmR1ZURhdGUpIHJldmlzaW9uVXBkYXRlLmR1ZURhdGUgPSBuZXcgRGF0ZSh1cGRhdGVEdG8uZHVlRGF0ZSk7XHJcbiAgICBpZiAodXBkYXRlRHRvLmRvY3VtZW50RGF0ZSlcclxuICAgICAgcmV2aXNpb25VcGRhdGUuZG9jdW1lbnREYXRlID0gbmV3IERhdGUodXBkYXRlRHRvLmRvY3VtZW50RGF0ZSk7XHJcbiAgICBpZiAodXBkYXRlRHRvLmlzc3VlZERhdGUpXHJcbiAgICAgIHJldmlzaW9uVXBkYXRlLmlzc3VlZERhdGUgPSBuZXcgRGF0ZSh1cGRhdGVEdG8uaXNzdWVkRGF0ZSk7XHJcbiAgICBpZiAodXBkYXRlRHRvLnJlY2VpdmVkRGF0ZSlcclxuICAgICAgcmV2aXNpb25VcGRhdGUucmVjZWl2ZWREYXRlID0gbmV3IERhdGUodXBkYXRlRHRvLnJlY2VpdmVkRGF0ZSk7XHJcbiAgICBpZiAodXBkYXRlRHRvLmRlc2NyaXB0aW9uKVxyXG4gICAgICByZXZpc2lvblVwZGF0ZS5kZXNjcmlwdGlvbiA9IHVwZGF0ZUR0by5kZXNjcmlwdGlvbjtcclxuICAgIGlmICh1cGRhdGVEdG8uZGV0YWlscykgcmV2aXNpb25VcGRhdGUuZGV0YWlscyA9IHVwZGF0ZUR0by5kZXRhaWxzO1xyXG5cclxuICAgIGlmIChPYmplY3Qua2V5cyhyZXZpc2lvblVwZGF0ZSkubGVuZ3RoID4gMCkge1xyXG4gICAgICBhd2FpdCB0aGlzLnJldmlzaW9uUmVwby51cGRhdGUocmV2aXNpb24uaWQsIHJldmlzaW9uVXBkYXRlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA0LjUgQ29tbWl0IG5ldyBhdHRhY2htZW50cyBmcm9tIFRlbXAg4oaSIFBlcm1hbmVudCAoVHdvLVBoYXNlIFN0b3JhZ2UpXHJcbiAgICBpZiAodXBkYXRlRHRvLmF0dGFjaG1lbnRUZW1wSWRzPy5sZW5ndGgpIHtcclxuICAgICAgY29uc3QgaXNzdWVEYXRlID0gdXBkYXRlRHRvLmlzc3VlZERhdGVcclxuICAgICAgICA/IG5ldyBEYXRlKHVwZGF0ZUR0by5pc3N1ZWREYXRlKVxyXG4gICAgICAgIDogdXBkYXRlRHRvLmRvY3VtZW50RGF0ZVxyXG4gICAgICAgICAgPyBuZXcgRGF0ZSh1cGRhdGVEdG8uZG9jdW1lbnREYXRlKVxyXG4gICAgICAgICAgOiByZXZpc2lvbi5pc3N1ZWREYXRlIHx8IHJldmlzaW9uLmRvY3VtZW50RGF0ZSB8fCB1bmRlZmluZWQ7XHJcblxyXG4gICAgICBhd2FpdCB0aGlzLmZpbGVTdG9yYWdlU2VydmljZS5jb21taXQodXBkYXRlRHRvLmF0dGFjaG1lbnRUZW1wSWRzLCB7XHJcbiAgICAgICAgaXNzdWVEYXRlOiBpc3N1ZURhdGUgPyBuZXcgRGF0ZShpc3N1ZURhdGUpIDogdW5kZWZpbmVkLFxyXG4gICAgICAgIGRvY3VtZW50VHlwZTogJ0NvcnJlc3BvbmRlbmNlJyxcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gNS4gVXBkYXRlIFJlY2lwaWVudHMgaWYgcHJvdmlkZWRcclxuICAgIGlmICh1cGRSZXNvbHZlZFJlY2lwaWVudHMpIHtcclxuICAgICAgY29uc3QgcmVjaXBpZW50UmVwbyA9IHRoaXMuZGF0YVNvdXJjZS5nZXRSZXBvc2l0b3J5KFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmVjaXBpZW50XHJcbiAgICAgICk7XHJcbiAgICAgIGF3YWl0IHJlY2lwaWVudFJlcG8uZGVsZXRlKHsgY29ycmVzcG9uZGVuY2VJZDogaWQgfSk7XHJcblxyXG4gICAgICBjb25zdCBuZXdSZWNpcGllbnRzID0gdXBkUmVzb2x2ZWRSZWNpcGllbnRzLm1hcCgocikgPT5cclxuICAgICAgICByZWNpcGllbnRSZXBvLmNyZWF0ZSh7XHJcbiAgICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiBpZCxcclxuICAgICAgICAgIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiByLm9yZ2FuaXphdGlvbklkLFxyXG4gICAgICAgICAgcmVjaXBpZW50VHlwZTogci50eXBlLFxyXG4gICAgICAgIH0pXHJcbiAgICAgICk7XHJcbiAgICAgIGF3YWl0IHJlY2lwaWVudFJlcG8uc2F2ZShuZXdSZWNpcGllbnRzKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA2LiBSZWdlbmVyYXRlIERvY3VtZW50IE51bWJlciBpZiBzdHJ1Y3R1cmFsIGZpZWxkcyBjaGFuZ2VkIChSZWNpcGllbnQsIERpc2NpcGxpbmUsIFR5cGUsIFByb2plY3QpXHJcbiAgICAvLyBBTkQgaXQgaXMgYSBEUkFGVC5cclxuXHJcbiAgICAvLyBGZXRjaCBmcmVzaCBkYXRhIGZvciBjb250ZXh0IGFuZCBjb21wYXJpc29uXHJcbiAgICBjb25zdCBjdXJyZW50Q29yciA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFsndHlwZScsICdyZWNpcGllbnRzJywgJ3JlY2lwaWVudHMucmVjaXBpZW50T3JnYW5pemF0aW9uJ10sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoY3VycmVudENvcnIpIHtcclxuICAgICAgY29uc3QgY3VycmVudFRvUmVjaXBpZW50ID0gY3VycmVudENvcnIucmVjaXBpZW50cz8uZmluZChcclxuICAgICAgICAocikgPT4gci5yZWNpcGllbnRUeXBlID09PSAnVE8nXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRSZWNpcGllbnRJZCA9IGN1cnJlbnRUb1JlY2lwaWVudD8ucmVjaXBpZW50T3JnYW5pemF0aW9uSWQ7XHJcblxyXG4gICAgICAvLyBDaGVjayBmb3IgQUNUVUFMIHZhbHVlIGNoYW5nZXNcclxuICAgICAgY29uc3QgaXNQcm9qZWN0Q2hhbmdlZCA9XHJcbiAgICAgICAgdXBkUmVzb2x2ZWRQcm9qZWN0SWQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHVwZFJlc29sdmVkUHJvamVjdElkICE9PSBjdXJyZW50Q29yci5wcm9qZWN0SWQ7XHJcbiAgICAgIGNvbnN0IGlzT3JpZ2luYXRvckNoYW5nZWQgPVxyXG4gICAgICAgIHVwZFJlc29sdmVkT3JpZ2luYXRvcklkICE9PSB1bmRlZmluZWQgJiZcclxuICAgICAgICB1cGRSZXNvbHZlZE9yaWdpbmF0b3JJZCAhPT0gY3VycmVudENvcnIub3JpZ2luYXRvcklkO1xyXG4gICAgICBjb25zdCBpc0Rpc2NpcGxpbmVDaGFuZ2VkID1cclxuICAgICAgICB1cGRhdGVEdG8uZGlzY2lwbGluZUlkICE9PSB1bmRlZmluZWQgJiZcclxuICAgICAgICB1cGRhdGVEdG8uZGlzY2lwbGluZUlkICE9PSBjdXJyZW50Q29yci5kaXNjaXBsaW5lSWQ7XHJcbiAgICAgIGNvbnN0IGlzVHlwZUNoYW5nZWQgPVxyXG4gICAgICAgIHVwZGF0ZUR0by50eXBlSWQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHVwZGF0ZUR0by50eXBlSWQgIT09IGN1cnJlbnRDb3JyLmNvcnJlc3BvbmRlbmNlVHlwZUlkO1xyXG5cclxuICAgICAgbGV0IGlzUmVjaXBpZW50Q2hhbmdlZCA9IGZhbHNlO1xyXG4gICAgICBsZXQgbmV3UmVjaXBpZW50SWQ6IG51bWJlciB8IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgIGlmICh1cGRSZXNvbHZlZFJlY2lwaWVudHMpIHtcclxuICAgICAgICBjb25zdCBuZXdUb1JlY2lwaWVudCA9IHVwZFJlc29sdmVkUmVjaXBpZW50cy5maW5kKFxyXG4gICAgICAgICAgKHIpID0+IHIudHlwZSA9PT0gJ1RPJ1xyXG4gICAgICAgICk7XHJcbiAgICAgICAgbmV3UmVjaXBpZW50SWQgPSBuZXdUb1JlY2lwaWVudD8ub3JnYW5pemF0aW9uSWQ7XHJcblxyXG4gICAgICAgIGlmIChuZXdSZWNpcGllbnRJZCAhPT0gY3VycmVudFJlY2lwaWVudElkKSB7XHJcbiAgICAgICAgICBpc1JlY2lwaWVudENoYW5nZWQgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKFxyXG4gICAgICAgIGlzUHJvamVjdENoYW5nZWQgfHxcclxuICAgICAgICBpc0Rpc2NpcGxpbmVDaGFuZ2VkIHx8XHJcbiAgICAgICAgaXNUeXBlQ2hhbmdlZCB8fFxyXG4gICAgICAgIGlzUmVjaXBpZW50Q2hhbmdlZCB8fFxyXG4gICAgICAgIGlzT3JpZ2luYXRvckNoYW5nZWRcclxuICAgICAgKSB7XHJcbiAgICAgICAgY29uc3QgdGFyZ2V0UmVjaXBpZW50SWQgPSBpc1JlY2lwaWVudENoYW5nZWRcclxuICAgICAgICAgID8gbmV3UmVjaXBpZW50SWRcclxuICAgICAgICAgIDogY3VycmVudFJlY2lwaWVudElkO1xyXG5cclxuICAgICAgICAvLyBSZXNvbHZlIFJlY2lwaWVudCBDb2RlIGZvciB0aGUgTkVXIGNvbnRleHRcclxuICAgICAgICBsZXQgcmVjaXBpZW50Q29kZSA9ICcnO1xyXG4gICAgICAgIGlmICh0YXJnZXRSZWNpcGllbnRJZCkge1xyXG4gICAgICAgICAgY29uc3QgcmVjT3JnID0gYXdhaXQgdGhpcy5kYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZShPcmdhbml6YXRpb24sIHtcclxuICAgICAgICAgICAgd2hlcmU6IHsgaWQ6IHRhcmdldFJlY2lwaWVudElkIH0sXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICAgIGlmIChyZWNPcmcpIHJlY2lwaWVudENvZGUgPSByZWNPcmcub3JnYW5pemF0aW9uQ29kZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFtGaXggIzZdIEZldGNoIHJlYWwgT1JHIENvZGUgZnJvbSBvcmlnaW5hdG9yIG9yZ2FuaXphdGlvblxyXG4gICAgICAgIGNvbnN0IG9yaWdpbmF0b3JPcmdGb3JVcGRhdGUgPSBhd2FpdCB0aGlzLmRhdGFTb3VyY2UubWFuYWdlci5maW5kT25lKFxyXG4gICAgICAgICAgT3JnYW5pemF0aW9uLFxyXG4gICAgICAgICAge1xyXG4gICAgICAgICAgICB3aGVyZToge1xyXG4gICAgICAgICAgICAgIGlkOiB1cGRSZXNvbHZlZE9yaWdpbmF0b3JJZCA/PyBjdXJyZW50Q29yci5vcmlnaW5hdG9ySWQgPz8gMCxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgIH1cclxuICAgICAgICApO1xyXG4gICAgICAgIGNvbnN0IG9yZ0NvZGUgPSBvcmlnaW5hdG9yT3JnRm9yVXBkYXRlPy5vcmdhbml6YXRpb25Db2RlID8/ICdVTksnO1xyXG5cclxuICAgICAgICAvLyBQcmVwYXJlIENvbnRleHRzXHJcbiAgICAgICAgY29uc3Qgb2xkQ3R4ID0ge1xyXG4gICAgICAgICAgcHJvamVjdElkOiBjdXJyZW50Q29yci5wcm9qZWN0SWQsXHJcbiAgICAgICAgICBvcmlnaW5hdG9yT3JnYW5pemF0aW9uSWQ6IGN1cnJlbnRDb3JyLm9yaWdpbmF0b3JJZCA/PyAwLFxyXG4gICAgICAgICAgdHlwZUlkOiBjdXJyZW50Q29yci5jb3JyZXNwb25kZW5jZVR5cGVJZCxcclxuICAgICAgICAgIGRpc2NpcGxpbmVJZDogY3VycmVudENvcnIuZGlzY2lwbGluZUlkLFxyXG4gICAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IGN1cnJlbnRSZWNpcGllbnRJZCxcclxuICAgICAgICAgIHllYXI6IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKSxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBuZXdDdHggPSB7XHJcbiAgICAgICAgICBwcm9qZWN0SWQ6IHVwZFJlc29sdmVkUHJvamVjdElkID8/IGN1cnJlbnRDb3JyLnByb2plY3RJZCxcclxuICAgICAgICAgIG9yaWdpbmF0b3JPcmdhbml6YXRpb25JZDpcclxuICAgICAgICAgICAgdXBkUmVzb2x2ZWRPcmlnaW5hdG9ySWQgPz8gY3VycmVudENvcnIub3JpZ2luYXRvcklkID8/IDAsXHJcbiAgICAgICAgICB0eXBlSWQ6IHVwZGF0ZUR0by50eXBlSWQgPz8gY3VycmVudENvcnIuY29ycmVzcG9uZGVuY2VUeXBlSWQsXHJcbiAgICAgICAgICBkaXNjaXBsaW5lSWQ6IHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQgPz8gY3VycmVudENvcnIuZGlzY2lwbGluZUlkLFxyXG4gICAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IHRhcmdldFJlY2lwaWVudElkLFxyXG4gICAgICAgICAgeWVhcjogbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpLFxyXG4gICAgICAgICAgdXNlcklkOiB1c2VyLnVzZXJfaWQsIC8vIFBhc3MgVXNlciBJRCBmb3IgQXVkaXRcclxuICAgICAgICAgIGN1c3RvbVRva2Vuczoge1xyXG4gICAgICAgICAgICBUWVBFX0NPREU6IGN1cnJlbnRDb3JyLnR5cGU/LnR5cGVDb2RlIHx8ICcnLFxyXG4gICAgICAgICAgICBPUkdfQ09ERTogb3JnQ29kZSxcclxuICAgICAgICAgICAgUkVDSVBJRU5UX0NPREU6IHJlY2lwaWVudENvZGUsXHJcbiAgICAgICAgICAgIFJFQ19DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvLyBJZiBUeXBlIENoYW5nZWQsIG5lZWQgTkVXIFR5cGUgQ29kZVxyXG4gICAgICAgIGlmIChpc1R5cGVDaGFuZ2VkKSB7XHJcbiAgICAgICAgICBjb25zdCBuZXdUeXBlID0gYXdhaXQgdGhpcy50eXBlUmVwby5maW5kT25lKHtcclxuICAgICAgICAgICAgd2hlcmU6IHsgaWQ6IG5ld0N0eC50eXBlSWQgfSxcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgaWYgKG5ld1R5cGUpIG5ld0N0eC5jdXN0b21Ub2tlbnMuVFlQRV9DT0RFID0gbmV3VHlwZS50eXBlQ29kZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld0RvY051bWJlciA9IGF3YWl0IHRoaXMubnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdChcclxuICAgICAgICAgIGN1cnJlbnRDb3JyLmNvcnJlc3BvbmRlbmNlTnVtYmVyLFxyXG4gICAgICAgICAgb2xkQ3R4LFxyXG4gICAgICAgICAgbmV3Q3R4XHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8udXBkYXRlKGlkLCB7XHJcbiAgICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogbmV3RG9jTnVtYmVyLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgdXBkYXRlZCA9IGF3YWl0IHRoaXMuZmluZE9uZShpZCk7XHJcblxyXG4gICAgLy8gUmUtaW5kZXggdXBkYXRlZCBkb2N1bWVudCBpbiBFbGFzdGljc2VhcmNoIChmaXJlLWFuZC1mb3JnZXQpXHJcbiAgICB2b2lkIHRoaXMuc2VhcmNoU2VydmljZS5pbmRleERvY3VtZW50KHtcclxuICAgICAgaWQ6IHVwZGF0ZWQuaWQsXHJcbiAgICAgIHB1YmxpY0lkOiB1cGRhdGVkLnB1YmxpY0lkLFxyXG4gICAgICB0eXBlOiAnY29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICBkb2NOdW1iZXI6IHVwZGF0ZWQuY29ycmVzcG9uZGVuY2VOdW1iZXIsXHJcbiAgICAgIHRpdGxlOiB1cGRhdGVEdG8uc3ViamVjdCA/PyB1cGRhdGVkLnJldmlzaW9ucz8uWzBdPy5zdWJqZWN0LFxyXG4gICAgICBkZXNjcmlwdGlvbjogdXBkYXRlRHRvLmRlc2NyaXB0aW9uID8/IHVwZGF0ZWQucmV2aXNpb25zPy5bMF0/LmRlc2NyaXB0aW9uLFxyXG4gICAgICBzdGF0dXM6ICdEUkFGVCcsXHJcbiAgICAgIHByb2plY3RJZDogdXBkYXRlZC5wcm9qZWN0SWQsXHJcbiAgICAgIGNyZWF0ZWRBdDogdXBkYXRlZC5jcmVhdGVkQXQsXHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gdXBkYXRlZDtcclxuICB9XHJcblxyXG4gIGFzeW5jIHByZXZpZXdEb2N1bWVudE51bWJlcihjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvLCB1c2VyOiBVc2VyKSB7XHJcbiAgICAvLyBBRFItMDE5OiBSZXNvbHZlIFVVSUQgcmVmZXJlbmNlc1xyXG4gICAgY29uc3QgcHJldmlld1Byb2plY3RJZCA9IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQoXHJcbiAgICAgIGNyZWF0ZUR0by5wcm9qZWN0SWRcclxuICAgICk7XHJcbiAgICBjb25zdCBwcmV2aWV3T3JpZ2luYXRvcklkID0gY3JlYXRlRHRvLm9yaWdpbmF0b3JJZFxyXG4gICAgICA/IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChjcmVhdGVEdG8ub3JpZ2luYXRvcklkKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuICAgIGNvbnN0IHByZXZpZXdSZWNpcGllbnRzID0gY3JlYXRlRHRvLnJlY2lwaWVudHNcclxuICAgICAgPyBhd2FpdCBQcm9taXNlLmFsbChcclxuICAgICAgICAgIGNyZWF0ZUR0by5yZWNpcGllbnRzLm1hcChcclxuICAgICAgICAgICAgYXN5bmMgKHIpOiBQcm9taXNlPFJlc29sdmVkUmVjaXBpZW50PiA9PiAoe1xyXG4gICAgICAgICAgICAgIG9yZ2FuaXphdGlvbklkOiBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoXHJcbiAgICAgICAgICAgICAgICByLm9yZ2FuaXphdGlvbklkXHJcbiAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICB0eXBlOiByLnR5cGUsXHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICApXHJcbiAgICAgICAgKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuXHJcbiAgICBjb25zdCB0eXBlID0gYXdhaXQgdGhpcy50eXBlUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgaWQ6IGNyZWF0ZUR0by50eXBlSWQgfSxcclxuICAgIH0pO1xyXG4gICAgaWYgKCF0eXBlKSB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oJ0RvY3VtZW50IFR5cGUgbm90IGZvdW5kJyk7XHJcblxyXG4gICAgbGV0IHVzZXJPcmdJZCA9IHVzZXIucHJpbWFyeU9yZ2FuaXphdGlvbklkO1xyXG4gICAgaWYgKCF1c2VyT3JnSWQpIHtcclxuICAgICAgY29uc3QgZnVsbFVzZXIgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmZpbmRPbmUodXNlci51c2VyX2lkKTtcclxuICAgICAgaWYgKGZ1bGxVc2VyKSB1c2VyT3JnSWQgPSBmdWxsVXNlci5wcmltYXJ5T3JnYW5pemF0aW9uSWQ7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHByZXZpZXdPcmlnaW5hdG9ySWQgJiYgcHJldmlld09yaWdpbmF0b3JJZCAhPT0gdXNlck9yZ0lkKSB7XHJcbiAgICAgIC8vIEFsbG93IGltcGVyc29uYXRpb24gZm9yIHByZXZpZXdcclxuICAgICAgdXNlck9yZ0lkID0gcHJldmlld09yaWdpbmF0b3JJZDtcclxuICAgIH1cclxuXHJcbiAgICAvLyBFeHRyYWN0IHJlY2lwaWVudCBmcm9tIHJlY2lwaWVudHMgYXJyYXlcclxuICAgIGNvbnN0IHRvUmVjaXBpZW50ID0gcHJldmlld1JlY2lwaWVudHM/LmZpbmQoKHIpID0+IHIudHlwZSA9PT0gJ1RPJyk7XHJcbiAgICBjb25zdCByZWNpcGllbnRPcmdhbml6YXRpb25JZCA9IHRvUmVjaXBpZW50Py5vcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICBsZXQgcmVjaXBpZW50Q29kZSA9ICcnO1xyXG4gICAgaWYgKHJlY2lwaWVudE9yZ2FuaXphdGlvbklkKSB7XHJcbiAgICAgIGNvbnN0IHJlY09yZyA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoT3JnYW5pemF0aW9uLCB7XHJcbiAgICAgICAgd2hlcmU6IHsgaWQ6IHJlY2lwaWVudE9yZ2FuaXphdGlvbklkIH0sXHJcbiAgICAgIH0pO1xyXG4gICAgICBpZiAocmVjT3JnKSByZWNpcGllbnRDb2RlID0gcmVjT3JnLm9yZ2FuaXphdGlvbkNvZGU7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMubnVtYmVyaW5nU2VydmljZS5wcmV2aWV3TnVtYmVyKHtcclxuICAgICAgcHJvamVjdElkOiBwcmV2aWV3UHJvamVjdElkLFxyXG4gICAgICBvcmlnaW5hdG9yT3JnYW5pemF0aW9uSWQ6IHVzZXJPcmdJZCEsXHJcbiAgICAgIHR5cGVJZDogY3JlYXRlRHRvLnR5cGVJZCxcclxuICAgICAgZGlzY2lwbGluZUlkOiBjcmVhdGVEdG8uZGlzY2lwbGluZUlkLFxyXG4gICAgICBzdWJUeXBlSWQ6IGNyZWF0ZUR0by5zdWJUeXBlSWQsXHJcbiAgICAgIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkLFxyXG4gICAgICB5ZWFyOiBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCksXHJcbiAgICAgIGN1c3RvbVRva2Vuczoge1xyXG4gICAgICAgIFRZUEVfQ09ERTogdHlwZS50eXBlQ29kZSxcclxuICAgICAgICBSRUNJUElFTlRfQ09ERTogcmVjaXBpZW50Q29kZSxcclxuICAgICAgICBSRUNfQ09ERTogcmVjaXBpZW50Q29kZSxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQnVzaW5lc3MgUnVsZSBJbXBsZW1lbnRhdGlvbjogRUMtQ09SUi0wMDEgLSBDYW5jZWwgQ29ycmVzcG9uZGVuY2Ugd2l0aCBEb3duc3RyZWFtIENpcmN1bGF0aW9uXHJcbiAgICogQ2FuY2VsIGNvcnJlc3BvbmRlbmNlIGFuZCBoYW5kbGUgcmVsYXRlZCBjaXJjdWxhdGlvbnNcclxuICAgKi9cclxuICBhc3luYyBjYW5jZWwocHVibGljSWQ6IHN0cmluZywgcmVhc29uOiBzdHJpbmcsIHVzZXI6IFVzZXIpIHtcclxuICAgIGNvbnN0IGNvcnJlc3BvbmRlbmNlID0gYXdhaXQgdGhpcy5maW5kT25lQnlVdWlkKHB1YmxpY0lkKTtcclxuXHJcbiAgICAvLyBDaGVjayBpZiB1c2VyIGhhcyBwZXJtaXNzaW9uIHRvIGNhbmNlbCAoT3JnIEFkbWluIG9yIFN1cGVyYWRtaW4gb25seSlcclxuICAgIGNvbnN0IHBlcm1pc3Npb25zID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS5nZXRVc2VyUGVybWlzc2lvbnModXNlci51c2VyX2lkKTtcclxuICAgIGNvbnN0IGNhbkNhbmNlbCA9XHJcbiAgICAgIHBlcm1pc3Npb25zLmluY2x1ZGVzKCdjb3JyZXNwb25kZW5jZS5jYW5jZWwnKSB8fFxyXG4gICAgICBwZXJtaXNzaW9ucy5pbmNsdWRlcygnc3lzdGVtLm1hbmFnZV9hbGwnKTtcclxuXHJcbiAgICBpZiAoIWNhbkNhbmNlbCkge1xyXG4gICAgICB0aHJvdyBuZXcgRm9yYmlkZGVuRXhjZXB0aW9uKFxyXG4gICAgICAgICdPbmx5IGFkbWluaXN0cmF0b3JzIGNhbiBjYW5jZWwgY29ycmVzcG9uZGVuY2VzJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENoZWNrIGlmIHRoZXJlIGFyZSBhbnkgYWN0aXZlIGNpcmN1bGF0aW9uc1xyXG4gICAgY29uc3QgY2lyY3VsYXRpb25SZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkoJ0NpcmN1bGF0aW9uJyk7XHJcbiAgICBjb25zdCBhY3RpdmVDaXJjdWxhdGlvbnMgPSBhd2FpdCBjaXJjdWxhdGlvblJlcG8uZmluZCh7XHJcbiAgICAgIHdoZXJlOiB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogY29ycmVzcG9uZGVuY2UuaWQsXHJcbiAgICAgICAgc3RhdHVzOiAnT1BFTicsXHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCB3YXJuaW5nTWVzc2FnZSA9XHJcbiAgICAgIGFjdGl2ZUNpcmN1bGF0aW9ucy5sZW5ndGggPiAwXHJcbiAgICAgICAgPyBgVGhlcmUgYXJlICR7YWN0aXZlQ2lyY3VsYXRpb25zLmxlbmd0aH0gYWN0aXZlIGNpcmN1bGF0aW9uKHMpIGZvciB0aGlzIGNvcnJlc3BvbmRlbmNlLiBDYW5jZWxpbmcgd2lsbCBmb3JjZSBjbG9zZSBhbGwgcmVsYXRlZCBjaXJjdWxhdGlvbnMuYFxyXG4gICAgICAgIDogJyc7XHJcblxyXG4gICAgLy8gR2V0IHRoZSBjdXJyZW50IHJldmlzaW9uIHRvIHVwZGF0ZSBzdGF0dXNcclxuICAgIGNvbnN0IGN1cnJlbnRSZXZpc2lvbiA9IGF3YWl0IHRoaXMucmV2aXNpb25SZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZToge1xyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IGNvcnJlc3BvbmRlbmNlLmlkLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghY3VycmVudFJldmlzaW9uKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignQ3VycmVudCByZXZpc2lvbiBub3QgZm91bmQnKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBHZXQgY2FuY2VsbGVkIHN0YXR1c1xyXG4gICAgY29uc3QgY2FuY2VsbGVkU3RhdHVzID0gYXdhaXQgdGhpcy5zdGF0dXNSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBzdGF0dXNDb2RlOiAnQ0FOQ0VMTEVEJyB9LFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKCFjYW5jZWxsZWRTdGF0dXMpIHtcclxuICAgICAgdGhyb3cgbmV3IEludGVybmFsU2VydmVyRXJyb3JFeGNlcHRpb24oJ0NBTkNFTExFRCBzdGF0dXMgbm90IGZvdW5kJyk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgcXVlcnlSdW5uZXIgPSB0aGlzLmRhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIoKTtcclxuICAgIGF3YWl0IHF1ZXJ5UnVubmVyLmNvbm5lY3QoKTtcclxuICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnN0YXJ0VHJhbnNhY3Rpb24oKTtcclxuXHJcbiAgICB0cnkge1xyXG4gICAgICAvLyBVcGRhdGUgY29ycmVzcG9uZGVuY2UgcmV2aXNpb24gc3RhdHVzIHRvIENBTkNFTExFRFxyXG4gICAgICBhd2FpdCBxdWVyeVJ1bm5lci5tYW5hZ2VyLnVwZGF0ZShcclxuICAgICAgICBDb3JyZXNwb25kZW5jZVJldmlzaW9uLFxyXG4gICAgICAgIGN1cnJlbnRSZXZpc2lvbi5pZCxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBzdGF0dXNJZDogY2FuY2VsbGVkU3RhdHVzLmlkLFxyXG4gICAgICAgICAgcmVtYXJrczogYENhbmNlbGxlZDogJHtyZWFzb259YCxcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcblxyXG4gICAgICAvLyBGb3JjZSBjbG9zZSBhbGwgYWN0aXZlIGNpcmN1bGF0aW9uc1xyXG4gICAgICBpZiAoYWN0aXZlQ2lyY3VsYXRpb25zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBhd2FpdCBxdWVyeVJ1bm5lci5tYW5hZ2VyLnVwZGF0ZShcclxuICAgICAgICAgICdDaXJjdWxhdGlvbicsXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IGNvcnJlc3BvbmRlbmNlLmlkLFxyXG4gICAgICAgICAgICBzdGF0dXM6ICdPUEVOJyxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHN0YXR1czogJ0ZPUkNFX0NMT1NFRCcsXHJcbiAgICAgICAgICAgIGNsb3NlZEF0OiBuZXcgRGF0ZSgpLFxyXG4gICAgICAgICAgICBjbG9zZWRCeTogdXNlci51c2VyX2lkLFxyXG4gICAgICAgICAgICBjbG9zZVJlYXNvbjogYENvcnJlc3BvbmRlbmNlIGNhbmNlbGxlZDogJHtyZWFzb259YCxcclxuICAgICAgICAgIH1cclxuICAgICAgICApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBhd2FpdCBxdWVyeVJ1bm5lci5jb21taXRUcmFuc2FjdGlvbigpO1xyXG5cclxuICAgICAgLy8gUmUtaW5kZXggY2FuY2VsbGVkIHN0YXR1cyBpbiBFbGFzdGljc2VhcmNoIChmaXJlLWFuZC1mb3JnZXQpXHJcbiAgICAgIHZvaWQgdGhpcy5zZWFyY2hTZXJ2aWNlLmluZGV4RG9jdW1lbnQoe1xyXG4gICAgICAgIGlkOiBjb3JyZXNwb25kZW5jZS5pZCxcclxuICAgICAgICBwdWJsaWNJZDogY29ycmVzcG9uZGVuY2UucHVibGljSWQsXHJcbiAgICAgICAgdHlwZTogJ2NvcnJlc3BvbmRlbmNlJyxcclxuICAgICAgICBkb2NOdW1iZXI6IGNvcnJlc3BvbmRlbmNlLmNvcnJlc3BvbmRlbmNlTnVtYmVyLFxyXG4gICAgICAgIHRpdGxlOiBjdXJyZW50UmV2aXNpb24uc3ViamVjdCxcclxuICAgICAgICBzdGF0dXM6ICdDQU5DRUxMRUQnLFxyXG4gICAgICAgIHByb2plY3RJZDogY29ycmVzcG9uZGVuY2UucHJvamVjdElkLFxyXG4gICAgICAgIGNyZWF0ZWRBdDogY29ycmVzcG9uZGVuY2UuY3JlYXRlZEF0LFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vIE5vdGlmeSBvcmlnaW5hdG9yJ3MgZG9jLWNvbnRyb2wgdXNlciBhYm91dCBjYW5jZWxsYXRpb24gKGZpcmUtYW5kLWZvcmdldClcclxuICAgICAgaWYgKGNvcnJlc3BvbmRlbmNlLm9yaWdpbmF0b3JJZCkge1xyXG4gICAgICAgIHZvaWQgdGhpcy51c2VyU2VydmljZVxyXG4gICAgICAgICAgLmZpbmREb2NDb250cm9sSWRCeU9yZyhjb3JyZXNwb25kZW5jZS5vcmlnaW5hdG9ySWQpXHJcbiAgICAgICAgICAudGhlbigodGFyZ2V0VXNlcklkKSA9PiB7XHJcbiAgICAgICAgICAgIGlmICh0YXJnZXRVc2VySWQpIHtcclxuICAgICAgICAgICAgICB2b2lkIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5zZW5kKHtcclxuICAgICAgICAgICAgICAgIHVzZXJJZDogdGFyZ2V0VXNlcklkLFxyXG4gICAgICAgICAgICAgICAgdGl0bGU6ICdDb3JyZXNwb25kZW5jZSBDYW5jZWxsZWQnLFxyXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYCR7Y29ycmVzcG9uZGVuY2UuY29ycmVzcG9uZGVuY2VOdW1iZXJ9IOKAlCAke2N1cnJlbnRSZXZpc2lvbi5zdWJqZWN0fSBoYXMgYmVlbiBjYW5jZWxsZWQuIFJlYXNvbjogJHtyZWFzb259YCxcclxuICAgICAgICAgICAgICAgIHR5cGU6ICdFTUFJTCcsXHJcbiAgICAgICAgICAgICAgICBlbnRpdHlUeXBlOiAnY29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICAgICAgICAgICAgZW50aXR5SWQ6IGNvcnJlc3BvbmRlbmNlLmlkLFxyXG4gICAgICAgICAgICAgICAgbGluazogYC9jb3JyZXNwb25kZW5jZXMvJHtjb3JyZXNwb25kZW5jZS5wdWJsaWNJZH1gLFxyXG4gICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KVxyXG4gICAgICAgICAgLmNhdGNoKChlcnI6IEVycm9yKSA9PlxyXG4gICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKGBDYW5jZWwgbm90aWZpY2F0aW9uIGZhaWxlZDogJHtlcnIubWVzc2FnZX1gKVxyXG4gICAgICAgICAgKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBzdWNjZXNzOiB0cnVlLFxyXG4gICAgICAgIG1lc3NhZ2U6IHdhcm5pbmdNZXNzYWdlIHx8ICdDb3JyZXNwb25kZW5jZSBjYW5jZWxsZWQgc3VjY2Vzc2Z1bGx5JyxcclxuICAgICAgICBhY3RpdmVDaXJjdWxhdGlvbnNDb3VudDogYWN0aXZlQ2lyY3VsYXRpb25zLmxlbmd0aCxcclxuICAgICAgfTtcclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJvbGxiYWNrVHJhbnNhY3Rpb24oKTtcclxuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXHJcbiAgICAgICAgYEZhaWxlZCB0byBjYW5jZWwgY29ycmVzcG9uZGVuY2U6ICR7KGVycm9yIGFzIEVycm9yKS5tZXNzYWdlfWBcclxuICAgICAgKTtcclxuICAgICAgdGhyb3cgZXJyb3I7XHJcbiAgICB9IGZpbmFsbHkge1xyXG4gICAgICBhd2FpdCBxdWVyeVJ1bm5lci5yZWxlYXNlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBidWxrQ2FuY2VsKFxyXG4gICAgcHVibGljSWRzOiBzdHJpbmdbXSxcclxuICAgIHJlYXNvbjogc3RyaW5nLFxyXG4gICAgdXNlcjogVXNlclxyXG4gICk6IFByb21pc2U8eyBzdWNjZWVkZWQ6IHN0cmluZ1tdOyBmYWlsZWQ6IHN0cmluZ1tdIH0+IHtcclxuICAgIGNvbnN0IHN1Y2NlZWRlZDogc3RyaW5nW10gPSBbXTtcclxuICAgIGNvbnN0IGZhaWxlZDogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IHB1YmxpY0lkIG9mIHB1YmxpY0lkcykge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGF3YWl0IHRoaXMuY2FuY2VsKHB1YmxpY0lkLCByZWFzb24sIHVzZXIpO1xyXG4gICAgICAgIHN1Y2NlZWRlZC5wdXNoKHB1YmxpY0lkKTtcclxuICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgZmFpbGVkLnB1c2gocHVibGljSWQpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHsgc3VjY2VlZGVkLCBmYWlsZWQgfTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGV4cG9ydENzdihzZWFyY2hEdG86IFNlYXJjaENvcnJlc3BvbmRlbmNlRHRvKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuICAgIGNvbnN0IHsgZGF0YSB9ID0gYXdhaXQgdGhpcy5maW5kQWxsKHNlYXJjaER0byk7XHJcblxyXG4gICAgY29uc3QgaGVhZGVyID0gW1xyXG4gICAgICAnRG9jdW1lbnQgTm8uJyxcclxuICAgICAgJ1JldicsXHJcbiAgICAgICdTdWJqZWN0JyxcclxuICAgICAgJ1R5cGUnLFxyXG4gICAgICAnU3RhdHVzJyxcclxuICAgICAgJ1Byb2plY3QnLFxyXG4gICAgICAnRnJvbScsXHJcbiAgICAgICdEdWUgRGF0ZScsXHJcbiAgICAgICdDcmVhdGVkIEF0JyxcclxuICAgIF07XHJcbiAgICBjb25zdCByb3dzID0gZGF0YS5tYXAoKHJldikgPT4ge1xyXG4gICAgICBjb25zdCBjb3JyID0gcmV2LmNvcnJlc3BvbmRlbmNlID8/IChyZXYgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcbiAgICAgIHJldHVybiBbXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YoY29yci5jb3JyZXNwb25kZW5jZU51bWJlciA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YocmV2LnJldmlzaW9uTGFiZWwgPz8gU3RyaW5nKHJldi5yZXZpc2lvbk51bWJlciA/PyAwKSksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YocmV2LnN1YmplY3QgPz8gJycpLFxyXG4gICAgICAgIHRoaXMuZXNjYXBlQ3N2KGNvcnIudHlwZT8udHlwZUNvZGUgPz8gJycpLFxyXG4gICAgICAgIHRoaXMuZXNjYXBlQ3N2KHJldi5zdGF0dXM/LnN0YXR1c0NvZGUgPz8gJycpLFxyXG4gICAgICAgIHRoaXMuZXNjYXBlQ3N2KGNvcnIucHJvamVjdD8ucHJvamVjdENvZGUgPz8gJycpLFxyXG4gICAgICAgIHRoaXMuZXNjYXBlQ3N2KGNvcnIub3JpZ2luYXRvcj8ub3JnYW5pemF0aW9uQ29kZSA/PyAnJyksXHJcbiAgICAgICAgcmV2LmR1ZURhdGUgPyBuZXcgRGF0ZShyZXYuZHVlRGF0ZSkudG9JU09TdHJpbmcoKS5zcGxpdCgnVCcpWzBdIDogJycsXHJcbiAgICAgICAgbmV3IERhdGUocmV2LmNyZWF0ZWRBdCkudG9JU09TdHJpbmcoKS5zcGxpdCgnVCcpWzBdLFxyXG4gICAgICBdLmpvaW4oJywnKTtcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiBbaGVhZGVyLmpvaW4oJywnKSwgLi4ucm93c10uam9pbignXFxuJyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGVzY2FwZUNzdih2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGlmICh2YWx1ZS5pbmNsdWRlcygnLCcpIHx8IHZhbHVlLmluY2x1ZGVzKCdcIicpIHx8IHZhbHVlLmluY2x1ZGVzKCdcXG4nKSkge1xyXG4gICAgICByZXR1cm4gYFwiJHt2YWx1ZS5yZXBsYWNlKC9cIi9nLCAnXCJcIicpfVwiYDtcclxuICAgIH1cclxuICAgIHJldHVybiB2YWx1ZTtcclxuICB9XHJcbn1cclxuIl0sInZlcnNpb24iOjN9 \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/e4/correspondenceservice_e4765c13e5e659b2418e3700423a4d1e.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/e4/correspondenceservice_e4765c13e5e659b2418e3700423a4d1e.map new file mode 100644 index 0000000..aca1ac8 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/e4/correspondenceservice_e4765c13e5e659b2418e3700423a4d1e.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.ts"],"sourcesContent":["// File: src/modules/correspondence/correspondence.service.ts\r\n\r\nimport {\r\n Injectable,\r\n NotFoundException,\r\n BadRequestException,\r\n InternalServerErrorException,\r\n ForbiddenException,\r\n Logger,\r\n} from '@nestjs/common';\r\nimport { InjectRepository } from '@nestjs/typeorm';\r\nimport { Repository, DataSource } from 'typeorm';\r\n\r\n// Entities\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Tag } from '../master/entities/tag.entity';\r\nimport { User } from '../user/entities/user.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\n\r\n// DTOs\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { AddReferenceDto } from './dto/add-reference.dto';\r\nimport { SearchCorrespondenceDto } from './dto/search-correspondence.dto';\r\n\r\n// Services\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\n\r\n/**\r\n * CorrespondenceService - Document management (CRUD)\r\n */\r\ninterface ResolvedRecipient {\r\n organizationId: number;\r\n type: 'TO' | 'CC';\r\n}\r\n@Injectable()\r\nexport class CorrespondenceService {\r\n private readonly logger = new Logger(CorrespondenceService.name);\r\n\r\n private async hasSystemManageAllPermission(userId: number): Promise {\r\n const permissions = await this.userService.getUserPermissions(userId);\r\n return permissions.includes('system.manage_all');\r\n }\r\n\r\n /**\r\n * Business Rule: Revision Label Strategy\r\n * - RFA, RFI: Use alphabet starting with 'A' (A, B, C...)\r\n * - Other types (LETTER, MEMO, etc.): Use numeric (null for first, then 1, 2, 3...)\r\n */\r\n private getInitialRevisionLabel(typeCode: string): string | undefined {\r\n const alphabetTypes = ['RFA', 'RFI'];\r\n if (alphabetTypes.includes(typeCode.toUpperCase())) {\r\n return 'A'; // Alphabet for RFA, RFI\r\n }\r\n return undefined; // Numeric (no label for revision 0)\r\n }\r\n\r\n constructor(\r\n @InjectRepository(Correspondence)\r\n private correspondenceRepo: Repository,\r\n @InjectRepository(CorrespondenceRevision)\r\n private revisionRepo: Repository,\r\n @InjectRepository(CorrespondenceType)\r\n private typeRepo: Repository,\r\n @InjectRepository(CorrespondenceStatus)\r\n private statusRepo: Repository,\r\n @InjectRepository(CorrespondenceReference)\r\n private referenceRepo: Repository,\r\n @InjectRepository(CorrespondenceTag)\r\n private tagRepo: Repository,\r\n private numberingService: DocumentNumberingService,\r\n private jsonSchemaService: JsonSchemaService,\r\n private workflowEngine: WorkflowEngineService,\r\n private userService: UserService,\r\n private dataSource: DataSource,\r\n private searchService: SearchService,\r\n private fileStorageService: FileStorageService,\r\n private uuidResolver: UuidResolverService,\r\n private notificationService: NotificationService\r\n ) {}\r\n\r\n /**\r\n * Business Rule Validation: EC-CORR-003 - Correspondence to Self\r\n * Prevent external correspondence to same organization\r\n */\r\n private async validateCorrespondenceRecipients(\r\n createDto: CreateCorrespondenceDto,\r\n user: User\r\n ): Promise {\r\n // Get user's organization\r\n let userOrgId = user.primaryOrganizationId;\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) {\r\n userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n }\r\n\r\n if (!userOrgId) {\r\n if (createDto.originatorId) {\r\n const canManageAll = await this.hasSystemManageAllPermission(\r\n user.user_id\r\n );\r\n if (canManageAll) {\r\n userOrgId = await this.uuidResolver.resolveOrganizationId(\r\n createDto.originatorId\r\n );\r\n }\r\n }\r\n\r\n if (!userOrgId) {\r\n throw new BadRequestException(\r\n 'User must belong to an organization to create documents'\r\n );\r\n }\r\n }\r\n\r\n // For impersonation, use the specified originator\r\n const originatorOrgId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : userOrgId;\r\n\r\n // Check if it's internal communication\r\n if (createDto.isInternal) {\r\n // Internal communications should use Circulation instead\r\n throw new BadRequestException(\r\n 'Internal communications should use Circulation Sheet instead of Correspondence'\r\n );\r\n }\r\n\r\n // Validate recipients\r\n if (!createDto.recipients || createDto.recipients.length === 0) {\r\n throw new BadRequestException(\r\n 'At least one recipient (TO or CC) is required'\r\n );\r\n }\r\n\r\n const toRecipients = createDto.recipients.filter((r) => r.type === 'TO');\r\n const ccRecipients = createDto.recipients.filter((r) => r.type === 'CC');\r\n\r\n if (toRecipients.length === 0 && ccRecipients.length === 0) {\r\n throw new BadRequestException(\r\n 'At least one TO or CC recipient is required'\r\n );\r\n }\r\n\r\n // Check for same organization correspondence\r\n for (const recipient of createDto.recipients) {\r\n const recipientOrgId = await this.uuidResolver.resolveOrganizationId(\r\n recipient.organizationId\r\n );\r\n\r\n if (recipientOrgId === originatorOrgId) {\r\n throw new BadRequestException(\r\n 'Cannot send correspondence to your own organization. Use Circulation Sheet for internal communication.'\r\n );\r\n }\r\n }\r\n }\r\n\r\n async create(createDto: CreateCorrespondenceDto, user: User) {\r\n // Business Rule Validation: EC-CORR-003 - Correspondence to Self\r\n await this.validateCorrespondenceRecipients(createDto, user);\r\n // ADR-019: Resolve UUID references to internal INT IDs\r\n const resolvedProjectId = await this.uuidResolver.resolveProjectId(\r\n createDto.projectId\r\n );\r\n const resolvedOriginatorId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : undefined;\r\n const resolvedRecipients = createDto.recipients\r\n ? await Promise.all(\r\n createDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n const type = await this.typeRepo.findOne({\r\n where: { id: createDto.typeId },\r\n });\r\n if (!type) throw new NotFoundException('Document Type not found');\r\n\r\n const statusDraft = await this.statusRepo.findOne({\r\n where: { statusCode: 'DRAFT' },\r\n });\r\n if (!statusDraft) {\r\n throw new InternalServerErrorException(\r\n 'Status DRAFT not found in Master Data'\r\n );\r\n }\r\n\r\n let userOrgId = user.primaryOrganizationId;\r\n\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) {\r\n userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n }\r\n\r\n // Impersonation Logic\r\n if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {\r\n const canManageAll = await this.hasSystemManageAllPermission(\r\n user.user_id\r\n );\r\n if (!canManageAll) {\r\n throw new ForbiddenException(\r\n 'You do not have permission to create documents on behalf of other organizations.'\r\n );\r\n }\r\n userOrgId = resolvedOriginatorId;\r\n }\r\n\r\n if (!userOrgId) {\r\n throw new BadRequestException(\r\n 'User must belong to an organization to create documents'\r\n );\r\n }\r\n\r\n if (createDto.details) {\r\n try {\r\n await this.jsonSchemaService.validate(type.typeCode, createDto.details);\r\n } catch (error: unknown) {\r\n this.logger.warn(\r\n `Schema validation warning for ${type.typeCode}: ${(error as Error).message}`\r\n );\r\n }\r\n }\r\n\r\n const queryRunner = this.dataSource.createQueryRunner();\r\n await queryRunner.connect();\r\n await queryRunner.startTransaction();\r\n\r\n try {\r\n // [Fix #6] Fetch real ORG Code from Organization entity\r\n const originatorOrg = await this.dataSource.manager.findOne(\r\n Organization,\r\n {\r\n where: { id: userOrgId },\r\n }\r\n );\r\n const orgCode = originatorOrg?.organizationCode ?? 'UNK';\r\n\r\n // [v1.5.1] Extract recipient organization from recipients array (Primary TO)\r\n const toRecipient = resolvedRecipients?.find((r) => r.type === 'TO');\r\n const recipientOrganizationId = toRecipient?.organizationId;\r\n\r\n let recipientCode = '';\r\n if (recipientOrganizationId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: recipientOrganizationId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n const docNumber = await this.numberingService.generateNextNumber({\r\n projectId: resolvedProjectId,\r\n originatorOrganizationId: userOrgId,\r\n typeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n subTypeId: createDto.subTypeId,\r\n recipientOrganizationId, // [v1.5.1] Pass recipient for document number format\r\n year: new Date().getFullYear(),\r\n customTokens: {\r\n TYPE_CODE: type.typeCode,\r\n ORG_CODE: orgCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n });\r\n\r\n const correspondence = queryRunner.manager.create(Correspondence, {\r\n correspondenceNumber: docNumber.number,\r\n correspondenceTypeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n projectId: resolvedProjectId,\r\n originatorId: userOrgId,\r\n isInternal: createDto.isInternal || false,\r\n createdBy: user.user_id,\r\n });\r\n const savedCorr = await queryRunner.manager.save(correspondence);\r\n\r\n const revision = queryRunner.manager.create(CorrespondenceRevision, {\r\n correspondenceId: savedCorr.id,\r\n revisionNumber: 0,\r\n revisionLabel: this.getInitialRevisionLabel(type.typeCode),\r\n isCurrent: true,\r\n statusId: statusDraft.id,\r\n subject: createDto.subject,\r\n body: createDto.body,\r\n remarks: createDto.remarks,\r\n dueDate: createDto.dueDate ? new Date(createDto.dueDate) : undefined,\r\n documentDate: createDto.documentDate\r\n ? new Date(createDto.documentDate)\r\n : undefined,\r\n issuedDate: createDto.issuedDate\r\n ? new Date(createDto.issuedDate)\r\n : undefined,\r\n receivedDate: createDto.receivedDate\r\n ? new Date(createDto.receivedDate)\r\n : undefined,\r\n description: createDto.description,\r\n details: createDto.details,\r\n createdBy: user.user_id,\r\n schemaVersion: 1,\r\n });\r\n await queryRunner.manager.save(revision);\r\n\r\n // Save Recipients (using resolved INT IDs)\r\n if (resolvedRecipients && resolvedRecipients.length > 0) {\r\n const recipients = resolvedRecipients.map((r) =>\r\n queryRunner.manager.create(CorrespondenceRecipient, {\r\n correspondenceId: savedCorr.id,\r\n recipientOrganizationId: r.organizationId,\r\n recipientType: r.type,\r\n })\r\n );\r\n await queryRunner.manager.save(recipients);\r\n }\r\n\r\n // Commit attachments from Temp → Permanent (Two-Phase Storage)\r\n if (createDto.attachmentTempIds?.length) {\r\n const issueDate = createDto.issuedDate\r\n ? new Date(createDto.issuedDate)\r\n : createDto.documentDate\r\n ? new Date(createDto.documentDate)\r\n : undefined;\r\n\r\n await this.fileStorageService.commit(createDto.attachmentTempIds, {\r\n issueDate,\r\n documentType: 'Correspondence',\r\n });\r\n }\r\n\r\n await queryRunner.commitTransaction();\r\n\r\n // Start Workflow Instance (non-blocking)\r\n try {\r\n const workflowCode = `CORRESPONDENCE_${type.typeCode}`;\r\n await this.workflowEngine.createInstance(\r\n workflowCode,\r\n 'correspondence',\r\n savedCorr.id.toString(),\r\n {\r\n projectId: resolvedProjectId,\r\n originatorId: userOrgId,\r\n disciplineId: createDto.disciplineId,\r\n initiatorId: user.user_id,\r\n } as Record\r\n );\r\n } catch (error: unknown) {\r\n this.logger.warn(\r\n `Workflow not started for ${docNumber.number} (Code: CORRESPONDENCE_${type.typeCode}): ${(error as Error).message}`\r\n );\r\n }\r\n\r\n // Fire-and-forget search indexing (non-blocking, void intentional)\r\n void this.searchService.indexDocument({\r\n id: savedCorr.id,\r\n publicId: savedCorr.publicId,\r\n type: 'correspondence',\r\n docNumber: docNumber.number,\r\n title: createDto.subject,\r\n description: createDto.description,\r\n status: 'DRAFT',\r\n projectId: resolvedProjectId,\r\n createdAt: new Date(),\r\n });\r\n\r\n return {\r\n ...savedCorr,\r\n currentRevision: revision,\r\n };\r\n } catch (err) {\r\n await queryRunner.rollbackTransaction();\r\n this.logger.error(\r\n `Failed to create correspondence: ${(err as Error).message}`\r\n );\r\n throw err;\r\n } finally {\r\n await queryRunner.release();\r\n }\r\n }\r\n\r\n async findAll(searchDto: SearchCorrespondenceDto = {}) {\r\n const {\r\n search,\r\n typeId,\r\n projectId,\r\n statusId,\r\n status,\r\n page = 1,\r\n limit = 10,\r\n } = searchDto;\r\n const skip = (page - 1) * limit;\r\n\r\n // Change: Query from Revision Repo\r\n const query = this.revisionRepo\r\n .createQueryBuilder('rev')\r\n .leftJoinAndSelect('rev.correspondence', 'corr')\r\n .leftJoinAndSelect('corr.type', 'type')\r\n .leftJoinAndSelect('corr.project', 'project')\r\n .leftJoinAndSelect('corr.originator', 'org')\r\n .leftJoinAndSelect('rev.status', 'status');\r\n\r\n // Filter by Revision Status\r\n const revStatus = searchDto.revisionStatus || 'CURRENT';\r\n\r\n if (revStatus === 'CURRENT') {\r\n query.where('rev.isCurrent = :isCurrent', { isCurrent: true });\r\n } else if (revStatus === 'OLD') {\r\n query.where('rev.isCurrent = :isCurrent', { isCurrent: false });\r\n }\r\n // If 'ALL', no filter needed on isCurrent\r\n\r\n if (projectId) {\r\n query.andWhere('corr.projectId = :projectId', { projectId });\r\n }\r\n\r\n if (typeId) {\r\n query.andWhere('corr.correspondenceTypeId = :typeId', { typeId });\r\n }\r\n\r\n if (statusId) {\r\n query.andWhere('rev.statusId = :statusId', { statusId });\r\n }\r\n\r\n if (status) {\r\n query.andWhere('status.statusCode = :status', { status });\r\n }\r\n\r\n if (search) {\r\n query.andWhere(\r\n '(corr.correspondenceNumber LIKE :search OR rev.subject LIKE :search)',\r\n { search: `%${search}%` }\r\n );\r\n }\r\n\r\n // Default Sort: Latest Created\r\n query.orderBy('rev.createdAt', 'DESC').skip(skip).take(limit);\r\n\r\n const [items, total] = await query.getManyAndCount();\r\n\r\n return {\r\n data: items,\r\n meta: {\r\n total,\r\n page,\r\n limit,\r\n totalPages: Math.ceil(total / limit),\r\n },\r\n };\r\n }\r\n\r\n async findOne(id: number) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n relations: [\r\n 'revisions',\r\n 'revisions.status',\r\n 'type',\r\n 'project',\r\n 'originator',\r\n 'recipients',\r\n 'recipients.recipientOrganization', // [v1.5.1] Fixed relation name\r\n ],\r\n });\r\n\r\n if (!correspondence) {\r\n throw new NotFoundException(`Correspondence with ID ${id} not found`);\r\n }\r\n return correspondence;\r\n }\r\n\r\n async findOneByUuid(publicId: string) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { publicId },\r\n relations: [\r\n 'revisions',\r\n 'revisions.status',\r\n 'type',\r\n 'project',\r\n 'originator',\r\n 'recipients',\r\n 'recipients.recipientOrganization',\r\n ],\r\n });\r\n\r\n if (!correspondence) {\r\n throw new NotFoundException(\r\n `Correspondence with UUID ${publicId} not found`\r\n );\r\n }\r\n return correspondence;\r\n }\r\n\r\n async addReference(id: number, dto: AddReferenceDto) {\r\n const source = await this.correspondenceRepo.findOne({ where: { id } });\r\n // ADR-019: Resolve target publicId → internal INT id\r\n const target = await this.correspondenceRepo.findOne({\r\n where: { publicId: dto.targetUuid },\r\n });\r\n\r\n if (!source || !target) {\r\n throw new NotFoundException('Source or Target correspondence not found');\r\n }\r\n\r\n if (source.id === target.id) {\r\n throw new BadRequestException('Cannot reference self');\r\n }\r\n\r\n const exists = await this.referenceRepo.findOne({\r\n where: {\r\n sourceId: id,\r\n targetId: target.id,\r\n },\r\n });\r\n\r\n if (exists) {\r\n return exists;\r\n }\r\n\r\n const ref = this.referenceRepo.create({\r\n sourceId: id,\r\n targetId: target.id,\r\n });\r\n\r\n return this.referenceRepo.save(ref);\r\n }\r\n\r\n async removeReference(id: number, targetId: number) {\r\n const result = await this.referenceRepo.delete({\r\n sourceId: id,\r\n targetId: targetId,\r\n });\r\n\r\n if (result.affected === 0) {\r\n throw new NotFoundException('Reference not found');\r\n }\r\n }\r\n\r\n async getTags(id: number) {\r\n const rows = await this.tagRepo.find({\r\n where: { correspondenceId: id },\r\n relations: ['tag'],\r\n });\r\n return rows.map((r) => r.tag).filter(Boolean);\r\n }\r\n\r\n async addTag(id: number, tagId: number) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n });\r\n if (!correspondence) {\r\n throw new NotFoundException(`Correspondence ${id} not found`);\r\n }\r\n\r\n const tag = await this.dataSource.manager.findOne(Tag, {\r\n where: { id: tagId },\r\n });\r\n if (!tag) {\r\n throw new NotFoundException(`Tag ${tagId} not found`);\r\n }\r\n\r\n const exists = await this.tagRepo.findOne({\r\n where: { correspondenceId: id, tagId },\r\n });\r\n if (exists) return exists;\r\n\r\n const row = this.tagRepo.create({ correspondenceId: id, tagId });\r\n return this.tagRepo.save(row);\r\n }\r\n\r\n async removeTag(id: number, tagId: number) {\r\n const result = await this.tagRepo.delete({ correspondenceId: id, tagId });\r\n if (result.affected === 0) {\r\n throw new NotFoundException('Tag assignment not found');\r\n }\r\n }\r\n\r\n async getReferences(id: number) {\r\n const outgoing = await this.referenceRepo.find({\r\n where: { sourceId: id },\r\n relations: ['target', 'target.type'],\r\n });\r\n\r\n const incoming = await this.referenceRepo.find({\r\n where: { targetId: id },\r\n relations: ['source', 'source.type'],\r\n });\r\n\r\n return { outgoing, incoming };\r\n }\r\n\r\n async update(id: number, updateDto: UpdateCorrespondenceDto, user: User) {\r\n // 1. Find Current Revision\r\n const revision = await this.revisionRepo.findOne({\r\n where: {\r\n correspondenceId: id,\r\n isCurrent: true,\r\n },\r\n relations: ['correspondence'],\r\n });\r\n\r\n if (!revision) {\r\n throw new NotFoundException(\r\n `Current revision for correspondence ${id} not found`\r\n );\r\n }\r\n\r\n // 2. Check Permission\r\n if (revision.statusId) {\r\n const status = await this.statusRepo.findOne({\r\n where: { id: revision.statusId },\r\n });\r\n\r\n if (status && status.statusCode !== 'DRAFT') {\r\n const permissions = await this.userService.getUserPermissions(\r\n user.user_id\r\n );\r\n const canEditSubmittedOrLater =\r\n permissions.includes('correspondence.cancel') ||\r\n permissions.includes('system.manage_all');\r\n\r\n if (!canEditSubmittedOrLater) {\r\n throw new ForbiddenException(\r\n 'Only Org Admin or Superadmin can edit non-draft correspondences'\r\n );\r\n }\r\n }\r\n }\r\n\r\n // ADR-019: Resolve UUID references in update DTO\r\n const updResolvedProjectId = updateDto.projectId\r\n ? await this.uuidResolver.resolveProjectId(updateDto.projectId)\r\n : undefined;\r\n const updResolvedOriginatorId = updateDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(updateDto.originatorId)\r\n : undefined;\r\n const updResolvedRecipients = updateDto.recipients\r\n ? await Promise.all(\r\n updateDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n\r\n // 3. Update Correspondence Entity if needed\r\n const correspondenceUpdate: Record = {};\r\n if (updateDto.disciplineId)\r\n correspondenceUpdate.disciplineId = updateDto.disciplineId;\r\n if (updResolvedProjectId)\r\n correspondenceUpdate.projectId = updResolvedProjectId;\r\n if (updResolvedOriginatorId)\r\n correspondenceUpdate.originatorId = updResolvedOriginatorId;\r\n\r\n if (Object.keys(correspondenceUpdate).length > 0) {\r\n await this.correspondenceRepo.update(id, correspondenceUpdate);\r\n }\r\n\r\n // 4. Update Revision Entity\r\n const revisionUpdate: Record = {};\r\n if (updateDto.subject) revisionUpdate.subject = updateDto.subject;\r\n if (updateDto.body) revisionUpdate.body = updateDto.body;\r\n if (updateDto.remarks) revisionUpdate.remarks = updateDto.remarks;\r\n // Format Date correctly if string\r\n if (updateDto.dueDate) revisionUpdate.dueDate = new Date(updateDto.dueDate);\r\n if (updateDto.documentDate)\r\n revisionUpdate.documentDate = new Date(updateDto.documentDate);\r\n if (updateDto.issuedDate)\r\n revisionUpdate.issuedDate = new Date(updateDto.issuedDate);\r\n if (updateDto.receivedDate)\r\n revisionUpdate.receivedDate = new Date(updateDto.receivedDate);\r\n if (updateDto.description)\r\n revisionUpdate.description = updateDto.description;\r\n if (updateDto.details) revisionUpdate.details = updateDto.details;\r\n\r\n if (Object.keys(revisionUpdate).length > 0) {\r\n await this.revisionRepo.update(revision.id, revisionUpdate);\r\n }\r\n\r\n // 4.5 Commit new attachments from Temp → Permanent (Two-Phase Storage)\r\n if (updateDto.attachmentTempIds?.length) {\r\n const issueDate = updateDto.issuedDate\r\n ? new Date(updateDto.issuedDate)\r\n : updateDto.documentDate\r\n ? new Date(updateDto.documentDate)\r\n : revision.issuedDate || revision.documentDate || undefined;\r\n\r\n await this.fileStorageService.commit(updateDto.attachmentTempIds, {\r\n issueDate: issueDate ? new Date(issueDate) : undefined,\r\n documentType: 'Correspondence',\r\n });\r\n }\r\n\r\n // 5. Update Recipients if provided\r\n if (updResolvedRecipients) {\r\n const recipientRepo = this.dataSource.getRepository(\r\n CorrespondenceRecipient\r\n );\r\n await recipientRepo.delete({ correspondenceId: id });\r\n\r\n const newRecipients = updResolvedRecipients.map((r) =>\r\n recipientRepo.create({\r\n correspondenceId: id,\r\n recipientOrganizationId: r.organizationId,\r\n recipientType: r.type,\r\n })\r\n );\r\n await recipientRepo.save(newRecipients);\r\n }\r\n\r\n // 6. Regenerate Document Number if structural fields changed (Recipient, Discipline, Type, Project)\r\n // AND it is a DRAFT.\r\n\r\n // Fetch fresh data for context and comparison\r\n const currentCorr = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n relations: ['type', 'recipients', 'recipients.recipientOrganization'],\r\n });\r\n\r\n if (currentCorr) {\r\n const currentToRecipient = currentCorr.recipients?.find(\r\n (r) => r.recipientType === 'TO'\r\n );\r\n const currentRecipientId = currentToRecipient?.recipientOrganizationId;\r\n\r\n // Check for ACTUAL value changes\r\n const isProjectChanged =\r\n updResolvedProjectId !== undefined &&\r\n updResolvedProjectId !== currentCorr.projectId;\r\n const isOriginatorChanged =\r\n updResolvedOriginatorId !== undefined &&\r\n updResolvedOriginatorId !== currentCorr.originatorId;\r\n const isDisciplineChanged =\r\n updateDto.disciplineId !== undefined &&\r\n updateDto.disciplineId !== currentCorr.disciplineId;\r\n const isTypeChanged =\r\n updateDto.typeId !== undefined &&\r\n updateDto.typeId !== currentCorr.correspondenceTypeId;\r\n\r\n let isRecipientChanged = false;\r\n let newRecipientId: number | undefined;\r\n\r\n if (updResolvedRecipients) {\r\n const newToRecipient = updResolvedRecipients.find(\r\n (r) => r.type === 'TO'\r\n );\r\n newRecipientId = newToRecipient?.organizationId;\r\n\r\n if (newRecipientId !== currentRecipientId) {\r\n isRecipientChanged = true;\r\n }\r\n }\r\n\r\n if (\r\n isProjectChanged ||\r\n isDisciplineChanged ||\r\n isTypeChanged ||\r\n isRecipientChanged ||\r\n isOriginatorChanged\r\n ) {\r\n const targetRecipientId = isRecipientChanged\r\n ? newRecipientId\r\n : currentRecipientId;\r\n\r\n // Resolve Recipient Code for the NEW context\r\n let recipientCode = '';\r\n if (targetRecipientId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: targetRecipientId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n // [Fix #6] Fetch real ORG Code from originator organization\r\n const originatorOrgForUpdate = await this.dataSource.manager.findOne(\r\n Organization,\r\n {\r\n where: {\r\n id: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0,\r\n },\r\n }\r\n );\r\n const orgCode = originatorOrgForUpdate?.organizationCode ?? 'UNK';\r\n\r\n // Prepare Contexts\r\n const oldCtx = {\r\n projectId: currentCorr.projectId,\r\n originatorOrganizationId: currentCorr.originatorId ?? 0,\r\n typeId: currentCorr.correspondenceTypeId,\r\n disciplineId: currentCorr.disciplineId,\r\n recipientOrganizationId: currentRecipientId,\r\n year: new Date().getFullYear(),\r\n };\r\n\r\n const newCtx = {\r\n projectId: updResolvedProjectId ?? currentCorr.projectId,\r\n originatorOrganizationId:\r\n updResolvedOriginatorId ?? currentCorr.originatorId ?? 0,\r\n typeId: updateDto.typeId ?? currentCorr.correspondenceTypeId,\r\n disciplineId: updateDto.disciplineId ?? currentCorr.disciplineId,\r\n recipientOrganizationId: targetRecipientId,\r\n year: new Date().getFullYear(),\r\n userId: user.user_id, // Pass User ID for Audit\r\n customTokens: {\r\n TYPE_CODE: currentCorr.type?.typeCode || '',\r\n ORG_CODE: orgCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n };\r\n\r\n // If Type Changed, need NEW Type Code\r\n if (isTypeChanged) {\r\n const newType = await this.typeRepo.findOne({\r\n where: { id: newCtx.typeId },\r\n });\r\n if (newType) newCtx.customTokens.TYPE_CODE = newType.typeCode;\r\n }\r\n\r\n const newDocNumber = await this.numberingService.updateNumberForDraft(\r\n currentCorr.correspondenceNumber,\r\n oldCtx,\r\n newCtx\r\n );\r\n\r\n await this.correspondenceRepo.update(id, {\r\n correspondenceNumber: newDocNumber,\r\n });\r\n }\r\n }\r\n\r\n const updated = await this.findOne(id);\r\n\r\n // Re-index updated document in Elasticsearch (fire-and-forget)\r\n void this.searchService.indexDocument({\r\n id: updated.id,\r\n publicId: updated.publicId,\r\n type: 'correspondence',\r\n docNumber: updated.correspondenceNumber,\r\n title: updateDto.subject ?? updated.revisions?.[0]?.subject,\r\n description: updateDto.description ?? updated.revisions?.[0]?.description,\r\n status: 'DRAFT',\r\n projectId: updated.projectId,\r\n createdAt: updated.createdAt,\r\n });\r\n\r\n return updated;\r\n }\r\n\r\n async previewDocumentNumber(createDto: CreateCorrespondenceDto, user: User) {\r\n // ADR-019: Resolve UUID references\r\n const previewProjectId = await this.uuidResolver.resolveProjectId(\r\n createDto.projectId\r\n );\r\n const previewOriginatorId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : undefined;\r\n const previewRecipients = createDto.recipients\r\n ? await Promise.all(\r\n createDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n\r\n const type = await this.typeRepo.findOne({\r\n where: { id: createDto.typeId },\r\n });\r\n if (!type) throw new NotFoundException('Document Type not found');\r\n\r\n let userOrgId = user.primaryOrganizationId;\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n\r\n if (previewOriginatorId && previewOriginatorId !== userOrgId) {\r\n // Allow impersonation for preview\r\n userOrgId = previewOriginatorId;\r\n }\r\n\r\n // Extract recipient from recipients array\r\n const toRecipient = previewRecipients?.find((r) => r.type === 'TO');\r\n const recipientOrganizationId = toRecipient?.organizationId;\r\n\r\n let recipientCode = '';\r\n if (recipientOrganizationId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: recipientOrganizationId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n return this.numberingService.previewNumber({\r\n projectId: previewProjectId,\r\n originatorOrganizationId: userOrgId!,\r\n typeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n subTypeId: createDto.subTypeId,\r\n recipientOrganizationId,\r\n year: new Date().getFullYear(),\r\n customTokens: {\r\n TYPE_CODE: type.typeCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Business Rule Implementation: EC-CORR-001 - Cancel Correspondence with Downstream Circulation\r\n * Cancel correspondence and handle related circulations\r\n */\r\n async cancel(publicId: string, reason: string, user: User) {\r\n const correspondence = await this.findOneByUuid(publicId);\r\n\r\n // Check if user has permission to cancel (Org Admin or Superadmin only)\r\n const permissions = await this.userService.getUserPermissions(user.user_id);\r\n const canCancel =\r\n permissions.includes('correspondence.cancel') ||\r\n permissions.includes('system.manage_all');\r\n\r\n if (!canCancel) {\r\n throw new ForbiddenException(\r\n 'Only administrators can cancel correspondences'\r\n );\r\n }\r\n\r\n // Check if there are any active circulations\r\n const circulationRepo = this.dataSource.getRepository('Circulation');\r\n const activeCirculations = await circulationRepo.find({\r\n where: {\r\n correspondenceId: correspondence.id,\r\n status: 'OPEN',\r\n },\r\n });\r\n\r\n const warningMessage =\r\n activeCirculations.length > 0\r\n ? `There are ${activeCirculations.length} active circulation(s) for this correspondence. Canceling will force close all related circulations.`\r\n : '';\r\n\r\n // Get the current revision to update status\r\n const currentRevision = await this.revisionRepo.findOne({\r\n where: {\r\n correspondenceId: correspondence.id,\r\n isCurrent: true,\r\n },\r\n });\r\n\r\n if (!currentRevision) {\r\n throw new NotFoundException('Current revision not found');\r\n }\r\n\r\n // Get cancelled status\r\n const cancelledStatus = await this.statusRepo.findOne({\r\n where: { statusCode: 'CANCELLED' },\r\n });\r\n\r\n if (!cancelledStatus) {\r\n throw new InternalServerErrorException('CANCELLED status not found');\r\n }\r\n\r\n const queryRunner = this.dataSource.createQueryRunner();\r\n await queryRunner.connect();\r\n await queryRunner.startTransaction();\r\n\r\n try {\r\n // Update correspondence revision status to CANCELLED\r\n await queryRunner.manager.update(\r\n CorrespondenceRevision,\r\n currentRevision.id,\r\n {\r\n statusId: cancelledStatus.id,\r\n remarks: `Cancelled: ${reason}`,\r\n }\r\n );\r\n\r\n // Force close all active circulations\r\n if (activeCirculations.length > 0) {\r\n await queryRunner.manager.update(\r\n 'Circulation',\r\n {\r\n correspondenceId: correspondence.id,\r\n status: 'OPEN',\r\n },\r\n {\r\n status: 'FORCE_CLOSED',\r\n closedAt: new Date(),\r\n closedBy: user.user_id,\r\n closeReason: `Correspondence cancelled: ${reason}`,\r\n }\r\n );\r\n }\r\n\r\n await queryRunner.commitTransaction();\r\n\r\n // Re-index cancelled status in Elasticsearch (fire-and-forget)\r\n void this.searchService.indexDocument({\r\n id: correspondence.id,\r\n publicId: correspondence.publicId,\r\n type: 'correspondence',\r\n docNumber: correspondence.correspondenceNumber,\r\n title: currentRevision.subject,\r\n status: 'CANCELLED',\r\n projectId: correspondence.projectId,\r\n createdAt: correspondence.createdAt,\r\n });\r\n\r\n // Notify originator's doc-control user about cancellation (fire-and-forget)\r\n if (correspondence.originatorId) {\r\n void this.userService\r\n .findDocControlIdByOrg(correspondence.originatorId)\r\n .then((targetUserId) => {\r\n if (targetUserId) {\r\n void this.notificationService.send({\r\n userId: targetUserId,\r\n title: 'Correspondence Cancelled',\r\n message: `${correspondence.correspondenceNumber} — ${currentRevision.subject} has been cancelled. Reason: ${reason}`,\r\n type: 'EMAIL',\r\n entityType: 'correspondence',\r\n entityId: correspondence.id,\r\n link: `/correspondences/${correspondence.publicId}`,\r\n });\r\n }\r\n })\r\n .catch((err: Error) =>\r\n this.logger.warn(`Cancel notification failed: ${err.message}`)\r\n );\r\n }\r\n\r\n return {\r\n success: true,\r\n message: warningMessage || 'Correspondence cancelled successfully',\r\n activeCirculationsCount: activeCirculations.length,\r\n };\r\n } catch (error) {\r\n await queryRunner.rollbackTransaction();\r\n this.logger.error(\r\n `Failed to cancel correspondence: ${(error as Error).message}`\r\n );\r\n throw error;\r\n } finally {\r\n await queryRunner.release();\r\n }\r\n }\r\n\r\n async bulkCancel(\r\n publicIds: string[],\r\n reason: string,\r\n user: User\r\n ): Promise<{ succeeded: string[]; failed: string[] }> {\r\n const succeeded: string[] = [];\r\n const failed: string[] = [];\r\n\r\n for (const publicId of publicIds) {\r\n try {\r\n await this.cancel(publicId, reason, user);\r\n succeeded.push(publicId);\r\n } catch {\r\n failed.push(publicId);\r\n }\r\n }\r\n\r\n return { succeeded, failed };\r\n }\r\n\r\n async exportCsv(searchDto: SearchCorrespondenceDto): Promise {\r\n const { data } = await this.findAll(searchDto);\r\n\r\n const header = [\r\n 'Document No.',\r\n 'Rev',\r\n 'Subject',\r\n 'Type',\r\n 'Status',\r\n 'Project',\r\n 'From',\r\n 'Due Date',\r\n 'Created At',\r\n ];\r\n const rows = data.map((rev) => {\r\n const corr = rev.correspondence ?? (rev as unknown as Correspondence);\r\n return [\r\n this.escapeCsv(corr.correspondenceNumber ?? ''),\r\n this.escapeCsv(rev.revisionLabel ?? String(rev.revisionNumber ?? 0)),\r\n this.escapeCsv(rev.subject ?? ''),\r\n this.escapeCsv(corr.type?.typeCode ?? ''),\r\n this.escapeCsv(rev.status?.statusCode ?? ''),\r\n this.escapeCsv(corr.project?.projectCode ?? ''),\r\n this.escapeCsv(corr.originator?.organizationCode ?? ''),\r\n rev.dueDate ? new Date(rev.dueDate).toISOString().split('T')[0] : '',\r\n new Date(rev.createdAt).toISOString().split('T')[0],\r\n ].join(',');\r\n });\r\n\r\n return [header.join(','), ...rows].join('\\n');\r\n }\r\n\r\n private escapeCsv(value: string): string {\r\n if (value.includes(',') || value.includes('\"') || value.includes('\\n')) {\r\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\r\n }\r\n return value;\r\n }\r\n}\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/perf-cache-60cab15b743c6776f41d29bcac696b99-da39a3ee5e6b4b0d3255bfef95601890 b/backend/src/.jest-cache/perf-cache-60cab15b743c6776f41d29bcac696b99-da39a3ee5e6b4b0d3255bfef95601890 index 1e9b7d2..29bb22f 100644 --- a/backend/src/.jest-cache/perf-cache-60cab15b743c6776f41d29bcac696b99-da39a3ee5e6b4b0d3255bfef95601890 +++ b/backend/src/.jest-cache/perf-cache-60cab15b743c6776f41d29bcac696b99-da39a3ee5e6b4b0d3255bfef95601890 @@ -1 +1 @@ -{"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\due-date-reminder.service.spec.ts":[1,1598],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts":[1,7578],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.service.spec.ts":[1,1526],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\document-numbering.service.spec.ts":[1,1474],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\casl\\ability.factory.spec.ts":[1,921],"E:\\np-dms\\lcbp3\\backend\\src\\common\\services\\uuid-resolver.service.spec.ts":[1,1166],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\workflow-engine.service.spec.ts":[1,1175],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\dsl\\parser.service.spec.ts":[1,4448],"E:\\np-dms\\lcbp3\\backend\\src\\common\\pipes\\parse-uuid.pipe.spec.ts":[1,369],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\user\\user.service.spec.ts":[1,1074],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.service.spec.ts":[1,1277],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.controller.spec.ts":[1,8589],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.service.spec.ts":[1,1251],"E:\\np-dms\\lcbp3\\backend\\src\\common\\entities\\uuid-base.entity.spec.ts":[1,460],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.service.spec.ts":[1,1043],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.controller.spec.ts":[1,2047],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\services\\manual-override.service.spec.ts":[1,936],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.controller.spec.ts":[1,1666],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.controller.spec.ts":[1,6122],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.controller.spec.ts":[1,1859],"E:\\np-dms\\lcbp3\\backend\\src\\app.controller.spec.ts":[1,564],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\json-schema\\json-schema.controller.spec.ts":[1,3140]} \ No newline at end of file +{"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\due-date-reminder.service.spec.ts":[1,1598],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts":[1,5627],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.service.spec.ts":[1,1526],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\document-numbering.service.spec.ts":[1,1474],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\casl\\ability.factory.spec.ts":[1,921],"E:\\np-dms\\lcbp3\\backend\\src\\common\\services\\uuid-resolver.service.spec.ts":[1,1166],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\workflow-engine.service.spec.ts":[1,1175],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\dsl\\parser.service.spec.ts":[1,4448],"E:\\np-dms\\lcbp3\\backend\\src\\common\\pipes\\parse-uuid.pipe.spec.ts":[1,369],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\user\\user.service.spec.ts":[1,1074],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.service.spec.ts":[1,1277],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.controller.spec.ts":[1,7855],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.service.spec.ts":[1,1251],"E:\\np-dms\\lcbp3\\backend\\src\\common\\entities\\uuid-base.entity.spec.ts":[1,460],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.service.spec.ts":[1,1043],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.controller.spec.ts":[1,2047],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\services\\manual-override.service.spec.ts":[1,936],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.controller.spec.ts":[1,1666],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.controller.spec.ts":[1,6122],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.controller.spec.ts":[1,1859],"E:\\np-dms\\lcbp3\\backend\\src\\app.controller.spec.ts":[1,564],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\json-schema\\json-schema.controller.spec.ts":[1,3140]} \ No newline at end of file diff --git a/backend/src/modules/correspondence/correspondence.service.spec.ts b/backend/src/modules/correspondence/correspondence.service.spec.ts index 4393e6c..aa72c36 100644 --- a/backend/src/modules/correspondence/correspondence.service.spec.ts +++ b/backend/src/modules/correspondence/correspondence.service.spec.ts @@ -1,6 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { DataSource, Repository } from 'typeorm'; +import { ForbiddenException } from '@nestjs/common'; import { CorrespondenceService } from './correspondence.service'; import { Correspondence } from './entities/correspondence.entity'; import { CorrespondenceRevision } from './entities/correspondence-revision.entity'; @@ -173,6 +174,83 @@ describe('CorrespondenceService', () => { }); describe('update', () => { + it('should allow non-draft update for org-admin+ permissions', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: 10, + } as unknown as User; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 23, + }; + + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision); + + const statusRepo = testingModule.get>( + getRepositoryToken(CorrespondenceStatus) + ); + (statusRepo.findOne as jest.Mock).mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + + const userService = testingModule.get(UserService); + (userService.getUserPermissions as jest.Mock).mockResolvedValue([ + 'correspondence.cancel', + ]); + + jest.spyOn(correspondenceRepo, 'findOne').mockResolvedValue({ + id: 1, + publicId: 'corr-uuid-1', + correspondenceNumber: 'CORR-001', + projectId: 1, + createdAt: new Date(), + revisions: [], + } as unknown as Correspondence); + + await expect( + service.update(1, { subject: 'Updated Subject' }, mockUser) + ).resolves.toBeDefined(); + }); + + it('should reject non-draft update for non-admin permissions', async () => { + const mockUser = { + user_id: 2, + primaryOrganizationId: 10, + } as unknown as User; + const mockRevision = { + id: 101, + correspondenceId: 2, + isCurrent: true, + statusId: 23, + }; + + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision); + + const statusRepo = testingModule.get>( + getRepositoryToken(CorrespondenceStatus) + ); + (statusRepo.findOne as jest.Mock).mockResolvedValue({ + id: 23, + statusCode: 'SUBOWN', + }); + + const userService = testingModule.get(UserService); + (userService.getUserPermissions as jest.Mock).mockResolvedValue([ + 'correspondence.edit', + ]); + + await expect( + service.update(2, { subject: 'Should Fail' }, mockUser) + ).rejects.toThrow(ForbiddenException); + }); + it('should NOT regenerate number if critical fields unchanged', async () => { const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User; const mockRevision = { diff --git a/backend/src/modules/correspondence/correspondence.service.ts b/backend/src/modules/correspondence/correspondence.service.ts index 83b4e99..331f2d3 100644 --- a/backend/src/modules/correspondence/correspondence.service.ts +++ b/backend/src/modules/correspondence/correspondence.service.ts @@ -631,8 +631,20 @@ export class CorrespondenceService { const status = await this.statusRepo.findOne({ where: { id: revision.statusId }, }); + if (status && status.statusCode !== 'DRAFT') { - throw new BadRequestException('Only DRAFT documents can be updated'); + const permissions = await this.userService.getUserPermissions( + user.user_id + ); + const canEditSubmittedOrLater = + permissions.includes('correspondence.cancel') || + permissions.includes('system.manage_all'); + + if (!canEditSubmittedOrLater) { + throw new ForbiddenException( + 'Only Org Admin or Superadmin can edit non-draft correspondences' + ); + } } } diff --git a/frontend/app/(dashboard)/correspondences/[uuid]/edit/page.tsx b/frontend/app/(dashboard)/correspondences/[uuid]/edit/page.tsx index fdb4ed7..2f39485 100644 --- a/frontend/app/(dashboard)/correspondences/[uuid]/edit/page.tsx +++ b/frontend/app/(dashboard)/correspondences/[uuid]/edit/page.tsx @@ -3,11 +3,13 @@ import { CorrespondenceForm } from '@/components/correspondences/form'; import { useCorrespondence } from '@/hooks/use-correspondence'; import { Loader2 } from 'lucide-react'; -import { useParams } from 'next/navigation'; +import { useParams, useSearchParams } from 'next/navigation'; export default function EditCorrespondencePage() { const params = useParams(); + const searchParams = useSearchParams(); const uuid = (params?.uuid as string) ?? ''; + const selectedRevisionId = searchParams.get('revId') ?? undefined; const { data: correspondence, isLoading, isError } = useCorrespondence(uuid); @@ -46,7 +48,7 @@ export default function EditCorrespondencePage() {
- +
); diff --git a/frontend/app/(dashboard)/correspondences/[uuid]/page.tsx b/frontend/app/(dashboard)/correspondences/[uuid]/page.tsx index f79a239..c9ff69c 100644 --- a/frontend/app/(dashboard)/correspondences/[uuid]/page.tsx +++ b/frontend/app/(dashboard)/correspondences/[uuid]/page.tsx @@ -3,11 +3,13 @@ import { CorrespondenceDetail } from '@/components/correspondences/detail'; import { useCorrespondence } from '@/hooks/use-correspondence'; import { Loader2 } from 'lucide-react'; -import { useParams } from 'next/navigation'; +import { useParams, useSearchParams } from 'next/navigation'; export default function CorrespondenceDetailPage() { const params = useParams(); + const searchParams = useSearchParams(); const uuid = (params?.uuid as string) ?? ''; + const selectedRevisionId = searchParams.get('revId') ?? undefined; const { data: correspondence, isLoading, isError } = useCorrespondence(uuid); @@ -36,5 +38,5 @@ export default function CorrespondenceDetailPage() { ); } - return ; + return ; } diff --git a/frontend/components/correspondences/detail.tsx b/frontend/components/correspondences/detail.tsx index 2e23018..1c974b3 100644 --- a/frontend/components/correspondences/detail.tsx +++ b/frontend/components/correspondences/detail.tsx @@ -22,26 +22,39 @@ import { Badge } from '@/components/ui/badge'; interface CorrespondenceDetailProps { data: Correspondence; + selectedRevisionId?: string; } -export function CorrespondenceDetail({ data }: CorrespondenceDetailProps) { +export function CorrespondenceDetail({ data, selectedRevisionId }: CorrespondenceDetailProps) { const submitMutation = useSubmitCorrespondence(); const processMutation = useProcessWorkflow(); const cancelMutation = useCancelCorrespondence(); - const { hasPermission } = useAuthStore(); + const { user, hasPermission } = useAuthStore(); const [actionState, setActionState] = useState<'approve' | 'reject' | 'cancel' | null>(null); const [comments, setComments] = useState(''); const [cancelReason, setCancelReason] = useState(''); if (!data) return
No data found
; - const currentRevision = data.revisions?.find((r) => r.isCurrent) || data.revisions?.[0]; + const selectedRevision = selectedRevisionId + ? data.revisions?.find((r) => r.publicId === selectedRevisionId) + : undefined; + const currentRevision = selectedRevision || data.revisions?.find((r) => r.isCurrent) || data.revisions?.[0]; const subject = currentRevision?.subject || '-'; const description = currentRevision?.description || '-'; const status = currentRevision?.status?.statusCode || 'UNKNOWN'; const attachments = currentRevision?.attachments || []; const importance = (currentRevision?.details?.importance as string) || 'NORMAL'; const canEditMetadata = hasPermission('correspondence.edit'); + const privilegedEditableStatuses = ['SUBCSC', 'SUBOWN', 'IN_REVIEW_CSC']; + const normalizedRole = (user?.role || '').toUpperCase().replace(/\s+/g, '_'); + const isPrivilegedEditRole = ['SUPERADMIN', 'SUPER_ADMIN', 'ADMIN', 'DC', 'DOCUMENT_CONTROL'].includes( + normalizedRole + ); + const canEditInStatus = + status === 'DRAFT' || + (privilegedEditableStatuses.includes(status) && isPrivilegedEditRole); + const canEditDocument = canEditInStatus && (hasPermission('correspondence.edit') || isPrivilegedEditRole); const toRecipients = data.recipients?.filter((r) => r.recipientType === 'TO') || []; const ccRecipients = data.recipients?.filter((r) => r.recipientType === 'CC') || []; @@ -100,15 +113,13 @@ export function CorrespondenceDetail({ data }: CorrespondenceDetailProps) {
- {status === 'DRAFT' && ( - - - - - + {canEditDocument && ( + + + )} {status === 'DRAFT' && ( diff --git a/frontend/components/correspondences/form.tsx b/frontend/components/correspondences/form.tsx index 287dfac..eac1270 100644 --- a/frontend/components/correspondences/form.tsx +++ b/frontend/components/correspondences/form.tsx @@ -75,6 +75,7 @@ interface InitialCorrespondenceData { correspondenceTypeId?: number; disciplineId?: number; revisions?: Array<{ + publicId?: string; isCurrent?: boolean; subject?: string; title?: string; @@ -124,7 +125,15 @@ const normalizePublicId = (value: unknown): string | undefined => { return trimmed.length > 0 ? trimmed : undefined; }; -export function CorrespondenceForm({ initialData, uuid }: { initialData?: InitialCorrespondenceData; uuid?: string }) { +export function CorrespondenceForm({ + initialData, + uuid, + selectedRevisionId, +}: { + initialData?: InitialCorrespondenceData; + uuid?: string; + selectedRevisionId?: string; +}) { const router = useRouter(); const createMutation = useCreateCorrespondence(); const updateMutation = useUpdateCorrespondence(); @@ -138,7 +147,10 @@ export function CorrespondenceForm({ initialData, uuid }: { initialData?: Initia const correspondenceTypes = extractArrayData(correspondenceTypesData); // Extract initial values if editing - const currentRev = initialData?.revisions?.find((r) => r.isCurrent) || initialData?.revisions?.[0]; + const selectedRevision = selectedRevisionId + ? initialData?.revisions?.find((r) => normalizePublicId(r.publicId) === selectedRevisionId) + : undefined; + const currentRev = selectedRevision || initialData?.revisions?.find((r) => r.isCurrent) || initialData?.revisions?.[0]; const initialToRecipient = initialData?.recipients?.find((r) => r.recipientType === 'TO'); const initialCcRecipientIds = initialData?.recipients diff --git a/frontend/components/correspondences/list.tsx b/frontend/components/correspondences/list.tsx index 50f5915..e341505 100644 --- a/frontend/components/correspondences/list.tsx +++ b/frontend/components/correspondences/list.tsx @@ -8,12 +8,16 @@ import { Button } from '@/components/ui/button'; import { Eye, Edit } from 'lucide-react'; import Link from 'next/link'; import { format } from 'date-fns'; +import { useAuthStore } from '@/lib/stores/auth-store'; interface CorrespondenceListProps { data: CorrespondenceRevision[]; } export function CorrespondenceList({ data }: CorrespondenceListProps) { + const { user, hasPermission } = useAuthStore(); + const privilegedEditableStatuses = ['SUBCSC', 'SUBOWN', 'IN_REVIEW_CSC']; + const columns: ColumnDef[] = [ { accessorKey: 'correspondence.correspondenceNumber', @@ -90,18 +94,33 @@ export function CorrespondenceList({ data }: CorrespondenceListProps) { // Edit/View link goes to the DOCUMENT detail (correspondence.publicId) // Ideally we might pass ?revId=item.publicId to view specific revision, but detail page defaults to latest. // For editing, we edit the document. - const docUuid = item.correspondence.publicId; + const docUuid = item.correspondence?.publicId; + const revId = item.publicId; const statusCode = item.status?.statusCode; + const normalizedRole = (user?.role || '').toUpperCase().replace(/\s+/g, '_'); + const isPrivilegedEditRole = ['SUPERADMIN', 'SUPER_ADMIN', 'ADMIN', 'DC', 'DOCUMENT_CONTROL'].includes( + normalizedRole + ); + const canEditInStatus = + statusCode === 'DRAFT' || + (typeof statusCode === 'string' && + privilegedEditableStatuses.includes(statusCode) && + isPrivilegedEditRole); + const canEdit = canEditInStatus && (hasPermission('correspondence.edit') || isPrivilegedEditRole); + + if (!docUuid) { + return null; + } return (
- + - {statusCode === 'DRAFT' && ( - + {canEdit && ( +