From 55ea870eac6d47813fcb6d2ff1b7726e203ccad8 Mon Sep 17 00:00:00 2001 From: phev8 Date: Thu, 17 Jul 2025 16:21:16 +0200 Subject: [PATCH 01/10] Add copy-paste functionality for survey items and components - Introduced the `CopyPaste` class to handle copying and pasting of survey items and components, including support for nested structures and translations. - Implemented methods for copying items, pasting items with unique key generation, and handling component-specific copy-paste operations. - Enhanced the `SurveyEditor` class to integrate copy-paste methods, allowing users to copy and paste items and components directly within the editor. - Added comprehensive tests to ensure the correctness of copy-paste operations, including validation of clipboard data formats and error handling for non-existent items. - Improved overall functionality and user experience in the survey editor by enabling efficient item management through copy-paste capabilities. --- .../survey-editor-copy-paste.test.ts | 1359 +++++++++++++++++ src/survey-editor/copy-paste.ts | 1162 ++++++++++++++ src/survey-editor/index.ts | 8 +- src/survey-editor/survey-editor.ts | 63 + 4 files changed, 2589 insertions(+), 3 deletions(-) create mode 100644 src/__tests__/survey-editor-copy-paste.test.ts create mode 100644 src/survey-editor/copy-paste.ts diff --git a/src/__tests__/survey-editor-copy-paste.test.ts b/src/__tests__/survey-editor-copy-paste.test.ts new file mode 100644 index 0000000..1e0ffa6 --- /dev/null +++ b/src/__tests__/survey-editor-copy-paste.test.ts @@ -0,0 +1,1359 @@ +import { CopyPaste, SurveyItemClipboardData, SurveyComponentClipboardData } from '../survey-editor/copy-paste'; +import { SurveyEditor } from '../survey-editor/survey-editor'; +import { Survey } from '../survey/survey'; +import { GroupItem, SingleChoiceQuestionItem, MultipleChoiceQuestionItem, DisplayItem, SurveyItemType } from '../survey/items'; +import { SurveyItemTranslations } from '../survey/utils'; +import { TextComponent } from '../survey/components'; +import { JsonSurveyItemGroup, JsonSurveyDisplayItem } from '../survey/items/survey-item-json'; +import { ContentType } from '../survey/utils/content'; +import { ScgMcgChoiceResponseConfig, ScgMcgOption, ItemComponentType } from '../survey/components'; + +describe('CopyPaste Functionality', () => { + let copyPaste: CopyPaste; + let editor: SurveyEditor; // Keep for non-copy-paste operations + let survey: Survey; + + beforeEach(() => { + // Create a test survey with some items + survey = new Survey('test-survey'); + + // Add a group + const group1 = new GroupItem('test-survey.group1'); + survey.surveyItems['test-survey.group1'] = group1; + (survey.surveyItems['test-survey'] as GroupItem).items = ['test-survey.group1']; + + // Add a single choice question + const question1 = new SingleChoiceQuestionItem('test-survey.group1.Q1'); + survey.surveyItems['test-survey.group1.Q1'] = question1; + group1.items = ['test-survey.group1.Q1']; + + // Add a display item + const display1 = new DisplayItem('test-survey.group1.display1'); + display1.components = [ + new TextComponent('text1', undefined, 'test-survey.group1.display1') + ]; + survey.surveyItems['test-survey.group1.display1'] = display1; + group1.items.push('test-survey.group1.display1'); + + copyPaste = new CopyPaste(survey); + editor = new SurveyEditor(survey); // Keep for non-copy-paste operations + }); + + describe('copyItem', () => { + test('should copy a single choice question item', () => { + const clipboardData = copyPaste.copyItem('test-survey.group1.Q1'); + + expect(clipboardData.type).toBe('survey-item'); + expect(clipboardData.version).toBe('1.0.0'); + expect(clipboardData.rootItemKey).toBe('test-survey.group1.Q1'); + expect(clipboardData.items).toHaveLength(1); + expect(clipboardData.items[0].itemKey).toBe('test-survey.group1.Q1'); + expect(clipboardData.items[0].itemData.itemType).toBe(SurveyItemType.SingleChoiceQuestion); + expect(clipboardData.translations['test-survey.group1.Q1']).toBeDefined(); + expect(typeof clipboardData.translations['test-survey.group1.Q1']).toBe('object'); + expect(clipboardData.prefills).toBeDefined(); + expect(clipboardData.timestamp).toBeGreaterThan(0); + }); + + test('should copy a group item with children and include entire subtree', () => { + const clipboardData = copyPaste.copyItem('test-survey.group1'); + + expect(clipboardData.type).toBe('survey-item'); + expect(clipboardData.rootItemKey).toBe('test-survey.group1'); + expect(clipboardData.items).toHaveLength(3); // group + 2 children + + // Check root item + const rootItem = clipboardData.items.find(item => item.itemKey === 'test-survey.group1'); + expect(rootItem).toBeDefined(); + expect(rootItem!.itemData.itemType).toBe(SurveyItemType.Group); + expect((rootItem!.itemData as JsonSurveyItemGroup).items).toEqual([ + 'test-survey.group1.Q1', + 'test-survey.group1.display1' + ]); + + // Check child items are included + const childKeys = clipboardData.items.map(item => item.itemKey).sort(); + expect(childKeys).toEqual([ + 'test-survey.group1', + 'test-survey.group1.Q1', + 'test-survey.group1.display1' + ]); + + // Check translations for all items + expect(clipboardData.translations['test-survey.group1']).toBeDefined(); + expect(typeof clipboardData.translations['test-survey.group1']).toBe('object'); + expect(clipboardData.translations['test-survey.group1.Q1']).toBeDefined(); + expect(typeof clipboardData.translations['test-survey.group1.Q1']).toBe('object'); + expect(clipboardData.translations['test-survey.group1.display1']).toBeDefined(); + expect(typeof clipboardData.translations['test-survey.group1.display1']).toBe('object'); + }); + + test('should copy a display item', () => { + const clipboardData = copyPaste.copyItem('test-survey.group1.display1'); + + expect(clipboardData.type).toBe('survey-item'); + expect(clipboardData.rootItemKey).toBe('test-survey.group1.display1'); + expect(clipboardData.items).toHaveLength(1); + expect(clipboardData.items[0].itemKey).toBe('test-survey.group1.display1'); + expect(clipboardData.items[0].itemData.itemType).toBe(SurveyItemType.Display); + expect((clipboardData.items[0].itemData as JsonSurveyDisplayItem).components).toBeDefined(); + }); + + test('should throw error for non-existent item', () => { + expect(() => { + copyPaste.copyItem('non-existent-item'); + }).toThrow("Item with key 'non-existent-item' not found"); + }); + + test('should include translations in clipboard data', () => { + const translations = new SurveyItemTranslations(); + translations.setContent('en', 'title', { type: ContentType.CQM, content: 'Test Title', attributions: [] }); + editor.updateItemTranslations('test-survey.group1.display1', translations); + + const clipboardData = copyPaste.copyItem('test-survey.group1.display1'); + + expect(Object.keys(clipboardData.translations['test-survey.group1.display1'])).toContain('en'); + expect(clipboardData.translations['test-survey.group1.display1']['en']['title']).toEqual({ + type: ContentType.CQM, + content: 'Test Title', + attributions: [] + }); + }); + }); + + describe('pasteItem', () => { + let clipboardData: SurveyItemClipboardData; + + beforeEach(() => { + clipboardData = copyPaste.copyItem('test-survey.group1.Q1'); + }); + + test('should paste item to specified location', () => { + const newItemKey = copyPaste.pasteItem(clipboardData, { + parentKey: 'test-survey.group1', + index: 0 + }); + + expect(newItemKey).toBe('test-survey.group1.Q1_copy'); + expect(survey.surveyItems[newItemKey]).toBeDefined(); + expect(survey.surveyItems[newItemKey].itemType).toBe(SurveyItemType.SingleChoiceQuestion); + + // Check that item was added to parent's items array + const parentGroup = survey.surveyItems['test-survey.group1'] as GroupItem; + expect(parentGroup.items?.[0]).toBe('test-survey.group1.Q1_copy'); + }); + + test('should generate unique keys for multiple pastes', () => { + const firstCopy = copyPaste.pasteItem(clipboardData, { + parentKey: 'test-survey.group1' + }); + const secondCopy = copyPaste.pasteItem(clipboardData, { + parentKey: 'test-survey.group1' + }); + const thirdCopy = copyPaste.pasteItem(clipboardData, { + parentKey: 'test-survey.group1' + }); + + expect(firstCopy).toBe('test-survey.group1.Q1_copy'); + expect(secondCopy).toBe('test-survey.group1.Q1_copy_2'); + expect(thirdCopy).toBe('test-survey.group1.Q1_copy_3'); + + expect(survey.surveyItems[firstCopy]).toBeDefined(); + expect(survey.surveyItems[secondCopy]).toBeDefined(); + expect(survey.surveyItems[thirdCopy]).toBeDefined(); + }); + + test('should paste item at specified index', () => { + const newItemKey = copyPaste.pasteItem(clipboardData, { + parentKey: 'test-survey.group1', + index: 0 + }); + + const parentGroup = survey.surveyItems['test-survey.group1'] as GroupItem; + expect(parentGroup.items?.[0]).toBe(newItemKey); + }); + + test('should recursively paste group with children', () => { + const groupClipboard = copyPaste.copyItem('test-survey.group1'); + + const newGroupKey = copyPaste.pasteItem(groupClipboard, { + parentKey: 'test-survey' + }); + + expect(newGroupKey).toBe('test-survey.group1_copy'); + const newGroup = survey.surveyItems[newGroupKey] as GroupItem; + expect(newGroup.items).toEqual([ + 'test-survey.group1_copy.Q1', + 'test-survey.group1_copy.display1' + ]); + + // Check that child items were created + expect(survey.surveyItems['test-survey.group1_copy.Q1']).toBeDefined(); + expect(survey.surveyItems['test-survey.group1_copy.display1']).toBeDefined(); + }); + + test('should preserve translations when pasting', () => { + const translations = new SurveyItemTranslations(); + translations.setContent('en', 'title', { type: ContentType.CQM, content: 'Test Title', attributions: [] }); + translations.setContent('de', 'title', { type: ContentType.CQM, content: 'Test Titel', attributions: [] }); + editor.updateItemTranslations('test-survey.group1.display1', translations); + + const displayClipboard = copyPaste.copyItem('test-survey.group1.display1'); + const newItemKey = copyPaste.pasteItem(displayClipboard, { + parentKey: 'test-survey.group1' + }); + + const newTranslations = survey.getItemTranslations(newItemKey); + expect(newTranslations?.locales).toContain('en'); + expect(newTranslations?.locales).toContain('de'); + expect(newTranslations?.getContent('en', 'title')).toEqual({ + type: ContentType.CQM, + content: 'Test Title', + attributions: [] + }); + expect(newTranslations?.getContent('de', 'title')).toEqual({ + type: ContentType.CQM, + content: 'Test Titel', + attributions: [] + }); + }); + + test('should validate clipboard data format', () => { + const invalidClipboard = { + type: 'invalid-type', + version: '1.0.0', + itemKey: 'test', + itemData: {}, + translations: new SurveyItemTranslations(), + timestamp: Date.now() + }; + + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + copyPaste.pasteItem(invalidClipboard as any, { parentKey: 'test-survey.group1' }); + }).toThrow('Invalid clipboard data format'); + }); + + test('should validate required clipboard data fields', () => { + const incompleteClipboard = { + type: 'survey-item', + version: '1.0.0', + itemKey: 'test' + // Missing itemData, translations, timestamp + }; + + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + copyPaste.pasteItem(incompleteClipboard as any, { parentKey: 'test-survey.group1' }); + }).toThrow('Invalid clipboard data format'); + }); + + + test('should handle undo/redo integration correctly', () => { + // Test that paste operation is properly tracked in undo/redo history + const initialHistoryLength = editor.undoRedo.getHistory().length + (editor.hasUncommittedChanges ? 1 : 0); + + // Commit the changes to create a history entry + const newItemKey = editor.pasteItem(clipboardData, { + parentKey: 'test-survey.group1' + }); + + // Should have added an operation to history + expect(editor.undoRedo.getHistory().length).toBe(initialHistoryLength + 1); + expect(editor.hasUncommittedChanges).toBe(false); + + // Verify the item was pasted + expect(editor.survey.surveyItems[newItemKey]).toBeDefined(); + const parentGroup = editor.survey.surveyItems['test-survey.group1'] as GroupItem; + expect(parentGroup.items).toContain(newItemKey); + + // Test undo + const undoSuccess = editor.undo(); + expect(undoSuccess).toBe(true); + expect(editor.survey.surveyItems[newItemKey]).toBeUndefined(); + expect((editor.survey.surveyItems['test-survey.group1'] as GroupItem).items).not.toContain(newItemKey); + + // Test redo + const redoSuccess = editor.redo(); + expect(redoSuccess).toBe(true); + expect(editor.survey.surveyItems[newItemKey]).toBeDefined(); + expect((editor.survey.surveyItems['test-survey.group1'] as GroupItem).items).toContain(newItemKey); + }); + + test('should handle case where original item no longer exists', () => { + // Remove the original item first + editor.removeItem('test-survey.group1.Q1'); + + const clipboardData = copyPaste.copyItem('test-survey.group1.display1'); // Copy a different item + + // Should still be able to paste from clipboard even if original is gone + expect(() => { + const newItemKey = copyPaste.pasteItem(clipboardData, { + parentKey: 'test-survey.group1' + }); + expect(newItemKey).toBe('test-survey.group1.display1_copy'); + }).not.toThrow(); + }); + + test('should handle empty target parent gracefully', () => { + const clipboardData = copyPaste.copyItem('test-survey.group1.Q1'); + const newItemKey = copyPaste.pasteItem(clipboardData, { + parentKey: 'test-survey.group1' + }); + + expect(newItemKey).toBe('test-survey.group1.Q1_copy'); + }); + + test('should handle JSON serialization correctly', () => { + const originalClipboard = copyPaste.copyItem('test-survey.group1.display1'); + + // Simulate serialization/deserialization (e.g., through system clipboard) + const serialized = JSON.stringify(originalClipboard); + const deserialized = JSON.parse(serialized); + + // Should be able to paste from deserialized data + const newItemKey = copyPaste.pasteItem(deserialized, { + parentKey: 'test-survey.group1' + }); + + expect(survey.surveyItems[newItemKey]).toBeDefined(); + expect(survey.surveyItems[newItemKey].itemType).toBe(SurveyItemType.Display); + }); + }); + + // Component tests now using copyPaste for component operations + describe('copyComponent', () => { + beforeEach(() => { + // Add a title to the question for testing + const question = survey.surveyItems['test-survey.group1.Q1'] as SingleChoiceQuestionItem; + question.header = { + title: new TextComponent('title', undefined, 'test-survey.group1.Q1') + }; + + // Add top content to question body + question.body = { + topContent: [ + new TextComponent('topText', undefined, 'test-survey.group1.Q1') + ] + }; + + copyPaste = new CopyPaste(survey); + editor = new SurveyEditor(survey); + }); + + test('should copy a display component', () => { + const clipboardData = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); + + expect(clipboardData.type).toBe('survey-component'); + expect(clipboardData.version).toBe('1.0.0'); + expect(clipboardData.componentKey).toBe('text1'); + expect(clipboardData.parentItemKey).toBe('test-survey.group1.display1'); + expect(clipboardData.componentData).toBeDefined(); + expect(clipboardData.translations).toBeDefined(); + expect(clipboardData.timestamp).toBeGreaterThan(0); + }); + + test('should copy a question header component', () => { + const clipboardData = copyPaste.copyComponent('test-survey.group1.Q1', 'title'); + + expect(clipboardData.type).toBe('survey-component'); + expect(clipboardData.componentKey).toBe('title'); + expect(clipboardData.parentItemKey).toBe('test-survey.group1.Q1'); + }); + + test('should copy a question body component', () => { + const clipboardData = copyPaste.copyComponent('test-survey.group1.Q1', 'topText'); + + expect(clipboardData.type).toBe('survey-component'); + expect(clipboardData.componentKey).toBe('topText'); + expect(clipboardData.parentItemKey).toBe('test-survey.group1.Q1'); + }); + + test('should include component translations in clipboard data', () => { + const translations = new SurveyItemTranslations(); + translations.setContent('en', 'text1', { type: ContentType.CQM, content: 'Test Text', attributions: [] }); + editor.updateItemTranslations('test-survey.group1.display1', translations); + + const clipboardData = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); + + expect(clipboardData.translations['en']).toBeDefined(); + expect(clipboardData.translations['en']['text1']).toEqual({ + type: ContentType.CQM, + content: 'Test Text', + attributions: [] + }); + }); + + test('should throw error for non-existent item', () => { + expect(() => { + copyPaste.copyComponent('non-existent-item', 'text1'); + }).toThrow("Item with key 'non-existent-item' not found"); + }); + + test('should throw error for non-existent component', () => { + expect(() => { + copyPaste.copyComponent('test-survey.group1.display1', 'non-existent-component'); + }).toThrow("Component with key 'non-existent-component' not found in item 'test-survey.group1.display1'"); + }); + }); + + describe('pasteComponent', () => { + let clipboardData: SurveyComponentClipboardData; + + beforeEach(() => { + clipboardData = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); + }); + + test('should paste component to display item', () => { + const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1'); + + expect(newComponentKey).toBe('text1_copy'); + + const displayItem = survey.surveyItems['test-survey.group1.display1'] as DisplayItem; + expect(displayItem.components?.length).toBe(2); // Original + pasted + expect(displayItem.components?.[1].key.componentKey).toBe('text1_copy'); + }); + + test('should paste component to question item header', () => { + const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.Q1', { + section: 'header', + subSection: 'title' + }); + + expect(newComponentKey).toBe('text1_copy'); + + const questionItem = survey.surveyItems['test-survey.group1.Q1'] as SingleChoiceQuestionItem; + expect(questionItem.header?.title?.key.componentKey).toBe('text1_copy'); + }); + + test('should paste component to question item body', () => { + const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.Q1', { + section: 'body', + subSection: 'topContent' + }); + + expect(newComponentKey).toBe('text1_copy'); + + const questionItem = survey.surveyItems['test-survey.group1.Q1'] as SingleChoiceQuestionItem; + expect(questionItem.body?.topContent?.length).toBe(1); + expect(questionItem.body?.topContent?.[0].key.componentKey).toBe('text1_copy'); + }); + + test('should generate unique component keys for multiple pastes', () => { + const firstCopy = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1'); + const secondCopy = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1'); + const thirdCopy = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1'); + + expect(firstCopy).toBe('text1_copy'); + expect(secondCopy).toBe('text1_copy_2'); + expect(thirdCopy).toBe('text1_copy_3'); + + const displayItem = survey.surveyItems['test-survey.group1.display1'] as DisplayItem; + expect(displayItem.components?.length).toBe(4); // Original + 3 copies + }); + + test('should paste component at specified index', () => { + const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1', { + index: 0 + }); + + const displayItem = survey.surveyItems['test-survey.group1.display1'] as DisplayItem; + expect(displayItem.components?.[0].key.componentKey).toBe('text1_copy'); + }); + + test('should preserve component translations when pasting', () => { + const translations = new SurveyItemTranslations(); + translations.setContent('en', 'text1', { type: ContentType.CQM, content: 'Test Text', attributions: [] }); + editor.updateItemTranslations('test-survey.group1.display1', translations); + + const componentClipboard = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); + const newComponentKey = copyPaste.pasteComponent(componentClipboard, 'test-survey.group1.display1'); + + const newTranslations = survey.getItemTranslations('test-survey.group1.display1'); + expect(newTranslations?.getContent('en', newComponentKey)).toEqual({ + type: ContentType.CQM, + content: 'Test Text', + attributions: [] + }); + }); + + test('should paste component across different items', () => { + // Create a second display item + const display2 = new DisplayItem('test-survey.group1.display2'); + survey.surveyItems['test-survey.group1.display2'] = display2; + (survey.surveyItems['test-survey.group1'] as GroupItem).items?.push('test-survey.group1.display2'); + + const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display2'); + + expect(newComponentKey).toBe('text1_copy'); + + const targetItem = survey.surveyItems['test-survey.group1.display2'] as DisplayItem; + expect(targetItem.components?.length).toBe(1); + expect(targetItem.components?.[0].key.componentKey).toBe('text1_copy'); + }); + + test('should validate clipboard data format', () => { + const invalidClipboard = { + type: 'invalid-type', + version: '1.0.0', + componentKey: 'test', + parentItemKey: 'test', + componentData: {}, + translations: {}, + timestamp: Date.now() + }; + + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + copyPaste.pasteComponent(invalidClipboard as any, 'test-survey.group1.display1'); + }).toThrow('Invalid component clipboard data format'); + }); + + test('should validate required clipboard data fields', () => { + const incompleteClipboard = { + type: 'survey-component', + version: '1.0.0', + componentKey: 'test' + // Missing other required fields + }; + + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + copyPaste.pasteComponent(incompleteClipboard as any, 'test-survey.group1.display1'); + }).toThrow('Invalid component clipboard data format'); + }); + + test('should throw error for non-existent target item', () => { + expect(() => { + copyPaste.pasteComponent(clipboardData, 'non-existent-item'); + }).toThrow("Target item with key 'non-existent-item' not found"); + }); + + test('should handle undo/redo integration correctly', () => { + // Test that paste component operation is properly tracked in undo/redo history + const initialHistoryLength = editor.undoRedo.getHistory().length; + + // Perform paste operation using editor method + const newComponentKey = editor.pasteComponent(clipboardData, 'test-survey.group1.display1'); + + // Should have added an operation to history + expect(editor.undoRedo.getHistory().length).toBe(initialHistoryLength + 1); + expect(editor.hasUncommittedChanges).toBe(false); + + // Verify the component was pasted + const displayItem = editor.survey.surveyItems['test-survey.group1.display1'] as DisplayItem; + const pastedComponent = displayItem.components?.find(c => c.key.componentKey === newComponentKey); + expect(pastedComponent).toBeDefined(); + + // Test undo + const undoSuccess = editor.undo(); + expect(undoSuccess).toBe(true); + const undoDisplayItem = editor.survey.surveyItems['test-survey.group1.display1'] as DisplayItem; + const undoComponent = undoDisplayItem.components?.find(c => c.key.componentKey === newComponentKey); + expect(undoComponent).toBeUndefined(); + + // Test redo + const redoSuccess = editor.redo(); + expect(redoSuccess).toBe(true); + const redoDisplayItem = editor.survey.surveyItems['test-survey.group1.display1'] as DisplayItem; + const redoComponent = redoDisplayItem.components?.find(c => c.key.componentKey === newComponentKey); + expect(redoComponent).toBeDefined(); + }); + + test('should handle JSON serialization correctly', () => { + const clipboardData = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); + + // Simulate serialization/deserialization + const serialized = JSON.stringify(clipboardData); + const deserialized = JSON.parse(serialized); + + // Should be able to paste from deserialized data + const newComponentKey = copyPaste.pasteComponent(deserialized, 'test-survey.group1.display1'); + + const displayItem = survey.surveyItems['test-survey.group1.display1'] as DisplayItem; + expect(displayItem.components?.find(c => c.key.componentKey === newComponentKey)).toBeDefined(); + }); + }); + + // Add comprehensive translation copy-paste tests + describe('Translation Copy-Paste Tests', () => { + let surveyWithTranslations: Survey; + let editorWithTranslations: SurveyEditor; + let copyPasteWithTranslations: CopyPaste; + + beforeEach(() => { + // Create a survey with complex structure for testing translations + surveyWithTranslations = new Survey('translation-test'); + editorWithTranslations = new SurveyEditor(surveyWithTranslations); + copyPasteWithTranslations = new CopyPaste(surveyWithTranslations); + + // Create a group with multiple items + const mainGroup = new GroupItem('translation-test.main-group'); + surveyWithTranslations.surveyItems['translation-test.main-group'] = mainGroup; + (surveyWithTranslations.surveyItems['translation-test'] as GroupItem).items = ['translation-test.main-group']; + + // Create Q1 + const q1 = new SingleChoiceQuestionItem('translation-test.main-group.Q1'); + surveyWithTranslations.surveyItems['translation-test.main-group.Q1'] = q1; + + // Create Q2 + const q2 = new MultipleChoiceQuestionItem('translation-test.main-group.Q2'); + surveyWithTranslations.surveyItems['translation-test.main-group.Q2'] = q2; + + // Create info display item + const info = new DisplayItem('translation-test.main-group.info'); + info.components = [ + new TextComponent('comp1', undefined, 'translation-test.main-group.info'), + new TextComponent('comp2', undefined, 'translation-test.main-group.info') + ]; + surveyWithTranslations.surveyItems['translation-test.main-group.info'] = info; + + // Create nested group + const nestedGroup = new GroupItem('translation-test.main-group.nested-group'); + surveyWithTranslations.surveyItems['translation-test.main-group.nested-group'] = nestedGroup; + + // Create Q3 in nested group + const q3 = new SingleChoiceQuestionItem('translation-test.main-group.nested-group.Q3'); + surveyWithTranslations.surveyItems['translation-test.main-group.nested-group.Q3'] = q3; + + // Set up item hierarchy + mainGroup.items = [ + 'translation-test.main-group.Q1', + 'translation-test.main-group.Q2', + 'translation-test.main-group.info', + 'translation-test.main-group.nested-group' + ]; + nestedGroup.items = ['translation-test.main-group.nested-group.Q3']; + + // Add comprehensive translations for all items + + // Main group translations + const mainGroupTranslations = new SurveyItemTranslations(); + mainGroupTranslations.setContent('en', 'title', { + type: ContentType.CQM, + content: 'Main Survey Group', + attributions: [] + }); + mainGroupTranslations.setContent('es', 'title', { + type: ContentType.CQM, + content: 'Grupo Principal de Encuesta', + attributions: [] + }); + mainGroupTranslations.setContent('fr', 'title', { + type: ContentType.CQM, + content: 'Groupe Principal d\'Enquête', + attributions: [] + }); + editorWithTranslations.updateItemTranslations('translation-test.main-group', mainGroupTranslations); + + // Q1 translations (with component translations) + const q1Translations = new SurveyItemTranslations(); + q1Translations.setContent('en', 'title', { + type: ContentType.CQM, + content: 'What is your favorite color?', + attributions: [] + }); + q1Translations.setContent('en', 'rg.1', { + type: ContentType.CQM, + content: 'Red', + attributions: [] + }); + q1Translations.setContent('en', 'rg.2', { + type: ContentType.CQM, + content: 'Blue', + attributions: [] + }); + q1Translations.setContent('en', 'helpPopover', { + type: ContentType.CQM, + content: 'Choose your preferred color from the list', + attributions: [] + }); + + q1Translations.setContent('es', 'title', { + type: ContentType.CQM, + content: '¿Cuál es tu color favorito?', + attributions: [] + }); + q1Translations.setContent('es', 'rg.1', { + type: ContentType.CQM, + content: 'Rojo', + attributions: [] + }); + q1Translations.setContent('es', 'rg.2', { + type: ContentType.CQM, + content: 'Azul', + attributions: [] + }); + q1Translations.setContent('es', 'helpPopover', { + type: ContentType.CQM, + content: 'Elige tu color preferido de la lista', + attributions: [] + }); + + q1Translations.setContent('fr', 'title', { + type: ContentType.CQM, + content: 'Quelle est votre couleur préférée?', + attributions: [] + }); + q1Translations.setContent('fr', 'rg.1', { + type: ContentType.CQM, + content: 'Rouge', + attributions: [] + }); + q1Translations.setContent('fr', 'rg.2', { + type: ContentType.CQM, + content: 'Bleu', + attributions: [] + }); + q1Translations.setContent('fr', 'helpPopover', { + type: ContentType.CQM, + content: 'Choisissez votre couleur préférée dans la liste', + attributions: [] + }); + editorWithTranslations.updateItemTranslations('translation-test.main-group.Q1', q1Translations); + + // Q2 translations + const q2Translations = new SurveyItemTranslations(); + q2Translations.setContent('en', 'title', { + type: ContentType.CQM, + content: 'Which activities do you enjoy?', + attributions: [] + }); + q2Translations.setContent('en', 'subtitle', { + type: ContentType.CQM, + content: 'Select all that apply', + attributions: [] + }); + q2Translations.setContent('en', 'rg.1', { + type: ContentType.CQM, + content: 'Reading', + attributions: [] + }); + q2Translations.setContent('en', 'rg.2', { + type: ContentType.CQM, + content: 'Swimming', + attributions: [] + }); + q2Translations.setContent('en', 'rg.3', { + type: ContentType.CQM, + content: 'Hiking', + attributions: [] + }); + + q2Translations.setContent('es', 'title', { + type: ContentType.CQM, + content: '¿Qué actividades disfrutas?', + attributions: [] + }); + q2Translations.setContent('es', 'subtitle', { + type: ContentType.CQM, + content: 'Selecciona todas las que apliquen', + attributions: [] + }); + q2Translations.setContent('es', 'rg.1', { + type: ContentType.CQM, + content: 'Lectura', + attributions: [] + }); + q2Translations.setContent('es', 'rg.2', { + type: ContentType.CQM, + content: 'Natación', + attributions: [] + }); + q2Translations.setContent('es', 'rg.3', { + type: ContentType.CQM, + content: 'Senderismo', + attributions: [] + }); + editorWithTranslations.updateItemTranslations('translation-test.main-group.Q2', q2Translations); + + // Display item translations + const infoTranslations = new SurveyItemTranslations(); + infoTranslations.setContent('en', 'comp1', { + type: ContentType.CQM, + content: 'Thank you for participating in our survey!', + attributions: [] + }); + infoTranslations.setContent('en', 'comp2', { + type: ContentType.md, + content: 'Your responses help us **improve** our services.' + }); + + infoTranslations.setContent('es', 'comp1', { + type: ContentType.CQM, + content: '¡Gracias por participar en nuestra encuesta!', + attributions: [] + }); + infoTranslations.setContent('es', 'comp2', { + type: ContentType.md, + content: 'Tus respuestas nos ayudan a **mejorar** nuestros servicios.' + }); + editorWithTranslations.updateItemTranslations('translation-test.main-group.info', infoTranslations); + + // Nested group translations + const nestedGroupTranslations = new SurveyItemTranslations(); + nestedGroupTranslations.setContent('en', 'title', { + type: ContentType.CQM, + content: 'Additional Questions', + attributions: [] + }); + nestedGroupTranslations.setContent('es', 'title', { + type: ContentType.CQM, + content: 'Preguntas Adicionales', + attributions: [] + }); + editorWithTranslations.updateItemTranslations('translation-test.main-group.nested-group', nestedGroupTranslations); + + // Q3 translations (nested item) + const q3Translations = new SurveyItemTranslations(); + q3Translations.setContent('en', 'title', { + type: ContentType.CQM, + content: 'How satisfied are you overall?', + attributions: [] + }); + q3Translations.setContent('en', 'rg.1', { + type: ContentType.CQM, + content: 'Very Satisfied', + attributions: [] + }); + q3Translations.setContent('en', 'rg.2', { + type: ContentType.CQM, + content: 'Satisfied', + attributions: [] + }); + q3Translations.setContent('en', 'rg.3', { + type: ContentType.CQM, + content: 'Neutral', + attributions: [] + }); + q3Translations.setContent('en', 'rg.4', { + type: ContentType.CQM, + content: 'Dissatisfied', + attributions: [] + }); + + q3Translations.setContent('es', 'title', { + type: ContentType.CQM, + content: '¿Qué tan satisfecho estás en general?', + attributions: [] + }); + q3Translations.setContent('es', 'rg.1', { + type: ContentType.CQM, + content: 'Muy Satisfecho', + attributions: [] + }); + q3Translations.setContent('es', 'rg.2', { + type: ContentType.CQM, + content: 'Satisfecho', + attributions: [] + }); + q3Translations.setContent('es', 'rg.3', { + type: ContentType.CQM, + content: 'Neutral', + attributions: [] + }); + q3Translations.setContent('es', 'rg.4', { + type: ContentType.CQM, + content: 'Insatisfecho', + attributions: [] + }); + editorWithTranslations.updateItemTranslations('translation-test.main-group.nested-group.Q3', q3Translations); + }); + + test('should copy single item with all its translations', () => { + const clipboardData = copyPasteWithTranslations.copyItem('translation-test.main-group.Q1'); + + expect(clipboardData.items).toHaveLength(1); + expect(clipboardData.rootItemKey).toBe('translation-test.main-group.Q1'); + + // Check translations are copied + const itemTranslations = clipboardData.translations['translation-test.main-group.Q1']; + expect(itemTranslations).toBeDefined(); + expect(Object.keys(itemTranslations)).toContain('en'); + expect(Object.keys(itemTranslations)).toContain('es'); + expect(Object.keys(itemTranslations)).toContain('fr'); + + // Verify specific translation content + expect(itemTranslations['en']['title']).toEqual({ + type: ContentType.CQM, + content: 'What is your favorite color?', + attributions: [] + }); + expect(itemTranslations['es']['title']).toEqual({ + type: ContentType.CQM, + content: '¿Cuál es tu color favorito?', + attributions: [] + }); + expect(itemTranslations['fr']['title']).toEqual({ + type: ContentType.CQM, + content: 'Quelle est votre couleur préférée?', + attributions: [] + }); + + // Verify component translations + expect(itemTranslations['en']['rg.1']).toEqual({ + type: ContentType.CQM, + content: 'Red', + attributions: [] + }); + expect(itemTranslations['es']['rg.1']).toEqual({ + type: ContentType.CQM, + content: 'Rojo', + attributions: [] + }); + expect(itemTranslations['fr']['rg.1']).toEqual({ + type: ContentType.CQM, + content: 'Rouge', + attributions: [] + }); + }); + + test('should copy group with entire subtree and all translations', () => { + const clipboardData = copyPasteWithTranslations.copyItem('translation-test.main-group'); + + // Should include main group + 4 items (Q1, Q2, info, nested-group) + 1 nested item (Q3) = 6 total + expect(clipboardData.items).toHaveLength(6); + expect(clipboardData.rootItemKey).toBe('translation-test.main-group'); + + // Check all expected items are included + const itemKeys = clipboardData.items.map(item => item.itemKey).sort(); + expect(itemKeys).toEqual([ + 'translation-test.main-group', + 'translation-test.main-group.Q1', + 'translation-test.main-group.Q2', + 'translation-test.main-group.info', + 'translation-test.main-group.nested-group', + 'translation-test.main-group.nested-group.Q3' + ]); + + // Verify translations exist for all items + expect(Object.keys(clipboardData.translations)).toEqual(itemKeys); + + // Spot check some specific translations + const mainGroupTranslations = clipboardData.translations['translation-test.main-group']; + expect(mainGroupTranslations['en']['title']).toEqual({ + type: ContentType.CQM, + content: 'Main Survey Group', + attributions: [] + }); + expect(mainGroupTranslations['es']['title']).toEqual({ + type: ContentType.CQM, + content: 'Grupo Principal de Encuesta', + attributions: [] + }); + + const q3Translations = clipboardData.translations['translation-test.main-group.nested-group.Q3']; + expect(q3Translations['en']['title']).toEqual({ + type: ContentType.CQM, + content: 'How satisfied are you overall?', + attributions: [] + }); + expect(q3Translations['es']['rg.1']).toEqual({ + type: ContentType.CQM, + content: 'Muy Satisfecho', + attributions: [] + }); + }); + + test('should paste single item with properly updated translation keys', () => { + const clipboardData = copyPasteWithTranslations.copyItem('translation-test.main-group.Q1'); + + // Create target location + const newSection = new GroupItem('translation-test.new-section'); + surveyWithTranslations.surveyItems['translation-test.new-section'] = newSection; + (surveyWithTranslations.surveyItems['translation-test'] as GroupItem).items!.push('translation-test.new-section'); + + const newItemKey = copyPasteWithTranslations.pasteItem(clipboardData, { + parentKey: 'translation-test.new-section' + }); + + expect(newItemKey).toBe('translation-test.new-section.Q1'); + + // Verify the item was created + expect(surveyWithTranslations.surveyItems[newItemKey]).toBeDefined(); + + // Verify translations were properly updated with new keys + const pastedTranslations = surveyWithTranslations.getItemTranslations(newItemKey); + expect(pastedTranslations).toBeDefined(); + expect(pastedTranslations!.locales).toContain('en'); + expect(pastedTranslations!.locales).toContain('es'); + expect(pastedTranslations!.locales).toContain('fr'); + + // Verify translation content is preserved + expect(pastedTranslations!.getContent('en', 'title')).toEqual({ + type: ContentType.CQM, + content: 'What is your favorite color?', + attributions: [] + }); + expect(pastedTranslations!.getContent('es', 'rg.2')).toEqual({ + type: ContentType.CQM, + content: 'Azul', + attributions: [] + }); + expect(pastedTranslations!.getContent('fr', 'helpPopover')).toEqual({ + type: ContentType.CQM, + content: 'Choisissez votre couleur préférée dans la liste', + attributions: [] + }); + + // Verify original translations are still intact + const originalTranslations = surveyWithTranslations.getItemTranslations('translation-test.main-group.Q1'); + expect(originalTranslations!.getContent('en', 'title')).toEqual({ + type: ContentType.CQM, + content: 'What is your favorite color?', + attributions: [] + }); + }); + + test('should paste group subtree with properly updated translation keys for all items', () => { + const clipboardData = copyPasteWithTranslations.copyItem('translation-test.main-group'); + + // Create target location + const copiedSection = new GroupItem('translation-test.copied-section'); + surveyWithTranslations.surveyItems['translation-test.copied-section'] = copiedSection; + (surveyWithTranslations.surveyItems['translation-test'] as GroupItem).items!.push('translation-test.copied-section'); + + const newRootKey = copyPasteWithTranslations.pasteItem(clipboardData, { + parentKey: 'translation-test.copied-section' + }); + + expect(newRootKey).toBe('translation-test.copied-section.main-group'); + + // Verify all items were created with correct keys + const expectedNewKeys = [ + 'translation-test.copied-section.main-group', + 'translation-test.copied-section.main-group.Q1', + 'translation-test.copied-section.main-group.Q2', + 'translation-test.copied-section.main-group.info', + 'translation-test.copied-section.main-group.nested-group', + 'translation-test.copied-section.main-group.nested-group.Q3' + ]; + + expectedNewKeys.forEach(key => { + expect(surveyWithTranslations.surveyItems[key]).toBeDefined(); + }); + + // Verify translations were properly updated for all items + expectedNewKeys.forEach(key => { + const translations = surveyWithTranslations.getItemTranslations(key); + expect(translations).toBeDefined(); + expect(translations!.locales.length).toBeGreaterThan(0); + }); + + // Spot check specific translations + const copiedQ1Translations = surveyWithTranslations.getItemTranslations('translation-test.copied-section.main-group.Q1'); + expect(copiedQ1Translations!.getContent('en', 'title')).toEqual({ + type: ContentType.CQM, + content: 'What is your favorite color?', + attributions: [] + }); + expect(copiedQ1Translations!.getContent('es', 'rg.1')).toEqual({ + type: ContentType.CQM, + content: 'Rojo', + attributions: [] + }); + + const copiedQ3Translations = surveyWithTranslations.getItemTranslations('translation-test.copied-section.main-group.nested-group.Q3'); + expect(copiedQ3Translations!.getContent('en', 'rg.3')).toEqual({ + type: ContentType.CQM, + content: 'Neutral', + attributions: [] + }); + expect(copiedQ3Translations!.getContent('es', 'rg.4')).toEqual({ + type: ContentType.CQM, + content: 'Insatisfecho', + attributions: [] + }); + + // Verify original translations are still intact + const originalQ1Translations = surveyWithTranslations.getItemTranslations('translation-test.main-group.Q1'); + expect(originalQ1Translations!.getContent('fr', 'title')).toEqual({ + type: ContentType.CQM, + content: 'Quelle est votre couleur préférée?', + attributions: [] + }); + }); + + test('should handle multiple pastes with unique keys and preserved translations', () => { + const clipboardData = copyPasteWithTranslations.copyItem('translation-test.main-group.Q2'); + + // Create target location + const multipleCopies = new GroupItem('translation-test.multiple-copies'); + surveyWithTranslations.surveyItems['translation-test.multiple-copies'] = multipleCopies; + (surveyWithTranslations.surveyItems['translation-test'] as GroupItem).items!.push('translation-test.multiple-copies'); + + // Paste the same item multiple times + const firstCopy = copyPasteWithTranslations.pasteItem(clipboardData, { + parentKey: 'translation-test.multiple-copies' + }); + const secondCopy = copyPasteWithTranslations.pasteItem(clipboardData, { + parentKey: 'translation-test.multiple-copies' + }); + const thirdCopy = copyPasteWithTranslations.pasteItem(clipboardData, { + parentKey: 'translation-test.multiple-copies' + }); + + expect(firstCopy).toBe('translation-test.multiple-copies.Q2'); + expect(secondCopy).toBe('translation-test.multiple-copies.Q2_copy'); + expect(thirdCopy).toBe('translation-test.multiple-copies.Q2_copy_2'); + + // Verify all copies have proper translations + [firstCopy, secondCopy, thirdCopy].forEach(key => { + const translations = surveyWithTranslations.getItemTranslations(key); + expect(translations).toBeDefined(); + expect(translations!.locales).toContain('en'); + expect(translations!.locales).toContain('es'); + + expect(translations!.getContent('en', 'title')).toEqual({ + type: ContentType.CQM, + content: 'Which activities do you enjoy?', + attributions: [] + }); + expect(translations!.getContent('es', 'subtitle')).toEqual({ + type: ContentType.CQM, + content: 'Selecciona todas las que apliquen', + attributions: [] + }); + expect(translations!.getContent('en', 'rg.3')).toEqual({ + type: ContentType.CQM, + content: 'Hiking', + attributions: [] + }); + }); + }); + + test('should preserve different content types in translations', () => { + const clipboardData = copyPasteWithTranslations.copyItem('translation-test.main-group.info'); + + // Create target location + const infoCopy = new GroupItem('translation-test.info-copy'); + surveyWithTranslations.surveyItems['translation-test.info-copy'] = infoCopy; + (surveyWithTranslations.surveyItems['translation-test'] as GroupItem).items!.push('translation-test.info-copy'); + + const newItemKey = copyPasteWithTranslations.pasteItem(clipboardData, { + parentKey: 'translation-test.info-copy' + }); + + const pastedTranslations = surveyWithTranslations.getItemTranslations(newItemKey); + expect(pastedTranslations).toBeDefined(); + + // Verify CQM content type is preserved + expect(pastedTranslations!.getContent('en', 'comp1')).toEqual({ + type: ContentType.CQM, + content: 'Thank you for participating in our survey!', + attributions: [] + }); + expect(pastedTranslations!.getContent('es', 'comp1')).toEqual({ + type: ContentType.CQM, + content: '¡Gracias por participar en nuestra encuesta!', + attributions: [] + }); + + // Verify Markdown content type is preserved + expect(pastedTranslations!.getContent('en', 'comp2')).toEqual({ + type: ContentType.md, + content: 'Your responses help us **improve** our services.' + }); + expect(pastedTranslations!.getContent('es', 'comp2')).toEqual({ + type: ContentType.md, + content: 'Tus respuestas nos ayudan a **mejorar** nuestros servicios.' + }); + }); + + test('should handle JSON serialization/deserialization of translations correctly', () => { + const clipboardData = copyPasteWithTranslations.copyItem('translation-test.main-group.Q1'); + + // Serialize to JSON and back (simulating clipboard operations) + const jsonString = JSON.stringify(clipboardData); + const deserializedData = JSON.parse(jsonString) as SurveyItemClipboardData; + + // Create target location + const jsonTest = new GroupItem('translation-test.json-test'); + surveyWithTranslations.surveyItems['translation-test.json-test'] = jsonTest; + (surveyWithTranslations.surveyItems['translation-test'] as GroupItem).items!.push('translation-test.json-test'); + + const newItemKey = copyPasteWithTranslations.pasteItem(deserializedData, { + parentKey: 'translation-test.json-test' + }); + + // Verify translations work after JSON round-trip + const pastedTranslations = surveyWithTranslations.getItemTranslations(newItemKey); + expect(pastedTranslations).toBeDefined(); + + expect(pastedTranslations!.getContent('en', 'title')).toEqual({ + type: ContentType.CQM, + content: 'What is your favorite color?', + attributions: [] + }); + expect(pastedTranslations!.getContent('fr', 'rg.2')).toEqual({ + type: ContentType.CQM, + content: 'Bleu', + attributions: [] + }); + }); + }); +}); + +describe('SurveyEditor - Smart Component Copy-Paste', () => { + let editor: SurveyEditor; + let survey: Survey; + + beforeEach(() => { + // Create a test survey with a single choice question + survey = new Survey('test-survey'); + const rootGroup = new GroupItem('root'); + rootGroup.items = []; + survey.surveyItems['root'] = rootGroup; + + const questionItem = new SingleChoiceQuestionItem('root.q1'); + // Initialize the question with basic structure + questionItem.header = { + title: new TextComponent('title', undefined, 'root.q1'), + subtitle: new TextComponent('subtitle', undefined, 'root.q1') + }; + questionItem.body = { + topContent: [] + }; + questionItem.responseConfig = new ScgMcgChoiceResponseConfig('rg', undefined, 'root.q1'); + questionItem.responseConfig.items = [ + new ScgMcgOption('1', 'rg', 'root.q1'), + new ScgMcgOption('2', 'rg', 'root.q1') + ]; + + survey.surveyItems['root.q1'] = questionItem; + rootGroup.items.push('root.q1'); + + editor = new SurveyEditor(survey); + }); + + describe('Single-slot component replacement', () => { + test('should replace title component when pasting into title', () => { + const originalTitle = (editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem).header!.title!; + + // Copy the title component + const clipboardData = editor.copyComponent('root.q1', 'title'); + + // Paste it back into the title slot - should replace + const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'title'); + + const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; + const newTitle = questionItem.header!.title!; + + // Should have replaced the component + expect(newTitle.key.fullKey).toBe(newComponentKey); + expect(newTitle.key.fullKey).not.toBe(originalTitle.key.fullKey); + expect(newTitle.key.componentKey).toBe('title_copy'); + }); + + test('should replace subtitle component when pasting into subtitle', () => { + const originalSubtitle = (editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem).header!.subtitle!; + + // Copy the subtitle component + const clipboardData = editor.copyComponent('root.q1', 'subtitle'); + + // Paste it into the subtitle slot - should replace + const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'subtitle'); + + const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; + const newSubtitle = questionItem.header!.subtitle!; + + // Should have replaced the component + expect(newSubtitle.key.fullKey).toBe(newComponentKey); + expect(newSubtitle.key.fullKey).not.toBe(originalSubtitle.key.fullKey); + expect(newSubtitle.key.componentKey).toBe('subtitle_copy'); + }); + }); + + describe('Group component addition', () => { + test('should add new option when pasting into response config', () => { + const originalOptionsCount = (editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem).responseConfig.items.length; + + // Copy an existing option + const clipboardData = editor.copyComponent('root.q1', 'rg.1'); + + // Paste it into the response config - should add new option + const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'rg'); + + const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; + const newOptionsCount = questionItem.responseConfig.items.length; + + // Should have added a new option + expect(newOptionsCount).toBe(originalOptionsCount + 1); + expect(newComponentKey).toBe('rg.1_copy'); + + // Verify the new option exists + const newOption = questionItem.responseConfig.items.find(opt => opt.key.fullKey === newComponentKey); + expect(newOption).toBeDefined(); + expect(newOption!.componentType).toBe(ItemComponentType.ScgMcgOption); + }); + + test('should add to topContent when pasting into topContent area', () => { + const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; + const originalTopContentCount = questionItem.body!.topContent?.length || 0; + + // Create a text component to copy + const textComponent = new TextComponent('test-text', undefined, 'root.q1'); + questionItem.body!.topContent = questionItem.body!.topContent || []; + questionItem.body!.topContent.push(textComponent); + + // Copy the text component + const clipboardData = editor.copyComponent('root.q1', 'test-text'); + + // Paste it into topContent - should add new component + const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'test-text'); + + const updatedTopContentCount = questionItem.body!.topContent!.length; + + // Should have added a new component + expect(updatedTopContentCount).toBe(originalTopContentCount + 2); // original + copied + expect(newComponentKey).toBe('test-text_copy'); + + // Verify the new component exists + const newComponent = questionItem.body!.topContent!.find(comp => comp.key.fullKey === newComponentKey); + expect(newComponent).toBeDefined(); + expect(newComponent!.componentType).toBe(ItemComponentType.Text); + }); + }); + + describe('Fallback to default behavior', () => { + test('should use default behavior when no target component is specified', () => { + const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; + + // Create a text component to copy + const textComponent = new TextComponent('test-text', undefined, 'root.q1'); + questionItem.body!.topContent = questionItem.body!.topContent || []; + questionItem.body!.topContent.push(textComponent); + + // Copy the text component + const clipboardData = editor.copyComponent('root.q1', 'test-text'); + + // Paste without specifying target component - should use default behavior + const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1'); + + // Should have added to default location (topContent) + const addedComponent = questionItem.body!.topContent!.find(comp => comp.key.fullKey === newComponentKey); + expect(addedComponent).toBeDefined(); + expect(newComponentKey).toBe('test-text_copy'); + }); + }); + + describe('Error handling', () => { + test('should throw error when target item does not exist', () => { + const clipboardData = editor.copyComponent('root.q1', 'title'); + + expect(() => { + editor.pasteComponent(clipboardData, 'nonexistent.item', 'title'); + }).toThrow("Target item with key 'nonexistent.item' not found"); + }); + + test('should handle non-existent target component gracefully', () => { + const clipboardData = editor.copyComponent('root.q1', 'title'); + + // This should not throw and should use fallback logic + expect(() => { + const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'nonexistent-component'); + expect(newComponentKey).toBeDefined(); + }).not.toThrow(); + }); + }); +}); diff --git a/src/survey-editor/copy-paste.ts b/src/survey-editor/copy-paste.ts new file mode 100644 index 0000000..8e812b9 --- /dev/null +++ b/src/survey-editor/copy-paste.ts @@ -0,0 +1,1162 @@ +import { Survey } from "../survey/survey"; +import { SurveyItem, GroupItem, SurveyItemType, DisplayItem, QuestionItem } from "../survey/items"; +import { SurveyItemTranslations, JsonComponentContent } from "../survey/utils"; +import { SurveyItemKey, ItemComponentKey } from "../survey/item-component-key"; +import { JsonSurveyItem } from "../survey/items/survey-item-json"; +import { JsonSurveyItemResponse } from "../survey/responses"; +import { ItemComponent, DisplayComponent, TextComponent, GroupComponent, ItemComponentType, ScgMcgChoiceResponseConfig, ScgMcgOptionBase } from "../survey/components"; + +// Serialized translation data format for clipboard +export type SerializedTranslations = { + [locale: string]: JsonComponentContent; +}; + +// Clipboard data structure for copy-paste functionality +export interface SurveyItemClipboardData { + type: 'survey-item'; + version: string; + items: Array<{ + itemKey: string; + itemData: JsonSurveyItem; + }>; + translations: { [itemKey: string]: SerializedTranslations }; + prefills: { [itemKey: string]: JsonSurveyItemResponse }; + rootItemKey: string; // The key of the main item being copied + timestamp: number; +} + +// Clipboard data structure for component copy-paste functionality +export interface SurveyComponentClipboardData { + type: 'survey-component'; + version: string; + componentData: unknown; // JSON representation of the component + componentKey: string; + parentItemKey: string; + translations: { [locale: string]: { [contentKey: string]: unknown } }; + timestamp: number; +} + +export class CopyPaste { + private survey: Survey; + + constructor(survey: Survey) { + this.survey = survey; + } + + // ITEM COPY-PASTE FUNCTIONALITY + + /** + * Copy a survey item and all its data to clipboard format + * When copying a group, automatically includes all items in the subtree + * @param itemKey - The full key of the item to copy + * @returns Clipboard data that can be serialized to JSON for clipboard + */ + copyItem(itemKey: string): SurveyItemClipboardData { + const item = this.survey.surveyItems[itemKey]; + if (!item) { + throw new Error(`Item with key '${itemKey}' not found`); + } + + // Collect all items to copy (including subtree for groups) + const itemsToCopy = this.collectItemsForCopy(itemKey); + + // Create items array with their data + const items = itemsToCopy.map(key => ({ + itemKey: key, + itemData: this.survey.surveyItems[key].toJson() + })); + + // Collect translations for all items + const translations: { [itemKey: string]: SerializedTranslations } = {}; + itemsToCopy.forEach(key => { + const itemTranslations = this.survey.getItemTranslations(key); + if (itemTranslations) { + // Serialize the translations to plain object format + const serializedTranslations: SerializedTranslations = {}; + itemTranslations.locales.forEach(locale => { + const localeContent = itemTranslations.getAllForLocale(locale); + if (localeContent) { + serializedTranslations[locale] = localeContent; + } + }); + translations[key] = serializedTranslations; + } else { + translations[key] = {}; + } + }); + + // Collect prefills for all items (if any exist) + const prefills: { [itemKey: string]: JsonSurveyItemResponse } = {}; + // Note: Prefills would typically come from the survey engine context + // For now, we'll create empty prefills structure that can be populated if needed + itemsToCopy.forEach(key => { + const surveyItem = this.survey.surveyItems[key]; + if (surveyItem.itemType !== SurveyItemType.Group && + surveyItem.itemType !== SurveyItemType.Display && + surveyItem.itemType !== SurveyItemType.PageBreak && + surveyItem.itemType !== SurveyItemType.SurveyEnd) { + // Create empty prefill structure for response items + prefills[key] = { + key: key, + itemType: surveyItem.itemType, + response: undefined + }; + } + }); + + // Create clipboard data + const clipboardData: SurveyItemClipboardData = { + type: 'survey-item', + version: '1.0.0', + items: items, + translations: translations, + prefills: prefills, + rootItemKey: itemKey, + timestamp: Date.now() + }; + + return clipboardData; + } + + /** + * Collect all items that should be copied, including subtree for groups + * @param itemKey - The root item key + * @returns Array of item keys to copy + */ + private collectItemsForCopy(itemKey: string): string[] { + const itemsToCopy: string[] = [itemKey]; + const item = this.survey.surveyItems[itemKey]; + + // If this is a group item, collect all child items recursively + if (item.itemType === SurveyItemType.Group) { + const groupItem = item as GroupItem; + if (groupItem.items) { + groupItem.items.forEach(childKey => { + // Recursively collect child items and their subtrees + const childItems = this.collectItemsForCopy(childKey); + itemsToCopy.push(...childItems); + }); + } + } + + return itemsToCopy; + } + + /** + * Update component parent item keys within item data + * @param itemData - The item data to update + * @param keyMapping - Mapping from old keys to new keys + */ + private updateComponentParentItemKeys(itemData: any, keyMapping: { [oldKey: string]: string }): void { + // Update component keys that reference parent items + this.updateComponentKeysRecursively(itemData, keyMapping); + } + + /** + * Recursively update component keys in item data + * @param data - The data object to update + * @param keyMapping - Mapping from old keys to new keys + */ + private updateComponentKeysRecursively(data: any, keyMapping: { [oldKey: string]: string }): void { + if (!data || typeof data !== 'object') return; + + // Update key field if it exists and has a mapping + if (data.key && typeof data.key === 'string' && keyMapping[data.key]) { + data.key = keyMapping[data.key]; + } + + // Recursively update nested objects and arrays + Object.keys(data).forEach(key => { + if (Array.isArray(data[key])) { + data[key].forEach((item: any) => this.updateComponentKeysRecursively(item, keyMapping)); + } else if (data[key] && typeof data[key] === 'object') { + this.updateComponentKeysRecursively(data[key], keyMapping); + } + }); + } + + /** + * Update prefill keys and store them (placeholder for future implementation) + * @param prefills - The prefills to update + * @param keyMapping - Mapping from old keys to new keys + */ + private updatePrefills(prefills: { [itemKey: string]: JsonSurveyItemResponse }, keyMapping: { [oldKey: string]: string }): void { + // Update prefill keys according to the key mapping + Object.keys(prefills).forEach(oldKey => { + const newKey = keyMapping[oldKey]; + if (newKey && newKey !== oldKey) { + const prefill = prefills[oldKey]; + prefill.key = newKey; + // Note: In a full implementation, these would be stored in the survey engine context + // For now, we just update the keys for consistency + } + }); + } + + /** + * Add an item to its parent group + * @param target - Target location information + * @param item - The item to add + */ + private addItemToParentGroup(target: { parentKey: string; index?: number }, item: SurveyItem): void { + // Find the parent group item + const parentGroup = this.survey.surveyItems[target.parentKey] as GroupItem; + + if (!parentGroup) { + throw new Error(`Parent item with key '${target.parentKey}' not found`); + } + + if (parentGroup.itemType !== SurveyItemType.Group) { + throw new Error(`Parent item '${target.parentKey}' is not a group item`); + } + + // Initialize items array if it doesn't exist + if (!parentGroup.items) { + parentGroup.items = []; + } + + // Determine insertion index + let insertIndex: number; + if (target.index !== undefined) { + // Insert at specified index, or at end if index is larger than array length + insertIndex = Math.min(target.index, parentGroup.items.length); + } else { + // Insert at the end + insertIndex = parentGroup.items.length; + } + + // Add the item key to the parent group's items array + parentGroup.items.splice(insertIndex, 0, item.key.fullKey); + } + + /** + * Paste a survey item from clipboard data to a target location + * Handles multiple items and subtrees from the clipboard data + * @param clipboardData - The clipboard data containing the item(s) to paste + * @param target - Target location where to paste the item + * @returns The full key of the pasted root item + */ + pasteItem(clipboardData: SurveyItemClipboardData, target: { + parentKey: string; + index?: number; + }): string { + // Validate clipboard data + if (!this.isValidClipboardData(clipboardData)) { + throw new Error('Invalid clipboard data format'); + } + + // Generate a new unique key for the root item + const originalRootKey = SurveyItemKey.fromFullKey(clipboardData.rootItemKey); + const newRootKey = this.generateUniqueItemKey(originalRootKey.itemKey, target.parentKey); + const newRootFullKey = target.parentKey ? `${target.parentKey}.${newRootKey}` : newRootKey; + + // Create key mapping for all items in the subtree + const keyMapping: { [oldKey: string]: string } = {}; + clipboardData.items.forEach(({ itemKey }) => { + if (itemKey === clipboardData.rootItemKey) { + keyMapping[itemKey] = newRootFullKey; + } else if (itemKey.startsWith(clipboardData.rootItemKey + '.')) { + // Update child keys to use the new root + const relativePath = itemKey.substring(clipboardData.rootItemKey.length + 1); + keyMapping[itemKey] = `${newRootFullKey}.${relativePath}`; + } else { + // This shouldn't happen if data is consistent, but handle gracefully + keyMapping[itemKey] = itemKey; + } + }); + + // Create all items with updated keys + const createdItems: { [newKey: string]: SurveyItem } = {}; + clipboardData.items.forEach(({ itemKey, itemData }) => { + const newKey = keyMapping[itemKey]; + if (newKey) { + // Update item data with new keys + const updatedItemData = this.updateItemKeysInData(itemData, itemKey, newKey); + + // Update component parent item keys within the item + this.updateComponentParentItemKeys(updatedItemData, keyMapping); + + // Create the new item from JSON + const newItem = SurveyItem.fromJson(newKey, updatedItemData); + createdItems[newKey] = newItem; + + // Add to survey items collection + this.survey.surveyItems[newKey] = newItem; + } + }); + + // Update translations with new keys + const updatedTranslations = this.updateTranslationKeys(clipboardData.translations, clipboardData.rootItemKey, newRootFullKey); + Object.keys(updatedTranslations).forEach(itemKey => { + // Convert serialized translations back to SurveyItemTranslations instance + const itemTranslations = new SurveyItemTranslations(); + const serializedData = updatedTranslations[itemKey]; + Object.keys(serializedData).forEach(locale => { + itemTranslations.setAllForLocale(locale, serializedData[locale]); + }); + this.survey.translations.setItemTranslations(itemKey, itemTranslations); + }); + + // Update and set prefills + this.updatePrefills(clipboardData.prefills, keyMapping); + + // Add the root item to the parent group + const rootItem = createdItems[newRootFullKey]; + if (rootItem) { + this.addItemToParentGroup(target, rootItem); + } + + return newRootFullKey; + } + + // COMPONENT COPY-PASTE FUNCTIONALITY + + /** + * Copy a component from an item + * @param itemKey - The full key of the item containing the component + * @param componentKey - The full key of the component to copy + * @returns Clipboard data for the component + */ + copyComponent(itemKey: string, componentKey: string): SurveyComponentClipboardData { + const item = this.survey.surveyItems[itemKey]; + if (!item) { + throw new Error(`Item with key '${itemKey}' not found`); + } + + // Find the component within the item + const component = this.findComponentInItem(item, componentKey); + if (!component) { + throw new Error(`Component with key '${componentKey}' not found in item '${itemKey}'`); + } + + // Get component translations + const itemTranslations = this.survey.getItemTranslations(itemKey); + const componentTranslations: { [locale: string]: { [contentKey: string]: any } } = {}; + + if (itemTranslations) { + itemTranslations.locales.forEach(locale => { + const localeContent = itemTranslations.getAllForLocale(locale); + if (localeContent) { + // Extract translations that match this component key + const componentLocaleContent: { [contentKey: string]: any } = {}; + Object.keys(localeContent).forEach(contentKey => { + if (contentKey === componentKey || contentKey.startsWith(componentKey + '.')) { + componentLocaleContent[contentKey] = localeContent[contentKey]; + } + }); + if (Object.keys(componentLocaleContent).length > 0) { + componentTranslations[locale] = componentLocaleContent; + } + } + }); + } + + return { + type: 'survey-component', + version: '1.0.0', + componentData: component.toJson(), + componentKey: componentKey, + parentItemKey: itemKey, + translations: componentTranslations, + timestamp: Date.now() + }; + } + + /** + * Paste a component into an item + * @param clipboardData - The clipboard data containing the component to paste + * @param targetItemKey - The item to paste the component into + * @param targetLocation - Where to insert the component (optional) + * @returns The full key of the pasted component + */ + pasteComponent( + clipboardData: SurveyComponentClipboardData, + targetItemKey: string, + targetLocation?: { + parentComponentKey?: string; + section?: 'header' | 'body' | 'footer' | 'responseConfig' | 'components'; + subSection?: 'title' | 'subtitle' | 'helpPopover' | 'topContent' | 'bottomContent'; + index?: number; + } + ): string { + // Validate clipboard data + if (!this.isValidComponentClipboardData(clipboardData)) { + throw new Error('Invalid component clipboard data format'); + } + + const targetItem = this.survey.surveyItems[targetItemKey]; + if (!targetItem) { + throw new Error(`Target item with key '${targetItemKey}' not found`); + } + + // Generate unique component key + const originalComponentKey = ItemComponentKey.fromFullKey(clipboardData.componentKey, clipboardData.parentItemKey); + const newComponentKey = this.generateUniqueComponentKey(originalComponentKey.componentKey, targetItemKey, targetLocation?.parentComponentKey); + const newFullComponentKey = targetLocation?.parentComponentKey ? + `${targetLocation.parentComponentKey}.${newComponentKey}` : + newComponentKey; + + // Update component data with new keys + const updatedComponentData = this.updateComponentKeysInData( + clipboardData.componentData, + clipboardData.componentKey, + newFullComponentKey, + targetItemKey + ); + + // Create the component from JSON + const newComponent = this.createComponentFromJson(updatedComponentData, targetLocation?.parentComponentKey, targetItemKey); + + // Insert component into the target item + this.insertComponentIntoItem(targetItem, newComponent, targetLocation); + + // Update translations + this.updateComponentTranslations(targetItemKey, clipboardData.translations, clipboardData.componentKey, newFullComponentKey); + + return newFullComponentKey; + } + + /** + * Paste a component into an item with intelligent placement based on target component + * @param clipboardData - The clipboard data containing the component to paste + * @param targetItemKey - The item to paste the component into + * @param targetComponentKey - The component key to paste into (if undefined, uses default behavior) + * @returns The full key of the pasted component + */ + pasteComponentSmart( + clipboardData: SurveyComponentClipboardData, + targetItemKey: string, + targetComponentKey?: string + ): string { + // If no target component specified, use default behavior + if (!targetComponentKey) { + return this.pasteComponent(clipboardData, targetItemKey); + } + + // Validate clipboard data + if (!this.isValidComponentClipboardData(clipboardData)) { + throw new Error('Invalid component clipboard data format'); + } + + const targetItem = this.survey.surveyItems[targetItemKey]; + if (!targetItem) { + throw new Error(`Target item with key '${targetItemKey}' not found`); + } + + // Find the target component to determine paste behavior + const targetComponent = this.findComponentInItem(targetItem, targetComponentKey); + const pasteInfo = this.determinePasteLocation(targetItem, targetComponentKey, targetComponent); + + // Generate unique component key + const originalComponentKey = ItemComponentKey.fromFullKey(clipboardData.componentKey, clipboardData.parentItemKey); + const newComponentKey = this.generateUniqueComponentKey(originalComponentKey.componentKey, targetItemKey, pasteInfo.parentComponentKey); + const newFullComponentKey = pasteInfo.parentComponentKey ? + `${pasteInfo.parentComponentKey}.${newComponentKey}` : + newComponentKey; + + // Update component data with new keys + const updatedComponentData = this.updateComponentKeysInData( + clipboardData.componentData, + clipboardData.componentKey, + newFullComponentKey, + targetItemKey + ); + + // Create the component from JSON + const newComponent = this.createComponentFromJson(updatedComponentData, pasteInfo.parentComponentKey, targetItemKey); + + // Insert component based on determined location + if (pasteInfo.shouldReplace && targetComponent) { + this.replaceComponent(targetItem, targetComponent, newComponent, pasteInfo); + } else { + this.insertComponentIntoItem(targetItem, newComponent, pasteInfo.location); + } + + // Update translations + this.updateComponentTranslations(targetItemKey, clipboardData.translations, clipboardData.componentKey, newFullComponentKey); + + return newFullComponentKey; + } + + // PRIVATE HELPER METHODS + + /** + * Validate clipboard data format + */ + private isValidClipboardData(data: any): data is SurveyItemClipboardData { + return ( + data && + typeof data === 'object' && + data.type === 'survey-item' && + data.version && + data.items && + Array.isArray(data.items) && + data.items.length > 0 && + data.items.every((item: any) => + item && + typeof item === 'object' && + item.itemKey && + typeof item.itemKey === 'string' && + item.itemData && + typeof item.itemData === 'object' + ) && + data.translations && + typeof data.translations === 'object' && + data.prefills && + typeof data.prefills === 'object' && + data.rootItemKey && + typeof data.rootItemKey === 'string' && + typeof data.timestamp === 'number' + ); + } + + /** + * Validate component clipboard data format + */ + private isValidComponentClipboardData(data: any): data is SurveyComponentClipboardData { + return ( + data && + typeof data === 'object' && + data.type === 'survey-component' && + data.version && + data.componentData && + data.componentKey && + data.parentItemKey && + data.translations && + typeof data.timestamp === 'number' + ); + } + + /** + * Generate a unique item key within the target parent + */ + private generateUniqueItemKey(baseKey: string, parentKey?: string): string { + const targetParentKey = parentKey || ''; + let counter = 0; + let candidateKey = baseKey; + + // Try the original key first + let candidateFullKey = targetParentKey ? `${targetParentKey}.${candidateKey}` : candidateKey; + + while (this.survey.surveyItems[candidateFullKey]) { + counter++; + candidateKey = `${baseKey}_copy${counter > 1 ? `_${counter}` : ''}`; + candidateFullKey = targetParentKey ? `${targetParentKey}.${candidateKey}` : candidateKey; + } + + return candidateKey; + } + + /** + * Generate a unique component key within the target item + */ + private generateUniqueComponentKey(baseKey: string, targetItemKey: string, parentComponentKey?: string): string { + let counter = 1; + let candidateKey = `${baseKey}_copy`; + + // Keep incrementing until we find a unique key + while (this.componentKeyExists(targetItemKey, candidateKey, parentComponentKey)) { + counter++; + candidateKey = `${baseKey}_copy_${counter}`; + } + + return candidateKey; + } + + /** + * Check if a component key already exists in the target item + */ + private componentKeyExists(itemKey: string, componentKey: string, parentComponentKey?: string): boolean { + const fullComponentKey = parentComponentKey ? `${parentComponentKey}.${componentKey}` : componentKey; + const item = this.survey.surveyItems[itemKey]; + if (!item) return false; + + return this.findComponentInItem(item, fullComponentKey) !== null; + } + + /** + * Update all item keys in the JSON data recursively + */ + private updateItemKeysInData(itemData: JsonSurveyItem, oldFullKey: string, newFullKey: string): JsonSurveyItem { + const updatedData = JSON.parse(JSON.stringify(itemData)); // Deep clone + + // If this is a group item, update all child item keys + if (updatedData.itemType === SurveyItemType.Group && updatedData.items) { + updatedData.items = updatedData.items.map((childKey: string) => { + const oldChildKey = SurveyItemKey.fromFullKey(childKey); + const newChildKey = new SurveyItemKey(oldChildKey.itemKey, newFullKey); + return newChildKey.fullKey; + }); + } + + // Update expressions that reference the old keys + this.updateExpressionsInItemData(updatedData, oldFullKey, newFullKey); + + return updatedData; + } + + /** + * Update component keys in component data + */ + private updateComponentKeysInData(componentData: any, oldFullKey: string, newFullKey: string, newItemKey: string): any { + const updatedData = JSON.parse(JSON.stringify(componentData)); // Deep clone + + // Update the main component key + updatedData.key = newFullKey; + + // If this is a group component with nested items, update their keys + if (updatedData.items && Array.isArray(updatedData.items)) { + updatedData.items = updatedData.items.map((childData: any) => { + if (childData.key && childData.key.startsWith(oldFullKey + '.')) { + const oldChildKey = ItemComponentKey.fromFullKey(childData.key, this.survey.surveyItems[newItemKey].key.fullKey); + const newChildKey = new ItemComponentKey(oldChildKey.componentKey, newFullKey, newItemKey); + return this.updateComponentKeysInData(childData, childData.key, newChildKey.fullKey, newItemKey); + } + return childData; + }); + } + + return updatedData; + } + + /** + * Update expressions in item data that reference the old keys + */ + private updateExpressionsInItemData(itemData: JsonSurveyItem, oldFullKey: string, newFullKey: string): void { + // Create a simple key mapping for this item + const keyMapping: { [oldKey: string]: string } = { [oldFullKey]: newFullKey }; + + // Update display conditions + if (itemData.displayConditions?.root) { + this.updateExpressionReferences(itemData.displayConditions.root, keyMapping); + } + if (itemData.displayConditions?.components) { + Object.values(itemData.displayConditions.components).forEach(expr => { + if (expr) this.updateExpressionReferences(expr, keyMapping); + }); + } + + // Update template values + if (itemData.templateValues) { + Object.values(itemData.templateValues).forEach(templateValue => { + if (templateValue.expression) { + this.updateExpressionReferences(templateValue.expression, keyMapping); + } + }); + } + + // Update disabled conditions + if (itemData.disabledConditions?.components) { + Object.values(itemData.disabledConditions.components).forEach(expr => { + if (expr) this.updateExpressionReferences(expr, keyMapping); + }); + } + + // Update validations + if (itemData.validations) { + Object.values(itemData.validations).forEach(expr => { + if (expr) this.updateExpressionReferences(expr, keyMapping); + }); + } + } + + /** + * Update references in a single expression (recursive) + */ + private updateExpressionReferences(expression: any, keyMapping: { [oldKey: string]: string }): void { + if (!expression || typeof expression !== 'object') { + return; + } + + // Handle expression arguments + if (Array.isArray(expression.data)) { + expression.data.forEach((arg: any) => { + if (arg && typeof arg === 'object') { + if (arg.str && typeof arg.str === 'string' && keyMapping[arg.str]) { + arg.str = keyMapping[arg.str]; + } + // Recursively update nested expressions + this.updateExpressionReferences(arg, keyMapping); + } + }); + } + + // Recursively process nested objects + Object.keys(expression).forEach(key => { + if (expression[key] && typeof expression[key] === 'object') { + this.updateExpressionReferences(expression[key], keyMapping); + } + }); + } + + /** +* Update translation keys for the pasted item +*/ + private updateTranslationKeys(translations: { [itemKey: string]: SerializedTranslations }, oldFullKey: string, newFullKey: string): { [itemKey: string]: SerializedTranslations } { + const newTranslations: { [itemKey: string]: SerializedTranslations } = {}; + + // Update keys for all items in the translation data + Object.keys(translations).forEach(itemKey => { + const itemTranslations = translations[itemKey]; + + // Determine the new key for this item (update the key mapping) + let newItemKey = itemKey; + if (itemKey === oldFullKey) { + newItemKey = newFullKey; + } else if (itemKey.startsWith(oldFullKey + '.')) { + newItemKey = itemKey.replace(oldFullKey, newFullKey); + } + + // Copy the serialized translations as-is (content is preserved, only keys change) + newTranslations[newItemKey] = itemTranslations; + }); + + return newTranslations; + } + + /** + * Add an item to the survey at the specified target location + */ + private addItemToSurvey(target: { + parentKey: string; + index?: number; + }, item: SurveyItem, content: SurveyItemTranslations): void { + // Find the parent group item + const parentGroup = this.survey.surveyItems[target.parentKey] as GroupItem; + + if (!parentGroup) { + throw new Error(`Parent item with key '${target.parentKey}' not found`); + } + + if (parentGroup.itemType !== SurveyItemType.Group) { + throw new Error(`Parent item '${target.parentKey}' is not a group item`); + } + + // Initialize items array if it doesn't exist + if (!parentGroup.items) { + parentGroup.items = []; + } + + // Determine insertion index + let insertIndex: number; + if (target.index !== undefined) { + // Insert at specified index, or at end if index is larger than array length + insertIndex = Math.min(target.index, parentGroup.items.length); + } else { + // Insert at the end + insertIndex = parentGroup.items.length; + } + + // Add the item to the survey items collection + this.survey.surveyItems[item.key.fullKey] = item; + + // Add the item key to the parent group's items array + parentGroup.items.splice(insertIndex, 0, item.key.fullKey); + + // Update translations in the survey + this.survey.translations.setItemTranslations(item.key.fullKey, content); + } + + /** + * Recursively create child items for a group item + */ + private createChildItemsRecursively(originalParentKey: string, newParentKey: string, originalClipboardData: SurveyItemClipboardData): void { + const groupData = originalClipboardData.items[0].itemData as any; + + if (groupData.items && Array.isArray(groupData.items)) { + groupData.items.forEach((originalChildKey: string) => { + // Check if the original child item exists in the source survey + const originalChildItem = this.survey.surveyItems[originalChildKey]; + if (originalChildItem) { + // Create clipboard data for the child item + const childClipboardData = this.copyItem(originalChildKey); + + // Generate new key for the child + const originalChildItemKey = SurveyItemKey.fromFullKey(originalChildKey); + const newChildKey = new SurveyItemKey(originalChildItemKey.itemKey, newParentKey); + + // Create the child item data with updated keys + const updatedChildData = this.updateItemKeysInData(childClipboardData.items[0].itemData, originalChildKey, newChildKey.fullKey); + + // Create the child item + const newChildItem = SurveyItem.fromJson(newChildKey.fullKey, updatedChildData); + + // Add to survey items + this.survey.surveyItems[newChildKey.fullKey] = newChildItem; + + // Update translations for child + const childTranslations = this.updateTranslationKeys(childClipboardData.translations, originalChildKey, newChildKey.fullKey); + const serializedChildTranslations = childTranslations[newChildKey.fullKey]; + if (serializedChildTranslations) { + const itemTranslations = new SurveyItemTranslations(); + Object.keys(serializedChildTranslations).forEach(locale => { + itemTranslations.setAllForLocale(locale, serializedChildTranslations[locale]); + }); + this.survey.translations.setItemTranslations(newChildKey.fullKey, itemTranslations); + } else { + this.survey.translations.setItemTranslations(newChildKey.fullKey, new SurveyItemTranslations()); + } + + // Recursively create grandchildren if this is a group + if (newChildItem.itemType === SurveyItemType.Group && (newChildItem as GroupItem).items) { + this.createChildItemsRecursively(originalChildKey, newChildKey.fullKey, childClipboardData); + } + } + }); + } + } + + /** + * Find a component within an item by its full key + */ + private findComponentInItem(item: SurveyItem, componentKey: string): ItemComponent | null { + // Search in different item types + if (item.itemType === SurveyItemType.Display) { + const displayItem = item as DisplayItem; + return this.searchComponentsArray(displayItem.components || [], componentKey); + } + + if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { + const questionItem = item as QuestionItem; + + // Check header components + if (questionItem.header?.title?.key.fullKey === componentKey) return questionItem.header.title; + if (questionItem.header?.subtitle?.key.fullKey === componentKey) return questionItem.header.subtitle; + if (questionItem.header?.helpPopover?.key.fullKey === componentKey) return questionItem.header.helpPopover; + + // Check body components + const topContentResult = this.searchComponentsArray(questionItem.body?.topContent || [], componentKey); + if (topContentResult) return topContentResult; + + const bottomContentResult = this.searchComponentsArray(questionItem.body?.bottomContent || [], componentKey); + if (bottomContentResult) return bottomContentResult; + + // Check footer + if (questionItem.footer?.key.fullKey === componentKey) return questionItem.footer; + + // Check response config and its children + if (questionItem.responseConfig.key.fullKey === componentKey) return questionItem.responseConfig; + + return this.searchComponentRecursively(questionItem.responseConfig, componentKey); + } + + return null; + } + + /** + * Search for a component in an array of components + */ + private searchComponentsArray(components: ItemComponent[], componentKey: string): ItemComponent | null { + for (const component of components) { + if (component.key.fullKey === componentKey) { + return component; + } + + // Search recursively in nested components + const nestedResult = this.searchComponentRecursively(component, componentKey); + if (nestedResult) return nestedResult; + } + return null; + } + + /** + * Search for a component recursively within a component + */ + private searchComponentRecursively(component: ItemComponent, componentKey: string): ItemComponent | null { + if (component instanceof GroupComponent && component.items) { + return this.searchComponentsArray(component.items, componentKey); + } + return null; + } + + /** + * Create a component from JSON data + */ + private createComponentFromJson(componentData: any, parentComponentKey: string | undefined, itemKey: string): ItemComponent { + // Determine component type and use appropriate factory method + const componentType = componentData.type; + + // For response config components, use specialized factories + if (componentType === ItemComponentType.SingleChoice || componentType === ItemComponentType.MultipleChoice) { + return ScgMcgChoiceResponseConfig.fromJson(componentData, parentComponentKey, itemKey); + } + + // For ScgMcg option components + if (componentType === ItemComponentType.ScgMcgOption || + componentType === ItemComponentType.ScgMcgOptionWithTextInput || + componentType === ItemComponentType.ScgMcgOptionWithNumberInput || + componentType === ItemComponentType.ScgMcgOptionWithDateInput || + componentType === ItemComponentType.ScgMcgOptionWithTimeInput || + componentType === ItemComponentType.ScgMcgOptionWithDropdown || + componentType === ItemComponentType.ScgMcgOptionWithCloze) { + return ScgMcgOptionBase.fromJson(componentData, parentComponentKey, itemKey); + } + + // Default to DisplayComponent for display components + return DisplayComponent.fromJson(componentData, parentComponentKey, itemKey); + } + + /** + * Insert a component into an item at the specified location + */ + private insertComponentIntoItem( + item: SurveyItem, + component: ItemComponent, + location?: { + parentComponentKey?: string; + section?: 'header' | 'body' | 'footer' | 'responseConfig' | 'components'; + subSection?: 'title' | 'subtitle' | 'helpPopover' | 'topContent' | 'bottomContent'; + index?: number; + } + ): void { + if (item.itemType === SurveyItemType.Display) { + const displayItem = item as DisplayItem; + if (!displayItem.components) displayItem.components = []; + + const insertIndex = location?.index !== undefined ? + Math.min(location.index, displayItem.components.length) : + displayItem.components.length; + + displayItem.components.splice(insertIndex, 0, component as DisplayComponent); + } else if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { + const questionItem = item as QuestionItem; + + // Handle insertion into response config (group components like SingleChoice options) + if (location?.parentComponentKey) { + const parentComponent = this.findComponentInItem(item, location.parentComponentKey); + if (parentComponent && parentComponent instanceof GroupComponent) { + if (!parentComponent.items) parentComponent.items = []; + const insertIndex = location.index !== undefined ? + Math.min(location.index, parentComponent.items.length) : + parentComponent.items.length; + parentComponent.items.splice(insertIndex, 0, component); + return; + } + } + + if (location?.section === 'header') { + if (!questionItem.header) questionItem.header = {}; + if (location.subSection === 'title') questionItem.header.title = component as TextComponent; + else if (location.subSection === 'subtitle') questionItem.header.subtitle = component as TextComponent; + else if (location.subSection === 'helpPopover') questionItem.header.helpPopover = component as TextComponent; + } else if (location?.section === 'body') { + if (!questionItem.body) questionItem.body = {}; + if (location.subSection === 'topContent') { + if (!questionItem.body.topContent) questionItem.body.topContent = []; + const insertIndex = location.index !== undefined ? + Math.min(location.index, questionItem.body.topContent.length) : + questionItem.body.topContent.length; + questionItem.body.topContent.splice(insertIndex, 0, component as DisplayComponent); + } else if (location.subSection === 'bottomContent') { + if (!questionItem.body.bottomContent) questionItem.body.bottomContent = []; + const insertIndex = location.index !== undefined ? + Math.min(location.index, questionItem.body.bottomContent.length) : + questionItem.body.bottomContent.length; + questionItem.body.bottomContent.splice(insertIndex, 0, component as DisplayComponent); + } + } else if (location?.section === 'footer') { + questionItem.footer = component as TextComponent; + } else { + // Default to body top content for question items + if (!questionItem.body) questionItem.body = {}; + if (!questionItem.body.topContent) questionItem.body.topContent = []; + questionItem.body.topContent.push(component as DisplayComponent); + } + } + } + + /** + * Update component translations for the pasted component + */ + private updateComponentTranslations( + targetItemKey: string, + componentTranslations: { [locale: string]: { [contentKey: string]: any } }, + oldComponentKey: string, + newComponentKey: string + ): void { + Object.keys(componentTranslations).forEach(locale => { + const localeTranslations = componentTranslations[locale]; + Object.keys(localeTranslations).forEach(contentKey => { + // Update content key if it references the old component key + let newContentKey = contentKey; + if (contentKey === oldComponentKey) { + newContentKey = newComponentKey; + } else if (contentKey.startsWith(oldComponentKey + '.')) { + newContentKey = contentKey.replace(oldComponentKey, newComponentKey); + } + + // Set the translation in the target item + const itemTranslations = this.survey.getItemTranslations(targetItemKey) || new SurveyItemTranslations(); + itemTranslations.setContent(locale, newContentKey, localeTranslations[contentKey]); + this.survey.translations.setItemTranslations(targetItemKey, itemTranslations); + }); + }); + } + + /** + * Determine where and how to paste a component based on the target + */ + private determinePasteLocation(item: SurveyItem, targetComponentKey: string, targetComponent: ItemComponent | null): { + shouldReplace: boolean; + parentComponentKey?: string; + location?: { + parentComponentKey?: string; + section?: 'header' | 'body' | 'footer' | 'responseConfig' | 'components'; + subSection?: 'title' | 'subtitle' | 'helpPopover' | 'topContent' | 'bottomContent'; + index?: number; + }; + } { + // If target component doesn't exist, determine insertion location based on key structure + if (!targetComponent) { + return this.determinePasteLocationFromKey(item, targetComponentKey); + } + + // Determine behavior based on component type and location + if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { + const questionItem = item as QuestionItem; + + // Check if target is a single-slot component (replace behavior) + if (questionItem.header?.title?.key.fullKey === targetComponentKey) { + return { + shouldReplace: true, + location: { section: 'header', subSection: 'title' } + }; + } + if (questionItem.header?.subtitle?.key.fullKey === targetComponentKey) { + return { + shouldReplace: true, + location: { section: 'header', subSection: 'subtitle' } + }; + } + if (questionItem.header?.helpPopover?.key.fullKey === targetComponentKey) { + return { + shouldReplace: true, + location: { section: 'header', subSection: 'helpPopover' } + }; + } + if (questionItem.footer?.key.fullKey === targetComponentKey) { + return { + shouldReplace: true, + location: { section: 'footer' } + }; + } + + // Check if target is in a group component (add behavior) + // Check response config (SingleChoice/MultipleChoice with items) + if (questionItem.responseConfig.key.fullKey === targetComponentKey) { + return { + shouldReplace: false, + parentComponentKey: targetComponentKey, + location: { parentComponentKey: targetComponentKey } + }; + } + + // Check if target is in topContent or bottomContent arrays + const topContentMatch = questionItem.body?.topContent?.find(comp => comp.key.fullKey === targetComponentKey); + if (topContentMatch) { + return { + shouldReplace: false, + location: { section: 'body', subSection: 'topContent' } + }; + } + + const bottomContentMatch = questionItem.body?.bottomContent?.find(comp => comp.key.fullKey === targetComponentKey); + if (bottomContentMatch) { + return { + shouldReplace: false, + location: { section: 'body', subSection: 'bottomContent' } + }; + } + } + + if (item.itemType === SurveyItemType.Display) { + const displayItem = item as DisplayItem; + + // For display items, components array allows adding + const componentMatch = displayItem.components?.find(comp => comp.key.fullKey === targetComponentKey); + if (componentMatch) { + return { + shouldReplace: false, + location: { section: 'components' } + }; + } + } + + // Default to adding behavior if we can't determine the specific context + return { + shouldReplace: false, + location: undefined + }; + } + + /** + * Determine paste location when target component doesn't exist based on key structure + */ + private determinePasteLocationFromKey(item: SurveyItem, targetComponentKey: string): { + shouldReplace: boolean; + parentComponentKey?: string; + location?: { + parentComponentKey?: string; + section?: 'header' | 'body' | 'footer' | 'responseConfig' | 'components'; + subSection?: 'title' | 'subtitle' | 'helpPopover' | 'topContent' | 'bottomContent'; + index?: number; + }; + } { + if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { + // Analyze key structure to determine intended location + if (targetComponentKey === 'title') { + return { shouldReplace: true, location: { section: 'header', subSection: 'title' } }; + } + if (targetComponentKey === 'subtitle') { + return { shouldReplace: true, location: { section: 'header', subSection: 'subtitle' } }; + } + if (targetComponentKey === 'helpPopover') { + return { shouldReplace: true, location: { section: 'header', subSection: 'helpPopover' } }; + } + if (targetComponentKey === 'footer') { + return { shouldReplace: true, location: { section: 'footer' } }; + } + if (targetComponentKey === 'rg' || targetComponentKey.startsWith('rg.')) { + return { shouldReplace: false, parentComponentKey: 'rg', location: { parentComponentKey: 'rg' } }; + } + + // Default to body top content for question items + return { shouldReplace: false, location: { section: 'body', subSection: 'topContent' } }; + } + + if (item.itemType === SurveyItemType.Display) { + // Default to components array for display items + return { shouldReplace: false, location: { section: 'components' } }; + } + + // Default behavior + return { shouldReplace: false, location: undefined }; + } + + /** + * Replace an existing component with a new one + */ + private replaceComponent( + item: SurveyItem, + oldComponent: ItemComponent, + newComponent: ItemComponent, + pasteInfo: { location?: any } + ): void { + if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { + const questionItem = item as QuestionItem; + + if (pasteInfo.location?.section === 'header') { + if (!questionItem.header) questionItem.header = {}; + if (pasteInfo.location.subSection === 'title') { + questionItem.header.title = newComponent as TextComponent; + } else if (pasteInfo.location.subSection === 'subtitle') { + questionItem.header.subtitle = newComponent as TextComponent; + } else if (pasteInfo.location.subSection === 'helpPopover') { + questionItem.header.helpPopover = newComponent as TextComponent; + } + } else if (pasteInfo.location?.section === 'footer') { + questionItem.footer = newComponent as TextComponent; + } + } + } +} diff --git a/src/survey-editor/index.ts b/src/survey-editor/index.ts index b8a6a2c..ace6733 100644 --- a/src/survey-editor/index.ts +++ b/src/survey-editor/index.ts @@ -1,5 +1,7 @@ -export * from './expression-editor'; -export * from './expression-editor-generators'; export * from './survey-editor'; +export * from './survey-item-editors'; export * from './component-editor'; -export * from './survey-item-editors'; \ No newline at end of file +export * from './expression-editor'; +export * from './expression-editor-generators'; +export * from './undo-redo'; +export * from './copy-paste'; diff --git a/src/survey-editor/survey-editor.ts b/src/survey-editor/survey-editor.ts index 4945482..f0d8124 100644 --- a/src/survey-editor/survey-editor.ts +++ b/src/survey-editor/survey-editor.ts @@ -4,6 +4,7 @@ import { SurveyEditorUndoRedo, type UndoRedoConfig } from "./undo-redo"; import { SurveyItemTranslations } from "../survey/utils"; import { SurveyItemKey } from "../survey/item-component-key"; import { JsonSurvey } from "../survey/survey-file-schema"; +import { CopyPaste, SurveyItemClipboardData, SurveyComponentClipboardData } from "./copy-paste"; // Interface for serializing SurveyEditor state export interface SurveyEditorJson { @@ -13,6 +14,7 @@ export interface SurveyEditorJson { hasUncommittedChanges: boolean; } + // Event types for the editor export type SurveyEditorEventType = 'survey-changed'; @@ -655,4 +657,65 @@ export class SurveyEditor { this.commit(`Deleted component ${componentKey} from ${itemKey}`); } + + /** + * Copy a survey item and all its data to clipboard format + * @param itemKey - The full key of the item to copy + * @returns Clipboard data that can be serialized to JSON for clipboard + */ + copyItem(itemKey: string): SurveyItemClipboardData { + const copyPaste = new CopyPaste(this._survey); + return copyPaste.copyItem(itemKey); + } + + /** + * Paste a survey item from clipboard data to a target location + * @param clipboardData - The clipboard data containing the item to paste + * @param target - Target location where to paste the item + * @returns The full key of the pasted item + */ + pasteItem(clipboardData: SurveyItemClipboardData, target: { + parentKey: string; + index?: number; + }): string { + this.commitIfNeeded(); + + const copyPaste = new CopyPaste(this._survey); + const newFullKey = copyPaste.pasteItem(clipboardData, target); + + this.commit(`Pasted ${newFullKey}`); + return newFullKey; + } + + /** + * Copy a component from an item + * @param itemKey - The full key of the item containing the component + * @param componentKey - The full key of the component to copy + * @returns Clipboard data for the component + */ + copyComponent(itemKey: string, componentKey: string): SurveyComponentClipboardData { + const copyPaste = new CopyPaste(this._survey); + return copyPaste.copyComponent(itemKey, componentKey); + } + + /** + * Paste a component into an item + * @param clipboardData - The clipboard data containing the component to paste + * @param targetItemKey - The item to paste the component into + * @param targetComponentKey - The component key to paste into (if undefined, pastes into default location) + * @returns The full key of the pasted component + */ + pasteComponent( + clipboardData: SurveyComponentClipboardData, + targetItemKey: string, + targetComponentKey?: string + ): string { + this.commitIfNeeded(); + + const copyPaste = new CopyPaste(this._survey); + const newFullComponentKey = copyPaste.pasteComponentSmart(clipboardData, targetItemKey, targetComponentKey); + + this.commit(`Pasted component ${newFullComponentKey} into ${targetItemKey}`); + return newFullComponentKey; + } } From 1e831a434ca2d0a1355c26fd5d6a427812b623d5 Mon Sep 17 00:00:00 2001 From: phev8 Date: Thu, 17 Jul 2025 17:00:12 +0200 Subject: [PATCH 02/10] Removed component paste function first - it needs different handling --- .../survey-editor-copy-paste.test.ts | 384 +----------- src/survey-editor/copy-paste.ts | 549 +----------------- src/survey-editor/survey-editor.ts | 21 +- 3 files changed, 29 insertions(+), 925 deletions(-) diff --git a/src/__tests__/survey-editor-copy-paste.test.ts b/src/__tests__/survey-editor-copy-paste.test.ts index 1e0ffa6..d5d9fed 100644 --- a/src/__tests__/survey-editor-copy-paste.test.ts +++ b/src/__tests__/survey-editor-copy-paste.test.ts @@ -321,6 +321,7 @@ describe('CopyPaste Functionality', () => { }); }); + // Component tests now using copyPaste for component operations describe('copyComponent', () => { beforeEach(() => { @@ -353,227 +354,9 @@ describe('CopyPaste Functionality', () => { expect(clipboardData.timestamp).toBeGreaterThan(0); }); - test('should copy a question header component', () => { - const clipboardData = copyPaste.copyComponent('test-survey.group1.Q1', 'title'); - - expect(clipboardData.type).toBe('survey-component'); - expect(clipboardData.componentKey).toBe('title'); - expect(clipboardData.parentItemKey).toBe('test-survey.group1.Q1'); - }); - - test('should copy a question body component', () => { - const clipboardData = copyPaste.copyComponent('test-survey.group1.Q1', 'topText'); - - expect(clipboardData.type).toBe('survey-component'); - expect(clipboardData.componentKey).toBe('topText'); - expect(clipboardData.parentItemKey).toBe('test-survey.group1.Q1'); - }); - - test('should include component translations in clipboard data', () => { - const translations = new SurveyItemTranslations(); - translations.setContent('en', 'text1', { type: ContentType.CQM, content: 'Test Text', attributions: [] }); - editor.updateItemTranslations('test-survey.group1.display1', translations); - - const clipboardData = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); - - expect(clipboardData.translations['en']).toBeDefined(); - expect(clipboardData.translations['en']['text1']).toEqual({ - type: ContentType.CQM, - content: 'Test Text', - attributions: [] - }); - }); - - test('should throw error for non-existent item', () => { - expect(() => { - copyPaste.copyComponent('non-existent-item', 'text1'); - }).toThrow("Item with key 'non-existent-item' not found"); - }); - - test('should throw error for non-existent component', () => { - expect(() => { - copyPaste.copyComponent('test-survey.group1.display1', 'non-existent-component'); - }).toThrow("Component with key 'non-existent-component' not found in item 'test-survey.group1.display1'"); - }); + // TODO: }); - describe('pasteComponent', () => { - let clipboardData: SurveyComponentClipboardData; - - beforeEach(() => { - clipboardData = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); - }); - - test('should paste component to display item', () => { - const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1'); - - expect(newComponentKey).toBe('text1_copy'); - - const displayItem = survey.surveyItems['test-survey.group1.display1'] as DisplayItem; - expect(displayItem.components?.length).toBe(2); // Original + pasted - expect(displayItem.components?.[1].key.componentKey).toBe('text1_copy'); - }); - - test('should paste component to question item header', () => { - const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.Q1', { - section: 'header', - subSection: 'title' - }); - - expect(newComponentKey).toBe('text1_copy'); - - const questionItem = survey.surveyItems['test-survey.group1.Q1'] as SingleChoiceQuestionItem; - expect(questionItem.header?.title?.key.componentKey).toBe('text1_copy'); - }); - - test('should paste component to question item body', () => { - const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.Q1', { - section: 'body', - subSection: 'topContent' - }); - - expect(newComponentKey).toBe('text1_copy'); - - const questionItem = survey.surveyItems['test-survey.group1.Q1'] as SingleChoiceQuestionItem; - expect(questionItem.body?.topContent?.length).toBe(1); - expect(questionItem.body?.topContent?.[0].key.componentKey).toBe('text1_copy'); - }); - - test('should generate unique component keys for multiple pastes', () => { - const firstCopy = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1'); - const secondCopy = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1'); - const thirdCopy = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1'); - - expect(firstCopy).toBe('text1_copy'); - expect(secondCopy).toBe('text1_copy_2'); - expect(thirdCopy).toBe('text1_copy_3'); - - const displayItem = survey.surveyItems['test-survey.group1.display1'] as DisplayItem; - expect(displayItem.components?.length).toBe(4); // Original + 3 copies - }); - - test('should paste component at specified index', () => { - const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display1', { - index: 0 - }); - - const displayItem = survey.surveyItems['test-survey.group1.display1'] as DisplayItem; - expect(displayItem.components?.[0].key.componentKey).toBe('text1_copy'); - }); - - test('should preserve component translations when pasting', () => { - const translations = new SurveyItemTranslations(); - translations.setContent('en', 'text1', { type: ContentType.CQM, content: 'Test Text', attributions: [] }); - editor.updateItemTranslations('test-survey.group1.display1', translations); - - const componentClipboard = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); - const newComponentKey = copyPaste.pasteComponent(componentClipboard, 'test-survey.group1.display1'); - - const newTranslations = survey.getItemTranslations('test-survey.group1.display1'); - expect(newTranslations?.getContent('en', newComponentKey)).toEqual({ - type: ContentType.CQM, - content: 'Test Text', - attributions: [] - }); - }); - - test('should paste component across different items', () => { - // Create a second display item - const display2 = new DisplayItem('test-survey.group1.display2'); - survey.surveyItems['test-survey.group1.display2'] = display2; - (survey.surveyItems['test-survey.group1'] as GroupItem).items?.push('test-survey.group1.display2'); - - const newComponentKey = copyPaste.pasteComponent(clipboardData, 'test-survey.group1.display2'); - - expect(newComponentKey).toBe('text1_copy'); - - const targetItem = survey.surveyItems['test-survey.group1.display2'] as DisplayItem; - expect(targetItem.components?.length).toBe(1); - expect(targetItem.components?.[0].key.componentKey).toBe('text1_copy'); - }); - - test('should validate clipboard data format', () => { - const invalidClipboard = { - type: 'invalid-type', - version: '1.0.0', - componentKey: 'test', - parentItemKey: 'test', - componentData: {}, - translations: {}, - timestamp: Date.now() - }; - - expect(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - copyPaste.pasteComponent(invalidClipboard as any, 'test-survey.group1.display1'); - }).toThrow('Invalid component clipboard data format'); - }); - - test('should validate required clipboard data fields', () => { - const incompleteClipboard = { - type: 'survey-component', - version: '1.0.0', - componentKey: 'test' - // Missing other required fields - }; - - expect(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - copyPaste.pasteComponent(incompleteClipboard as any, 'test-survey.group1.display1'); - }).toThrow('Invalid component clipboard data format'); - }); - - test('should throw error for non-existent target item', () => { - expect(() => { - copyPaste.pasteComponent(clipboardData, 'non-existent-item'); - }).toThrow("Target item with key 'non-existent-item' not found"); - }); - - test('should handle undo/redo integration correctly', () => { - // Test that paste component operation is properly tracked in undo/redo history - const initialHistoryLength = editor.undoRedo.getHistory().length; - - // Perform paste operation using editor method - const newComponentKey = editor.pasteComponent(clipboardData, 'test-survey.group1.display1'); - - // Should have added an operation to history - expect(editor.undoRedo.getHistory().length).toBe(initialHistoryLength + 1); - expect(editor.hasUncommittedChanges).toBe(false); - - // Verify the component was pasted - const displayItem = editor.survey.surveyItems['test-survey.group1.display1'] as DisplayItem; - const pastedComponent = displayItem.components?.find(c => c.key.componentKey === newComponentKey); - expect(pastedComponent).toBeDefined(); - - // Test undo - const undoSuccess = editor.undo(); - expect(undoSuccess).toBe(true); - const undoDisplayItem = editor.survey.surveyItems['test-survey.group1.display1'] as DisplayItem; - const undoComponent = undoDisplayItem.components?.find(c => c.key.componentKey === newComponentKey); - expect(undoComponent).toBeUndefined(); - - // Test redo - const redoSuccess = editor.redo(); - expect(redoSuccess).toBe(true); - const redoDisplayItem = editor.survey.surveyItems['test-survey.group1.display1'] as DisplayItem; - const redoComponent = redoDisplayItem.components?.find(c => c.key.componentKey === newComponentKey); - expect(redoComponent).toBeDefined(); - }); - - test('should handle JSON serialization correctly', () => { - const clipboardData = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); - - // Simulate serialization/deserialization - const serialized = JSON.stringify(clipboardData); - const deserialized = JSON.parse(serialized); - - // Should be able to paste from deserialized data - const newComponentKey = copyPaste.pasteComponent(deserialized, 'test-survey.group1.display1'); - - const displayItem = survey.surveyItems['test-survey.group1.display1'] as DisplayItem; - expect(displayItem.components?.find(c => c.key.componentKey === newComponentKey)).toBeDefined(); - }); - }); // Add comprehensive translation copy-paste tests describe('Translation Copy-Paste Tests', () => { @@ -1194,166 +977,3 @@ describe('CopyPaste Functionality', () => { }); }); -describe('SurveyEditor - Smart Component Copy-Paste', () => { - let editor: SurveyEditor; - let survey: Survey; - - beforeEach(() => { - // Create a test survey with a single choice question - survey = new Survey('test-survey'); - const rootGroup = new GroupItem('root'); - rootGroup.items = []; - survey.surveyItems['root'] = rootGroup; - - const questionItem = new SingleChoiceQuestionItem('root.q1'); - // Initialize the question with basic structure - questionItem.header = { - title: new TextComponent('title', undefined, 'root.q1'), - subtitle: new TextComponent('subtitle', undefined, 'root.q1') - }; - questionItem.body = { - topContent: [] - }; - questionItem.responseConfig = new ScgMcgChoiceResponseConfig('rg', undefined, 'root.q1'); - questionItem.responseConfig.items = [ - new ScgMcgOption('1', 'rg', 'root.q1'), - new ScgMcgOption('2', 'rg', 'root.q1') - ]; - - survey.surveyItems['root.q1'] = questionItem; - rootGroup.items.push('root.q1'); - - editor = new SurveyEditor(survey); - }); - - describe('Single-slot component replacement', () => { - test('should replace title component when pasting into title', () => { - const originalTitle = (editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem).header!.title!; - - // Copy the title component - const clipboardData = editor.copyComponent('root.q1', 'title'); - - // Paste it back into the title slot - should replace - const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'title'); - - const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; - const newTitle = questionItem.header!.title!; - - // Should have replaced the component - expect(newTitle.key.fullKey).toBe(newComponentKey); - expect(newTitle.key.fullKey).not.toBe(originalTitle.key.fullKey); - expect(newTitle.key.componentKey).toBe('title_copy'); - }); - - test('should replace subtitle component when pasting into subtitle', () => { - const originalSubtitle = (editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem).header!.subtitle!; - - // Copy the subtitle component - const clipboardData = editor.copyComponent('root.q1', 'subtitle'); - - // Paste it into the subtitle slot - should replace - const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'subtitle'); - - const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; - const newSubtitle = questionItem.header!.subtitle!; - - // Should have replaced the component - expect(newSubtitle.key.fullKey).toBe(newComponentKey); - expect(newSubtitle.key.fullKey).not.toBe(originalSubtitle.key.fullKey); - expect(newSubtitle.key.componentKey).toBe('subtitle_copy'); - }); - }); - - describe('Group component addition', () => { - test('should add new option when pasting into response config', () => { - const originalOptionsCount = (editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem).responseConfig.items.length; - - // Copy an existing option - const clipboardData = editor.copyComponent('root.q1', 'rg.1'); - - // Paste it into the response config - should add new option - const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'rg'); - - const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; - const newOptionsCount = questionItem.responseConfig.items.length; - - // Should have added a new option - expect(newOptionsCount).toBe(originalOptionsCount + 1); - expect(newComponentKey).toBe('rg.1_copy'); - - // Verify the new option exists - const newOption = questionItem.responseConfig.items.find(opt => opt.key.fullKey === newComponentKey); - expect(newOption).toBeDefined(); - expect(newOption!.componentType).toBe(ItemComponentType.ScgMcgOption); - }); - - test('should add to topContent when pasting into topContent area', () => { - const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; - const originalTopContentCount = questionItem.body!.topContent?.length || 0; - - // Create a text component to copy - const textComponent = new TextComponent('test-text', undefined, 'root.q1'); - questionItem.body!.topContent = questionItem.body!.topContent || []; - questionItem.body!.topContent.push(textComponent); - - // Copy the text component - const clipboardData = editor.copyComponent('root.q1', 'test-text'); - - // Paste it into topContent - should add new component - const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'test-text'); - - const updatedTopContentCount = questionItem.body!.topContent!.length; - - // Should have added a new component - expect(updatedTopContentCount).toBe(originalTopContentCount + 2); // original + copied - expect(newComponentKey).toBe('test-text_copy'); - - // Verify the new component exists - const newComponent = questionItem.body!.topContent!.find(comp => comp.key.fullKey === newComponentKey); - expect(newComponent).toBeDefined(); - expect(newComponent!.componentType).toBe(ItemComponentType.Text); - }); - }); - - describe('Fallback to default behavior', () => { - test('should use default behavior when no target component is specified', () => { - const questionItem = editor.survey.surveyItems['root.q1'] as SingleChoiceQuestionItem; - - // Create a text component to copy - const textComponent = new TextComponent('test-text', undefined, 'root.q1'); - questionItem.body!.topContent = questionItem.body!.topContent || []; - questionItem.body!.topContent.push(textComponent); - - // Copy the text component - const clipboardData = editor.copyComponent('root.q1', 'test-text'); - - // Paste without specifying target component - should use default behavior - const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1'); - - // Should have added to default location (topContent) - const addedComponent = questionItem.body!.topContent!.find(comp => comp.key.fullKey === newComponentKey); - expect(addedComponent).toBeDefined(); - expect(newComponentKey).toBe('test-text_copy'); - }); - }); - - describe('Error handling', () => { - test('should throw error when target item does not exist', () => { - const clipboardData = editor.copyComponent('root.q1', 'title'); - - expect(() => { - editor.pasteComponent(clipboardData, 'nonexistent.item', 'title'); - }).toThrow("Target item with key 'nonexistent.item' not found"); - }); - - test('should handle non-existent target component gracefully', () => { - const clipboardData = editor.copyComponent('root.q1', 'title'); - - // This should not throw and should use fallback logic - expect(() => { - const newComponentKey = editor.pasteComponent(clipboardData, 'root.q1', 'nonexistent-component'); - expect(newComponentKey).toBeDefined(); - }).not.toThrow(); - }); - }); -}); diff --git a/src/survey-editor/copy-paste.ts b/src/survey-editor/copy-paste.ts index 8e812b9..cf00673 100644 --- a/src/survey-editor/copy-paste.ts +++ b/src/survey-editor/copy-paste.ts @@ -2,9 +2,9 @@ import { Survey } from "../survey/survey"; import { SurveyItem, GroupItem, SurveyItemType, DisplayItem, QuestionItem } from "../survey/items"; import { SurveyItemTranslations, JsonComponentContent } from "../survey/utils"; import { SurveyItemKey, ItemComponentKey } from "../survey/item-component-key"; -import { JsonSurveyItem } from "../survey/items/survey-item-json"; +import { JsonSurveyItem, JsonSurveyItemGroup } from "../survey/items/survey-item-json"; import { JsonSurveyItemResponse } from "../survey/responses"; -import { ItemComponent, DisplayComponent, TextComponent, GroupComponent, ItemComponentType, ScgMcgChoiceResponseConfig, ScgMcgOptionBase } from "../survey/components"; +import { ItemComponent, GroupComponent } from "../survey/components"; // Serialized translation data format for clipboard export type SerializedTranslations = { @@ -241,7 +241,7 @@ export class CopyPaste { index?: number; }): string { // Validate clipboard data - if (!this.isValidClipboardData(clipboardData)) { + if (!CopyPaste.isValidClipboardData(clipboardData)) { throw new Error('Invalid clipboard data format'); } @@ -362,171 +362,7 @@ export class CopyPaste { }; } - /** - * Paste a component into an item - * @param clipboardData - The clipboard data containing the component to paste - * @param targetItemKey - The item to paste the component into - * @param targetLocation - Where to insert the component (optional) - * @returns The full key of the pasted component - */ - pasteComponent( - clipboardData: SurveyComponentClipboardData, - targetItemKey: string, - targetLocation?: { - parentComponentKey?: string; - section?: 'header' | 'body' | 'footer' | 'responseConfig' | 'components'; - subSection?: 'title' | 'subtitle' | 'helpPopover' | 'topContent' | 'bottomContent'; - index?: number; - } - ): string { - // Validate clipboard data - if (!this.isValidComponentClipboardData(clipboardData)) { - throw new Error('Invalid component clipboard data format'); - } - - const targetItem = this.survey.surveyItems[targetItemKey]; - if (!targetItem) { - throw new Error(`Target item with key '${targetItemKey}' not found`); - } - - // Generate unique component key - const originalComponentKey = ItemComponentKey.fromFullKey(clipboardData.componentKey, clipboardData.parentItemKey); - const newComponentKey = this.generateUniqueComponentKey(originalComponentKey.componentKey, targetItemKey, targetLocation?.parentComponentKey); - const newFullComponentKey = targetLocation?.parentComponentKey ? - `${targetLocation.parentComponentKey}.${newComponentKey}` : - newComponentKey; - - // Update component data with new keys - const updatedComponentData = this.updateComponentKeysInData( - clipboardData.componentData, - clipboardData.componentKey, - newFullComponentKey, - targetItemKey - ); - - // Create the component from JSON - const newComponent = this.createComponentFromJson(updatedComponentData, targetLocation?.parentComponentKey, targetItemKey); - - // Insert component into the target item - this.insertComponentIntoItem(targetItem, newComponent, targetLocation); - - // Update translations - this.updateComponentTranslations(targetItemKey, clipboardData.translations, clipboardData.componentKey, newFullComponentKey); - - return newFullComponentKey; - } - - /** - * Paste a component into an item with intelligent placement based on target component - * @param clipboardData - The clipboard data containing the component to paste - * @param targetItemKey - The item to paste the component into - * @param targetComponentKey - The component key to paste into (if undefined, uses default behavior) - * @returns The full key of the pasted component - */ - pasteComponentSmart( - clipboardData: SurveyComponentClipboardData, - targetItemKey: string, - targetComponentKey?: string - ): string { - // If no target component specified, use default behavior - if (!targetComponentKey) { - return this.pasteComponent(clipboardData, targetItemKey); - } - - // Validate clipboard data - if (!this.isValidComponentClipboardData(clipboardData)) { - throw new Error('Invalid component clipboard data format'); - } - - const targetItem = this.survey.surveyItems[targetItemKey]; - if (!targetItem) { - throw new Error(`Target item with key '${targetItemKey}' not found`); - } - - // Find the target component to determine paste behavior - const targetComponent = this.findComponentInItem(targetItem, targetComponentKey); - const pasteInfo = this.determinePasteLocation(targetItem, targetComponentKey, targetComponent); - - // Generate unique component key - const originalComponentKey = ItemComponentKey.fromFullKey(clipboardData.componentKey, clipboardData.parentItemKey); - const newComponentKey = this.generateUniqueComponentKey(originalComponentKey.componentKey, targetItemKey, pasteInfo.parentComponentKey); - const newFullComponentKey = pasteInfo.parentComponentKey ? - `${pasteInfo.parentComponentKey}.${newComponentKey}` : - newComponentKey; - - // Update component data with new keys - const updatedComponentData = this.updateComponentKeysInData( - clipboardData.componentData, - clipboardData.componentKey, - newFullComponentKey, - targetItemKey - ); - - // Create the component from JSON - const newComponent = this.createComponentFromJson(updatedComponentData, pasteInfo.parentComponentKey, targetItemKey); - - // Insert component based on determined location - if (pasteInfo.shouldReplace && targetComponent) { - this.replaceComponent(targetItem, targetComponent, newComponent, pasteInfo); - } else { - this.insertComponentIntoItem(targetItem, newComponent, pasteInfo.location); - } - - // Update translations - this.updateComponentTranslations(targetItemKey, clipboardData.translations, clipboardData.componentKey, newFullComponentKey); - - return newFullComponentKey; - } - // PRIVATE HELPER METHODS - - /** - * Validate clipboard data format - */ - private isValidClipboardData(data: any): data is SurveyItemClipboardData { - return ( - data && - typeof data === 'object' && - data.type === 'survey-item' && - data.version && - data.items && - Array.isArray(data.items) && - data.items.length > 0 && - data.items.every((item: any) => - item && - typeof item === 'object' && - item.itemKey && - typeof item.itemKey === 'string' && - item.itemData && - typeof item.itemData === 'object' - ) && - data.translations && - typeof data.translations === 'object' && - data.prefills && - typeof data.prefills === 'object' && - data.rootItemKey && - typeof data.rootItemKey === 'string' && - typeof data.timestamp === 'number' - ); - } - - /** - * Validate component clipboard data format - */ - private isValidComponentClipboardData(data: any): data is SurveyComponentClipboardData { - return ( - data && - typeof data === 'object' && - data.type === 'survey-component' && - data.version && - data.componentData && - data.componentKey && - data.parentItemKey && - data.translations && - typeof data.timestamp === 'number' - ); - } - /** * Generate a unique item key within the target parent */ @@ -547,33 +383,6 @@ export class CopyPaste { return candidateKey; } - /** - * Generate a unique component key within the target item - */ - private generateUniqueComponentKey(baseKey: string, targetItemKey: string, parentComponentKey?: string): string { - let counter = 1; - let candidateKey = `${baseKey}_copy`; - - // Keep incrementing until we find a unique key - while (this.componentKeyExists(targetItemKey, candidateKey, parentComponentKey)) { - counter++; - candidateKey = `${baseKey}_copy_${counter}`; - } - - return candidateKey; - } - - /** - * Check if a component key already exists in the target item - */ - private componentKeyExists(itemKey: string, componentKey: string, parentComponentKey?: string): boolean { - const fullComponentKey = parentComponentKey ? `${parentComponentKey}.${componentKey}` : componentKey; - const item = this.survey.surveyItems[itemKey]; - if (!item) return false; - - return this.findComponentInItem(item, fullComponentKey) !== null; - } - /** * Update all item keys in the JSON data recursively */ @@ -714,54 +523,11 @@ export class CopyPaste { return newTranslations; } - /** - * Add an item to the survey at the specified target location - */ - private addItemToSurvey(target: { - parentKey: string; - index?: number; - }, item: SurveyItem, content: SurveyItemTranslations): void { - // Find the parent group item - const parentGroup = this.survey.surveyItems[target.parentKey] as GroupItem; - - if (!parentGroup) { - throw new Error(`Parent item with key '${target.parentKey}' not found`); - } - - if (parentGroup.itemType !== SurveyItemType.Group) { - throw new Error(`Parent item '${target.parentKey}' is not a group item`); - } - - // Initialize items array if it doesn't exist - if (!parentGroup.items) { - parentGroup.items = []; - } - - // Determine insertion index - let insertIndex: number; - if (target.index !== undefined) { - // Insert at specified index, or at end if index is larger than array length - insertIndex = Math.min(target.index, parentGroup.items.length); - } else { - // Insert at the end - insertIndex = parentGroup.items.length; - } - - // Add the item to the survey items collection - this.survey.surveyItems[item.key.fullKey] = item; - - // Add the item key to the parent group's items array - parentGroup.items.splice(insertIndex, 0, item.key.fullKey); - - // Update translations in the survey - this.survey.translations.setItemTranslations(item.key.fullKey, content); - } - /** * Recursively create child items for a group item */ - private createChildItemsRecursively(originalParentKey: string, newParentKey: string, originalClipboardData: SurveyItemClipboardData): void { - const groupData = originalClipboardData.items[0].itemData as any; + private createChildItemsRecursively(newParentKey: string, originalClipboardData: SurveyItemClipboardData): void { + const groupData = originalClipboardData.items[0].itemData as JsonSurveyItemGroup; if (groupData.items && Array.isArray(groupData.items)) { groupData.items.forEach((originalChildKey: string) => { @@ -799,7 +565,7 @@ export class CopyPaste { // Recursively create grandchildren if this is a group if (newChildItem.itemType === SurveyItemType.Group && (newChildItem as GroupItem).items) { - this.createChildItemsRecursively(originalChildKey, newChildKey.fullKey, childClipboardData); + this.createChildItemsRecursively(newChildKey.fullKey, childClipboardData); } } }); @@ -869,294 +635,31 @@ export class CopyPaste { return null; } - /** - * Create a component from JSON data - */ - private createComponentFromJson(componentData: any, parentComponentKey: string | undefined, itemKey: string): ItemComponent { - // Determine component type and use appropriate factory method - const componentType = componentData.type; - - // For response config components, use specialized factories - if (componentType === ItemComponentType.SingleChoice || componentType === ItemComponentType.MultipleChoice) { - return ScgMcgChoiceResponseConfig.fromJson(componentData, parentComponentKey, itemKey); - } - - // For ScgMcg option components - if (componentType === ItemComponentType.ScgMcgOption || - componentType === ItemComponentType.ScgMcgOptionWithTextInput || - componentType === ItemComponentType.ScgMcgOptionWithNumberInput || - componentType === ItemComponentType.ScgMcgOptionWithDateInput || - componentType === ItemComponentType.ScgMcgOptionWithTimeInput || - componentType === ItemComponentType.ScgMcgOptionWithDropdown || - componentType === ItemComponentType.ScgMcgOptionWithCloze) { - return ScgMcgOptionBase.fromJson(componentData, parentComponentKey, itemKey); - } - - // Default to DisplayComponent for display components - return DisplayComponent.fromJson(componentData, parentComponentKey, itemKey); - } /** - * Insert a component into an item at the specified location - */ - private insertComponentIntoItem( - item: SurveyItem, - component: ItemComponent, - location?: { - parentComponentKey?: string; - section?: 'header' | 'body' | 'footer' | 'responseConfig' | 'components'; - subSection?: 'title' | 'subtitle' | 'helpPopover' | 'topContent' | 'bottomContent'; - index?: number; - } - ): void { - if (item.itemType === SurveyItemType.Display) { - const displayItem = item as DisplayItem; - if (!displayItem.components) displayItem.components = []; - - const insertIndex = location?.index !== undefined ? - Math.min(location.index, displayItem.components.length) : - displayItem.components.length; - - displayItem.components.splice(insertIndex, 0, component as DisplayComponent); - } else if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { - const questionItem = item as QuestionItem; - - // Handle insertion into response config (group components like SingleChoice options) - if (location?.parentComponentKey) { - const parentComponent = this.findComponentInItem(item, location.parentComponentKey); - if (parentComponent && parentComponent instanceof GroupComponent) { - if (!parentComponent.items) parentComponent.items = []; - const insertIndex = location.index !== undefined ? - Math.min(location.index, parentComponent.items.length) : - parentComponent.items.length; - parentComponent.items.splice(insertIndex, 0, component); - return; - } - } - - if (location?.section === 'header') { - if (!questionItem.header) questionItem.header = {}; - if (location.subSection === 'title') questionItem.header.title = component as TextComponent; - else if (location.subSection === 'subtitle') questionItem.header.subtitle = component as TextComponent; - else if (location.subSection === 'helpPopover') questionItem.header.helpPopover = component as TextComponent; - } else if (location?.section === 'body') { - if (!questionItem.body) questionItem.body = {}; - if (location.subSection === 'topContent') { - if (!questionItem.body.topContent) questionItem.body.topContent = []; - const insertIndex = location.index !== undefined ? - Math.min(location.index, questionItem.body.topContent.length) : - questionItem.body.topContent.length; - questionItem.body.topContent.splice(insertIndex, 0, component as DisplayComponent); - } else if (location.subSection === 'bottomContent') { - if (!questionItem.body.bottomContent) questionItem.body.bottomContent = []; - const insertIndex = location.index !== undefined ? - Math.min(location.index, questionItem.body.bottomContent.length) : - questionItem.body.bottomContent.length; - questionItem.body.bottomContent.splice(insertIndex, 0, component as DisplayComponent); - } - } else if (location?.section === 'footer') { - questionItem.footer = component as TextComponent; - } else { - // Default to body top content for question items - if (!questionItem.body) questionItem.body = {}; - if (!questionItem.body.topContent) questionItem.body.topContent = []; - questionItem.body.topContent.push(component as DisplayComponent); - } - } - } - - /** - * Update component translations for the pasted component - */ - private updateComponentTranslations( - targetItemKey: string, - componentTranslations: { [locale: string]: { [contentKey: string]: any } }, - oldComponentKey: string, - newComponentKey: string - ): void { - Object.keys(componentTranslations).forEach(locale => { - const localeTranslations = componentTranslations[locale]; - Object.keys(localeTranslations).forEach(contentKey => { - // Update content key if it references the old component key - let newContentKey = contentKey; - if (contentKey === oldComponentKey) { - newContentKey = newComponentKey; - } else if (contentKey.startsWith(oldComponentKey + '.')) { - newContentKey = contentKey.replace(oldComponentKey, newComponentKey); - } - - // Set the translation in the target item - const itemTranslations = this.survey.getItemTranslations(targetItemKey) || new SurveyItemTranslations(); - itemTranslations.setContent(locale, newContentKey, localeTranslations[contentKey]); - this.survey.translations.setItemTranslations(targetItemKey, itemTranslations); - }); - }); - } - - /** - * Determine where and how to paste a component based on the target - */ - private determinePasteLocation(item: SurveyItem, targetComponentKey: string, targetComponent: ItemComponent | null): { - shouldReplace: boolean; - parentComponentKey?: string; - location?: { - parentComponentKey?: string; - section?: 'header' | 'body' | 'footer' | 'responseConfig' | 'components'; - subSection?: 'title' | 'subtitle' | 'helpPopover' | 'topContent' | 'bottomContent'; - index?: number; - }; - } { - // If target component doesn't exist, determine insertion location based on key structure - if (!targetComponent) { - return this.determinePasteLocationFromKey(item, targetComponentKey); - } - - // Determine behavior based on component type and location - if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { - const questionItem = item as QuestionItem; - - // Check if target is a single-slot component (replace behavior) - if (questionItem.header?.title?.key.fullKey === targetComponentKey) { - return { - shouldReplace: true, - location: { section: 'header', subSection: 'title' } - }; - } - if (questionItem.header?.subtitle?.key.fullKey === targetComponentKey) { - return { - shouldReplace: true, - location: { section: 'header', subSection: 'subtitle' } - }; - } - if (questionItem.header?.helpPopover?.key.fullKey === targetComponentKey) { - return { - shouldReplace: true, - location: { section: 'header', subSection: 'helpPopover' } - }; - } - if (questionItem.footer?.key.fullKey === targetComponentKey) { - return { - shouldReplace: true, - location: { section: 'footer' } - }; - } - - // Check if target is in a group component (add behavior) - // Check response config (SingleChoice/MultipleChoice with items) - if (questionItem.responseConfig.key.fullKey === targetComponentKey) { - return { - shouldReplace: false, - parentComponentKey: targetComponentKey, - location: { parentComponentKey: targetComponentKey } - }; - } - - // Check if target is in topContent or bottomContent arrays - const topContentMatch = questionItem.body?.topContent?.find(comp => comp.key.fullKey === targetComponentKey); - if (topContentMatch) { - return { - shouldReplace: false, - location: { section: 'body', subSection: 'topContent' } - }; - } - - const bottomContentMatch = questionItem.body?.bottomContent?.find(comp => comp.key.fullKey === targetComponentKey); - if (bottomContentMatch) { - return { - shouldReplace: false, - location: { section: 'body', subSection: 'bottomContent' } - }; - } - } - - if (item.itemType === SurveyItemType.Display) { - const displayItem = item as DisplayItem; - - // For display items, components array allows adding - const componentMatch = displayItem.components?.find(comp => comp.key.fullKey === targetComponentKey); - if (componentMatch) { - return { - shouldReplace: false, - location: { section: 'components' } - }; - } - } - - // Default to adding behavior if we can't determine the specific context - return { - shouldReplace: false, - location: undefined - }; - } - - /** - * Determine paste location when target component doesn't exist based on key structure - */ - private determinePasteLocationFromKey(item: SurveyItem, targetComponentKey: string): { - shouldReplace: boolean; - parentComponentKey?: string; - location?: { - parentComponentKey?: string; - section?: 'header' | 'body' | 'footer' | 'responseConfig' | 'components'; - subSection?: 'title' | 'subtitle' | 'helpPopover' | 'topContent' | 'bottomContent'; - index?: number; - }; - } { - if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { - // Analyze key structure to determine intended location - if (targetComponentKey === 'title') { - return { shouldReplace: true, location: { section: 'header', subSection: 'title' } }; - } - if (targetComponentKey === 'subtitle') { - return { shouldReplace: true, location: { section: 'header', subSection: 'subtitle' } }; - } - if (targetComponentKey === 'helpPopover') { - return { shouldReplace: true, location: { section: 'header', subSection: 'helpPopover' } }; - } - if (targetComponentKey === 'footer') { - return { shouldReplace: true, location: { section: 'footer' } }; - } - if (targetComponentKey === 'rg' || targetComponentKey.startsWith('rg.')) { - return { shouldReplace: false, parentComponentKey: 'rg', location: { parentComponentKey: 'rg' } }; - } - - // Default to body top content for question items - return { shouldReplace: false, location: { section: 'body', subSection: 'topContent' } }; - } - - if (item.itemType === SurveyItemType.Display) { - // Default to components array for display items - return { shouldReplace: false, location: { section: 'components' } }; - } - - // Default behavior - return { shouldReplace: false, location: undefined }; + * Validate clipboard data format + */ + static isValidClipboardData(data: unknown): data is SurveyItemClipboardData { + if (typeof data !== 'object' || data === null || data === undefined) return false; + const clipboardData = data as SurveyItemClipboardData; + return ( + clipboardData.type === 'survey-item' && + clipboardData.version === '1.0.0' && + clipboardData.rootItemKey !== undefined + ); } /** - * Replace an existing component with a new one + * Validate component clipboard data format */ - private replaceComponent( - item: SurveyItem, - oldComponent: ItemComponent, - newComponent: ItemComponent, - pasteInfo: { location?: any } - ): void { - if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { - const questionItem = item as QuestionItem; - - if (pasteInfo.location?.section === 'header') { - if (!questionItem.header) questionItem.header = {}; - if (pasteInfo.location.subSection === 'title') { - questionItem.header.title = newComponent as TextComponent; - } else if (pasteInfo.location.subSection === 'subtitle') { - questionItem.header.subtitle = newComponent as TextComponent; - } else if (pasteInfo.location.subSection === 'helpPopover') { - questionItem.header.helpPopover = newComponent as TextComponent; - } - } else if (pasteInfo.location?.section === 'footer') { - questionItem.footer = newComponent as TextComponent; - } - } + static isValidComponentClipboardData(data: unknown): data is SurveyComponentClipboardData { + if (typeof data !== 'object' || data === null || data === undefined) return false; + const clipboardData = data as SurveyComponentClipboardData; + return ( + clipboardData.type === 'survey-component' && + clipboardData.version === '1.0.0' && + clipboardData.componentKey !== undefined && + clipboardData.parentItemKey !== undefined + ); } } diff --git a/src/survey-editor/survey-editor.ts b/src/survey-editor/survey-editor.ts index f0d8124..8b3e86d 100644 --- a/src/survey-editor/survey-editor.ts +++ b/src/survey-editor/survey-editor.ts @@ -698,24 +698,5 @@ export class SurveyEditor { return copyPaste.copyComponent(itemKey, componentKey); } - /** - * Paste a component into an item - * @param clipboardData - The clipboard data containing the component to paste - * @param targetItemKey - The item to paste the component into - * @param targetComponentKey - The component key to paste into (if undefined, pastes into default location) - * @returns The full key of the pasted component - */ - pasteComponent( - clipboardData: SurveyComponentClipboardData, - targetItemKey: string, - targetComponentKey?: string - ): string { - this.commitIfNeeded(); - - const copyPaste = new CopyPaste(this._survey); - const newFullComponentKey = copyPaste.pasteComponentSmart(clipboardData, targetItemKey, targetComponentKey); - - this.commit(`Pasted component ${newFullComponentKey} into ${targetItemKey}`); - return newFullComponentKey; - } + // TODO: add paste component } From 0463e62228d7f3f1951133cfa32defd832aa26b7 Mon Sep 17 00:00:00 2001 From: phev8 Date: Thu, 17 Jul 2025 19:57:24 +0200 Subject: [PATCH 03/10] Refactor survey item handling by removing prefill rules - Removed prefill rules from the `Survey` and `JsonSurvey` types, streamlining the data structure. - Updated the `CopyPaste` class to eliminate prefills from clipboard data, simplifying the copy-paste functionality. - Adjusted related tests to reflect the removal of prefill handling, ensuring consistency across the codebase. --- .../survey-editor-copy-paste.test.ts | 3 +-- src/survey-editor/copy-paste.ts | 24 +------------------ src/survey/items/survey-item-json.ts | 1 + src/survey/items/survey-item.ts | 4 +++- src/survey/survey-file-schema.ts | 2 -- src/survey/survey.ts | 10 +------- 6 files changed, 7 insertions(+), 37 deletions(-) diff --git a/src/__tests__/survey-editor-copy-paste.test.ts b/src/__tests__/survey-editor-copy-paste.test.ts index d5d9fed..479bbe0 100644 --- a/src/__tests__/survey-editor-copy-paste.test.ts +++ b/src/__tests__/survey-editor-copy-paste.test.ts @@ -6,7 +6,7 @@ import { SurveyItemTranslations } from '../survey/utils'; import { TextComponent } from '../survey/components'; import { JsonSurveyItemGroup, JsonSurveyDisplayItem } from '../survey/items/survey-item-json'; import { ContentType } from '../survey/utils/content'; -import { ScgMcgChoiceResponseConfig, ScgMcgOption, ItemComponentType } from '../survey/components'; + describe('CopyPaste Functionality', () => { let copyPaste: CopyPaste; @@ -51,7 +51,6 @@ describe('CopyPaste Functionality', () => { expect(clipboardData.items[0].itemData.itemType).toBe(SurveyItemType.SingleChoiceQuestion); expect(clipboardData.translations['test-survey.group1.Q1']).toBeDefined(); expect(typeof clipboardData.translations['test-survey.group1.Q1']).toBe('object'); - expect(clipboardData.prefills).toBeDefined(); expect(clipboardData.timestamp).toBeGreaterThan(0); }); diff --git a/src/survey-editor/copy-paste.ts b/src/survey-editor/copy-paste.ts index cf00673..ab11b47 100644 --- a/src/survey-editor/copy-paste.ts +++ b/src/survey-editor/copy-paste.ts @@ -20,7 +20,6 @@ export interface SurveyItemClipboardData { itemData: JsonSurveyItem; }>; translations: { [itemKey: string]: SerializedTranslations }; - prefills: { [itemKey: string]: JsonSurveyItemResponse }; rootItemKey: string; // The key of the main item being copied timestamp: number; } @@ -85,32 +84,12 @@ export class CopyPaste { } }); - // Collect prefills for all items (if any exist) - const prefills: { [itemKey: string]: JsonSurveyItemResponse } = {}; - // Note: Prefills would typically come from the survey engine context - // For now, we'll create empty prefills structure that can be populated if needed - itemsToCopy.forEach(key => { - const surveyItem = this.survey.surveyItems[key]; - if (surveyItem.itemType !== SurveyItemType.Group && - surveyItem.itemType !== SurveyItemType.Display && - surveyItem.itemType !== SurveyItemType.PageBreak && - surveyItem.itemType !== SurveyItemType.SurveyEnd) { - // Create empty prefill structure for response items - prefills[key] = { - key: key, - itemType: surveyItem.itemType, - response: undefined - }; - } - }); - // Create clipboard data const clipboardData: SurveyItemClipboardData = { type: 'survey-item', version: '1.0.0', items: items, translations: translations, - prefills: prefills, rootItemKey: itemKey, timestamp: Date.now() }; @@ -297,8 +276,7 @@ export class CopyPaste { this.survey.translations.setItemTranslations(itemKey, itemTranslations); }); - // Update and set prefills - this.updatePrefills(clipboardData.prefills, keyMapping); + // TODO: update prefill rules where needed to use the new keys // Add the root item to the parent group const rootItem = createdItems[newRootFullKey]; diff --git a/src/survey/items/survey-item-json.ts b/src/survey/items/survey-item-json.ts index fba81f1..931ab44 100644 --- a/src/survey/items/survey-item-json.ts +++ b/src/survey/items/survey-item-json.ts @@ -27,6 +27,7 @@ export interface JsonSurveyItemBase { [componentKey: string]: JsonExpression | undefined; } } + prefillRules?: Array; } diff --git a/src/survey/items/survey-item.ts b/src/survey/items/survey-item.ts index 70d188d..9af4f15 100644 --- a/src/survey/items/survey-item.ts +++ b/src/survey/items/survey-item.ts @@ -26,6 +26,7 @@ export abstract class SurveyItem { validations?: { [validationKey: string]: Expression | undefined; } + prefillRules?: Array; constructor(itemFullKey: string, itemType: SurveyItemType) { this.key = SurveyItemKey.fromFullKey(itemFullKey); @@ -158,7 +159,6 @@ export class GroupItem extends SurveyItem { group.shuffleItems = json.shuffleItems; group.metadata = json.metadata; - group.displayConditions = json.displayConditions ? displayConditionsFromJson(json.displayConditions) : undefined; return group; } @@ -323,6 +323,7 @@ export abstract class QuestionItem extends SurveyItem { this.disabledConditions = json.disabledConditions ? disabledConditionsFromJson(json.disabledConditions) : undefined; this.templateValues = json.templateValues ? templateValuesFromJson(json.templateValues) : undefined; this.validations = json.validations ? Object.fromEntries(Object.entries(json.validations).map(([key, value]) => [key, Expression.fromJson(value)])) : undefined; + this.prefillRules = json.prefillRules ? json.prefillRules.map(rule => rule ? Expression.fromJson(rule) : undefined) : undefined; if (json.header) { this.header = { @@ -352,6 +353,7 @@ export abstract class QuestionItem extends SurveyItem { disabledConditions: this.disabledConditions ? disabledConditionsToJson(this.disabledConditions) : undefined, templateValues: this.templateValues ? templateValuesToJson(this.templateValues) : undefined, validations: this.validations ? Object.fromEntries(Object.entries(this.validations).map(([key, value]) => [key, value?.toJson()])) : undefined, + prefillRules: this.prefillRules ? this.prefillRules.map(rule => rule?.toJson()) : undefined, } if (this.header) { diff --git a/src/survey/survey-file-schema.ts b/src/survey/survey-file-schema.ts index d3b729f..4eba132 100644 --- a/src/survey/survey-file-schema.ts +++ b/src/survey/survey-file-schema.ts @@ -1,4 +1,3 @@ -import { Expression } from "../data_types/expression"; import { JsonSurveyItem } from "./items"; import { JsonSurveyTranslations } from "./utils/translations"; @@ -18,7 +17,6 @@ type ItemKey = string; export type JsonSurvey = { $schema: string; - prefillRules?: Expression[]; maxItemsPerPage?: { large: number, small: number }; availableFor?: string; requireLoginBeforeSubmission?: boolean; diff --git a/src/survey/survey.ts b/src/survey/survey.ts index 4d4cc03..3704633 100644 --- a/src/survey/survey.ts +++ b/src/survey/survey.ts @@ -1,4 +1,3 @@ -import { Expression } from "../data_types/expression"; import { CURRENT_SURVEY_SCHEMA, JsonSurvey, } from "./survey-file-schema"; import { SurveyItemTranslations, SurveyTranslations } from "./utils/translations"; import { GroupItem, QuestionItem, SurveyItem } from "./items"; @@ -8,7 +7,6 @@ import { ReferenceUsage } from "./utils/value-reference"; abstract class SurveyBase { - prefillRules?: Expression[]; maxItemsPerPage?: { large: number, small: number }; availableFor?: string; requireLoginBeforeSubmission?: boolean; @@ -52,9 +50,6 @@ export class Survey extends SurveyBase { // Parse other fields survey._translations = new SurveyTranslations(rawSurvey.translations); - if (rawSurvey.prefillRules) { - survey.prefillRules = rawSurvey.prefillRules; - } if (rawSurvey.maxItemsPerPage) { survey.maxItemsPerPage = rawSurvey.maxItemsPerPage; } @@ -80,9 +75,6 @@ export class Survey extends SurveyBase { // Export other fields json.translations = this._translations?.toJson(); - if (this.prefillRules) { - json.prefillRules = this.prefillRules; - } if (this.maxItemsPerPage) { json.maxItemsPerPage = this.maxItemsPerPage; } @@ -187,4 +179,4 @@ export class Survey extends SurveyBase { } return invalidUsages; } -} \ No newline at end of file +} From d658dbfda05a048ceb42f46b1b1af75e17e0d736 Mon Sep 17 00:00:00 2001 From: phev8 Date: Thu, 17 Jul 2025 20:19:39 +0200 Subject: [PATCH 04/10] Refactor copy-paste functionality in SurveyEditor - Replaced the `CopyPaste` class with `ItemCopyPaste` to streamline item copy-paste operations. - Updated tests to reflect changes in the copy-paste implementation, ensuring compatibility with the new class structure. - Removed unused component copy functionality and adjusted related methods in `SurveyEditor` for improved clarity and maintainability. - Introduced a new `survey-item-component-json.ts` file to separate JSON schema definitions for item components, enhancing code organization. --- .../survey-editor-copy-paste.test.ts | 47 +------ src/survey-editor/index.ts | 2 +- .../{copy-paste.ts => item-copy-paste.ts} | 120 +----------------- src/survey-editor/survey-editor.ts | 19 +-- src/survey/components/index.ts | 1 + .../components/survey-item-component-json.ts | 16 +++ .../components/survey-item-component.ts | 2 +- src/survey/items/survey-item-json.ts | 2 +- src/survey/survey-file-schema.ts | 21 --- 9 files changed, 32 insertions(+), 198 deletions(-) rename src/survey-editor/{copy-paste.ts => item-copy-paste.ts} (80%) create mode 100644 src/survey/components/survey-item-component-json.ts diff --git a/src/__tests__/survey-editor-copy-paste.test.ts b/src/__tests__/survey-editor-copy-paste.test.ts index 479bbe0..2dcbaf0 100644 --- a/src/__tests__/survey-editor-copy-paste.test.ts +++ b/src/__tests__/survey-editor-copy-paste.test.ts @@ -1,4 +1,4 @@ -import { CopyPaste, SurveyItemClipboardData, SurveyComponentClipboardData } from '../survey-editor/copy-paste'; +import { ItemCopyPaste, SurveyItemClipboardData } from '../survey-editor/item-copy-paste'; import { SurveyEditor } from '../survey-editor/survey-editor'; import { Survey } from '../survey/survey'; import { GroupItem, SingleChoiceQuestionItem, MultipleChoiceQuestionItem, DisplayItem, SurveyItemType } from '../survey/items'; @@ -9,7 +9,7 @@ import { ContentType } from '../survey/utils/content'; describe('CopyPaste Functionality', () => { - let copyPaste: CopyPaste; + let copyPaste: ItemCopyPaste; let editor: SurveyEditor; // Keep for non-copy-paste operations let survey: Survey; @@ -35,7 +35,7 @@ describe('CopyPaste Functionality', () => { survey.surveyItems['test-survey.group1.display1'] = display1; group1.items.push('test-survey.group1.display1'); - copyPaste = new CopyPaste(survey); + copyPaste = new ItemCopyPaste(survey); editor = new SurveyEditor(survey); // Keep for non-copy-paste operations }); @@ -320,54 +320,17 @@ describe('CopyPaste Functionality', () => { }); }); - - // Component tests now using copyPaste for component operations - describe('copyComponent', () => { - beforeEach(() => { - // Add a title to the question for testing - const question = survey.surveyItems['test-survey.group1.Q1'] as SingleChoiceQuestionItem; - question.header = { - title: new TextComponent('title', undefined, 'test-survey.group1.Q1') - }; - - // Add top content to question body - question.body = { - topContent: [ - new TextComponent('topText', undefined, 'test-survey.group1.Q1') - ] - }; - - copyPaste = new CopyPaste(survey); - editor = new SurveyEditor(survey); - }); - - test('should copy a display component', () => { - const clipboardData = copyPaste.copyComponent('test-survey.group1.display1', 'text1'); - - expect(clipboardData.type).toBe('survey-component'); - expect(clipboardData.version).toBe('1.0.0'); - expect(clipboardData.componentKey).toBe('text1'); - expect(clipboardData.parentItemKey).toBe('test-survey.group1.display1'); - expect(clipboardData.componentData).toBeDefined(); - expect(clipboardData.translations).toBeDefined(); - expect(clipboardData.timestamp).toBeGreaterThan(0); - }); - - // TODO: - }); - - // Add comprehensive translation copy-paste tests describe('Translation Copy-Paste Tests', () => { let surveyWithTranslations: Survey; let editorWithTranslations: SurveyEditor; - let copyPasteWithTranslations: CopyPaste; + let copyPasteWithTranslations: ItemCopyPaste; beforeEach(() => { // Create a survey with complex structure for testing translations surveyWithTranslations = new Survey('translation-test'); editorWithTranslations = new SurveyEditor(surveyWithTranslations); - copyPasteWithTranslations = new CopyPaste(surveyWithTranslations); + copyPasteWithTranslations = new ItemCopyPaste(surveyWithTranslations); // Create a group with multiple items const mainGroup = new GroupItem('translation-test.main-group'); diff --git a/src/survey-editor/index.ts b/src/survey-editor/index.ts index ace6733..da620cf 100644 --- a/src/survey-editor/index.ts +++ b/src/survey-editor/index.ts @@ -4,4 +4,4 @@ export * from './component-editor'; export * from './expression-editor'; export * from './expression-editor-generators'; export * from './undo-redo'; -export * from './copy-paste'; +export * from './item-copy-paste'; diff --git a/src/survey-editor/copy-paste.ts b/src/survey-editor/item-copy-paste.ts similarity index 80% rename from src/survey-editor/copy-paste.ts rename to src/survey-editor/item-copy-paste.ts index ab11b47..a1d250a 100644 --- a/src/survey-editor/copy-paste.ts +++ b/src/survey-editor/item-copy-paste.ts @@ -1,11 +1,12 @@ import { Survey } from "../survey/survey"; -import { SurveyItem, GroupItem, SurveyItemType, DisplayItem, QuestionItem } from "../survey/items"; +import { SurveyItem, GroupItem, SurveyItemType } from "../survey/items"; import { SurveyItemTranslations, JsonComponentContent } from "../survey/utils"; import { SurveyItemKey, ItemComponentKey } from "../survey/item-component-key"; import { JsonSurveyItem, JsonSurveyItemGroup } from "../survey/items/survey-item-json"; import { JsonSurveyItemResponse } from "../survey/responses"; import { ItemComponent, GroupComponent } from "../survey/components"; + // Serialized translation data format for clipboard export type SerializedTranslations = { [locale: string]: JsonComponentContent; @@ -24,18 +25,8 @@ export interface SurveyItemClipboardData { timestamp: number; } -// Clipboard data structure for component copy-paste functionality -export interface SurveyComponentClipboardData { - type: 'survey-component'; - version: string; - componentData: unknown; // JSON representation of the component - componentKey: string; - parentItemKey: string; - translations: { [locale: string]: { [contentKey: string]: unknown } }; - timestamp: number; -} -export class CopyPaste { +export class ItemCopyPaste { private survey: Survey; constructor(survey: Survey) { @@ -220,7 +211,7 @@ export class CopyPaste { index?: number; }): string { // Validate clipboard data - if (!CopyPaste.isValidClipboardData(clipboardData)) { + if (!ItemCopyPaste.isValidClipboardData(clipboardData)) { throw new Error('Invalid clipboard data format'); } @@ -287,59 +278,6 @@ export class CopyPaste { return newRootFullKey; } - // COMPONENT COPY-PASTE FUNCTIONALITY - - /** - * Copy a component from an item - * @param itemKey - The full key of the item containing the component - * @param componentKey - The full key of the component to copy - * @returns Clipboard data for the component - */ - copyComponent(itemKey: string, componentKey: string): SurveyComponentClipboardData { - const item = this.survey.surveyItems[itemKey]; - if (!item) { - throw new Error(`Item with key '${itemKey}' not found`); - } - - // Find the component within the item - const component = this.findComponentInItem(item, componentKey); - if (!component) { - throw new Error(`Component with key '${componentKey}' not found in item '${itemKey}'`); - } - - // Get component translations - const itemTranslations = this.survey.getItemTranslations(itemKey); - const componentTranslations: { [locale: string]: { [contentKey: string]: any } } = {}; - - if (itemTranslations) { - itemTranslations.locales.forEach(locale => { - const localeContent = itemTranslations.getAllForLocale(locale); - if (localeContent) { - // Extract translations that match this component key - const componentLocaleContent: { [contentKey: string]: any } = {}; - Object.keys(localeContent).forEach(contentKey => { - if (contentKey === componentKey || contentKey.startsWith(componentKey + '.')) { - componentLocaleContent[contentKey] = localeContent[contentKey]; - } - }); - if (Object.keys(componentLocaleContent).length > 0) { - componentTranslations[locale] = componentLocaleContent; - } - } - }); - } - - return { - type: 'survey-component', - version: '1.0.0', - componentData: component.toJson(), - componentKey: componentKey, - parentItemKey: itemKey, - translations: componentTranslations, - timestamp: Date.now() - }; - } - // PRIVATE HELPER METHODS /** * Generate a unique item key within the target parent @@ -550,42 +488,6 @@ export class CopyPaste { } } - /** - * Find a component within an item by its full key - */ - private findComponentInItem(item: SurveyItem, componentKey: string): ItemComponent | null { - // Search in different item types - if (item.itemType === SurveyItemType.Display) { - const displayItem = item as DisplayItem; - return this.searchComponentsArray(displayItem.components || [], componentKey); - } - - if (item.itemType === SurveyItemType.SingleChoiceQuestion || item.itemType === SurveyItemType.MultipleChoiceQuestion) { - const questionItem = item as QuestionItem; - - // Check header components - if (questionItem.header?.title?.key.fullKey === componentKey) return questionItem.header.title; - if (questionItem.header?.subtitle?.key.fullKey === componentKey) return questionItem.header.subtitle; - if (questionItem.header?.helpPopover?.key.fullKey === componentKey) return questionItem.header.helpPopover; - - // Check body components - const topContentResult = this.searchComponentsArray(questionItem.body?.topContent || [], componentKey); - if (topContentResult) return topContentResult; - - const bottomContentResult = this.searchComponentsArray(questionItem.body?.bottomContent || [], componentKey); - if (bottomContentResult) return bottomContentResult; - - // Check footer - if (questionItem.footer?.key.fullKey === componentKey) return questionItem.footer; - - // Check response config and its children - if (questionItem.responseConfig.key.fullKey === componentKey) return questionItem.responseConfig; - - return this.searchComponentRecursively(questionItem.responseConfig, componentKey); - } - - return null; - } /** * Search for a component in an array of components @@ -626,18 +528,4 @@ export class CopyPaste { clipboardData.rootItemKey !== undefined ); } - - /** - * Validate component clipboard data format - */ - static isValidComponentClipboardData(data: unknown): data is SurveyComponentClipboardData { - if (typeof data !== 'object' || data === null || data === undefined) return false; - const clipboardData = data as SurveyComponentClipboardData; - return ( - clipboardData.type === 'survey-component' && - clipboardData.version === '1.0.0' && - clipboardData.componentKey !== undefined && - clipboardData.parentItemKey !== undefined - ); - } } diff --git a/src/survey-editor/survey-editor.ts b/src/survey-editor/survey-editor.ts index 8b3e86d..8b807ca 100644 --- a/src/survey-editor/survey-editor.ts +++ b/src/survey-editor/survey-editor.ts @@ -4,7 +4,7 @@ import { SurveyEditorUndoRedo, type UndoRedoConfig } from "./undo-redo"; import { SurveyItemTranslations } from "../survey/utils"; import { SurveyItemKey } from "../survey/item-component-key"; import { JsonSurvey } from "../survey/survey-file-schema"; -import { CopyPaste, SurveyItemClipboardData, SurveyComponentClipboardData } from "./copy-paste"; +import { ItemCopyPaste, SurveyItemClipboardData } from "./item-copy-paste"; // Interface for serializing SurveyEditor state export interface SurveyEditorJson { @@ -664,7 +664,7 @@ export class SurveyEditor { * @returns Clipboard data that can be serialized to JSON for clipboard */ copyItem(itemKey: string): SurveyItemClipboardData { - const copyPaste = new CopyPaste(this._survey); + const copyPaste = new ItemCopyPaste(this._survey); return copyPaste.copyItem(itemKey); } @@ -680,23 +680,10 @@ export class SurveyEditor { }): string { this.commitIfNeeded(); - const copyPaste = new CopyPaste(this._survey); + const copyPaste = new ItemCopyPaste(this._survey); const newFullKey = copyPaste.pasteItem(clipboardData, target); this.commit(`Pasted ${newFullKey}`); return newFullKey; } - - /** - * Copy a component from an item - * @param itemKey - The full key of the item containing the component - * @param componentKey - The full key of the component to copy - * @returns Clipboard data for the component - */ - copyComponent(itemKey: string, componentKey: string): SurveyComponentClipboardData { - const copyPaste = new CopyPaste(this._survey); - return copyPaste.copyComponent(itemKey, componentKey); - } - - // TODO: add paste component } diff --git a/src/survey/components/index.ts b/src/survey/components/index.ts index 2e35981..9b3d696 100644 --- a/src/survey/components/index.ts +++ b/src/survey/components/index.ts @@ -1,2 +1,3 @@ export * from './survey-item-component'; +export * from './survey-item-component-json'; export * from './types'; diff --git a/src/survey/components/survey-item-component-json.ts b/src/survey/components/survey-item-component-json.ts new file mode 100644 index 0000000..7839f2e --- /dev/null +++ b/src/survey/components/survey-item-component-json.ts @@ -0,0 +1,16 @@ +export interface JsonItemComponent { + key: string; // unique identifier + type: string; // type of the component + styles?: { + classNames?: string | { + [key: string]: string; + } + } + properties?: { + [key: string]: string | number | boolean | { + type: 'templateValue', + templateValueKey: string; + } + } + items?: Array; +} diff --git a/src/survey/components/survey-item-component.ts b/src/survey/components/survey-item-component.ts index e6e0f71..89347cf 100644 --- a/src/survey/components/survey-item-component.ts +++ b/src/survey/components/survey-item-component.ts @@ -1,5 +1,5 @@ import { ItemComponentKey } from "../item-component-key"; -import { JsonItemComponent } from "../survey-file-schema"; +import { JsonItemComponent } from "./survey-item-component-json"; import { ExpectedValueType } from "../utils"; import { ValueReference, ValueReferenceMethod } from "../utils/value-reference"; import { DisplayComponentTypes, ItemComponentType, ResponseConfigComponentTypes, ScgMcgOptionTypes } from "./types"; diff --git a/src/survey/items/survey-item-json.ts b/src/survey/items/survey-item-json.ts index 931ab44..e09075f 100644 --- a/src/survey/items/survey-item-json.ts +++ b/src/survey/items/survey-item-json.ts @@ -1,5 +1,5 @@ import { JsonExpression } from "../../expressions"; -import { JsonItemComponent } from "../survey-file-schema"; +import { JsonItemComponent } from "../components"; import { JsonTemplateValue } from "../../expressions/template-value"; import { ConfidentialMode, SurveyItemType } from "./types"; diff --git a/src/survey/survey-file-schema.ts b/src/survey/survey-file-schema.ts index 4eba132..a66a4a8 100644 --- a/src/survey/survey-file-schema.ts +++ b/src/survey/survey-file-schema.ts @@ -31,24 +31,3 @@ export type JsonSurvey = { translations?: JsonSurveyTranslations; } - - - - -// TODO: move to survey-item-component.ts -export interface JsonItemComponent { - key: string; // unique identifier - type: string; // type of the component - styles?: { - classNames?: string | { - [key: string]: string; - } - } - properties?: { - [key: string]: string | number | boolean | { - type: 'templateValue', - templateValueKey: string; - } - } - items?: Array; -} From 6c7a8e0c0c713d1572fe0bf2d3e264a0e346a0ee Mon Sep 17 00:00:00 2001 From: phev8 Date: Fri, 18 Jul 2025 14:56:10 +0200 Subject: [PATCH 05/10] Update TypeScript configuration and refactor expression declarations - Updated TypeScript target from ES6 to ES2023 in `tsconfig.json` for improved language features. - Removed the `yarn.lock` file to streamline dependency management. - Refactored expression classes to use `declare` for type properties, enhancing clarity and consistency in `expression.ts`, `survey-item.ts`, and `survey-item-editors.ts`. - Added error handling in `SurveyEditor` for duplicate item keys in groups, improving robustness in item management. - Introduced a new `GroupItemEditor` class to manage group items, including methods for item ordering, swapping, and adding/removing child items, enhancing the survey editor's functionality. --- pnpm-lock.yaml | 4058 +++++++++++++++++ src/__tests__/group-item-editor.test.ts | 236 + src/expressions/expression.ts | 8 +- src/survey-editor/survey-editor.ts | 4 + src/survey-editor/survey-item-editors.ts | 219 +- .../components/survey-item-component.ts | 6 +- src/survey/items/survey-item.ts | 4 +- tsconfig.json | 6 +- yarn.lock | 3770 --------------- 9 files changed, 4527 insertions(+), 3784 deletions(-) create mode 100644 pnpm-lock.yaml create mode 100644 src/__tests__/group-item-editor.test.ts delete mode 100644 yarn.lock diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..539c85c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,4058 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + date-fns: + specifier: ^4.1.0 + version: 4.1.0 + devDependencies: + '@types/jest': + specifier: ^30.0.0 + version: 30.0.0 + eslint: + specifier: ^9.29.0 + version: 9.31.0(jiti@2.4.2) + jest: + specifier: ^30.0.2 + version: 30.0.4(@types/node@24.0.14) + ts-jest: + specifier: ^29.4.0 + version: 29.4.0(@babel/core@7.28.0)(@jest/transform@30.0.4)(@jest/types@30.0.1)(babel-jest@30.0.4(@babel/core@7.28.0))(jest-util@30.0.2)(jest@30.0.4(@types/node@24.0.14))(typescript@5.8.3) + tsdown: + specifier: ^0.12.8 + version: 0.12.9(typescript@5.8.3) + typescript: + specifier: ^5.8.3 + version: 5.8.3 + typescript-eslint: + specifier: ^8.35.0 + version: 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.0': + resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.0': + resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.0': + resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.27.6': + resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.0': + resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.0': + resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.1': + resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@emnapi/core@1.4.5': + resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==} + + '@emnapi/runtime@1.4.5': + resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==} + + '@emnapi/wasi-threads@1.0.4': + resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==} + + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.3.0': + resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.1': + resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.31.0': + resolution: {integrity: sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.3.3': + resolution: {integrity: sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@30.0.4': + resolution: {integrity: sha512-tMLCDvBJBwPqMm4OAiuKm2uF5y5Qe26KgcMn+nrDSWpEW+eeFmqA0iO4zJfL16GP7gE3bUUQ3hIuUJ22AqVRnw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/core@30.0.4': + resolution: {integrity: sha512-MWScSO9GuU5/HoWjpXAOBs6F/iobvK1XlioelgOM9St7S0Z5WTI9kjCQLPeo4eQRRYusyLW25/J7J5lbFkrYXw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/diff-sequences@30.0.1': + resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/environment@30.0.4': + resolution: {integrity: sha512-5NT+sr7ZOb8wW7C4r7wOKnRQ8zmRWQT2gW4j73IXAKp5/PX1Z8MCStBLQDYfIG3n1Sw0NRfYGdp0iIPVooBAFQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect-utils@30.0.4': + resolution: {integrity: sha512-EgXecHDNfANeqOkcak0DxsoVI4qkDUsR7n/Lr2vtmTBjwLPBnnPOF71S11Q8IObWzxm2QgQoY6f9hzrRD3gHRA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect@30.0.4': + resolution: {integrity: sha512-Z/DL7t67LBHSX4UzDyeYKqOxE/n7lbrrgEwWM3dGiH5Dgn35nk+YtgzKudmfIrBI8DRRrKYY5BCo3317HZV1Fw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/fake-timers@30.0.4': + resolution: {integrity: sha512-qZ7nxOcL5+gwBO6LErvwVy5k06VsX/deqo2XnVUSTV0TNC9lrg8FC3dARbi+5lmrr5VyX5drragK+xLcOjvjYw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/get-type@30.0.1': + resolution: {integrity: sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/globals@30.0.4': + resolution: {integrity: sha512-avyZuxEHF2EUhFF6NEWVdxkRRV6iXXcIES66DLhuLlU7lXhtFG/ySq/a8SRZmEJSsLkNAFX6z6mm8KWyXe9OEA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/pattern@30.0.1': + resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/reporters@30.0.4': + resolution: {integrity: sha512-6ycNmP0JSJEEys1FbIzHtjl9BP0tOZ/KN6iMeAKrdvGmUsa1qfRdlQRUDKJ4P84hJ3xHw1yTqJt4fvPNHhyE+g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@30.0.1': + resolution: {integrity: sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/snapshot-utils@30.0.4': + resolution: {integrity: sha512-BEpX8M/Y5lG7MI3fmiO+xCnacOrVsnbqVrcDZIT8aSGkKV1w2WwvRQxSWw5SIS8ozg7+h8tSj5EO1Riqqxcdag==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/source-map@30.0.1': + resolution: {integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-result@30.0.4': + resolution: {integrity: sha512-Mfpv8kjyKTHqsuu9YugB6z1gcdB3TSSOaKlehtVaiNlClMkEHY+5ZqCY2CrEE3ntpBMlstX/ShDAf84HKWsyIw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-sequencer@30.0.4': + resolution: {integrity: sha512-bj6ePmqi4uxAE8EHE0Slmk5uBYd9Vd/PcVt06CsBxzH4bbA8nGsI1YbXl/NH+eii4XRtyrRx+Cikub0x8H4vDg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/transform@30.0.4': + resolution: {integrity: sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/types@30.0.1': + resolution: {integrity: sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} + + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + + '@napi-rs/wasm-runtime@1.0.0': + resolution: {integrity: sha512-OInwPIZhcQ+aWOBFMUXzv95RLDTBRPaNPm5kSFJaL3gVAMVxrzc0YXNsVeLPHf+4sTviOy2e5wZdvKILb7dC/w==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@oxc-project/runtime@0.77.2': + resolution: {integrity: sha512-oqzN82vVbqK6BnUuYDlBMlMr8mEeysMn/P8HbiB3j5rD04JvIfONCfh6SbtJTxhp1C4cjLi1evrtVTIptrln7Q==} + engines: {node: '>=6.9.0'} + + '@oxc-project/types@0.77.2': + resolution: {integrity: sha512-+ZFWJF8ZBTOIO5PiNohNIw7JBzJCybScfrhLh65tcHCAtqaQkVDonjRD1HmMV/RF3rtt3r88hzSyTqvXs4j7vw==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.2.7': + resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@quansync/fs@0.1.3': + resolution: {integrity: sha512-G0OnZbMWEs5LhDyqy2UL17vGhSVHkQIfVojMtEWVenvj0V5S84VBgy86kJIuNsGDp2p7sTKlpSIpBUWdC35OKg==} + engines: {node: '>=20.0.0'} + + '@rolldown/binding-android-arm64@1.0.0-beta.28': + resolution: {integrity: sha512-hLb7k11KBXtO8xc7DO1OWriXWM/2FKv/R510NChqpzoI6au2aJbGUQTKJw4D8Mj7oHfY2Nwzy+sJBgWx/P8IKw==} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-beta.28': + resolution: {integrity: sha512-yRhjS3dcjfAasnJ2pTyCVm5rtfOmkGIglrFh+n9J7Zi4owJFsVVpbY7dOE3T1Op3mQ94apGN+Twtv6CIk6GFIQ==} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-beta.28': + resolution: {integrity: sha512-eOX0pjz++yVdqcDqnoZeVXUHxak2AcEgQBlEKJYaeJj+O5V3r3wSnlDVSkgD6YEAHo2IlIa89+qFHv529esY6w==} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-beta.28': + resolution: {integrity: sha512-WV1QYVMkkp/568iaEBoZhD1axFLhSO+ybCJlbmHkTFMub4wb5bmKtfuaBgjUVDDSB6JfZ6UL3Z0Q9VVHENOgsg==} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.28': + resolution: {integrity: sha512-ug/Wh9Tz4XB/CsYvaI2r5uC3vE3zrP5iDIsD+uEgFPV71BOQOfXFgZbC1zv+J1adkzWACr578aGQqW9jRj0gVA==} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.28': + resolution: {integrity: sha512-h3hzQuP+5l47wxn9+A39n1Q3i4mAvbNFJCZ8EZLrkqfsecfeZ5btIbDJTVAIQTy+uPr7uluAHIf11Jw+YkWjOQ==} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.28': + resolution: {integrity: sha512-oW5LydGtfdT8TI5HTybxi1DdMCXCmVE1ak4VrSmVKsbBZyE0bDgL1UvTS1OOvuq4PM24zQHIuSNOpgLXgVj4vQ==} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-ohos@1.0.0-beta.28': + resolution: {integrity: sha512-yeAAPMgssEkTCouUSYLrSWm+EXYBFI+ZTe8BVQkY5le51OCbqFNibtYkKZNHZBdhNRjWcSKSIuXN4MAXBz1j+g==} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.28': + resolution: {integrity: sha512-xWsylmva9L4ZFc28A9VGlF9fnrFpVxVC+kKqrBoqz2l/p5b4zRoFNtnSecivnxuPeR5Ga6W6lnpwGeWDvqBZ1Q==} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.28': + resolution: {integrity: sha512-IdtRNm70EH7/1mjqXJc4pa2MoAxo/xl9hN8VySG9BQuYfhQz+JDC+FZBc+krlVUO3cTJz/o4xI/x4kA+rLKTwA==} + cpu: [x64] + os: [linux] + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.28': + resolution: {integrity: sha512-jS2G0+GtUCVcglCefScxgXeLJal0UAvVwvpy3reoC07K16k8WM/lXoYsZdpw34d5ONg0XcZpcokzA9R5K2o0lQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.28': + resolution: {integrity: sha512-K6SO4e48aqpE/E6iEaXYG1kVX3owLierZUngP44f7s6WcnNUXsX8aborZZkKDKjgfk654M/EjSI7riPQXfynIA==} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.28': + resolution: {integrity: sha512-IIAecHvlUY/oxADfA6sZFfmRx0ajY+U1rAPFT77COp11kf7irUJeD9GskFzCm+7Wm+q8Vogyh0KWqqd6f5Azgg==} + cpu: [ia32] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.28': + resolution: {integrity: sha512-eMGdPBhNkylib+7eaeC69axEjg5Y1Vie5LoKDBVaZ71jYTmtrUdna9PTUblkCIChNTQKlgxpi/eCaYmhId0aYA==} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-beta.28': + resolution: {integrity: sha512-fe3/1HZ3qJmXvkGv1kacKq2b+x9gbcyF1hnmLBVrRFEQWoOcRapQjXf8+hgyxI0EJAbnKEtrp5yhohQCFCjycw==} + + '@sinclair/typebox@0.34.38': + resolution: {integrity: sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@13.0.5': + resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} + + '@tybys/wasm-util@0.10.0': + resolution: {integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.7': + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@30.0.0': + resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@24.0.14': + resolution: {integrity: sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + + '@typescript-eslint/eslint-plugin@8.37.0': + resolution: {integrity: sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.37.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/parser@8.37.0': + resolution: {integrity: sha512-kVIaQE9vrN9RLCQMQ3iyRlVJpTiDUY6woHGb30JDkfJErqrQEmtdWH3gV0PBAfGZgQXoqzXOO0T3K6ioApbbAA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/project-service@8.37.0': + resolution: {integrity: sha512-BIUXYsbkl5A1aJDdYJCBAo8rCEbAvdquQ8AnLb6z5Lp1u3x5PNgSSx9A/zqYc++Xnr/0DVpls8iQ2cJs/izTXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/scope-manager@8.37.0': + resolution: {integrity: sha512-0vGq0yiU1gbjKob2q691ybTg9JX6ShiVXAAfm2jGf3q0hdP6/BruaFjL/ManAR/lj05AvYCH+5bbVo0VtzmjOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.37.0': + resolution: {integrity: sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/type-utils@8.37.0': + resolution: {integrity: sha512-SPkXWIkVZxhgwSwVq9rqj/4VFo7MnWwVaRNznfQDc/xPYHjXnPfLWn+4L6FF1cAz6e7dsqBeMawgl7QjUMj4Ow==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/types@8.37.0': + resolution: {integrity: sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.37.0': + resolution: {integrity: sha512-zuWDMDuzMRbQOM+bHyU4/slw27bAUEcKSKKs3hcv2aNnc/tvE/h7w60dwVw8vnal2Pub6RT1T7BI8tFZ1fE+yg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/utils@8.37.0': + resolution: {integrity: sha512-TSFvkIW6gGjN2p6zbXo20FzCABbyUAuq6tBvNRGsKdsSQ6a7rnV6ADfZ7f4iI3lIiXc4F4WWvtUfDw9CJ9pO5A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/visitor-keys@8.37.0': + resolution: {integrity: sha512-YzfhzcTnZVPiLfP/oeKtDp2evwvHLMe0LOy7oe+hb9KKIumLNohYS9Hgp1ifwpu42YWxhZE8yieggz6JpqO/1w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + ansis@4.1.0: + resolution: {integrity: sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==} + engines: {node: '>=14'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + ast-kit@2.1.1: + resolution: {integrity: sha512-mfh6a7gKXE8pDlxTvqIc/syH/P3RkzbOF6LeHdcKztLEzYe6IMsRCL7N8vI7hqTGWNxpkCuuRTpT21xNWqhRtQ==} + engines: {node: '>=20.18.0'} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + babel-jest@30.0.4: + resolution: {integrity: sha512-UjG2j7sAOqsp2Xua1mS/e+ekddkSu3wpf4nZUSvXNHuVWdaOUXQ77+uyjJLDE9i0atm5x4kds8K9yb5lRsRtcA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 + + babel-plugin-istanbul@7.0.0: + resolution: {integrity: sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==} + engines: {node: '>=12'} + + babel-plugin-jest-hoist@30.0.1: + resolution: {integrity: sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@30.0.1: + resolution: {integrity: sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + birpc@2.5.0: + resolution: {integrity: sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.25.1: + resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001727: + resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + ci-info@4.3.0: + resolution: {integrity: sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==} + engines: {node: '>=8'} + + cjs-module-lexer@2.1.0: + resolution: {integrity: sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + dedent@1.6.0: + resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + diff@8.0.2: + resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} + engines: {node: '>=0.3.1'} + + dts-resolver@2.1.1: + resolution: {integrity: sha512-3BiGFhB6mj5Kv+W2vdJseQUYW+SKVzAFJL6YNP6ursbrwy1fXHRotfHi3xLNxe4wZl/K8qbAFeCDjZLjzqxxRw==} + engines: {node: '>=20.18.0'} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.187: + resolution: {integrity: sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.31.0: + resolution: {integrity: sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exit-x@0.2.2: + resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} + engines: {node: '>= 0.8.0'} + + expect@30.0.4: + resolution: {integrity: sha512-dDLGjnP2cKbEppxVICxI/Uf4YemmGMPNy0QytCbfafbpYk9AFQsxb8Uyrxii0RPK7FWgLGlSem+07WirwS3cFQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + fdir@6.4.6: + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + + jest-changed-files@30.0.2: + resolution: {integrity: sha512-Ius/iRST9FKfJI+I+kpiDh8JuUlAISnRszF9ixZDIqJF17FckH5sOzKC8a0wd0+D+8em5ADRHA5V5MnfeDk2WA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-circus@30.0.4: + resolution: {integrity: sha512-o6UNVfbXbmzjYgmVPtSQrr5xFZCtkDZGdTlptYvGFSN80RuOOlTe73djvMrs+QAuSERZWcHBNIOMH+OEqvjWuw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-cli@30.0.4: + resolution: {integrity: sha512-3dOrP3zqCWBkjoVG1zjYJpD9143N9GUCbwaF2pFF5brnIgRLHmKcCIw+83BvF1LxggfMWBA0gxkn6RuQVuRhIQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@30.0.4: + resolution: {integrity: sha512-3dzbO6sh34thAGEjJIW0fgT0GA0EVlkski6ZzMcbW6dzhenylXAE/Mj2MI4HonroWbkKc6wU6bLVQ8dvBSZ9lA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@types/node': '*' + esbuild-register: '>=3.4.0' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + esbuild-register: + optional: true + ts-node: + optional: true + + jest-diff@30.0.4: + resolution: {integrity: sha512-TSjceIf6797jyd+R64NXqicttROD+Qf98fex7CowmlSn7f8+En0da1Dglwr1AXxDtVizoxXYZBlUQwNhoOXkNw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-docblock@30.0.1: + resolution: {integrity: sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-each@30.0.2: + resolution: {integrity: sha512-ZFRsTpe5FUWFQ9cWTMguCaiA6kkW5whccPy9JjD1ezxh+mJeqmz8naL8Fl/oSbNJv3rgB0x87WBIkA5CObIUZQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-environment-node@30.0.4: + resolution: {integrity: sha512-p+rLEzC2eThXqiNh9GHHTC0OW5Ca4ZfcURp7scPjYBcmgpR9HG6750716GuUipYf2AcThU3k20B31USuiaaIEg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-haste-map@30.0.2: + resolution: {integrity: sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-leak-detector@30.0.2: + resolution: {integrity: sha512-U66sRrAYdALq+2qtKffBLDWsQ/XoNNs2Lcr83sc9lvE/hEpNafJlq2lXCPUBMNqamMECNxSIekLfe69qg4KMIQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-matcher-utils@30.0.4: + resolution: {integrity: sha512-ubCewJ54YzeAZ2JeHHGVoU+eDIpQFsfPQs0xURPWoNiO42LGJ+QGgfSf+hFIRplkZDkhH5MOvuxHKXRTUU3dUQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-message-util@30.0.2: + resolution: {integrity: sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-mock@30.0.2: + resolution: {integrity: sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@30.0.1: + resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve-dependencies@30.0.4: + resolution: {integrity: sha512-EQBYow19B/hKr4gUTn+l8Z+YLlP2X0IoPyp0UydOtrcPbIOYzJ8LKdFd+yrbwztPQvmlBFUwGPPEzHH1bAvFAw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve@30.0.2: + resolution: {integrity: sha512-q/XT0XQvRemykZsvRopbG6FQUT6/ra+XV6rPijyjT6D0msOyCvR2A5PlWZLd+fH0U8XWKZfDiAgrUNDNX2BkCw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runner@30.0.4: + resolution: {integrity: sha512-mxY0vTAEsowJwvFJo5pVivbCpuu6dgdXRmt3v3MXjBxFly7/lTk3Td0PaMyGOeNQUFmSuGEsGYqhbn7PA9OekQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runtime@30.0.4: + resolution: {integrity: sha512-tUQrZ8+IzoZYIHoPDQEB4jZoPyzBjLjq7sk0KVyd5UPRjRDOsN7o6UlvaGF8ddpGsjznl9PW+KRgWqCNO+Hn7w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-snapshot@30.0.4: + resolution: {integrity: sha512-S/8hmSkeUib8WRUq9pWEb5zMfsOjiYWDWzFzKnjX7eDyKKgimsu9hcmsUEg8a7dPAw8s/FacxsXquq71pDgPjQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-util@30.0.2: + resolution: {integrity: sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-validate@30.0.2: + resolution: {integrity: sha512-noOvul+SFER4RIvNAwGn6nmV2fXqBq67j+hKGHKGFCmK4ks/Iy1FSrqQNBLGKlu4ZZIRL6Kg1U72N1nxuRCrGQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-watcher@30.0.4: + resolution: {integrity: sha512-YESbdHDs7aQOCSSKffG8jXqOKFqw4q4YqR+wHYpR5GWEQioGvL0BfbcjvKIvPEM0XGfsfJrka7jJz3Cc3gI4VQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-worker@30.0.2: + resolution: {integrity: sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest@30.0.4: + resolution: {integrity: sha512-9QE0RS4WwTj/TtTC4h/eFVmFAhGNVerSB9XpJh8sqaXlP73ILcPcZ7JWjjEtJJe2m8QyBLKKfPQuK+3F+Xij/g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + napi-postinstall@0.3.0: + resolution: {integrity: sha512-M7NqKyhODKV1gRLdkwE7pDsZP2/SC2a2vHkOYh9MCpKMbWVfyVfUw5MaH83Fv6XMjxr5jryUp3IDDL9rlxsTeA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + pretty-format@30.0.2: + resolution: {integrity: sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pure-rand@7.0.1: + resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} + + quansync@0.2.10: + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rolldown-plugin-dts@0.13.14: + resolution: {integrity: sha512-wjNhHZz9dlN6PTIXyizB6u/mAg1wEFMW9yw7imEVe3CxHSRnNHVyycIX0yDEOVJfDNISLPbkCIPEpFpizy5+PQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + '@typescript/native-preview': '>=7.0.0-dev.20250601.1' + rolldown: ^1.0.0-beta.9 + typescript: ^5.0.0 + vue-tsc: ^2.2.0 || ^3.0.0 + peerDependenciesMeta: + '@typescript/native-preview': + optional: true + typescript: + optional: true + vue-tsc: + optional: true + + rolldown@1.0.0-beta.28: + resolution: {integrity: sha512-QOANlVluwwrLP5snQqKfC2lv/KJphMkjh4V0gpw0K40GdKmhd8eShIGOJNAC51idk5cn3xI08SZTRWj0R2XlDw==} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + synckit@0.11.8: + resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} + engines: {node: ^14.18.0 || >=16.0.0} + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + tinyexec@1.0.1: + resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-jest@29.4.0: + resolution: {integrity: sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 || ^30.0.0 + '@jest/types': ^29.0.0 || ^30.0.0 + babel-jest: ^29.0.0 || ^30.0.0 + esbuild: '*' + jest: ^29.0.0 || ^30.0.0 + jest-util: ^29.0.0 || ^30.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/transform': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + jest-util: + optional: true + + tsdown@0.12.9: + resolution: {integrity: sha512-MfrXm9PIlT3saovtWKf/gCJJ/NQCdE0SiREkdNC+9Qy6UHhdeDPxnkFaBD7xttVUmgp0yUHtGirpoLB+OVLuLA==} + engines: {node: '>=18.0.0'} + hasBin: true + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + publint: ^0.3.0 + typescript: ^5.0.0 + unplugin-lightningcss: ^0.4.0 + unplugin-unused: ^0.5.0 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + publint: + optional: true + typescript: + optional: true + unplugin-lightningcss: + optional: true + unplugin-unused: + optional: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + typescript-eslint@8.37.0: + resolution: {integrity: sha512-TnbEjzkE9EmcO0Q2zM+GE8NQLItNAJpMmED1BdgoBMYNdqMhzlbqfdSwiRlAzEK2pA9UzVW0gzaaIzXWg2BjfA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + unconfig@7.3.2: + resolution: {integrity: sha512-nqG5NNL2wFVGZ0NA/aCFw0oJ2pxSf1lwg4Z5ill8wd7K4KX/rQbHlwbh+bjctXL5Ly1xtzHenHGOK0b+lG6JVg==} + + undici-types@7.8.0: + resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.0': {} + + '@babel/core@7.28.0': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/helpers': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.1 + convert-source-map: 2.0.0 + debug: 4.4.1 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.0': + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.25.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.27.6': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.1 + + '@babel/parser@7.28.0': + dependencies: + '@babel/types': 7.28.1 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + + '@babel/traverse@7.28.0': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.1 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.1': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@bcoe/v8-coverage@0.2.3': {} + + '@emnapi/core@1.4.5': + dependencies: + '@emnapi/wasi-threads': 1.0.4 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.4.5': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.0.4': + dependencies: + tslib: 2.8.1 + optional: true + + '@eslint-community/eslint-utils@4.7.0(eslint@9.31.0(jiti@2.4.2))': + dependencies: + eslint: 9.31.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.3.0': {} + + '@eslint/core@0.15.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.1 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.31.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.3': + dependencies: + '@eslint/core': 0.15.1 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@30.0.4': + dependencies: + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + chalk: 4.1.2 + jest-message-util: 30.0.2 + jest-util: 30.0.2 + slash: 3.0.0 + + '@jest/core@30.0.4': + dependencies: + '@jest/console': 30.0.4 + '@jest/pattern': 30.0.1 + '@jest/reporters': 30.0.4 + '@jest/test-result': 30.0.4 + '@jest/transform': 30.0.4 + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 4.3.0 + exit-x: 0.2.2 + graceful-fs: 4.2.11 + jest-changed-files: 30.0.2 + jest-config: 30.0.4(@types/node@24.0.14) + jest-haste-map: 30.0.2 + jest-message-util: 30.0.2 + jest-regex-util: 30.0.1 + jest-resolve: 30.0.2 + jest-resolve-dependencies: 30.0.4 + jest-runner: 30.0.4 + jest-runtime: 30.0.4 + jest-snapshot: 30.0.4 + jest-util: 30.0.2 + jest-validate: 30.0.2 + jest-watcher: 30.0.4 + micromatch: 4.0.8 + pretty-format: 30.0.2 + slash: 3.0.0 + transitivePeerDependencies: + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + '@jest/diff-sequences@30.0.1': {} + + '@jest/environment@30.0.4': + dependencies: + '@jest/fake-timers': 30.0.4 + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + jest-mock: 30.0.2 + + '@jest/expect-utils@30.0.4': + dependencies: + '@jest/get-type': 30.0.1 + + '@jest/expect@30.0.4': + dependencies: + expect: 30.0.4 + jest-snapshot: 30.0.4 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@30.0.4': + dependencies: + '@jest/types': 30.0.1 + '@sinonjs/fake-timers': 13.0.5 + '@types/node': 24.0.14 + jest-message-util: 30.0.2 + jest-mock: 30.0.2 + jest-util: 30.0.2 + + '@jest/get-type@30.0.1': {} + + '@jest/globals@30.0.4': + dependencies: + '@jest/environment': 30.0.4 + '@jest/expect': 30.0.4 + '@jest/types': 30.0.1 + jest-mock: 30.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/pattern@30.0.1': + dependencies: + '@types/node': 24.0.14 + jest-regex-util: 30.0.1 + + '@jest/reporters@30.0.4': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 30.0.4 + '@jest/test-result': 30.0.4 + '@jest/transform': 30.0.4 + '@jest/types': 30.0.1 + '@jridgewell/trace-mapping': 0.3.29 + '@types/node': 24.0.14 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit-x: 0.2.2 + glob: 10.4.5 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + jest-message-util: 30.0.2 + jest-util: 30.0.2 + jest-worker: 30.0.2 + slash: 3.0.0 + string-length: 4.0.2 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@30.0.1': + dependencies: + '@sinclair/typebox': 0.34.38 + + '@jest/snapshot-utils@30.0.4': + dependencies: + '@jest/types': 30.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + natural-compare: 1.4.0 + + '@jest/source-map@30.0.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.29 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@30.0.4': + dependencies: + '@jest/console': 30.0.4 + '@jest/types': 30.0.1 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@30.0.4': + dependencies: + '@jest/test-result': 30.0.4 + graceful-fs: 4.2.11 + jest-haste-map: 30.0.2 + slash: 3.0.0 + + '@jest/transform@30.0.4': + dependencies: + '@babel/core': 7.28.0 + '@jest/types': 30.0.1 + '@jridgewell/trace-mapping': 0.3.29 + babel-plugin-istanbul: 7.0.0 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.0.2 + jest-regex-util: 30.0.1 + jest-util: 30.0.2 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + + '@jest/types@30.0.1': + dependencies: + '@jest/pattern': 30.0.1 + '@jest/schemas': 30.0.1 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 24.0.14 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.12': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.4': {} + + '@jridgewell/trace-mapping@0.3.29': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.4 + + '@napi-rs/wasm-runtime@0.2.12': + dependencies: + '@emnapi/core': 1.4.5 + '@emnapi/runtime': 1.4.5 + '@tybys/wasm-util': 0.10.0 + optional: true + + '@napi-rs/wasm-runtime@1.0.0': + dependencies: + '@emnapi/core': 1.4.5 + '@emnapi/runtime': 1.4.5 + '@tybys/wasm-util': 0.10.0 + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@oxc-project/runtime@0.77.2': {} + + '@oxc-project/types@0.77.2': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.2.7': {} + + '@quansync/fs@0.1.3': + dependencies: + quansync: 0.2.10 + + '@rolldown/binding-android-arm64@1.0.0-beta.28': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-beta.28': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-beta.28': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-beta.28': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.28': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.28': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.28': + optional: true + + '@rolldown/binding-linux-arm64-ohos@1.0.0-beta.28': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.28': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.28': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.28': + dependencies: + '@napi-rs/wasm-runtime': 1.0.0 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.28': + optional: true + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.28': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.28': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.28': {} + + '@sinclair/typebox@0.34.38': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@13.0.5': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@tybys/wasm-util@0.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.7 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.28.1 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + + '@types/babel__traverse@7.20.7': + dependencies: + '@babel/types': 7.28.1 + + '@types/estree@1.0.8': {} + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@30.0.0': + dependencies: + expect: 30.0.4 + pretty-format: 30.0.2 + + '@types/json-schema@7.0.15': {} + + '@types/node@24.0.14': + dependencies: + undici-types: 7.8.0 + + '@types/stack-utils@2.0.3': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@typescript-eslint/eslint-plugin@8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.37.0 + '@typescript-eslint/type-utils': 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.37.0 + eslint: 9.31.0(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.37.0 + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.37.0 + debug: 4.4.1 + eslint: 9.31.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.37.0(typescript@5.8.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.8.3) + '@typescript-eslint/types': 8.37.0 + debug: 4.4.1 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.37.0': + dependencies: + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/visitor-keys': 8.37.0 + + '@typescript-eslint/tsconfig-utils@8.37.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@typescript-eslint/type-utils@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + debug: 4.4.1 + eslint: 9.31.0(jiti@2.4.2) + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.37.0': {} + + '@typescript-eslint/typescript-estree@8.37.0(typescript@5.8.3)': + dependencies: + '@typescript-eslint/project-service': 8.37.0(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.8.3) + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/visitor-keys': 8.37.0 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.37.0 + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) + eslint: 9.31.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.37.0': + dependencies: + '@typescript-eslint/types': 8.37.0 + eslint-visitor-keys: 4.2.1 + + '@ungap/structured-clone@1.3.0': {} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + ansis@4.1.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + ast-kit@2.1.1: + dependencies: + '@babel/parser': 7.28.0 + pathe: 2.0.3 + + async@3.2.6: {} + + babel-jest@30.0.4(@babel/core@7.28.0): + dependencies: + '@babel/core': 7.28.0 + '@jest/transform': 30.0.4 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 7.0.0 + babel-preset-jest: 30.0.1(@babel/core@7.28.0) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@7.0.0: + dependencies: + '@babel/helper-plugin-utils': 7.27.1 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 6.0.3 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@30.0.1: + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.1 + '@types/babel__core': 7.20.5 + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.28.0): + dependencies: + '@babel/core': 7.28.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.0) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.0) + + babel-preset-jest@30.0.1(@babel/core@7.28.0): + dependencies: + '@babel/core': 7.28.0 + babel-plugin-jest-hoist: 30.0.1 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.0) + + balanced-match@1.0.2: {} + + birpc@2.5.0: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.25.1: + dependencies: + caniuse-lite: 1.0.30001727 + electron-to-chromium: 1.5.187 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.25.1) + + bs-logger@0.2.6: + dependencies: + fast-json-stable-stringify: 2.1.0 + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + + cac@6.7.14: {} + + callsites@3.1.0: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001727: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + char-regex@1.0.2: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + ci-info@4.3.0: {} + + cjs-module-lexer@2.1.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + co@4.6.0: {} + + collect-v8-coverage@1.0.2: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + concat-map@0.0.1: {} + + convert-source-map@2.0.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + date-fns@4.1.0: {} + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + dedent@1.6.0: {} + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + defu@6.1.4: {} + + detect-newline@3.1.0: {} + + diff@8.0.2: {} + + dts-resolver@2.1.1: {} + + eastasianwidth@0.2.0: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-to-chromium@1.5.187: {} + + emittery@0.13.1: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + empathic@2.0.0: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + escalade@3.2.0: {} + + escape-string-regexp@2.0.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.31.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.0 + '@eslint/core': 0.15.1 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.31.0 + '@eslint/plugin-kit': 0.3.3 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exit-x@0.2.2: {} + + expect@30.0.4: + dependencies: + '@jest/expect-utils': 30.0.4 + '@jest/get-type': 30.0.1 + jest-matcher-utils: 30.0.4 + jest-message-util: 30.0.2 + jest-mock: 30.0.2 + jest-util: 30.0.2 + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + fdir@6.4.6(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-package-type@0.1.0: {} + + get-stream@6.0.1: {} + + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@14.0.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + has-flag@4.0.0: {} + + hookable@5.5.3: {} + + html-escaper@2.0.2: {} + + human-signals@2.1.0: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + is-arrayish@0.2.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-fn@2.1.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-stream@2.0.1: {} + + isexe@2.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.28.0 + '@babel/parser': 7.28.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.29 + debug: 4.4.1 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + + jest-changed-files@30.0.2: + dependencies: + execa: 5.1.1 + jest-util: 30.0.2 + p-limit: 3.1.0 + + jest-circus@30.0.4: + dependencies: + '@jest/environment': 30.0.4 + '@jest/expect': 30.0.4 + '@jest/test-result': 30.0.4 + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.6.0 + is-generator-fn: 2.1.0 + jest-each: 30.0.2 + jest-matcher-utils: 30.0.4 + jest-message-util: 30.0.2 + jest-runtime: 30.0.4 + jest-snapshot: 30.0.4 + jest-util: 30.0.2 + p-limit: 3.1.0 + pretty-format: 30.0.2 + pure-rand: 7.0.1 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@30.0.4(@types/node@24.0.14): + dependencies: + '@jest/core': 30.0.4 + '@jest/test-result': 30.0.4 + '@jest/types': 30.0.1 + chalk: 4.1.2 + exit-x: 0.2.2 + import-local: 3.2.0 + jest-config: 30.0.4(@types/node@24.0.14) + jest-util: 30.0.2 + jest-validate: 30.0.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + jest-config@30.0.4(@types/node@24.0.14): + dependencies: + '@babel/core': 7.28.0 + '@jest/get-type': 30.0.1 + '@jest/pattern': 30.0.1 + '@jest/test-sequencer': 30.0.4 + '@jest/types': 30.0.1 + babel-jest: 30.0.4(@babel/core@7.28.0) + chalk: 4.1.2 + ci-info: 4.3.0 + deepmerge: 4.3.1 + glob: 10.4.5 + graceful-fs: 4.2.11 + jest-circus: 30.0.4 + jest-docblock: 30.0.1 + jest-environment-node: 30.0.4 + jest-regex-util: 30.0.1 + jest-resolve: 30.0.2 + jest-runner: 30.0.4 + jest-util: 30.0.2 + jest-validate: 30.0.2 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 30.0.2 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 24.0.14 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@30.0.4: + dependencies: + '@jest/diff-sequences': 30.0.1 + '@jest/get-type': 30.0.1 + chalk: 4.1.2 + pretty-format: 30.0.2 + + jest-docblock@30.0.1: + dependencies: + detect-newline: 3.1.0 + + jest-each@30.0.2: + dependencies: + '@jest/get-type': 30.0.1 + '@jest/types': 30.0.1 + chalk: 4.1.2 + jest-util: 30.0.2 + pretty-format: 30.0.2 + + jest-environment-node@30.0.4: + dependencies: + '@jest/environment': 30.0.4 + '@jest/fake-timers': 30.0.4 + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + jest-mock: 30.0.2 + jest-util: 30.0.2 + jest-validate: 30.0.2 + + jest-haste-map@30.0.2: + dependencies: + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 30.0.1 + jest-util: 30.0.2 + jest-worker: 30.0.2 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-leak-detector@30.0.2: + dependencies: + '@jest/get-type': 30.0.1 + pretty-format: 30.0.2 + + jest-matcher-utils@30.0.4: + dependencies: + '@jest/get-type': 30.0.1 + chalk: 4.1.2 + jest-diff: 30.0.4 + pretty-format: 30.0.2 + + jest-message-util@30.0.2: + dependencies: + '@babel/code-frame': 7.27.1 + '@jest/types': 30.0.1 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 30.0.2 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@30.0.2: + dependencies: + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + jest-util: 30.0.2 + + jest-pnp-resolver@1.2.3(jest-resolve@30.0.2): + optionalDependencies: + jest-resolve: 30.0.2 + + jest-regex-util@30.0.1: {} + + jest-resolve-dependencies@30.0.4: + dependencies: + jest-regex-util: 30.0.1 + jest-snapshot: 30.0.4 + transitivePeerDependencies: + - supports-color + + jest-resolve@30.0.2: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 30.0.2 + jest-pnp-resolver: 1.2.3(jest-resolve@30.0.2) + jest-util: 30.0.2 + jest-validate: 30.0.2 + slash: 3.0.0 + unrs-resolver: 1.11.1 + + jest-runner@30.0.4: + dependencies: + '@jest/console': 30.0.4 + '@jest/environment': 30.0.4 + '@jest/test-result': 30.0.4 + '@jest/transform': 30.0.4 + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + chalk: 4.1.2 + emittery: 0.13.1 + exit-x: 0.2.2 + graceful-fs: 4.2.11 + jest-docblock: 30.0.1 + jest-environment-node: 30.0.4 + jest-haste-map: 30.0.2 + jest-leak-detector: 30.0.2 + jest-message-util: 30.0.2 + jest-resolve: 30.0.2 + jest-runtime: 30.0.4 + jest-util: 30.0.2 + jest-watcher: 30.0.4 + jest-worker: 30.0.2 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + + jest-runtime@30.0.4: + dependencies: + '@jest/environment': 30.0.4 + '@jest/fake-timers': 30.0.4 + '@jest/globals': 30.0.4 + '@jest/source-map': 30.0.1 + '@jest/test-result': 30.0.4 + '@jest/transform': 30.0.4 + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + chalk: 4.1.2 + cjs-module-lexer: 2.1.0 + collect-v8-coverage: 1.0.2 + glob: 10.4.5 + graceful-fs: 4.2.11 + jest-haste-map: 30.0.2 + jest-message-util: 30.0.2 + jest-mock: 30.0.2 + jest-regex-util: 30.0.1 + jest-resolve: 30.0.2 + jest-snapshot: 30.0.4 + jest-util: 30.0.2 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@30.0.4: + dependencies: + '@babel/core': 7.28.0 + '@babel/generator': 7.28.0 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/types': 7.28.1 + '@jest/expect-utils': 30.0.4 + '@jest/get-type': 30.0.1 + '@jest/snapshot-utils': 30.0.4 + '@jest/transform': 30.0.4 + '@jest/types': 30.0.1 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.0) + chalk: 4.1.2 + expect: 30.0.4 + graceful-fs: 4.2.11 + jest-diff: 30.0.4 + jest-matcher-utils: 30.0.4 + jest-message-util: 30.0.2 + jest-util: 30.0.2 + pretty-format: 30.0.2 + semver: 7.7.2 + synckit: 0.11.8 + transitivePeerDependencies: + - supports-color + + jest-util@30.0.2: + dependencies: + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + chalk: 4.1.2 + ci-info: 4.3.0 + graceful-fs: 4.2.11 + picomatch: 4.0.3 + + jest-validate@30.0.2: + dependencies: + '@jest/get-type': 30.0.1 + '@jest/types': 30.0.1 + camelcase: 6.3.0 + chalk: 4.1.2 + leven: 3.1.0 + pretty-format: 30.0.2 + + jest-watcher@30.0.4: + dependencies: + '@jest/test-result': 30.0.4 + '@jest/types': 30.0.1 + '@types/node': 24.0.14 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 30.0.2 + string-length: 4.0.2 + + jest-worker@30.0.2: + dependencies: + '@types/node': 24.0.14 + '@ungap/structured-clone': 1.3.0 + jest-util: 30.0.2 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@30.0.4(@types/node@24.0.14): + dependencies: + '@jest/core': 30.0.4 + '@jest/types': 30.0.1 + import-local: 3.2.0 + jest-cli: 30.0.4(@types/node@24.0.14) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + jiti@2.4.2: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + leven@3.1.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lines-and-columns@1.2.4: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.memoize@4.1.2: {} + + lodash.merge@4.6.2: {} + + lru-cache@10.4.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.2 + + make-error@1.3.6: {} + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mimic-fn@2.1.0: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.2 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minipass@7.1.2: {} + + ms@2.1.3: {} + + napi-postinstall@0.3.0: {} + + natural-compare@1.4.0: {} + + node-int64@0.4.0: {} + + node-releases@2.0.19: {} + + normalize-path@3.0.0: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + pirates@4.0.7: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + prelude-ls@1.2.1: {} + + pretty-format@30.0.2: + dependencies: + '@jest/schemas': 30.0.1 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + punycode@2.3.1: {} + + pure-rand@7.0.1: {} + + quansync@0.2.10: {} + + queue-microtask@1.2.3: {} + + react-is@18.3.1: {} + + readdirp@4.1.2: {} + + require-directory@2.1.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + reusify@1.1.0: {} + + rolldown-plugin-dts@0.13.14(rolldown@1.0.0-beta.28)(typescript@5.8.3): + dependencies: + '@babel/generator': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + ast-kit: 2.1.1 + birpc: 2.5.0 + debug: 4.4.1 + dts-resolver: 2.1.1 + get-tsconfig: 4.10.1 + rolldown: 1.0.0-beta.28 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - oxc-resolver + - supports-color + + rolldown@1.0.0-beta.28: + dependencies: + '@oxc-project/runtime': 0.77.2 + '@oxc-project/types': 0.77.2 + '@rolldown/pluginutils': 1.0.0-beta.28 + ansis: 4.1.0 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-beta.28 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.28 + '@rolldown/binding-darwin-x64': 1.0.0-beta.28 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.28 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.28 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.28 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.28 + '@rolldown/binding-linux-arm64-ohos': 1.0.0-beta.28 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.28 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.28 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.28 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.28 + '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.28 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.28 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + semver@6.3.1: {} + + semver@7.7.2: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + slash@3.0.0: {} + + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + sprintf-js@1.0.3: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom@4.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + synckit@0.11.8: + dependencies: + '@pkgr/core': 0.2.7 + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + tinyexec@1.0.1: {} + + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + + tmpl@1.0.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + ts-api-utils@2.1.0(typescript@5.8.3): + dependencies: + typescript: 5.8.3 + + ts-jest@29.4.0(@babel/core@7.28.0)(@jest/transform@30.0.4)(@jest/types@30.0.1)(babel-jest@30.0.4(@babel/core@7.28.0))(jest-util@30.0.2)(jest@30.0.4(@types/node@24.0.14))(typescript@5.8.3): + dependencies: + bs-logger: 0.2.6 + ejs: 3.1.10 + fast-json-stable-stringify: 2.1.0 + jest: 30.0.4(@types/node@24.0.14) + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.7.2 + type-fest: 4.41.0 + typescript: 5.8.3 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.28.0 + '@jest/transform': 30.0.4 + '@jest/types': 30.0.1 + babel-jest: 30.0.4(@babel/core@7.28.0) + jest-util: 30.0.2 + + tsdown@0.12.9(typescript@5.8.3): + dependencies: + ansis: 4.1.0 + cac: 6.7.14 + chokidar: 4.0.3 + debug: 4.4.1 + diff: 8.0.2 + empathic: 2.0.0 + hookable: 5.5.3 + rolldown: 1.0.0-beta.28 + rolldown-plugin-dts: 0.13.14(rolldown@1.0.0-beta.28)(typescript@5.8.3) + semver: 7.7.2 + tinyexec: 1.0.1 + tinyglobby: 0.2.14 + unconfig: 7.3.2 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@typescript/native-preview' + - oxc-resolver + - supports-color + - vue-tsc + + tslib@2.8.1: + optional: true + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-detect@4.0.8: {} + + type-fest@0.21.3: {} + + type-fest@4.41.0: {} + + typescript-eslint@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/parser': 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + eslint: 9.31.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + typescript@5.8.3: {} + + unconfig@7.3.2: + dependencies: + '@quansync/fs': 0.1.3 + defu: 6.1.4 + jiti: 2.4.2 + quansync: 0.2.10 + + undici-types@7.8.0: {} + + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.0 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + + update-browserslist-db@1.1.3(browserslist@4.25.1): + dependencies: + browserslist: 4.25.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.29 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} diff --git a/src/__tests__/group-item-editor.test.ts b/src/__tests__/group-item-editor.test.ts new file mode 100644 index 0000000..fad70f9 --- /dev/null +++ b/src/__tests__/group-item-editor.test.ts @@ -0,0 +1,236 @@ +import { Survey } from '../survey/survey'; +import { SurveyEditor } from '../survey-editor/survey-editor'; +import { GroupItemEditor } from '../survey-editor/survey-item-editors'; +import { GroupItem, SurveyItemType, SingleChoiceQuestionItem } from '../survey/items'; +import { SurveyItemTranslations } from '../survey/utils'; + +describe('GroupItemEditor', () => { + let survey: Survey; + let editor: SurveyEditor; + let groupEditor: GroupItemEditor; + let rootGroupKey: string; + + beforeEach(() => { + // Create a simple survey with a root group and some child items + const rootGroup = new GroupItem('root'); + rootGroup.items = ['root.item1', 'root.item2', 'root.item3']; + + const item1 = new SingleChoiceQuestionItem('root.item1'); + const item2 = new SingleChoiceQuestionItem('root.item2'); + const item3 = new SingleChoiceQuestionItem('root.item3'); + + survey = new Survey('root'); + survey.surveyItems = { + 'root': rootGroup, + 'root.item1': item1, + 'root.item2': item2, + 'root.item3': item3 + }; + + editor = new SurveyEditor(survey); + rootGroupKey = 'root'; + groupEditor = new GroupItemEditor(editor, rootGroupKey); + }); + + describe('constructor', () => { + it('should create a GroupItemEditor for a valid group item', () => { + expect(groupEditor).toBeInstanceOf(GroupItemEditor); + expect(groupEditor.childItemKeys).toEqual(['root.item1', 'root.item2', 'root.item3']); + }); + + it('should throw error for non-group item', () => { + expect(() => { + new GroupItemEditor(editor, 'root.item1'); + }).toThrow('Item root.item1 is not a group'); + }); + + it('should throw error for non-existent item', () => { + expect(() => { + new GroupItemEditor(editor, 'nonexistent'); + }).toThrow('Item nonexistent not found in survey'); + }); + }); + + describe('childItemKeys and childItems', () => { + it('should return correct child item keys', () => { + expect(groupEditor.childItemKeys).toEqual(['root.item1', 'root.item2', 'root.item3']); + }); + + it('should return correct child items', () => { + const childItems = groupEditor.childItems; + expect(childItems).toHaveLength(3); + expect(childItems[0].key.fullKey).toBe('root.item1'); + expect(childItems[1].key.fullKey).toBe('root.item2'); + expect(childItems[2].key.fullKey).toBe('root.item3'); + }); + + it('should handle empty group', () => { + const emptyGroup = new GroupItem('empty'); + survey.surveyItems['empty'] = emptyGroup; + const emptyGroupEditor = new GroupItemEditor(editor, 'empty'); + + expect(emptyGroupEditor.childItemKeys).toEqual([]); + expect(emptyGroupEditor.childItems).toEqual([]); + }); + }); + + describe('updateItemOrdering', () => { + it('should reorder items correctly', () => { + const newOrder = ['root.item3', 'root.item1', 'root.item2']; + groupEditor.updateItemOrdering(newOrder); + + expect(groupEditor.childItemKeys).toEqual(newOrder); + }); + + it('should throw error for invalid new order', () => { + expect(() => { + groupEditor.updateItemOrdering(['root.item1', 'root.item2']); // Missing item3 + }).toThrow('New order must contain exactly the same items as current children'); + + expect(() => { + groupEditor.updateItemOrdering(['root.item1', 'root.item2', 'root.nonexistent']); + }).toThrow('New order must contain exactly the same items as current children'); + }); + }); + + describe('swapItemsByIndex', () => { + it('should swap items at given indices', () => { + groupEditor.swapItemsByIndex(0, 2); + expect(groupEditor.childItemKeys).toEqual(['root.item3', 'root.item2', 'root.item1']); + }); + + it('should handle same index (no operation)', () => { + const originalOrder = [...groupEditor.childItemKeys]; + groupEditor.swapItemsByIndex(1, 1); + expect(groupEditor.childItemKeys).toEqual(originalOrder); + }); + + it('should throw error for out of bounds indices', () => { + expect(() => { + groupEditor.swapItemsByIndex(-1, 1); + }).toThrow('Index out of bounds'); + + expect(() => { + groupEditor.swapItemsByIndex(0, 5); + }).toThrow('Index out of bounds'); + }); + }); + + describe('swapItemsByKey', () => { + it('should swap items by their keys', () => { + groupEditor.swapItemsByKey('root.item1', 'root.item3'); + expect(groupEditor.childItemKeys).toEqual(['root.item3', 'root.item2', 'root.item1']); + }); + + it('should throw error for non-existent keys', () => { + expect(() => { + groupEditor.swapItemsByKey('root.item1', 'root.nonexistent'); + }).toThrow("Item 'root.nonexistent' not found in group 'root'"); + }); + }); + + describe('moveItem', () => { + it('should move item from one position to another', () => { + groupEditor.moveItem(0, 2); // Move first item to last position + expect(groupEditor.childItemKeys).toEqual(['root.item2', 'root.item3', 'root.item1']); + }); + + it('should move item backwards', () => { + groupEditor.moveItem(2, 0); // Move last item to first position + expect(groupEditor.childItemKeys).toEqual(['root.item3', 'root.item1', 'root.item2']); + }); + + it('should handle same position (no operation)', () => { + const originalOrder = [...groupEditor.childItemKeys]; + groupEditor.moveItem(1, 1); + expect(groupEditor.childItemKeys).toEqual(originalOrder); + }); + }); + + describe('moveItemByKey', () => { + it('should move item by key to specified position', () => { + groupEditor.moveItemByKey('root.item1', 2); + expect(groupEditor.childItemKeys).toEqual(['root.item2', 'root.item3', 'root.item1']); + }); + + it('should throw error for non-existent key', () => { + expect(() => { + groupEditor.moveItemByKey('root.nonexistent', 1); + }).toThrow("Item 'root.nonexistent' not found in group 'root'"); + }); + }); + + describe('utility methods', () => { + it('should get item index correctly', () => { + expect(groupEditor.getItemIndex('root.item1')).toBe(0); + expect(groupEditor.getItemIndex('root.item2')).toBe(1); + expect(groupEditor.getItemIndex('root.item3')).toBe(2); + expect(groupEditor.getItemIndex('root.nonexistent')).toBe(-1); + }); + + it('should check if item is child correctly', () => { + expect(groupEditor.hasChildItem('root.item1')).toBe(true); + expect(groupEditor.hasChildItem('root.item2')).toBe(true); + expect(groupEditor.hasChildItem('root.nonexistent')).toBe(false); + }); + }); + + describe('shuffleItems', () => { + it('should set and get shuffle items correctly', () => { + expect(groupEditor.getShuffleItems()).toBe(false); + + groupEditor.setShuffleItems(true); + expect(groupEditor.getShuffleItems()).toBe(true); + + groupEditor.setShuffleItems(false); + expect(groupEditor.getShuffleItems()).toBe(false); + }); + }); + + describe('addChildItem and removeChildItem', () => { + it('should add child item at specified position', () => { + const newItem = new SingleChoiceQuestionItem('root.item4'); + const translations = new SurveyItemTranslations(); + + groupEditor.addChildItem(newItem, translations, 1); + expect(groupEditor.childItemKeys).toEqual(['root.item1', 'root.item4', 'root.item2', 'root.item3']); + }); + + it('should add child item at end if no position specified', () => { + const newItem = new SingleChoiceQuestionItem('root.item4'); + const translations = new SurveyItemTranslations(); + + groupEditor.addChildItem(newItem, translations); + expect(groupEditor.childItemKeys).toEqual(['root.item1', 'root.item2', 'root.item3', 'root.item4']); + }); + + it('should remove child item', () => { + const removed = groupEditor.removeChildItem('root.item2'); + expect(removed).toBe(true); + expect(groupEditor.childItemKeys).toEqual(['root.item1', 'root.item3']); + }); + + it('should return false when removing non-existent child', () => { + const removed = groupEditor.removeChildItem('root.nonexistent'); + expect(removed).toBe(false); + }); + + it('should add duplicate entry when adding item with duplicate key', () => { + const duplicateItem = new SingleChoiceQuestionItem('root.item1'); // Same key as existing item + const translations = new SurveyItemTranslations(); + + // Adding a duplicate item (same key as existing child) should throw an error + expect(() => { + groupEditor.addChildItem(duplicateItem, translations); + }).toThrow('Item root.item1 already in this group'); + }); + + it('should successfully add new item with unique key', () => { + const newItem = new SingleChoiceQuestionItem('root.uniqueItem'); + const translations = new SurveyItemTranslations(); + + groupEditor.addChildItem(newItem, translations); + expect(groupEditor.hasChildItem('root.uniqueItem')).toBe(true); + }); + }); +}); diff --git a/src/expressions/expression.ts b/src/expressions/expression.ts index b7cb5fe..bac44ea 100644 --- a/src/expressions/expression.ts +++ b/src/expressions/expression.ts @@ -110,7 +110,7 @@ export abstract class Expression { } export class ConstExpression extends Expression { - type!: ExpressionType.Const; + declare type: ExpressionType.Const; value?: ValueType; constructor(value?: ValueType, editorConfig?: ExpressionEditorConfig) { @@ -146,7 +146,7 @@ export class ConstExpression extends Expression { } export class ResponseVariableExpression extends Expression { - type: ExpressionType.ResponseVariable; + declare type: ExpressionType.ResponseVariable; variableRef: string; constructor(variableRef: string, editorConfig?: ExpressionEditorConfig) { @@ -191,7 +191,7 @@ export class ResponseVariableExpression extends Expression { } export class ContextVariableExpression extends Expression { - type: ExpressionType.ContextVariable; + declare type: ExpressionType.ContextVariable; contextType: ContextVariableType; key?: Expression; @@ -277,7 +277,7 @@ export enum FunctionExpressionNames { } export class FunctionExpression extends Expression { - type: ExpressionType.Function; + declare type: ExpressionType.Function; functionName: FunctionExpressionNames; arguments: Array; diff --git a/src/survey-editor/survey-editor.ts b/src/survey-editor/survey-editor.ts index 8b807ca..545bee3 100644 --- a/src/survey-editor/survey-editor.ts +++ b/src/survey-editor/survey-editor.ts @@ -395,6 +395,10 @@ export class SurveyEditor { parentGroup.items = []; } + if (parentGroup.items.includes(item.key.fullKey)) { + throw new Error(`Item ${item.key.fullKey} already in this group`); + } + // Determine insertion index let insertIndex: number; if (target?.index !== undefined) { diff --git a/src/survey-editor/survey-item-editors.ts b/src/survey-editor/survey-item-editors.ts index cc727b5..5735f71 100644 --- a/src/survey-editor/survey-item-editors.ts +++ b/src/survey-editor/survey-item-editors.ts @@ -1,6 +1,6 @@ import { SurveyItemKey } from "../survey/item-component-key"; import { SurveyEditor } from "./survey-editor"; -import { MultipleChoiceQuestionItem, QuestionItem, SingleChoiceQuestionItem, SurveyItem, SurveyItemType } from "../survey/items"; +import { MultipleChoiceQuestionItem, QuestionItem, SingleChoiceQuestionItem, SurveyItem, SurveyItemType, GroupItem } from "../survey/items"; import { DisplayComponentEditor, ScgMcgOptionBaseEditor } from "./component-editor"; import { DisplayComponent, ItemComponent, ItemComponentType, ScgMcgOption, ScgMcgOptionBase, ScgMcgOptionTypes } from "../survey"; import { Content } from "../survey/utils/content"; @@ -242,7 +242,7 @@ export abstract class QuestionEditor extends SurveyItemEditor { * Single choice question and multiple choice question are very similar things, this is the base class for them. */ abstract class ScgMcgEditor extends QuestionEditor { - protected _currentItem!: SingleChoiceQuestionItem | MultipleChoiceQuestionItem; + declare protected _currentItem: SingleChoiceQuestionItem | MultipleChoiceQuestionItem; constructor(editor: SurveyEditor, itemFullKey: string, type: SurveyItemType.SingleChoiceQuestion | SurveyItemType.MultipleChoiceQuestion) { super(editor, itemFullKey, type); @@ -309,3 +309,218 @@ export class SingleChoiceQuestionEditor extends ScgMcgEditor { } } } + +export class GroupItemEditor extends SurveyItemEditor { + protected _currentItem: GroupItem; + + constructor(editor: SurveyEditor, itemFullKey: string) { + super(editor, itemFullKey, SurveyItemType.Group); + this._currentItem = this._editor.survey.surveyItems[itemFullKey] as GroupItem; + if (!this._currentItem) { + throw new Error(`Can't find group item ${itemFullKey}`); + } + } + + /** + * Get the ordered list of child item keys in this group + * @returns Array of child item keys in their current order + */ + get childItemKeys(): string[] { + return this._currentItem.items || []; + } + + /** + * Get the child items as SurveyItem objects in their current order + * @returns Array of child SurveyItem objects + */ + get childItems(): SurveyItem[] { + const childKeys = this.childItemKeys; + return childKeys + .map(key => this._editor.survey.surveyItems[key]) + .filter(item => item !== undefined); // Filter out any missing items + } + + /** + * Update the ordering of items within this group + * @param newOrder Array of item keys in the desired order + * @throws Error if any key in newOrder is not a child of this group + */ + updateItemOrdering(newOrder: string[]): void { + this._editor.commitIfNeeded(); + + const currentKeys = new Set(this.childItemKeys); + + // Validate that all items in newOrder are current children + if (newOrder.length !== currentKeys.size || !newOrder.every(key => currentKeys.has(key))) { + throw new Error('New order must contain exactly the same items as current children'); + } + + // Update the items array with the new order + this._currentItem.items = [...newOrder]; + + this._editor.commit(`Reordered items in group ${this._currentItem.key.fullKey}`); + } + + /** + * Swap two items by their positions in the group + * @param fromIndex The index of the first item to swap + * @param toIndex The index of the second item to swap + * @throws Error if indices are out of bounds + */ + swapItemsByIndex(fromIndex: number, toIndex: number): void { + this._editor.commitIfNeeded(); + + const items = this.childItemKeys; + + if (fromIndex < 0 || fromIndex >= items.length || toIndex < 0 || toIndex >= items.length) { + throw new Error(`Index out of bounds. Valid range is 0-${items.length - 1}`); + } + + if (fromIndex === toIndex) { + return; // No operation needed + } + + // Swap the items + const newOrder = [...items]; + [newOrder[fromIndex], newOrder[toIndex]] = [newOrder[toIndex], newOrder[fromIndex]]; + + this._currentItem.items = newOrder; + + this._editor.commit(`Swapped items at positions ${fromIndex} and ${toIndex} in group ${this._currentItem.key.fullKey}`); + } + + /** + * Swap two items by their keys + * @param itemKey1 The key of the first item to swap + * @param itemKey2 The key of the second item to swap + * @throws Error if either key is not found in this group + */ + swapItemsByKey(itemKey1: string, itemKey2: string): void { + const items = this.childItemKeys; + const index1 = items.indexOf(itemKey1); + const index2 = items.indexOf(itemKey2); + + if (index1 === -1) { + throw new Error(`Item '${itemKey1}' not found in group '${this._currentItem.key.fullKey}'`); + } + + if (index2 === -1) { + throw new Error(`Item '${itemKey2}' not found in group '${this._currentItem.key.fullKey}'`); + } + + this.swapItemsByIndex(index1, index2); + } + + /** + * Move an item from one position to another within the group + * @param fromIndex The current index of the item to move + * @param toIndex The target index where the item should be moved + * @throws Error if indices are out of bounds + */ + moveItem(fromIndex: number, toIndex: number): void { + this._editor.commitIfNeeded(); + + const items = this.childItemKeys; + + if (fromIndex < 0 || fromIndex >= items.length || toIndex < 0 || toIndex >= items.length) { + throw new Error(`Index out of bounds. Valid range is 0-${items.length - 1}`); + } + + if (fromIndex === toIndex) { + return; // No operation needed + } + + // Create new order by moving the item + const newOrder = [...items]; + const [movedItem] = newOrder.splice(fromIndex, 1); + newOrder.splice(toIndex, 0, movedItem); + + this._currentItem.items = newOrder; + + this._editor.commit(`Moved item from position ${fromIndex} to ${toIndex} in group ${this._currentItem.key.fullKey}`); + } + + /** + * Move an item by key to a specific position + * @param itemKey The key of the item to move + * @param toIndex The target index where the item should be moved + * @throws Error if the item key is not found or index is out of bounds + */ + moveItemByKey(itemKey: string, toIndex: number): void { + const items = this.childItemKeys; + const fromIndex = items.indexOf(itemKey); + + if (fromIndex === -1) { + throw new Error(`Item '${itemKey}' not found in group '${this._currentItem.key.fullKey}'`); + } + + this.moveItem(fromIndex, toIndex); + } + + /** + * Add an existing item to this group at a specific position + * @param itemKey The key of the item to add + * @param index Optional index where to insert the item (defaults to end) + * @throws Error if the item doesn't exist or is already in this group + */ + addChildItem(item: SurveyItem, translations: SurveyItemTranslations, index?: number): void { + this._editor.addItem({ + parentKey: this._currentItem.key.fullKey, + index + }, item, translations) + } + + /** + * Remove an item from this group (doesn't delete the item from the survey) + * @param itemKey The key of the item to remove from this group + * @returns true if the item was removed, false if it wasn't in the group + */ + removeChildItem(itemKey: string): boolean { + return this._editor.removeItem(itemKey); + } + + /** + * Get the index of an item within this group + * @param itemKey The key of the item to find + * @returns The index of the item, or -1 if not found + */ + getItemIndex(itemKey: string): number { + return this.childItemKeys.indexOf(itemKey); + } + + /** + * Check if an item is a direct child of this group + * @param itemKey The key of the item to check + * @returns true if the item is a direct child of this group + */ + hasChildItem(itemKey: string): boolean { + return this.childItemKeys.includes(itemKey); + } + + /** + * Set whether items in this group should be shuffled + * @param shouldShuffle Whether to shuffle items in this group + */ + setShuffleItems(shouldShuffle: boolean): void { + this._editor.commitIfNeeded(); + this._currentItem.shuffleItems = shouldShuffle; + this._editor.commit(`Set shuffleItems to ${shouldShuffle} for group ${this._currentItem.key.fullKey}`); + } + + /** + * Get whether items in this group are set to be shuffled + * @returns true if items should be shuffled + */ + getShuffleItems(): boolean { + return this._currentItem.shuffleItems || false; + } + + convertToType(type: SurveyItemType): void { + switch (type) { + case SurveyItemType.Group: + return; // Already a group + default: + throw new Error(`Cannot convert group item to ${type}`); + } + } +} diff --git a/src/survey/components/survey-item-component.ts b/src/survey/components/survey-item-component.ts index 89347cf..f81b641 100644 --- a/src/survey/components/survey-item-component.ts +++ b/src/survey/components/survey-item-component.ts @@ -140,7 +140,7 @@ export abstract class GroupComponent extends ItemComponent { // DISPLAY COMPONENTS // ======================================== export class DisplayComponent extends ItemComponent { - componentType!: DisplayComponentTypes; + declare componentType: DisplayComponentTypes; constructor( type: DisplayComponentTypes, @@ -236,7 +236,7 @@ export abstract class ResponseConfigComponent extends ItemComponent { export class ScgMcgChoiceResponseConfig extends GroupComponent { componentType: ItemComponentType.SingleChoice = ItemComponentType.SingleChoice; items: Array; - shuffleItems?: boolean; + declare shuffleItems?: boolean; constructor(compKey: string, parentFullKey: string | undefined = undefined, parentItemKey: string | undefined = undefined) { @@ -287,7 +287,7 @@ export class ScgMcgChoiceResponseConfig extends GroupComponent { } export abstract class ScgMcgOptionBase extends ItemComponent { - componentType!: ScgMcgOptionTypes; + declare componentType: ScgMcgOptionTypes; static fromJson(item: JsonItemComponent, parentFullKey: string | undefined = undefined, parentItemKey: string): ScgMcgOptionBase { switch (item.type) { diff --git a/src/survey/items/survey-item.ts b/src/survey/items/survey-item.ts index 9af4f15..2f3ffa5 100644 --- a/src/survey/items/survey-item.ts +++ b/src/survey/items/survey-item.ts @@ -511,7 +511,7 @@ abstract class ScgMcgQuestionItem extends QuestionItem { export class SingleChoiceQuestionItem extends ScgMcgQuestionItem { itemType: SurveyItemType.SingleChoiceQuestion = SurveyItemType.SingleChoiceQuestion; - responseConfig!: ScgMcgChoiceResponseConfig; + declare responseConfig: ScgMcgChoiceResponseConfig; constructor(itemFullKey: string) { super(itemFullKey, SurveyItemType.SingleChoiceQuestion); @@ -527,7 +527,7 @@ export class SingleChoiceQuestionItem extends ScgMcgQuestionItem { export class MultipleChoiceQuestionItem extends ScgMcgQuestionItem { itemType: SurveyItemType.MultipleChoiceQuestion = SurveyItemType.MultipleChoiceQuestion; - responseConfig!: ScgMcgChoiceResponseConfig; + declare responseConfig: ScgMcgChoiceResponseConfig; constructor(itemFullKey: string) { super(itemFullKey, SurveyItemType.MultipleChoiceQuestion); diff --git a/tsconfig.json b/tsconfig.json index 72dfc82..b1bae5c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es6", + "target": "es2023", "module": "ESNext", "declaration": true, "outDir": "./build", @@ -8,7 +8,7 @@ "strict": true, "moduleResolution": "node", "resolveJsonModule": true, - "esModuleInterop": true + "esModuleInterop": true, }, "include": [ "src" @@ -18,4 +18,4 @@ "build", "**/__tests__/*", ] -} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 00b07cb..0000000 --- a/yarn.lock +++ /dev/null @@ -1,3770 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.2.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== - dependencies: - "@babel/highlight" "^7.24.7" - picocolors "^1.0.0" - -"@babel/code-frame@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" - integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== - dependencies: - "@babel/helper-validator-identifier" "^7.27.1" - js-tokens "^4.0.0" - picocolors "^1.1.1" - -"@babel/compat-data@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed" - integrity sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw== - -"@babel/compat-data@^7.27.2": - version "7.27.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.5.tgz#7d0658ec1a8420fc866d1df1b03bea0e79934c82" - integrity sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg== - -"@babel/core@^7.23.9": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.7.tgz#b676450141e0b52a3d43bc91da86aa608f950ac4" - integrity sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.7" - "@babel/generator" "^7.24.7" - "@babel/helper-compilation-targets" "^7.24.7" - "@babel/helper-module-transforms" "^7.24.7" - "@babel/helpers" "^7.24.7" - "@babel/parser" "^7.24.7" - "@babel/template" "^7.24.7" - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/core@^7.27.4": - version "7.27.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.4.tgz#cc1fc55d0ce140a1828d1dd2a2eba285adbfb3ce" - integrity sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.27.3" - "@babel/helper-compilation-targets" "^7.27.2" - "@babel/helper-module-transforms" "^7.27.3" - "@babel/helpers" "^7.27.4" - "@babel/parser" "^7.27.4" - "@babel/template" "^7.27.2" - "@babel/traverse" "^7.27.4" - "@babel/types" "^7.27.3" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.7.tgz#1654d01de20ad66b4b4d99c135471bc654c55e6d" - integrity sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA== - dependencies: - "@babel/types" "^7.24.7" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" - -"@babel/generator@^7.27.3": - version "7.27.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.3.tgz#ef1c0f7cfe3b5fc8cbb9f6cc69f93441a68edefc" - integrity sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q== - dependencies: - "@babel/parser" "^7.27.3" - "@babel/types" "^7.27.3" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^3.0.2" - -"@babel/generator@^7.27.5": - version "7.27.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.5.tgz#3eb01866b345ba261b04911020cbe22dd4be8c8c" - integrity sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw== - dependencies: - "@babel/parser" "^7.27.5" - "@babel/types" "^7.27.3" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^3.0.2" - -"@babel/helper-compilation-targets@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz#4eb6c4a80d6ffeac25ab8cd9a21b5dfa48d503a9" - integrity sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg== - dependencies: - "@babel/compat-data" "^7.24.7" - "@babel/helper-validator-option" "^7.24.7" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-compilation-targets@^7.27.2": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" - integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== - dependencies: - "@babel/compat-data" "^7.27.2" - "@babel/helper-validator-option" "^7.27.1" - browserslist "^4.24.0" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-environment-visitor@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" - integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== - dependencies: - "@babel/types" "^7.24.7" - -"@babel/helper-function-name@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" - integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== - dependencies: - "@babel/template" "^7.24.7" - "@babel/types" "^7.24.7" - -"@babel/helper-hoist-variables@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" - integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== - dependencies: - "@babel/types" "^7.24.7" - -"@babel/helper-module-imports@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" - integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== - dependencies: - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - -"@babel/helper-module-imports@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" - integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== - dependencies: - "@babel/traverse" "^7.27.1" - "@babel/types" "^7.27.1" - -"@babel/helper-module-transforms@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz#31b6c9a2930679498db65b685b1698bfd6c7daf8" - integrity sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ== - dependencies: - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-module-imports" "^7.24.7" - "@babel/helper-simple-access" "^7.24.7" - "@babel/helper-split-export-declaration" "^7.24.7" - "@babel/helper-validator-identifier" "^7.24.7" - -"@babel/helper-module-transforms@^7.27.3": - version "7.27.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz#db0bbcfba5802f9ef7870705a7ef8788508ede02" - integrity sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg== - dependencies: - "@babel/helper-module-imports" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - "@babel/traverse" "^7.27.3" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz#98c84fe6fe3d0d3ae7bfc3a5e166a46844feb2a0" - integrity sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg== - -"@babel/helper-plugin-utils@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" - integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== - -"@babel/helper-simple-access@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" - integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== - dependencies: - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - -"@babel/helper-split-export-declaration@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" - integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== - dependencies: - "@babel/types" "^7.24.7" - -"@babel/helper-string-parser@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz#4d2d0f14820ede3b9807ea5fc36dfc8cd7da07f2" - integrity sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg== - -"@babel/helper-string-parser@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" - integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== - -"@babel/helper-validator-identifier@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" - integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== - -"@babel/helper-validator-identifier@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" - integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== - -"@babel/helper-validator-option@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6" - integrity sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw== - -"@babel/helper-validator-option@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" - integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== - -"@babel/helpers@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.7.tgz#aa2ccda29f62185acb5d42fb4a3a1b1082107416" - integrity sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg== - dependencies: - "@babel/template" "^7.24.7" - "@babel/types" "^7.24.7" - -"@babel/helpers@^7.27.4": - version "7.27.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.6.tgz#6456fed15b2cb669d2d1fabe84b66b34991d812c" - integrity sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug== - dependencies: - "@babel/template" "^7.27.2" - "@babel/types" "^7.27.6" - -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== - dependencies: - "@babel/helper-validator-identifier" "^7.24.7" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" - integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== - -"@babel/parser@^7.27.2", "@babel/parser@^7.27.4", "@babel/parser@^7.27.5": - version "7.27.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.5.tgz#ed22f871f110aa285a6fd934a0efed621d118826" - integrity sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg== - dependencies: - "@babel/types" "^7.27.3" - -"@babel/parser@^7.27.3": - version "7.27.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.4.tgz#f92e89e4f51847be05427285836fc88341c956df" - integrity sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g== - dependencies: - "@babel/types" "^7.27.3" - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-import-attributes@^7.24.7": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" - integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== - dependencies: - "@babel/helper-plugin-utils" "^7.27.1" - -"@babel/plugin-syntax-import-meta@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c" - integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== - dependencies: - "@babel/helper-plugin-utils" "^7.27.1" - -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz#5147d29066a793450f220c63fa3a9431b7e6dd18" - integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== - dependencies: - "@babel/helper-plugin-utils" "^7.27.1" - -"@babel/template@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" - integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== - dependencies: - "@babel/code-frame" "^7.24.7" - "@babel/parser" "^7.24.7" - "@babel/types" "^7.24.7" - -"@babel/template@^7.27.2": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" - integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/parser" "^7.27.2" - "@babel/types" "^7.27.1" - -"@babel/traverse@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.7.tgz#de2b900163fa741721ba382163fe46a936c40cf5" - integrity sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA== - dependencies: - "@babel/code-frame" "^7.24.7" - "@babel/generator" "^7.24.7" - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-function-name" "^7.24.7" - "@babel/helper-hoist-variables" "^7.24.7" - "@babel/helper-split-export-declaration" "^7.24.7" - "@babel/parser" "^7.24.7" - "@babel/types" "^7.24.7" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/traverse@^7.27.1", "@babel/traverse@^7.27.3", "@babel/traverse@^7.27.4": - version "7.27.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.4.tgz#b0045ac7023c8472c3d35effd7cc9ebd638da6ea" - integrity sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.27.3" - "@babel/parser" "^7.27.4" - "@babel/template" "^7.27.2" - "@babel/types" "^7.27.3" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2" - integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q== - dependencies: - "@babel/helper-string-parser" "^7.24.7" - "@babel/helper-validator-identifier" "^7.24.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.27.1", "@babel/types@^7.27.6": - version "7.27.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.6.tgz#a434ca7add514d4e646c80f7375c0aa2befc5535" - integrity sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q== - dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - -"@babel/types@^7.27.3": - version "7.27.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.3.tgz#c0257bedf33aad6aad1f406d35c44758321eb3ec" - integrity sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw== - dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@emnapi/core@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.3.tgz#9ac52d2d5aea958f67e52c40a065f51de59b77d6" - integrity sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g== - dependencies: - "@emnapi/wasi-threads" "1.0.2" - tslib "^2.4.0" - -"@emnapi/runtime@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.3.tgz#c0564665c80dc81c448adac23f9dfbed6c838f7d" - integrity sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ== - dependencies: - tslib "^2.4.0" - -"@emnapi/wasi-threads@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz#977f44f844eac7d6c138a415a123818c655f874c" - integrity sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA== - dependencies: - tslib "^2.4.0" - -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a" - integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw== - dependencies: - eslint-visitor-keys "^3.4.3" - -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" - integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== - -"@eslint/config-array@^0.20.1": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.20.1.tgz#454f89be82b0e5b1ae872c154c7e2f3dd42c3979" - integrity sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw== - dependencies: - "@eslint/object-schema" "^2.1.6" - debug "^4.3.1" - minimatch "^3.1.2" - -"@eslint/config-helpers@^0.2.1": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.2.tgz#3779f76b894de3a8ec4763b79660e6d54d5b1010" - integrity sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg== - -"@eslint/core@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.14.0.tgz#326289380968eaf7e96f364e1e4cf8f3adf2d003" - integrity sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg== - dependencies: - "@types/json-schema" "^7.0.15" - -"@eslint/eslintrc@^3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" - integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^10.0.1" - globals "^14.0.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@9.29.0": - version "9.29.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.29.0.tgz#dc6fd117c19825f8430867a662531da36320fe56" - integrity sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ== - -"@eslint/object-schema@^2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" - integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== - -"@eslint/plugin-kit@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz#b71b037b2d4d68396df04a8c35a49481e5593067" - integrity sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w== - dependencies: - "@eslint/core" "^0.14.0" - levn "^0.4.1" - -"@humanfs/core@^0.19.1": - version "0.19.1" - resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" - integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== - -"@humanfs/node@^0.16.6": - version "0.16.6" - resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" - integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== - dependencies: - "@humanfs/core" "^0.19.1" - "@humanwhocodes/retry" "^0.3.0" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/retry@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" - integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== - -"@humanwhocodes/retry@^0.4.2": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" - integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-30.0.2.tgz#e2bf6c7703d45f9824d77c7332388c3e1685afd7" - integrity sha512-krGElPU0FipAqpVZ/BRZOy0MZh/ARdJ0Nj+PiH1ykFY1+VpBlYNLjdjVA5CFKxnKR6PFqFutO4Z7cdK9BlGiDA== - dependencies: - "@jest/types" "30.0.1" - "@types/node" "*" - chalk "^4.1.2" - jest-message-util "30.0.2" - jest-util "30.0.2" - slash "^3.0.0" - -"@jest/core@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-30.0.2.tgz#c84c85baac55e6fa85b491edc4280425631951c7" - integrity sha512-mUMFdDtYWu7la63NxlyNIhgnzynszxunXWrtryR7bV24jV9hmi7XCZTzZHaLJjcBU66MeUAPZ81HjwASVpYhYQ== - dependencies: - "@jest/console" "30.0.2" - "@jest/pattern" "30.0.1" - "@jest/reporters" "30.0.2" - "@jest/test-result" "30.0.2" - "@jest/transform" "30.0.2" - "@jest/types" "30.0.1" - "@types/node" "*" - ansi-escapes "^4.3.2" - chalk "^4.1.2" - ci-info "^4.2.0" - exit-x "^0.2.2" - graceful-fs "^4.2.11" - jest-changed-files "30.0.2" - jest-config "30.0.2" - jest-haste-map "30.0.2" - jest-message-util "30.0.2" - jest-regex-util "30.0.1" - jest-resolve "30.0.2" - jest-resolve-dependencies "30.0.2" - jest-runner "30.0.2" - jest-runtime "30.0.2" - jest-snapshot "30.0.2" - jest-util "30.0.2" - jest-validate "30.0.2" - jest-watcher "30.0.2" - micromatch "^4.0.8" - pretty-format "30.0.2" - slash "^3.0.0" - -"@jest/diff-sequences@30.0.0": - version "30.0.0" - resolved "https://registry.yarnpkg.com/@jest/diff-sequences/-/diff-sequences-30.0.0.tgz#402d27d14e9d5161dedfca98bf181018a8931eb1" - integrity sha512-xMbtoCeKJDto86GW6AiwVv7M4QAuI56R7dVBr1RNGYbOT44M2TIzOiske2RxopBqkumDY+A1H55pGvuribRY9A== - -"@jest/diff-sequences@30.0.1": - version "30.0.1" - resolved "https://registry.yarnpkg.com/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz#0ededeae4d071f5c8ffe3678d15f3a1be09156be" - integrity sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw== - -"@jest/environment@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-30.0.2.tgz#1b0d055070e97f697e9edb25059e9435221cbe65" - integrity sha512-hRLhZRJNxBiOhxIKSq2UkrlhMt3/zVFQOAi5lvS8T9I03+kxsbflwHJEF+eXEYXCrRGRhHwECT7CDk6DyngsRA== - dependencies: - "@jest/fake-timers" "30.0.2" - "@jest/types" "30.0.1" - "@types/node" "*" - jest-mock "30.0.2" - -"@jest/expect-utils@30.0.0": - version "30.0.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-30.0.0.tgz#118d41d9df420db61d307308848a9e12f0fc1fad" - integrity sha512-UiWfsqNi/+d7xepfOv8KDcbbzcYtkWBe3a3kVDtg6M1kuN6CJ7b4HzIp5e1YHrSaQaVS8sdCoyCMCZClTLNKFQ== - dependencies: - "@jest/get-type" "30.0.0" - -"@jest/expect-utils@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-30.0.2.tgz#d065f68c128cec526540193d88f2fc64c3d4f971" - integrity sha512-FHF2YdtFBUQOo0/qdgt+6UdBFcNPF/TkVzcc+4vvf8uaBzUlONytGBeeudufIHHW1khRfM1sBbRT1VCK7n/0dQ== - dependencies: - "@jest/get-type" "30.0.1" - -"@jest/expect@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-30.0.2.tgz#b3d5adec28f3884d6fd0746c4b5d0d2473e9e212" - integrity sha512-blWRFPjv2cVfh42nLG6L3xIEbw+bnuiZYZDl/BZlsNG/i3wKV6FpPZ2EPHguk7t5QpLaouIu+7JmYO4uBR6AOg== - dependencies: - expect "30.0.2" - jest-snapshot "30.0.2" - -"@jest/fake-timers@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-30.0.2.tgz#ec758b28ae6f63a49eda9e8d6af274d152d37c09" - integrity sha512-jfx0Xg7l0gmphTY9UKm5RtH12BlLYj/2Plj6wXjVW5Era4FZKfXeIvwC67WX+4q8UCFxYS20IgnMcFBcEU0DtA== - dependencies: - "@jest/types" "30.0.1" - "@sinonjs/fake-timers" "^13.0.0" - "@types/node" "*" - jest-message-util "30.0.2" - jest-mock "30.0.2" - jest-util "30.0.2" - -"@jest/get-type@30.0.0": - version "30.0.0" - resolved "https://registry.yarnpkg.com/@jest/get-type/-/get-type-30.0.0.tgz#59dcb5a9cbd9eb0004d3a2ed2fa9c9c3abfbf005" - integrity sha512-VZWMjrBzqfDKngQ7sUctKeLxanAbsBFoZnPxNIG6CmxK7Gv6K44yqd0nzveNIBfuhGZMmk1n5PGbvdSTOu0yTg== - -"@jest/get-type@30.0.1": - version "30.0.1" - resolved "https://registry.yarnpkg.com/@jest/get-type/-/get-type-30.0.1.tgz#0d32f1bbfba511948ad247ab01b9007724fc9f52" - integrity sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw== - -"@jest/globals@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-30.0.2.tgz#3b401bb7cb8cc0a00476630298747a38e40a6fc1" - integrity sha512-DwTtus9jjbG7b6jUdkcVdptf0wtD1v153A+PVwWB/zFwXhqu6hhtSd+uq88jofMhmYPtkmPmVGUBRNCZEKXn+w== - dependencies: - "@jest/environment" "30.0.2" - "@jest/expect" "30.0.2" - "@jest/types" "30.0.1" - jest-mock "30.0.2" - -"@jest/pattern@30.0.0": - version "30.0.0" - resolved "https://registry.yarnpkg.com/@jest/pattern/-/pattern-30.0.0.tgz#2d1f04c8b64b31f1bfa71ccb60593a4415d0d452" - integrity sha512-k+TpEThzLVXMkbdxf8KHjZ83Wl+G54ytVJoDIGWwS96Ql4xyASRjc6SU1hs5jHVql+hpyK9G8N7WuFhLpGHRpQ== - dependencies: - "@types/node" "*" - jest-regex-util "30.0.0" - -"@jest/pattern@30.0.1": - version "30.0.1" - resolved "https://registry.yarnpkg.com/@jest/pattern/-/pattern-30.0.1.tgz#d5304147f49a052900b4b853dedb111d080e199f" - integrity sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA== - dependencies: - "@types/node" "*" - jest-regex-util "30.0.1" - -"@jest/reporters@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-30.0.2.tgz#e804435ab77cd05b7e8732b91006cd00bd822399" - integrity sha512-l4QzS/oKf57F8WtPZK+vvF4Io6ukplc6XgNFu4Hd/QxaLEO9f+8dSFzUua62Oe0HKlCUjKHpltKErAgDiMJKsA== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "30.0.2" - "@jest/test-result" "30.0.2" - "@jest/transform" "30.0.2" - "@jest/types" "30.0.1" - "@jridgewell/trace-mapping" "^0.3.25" - "@types/node" "*" - chalk "^4.1.2" - collect-v8-coverage "^1.0.2" - exit-x "^0.2.2" - glob "^10.3.10" - graceful-fs "^4.2.11" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^6.0.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^5.0.0" - istanbul-reports "^3.1.3" - jest-message-util "30.0.2" - jest-util "30.0.2" - jest-worker "30.0.2" - slash "^3.0.0" - string-length "^4.0.2" - v8-to-istanbul "^9.0.1" - -"@jest/schemas@30.0.0": - version "30.0.0" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-30.0.0.tgz#427b862696c65ea6f6a138a9221326519877555f" - integrity sha512-NID2VRyaEkevCRz6badhfqYwri/RvMbiHY81rk3AkK/LaiB0LSxi1RdVZ7MpZdTjNugtZeGfpL0mLs9Kp3MrQw== - dependencies: - "@sinclair/typebox" "^0.34.0" - -"@jest/schemas@30.0.1": - version "30.0.1" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-30.0.1.tgz#27c00d707d480ece0c19126af97081a1af3bc46e" - integrity sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w== - dependencies: - "@sinclair/typebox" "^0.34.0" - -"@jest/snapshot-utils@30.0.1": - version "30.0.1" - resolved "https://registry.yarnpkg.com/@jest/snapshot-utils/-/snapshot-utils-30.0.1.tgz#536108aa6b74858d758ae3b5229518c3d818bd68" - integrity sha512-6Dpv7vdtoRiISEFwYF8/c7LIvqXD7xDXtLPNzC2xqAfBznKip0MQM+rkseKwUPUpv2PJ7KW/YsnwWXrIL2xF+A== - dependencies: - "@jest/types" "30.0.1" - chalk "^4.1.2" - graceful-fs "^4.2.11" - natural-compare "^1.4.0" - -"@jest/source-map@30.0.1": - version "30.0.1" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-30.0.1.tgz#305ebec50468f13e658b3d5c26f85107a5620aaa" - integrity sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg== - dependencies: - "@jridgewell/trace-mapping" "^0.3.25" - callsites "^3.1.0" - graceful-fs "^4.2.11" - -"@jest/test-result@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-30.0.2.tgz#786849e33da6060381c508986fa7309ff855a367" - integrity sha512-KKMuBKkkZYP/GfHMhI+cH2/P3+taMZS3qnqqiPC1UXZTJskkCS+YU/ILCtw5anw1+YsTulDHFpDo70mmCedW8w== - dependencies: - "@jest/console" "30.0.2" - "@jest/types" "30.0.1" - "@types/istanbul-lib-coverage" "^2.0.6" - collect-v8-coverage "^1.0.2" - -"@jest/test-sequencer@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-30.0.2.tgz#2693692d285b1c929ed353f7f0b7cbea51c57515" - integrity sha512-fbyU5HPka0rkalZ3MXVvq0hwZY8dx3Y6SCqR64zRmh+xXlDeFl0IdL4l9e7vp4gxEXTYHbwLFA1D+WW5CucaSw== - dependencies: - "@jest/test-result" "30.0.2" - graceful-fs "^4.2.11" - jest-haste-map "30.0.2" - slash "^3.0.0" - -"@jest/transform@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-30.0.2.tgz#62ba84fcc2389ab751e7ec923958c9b1163d90c3" - integrity sha512-kJIuhLMTxRF7sc0gPzPtCDib/V9KwW3I2U25b+lYCYMVqHHSrcZopS8J8H+znx9yixuFv+Iozl8raLt/4MoxrA== - dependencies: - "@babel/core" "^7.27.4" - "@jest/types" "30.0.1" - "@jridgewell/trace-mapping" "^0.3.25" - babel-plugin-istanbul "^7.0.0" - chalk "^4.1.2" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.11" - jest-haste-map "30.0.2" - jest-regex-util "30.0.1" - jest-util "30.0.2" - micromatch "^4.0.8" - pirates "^4.0.7" - slash "^3.0.0" - write-file-atomic "^5.0.1" - -"@jest/types@30.0.0": - version "30.0.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-30.0.0.tgz#7afb1d34937f722f667b621eb9c653f0f8fda07e" - integrity sha512-1Nox8mAL52PKPfEnUQWBvKU/bp8FTT6AiDu76bFDEJj/qsRFSAVSldfCH3XYMqialti2zHXKvD5gN0AaHc0yKA== - dependencies: - "@jest/pattern" "30.0.0" - "@jest/schemas" "30.0.0" - "@types/istanbul-lib-coverage" "^2.0.6" - "@types/istanbul-reports" "^3.0.4" - "@types/node" "*" - "@types/yargs" "^17.0.33" - chalk "^4.1.2" - -"@jest/types@30.0.1": - version "30.0.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-30.0.1.tgz#a46df6a99a416fa685740ac4264b9f9cd7da1598" - integrity sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw== - dependencies: - "@jest/pattern" "30.0.1" - "@jest/schemas" "30.0.1" - "@types/istanbul-lib-coverage" "^2.0.6" - "@types/istanbul-reports" "^3.0.4" - "@types/node" "*" - "@types/yargs" "^17.0.33" - chalk "^4.1.2" - -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@napi-rs/wasm-runtime@^0.2.10", "@napi-rs/wasm-runtime@^0.2.11": - version "0.2.11" - resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz#192c1610e1625048089ab4e35bc0649ce478500e" - integrity sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA== - dependencies: - "@emnapi/core" "^1.4.3" - "@emnapi/runtime" "^1.4.3" - "@tybys/wasm-util" "^0.9.0" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@oxc-project/runtime@=0.72.3": - version "0.72.3" - resolved "https://registry.yarnpkg.com/@oxc-project/runtime/-/runtime-0.72.3.tgz#9a332ae8ad9fcbc2345c4040ab39e03b03b8ffaa" - integrity sha512-FtOS+0v7rZcnjXzYTTqv1vu/KDptD1UztFgoZkYBGe/6TcNFm+SP/jQoLvzau1SPir95WgDOBOUm2Gmsm+bQag== - -"@oxc-project/types@=0.72.3": - version "0.72.3" - resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.72.3.tgz#2463a4ba6c57e25c72029981909316b77ada59cd" - integrity sha512-CfAC4wrmMkUoISpQkFAIfMVvlPfQV3xg7ZlcqPXPOIMQhdKIId44G8W0mCPgtpWdFFAyJ+SFtiM+9vbyCkoVng== - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@pkgr/core@^0.2.4": - version "0.2.7" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.7.tgz#eb5014dfd0b03e7f3ba2eeeff506eed89b028058" - integrity sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg== - -"@quansync/fs@^0.1.1": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@quansync/fs/-/fs-0.1.3.tgz#2328aec83fef343b72c73ca77ca08e1e12bcf9d9" - integrity sha512-G0OnZbMWEs5LhDyqy2UL17vGhSVHkQIfVojMtEWVenvj0V5S84VBgy86kJIuNsGDp2p7sTKlpSIpBUWdC35OKg== - dependencies: - quansync "^0.2.10" - -"@rolldown/binding-darwin-arm64@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.15.tgz#255bfe798d47bb479dcf7c81bf796d9f9745a953" - integrity sha512-YInZppDBLp5DadbJZGc7xBfDrMCSj3P6i2rPlvOCMlvjBQxJi2kX8Jquh+LufsWUiHD3JsvvH5EuUUc/tF5fkA== - -"@rolldown/binding-darwin-x64@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.15.tgz#6caaf21aea142ad4e37b7d3f9cd3dedb63ce38e5" - integrity sha512-Zwv8KHU/XdVwLseHG6slJ0FAFklPpiO0sjNvhrcMp1X3F2ajPzUdIO8Cnu3KLmX1GWVSvu6q1kyARLUqPvlh7Q== - -"@rolldown/binding-freebsd-x64@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.15.tgz#6e91ada6eaa63111c5465d2c29e04462f2cfafc6" - integrity sha512-FwhNC23Fz9ldHW1/rX4QaoQe4kyOybCgxO9eglue3cbb3ol28KWpQl3xJfvXc9+O6PDefAs4oFBCbtTh8seiUw== - -"@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.15.tgz#d3d0c775af80d4f4b9f50adce778b19ac79bcf38" - integrity sha512-E60pNliWl4j7EFEVX2oeJZ5VzR+NG6fvDJoqfqRfCl8wtKIf9E1WPWVQIrT+zkz+Fhc5op8g7h25z6rtxsDy9g== - -"@rolldown/binding-linux-arm64-gnu@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.15.tgz#6cdea96e9558eeed75a749ba3b680804a2a7fb94" - integrity sha512-d+qo1LZ/a3EcQW08byIIZy0PBthmG/7dr69pifmNIet/azWR8jbceQaRFFczVc/NwVV3fsZDCmjG8mgJzsNEAg== - -"@rolldown/binding-linux-arm64-musl@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.15.tgz#441b703d17f01302b9b208b57b0b9eba0a5f5e8a" - integrity sha512-P1hbtYF+5ftJI2Ergs4iARbAk6Xd6WnTQb3CF9kjN3KfJTsRYdo5/fvU8Lz/gzhZVvkCXXH3NxDd9308UBO8cw== - -"@rolldown/binding-linux-x64-gnu@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.15.tgz#f5d54182fa09f5c6292f039a7f37cd67e530410f" - integrity sha512-Q9NM9uMFN9cjcrW7gd9U087B5WzkEj9dQQHOgoENZSy+vYJYS2fINCIG40ljEVC6jXmVrJgUhJKv7elRZM1nng== - -"@rolldown/binding-linux-x64-musl@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.15.tgz#230b6d74c7869b448d67ca9e3c9fa7a7c4cfc66c" - integrity sha512-1tuCWuR8gx9PyW2pxAx2ZqnOnwhoY6NWBVP6ZmrjCKQ16NclYc61BzegFXSdugCy8w1QpBPT8/c5oh2W4E5aeA== - -"@rolldown/binding-wasm32-wasi@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.15.tgz#fbc31232a97ce022b670f78cfabe33ba3215ba0e" - integrity sha512-zrSeYrpTf27hRxMLh0qpkCoWgzRKG8EyR6o09Zt9xkqCOeE5tEK/S3jV1Nii9WSqVCWFRA+OYxKzMNoykV590g== - dependencies: - "@napi-rs/wasm-runtime" "^0.2.10" - -"@rolldown/binding-win32-arm64-msvc@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.15.tgz#63e43abaac807313bfcdbfbac4887e174c4b35ce" - integrity sha512-diR41DsMUnkvb9hvW8vuIrA0WaacAN1fu6lPseXhYifAOZN6kvxEwKn7Xib8i0zjdrYErLv7GNSQ48W+xiNOnA== - -"@rolldown/binding-win32-ia32-msvc@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.15.tgz#b48f44dc2989c20b87d96c00f090e96ed44e2d78" - integrity sha512-oCbbcDC3Lk8YgdxCkG23UqVrvXVvllIBgmmwq89bhq5okPP899OI/P+oTTDsUTbhljzNq1pH8a+mR6YBxAFfvw== - -"@rolldown/binding-win32-x64-msvc@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.15.tgz#7f819d61f2643da8844e6c33e5d3dd7ba433e3e5" - integrity sha512-w5hVsOv3dzKo10wAXizmnDvUo1yasn/ps+mcn9H9TiJ/GeRE5/15Y6hG6vUQYRQNLVbYRHUt2qG0MyOoasPcHg== - -"@rolldown/pluginutils@1.0.0-beta.15": - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.15.tgz#fd82a9bb7d5349fd31964985c595b260d5709d74" - integrity sha512-lvFtIbidq5EqyAAeiVk41ZNjGRgUoGRBIuqpe1VRJ7R8Av7TLAgGWAwGlHNhO7MFkl7MNRX350CsTtIWIYkNIQ== - -"@sinclair/typebox@^0.34.0": - version "0.34.33" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.33.tgz#10ab3f1261ed9e754660250fad3e69cca1fa44b2" - integrity sha512-5HAV9exOMcXRUxo+9iYB5n09XxzCXnfy4VTNW4xnDv+FgjzAGY989C28BIdljKqmF+ZltUwujE3aossvcVtq6g== - -"@sinonjs/commons@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^13.0.0": - version "13.0.5" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz#36b9dbc21ad5546486ea9173d6bea063eb1717d5" - integrity sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw== - dependencies: - "@sinonjs/commons" "^3.0.1" - -"@tybys/wasm-util@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355" - integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw== - dependencies: - tslib "^2.4.0" - -"@types/babel__core@^7.20.5": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*": - version "7.20.6" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" - integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== - dependencies: - "@babel/types" "^7.20.7" - -"@types/estree@^1.0.6": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" - integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.1", "@types/istanbul-lib-coverage@^2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@^30.0.0": - version "30.0.0" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-30.0.0.tgz#5e85ae568006712e4ad66f25433e9bdac8801f1d" - integrity sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA== - dependencies: - expect "^30.0.0" - pretty-format "^30.0.0" - -"@types/json-schema@^7.0.15": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/node@*": - version "20.14.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.2.tgz#a5f4d2bcb4b6a87bffcaa717718c5a0f208f4a18" - integrity sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q== - dependencies: - undici-types "~5.26.4" - -"@types/stack-utils@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== - -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^17.0.33": - version "17.0.33" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" - integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/eslint-plugin@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz#515170100ff867445fe0a17ce05c14fc5fd9ca63" - integrity sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg== - dependencies: - "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "8.35.0" - "@typescript-eslint/type-utils" "8.35.0" - "@typescript-eslint/utils" "8.35.0" - "@typescript-eslint/visitor-keys" "8.35.0" - graphemer "^1.4.0" - ignore "^7.0.0" - natural-compare "^1.4.0" - ts-api-utils "^2.1.0" - -"@typescript-eslint/parser@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.35.0.tgz#20a0e17778a329a6072722f5ac418d4376b767d2" - integrity sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA== - dependencies: - "@typescript-eslint/scope-manager" "8.35.0" - "@typescript-eslint/types" "8.35.0" - "@typescript-eslint/typescript-estree" "8.35.0" - "@typescript-eslint/visitor-keys" "8.35.0" - debug "^4.3.4" - -"@typescript-eslint/project-service@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.35.0.tgz#00bd77e6845fbdb5684c6ab2d8a400a58dcfb07b" - integrity sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ== - dependencies: - "@typescript-eslint/tsconfig-utils" "^8.35.0" - "@typescript-eslint/types" "^8.35.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz#8ccb2ab63383544fab98fc4b542d8d141259ff4f" - integrity sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA== - dependencies: - "@typescript-eslint/types" "8.35.0" - "@typescript-eslint/visitor-keys" "8.35.0" - -"@typescript-eslint/tsconfig-utils@8.35.0", "@typescript-eslint/tsconfig-utils@^8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz#6e05aeb999999e31d562ceb4fe144f3cbfbd670e" - integrity sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA== - -"@typescript-eslint/type-utils@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.35.0.tgz#0201eae9d83ffcc3451ef8c94f53ecfbf2319ecc" - integrity sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA== - dependencies: - "@typescript-eslint/typescript-estree" "8.35.0" - "@typescript-eslint/utils" "8.35.0" - debug "^4.3.4" - ts-api-utils "^2.1.0" - -"@typescript-eslint/types@8.35.0", "@typescript-eslint/types@^8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.35.0.tgz#e60d062907930e30008d796de5c4170f02618a93" - integrity sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ== - -"@typescript-eslint/typescript-estree@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz#86141e6c55b75bc1eaecc0781bd39704de14e52a" - integrity sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w== - dependencies: - "@typescript-eslint/project-service" "8.35.0" - "@typescript-eslint/tsconfig-utils" "8.35.0" - "@typescript-eslint/types" "8.35.0" - "@typescript-eslint/visitor-keys" "8.35.0" - debug "^4.3.4" - fast-glob "^3.3.2" - is-glob "^4.0.3" - minimatch "^9.0.4" - semver "^7.6.0" - ts-api-utils "^2.1.0" - -"@typescript-eslint/utils@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.35.0.tgz#aaf0afab5ab51ea2f1897002907eacd9834606d5" - integrity sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg== - dependencies: - "@eslint-community/eslint-utils" "^4.7.0" - "@typescript-eslint/scope-manager" "8.35.0" - "@typescript-eslint/types" "8.35.0" - "@typescript-eslint/typescript-estree" "8.35.0" - -"@typescript-eslint/visitor-keys@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz#93e905e7f1e94d26a79771d1b1eb0024cb159dbf" - integrity sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g== - dependencies: - "@typescript-eslint/types" "8.35.0" - eslint-visitor-keys "^4.2.1" - -"@ungap/structured-clone@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" - integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== - -"@unrs/resolver-binding-darwin-arm64@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.8.1.tgz#4ebdbe47a4d8e45690f03482d7463b282683ded8" - integrity sha512-OKuBTQdOb4Kjbe+y4KgbRhn+nu47hNyNU2K3qjD+SA/bnQouvZnRzEiR85xZAIyZ6z1C+O1Zg1dK4hGH1RPdYA== - -"@unrs/resolver-binding-darwin-x64@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.8.1.tgz#2d36bee16e8dc8594a7ddbd04cc1e6c572bb1b68" - integrity sha512-inaphBsOqqzauNvx6kSHrgqDLShicPg3+fInBcEdD7Ut8sUUbm2z19LL+S9ccGpHnYoNiJ+Qrf7/B8hRsCUvBw== - -"@unrs/resolver-binding-freebsd-x64@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.8.1.tgz#cc546963b5eabd059587498f81cf69a6f75e89ec" - integrity sha512-LkGw7jDoLKEZO6yYwTKUlrboD6Qmy9Jkq7ZDPlJReq/FnCnNh0k1Z1hjtevpqPCMLz9hGW0ITMb04jdDZ796Cg== - -"@unrs/resolver-binding-linux-arm-gnueabihf@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.8.1.tgz#7135d3df1faa37b33923c8ee20314b6cef267e7f" - integrity sha512-6vhu22scv64dynXTVmeClenn3OPI8cwdhtydLFDkoW4UJzNwcgJ5mVtzbtikDGM9PmIQa+ekpH6tdvKt0ToK3A== - -"@unrs/resolver-binding-linux-arm-musleabihf@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.8.1.tgz#0ae5128e38d8df8ad685867b4de4d8df9a4fbf35" - integrity sha512-SrQ286JVFWlnZSm1/TJwulTgJVOdb1x8BWW2ecOK0Sx+acdRpoMf4WSxH+/+R4LyE/YYyekcEtUrPhSEgJ748g== - -"@unrs/resolver-binding-linux-arm64-gnu@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.8.1.tgz#139d34a03f4232836e761f2aa28751fd8f86fa0e" - integrity sha512-I2s4L27V+2kAee43x/qAkFjTZJgmDvSd9vtnyINOdBEdz5+QqiG6ccd5pgOw06MsUwygkrhB4jOe4ZN4SA6IwA== - -"@unrs/resolver-binding-linux-arm64-musl@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.8.1.tgz#b095fcb567f00c6df88ff334e0c1cba3ea12ec44" - integrity sha512-Drq80e/EQbdSVyJpheF65qVmfYy8OaDdQqoWV+09tZHz/P1SdSulvVtgtYrk216D++9hbx3c1bwVXwR5PZ2TzA== - -"@unrs/resolver-binding-linux-ppc64-gnu@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.8.1.tgz#3fde0589f276be5e21d7b90fe264448839afa2b8" - integrity sha512-EninHQHw8Zkq8K5qB6KWNDqjCtUzTDsCRQ6LzAtQWIxic/VQxR5Kl36V/GCXNvQaR7W0AB5gvJLyQtJwkf+AJA== - -"@unrs/resolver-binding-linux-riscv64-gnu@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.8.1.tgz#ad21df9d44960e751cadf10a915eb190044be433" - integrity sha512-s7Xu5PS4vWhsb5ZFAi+UBguTn0g8qDhN+BbB1t9APX23AdAI7TS4DRrJV5dBVdQ6a8MiergGr1Cjb0Q1V/sW8w== - -"@unrs/resolver-binding-linux-riscv64-musl@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.8.1.tgz#b38d5c9fad291b542e45baccd9d43849f4dc0733" - integrity sha512-Ca+bVzOJtgQ3OrMkRSeDLYWJIjRmEylDHSZuSKqqPmZI2vgX6yZgzrKY28I6hjjG9idlW4DcJzLv/TjFXev+4Q== - -"@unrs/resolver-binding-linux-s390x-gnu@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.8.1.tgz#b77d80b7dea1e34d833b21d9579fd4956061d5c5" - integrity sha512-ut1vBBFs6AC5EcerH8HorcmS/9wAy6iI1tfpzT7jy+SKnMgmPth/psc3W5V04njble7cyLPjFHwYJTlxmozQ/g== - -"@unrs/resolver-binding-linux-x64-gnu@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.8.1.tgz#a2371b20d7ae7f482d247f2f45699ea314a4ceeb" - integrity sha512-w5agLxesvrYKrCOlAsUkwRDogjnyRBi4/vEaujZRkXbeRCupJ9dFD0qUhLXZyIed+GSzJJIsJocUZIVzcTHYXQ== - -"@unrs/resolver-binding-linux-x64-musl@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.8.1.tgz#45f2f58ad4fc103f7feea0899e638021d5bf2c57" - integrity sha512-vk5htmWYCLRpfjn2wmCUne6pLvlcYUFDAAut4g02/2iWeGeZO/3GmSLmiZ9fcn9oH0FUzgetg0/zSo8oZ7liIg== - -"@unrs/resolver-binding-wasm32-wasi@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.8.1.tgz#d57ea7275464328403fc103347db1fa4900f220e" - integrity sha512-RcsLTcrqDT5XW/TnhhIeM7lVLgUv/gvPEC4WaH+OhkLCkRfH6EEuhprwrcp1WhdlrtL/U5FkHh4NtFLnMXoeXA== - dependencies: - "@napi-rs/wasm-runtime" "^0.2.11" - -"@unrs/resolver-binding-win32-arm64-msvc@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.8.1.tgz#41eeb4731c22e74d87be0628df1eb79298ed663b" - integrity sha512-XbSRLZY/gEi5weYv/aCkiUiSWvrNKkvec3m6/bDypDI+ZACwMllPH7smeOW/fdnIGhf9YtPATNliJHAS2GyMUA== - -"@unrs/resolver-binding-win32-ia32-msvc@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.8.1.tgz#399763affd06fb409f6d22f1e4d26e9cb3ac8982" - integrity sha512-SbCJMKOmqOsIBCklT5c+t0DjVbOkseE7ZN0OtMxRnraLKdj1AAv7d3cjJMYkPd9ZGKosHoMXo66gBs02YM8KeA== - -"@unrs/resolver-binding-win32-x64-msvc@1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.8.1.tgz#91e3322e735382cbe5611d1467fd95411cb58141" - integrity sha512-DdHqo7XbeUa/ZOcxq+q5iuO4sSxhwX9HR1JPL0JMOKEzgkIO4OKF2TPjqmo6UCCGZUXIMwrAycFXj/40sICagw== - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.14.0, acorn@^8.15.0: - version "8.15.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" - integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== - -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-escapes@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" - integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -ansis@^4.0.0, ansis@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansis/-/ansis-4.1.0.tgz#cd43ecd3f814f37223e518291c0e0b04f2915a0d" - integrity sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w== - -anymatch@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -ast-kit@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ast-kit/-/ast-kit-2.1.0.tgz#4544a2511f9300c74179ced89251bfdcb47e6d79" - integrity sha512-ROM2LlXbZBZVk97crfw8PGDOBzzsJvN2uJCmwswvPUNyfH14eg90mSN3xNqsri1JS1G9cz0VzeDUhxJkTrr4Ew== - dependencies: - "@babel/parser" "^7.27.3" - pathe "^2.0.3" - -async@^3.2.3: - version "3.2.6" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - -babel-jest@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-30.0.2.tgz#f627dc5afc3bd5795fc84735b4f1d74f9d4b8e91" - integrity sha512-A5kqR1/EUTidM2YC2YMEUDP2+19ppgOwK0IAd9Swc3q2KqFb5f9PtRUXVeZcngu0z5mDMyZ9zH2huJZSOMLiTQ== - dependencies: - "@jest/transform" "30.0.2" - "@types/babel__core" "^7.20.5" - babel-plugin-istanbul "^7.0.0" - babel-preset-jest "30.0.1" - chalk "^4.1.2" - graceful-fs "^4.2.11" - slash "^3.0.0" - -babel-plugin-istanbul@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz#629a178f63b83dc9ecee46fd20266283b1f11280" - integrity sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.3" - istanbul-lib-instrument "^6.0.2" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@30.0.1: - version "30.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz#f271b2066d2c1fb26a863adb8e13f85b06247125" - integrity sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ== - dependencies: - "@babel/template" "^7.27.2" - "@babel/types" "^7.27.3" - "@types/babel__core" "^7.20.5" - -babel-preset-current-node-syntax@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz#9a929eafece419612ef4ae4f60b1862ebad8ef30" - integrity sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-import-attributes" "^7.24.7" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - -babel-preset-jest@30.0.1: - version "30.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz#7d28db9531bce264e846c8483d54236244b8ae88" - integrity sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw== - dependencies: - babel-plugin-jest-hoist "30.0.1" - babel-preset-current-node-syntax "^1.1.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -birpc@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/birpc/-/birpc-2.3.0.tgz#e5a402dc785ef952a2383ef3cfc075e0842f3e8c" - integrity sha512-ijbtkn/F3Pvzb6jHypHRyve2QApOCZDR25D/VnkY2G/lBNcXCTsnsCxgY4k4PkVB7zfwzYbY3O9Lcqe3xufS5g== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browserslist@^4.22.2: - version "4.23.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96" - integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw== - dependencies: - caniuse-lite "^1.0.30001629" - electron-to-chromium "^1.4.796" - node-releases "^2.0.14" - update-browserslist-db "^1.0.16" - -browserslist@^4.24.0: - version "4.25.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.0.tgz#986aa9c6d87916885da2b50d8eb577ac8d133b2c" - integrity sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA== - dependencies: - caniuse-lite "^1.0.30001718" - electron-to-chromium "^1.5.160" - node-releases "^2.0.19" - update-browserslist-db "^1.1.3" - -bs-logger@^0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -cac@^6.7.14: - version "6.7.14" - resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" - integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== - -callsites@^3.0.0, callsites@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-lite@^1.0.30001629: - version "1.0.30001632" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001632.tgz#964207b7cba5851701afb4c8afaf1448db3884b6" - integrity sha512-udx3o7yHJfUxMLkGohMlVHCvFvWmirKh9JAH/d7WOLPetlH+LTL5cocMZ0t7oZx/mdlOWXti97xLZWc8uURRHg== - -caniuse-lite@^1.0.30001718: - version "1.0.30001722" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz#ec25a2b3085b25b9079b623db83c22a70882ce85" - integrity sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -chokidar@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" - integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== - dependencies: - readdirp "^4.0.1" - -ci-info@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.2.0.tgz#cbd21386152ebfe1d56f280a3b5feccbd96764c7" - integrity sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg== - -cjs-module-lexer@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz#586e87d4341cb2661850ece5190232ccdebcff8b" - integrity sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== - -collect-v8-coverage@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -cross-spawn@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" - integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -date-fns@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14" - integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg== - -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - -debug@^4.3.2, debug@^4.3.4, debug@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" - integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== - dependencies: - ms "^2.1.3" - -dedent@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.6.0.tgz#79d52d6389b1ffa67d2bcef59ba51847a9d503b2" - integrity sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deepmerge@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -defu@^6.1.4: - version "6.1.4" - resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" - integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== - -detect-newline@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -diff@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-8.0.2.tgz#712156a6dd288e66ebb986864e190c2fc9eddfae" - integrity sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg== - -dts-resolver@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/dts-resolver/-/dts-resolver-2.1.1.tgz#313adeda96d66492e9e24a0c5ac820ab4f11878e" - integrity sha512-3BiGFhB6mj5Kv+W2vdJseQUYW+SKVzAFJL6YNP6ursbrwy1fXHRotfHi3xLNxe4wZl/K8qbAFeCDjZLjzqxxRw== - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -ejs@^3.1.10: - version "3.1.10" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" - integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== - dependencies: - jake "^10.8.5" - -electron-to-chromium@^1.4.796: - version "1.4.799" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.799.tgz#271c56654ab4dc703037e47a5af4fc8945160611" - integrity sha512-3D3DwWkRTzrdEpntY0hMLYwj7SeBk1138CkPE8sBDSj3WzrzOiG2rHm3luw8jucpf+WiyLBCZyU9lMHyQI9M9Q== - -electron-to-chromium@^1.5.160: - version "1.5.166" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.166.tgz#3fff386ed473cc2169dbe2d3ace9592262601114" - integrity sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -empathic@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/empathic/-/empathic-1.1.0.tgz#a0de7dcaab07695bcab54117116d44c92b89e79f" - integrity sha512-rsPft6CK3eHtrlp9Y5ALBb+hfK+DWnA4WFebbazxjWyx8vSm3rZeoM3z9irsjcqO3PYRzlfv27XIB4tz2DV7RA== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -escalade@^3.1.1, escalade@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== - -escalade@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" - integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint-visitor-keys@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" - integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== - -eslint-visitor-keys@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" - integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== - -eslint@^9.29.0: - version "9.29.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.29.0.tgz#65e3db3b7e5a5b04a8af541741a0f3648d0a81a6" - integrity sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.20.1" - "@eslint/config-helpers" "^0.2.1" - "@eslint/core" "^0.14.0" - "@eslint/eslintrc" "^3.3.1" - "@eslint/js" "9.29.0" - "@eslint/plugin-kit" "^0.3.1" - "@humanfs/node" "^0.16.6" - "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.4.2" - "@types/estree" "^1.0.6" - "@types/json-schema" "^7.0.15" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.6" - debug "^4.3.2" - escape-string-regexp "^4.0.0" - eslint-scope "^8.4.0" - eslint-visitor-keys "^4.2.1" - espree "^10.4.0" - esquery "^1.5.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^8.0.0" - find-up "^5.0.0" - glob-parent "^6.0.2" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - json-stable-stringify-without-jsonify "^1.0.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - -espree@^10.0.1: - version "10.3.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" - integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== - dependencies: - acorn "^8.14.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^4.2.0" - -espree@^10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" - integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== - dependencies: - acorn "^8.15.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^4.2.1" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" - integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -execa@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exit-x@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/exit-x/-/exit-x-0.2.2.tgz#1f9052de3b8d99a696b10dad5bced9bdd5c3aa64" - integrity sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ== - -expect@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/expect/-/expect-30.0.2.tgz#d073942c19d54cb7bc42c9b2a434d850433a7def" - integrity sha512-YN9Mgv2mtTWXVmifQq3QT+ixCL/uLuLJw+fdp8MOjKqu8K3XQh3o5aulMM1tn+O2DdrWNxLZTeJsCY/VofUA0A== - dependencies: - "@jest/expect-utils" "30.0.2" - "@jest/get-type" "30.0.1" - jest-matcher-utils "30.0.2" - jest-message-util "30.0.2" - jest-mock "30.0.2" - jest-util "30.0.2" - -expect@^30.0.0: - version "30.0.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-30.0.0.tgz#460dfda282e0a8de8302aabee951dba7e79a5a53" - integrity sha512-xCdPp6gwiR9q9lsPCHANarIkFTN/IMZso6Kkq03sOm9IIGtzK/UJqml0dkhHibGh8HKOj8BIDIpZ0BZuU7QK6w== - dependencies: - "@jest/expect-utils" "30.0.0" - "@jest/get-type" "30.0.0" - jest-matcher-utils "30.0.0" - jest-message-util "30.0.0" - jest-mock "30.0.0" - jest-util "30.0.0" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" - integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.8" - -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.19.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" - integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== - dependencies: - reusify "^1.0.4" - -fb-watchman@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - -fdir@^6.4.4: - version "6.4.5" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.5.tgz#328e280f3a23699362f95f2e82acf978a0c0cb49" - integrity sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw== - -file-entry-cache@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" - integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== - dependencies: - flat-cache "^4.0.0" - -filelist@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" - integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== - dependencies: - minimatch "^5.0.1" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" - integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.4" - -flatted@^3.2.9: - version "3.3.3" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" - integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== - -foreground-child@^3.1.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" - integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== - dependencies: - cross-spawn "^7.0.6" - signal-exit "^4.0.1" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-tsconfig@^4.10.1: - version "4.10.1" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.1.tgz#d34c1c01f47d65a606c37aa7a177bc3e56ab4b2e" - integrity sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ== - dependencies: - resolve-pkg-maps "^1.0.0" - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@^10.3.10: - version "10.4.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" - integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - package-json-from-dist "^1.0.0" - path-scurry "^1.11.1" - -glob@^7.1.4: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" - integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== - -graceful-fs@^4.2.11: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -hookable@^5.5.3: - version "5.5.3" - resolved "https://registry.yarnpkg.com/hookable/-/hookable-5.5.3.tgz#6cfc358984a1ef991e2518cb9ed4a778bbd3215d" - integrity sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ== - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -ignore@^5.2.0: - version "5.3.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" - integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== - -ignore@^7.0.0: - version "7.0.5" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" - integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== - -import-fresh@^3.2.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" - integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" - integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" - integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== - -istanbul-lib-instrument@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz#91655936cf7380e4e473383081e38478b69993b1" - integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== - dependencies: - "@babel/core" "^7.23.9" - "@babel/parser" "^7.23.9" - "@istanbuljs/schema" "^0.1.3" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - -istanbul-lib-instrument@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" - integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== - dependencies: - "@babel/core" "^7.23.9" - "@babel/parser" "^7.23.9" - "@istanbuljs/schema" "^0.1.3" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - -istanbul-lib-report@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^4.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^5.0.0: - version "5.0.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" - integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== - dependencies: - "@jridgewell/trace-mapping" "^0.3.23" - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - -istanbul-reports@^3.1.3: - version "3.1.7" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" - integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -jackspeak@^3.1.2: - version "3.4.3" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" - integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jake@^10.8.5: - version "10.9.2" - resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" - integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA== - dependencies: - async "^3.2.3" - chalk "^4.0.2" - filelist "^1.0.4" - minimatch "^3.1.2" - -jest-changed-files@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-30.0.2.tgz#2c275263037f8f291b71cbb0a4f639c519ab7eb8" - integrity sha512-Ius/iRST9FKfJI+I+kpiDh8JuUlAISnRszF9ixZDIqJF17FckH5sOzKC8a0wd0+D+8em5ADRHA5V5MnfeDk2WA== - dependencies: - execa "^5.1.1" - jest-util "30.0.2" - p-limit "^3.1.0" - -jest-circus@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-30.0.2.tgz#a00a408d5d32d2b547f20f9e84a487d236ed8ee1" - integrity sha512-NRozwx4DaFHcCUtwdEd/0jBLL1imyMrCbla3vF//wdsB2g6jIicMbjx9VhqE/BYU4dwsOQld+06ODX0oZ9xOLg== - dependencies: - "@jest/environment" "30.0.2" - "@jest/expect" "30.0.2" - "@jest/test-result" "30.0.2" - "@jest/types" "30.0.1" - "@types/node" "*" - chalk "^4.1.2" - co "^4.6.0" - dedent "^1.6.0" - is-generator-fn "^2.1.0" - jest-each "30.0.2" - jest-matcher-utils "30.0.2" - jest-message-util "30.0.2" - jest-runtime "30.0.2" - jest-snapshot "30.0.2" - jest-util "30.0.2" - p-limit "^3.1.0" - pretty-format "30.0.2" - pure-rand "^7.0.0" - slash "^3.0.0" - stack-utils "^2.0.6" - -jest-cli@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-30.0.2.tgz#cf8ad8a1157721c3a1dc3a371565f6b7f5e6b549" - integrity sha512-yQ6Qz747oUbMYLNAqOlEby+hwXx7WEJtCl0iolBRpJhr2uvkBgiVMrvuKirBc8utwQBnkETFlDUkYifbRpmBrQ== - dependencies: - "@jest/core" "30.0.2" - "@jest/test-result" "30.0.2" - "@jest/types" "30.0.1" - chalk "^4.1.2" - exit-x "^0.2.2" - import-local "^3.2.0" - jest-config "30.0.2" - jest-util "30.0.2" - jest-validate "30.0.2" - yargs "^17.7.2" - -jest-config@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-30.0.2.tgz#a4884ba3b4d31fb0599b0b78e7a0204efb126f9d" - integrity sha512-vo0fVq+uzDcXETFVnCUyr5HaUCM8ES6DEuS9AFpma34BVXMRRNlsqDyiW5RDHaEFoeFlJHoI4Xjh/WSYIAL58g== - dependencies: - "@babel/core" "^7.27.4" - "@jest/get-type" "30.0.1" - "@jest/pattern" "30.0.1" - "@jest/test-sequencer" "30.0.2" - "@jest/types" "30.0.1" - babel-jest "30.0.2" - chalk "^4.1.2" - ci-info "^4.2.0" - deepmerge "^4.3.1" - glob "^10.3.10" - graceful-fs "^4.2.11" - jest-circus "30.0.2" - jest-docblock "30.0.1" - jest-environment-node "30.0.2" - jest-regex-util "30.0.1" - jest-resolve "30.0.2" - jest-runner "30.0.2" - jest-util "30.0.2" - jest-validate "30.0.2" - micromatch "^4.0.8" - parse-json "^5.2.0" - pretty-format "30.0.2" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@30.0.0: - version "30.0.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-30.0.0.tgz#d3d4f75e257e3c2cb8729438fe9cec66098f6176" - integrity sha512-TgT1+KipV8JTLXXeFX0qSvIJR/UXiNNojjxb/awh3vYlBZyChU/NEmyKmq+wijKjWEztyrGJFL790nqMqNjTHA== - dependencies: - "@jest/diff-sequences" "30.0.0" - "@jest/get-type" "30.0.0" - chalk "^4.1.2" - pretty-format "30.0.0" - -jest-diff@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-30.0.2.tgz#db77e7ca48a964337c0a4259d5e389c0bb124d7e" - integrity sha512-2UjrNvDJDn/oHFpPrUTVmvYYDNeNtw2DlY3er8bI6vJJb9Fb35ycp/jFLd5RdV59tJ8ekVXX3o/nwPcscgXZJQ== - dependencies: - "@jest/diff-sequences" "30.0.1" - "@jest/get-type" "30.0.1" - chalk "^4.1.2" - pretty-format "30.0.2" - -jest-docblock@30.0.1: - version "30.0.1" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-30.0.1.tgz#545ff59f2fa88996bd470dba7d3798a8421180b1" - integrity sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA== - dependencies: - detect-newline "^3.1.0" - -jest-each@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-30.0.2.tgz#402e189784715f5c76f1bb97c29842e79abe99a1" - integrity sha512-ZFRsTpe5FUWFQ9cWTMguCaiA6kkW5whccPy9JjD1ezxh+mJeqmz8naL8Fl/oSbNJv3rgB0x87WBIkA5CObIUZQ== - dependencies: - "@jest/get-type" "30.0.1" - "@jest/types" "30.0.1" - chalk "^4.1.2" - jest-util "30.0.2" - pretty-format "30.0.2" - -jest-environment-node@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-30.0.2.tgz#3c24d6becb505f344f52cddb15ea506cf3288543" - integrity sha512-XsGtZ0H+a70RsxAQkKuIh0D3ZlASXdZdhpOSBq9WRPq6lhe0IoQHGW0w9ZUaPiZQ/CpkIdprvlfV1QcXcvIQLQ== - dependencies: - "@jest/environment" "30.0.2" - "@jest/fake-timers" "30.0.2" - "@jest/types" "30.0.1" - "@types/node" "*" - jest-mock "30.0.2" - jest-util "30.0.2" - jest-validate "30.0.2" - -jest-haste-map@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-30.0.2.tgz#83826e7e352fa139dc95100337aff4de58c99453" - integrity sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ== - dependencies: - "@jest/types" "30.0.1" - "@types/node" "*" - anymatch "^3.1.3" - fb-watchman "^2.0.2" - graceful-fs "^4.2.11" - jest-regex-util "30.0.1" - jest-util "30.0.2" - jest-worker "30.0.2" - micromatch "^4.0.8" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.3" - -jest-leak-detector@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-30.0.2.tgz#da4df660615d170136d2b468af3bf1c9bff0137e" - integrity sha512-U66sRrAYdALq+2qtKffBLDWsQ/XoNNs2Lcr83sc9lvE/hEpNafJlq2lXCPUBMNqamMECNxSIekLfe69qg4KMIQ== - dependencies: - "@jest/get-type" "30.0.1" - pretty-format "30.0.2" - -jest-matcher-utils@30.0.0: - version "30.0.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-30.0.0.tgz#f72a65e248c0462795f7e14386682bfee6ad4386" - integrity sha512-m5mrunqopkrqwG1mMdJxe1J4uGmS9AHHKYUmoxeQOxBcLjEvirIrIDwuKmUYrecPHVB/PUBpXs2gPoeA2FSSLQ== - dependencies: - "@jest/get-type" "30.0.0" - chalk "^4.1.2" - jest-diff "30.0.0" - pretty-format "30.0.0" - -jest-matcher-utils@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-30.0.2.tgz#2dbb5f9aacfdd9c013fa72ed6132ca4e1b41f8db" - integrity sha512-1FKwgJYECR8IT93KMKmjKHSLyru0DqguThov/aWpFccC0wbiXGOxYEu7SScderBD7ruDOpl7lc5NG6w3oxKfaA== - dependencies: - "@jest/get-type" "30.0.1" - chalk "^4.1.2" - jest-diff "30.0.2" - pretty-format "30.0.2" - -jest-message-util@30.0.0: - version "30.0.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-30.0.0.tgz#b115d408cd877a6e3e711485a3bd240c7a27503c" - integrity sha512-pV3qcrb4utEsa/U7UI2VayNzSDQcmCllBZLSoIucrESRu0geKThFZOjjh0kACDJFJRAQwsK7GVsmS6SpEceD8w== - dependencies: - "@babel/code-frame" "^7.27.1" - "@jest/types" "30.0.0" - "@types/stack-utils" "^2.0.3" - chalk "^4.1.2" - graceful-fs "^4.2.11" - micromatch "^4.0.8" - pretty-format "30.0.0" - slash "^3.0.0" - stack-utils "^2.0.6" - -jest-message-util@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-30.0.2.tgz#9dfdc37570d172f0ffdc42a0318036ff4008837f" - integrity sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw== - dependencies: - "@babel/code-frame" "^7.27.1" - "@jest/types" "30.0.1" - "@types/stack-utils" "^2.0.3" - chalk "^4.1.2" - graceful-fs "^4.2.11" - micromatch "^4.0.8" - pretty-format "30.0.2" - slash "^3.0.0" - stack-utils "^2.0.6" - -jest-mock@30.0.0: - version "30.0.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-30.0.0.tgz#f3b3115cd80c3eec7df93809430ab1feaeeb7229" - integrity sha512-W2sRA4ALXILrEetEOh2ooZG6fZ01iwVs0OWMKSSWRcUlaLr4ESHuiKXDNTg+ZVgOq8Ei5445i/Yxrv59VT+XkA== - dependencies: - "@jest/types" "30.0.0" - "@types/node" "*" - jest-util "30.0.0" - -jest-mock@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-30.0.2.tgz#5e4245f25f6f9532714906cab10a2b9e39eb2183" - integrity sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA== - dependencies: - "@jest/types" "30.0.1" - "@types/node" "*" - jest-util "30.0.2" - -jest-pnp-resolver@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" - integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== - -jest-regex-util@30.0.0: - version "30.0.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-30.0.0.tgz#031f385ebb947e770e409ede703d200b3405413e" - integrity sha512-rT84010qRu/5OOU7a9TeidC2Tp3Qgt9Sty4pOZ/VSDuEmRupIjKZAb53gU3jr4ooMlhwScrgC9UixJxWzVu9oQ== - -jest-regex-util@30.0.1: - version "30.0.1" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-30.0.1.tgz#f17c1de3958b67dfe485354f5a10093298f2a49b" - integrity sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA== - -jest-resolve-dependencies@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.2.tgz#0c5da8dc5f791f3de10c1d5df294503cd612e5a6" - integrity sha512-Lp1iIXpsF5fGM4vyP8xHiIy2H5L5yO67/nXoYJzH4kz+fQmO+ZMKxzYLyWxYy4EeCLeNQ6a9OozL+uHZV2iuEA== - dependencies: - jest-regex-util "30.0.1" - jest-snapshot "30.0.2" - -jest-resolve@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-30.0.2.tgz#4b7c826a35e9657189568e4dafc0ba5f05868cf2" - integrity sha512-q/XT0XQvRemykZsvRopbG6FQUT6/ra+XV6rPijyjT6D0msOyCvR2A5PlWZLd+fH0U8XWKZfDiAgrUNDNX2BkCw== - dependencies: - chalk "^4.1.2" - graceful-fs "^4.2.11" - jest-haste-map "30.0.2" - jest-pnp-resolver "^1.2.3" - jest-util "30.0.2" - jest-validate "30.0.2" - slash "^3.0.0" - unrs-resolver "^1.7.11" - -jest-runner@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-30.0.2.tgz#28022ea290e2759864ae97cb5307bcae98e68f2d" - integrity sha512-6H+CIFiDLVt1Ix6jLzASXz3IoIiDukpEIxL9FHtDQ2BD/k5eFtDF5e5N9uItzRE3V1kp7VoSRyrGBytXKra4xA== - dependencies: - "@jest/console" "30.0.2" - "@jest/environment" "30.0.2" - "@jest/test-result" "30.0.2" - "@jest/transform" "30.0.2" - "@jest/types" "30.0.1" - "@types/node" "*" - chalk "^4.1.2" - emittery "^0.13.1" - exit-x "^0.2.2" - graceful-fs "^4.2.11" - jest-docblock "30.0.1" - jest-environment-node "30.0.2" - jest-haste-map "30.0.2" - jest-leak-detector "30.0.2" - jest-message-util "30.0.2" - jest-resolve "30.0.2" - jest-runtime "30.0.2" - jest-util "30.0.2" - jest-watcher "30.0.2" - jest-worker "30.0.2" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-30.0.2.tgz#db5b4723ebdb8c2158779c055976cb6cc22ce1df" - integrity sha512-H1a51/soNOeAjoggu6PZKTH7DFt8JEGN4mesTSwyqD2jU9PXD04Bp6DKbt2YVtQvh2JcvH2vjbkEerCZ3lRn7A== - dependencies: - "@jest/environment" "30.0.2" - "@jest/fake-timers" "30.0.2" - "@jest/globals" "30.0.2" - "@jest/source-map" "30.0.1" - "@jest/test-result" "30.0.2" - "@jest/transform" "30.0.2" - "@jest/types" "30.0.1" - "@types/node" "*" - chalk "^4.1.2" - cjs-module-lexer "^2.1.0" - collect-v8-coverage "^1.0.2" - glob "^10.3.10" - graceful-fs "^4.2.11" - jest-haste-map "30.0.2" - jest-message-util "30.0.2" - jest-mock "30.0.2" - jest-regex-util "30.0.1" - jest-resolve "30.0.2" - jest-snapshot "30.0.2" - jest-util "30.0.2" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-30.0.2.tgz#0f9f2c59c2070874a2db96d30c8543dfef657701" - integrity sha512-KeoHikoKGln3OlN7NS7raJ244nIVr2K46fBTNdfuxqYv2/g4TVyWDSO4fmk08YBJQMjs3HNfG1rlLfL/KA+nUw== - dependencies: - "@babel/core" "^7.27.4" - "@babel/generator" "^7.27.5" - "@babel/plugin-syntax-jsx" "^7.27.1" - "@babel/plugin-syntax-typescript" "^7.27.1" - "@babel/types" "^7.27.3" - "@jest/expect-utils" "30.0.2" - "@jest/get-type" "30.0.1" - "@jest/snapshot-utils" "30.0.1" - "@jest/transform" "30.0.2" - "@jest/types" "30.0.1" - babel-preset-current-node-syntax "^1.1.0" - chalk "^4.1.2" - expect "30.0.2" - graceful-fs "^4.2.11" - jest-diff "30.0.2" - jest-matcher-utils "30.0.2" - jest-message-util "30.0.2" - jest-util "30.0.2" - pretty-format "30.0.2" - semver "^7.7.2" - synckit "^0.11.8" - -jest-util@30.0.0: - version "30.0.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-30.0.0.tgz#d4f20f59e1fd72c7143143f4aa961bb71aeddad0" - integrity sha512-fhNBBM9uSUbd4Lzsf8l/kcAdaHD/4SgoI48en3HXcBEMwKwoleKFMZ6cYEYs21SB779PRuRCyNLmymApAm8tZw== - dependencies: - "@jest/types" "30.0.0" - "@types/node" "*" - chalk "^4.1.2" - ci-info "^4.2.0" - graceful-fs "^4.2.11" - picomatch "^4.0.2" - -jest-util@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-30.0.2.tgz#1bd8411f81e6f5e2ca8b31bb2534ebcd7cbac065" - integrity sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg== - dependencies: - "@jest/types" "30.0.1" - "@types/node" "*" - chalk "^4.1.2" - ci-info "^4.2.0" - graceful-fs "^4.2.11" - picomatch "^4.0.2" - -jest-validate@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-30.0.2.tgz#f62a2f0e014dac94747509ba8c2bcd5d48215b7f" - integrity sha512-noOvul+SFER4RIvNAwGn6nmV2fXqBq67j+hKGHKGFCmK4ks/Iy1FSrqQNBLGKlu4ZZIRL6Kg1U72N1nxuRCrGQ== - dependencies: - "@jest/get-type" "30.0.1" - "@jest/types" "30.0.1" - camelcase "^6.3.0" - chalk "^4.1.2" - leven "^3.1.0" - pretty-format "30.0.2" - -jest-watcher@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-30.0.2.tgz#ec93ed25183679f549a47f6197267d50ec83ea51" - integrity sha512-vYO5+E7jJuF+XmONr6CrbXdlYrgvZqtkn6pdkgjt/dU64UAdc0v1cAVaAeWtAfUUMScxNmnUjKPUMdCpNVASwg== - dependencies: - "@jest/test-result" "30.0.2" - "@jest/types" "30.0.1" - "@types/node" "*" - ansi-escapes "^4.3.2" - chalk "^4.1.2" - emittery "^0.13.1" - jest-util "30.0.2" - string-length "^4.0.2" - -jest-worker@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-30.0.2.tgz#e67bd7debbc9d8445907a17067a89359acedc8c5" - integrity sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg== - dependencies: - "@types/node" "*" - "@ungap/structured-clone" "^1.3.0" - jest-util "30.0.2" - merge-stream "^2.0.0" - supports-color "^8.1.1" - -jest@^30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest/-/jest-30.0.2.tgz#0b3af654548d706bdde6f1bba93099ec343b8772" - integrity sha512-HlSEiHRcmTuGwNyeawLTEzpQUMFn+f741FfoNg7RXG2h0WLJKozVCpcQLT0GW17H6kNCqRwGf+Ii/I1YVNvEGQ== - dependencies: - "@jest/core" "30.0.2" - "@jest/types" "30.0.1" - import-local "^3.2.0" - jest-cli "30.0.2" - -jiti@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560" - integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" - integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -keyv@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lru-cache@^10.2.0: - version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" - integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -make-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== - dependencies: - semver "^7.5.3" - -make-error@^1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^9.0.4: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== - dependencies: - brace-expansion "^2.0.1" - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -napi-postinstall@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.2.4.tgz#419697d0288cb524623e422f919624f22a5e4028" - integrity sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -node-releases@^2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" - integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.9.3: - version "0.9.4" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" - integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.5" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2, p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-json-from-dist@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" - integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-scurry@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== - dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -pathe@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" - integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== - -picocolors@^1.0.0, picocolors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - -picocolors@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -picomatch@^2.0.4, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== - -pirates@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" - integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -pretty-format@30.0.0, pretty-format@^30.0.0: - version "30.0.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-30.0.0.tgz#a3137bed442af87eadea2c427a1b201189e590a4" - integrity sha512-18NAOUr4ZOQiIR+BgI5NhQE7uREdx4ZyV0dyay5izh4yfQ+1T7BSvggxvRGoXocrRyevqW5OhScUjbi9GB8R8Q== - dependencies: - "@jest/schemas" "30.0.0" - ansi-styles "^5.2.0" - react-is "^18.3.1" - -pretty-format@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-30.0.2.tgz#54717b6aa2b4357a2e6d83868e10a2ea8dd647c7" - integrity sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg== - dependencies: - "@jest/schemas" "30.0.1" - ansi-styles "^5.2.0" - react-is "^18.3.1" - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -pure-rand@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-7.0.1.tgz#6f53a5a9e3e4a47445822af96821ca509ed37566" - integrity sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ== - -quansync@^0.2.10, quansync@^0.2.8: - version "0.2.10" - resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.10.tgz#32053cf166fa36511aae95fc49796116f2dc20e1" - integrity sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -react-is@^18.3.1: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" - integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== - -readdirp@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" - integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -reusify@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" - integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== - -rolldown-plugin-dts@^0.13.11: - version "0.13.11" - resolved "https://registry.yarnpkg.com/rolldown-plugin-dts/-/rolldown-plugin-dts-0.13.11.tgz#25ca436174c4723510d9e00f28815394ef6a089d" - integrity sha512-1TScN31JImk8xcq9kdm52z2W8/QX3zeDpEjFkyZmK+GcD0u8QqSWWARBsCEdfS99NyI6D9NIbUpsABXlcpZhig== - dependencies: - "@babel/generator" "^7.27.5" - "@babel/parser" "^7.27.5" - "@babel/types" "^7.27.6" - ast-kit "^2.1.0" - birpc "^2.3.0" - debug "^4.4.1" - dts-resolver "^2.1.1" - get-tsconfig "^4.10.1" - -rolldown@1.0.0-beta.15: - version "1.0.0-beta.15" - resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.0.0-beta.15.tgz#746566a3e434d40af5abfb080e8c6f02bfe90b17" - integrity sha512-ep788NsIGl0W5gT+99hBrSGe4Hdhcwc55PqM3O0mR5H0C4ZpGpDGgu9YzTJ8a6mFDLnFnc/LYC+Dszb7oWK/dg== - dependencies: - "@oxc-project/runtime" "=0.72.3" - "@oxc-project/types" "=0.72.3" - "@rolldown/pluginutils" "1.0.0-beta.15" - ansis "^4.0.0" - optionalDependencies: - "@rolldown/binding-darwin-arm64" "1.0.0-beta.15" - "@rolldown/binding-darwin-x64" "1.0.0-beta.15" - "@rolldown/binding-freebsd-x64" "1.0.0-beta.15" - "@rolldown/binding-linux-arm-gnueabihf" "1.0.0-beta.15" - "@rolldown/binding-linux-arm64-gnu" "1.0.0-beta.15" - "@rolldown/binding-linux-arm64-musl" "1.0.0-beta.15" - "@rolldown/binding-linux-x64-gnu" "1.0.0-beta.15" - "@rolldown/binding-linux-x64-musl" "1.0.0-beta.15" - "@rolldown/binding-wasm32-wasi" "1.0.0-beta.15" - "@rolldown/binding-win32-arm64-msvc" "1.0.0-beta.15" - "@rolldown/binding-win32-ia32-msvc" "1.0.0-beta.15" - "@rolldown/binding-win32-x64-msvc" "1.0.0-beta.15" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.3, semver@^7.5.4: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - -semver@^7.6.0, semver@^7.7.2: - version "7.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" - integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -stack-utils@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - -string-length@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -synckit@^0.11.8: - version "0.11.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" - integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== - dependencies: - "@pkgr/core" "^0.2.4" - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -tinyexec@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.0.1.tgz#70c31ab7abbb4aea0a24f55d120e5990bfa1e0b1" - integrity sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw== - -tinyglobby@^0.2.14: - version "0.2.14" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" - integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== - dependencies: - fdir "^6.4.4" - picomatch "^4.0.2" - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -ts-api-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" - integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== - -ts-jest@^29.4.0: - version "29.4.0" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.4.0.tgz#bef0ee98d94c83670af7462a1617bf2367a83740" - integrity sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q== - dependencies: - bs-logger "^0.2.6" - ejs "^3.1.10" - fast-json-stable-stringify "^2.1.0" - json5 "^2.2.3" - lodash.memoize "^4.1.2" - make-error "^1.3.6" - semver "^7.7.2" - type-fest "^4.41.0" - yargs-parser "^21.1.1" - -tsdown@^0.12.8: - version "0.12.8" - resolved "https://registry.yarnpkg.com/tsdown/-/tsdown-0.12.8.tgz#247c590b55e3bc0b2d776f2dc482e218c38d2fb5" - integrity sha512-niHeVcFCNjvVZYVGTeoM4BF+/DWxP8pFH2tUs71sEKYdcKtJIbkSdEmtxByaRZeMgwVbVgPb8nv9i9okVwFLAA== - dependencies: - ansis "^4.1.0" - cac "^6.7.14" - chokidar "^4.0.3" - debug "^4.4.1" - diff "^8.0.2" - empathic "^1.1.0" - hookable "^5.5.3" - rolldown "1.0.0-beta.15" - rolldown-plugin-dts "^0.13.11" - semver "^7.7.2" - tinyexec "^1.0.1" - tinyglobby "^0.2.14" - unconfig "^7.3.2" - -tslib@^2.4.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^4.41.0: - version "4.41.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" - integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== - -typescript-eslint@^8.35.0: - version "8.35.0" - resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.35.0.tgz#65afcdde973614b8f44fa89293919420ca9b904e" - integrity sha512-uEnz70b7kBz6eg/j0Czy6K5NivaYopgxRjsnAJ2Fx5oTLo3wefTHIbL7AkQr1+7tJCRVpTs/wiM8JR/11Loq9A== - dependencies: - "@typescript-eslint/eslint-plugin" "8.35.0" - "@typescript-eslint/parser" "8.35.0" - "@typescript-eslint/utils" "8.35.0" - -typescript@^5.8.3: - version "5.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" - integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== - -unconfig@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/unconfig/-/unconfig-7.3.2.tgz#170a34ee9b86cec5aaec953260d2da864218b998" - integrity sha512-nqG5NNL2wFVGZ0NA/aCFw0oJ2pxSf1lwg4Z5ill8wd7K4KX/rQbHlwbh+bjctXL5Ly1xtzHenHGOK0b+lG6JVg== - dependencies: - "@quansync/fs" "^0.1.1" - defu "^6.1.4" - jiti "^2.4.2" - quansync "^0.2.8" - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -unrs-resolver@^1.7.11: - version "1.8.1" - resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.8.1.tgz#f84ce4aee9ffc2d6eaad497178e0a996bc18433c" - integrity sha512-M5++xH5Tu/m3NNAc0+dBHidXfF6bTC08mfhQ3AB5UTonEzQSH9ASC/a7EbZN3WU5m0OWMTvf12GHVJZ3uUmPtA== - dependencies: - napi-postinstall "^0.2.2" - optionalDependencies: - "@unrs/resolver-binding-darwin-arm64" "1.8.1" - "@unrs/resolver-binding-darwin-x64" "1.8.1" - "@unrs/resolver-binding-freebsd-x64" "1.8.1" - "@unrs/resolver-binding-linux-arm-gnueabihf" "1.8.1" - "@unrs/resolver-binding-linux-arm-musleabihf" "1.8.1" - "@unrs/resolver-binding-linux-arm64-gnu" "1.8.1" - "@unrs/resolver-binding-linux-arm64-musl" "1.8.1" - "@unrs/resolver-binding-linux-ppc64-gnu" "1.8.1" - "@unrs/resolver-binding-linux-riscv64-gnu" "1.8.1" - "@unrs/resolver-binding-linux-riscv64-musl" "1.8.1" - "@unrs/resolver-binding-linux-s390x-gnu" "1.8.1" - "@unrs/resolver-binding-linux-x64-gnu" "1.8.1" - "@unrs/resolver-binding-linux-x64-musl" "1.8.1" - "@unrs/resolver-binding-wasm32-wasi" "1.8.1" - "@unrs/resolver-binding-win32-arm64-msvc" "1.8.1" - "@unrs/resolver-binding-win32-ia32-msvc" "1.8.1" - "@unrs/resolver-binding-win32-x64-msvc" "1.8.1" - -update-browserslist-db@^1.0.16: - version "1.0.16" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" - integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== - dependencies: - escalade "^3.1.2" - picocolors "^1.0.1" - -update-browserslist-db@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" - integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== - dependencies: - escalade "^3.2.0" - picocolors "^1.1.1" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -v8-to-istanbul@^9.0.1: - version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^2.0.0" - -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" - integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^4.0.1" - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.7.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 1111b3760125e2e6cd08830564ef74a10fe8d7cb Mon Sep 17 00:00:00 2001 From: phev8 Date: Fri, 18 Jul 2025 15:12:23 +0200 Subject: [PATCH 06/10] Remove unused `shuffleItems` and `responseConfig` properties from `ScgMcgChoiceResponseConfig` and `SingleChoiceQuestionItem` classes to streamline code and improve clarity. --- src/survey/components/survey-item-component.ts | 1 - src/survey/items/survey-item.ts | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/survey/components/survey-item-component.ts b/src/survey/components/survey-item-component.ts index f81b641..8f0808a 100644 --- a/src/survey/components/survey-item-component.ts +++ b/src/survey/components/survey-item-component.ts @@ -236,7 +236,6 @@ export abstract class ResponseConfigComponent extends ItemComponent { export class ScgMcgChoiceResponseConfig extends GroupComponent { componentType: ItemComponentType.SingleChoice = ItemComponentType.SingleChoice; items: Array; - declare shuffleItems?: boolean; constructor(compKey: string, parentFullKey: string | undefined = undefined, parentItemKey: string | undefined = undefined) { diff --git a/src/survey/items/survey-item.ts b/src/survey/items/survey-item.ts index 2f3ffa5..a2ff29a 100644 --- a/src/survey/items/survey-item.ts +++ b/src/survey/items/survey-item.ts @@ -511,7 +511,6 @@ abstract class ScgMcgQuestionItem extends QuestionItem { export class SingleChoiceQuestionItem extends ScgMcgQuestionItem { itemType: SurveyItemType.SingleChoiceQuestion = SurveyItemType.SingleChoiceQuestion; - declare responseConfig: ScgMcgChoiceResponseConfig; constructor(itemFullKey: string) { super(itemFullKey, SurveyItemType.SingleChoiceQuestion); @@ -527,7 +526,6 @@ export class SingleChoiceQuestionItem extends ScgMcgQuestionItem { export class MultipleChoiceQuestionItem extends ScgMcgQuestionItem { itemType: SurveyItemType.MultipleChoiceQuestion = SurveyItemType.MultipleChoiceQuestion; - declare responseConfig: ScgMcgChoiceResponseConfig; constructor(itemFullKey: string) { super(itemFullKey, SurveyItemType.MultipleChoiceQuestion); From f7562ff76e597cd3a8e2d5f131c0a67f1e1bc9d4 Mon Sep 17 00:00:00 2001 From: phev8 Date: Wed, 23 Jul 2025 09:43:18 +0200 Subject: [PATCH 07/10] Add ItemInitHelper and corresponding tests for unique key generation and group management - Introduced the `ItemInitHelper` class to facilitate the creation and management of survey items, including unique key generation for groups. - Implemented methods for adding groups with customizable shuffle options and ensuring unique keys among siblings. - Added comprehensive tests in `item-init-helper.test.ts` to validate key generation logic, group creation, and error handling scenarios. - Enhanced the `SurveyEditor` class to support new item management functionalities, improving overall survey editing capabilities. --- src/__tests__/item-init-helper.test.ts | 366 +++++++++++++++++++++++++ src/survey-editor/item-init-helper.ts | 96 +++++++ src/survey-editor/survey-editor.ts | 2 +- 3 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 src/__tests__/item-init-helper.test.ts create mode 100644 src/survey-editor/item-init-helper.ts diff --git a/src/__tests__/item-init-helper.test.ts b/src/__tests__/item-init-helper.test.ts new file mode 100644 index 0000000..2b88335 --- /dev/null +++ b/src/__tests__/item-init-helper.test.ts @@ -0,0 +1,366 @@ +import { Survey } from '../survey/survey'; +import { SurveyEditor } from '../survey-editor/survey-editor'; +import { ItemInitHelper } from '../survey-editor/item-init-helper'; +import { GroupItem, SingleChoiceQuestionItem, DisplayItem, SurveyItemType } from '../survey/items'; + +// Helper function to create a test survey with some existing items +const createTestSurvey = (surveyKey: string = 'test-survey'): Survey => { + const survey = new Survey(surveyKey); + + // Add a sub-group to the root + const subGroup = new GroupItem(`${surveyKey}.page1`); + survey.surveyItems[`${surveyKey}.page1`] = subGroup; + + // Add the sub-group to the root group's items + const rootGroup = survey.surveyItems[surveyKey] as GroupItem; + rootGroup.items = [`${surveyKey}.page1`]; + + return survey; +}; + +// Helper function to add items with known keys to test uniqueness +const addKnownItems = (survey: Survey, parentKey: string, itemKeys: string[]): void => { + itemKeys.forEach(key => { + const fullKey = `${parentKey}.${key}`; + const item = new DisplayItem(fullKey); + survey.surveyItems[fullKey] = item; + + // Add to parent's items array + const parentItem = survey.surveyItems[parentKey] as GroupItem; + if (!parentItem.items) { + parentItem.items = []; + } + parentItem.items.push(fullKey); + }); +}; + +describe('ItemInitHelper', () => { + let survey: Survey; + let editor: SurveyEditor; + let initAndAdd: ItemInitHelper; + + beforeEach(() => { + survey = createTestSurvey(); + editor = new SurveyEditor(survey); + initAndAdd = new ItemInitHelper(editor); + }); + + describe('generateUniqueKey', () => { + it('should generate a 3-character key by default', () => { + const key = (initAndAdd as any).generateUniqueKey('test-survey.page1'); + + expect(typeof key).toBe('string'); + expect(key).toHaveLength(3); + expect(key).toMatch(/^[a-zA-Z0-9]{3}$/); + }); + + it('should generate a key of specified length', () => { + const key5 = (initAndAdd as any).generateUniqueKey('test-survey.page1', 5); + const key1 = (initAndAdd as any).generateUniqueKey('test-survey.page1', 1); + const key10 = (initAndAdd as any).generateUniqueKey('test-survey.page1', 10); + + expect(key5).toHaveLength(5); + expect(key1).toHaveLength(1); + expect(key10).toHaveLength(10); + + expect(key5).toMatch(/^[a-zA-Z0-9]{5}$/); + expect(key1).toMatch(/^[a-zA-Z0-9]{1}$/); + expect(key10).toMatch(/^[a-zA-Z0-9]{10}$/); + }); + + it('should generate unique keys when siblings exist', () => { + // Add some existing items with known keys + addKnownItems(survey, 'test-survey.page1', ['abc', 'def', 'xyz']); + + const generatedKeys = new Set(); + + // Generate multiple keys and ensure they're all unique and different from existing ones + for (let i = 0; i < 10; i++) { + const key = (initAndAdd as any).generateUniqueKey('test-survey.page1'); + + expect(key).not.toBe('abc'); + expect(key).not.toBe('def'); + expect(key).not.toBe('xyz'); + expect(generatedKeys.has(key)).toBe(false); + + generatedKeys.add(key); + } + + expect(generatedKeys.size).toBe(10); + }); + + it('should handle empty parent (no existing siblings)', () => { + const key = (initAndAdd as any).generateUniqueKey('test-survey.page1'); + + expect(typeof key).toBe('string'); + expect(key).toHaveLength(3); + expect(key).toMatch(/^[a-zA-Z0-9]{3}$/); + }); + + it('should generate different keys for different parents', () => { + // Add another sub-group + const subGroup2 = new GroupItem('test-survey.page2'); + survey.surveyItems['test-survey.page2'] = subGroup2; + const rootGroup = survey.surveyItems['test-survey'] as GroupItem; + rootGroup.items?.push('test-survey.page2'); + + // Add the same key to both parents + addKnownItems(survey, 'test-survey.page1', ['abc']); + addKnownItems(survey, 'test-survey.page2', ['abc']); + + // Generate keys for both parents - they should be able to avoid 'abc' independently + const key1 = (initAndAdd as any).generateUniqueKey('test-survey.page1'); + const key2 = (initAndAdd as any).generateUniqueKey('test-survey.page2'); + + expect(key1).not.toBe('abc'); + expect(key2).not.toBe('abc'); + expect(typeof key1).toBe('string'); + expect(typeof key2).toBe('string'); + }); + + it('should work with nested parent keys', () => { + // Create a deeply nested structure + const nestedGroup = new GroupItem('test-survey.page1.section1'); + survey.surveyItems['test-survey.page1.section1'] = nestedGroup; + + const key = (initAndAdd as any).generateUniqueKey('test-survey.page1.section1'); + + expect(typeof key).toBe('string'); + expect(key).toHaveLength(3); + expect(key).toMatch(/^[a-zA-Z0-9]{3}$/); + }); + + it('should handle case where many keys are already taken', () => { + // Fill up many single character combinations to test the algorithm under pressure + const existingKeys: string[] = []; + for (let i = 0; i < 100; i++) { + existingKeys.push(`k${i.toString().padStart(2, '0')}`); + } + + addKnownItems(survey, 'test-survey.page1', existingKeys); + + const key = (initAndAdd as any).generateUniqueKey('test-survey.page1'); + + expect(typeof key).toBe('string'); + expect(key).toHaveLength(3); + expect(existingKeys).not.toContain(key); + }); + + it('should throw error if unable to generate unique key after max attempts', () => { + // Mock Math.random to always return the same value, causing key generation to fail + const originalRandom = Math.random; + Math.random = jest.fn(() => 0.5); + + // Calculate what key will be generated when random always returns 0.5 + // chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' (62 chars) + // Math.floor(0.5 * 62) = 31, which is 'F' (0-indexed) + const predictableKey = 'FFF'; + addKnownItems(survey, 'test-survey.page1', [predictableKey]); + + expect(() => { + (initAndAdd as any).generateUniqueKey('test-survey.page1'); + }).toThrow('Failed to generate unique key after 1000 attempts'); + + // Restore original Math.random + Math.random = originalRandom; + }); + + it('should generate multiple unique keys in sequence', () => { + const generatedKeys = new Set(); + + // Generate 20 keys and ensure they're all unique + for (let i = 0; i < 20; i++) { + const key = (initAndAdd as any).generateUniqueKey('test-survey.page1'); + expect(generatedKeys.has(key)).toBe(false); + generatedKeys.add(key); + + // Add the generated key to the survey so the next generation avoids it + const fullKey = `test-survey.page1.${key}`; + const item = new DisplayItem(fullKey); + survey.surveyItems[fullKey] = item; + + // Add to parent's items array + const parentItem = survey.surveyItems['test-survey.page1'] as GroupItem; + if (!parentItem.items) { + parentItem.items = []; + } + parentItem.items.push(fullKey); + } + + expect(generatedKeys.size).toBe(20); + }); + }); + + describe('initAndAddGroup', () => { + it('should create and add a group with default shuffleItems (false)', () => { + const parentKey = 'test-survey.page1'; + + const groupKey = initAndAdd.group({ + parentFullKey: parentKey + }); + + // Verify the group was created + expect(groupKey).toBeDefined(); + expect(groupKey).toMatch(/^test-survey\.page1\.[a-zA-Z0-9]{3}$/); + + // Verify the group exists in the survey + const createdGroup = survey.surveyItems[groupKey] as GroupItem; + expect(createdGroup).toBeDefined(); + expect(createdGroup.itemType).toBe(SurveyItemType.Group); + expect(createdGroup.shuffleItems).toBe(false); + + // Verify the group was added to the parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(groupKey); + }); + + it('should create and add a group with shuffleItems set to true', () => { + const parentKey = 'test-survey.page1'; + + const groupKey = initAndAdd.group({ + parentFullKey: parentKey + }, true); + + // Verify the group was created with shuffleItems = true + const createdGroup = survey.surveyItems[groupKey] as GroupItem; + expect(createdGroup).toBeDefined(); + expect(createdGroup.itemType).toBe(SurveyItemType.Group); + expect(createdGroup.shuffleItems).toBe(true); + + // Verify the group was added to the parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(groupKey); + }); + + it('should create and add a group with shuffleItems explicitly set to false', () => { + const parentKey = 'test-survey.page1'; + + const groupKey = initAndAdd.group({ + parentFullKey: parentKey + }, false); + + // Verify the group was created with shuffleItems = false + const createdGroup = survey.surveyItems[groupKey] as GroupItem; + expect(createdGroup).toBeDefined(); + expect(createdGroup.itemType).toBe(SurveyItemType.Group); + expect(createdGroup.shuffleItems).toBe(false); + }); + + it('should add group at specified position', () => { + const parentKey = 'test-survey.page1'; + + // First add some items to the parent group + const item1 = new DisplayItem(`${parentKey}.item1`); + const item2 = new DisplayItem(`${parentKey}.item2`); + survey.surveyItems[`${parentKey}.item1`] = item1; + survey.surveyItems[`${parentKey}.item2`] = item2; + + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + parentGroup.items = [`${parentKey}.item1`, `${parentKey}.item2`]; + + // Add group at position 1 (between item1 and item2) + const groupKey = initAndAdd.group({ + parentFullKey: parentKey, + position: 1 + }); + + // Verify the group was inserted at the correct position + expect(parentGroup.items).toEqual([ + `${parentKey}.item1`, + groupKey, + `${parentKey}.item2` + ]); + }); + + it('should add group at the end when no position is specified', () => { + const parentKey = 'test-survey.page1'; + + // First add some items to the parent group + const item1 = new DisplayItem(`${parentKey}.item1`); + survey.surveyItems[`${parentKey}.item1`] = item1; + + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + parentGroup.items = [`${parentKey}.item1`]; + + // Add group without specifying position + const groupKey = initAndAdd.group({ + parentFullKey: parentKey + }); + + // Verify the group was added at the end + expect(parentGroup.items).toEqual([ + `${parentKey}.item1`, + groupKey + ]); + }); + + it('should generate unique keys for multiple groups', () => { + const parentKey = 'test-survey.page1'; + + // Create multiple groups + const group1Key = initAndAdd.group({ + parentFullKey: parentKey + }); + const group2Key = initAndAdd.group({ + parentFullKey: parentKey + }); + const group3Key = initAndAdd.group({ + parentFullKey: parentKey + }); + + // Verify all keys are unique + expect(group1Key).not.toBe(group2Key); + expect(group1Key).not.toBe(group3Key); + expect(group2Key).not.toBe(group3Key); + + // Verify all groups exist + expect(survey.surveyItems[group1Key]).toBeDefined(); + expect(survey.surveyItems[group2Key]).toBeDefined(); + expect(survey.surveyItems[group3Key]).toBeDefined(); + + // Verify all are added to parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(group1Key); + expect(parentGroup.items).toContain(group2Key); + expect(parentGroup.items).toContain(group3Key); + }); + + it('should work with root group as parent', () => { + const rootKey = 'test-survey'; + + const groupKey = initAndAdd.group({ + parentFullKey: rootKey + }, true); + + // Verify the group was created and added to root + const createdGroup = survey.surveyItems[groupKey] as GroupItem; + expect(createdGroup).toBeDefined(); + expect(createdGroup.shuffleItems).toBe(true); + + const rootGroup = survey.surveyItems[rootKey] as GroupItem; + expect(rootGroup.items).toContain(groupKey); + }); + + it('should throw error for non-existent parent', () => { + expect(() => { + initAndAdd.group({ + parentFullKey: 'non-existent-parent' + }); + }).toThrow(); + }); + + it('should return the full key of the created group', () => { + const parentKey = 'test-survey.page1'; + + const groupKey = initAndAdd.group({ + parentFullKey: parentKey + }); + + // Verify the returned key is a valid full key format + expect(groupKey).toMatch(/^test-survey\.page1\.[a-zA-Z0-9]{3}$/); + + // Verify the key corresponds to an actual item + expect(survey.surveyItems[groupKey]).toBeDefined(); + }); + }); +}); diff --git a/src/survey-editor/item-init-helper.ts b/src/survey-editor/item-init-helper.ts new file mode 100644 index 0000000..ee061bd --- /dev/null +++ b/src/survey-editor/item-init-helper.ts @@ -0,0 +1,96 @@ +import { SurveyEditor } from "./survey-editor"; +import { GroupItem, SurveyItemType } from "../survey/items"; +import { SurveyItemTranslations } from "../survey/utils"; + +interface Target { + parentFullKey: string; + position?: number; +} + +export class ItemInitHelper { + constructor(private _editor: SurveyEditor) { + + } + + // Structure items + group(target: Target, shuffleItems: boolean = false): string { + // Generate a unique key for the new group + const uniqueKey = this.generateUniqueKey(target.parentFullKey); + + // Create the new GroupItem + const newGroup = new GroupItem(`${target.parentFullKey}.${uniqueKey}`); + newGroup.shuffleItems = shuffleItems; + + + // Add the group to the survey via the editor + this._editor.addItem({ + parentKey: target.parentFullKey, + index: target.position + }, newGroup); + + return newGroup.key.fullKey; + } + + surveyEnd(target: Target) { + + } + + pageBreak(target: Target) { + } + + // Display items + displayItem(target: Target) { + } + + // Response items + singleChoiceQuestion(target: Target) { + + } + + multipleChoiceQuestion(target: Target) { + + } + + + /** + * Generates a unique item key of specified length within the specified parent. + * Keeps generating until it finds a key that doesn't already exist among siblings. + * @param parentFullKey The full key of the parent item + * @param keyLength The length of the key to generate (default: 3) + * @returns A unique string of the specified length + */ + private generateUniqueKey(parentFullKey: string, keyLength: number = 3): string { + const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + // Get existing sibling item keys within the parent + const existingSiblingKeys = new Set(); + + for (const itemFullKey of Object.keys(this._editor.survey.surveyItems)) { + const item = this._editor.survey.surveyItems[itemFullKey]; + + // Check if this item has the same parent + if (item.key.parentFullKey === parentFullKey) { + existingSiblingKeys.add(item.key.itemKey); + } + } + + // Generate keys until we find a unique one + let attempts = 0; + const maxAttempts = 1000; // Safety limit to prevent infinite loops + + while (attempts < maxAttempts) { + let key = ''; + for (let i = 0; i < keyLength; i++) { + key += chars.charAt(Math.floor(Math.random() * chars.length)); + } + + if (!existingSiblingKeys.has(key)) { + return key; + } + + attempts++; + } + + throw new Error(`Failed to generate unique key after ${maxAttempts} attempts`); + } +} diff --git a/src/survey-editor/survey-editor.ts b/src/survey-editor/survey-editor.ts index 545bee3..f0973c2 100644 --- a/src/survey-editor/survey-editor.ts +++ b/src/survey-editor/survey-editor.ts @@ -354,7 +354,7 @@ export class SurveyEditor { index?: number; } | undefined, item: SurveyItem, - content: SurveyItemTranslations + content?: SurveyItemTranslations ) { this.commitIfNeeded(); From b611d27802eaf4a470f3df93c56e94966183d640 Mon Sep 17 00:00:00 2001 From: phev8 Date: Wed, 23 Jul 2025 10:26:37 +0200 Subject: [PATCH 08/10] Add survey item creation methods in ItemInitHelper - Expanded the `ItemInitHelper` class to include methods for creating survey end items, page breaks, and display items, enhancing the survey item management capabilities. - Implemented unique key generation for each new item, ensuring no conflicts within the survey structure. - Updated the `surveyEnd` and `pageBreak` methods to support optional positioning for item insertion. - Added comprehensive tests in `item-init-helper.test.ts` to validate the new functionalities and ensure robust error handling for non-existent parents. - Enhanced the `survey-editor` module to export the `ItemInitHelper`, making it accessible for broader use in the survey editing process. --- docs/example-usage.md | 108 ++++++++++ src/__tests__/item-init-helper.test.ts | 266 +++++++++++++++++++++++++ src/survey-editor/index.ts | 1 + src/survey-editor/item-init-helper.ts | 79 +++++++- 4 files changed, 450 insertions(+), 4 deletions(-) diff --git a/docs/example-usage.md b/docs/example-usage.md index dea1a31..e75d6e7 100644 --- a/docs/example-usage.md +++ b/docs/example-usage.md @@ -112,3 +112,111 @@ class EditorAnalytics { 3. **Performance**: Be mindful of heavy operations in the `survey-changed` event as it fires on every modification 4. **Memory leaks**: Remove listeners when components unmount to prevent memory leaks 5. **Check event type**: Use the `isCommit` flag to differentiate between modifications and commits + +# Survey Engine Example Usage + +## ItemInitHelper Usage + +The `ItemInitHelper` class provides convenient methods for creating and adding survey items to a survey. + +### Creating Groups + +```typescript +import { Survey } from '../survey/survey'; +import { SurveyEditor } from '../survey-editor/survey-editor'; +import { ItemInitHelper } from '../survey-editor/item-init-helper'; + +const survey = new Survey('my-survey'); +const editor = new SurveyEditor(survey); +const initHelper = new ItemInitHelper(editor); + +// Create a group with default shuffleItems (false) +const groupKey = initHelper.group({ + parentFullKey: 'my-survey' +}); + +// Create a group with shuffleItems enabled +const shuffledGroupKey = initHelper.group({ + parentFullKey: 'my-survey' +}, true); + +// Create a group at a specific position +const positionedGroupKey = initHelper.group({ + parentFullKey: 'my-survey', + position: 1 +}); +``` + +### Creating Survey End Items + +```typescript +// Create a survey end item +const surveyEndKey = initHelper.surveyEnd({ + parentFullKey: 'my-survey' +}); + +// Create a survey end item at a specific position +const positionedSurveyEndKey = initHelper.surveyEnd({ + parentFullKey: 'my-survey', + position: 2 +}); +``` + +### Creating Page Break Items + +```typescript +// Create a page break item +const pageBreakKey = initHelper.pageBreak({ + parentFullKey: 'my-survey' +}); + +// Create a page break item at a specific position +const positionedPageBreakKey = initHelper.pageBreak({ + parentFullKey: 'my-survey', + position: 1 +}); +``` + +### Complete Example + +```typescript +import { Survey } from '../survey/survey'; +import { SurveyEditor } from '../survey-editor/survey-editor'; +import { ItemInitHelper } from '../survey-editor/item-init-helper'; + +// Create a new survey +const survey = new Survey('example-survey'); +const editor = new SurveyEditor(survey); +const initHelper = new ItemInitHelper(editor); + +// Create the survey structure +const group1Key = initHelper.group({ + parentFullKey: 'example-survey' +}); + +const pageBreakKey = initHelper.pageBreak({ + parentFullKey: 'example-survey' +}); + +const group2Key = initHelper.group({ + parentFullKey: 'example-survey' +}); + +const surveyEndKey = initHelper.surveyEnd({ + parentFullKey: 'example-survey' +}); + +console.log('Created survey structure:'); +console.log('- Group 1:', group1Key); +console.log('- Page Break:', pageBreakKey); +console.log('- Group 2:', group2Key); +console.log('- Survey End:', surveyEndKey); +``` + +## Key Features + +- **Automatic Key Generation**: All methods generate unique keys automatically +- **Position Control**: Items can be inserted at specific positions within their parent +- **Type Safety**: All methods return the full key of the created item +- **Error Handling**: Throws errors for invalid parent keys or other issues +- **Consistent API**: All methods follow the same pattern for easy use diff --git a/src/__tests__/item-init-helper.test.ts b/src/__tests__/item-init-helper.test.ts index 2b88335..d42bfb6 100644 --- a/src/__tests__/item-init-helper.test.ts +++ b/src/__tests__/item-init-helper.test.ts @@ -363,4 +363,270 @@ describe('ItemInitHelper', () => { expect(survey.surveyItems[groupKey]).toBeDefined(); }); }); + + describe('surveyEnd', () => { + it('should create and add a survey end item', () => { + const parentKey = 'test-survey.page1'; + + const surveyEndKey = initAndAdd.surveyEnd({ + parentFullKey: parentKey + }); + + // Verify the survey end was created + expect(surveyEndKey).toBeDefined(); + expect(surveyEndKey).toMatch(/^test-survey\.page1\.[a-zA-Z0-9]{3}$/); + + // Verify the survey end exists in the survey + const createdSurveyEnd = survey.surveyItems[surveyEndKey]; + expect(createdSurveyEnd).toBeDefined(); + expect(createdSurveyEnd.itemType).toBe(SurveyItemType.SurveyEnd); + + // Verify the survey end was added to the parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(surveyEndKey); + }); + + it('should add survey end at specified position', () => { + const parentKey = 'test-survey.page1'; + + // First add some items to the parent group + const item1 = new DisplayItem(`${parentKey}.item1`); + const item2 = new DisplayItem(`${parentKey}.item2`); + survey.surveyItems[`${parentKey}.item1`] = item1; + survey.surveyItems[`${parentKey}.item2`] = item2; + + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + parentGroup.items = [`${parentKey}.item1`, `${parentKey}.item2`]; + + // Add survey end at position 1 (between item1 and item2) + const surveyEndKey = initAndAdd.surveyEnd({ + parentFullKey: parentKey, + position: 1 + }); + + // Verify the survey end was inserted at the correct position + expect(parentGroup.items).toEqual([ + `${parentKey}.item1`, + surveyEndKey, + `${parentKey}.item2` + ]); + }); + + it('should add survey end at the end when no position is specified', () => { + const parentKey = 'test-survey.page1'; + + // First add some items to the parent group + const item1 = new DisplayItem(`${parentKey}.item1`); + survey.surveyItems[`${parentKey}.item1`] = item1; + + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + parentGroup.items = [`${parentKey}.item1`]; + + // Add survey end without specifying position + const surveyEndKey = initAndAdd.surveyEnd({ + parentFullKey: parentKey + }); + + // Verify the survey end was added at the end + expect(parentGroup.items).toEqual([ + `${parentKey}.item1`, + surveyEndKey + ]); + }); + + it('should generate unique keys for multiple survey ends', () => { + const parentKey = 'test-survey.page1'; + + // Create multiple survey ends + const surveyEnd1Key = initAndAdd.surveyEnd({ + parentFullKey: parentKey + }); + const surveyEnd2Key = initAndAdd.surveyEnd({ + parentFullKey: parentKey + }); + + // Verify all keys are unique + expect(surveyEnd1Key).not.toBe(surveyEnd2Key); + + // Verify all survey ends exist + expect(survey.surveyItems[surveyEnd1Key]).toBeDefined(); + expect(survey.surveyItems[surveyEnd2Key]).toBeDefined(); + + // Verify all are added to parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(surveyEnd1Key); + expect(parentGroup.items).toContain(surveyEnd2Key); + }); + + it('should work with root group as parent', () => { + const rootKey = 'test-survey'; + + const surveyEndKey = initAndAdd.surveyEnd({ + parentFullKey: rootKey + }); + + // Verify the survey end was created and added to root + const createdSurveyEnd = survey.surveyItems[surveyEndKey]; + expect(createdSurveyEnd).toBeDefined(); + expect(createdSurveyEnd.itemType).toBe(SurveyItemType.SurveyEnd); + + const rootGroup = survey.surveyItems[rootKey] as GroupItem; + expect(rootGroup.items).toContain(surveyEndKey); + }); + + it('should throw error for non-existent parent', () => { + expect(() => { + initAndAdd.surveyEnd({ + parentFullKey: 'non-existent-parent' + }); + }).toThrow(); + }); + + it('should return the full key of the created survey end', () => { + const parentKey = 'test-survey.page1'; + + const surveyEndKey = initAndAdd.surveyEnd({ + parentFullKey: parentKey + }); + + // Verify the returned key is a valid full key format + expect(surveyEndKey).toMatch(/^test-survey\.page1\.[a-zA-Z0-9]{3}$/); + + // Verify the key corresponds to an actual item + expect(survey.surveyItems[surveyEndKey]).toBeDefined(); + }); + }); + + describe('pageBreak', () => { + it('should create and add a page break item', () => { + const parentKey = 'test-survey.page1'; + + const pageBreakKey = initAndAdd.pageBreak({ + parentFullKey: parentKey + }); + + // Verify the page break was created + expect(pageBreakKey).toBeDefined(); + expect(pageBreakKey).toMatch(/^test-survey\.page1\.[a-zA-Z0-9]{3}$/); + + // Verify the page break exists in the survey + const createdPageBreak = survey.surveyItems[pageBreakKey]; + expect(createdPageBreak).toBeDefined(); + expect(createdPageBreak.itemType).toBe(SurveyItemType.PageBreak); + + // Verify the page break was added to the parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(pageBreakKey); + }); + + it('should add page break at specified position', () => { + const parentKey = 'test-survey.page1'; + + // First add some items to the parent group + const item1 = new DisplayItem(`${parentKey}.item1`); + const item2 = new DisplayItem(`${parentKey}.item2`); + survey.surveyItems[`${parentKey}.item1`] = item1; + survey.surveyItems[`${parentKey}.item2`] = item2; + + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + parentGroup.items = [`${parentKey}.item1`, `${parentKey}.item2`]; + + // Add page break at position 1 (between item1 and item2) + const pageBreakKey = initAndAdd.pageBreak({ + parentFullKey: parentKey, + position: 1 + }); + + // Verify the page break was inserted at the correct position + expect(parentGroup.items).toEqual([ + `${parentKey}.item1`, + pageBreakKey, + `${parentKey}.item2` + ]); + }); + + it('should add page break at the end when no position is specified', () => { + const parentKey = 'test-survey.page1'; + + // First add some items to the parent group + const item1 = new DisplayItem(`${parentKey}.item1`); + survey.surveyItems[`${parentKey}.item1`] = item1; + + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + parentGroup.items = [`${parentKey}.item1`]; + + // Add page break without specifying position + const pageBreakKey = initAndAdd.pageBreak({ + parentFullKey: parentKey + }); + + // Verify the page break was added at the end + expect(parentGroup.items).toEqual([ + `${parentKey}.item1`, + pageBreakKey + ]); + }); + + it('should generate unique keys for multiple page breaks', () => { + const parentKey = 'test-survey.page1'; + + // Create multiple page breaks + const pageBreak1Key = initAndAdd.pageBreak({ + parentFullKey: parentKey + }); + const pageBreak2Key = initAndAdd.pageBreak({ + parentFullKey: parentKey + }); + + // Verify all keys are unique + expect(pageBreak1Key).not.toBe(pageBreak2Key); + + // Verify all page breaks exist + expect(survey.surveyItems[pageBreak1Key]).toBeDefined(); + expect(survey.surveyItems[pageBreak2Key]).toBeDefined(); + + // Verify all are added to parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(pageBreak1Key); + expect(parentGroup.items).toContain(pageBreak2Key); + }); + + it('should work with root group as parent', () => { + const rootKey = 'test-survey'; + + const pageBreakKey = initAndAdd.pageBreak({ + parentFullKey: rootKey + }); + + // Verify the page break was created and added to root + const createdPageBreak = survey.surveyItems[pageBreakKey]; + expect(createdPageBreak).toBeDefined(); + expect(createdPageBreak.itemType).toBe(SurveyItemType.PageBreak); + + const rootGroup = survey.surveyItems[rootKey] as GroupItem; + expect(rootGroup.items).toContain(pageBreakKey); + }); + + it('should throw error for non-existent parent', () => { + expect(() => { + initAndAdd.pageBreak({ + parentFullKey: 'non-existent-parent' + }); + }).toThrow(); + }); + + it('should return the full key of the created page break', () => { + const parentKey = 'test-survey.page1'; + + const pageBreakKey = initAndAdd.pageBreak({ + parentFullKey: parentKey + }); + + // Verify the returned key is a valid full key format + expect(pageBreakKey).toMatch(/^test-survey\.page1\.[a-zA-Z0-9]{3}$/); + + // Verify the key corresponds to an actual item + expect(survey.surveyItems[pageBreakKey]).toBeDefined(); + }); + }); }); diff --git a/src/survey-editor/index.ts b/src/survey-editor/index.ts index da620cf..c3ad493 100644 --- a/src/survey-editor/index.ts +++ b/src/survey-editor/index.ts @@ -5,3 +5,4 @@ export * from './expression-editor'; export * from './expression-editor-generators'; export * from './undo-redo'; export * from './item-copy-paste'; +export * from './item-init-helper'; diff --git a/src/survey-editor/item-init-helper.ts b/src/survey-editor/item-init-helper.ts index ee061bd..d13040e 100644 --- a/src/survey-editor/item-init-helper.ts +++ b/src/survey-editor/item-init-helper.ts @@ -1,6 +1,6 @@ import { SurveyEditor } from "./survey-editor"; -import { GroupItem, SurveyItemType } from "../survey/items"; -import { SurveyItemTranslations } from "../survey/utils"; +import { DisplayItem, GroupItem, MultipleChoiceQuestionItem, PageBreakItem, SingleChoiceQuestionItem, SurveyEndItem } from "../survey/items"; +import { ContentType, SurveyItemTranslations } from "../survey/utils"; interface Target { parentFullKey: string; @@ -31,24 +31,95 @@ export class ItemInitHelper { return newGroup.key.fullKey; } - surveyEnd(target: Target) { + surveyEnd(target: Target): string { + // Generate a unique key for the new survey end + const uniqueKey = this.generateUniqueKey(target.parentFullKey); + + // Create the new SurveyEndItem + const newSurveyEnd = new SurveyEndItem(`${target.parentFullKey}.${uniqueKey}`); + // Create translations for the survey end (empty by default) + const translations = new SurveyItemTranslations(); + for (const locale of this._editor.survey.locales) { + translations.setContent(locale, 'title', { + content: '', + type: ContentType.CQM + }); + } + + // Add the survey end to the survey via the editor + this._editor.addItem({ + parentKey: target.parentFullKey, + index: target.position + }, newSurveyEnd, translations); + + return newSurveyEnd.key.fullKey; } - pageBreak(target: Target) { + pageBreak(target: Target): string { + // Generate a unique key for the new page break + const uniqueKey = this.generateUniqueKey(target.parentFullKey); + + // Create the new PageBreakItem + const newPageBreak = new PageBreakItem(`${target.parentFullKey}.${uniqueKey}`); + + // Add the page break to the survey via the editor + this._editor.addItem({ + parentKey: target.parentFullKey, + index: target.position + }, newPageBreak); + + return newPageBreak.key.fullKey; } // Display items displayItem(target: Target) { + // Generate a unique key for the new display item + const uniqueKey = this.generateUniqueKey(target.parentFullKey); + + // Create the new DisplayItem + const newDisplayItem = new DisplayItem(`${target.parentFullKey}.${uniqueKey}`); + + // Add the display item to the survey via the editor + this._editor.addItem({ + parentKey: target.parentFullKey, + index: target.position + }, newDisplayItem); + + return newDisplayItem.key.fullKey; } // Response items singleChoiceQuestion(target: Target) { + // Generate a unique key for the new single choice question + const uniqueKey = this.generateUniqueKey(target.parentFullKey); + + // Create the new SingleChoiceQuestionItem + const newSingleChoiceQuestion = new SingleChoiceQuestionItem(`${target.parentFullKey}.${uniqueKey}`); + // Add the single choice question to the survey via the editor + this._editor.addItem({ + parentKey: target.parentFullKey, + index: target.position + }, newSingleChoiceQuestion); + + return newSingleChoiceQuestion.key.fullKey; } multipleChoiceQuestion(target: Target) { + // Generate a unique key for the new multiple choice question + const uniqueKey = this.generateUniqueKey(target.parentFullKey); + + // Create the new MultipleChoiceQuestionItem + const newMultipleChoiceQuestion = new MultipleChoiceQuestionItem(`${target.parentFullKey}.${uniqueKey}`); + + // Add the multiple choice question to the survey via the editor + this._editor.addItem({ + parentKey: target.parentFullKey, + index: target.position + }, newMultipleChoiceQuestion); + return newMultipleChoiceQuestion.key.fullKey; } From 79aa37fd2e20419bbf2ac7998701842aa441a239 Mon Sep 17 00:00:00 2001 From: phev8 Date: Thu, 24 Jul 2025 09:09:13 +0200 Subject: [PATCH 09/10] Enhance item initialization tests and update survey editor translation handling - Added tests for creating and adding display items, single choice questions, and multiple choice questions in `item-init-helper.test.ts`, ensuring comprehensive coverage for new item types. - Updated the `SurveyEditor` class to conditionally set item translations only if content is provided, improving robustness in translation management. - Enhanced existing tests to verify the correct positioning of items within parent groups and ensure proper error handling for non-existent parents. --- src/__tests__/item-init-helper.test.ts | 233 ++++++++++++++++++++++++- src/survey-editor/survey-editor.ts | 4 +- 2 files changed, 235 insertions(+), 2 deletions(-) diff --git a/src/__tests__/item-init-helper.test.ts b/src/__tests__/item-init-helper.test.ts index d42bfb6..12b2053 100644 --- a/src/__tests__/item-init-helper.test.ts +++ b/src/__tests__/item-init-helper.test.ts @@ -2,6 +2,7 @@ import { Survey } from '../survey/survey'; import { SurveyEditor } from '../survey-editor/survey-editor'; import { ItemInitHelper } from '../survey-editor/item-init-helper'; import { GroupItem, SingleChoiceQuestionItem, DisplayItem, SurveyItemType } from '../survey/items'; +import { ContentType } from '../survey/utils/content'; // Helper function to create a test survey with some existing items const createTestSurvey = (surveyKey: string = 'test-survey'): Survey => { @@ -365,9 +366,16 @@ describe('ItemInitHelper', () => { }); describe('surveyEnd', () => { - it('should create and add a survey end item', () => { + it('should create and add a survey end item with translations', () => { const parentKey = 'test-survey.page1'; + // Set up locales in the survey first + survey.translations.setSurveyCardContent('en', { + name: { type: ContentType.md, content: 'Test Survey' }, + description: { type: ContentType.md, content: 'Test Description' }, + typicalDuration: { type: ContentType.md, content: '5 minutes' } + }); + const surveyEndKey = initAndAdd.surveyEnd({ parentFullKey: parentKey }); @@ -384,6 +392,10 @@ describe('ItemInitHelper', () => { // Verify the survey end was added to the parent const parentGroup = survey.surveyItems[parentKey] as GroupItem; expect(parentGroup.items).toContain(surveyEndKey); + + // Verify translations were created + const itemTranslations = survey.getItemTranslations(surveyEndKey); + expect(itemTranslations?.getContent('en', 'title')).toBeDefined(); }); it('should add survey end at specified position', () => { @@ -497,6 +509,225 @@ describe('ItemInitHelper', () => { }); }); + describe('displayItem', () => { + it('should create and add a display item', () => { + const parentKey = 'test-survey.page1'; + + const displayItemKey = initAndAdd.displayItem({ + parentFullKey: parentKey + }); + + // Verify the display item was created + expect(displayItemKey).toBeDefined(); + expect(displayItemKey).toMatch(/^test-survey\.page1\.[a-zA-Z0-9]{3}$/); + + // Verify the display item exists in the survey + const createdDisplayItem = survey.surveyItems[displayItemKey]; + expect(createdDisplayItem).toBeDefined(); + expect(createdDisplayItem.itemType).toBe(SurveyItemType.Display); + + // Verify the display item was added to the parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(displayItemKey); + }); + + it('should add display item at specified position', () => { + const parentKey = 'test-survey.page1'; + + // First add some items to the parent group + const item1 = new DisplayItem(`${parentKey}.item1`); + const item2 = new DisplayItem(`${parentKey}.item2`); + survey.surveyItems[`${parentKey}.item1`] = item1; + survey.surveyItems[`${parentKey}.item2`] = item2; + + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + parentGroup.items = [`${parentKey}.item1`, `${parentKey}.item2`]; + + // Add display item at position 1 (between item1 and item2) + const displayItemKey = initAndAdd.displayItem({ + parentFullKey: parentKey, + position: 1 + }); + + // Verify the display item was inserted at the correct position + expect(parentGroup.items).toEqual([ + `${parentKey}.item1`, + displayItemKey, + `${parentKey}.item2` + ]); + }); + + it('should work with root group as parent', () => { + const rootKey = 'test-survey'; + + const displayItemKey = initAndAdd.displayItem({ + parentFullKey: rootKey + }); + + // Verify the display item was created and added to root + const createdDisplayItem = survey.surveyItems[displayItemKey]; + expect(createdDisplayItem).toBeDefined(); + expect(createdDisplayItem.itemType).toBe(SurveyItemType.Display); + + const rootGroup = survey.surveyItems[rootKey] as GroupItem; + expect(rootGroup.items).toContain(displayItemKey); + }); + + it('should throw error for non-existent parent', () => { + expect(() => { + initAndAdd.displayItem({ + parentFullKey: 'non-existent-parent' + }); + }).toThrow(); + }); + }); + + describe('singleChoiceQuestion', () => { + it('should create and add a single choice question', () => { + const parentKey = 'test-survey.page1'; + + const singleChoiceKey = initAndAdd.singleChoiceQuestion({ + parentFullKey: parentKey + }); + + // Verify the single choice question was created + expect(singleChoiceKey).toBeDefined(); + expect(singleChoiceKey).toMatch(/^test-survey\.page1\.[a-zA-Z0-9]{3}$/); + + // Verify the single choice question exists in the survey + const createdSingleChoice = survey.surveyItems[singleChoiceKey]; + expect(createdSingleChoice).toBeDefined(); + expect(createdSingleChoice.itemType).toBe(SurveyItemType.SingleChoiceQuestion); + + // Verify the single choice question was added to the parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(singleChoiceKey); + }); + + it('should add single choice question at specified position', () => { + const parentKey = 'test-survey.page1'; + + // First add some items to the parent group + const item1 = new DisplayItem(`${parentKey}.item1`); + const item2 = new DisplayItem(`${parentKey}.item2`); + survey.surveyItems[`${parentKey}.item1`] = item1; + survey.surveyItems[`${parentKey}.item2`] = item2; + + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + parentGroup.items = [`${parentKey}.item1`, `${parentKey}.item2`]; + + // Add single choice question at position 1 (between item1 and item2) + const singleChoiceKey = initAndAdd.singleChoiceQuestion({ + parentFullKey: parentKey, + position: 1 + }); + + // Verify the single choice question was inserted at the correct position + expect(parentGroup.items).toEqual([ + `${parentKey}.item1`, + singleChoiceKey, + `${parentKey}.item2` + ]); + }); + + it('should work with root group as parent', () => { + const rootKey = 'test-survey'; + + const singleChoiceKey = initAndAdd.singleChoiceQuestion({ + parentFullKey: rootKey + }); + + // Verify the single choice question was created and added to root + const createdSingleChoice = survey.surveyItems[singleChoiceKey]; + expect(createdSingleChoice).toBeDefined(); + expect(createdSingleChoice.itemType).toBe(SurveyItemType.SingleChoiceQuestion); + + const rootGroup = survey.surveyItems[rootKey] as GroupItem; + expect(rootGroup.items).toContain(singleChoiceKey); + }); + + it('should throw error for non-existent parent', () => { + expect(() => { + initAndAdd.singleChoiceQuestion({ + parentFullKey: 'non-existent-parent' + }); + }).toThrow(); + }); + }); + + describe('multipleChoiceQuestion', () => { + it('should create and add a multiple choice question', () => { + const parentKey = 'test-survey.page1'; + + const multipleChoiceKey = initAndAdd.multipleChoiceQuestion({ + parentFullKey: parentKey + }); + + // Verify the multiple choice question was created + expect(multipleChoiceKey).toBeDefined(); + expect(multipleChoiceKey).toMatch(/^test-survey\.page1\.[a-zA-Z0-9]{3}$/); + + // Verify the multiple choice question exists in the survey + const createdMultipleChoice = survey.surveyItems[multipleChoiceKey]; + expect(createdMultipleChoice).toBeDefined(); + expect(createdMultipleChoice.itemType).toBe(SurveyItemType.MultipleChoiceQuestion); + + // Verify the multiple choice question was added to the parent + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + expect(parentGroup.items).toContain(multipleChoiceKey); + }); + + it('should add multiple choice question at specified position', () => { + const parentKey = 'test-survey.page1'; + + // First add some items to the parent group + const item1 = new DisplayItem(`${parentKey}.item1`); + const item2 = new DisplayItem(`${parentKey}.item2`); + survey.surveyItems[`${parentKey}.item1`] = item1; + survey.surveyItems[`${parentKey}.item2`] = item2; + + const parentGroup = survey.surveyItems[parentKey] as GroupItem; + parentGroup.items = [`${parentKey}.item1`, `${parentKey}.item2`]; + + // Add multiple choice question at position 1 (between item1 and item2) + const multipleChoiceKey = initAndAdd.multipleChoiceQuestion({ + parentFullKey: parentKey, + position: 1 + }); + + // Verify the multiple choice question was inserted at the correct position + expect(parentGroup.items).toEqual([ + `${parentKey}.item1`, + multipleChoiceKey, + `${parentKey}.item2` + ]); + }); + + it('should work with root group as parent', () => { + const rootKey = 'test-survey'; + + const multipleChoiceKey = initAndAdd.multipleChoiceQuestion({ + parentFullKey: rootKey + }); + + // Verify the multiple choice question was created and added to root + const createdMultipleChoice = survey.surveyItems[multipleChoiceKey]; + expect(createdMultipleChoice).toBeDefined(); + expect(createdMultipleChoice.itemType).toBe(SurveyItemType.MultipleChoiceQuestion); + + const rootGroup = survey.surveyItems[rootKey] as GroupItem; + expect(rootGroup.items).toContain(multipleChoiceKey); + }); + + it('should throw error for non-existent parent', () => { + expect(() => { + initAndAdd.multipleChoiceQuestion({ + parentFullKey: 'non-existent-parent' + }); + }).toThrow(); + }); + }); + describe('pageBreak', () => { it('should create and add a page break item', () => { const parentKey = 'test-survey.page1'; diff --git a/src/survey-editor/survey-editor.ts b/src/survey-editor/survey-editor.ts index f0973c2..226e942 100644 --- a/src/survey-editor/survey-editor.ts +++ b/src/survey-editor/survey-editor.ts @@ -416,7 +416,9 @@ export class SurveyEditor { parentGroup.items.splice(insertIndex, 0, item.key.fullKey); // Update translations in the survey - this._survey.translations.setItemTranslations(item.key.fullKey, content); + if (content) { + this._survey.translations.setItemTranslations(item.key.fullKey, content); + } // Mark as modified (uncommitted change) this.commit(`Added ${item.key.fullKey}`); From e64d6a2ba4bf1fd23c3c715cded2ea2e3464b0ae Mon Sep 17 00:00:00 2001 From: phev8 Date: Fri, 8 Aug 2025 12:25:11 +0200 Subject: [PATCH 10/10] Refactor item copy-paste functionality and clean up imports - Removed unused imports and commented-out methods in `item-copy-paste.ts` to streamline the code and improve clarity. - Updated `item-init-helper.test.ts` to remove the import of `SingleChoiceQuestionItem`, reflecting changes in item management. - Enhanced overall maintainability by eliminating redundant code and focusing on essential functionalities. --- src/__tests__/item-init-helper.test.ts | 2 +- src/survey-editor/item-copy-paste.ts | 124 +------------------------ 2 files changed, 3 insertions(+), 123 deletions(-) diff --git a/src/__tests__/item-init-helper.test.ts b/src/__tests__/item-init-helper.test.ts index 12b2053..5a030c4 100644 --- a/src/__tests__/item-init-helper.test.ts +++ b/src/__tests__/item-init-helper.test.ts @@ -1,7 +1,7 @@ import { Survey } from '../survey/survey'; import { SurveyEditor } from '../survey-editor/survey-editor'; import { ItemInitHelper } from '../survey-editor/item-init-helper'; -import { GroupItem, SingleChoiceQuestionItem, DisplayItem, SurveyItemType } from '../survey/items'; +import { GroupItem, DisplayItem, SurveyItemType } from '../survey/items'; import { ContentType } from '../survey/utils/content'; // Helper function to create a test survey with some existing items diff --git a/src/survey-editor/item-copy-paste.ts b/src/survey-editor/item-copy-paste.ts index a1d250a..b24e7ab 100644 --- a/src/survey-editor/item-copy-paste.ts +++ b/src/survey-editor/item-copy-paste.ts @@ -1,10 +1,8 @@ import { Survey } from "../survey/survey"; import { SurveyItem, GroupItem, SurveyItemType } from "../survey/items"; import { SurveyItemTranslations, JsonComponentContent } from "../survey/utils"; -import { SurveyItemKey, ItemComponentKey } from "../survey/item-component-key"; -import { JsonSurveyItem, JsonSurveyItemGroup } from "../survey/items/survey-item-json"; -import { JsonSurveyItemResponse } from "../survey/responses"; -import { ItemComponent, GroupComponent } from "../survey/components"; +import { SurveyItemKey } from "../survey/item-component-key"; +import { JsonSurveyItem } from "../survey/items/survey-item-json"; // Serialized translation data format for clipboard @@ -145,24 +143,6 @@ export class ItemCopyPaste { }); } - /** - * Update prefill keys and store them (placeholder for future implementation) - * @param prefills - The prefills to update - * @param keyMapping - Mapping from old keys to new keys - */ - private updatePrefills(prefills: { [itemKey: string]: JsonSurveyItemResponse }, keyMapping: { [oldKey: string]: string }): void { - // Update prefill keys according to the key mapping - Object.keys(prefills).forEach(oldKey => { - const newKey = keyMapping[oldKey]; - if (newKey && newKey !== oldKey) { - const prefill = prefills[oldKey]; - prefill.key = newKey; - // Note: In a full implementation, these would be stored in the survey engine context - // For now, we just update the keys for consistency - } - }); - } - /** * Add an item to its parent group * @param target - Target location information @@ -320,30 +300,6 @@ export class ItemCopyPaste { return updatedData; } - /** - * Update component keys in component data - */ - private updateComponentKeysInData(componentData: any, oldFullKey: string, newFullKey: string, newItemKey: string): any { - const updatedData = JSON.parse(JSON.stringify(componentData)); // Deep clone - - // Update the main component key - updatedData.key = newFullKey; - - // If this is a group component with nested items, update their keys - if (updatedData.items && Array.isArray(updatedData.items)) { - updatedData.items = updatedData.items.map((childData: any) => { - if (childData.key && childData.key.startsWith(oldFullKey + '.')) { - const oldChildKey = ItemComponentKey.fromFullKey(childData.key, this.survey.surveyItems[newItemKey].key.fullKey); - const newChildKey = new ItemComponentKey(oldChildKey.componentKey, newFullKey, newItemKey); - return this.updateComponentKeysInData(childData, childData.key, newChildKey.fullKey, newItemKey); - } - return childData; - }); - } - - return updatedData; - } - /** * Update expressions in item data that reference the old keys */ @@ -439,82 +395,6 @@ export class ItemCopyPaste { return newTranslations; } - /** - * Recursively create child items for a group item - */ - private createChildItemsRecursively(newParentKey: string, originalClipboardData: SurveyItemClipboardData): void { - const groupData = originalClipboardData.items[0].itemData as JsonSurveyItemGroup; - - if (groupData.items && Array.isArray(groupData.items)) { - groupData.items.forEach((originalChildKey: string) => { - // Check if the original child item exists in the source survey - const originalChildItem = this.survey.surveyItems[originalChildKey]; - if (originalChildItem) { - // Create clipboard data for the child item - const childClipboardData = this.copyItem(originalChildKey); - - // Generate new key for the child - const originalChildItemKey = SurveyItemKey.fromFullKey(originalChildKey); - const newChildKey = new SurveyItemKey(originalChildItemKey.itemKey, newParentKey); - - // Create the child item data with updated keys - const updatedChildData = this.updateItemKeysInData(childClipboardData.items[0].itemData, originalChildKey, newChildKey.fullKey); - - // Create the child item - const newChildItem = SurveyItem.fromJson(newChildKey.fullKey, updatedChildData); - - // Add to survey items - this.survey.surveyItems[newChildKey.fullKey] = newChildItem; - - // Update translations for child - const childTranslations = this.updateTranslationKeys(childClipboardData.translations, originalChildKey, newChildKey.fullKey); - const serializedChildTranslations = childTranslations[newChildKey.fullKey]; - if (serializedChildTranslations) { - const itemTranslations = new SurveyItemTranslations(); - Object.keys(serializedChildTranslations).forEach(locale => { - itemTranslations.setAllForLocale(locale, serializedChildTranslations[locale]); - }); - this.survey.translations.setItemTranslations(newChildKey.fullKey, itemTranslations); - } else { - this.survey.translations.setItemTranslations(newChildKey.fullKey, new SurveyItemTranslations()); - } - - // Recursively create grandchildren if this is a group - if (newChildItem.itemType === SurveyItemType.Group && (newChildItem as GroupItem).items) { - this.createChildItemsRecursively(newChildKey.fullKey, childClipboardData); - } - } - }); - } - } - - - /** - * Search for a component in an array of components - */ - private searchComponentsArray(components: ItemComponent[], componentKey: string): ItemComponent | null { - for (const component of components) { - if (component.key.fullKey === componentKey) { - return component; - } - - // Search recursively in nested components - const nestedResult = this.searchComponentRecursively(component, componentKey); - if (nestedResult) return nestedResult; - } - return null; - } - - /** - * Search for a component recursively within a component - */ - private searchComponentRecursively(component: ItemComponent, componentKey: string): ItemComponent | null { - if (component instanceof GroupComponent && component.items) { - return this.searchComponentsArray(component.items, componentKey); - } - return null; - } - /** * Validate clipboard data format