From f572fdebcacd06c6a20e45ab3be96aa23ef28c74 Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Tue, 2 Sep 2025 21:44:13 +0500 Subject: [PATCH] [code] Add ts instruments & refactor all code --- .eslintignore | 40 + .eslintrc.js | 181 + .gitignore | 7 + .prettierignore | 26 + .prettierrc.js | 44 + Content/Blueprints/BP_MainCharacter.ts | 129 +- Content/Blueprints/BP_MainCharacter.uasset | 4 +- Content/Blueprints/BP_TengriGameMode.ts | 8 + Content/Debug/Components/AC_DebugHUD.ts | 727 ++-- Content/Debug/Components/AC_DebugHUD.uasset | 4 +- Content/Debug/Enums/E_DebugMode.ts | 6 - Content/Debug/Enums/E_DebugMode.uasset | 3 - Content/Debug/Enums/E_DebugPageID.ts | 8 +- Content/Debug/Enums/E_DebugUpdateFunction.ts | 8 +- Content/Debug/Structs/S_DebugColors.uasset | 3 - Content/Debug/Structs/S_DebugPage.ts | 8 +- Content/Debug/Structs/S_DebugSettings.ts | 9 +- Content/Debug/Structs/S_DebugSettings.uasset | 4 +- Content/Debug/Tables/DT_DebugPages.ts | 39 + Content/Debug/Tables/DT_DebugPages.uasset | 3 + Content/Debug/Tests/FT_DebugNavigation.ts | 112 + Content/Debug/Tests/FT_DebugNavigation.uasset | 3 + .../Tests/FT_DebugPageContentGenerator.ts | 109 + .../Tests/FT_DebugPageContentGenerator.uasset | 3 + Content/Debug/Tests/FT_DebugSystem.ts | 95 + Content/Debug/Tests/FT_DebugSystem.uasset | 3 + Content/Debug/UI/WBP_DebugHUD.ts | 162 +- Content/Debug/UI/WBP_DebugHUD.uasset | 4 +- Content/Debug/UI/WBP_TestResult.uasset | 3 - Content/Input/Actions/IA_LeftTrigger.ts | 7 +- Content/Input/Actions/IA_Look.ts | 6 + Content/Input/Actions/IA_Move.ts | 6 + Content/Input/Actions/IA_NextDebugMode.ts | 6 +- Content/Input/Actions/IA_PrevDebugMode.ts | 6 +- Content/Input/Actions/IA_RightTrigger.ts | 6 +- Content/Input/Actions/IA_ToggleHUD.ts | 6 +- Content/Input/Actions/IA_ToggleVisualDebug.ts | 9 +- Content/Input/Enums/E_InputDeviceType.ts | 7 + Content/Input/IMC_Default.ts | 36 +- Content/Levels/TestLevel.ts | 6 +- Content/Levels/TestLevel.umap | 4 +- Content/Math/Libraries/BFL_Vectors.ts | 85 + Content/Math/Libraries/BFL_Vectors.uasset | 3 + Content/Movement/Components/AC_Movement.ts | 285 +- .../Movement/Components/AC_Movement.uasset | 4 +- Content/Movement/Enums/E_SurfaceType.ts | 12 +- Content/Movement/Structs/S_AngleThresholds.ts | 10 +- .../Movement/Structs/S_MovementConstants.ts | 4 +- Content/Movement/Structs/S_SurfaceTestCase.ts | 6 +- .../Tests/FT_SurfaceClassification.ts | 146 + .../Tests/FT_SurfaceClassification.uasset | 3 + Content/Toasts/Components/AC_ToastSystem.ts | 271 ++ .../Toasts/Components/AC_ToastSystem.uasset | 3 + Content/Toasts/Compontents/AC_ToastSystem.ts | 192 - .../Toasts/Compontents/AC_ToastSystem.uasset | 3 - Content/Toasts/Structs/S_ToastMessage.ts | 8 +- Content/Toasts/Structs/S_ToastSettings.ts | 5 +- Content/Toasts/Tests/FT_ToastLimit.ts | 65 + Content/Toasts/Tests/FT_ToastLimit.uasset | 3 + .../Toasts/Tests/FT_ToastsDurationHandling.ts | 65 + .../Tests/FT_ToastsDurationHandling.uasset | 3 + Content/Toasts/Tests/FT_ToastsEdgeCases.ts | 105 + .../Toasts/Tests/FT_ToastsEdgeCases.uasset | 3 + .../Tests/FT_ToastsSystemInitialization.ts | 54 + .../FT_ToastsSystemInitialization.uasset | 3 + .../Toasts/Tests/FT_ToastsToastCreation.ts | 71 + .../Tests/FT_ToastsToastCreation.uasset | 3 + Content/Toasts/UI/WBP_Toast.ts | 136 +- Content/Toasts/UI/WBP_Toast.uasset | 4 +- Content/Toasts/UI/WBP_ToastContainer.ts | 99 +- Content/Toasts/UI/WBP_ToastContainer.uasset | 4 +- Content/UE/Actor.ts | 10 + Content/UE/ActorComponent.ts | 10 + Content/UE/BlueprintFunctionLibrary.ts | 12 + Content/UE/Border.ts | 16 + Content/UE/Byte.ts | 3 + Content/UE/Cast.ts | 5 + Content/UE/Color.ts | 15 + Content/UE/ContentWidget.ts | 11 + Content/UE/Controller.ts | 15 + Content/UE/CteateWidget.ts | 11 + Content/UE/DataAsset.ts | 10 + Content/UE/DataTable.ts | 41 + Content/UE/DataTableFunctionLibrary.ts | 20 + Content/UE/EFunctionalTestResult.ts | 10 + Content/UE/ESlateVisibility.ts | 9 + Content/UE/EnhancedActionKeyMapping.ts | 29 + .../UE/EnhancedInputLocalPlayerSubsystem.ts | 22 + Content/UE/Float.ts | 3 + Content/UE/FunctionalTest.ts | 21 + Content/UE/GameModeBase.ts | 11 + Content/UE/Info.ts | 11 + Content/UE/InputAction.ts | 11 + Content/UE/InputMappingContext.ts | 26 + Content/UE/InputModifier.ts | 10 + Content/UE/InputTrigger.ts | 10 + Content/UE/Integer.ts | 3 + Content/UE/Key.ts | 18 + Content/UE/LinearColor.ts | 19 + Content/UE/LocalPlayerSubsystem.ts | 11 + Content/UE/MathLibrary.ts | 94 + Content/UE/ModifyContextOptions.ts | 20 + Content/UE/Name.ts | 18 + Content/UE/PanelSlot.ts | 11 + Content/UE/PanelWidget.ts | 17 + Content/UE/Pawn.ts | 11 + Content/UE/PlayerController.ts | 11 + Content/UE/StringLibrary.ts | 18 + Content/UE/StructBase.ts | 11 + Content/UE/Subsystem.ts | 10 + Content/UE/SystemLibrary.ts | 55 + Content/UE/Text.ts | 3 + Content/UE/TextBlock.ts | 20 + Content/UE/TextLayoutWidget.ts | 11 + Content/UE/TextLibrary.ts | 23 + Content/UE/UEArray.ts | 44 + Content/UE/UEObject.ts | 18 + Content/UE/UInt8.ts | 3 + Content/UE/UserWidget.ts | 15 + Content/UE/Vector.ts | 18 + Content/UE/VerticalBox.ts | 11 + Content/UE/Visual.ts | 10 + Content/UE/Widget.ts | 20 + Content/UE/_WrapperBase.ts | 10 + Content/UI/Enums/E_MessageType.ts | 14 +- Content/UI/Libraries/BFL_Colors.ts | 27 + Content/UI/Libraries/BFL_Colors.uasset | 3 + Content/UI/Libraries/FL_Colors.uasset | 3 - Content/classes.ts | 38 - Content/enums.ts | 9 - Content/functions.ts | 86 - Content/types.ts | 14 - package-lock.json | 3634 +++++++++++++++++ package.json | 26 + tsconfig.json | 64 + 135 files changed, 7084 insertions(+), 1237 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.js create mode 100644 .prettierignore create mode 100644 .prettierrc.js create mode 100644 Content/Blueprints/BP_TengriGameMode.ts delete mode 100644 Content/Debug/Enums/E_DebugMode.ts delete mode 100644 Content/Debug/Enums/E_DebugMode.uasset delete mode 100644 Content/Debug/Structs/S_DebugColors.uasset create mode 100644 Content/Debug/Tables/DT_DebugPages.ts create mode 100644 Content/Debug/Tables/DT_DebugPages.uasset create mode 100644 Content/Debug/Tests/FT_DebugNavigation.ts create mode 100644 Content/Debug/Tests/FT_DebugNavigation.uasset create mode 100644 Content/Debug/Tests/FT_DebugPageContentGenerator.ts create mode 100644 Content/Debug/Tests/FT_DebugPageContentGenerator.uasset create mode 100644 Content/Debug/Tests/FT_DebugSystem.ts create mode 100644 Content/Debug/Tests/FT_DebugSystem.uasset delete mode 100644 Content/Debug/UI/WBP_TestResult.uasset create mode 100644 Content/Input/Actions/IA_Look.ts create mode 100644 Content/Input/Actions/IA_Move.ts create mode 100644 Content/Input/Enums/E_InputDeviceType.ts create mode 100644 Content/Math/Libraries/BFL_Vectors.ts create mode 100644 Content/Math/Libraries/BFL_Vectors.uasset create mode 100644 Content/Movement/Tests/FT_SurfaceClassification.ts create mode 100644 Content/Movement/Tests/FT_SurfaceClassification.uasset create mode 100644 Content/Toasts/Components/AC_ToastSystem.ts create mode 100644 Content/Toasts/Components/AC_ToastSystem.uasset delete mode 100644 Content/Toasts/Compontents/AC_ToastSystem.ts delete mode 100644 Content/Toasts/Compontents/AC_ToastSystem.uasset create mode 100644 Content/Toasts/Tests/FT_ToastLimit.ts create mode 100644 Content/Toasts/Tests/FT_ToastLimit.uasset create mode 100644 Content/Toasts/Tests/FT_ToastsDurationHandling.ts create mode 100644 Content/Toasts/Tests/FT_ToastsDurationHandling.uasset create mode 100644 Content/Toasts/Tests/FT_ToastsEdgeCases.ts create mode 100644 Content/Toasts/Tests/FT_ToastsEdgeCases.uasset create mode 100644 Content/Toasts/Tests/FT_ToastsSystemInitialization.ts create mode 100644 Content/Toasts/Tests/FT_ToastsSystemInitialization.uasset create mode 100644 Content/Toasts/Tests/FT_ToastsToastCreation.ts create mode 100644 Content/Toasts/Tests/FT_ToastsToastCreation.uasset create mode 100644 Content/UE/Actor.ts create mode 100644 Content/UE/ActorComponent.ts create mode 100644 Content/UE/BlueprintFunctionLibrary.ts create mode 100644 Content/UE/Border.ts create mode 100644 Content/UE/Byte.ts create mode 100644 Content/UE/Cast.ts create mode 100644 Content/UE/Color.ts create mode 100644 Content/UE/ContentWidget.ts create mode 100644 Content/UE/Controller.ts create mode 100644 Content/UE/CteateWidget.ts create mode 100644 Content/UE/DataAsset.ts create mode 100644 Content/UE/DataTable.ts create mode 100644 Content/UE/DataTableFunctionLibrary.ts create mode 100644 Content/UE/EFunctionalTestResult.ts create mode 100644 Content/UE/ESlateVisibility.ts create mode 100644 Content/UE/EnhancedActionKeyMapping.ts create mode 100644 Content/UE/EnhancedInputLocalPlayerSubsystem.ts create mode 100644 Content/UE/Float.ts create mode 100644 Content/UE/FunctionalTest.ts create mode 100644 Content/UE/GameModeBase.ts create mode 100644 Content/UE/Info.ts create mode 100644 Content/UE/InputAction.ts create mode 100644 Content/UE/InputMappingContext.ts create mode 100644 Content/UE/InputModifier.ts create mode 100644 Content/UE/InputTrigger.ts create mode 100644 Content/UE/Integer.ts create mode 100644 Content/UE/Key.ts create mode 100644 Content/UE/LinearColor.ts create mode 100644 Content/UE/LocalPlayerSubsystem.ts create mode 100644 Content/UE/MathLibrary.ts create mode 100644 Content/UE/ModifyContextOptions.ts create mode 100644 Content/UE/Name.ts create mode 100644 Content/UE/PanelSlot.ts create mode 100644 Content/UE/PanelWidget.ts create mode 100644 Content/UE/Pawn.ts create mode 100644 Content/UE/PlayerController.ts create mode 100644 Content/UE/StringLibrary.ts create mode 100644 Content/UE/StructBase.ts create mode 100644 Content/UE/Subsystem.ts create mode 100644 Content/UE/SystemLibrary.ts create mode 100644 Content/UE/Text.ts create mode 100644 Content/UE/TextBlock.ts create mode 100644 Content/UE/TextLayoutWidget.ts create mode 100644 Content/UE/TextLibrary.ts create mode 100644 Content/UE/UEArray.ts create mode 100644 Content/UE/UEObject.ts create mode 100644 Content/UE/UInt8.ts create mode 100644 Content/UE/UserWidget.ts create mode 100644 Content/UE/Vector.ts create mode 100644 Content/UE/VerticalBox.ts create mode 100644 Content/UE/Visual.ts create mode 100644 Content/UE/Widget.ts create mode 100644 Content/UE/_WrapperBase.ts create mode 100644 Content/UI/Libraries/BFL_Colors.ts create mode 100644 Content/UI/Libraries/BFL_Colors.uasset delete mode 100644 Content/UI/Libraries/FL_Colors.uasset delete mode 100644 Content/classes.ts delete mode 100644 Content/enums.ts delete mode 100644 Content/functions.ts delete mode 100644 Content/types.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 tsconfig.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..33ef8c2 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,40 @@ +# Dependencies +node_modules/ + +# Build outputs +dist/ +build/ +out/ + +# TypeScript declaration files +**/*.d.ts + +# ESLint config files +.eslintrc.js +.eslintrc.cjs + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# IDE files +.vscode/ +.idea/ + +# OS files +.DS_Store +Thumbs.db + +# Temporary files +*.tmp +*.temp + +# Test coverage +coverage/ + +# Package manager files +package-lock.json +yarn.lock diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..752d591 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,181 @@ +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, + plugins: [ + '@typescript-eslint', + 'import', + 'prefer-arrow', + ], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'prettier', // Must be last to override other configs + ], + rules: { + // TypeScript specific + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], + '@typescript-eslint/explicit-function-return-type': 'warn', + '@typescript-eslint/explicit-module-boundary-types': 'warn', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/prefer-nullish-coalescing': 'error', + '@typescript-eslint/prefer-optional-chain': 'error', + '@typescript-eslint/no-unnecessary-type-assertion': 'error', + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/await-thenable': 'error', + '@typescript-eslint/require-await': 'error', + '@typescript-eslint/no-misused-promises': 'error', + + // Import rules + 'import/order': ['error', { + 'groups': [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + ], + 'pathGroups': [ + { + 'pattern': '#root/**', + 'group': 'internal', + 'position': 'before' + } + ], + 'pathGroupsExcludedImportTypes': ['builtin'], + 'newlines-between': 'never', + 'alphabetize': { + 'order': 'asc', + 'caseInsensitive': true + } + }], + 'import/no-unresolved': 'error', + 'import/extensions': ['error', 'always', { + 'ts': 'always', + 'js': 'always' + }], + + // General code quality + 'no-console': 'off', // Allowed for game development + 'no-debugger': 'warn', + 'no-unused-vars': 'off', // Use TypeScript version instead + 'prefer-const': 'error', + 'no-var': 'error', + 'object-shorthand': 'error', + 'prefer-template': 'error', + 'prefer-arrow-callback': 'error', + 'arrow-body-style': ['error', 'as-needed'], + + // Stylistic (handled by Prettier, but some logical ones) + 'curly': ['error', 'all'], + 'brace-style': 'off', // Prettier handles this + 'comma-dangle': 'off', // Prettier handles this + 'quotes': 'off', // Prettier handles this + 'semi': 'off', // Prettier handles this + + // Best practices + 'eqeqeq': ['error', 'always'], + 'no-eval': 'error', + 'no-implied-eval': 'error', + 'no-new-wrappers': 'error', + 'no-throw-literal': 'error', + 'no-return-await': 'error', + + // Complexity + 'complexity': ['warn', 10], + 'max-lines': ['warn', { max: 500, skipBlankLines: true, skipComments: true }], + 'max-lines-per-function': ['warn', { max: 100, skipBlankLines: true, skipComments: true }], + + // Naming conventions + '@typescript-eslint/naming-convention': [ + 'error', + { + 'selector': 'default', + 'format': ['PascalCase', 'camelCase'] + }, + { + 'selector': 'function', + 'format': ['PascalCase', 'camelCase'] + }, + { + 'selector': 'variable', + 'format': ['camelCase', 'UPPER_CASE', 'PascalCase'], + 'prefix': ['_', 'BP_', 'AC_', 'WBP_', 'UBP_', 'ABP_', 'IMC_', 'IA_', 'DT_', 'BFL_', 'U', 'A', 'T', 'F'] + }, + { + 'selector': 'variable', + 'format': ['camelCase', 'UPPER_CASE', 'PascalCase'], + 'filter': { + 'regex': '^(?!_|BP_|AC_|WBP_|UBP_|ABP_|IA_|DT_|IMC_|BFL_|U[A-Z]|A[A-Z]|T[A-Z]|F[A-Z])', + 'match': true + } + }, + // Unreal Engine classes with prefixes + { + 'selector': 'class', + 'format': ['PascalCase'], + 'prefix': ['_', 'BP_', 'AC_', 'WBP_', 'UBP_', 'ABP_', 'IMC_', 'IA_', 'DT_', 'FT_', 'BFL_', 'U', 'A', 'T', 'F'] + }, + // Regular classes without prefix + { + 'selector': 'class', + 'format': ['PascalCase'], + 'filter': { + 'regex': '^(?!_|BP_|AC_|WBP_|UBP_|ABP_|IA_|IMC_|BFL_|U[A-Z]|A[A-Z]|T[A-Z]|F[A-Z])', + 'match': true + } + }, + // Interfaces and Structs + { + 'selector': 'interface', + 'format': ['PascalCase'], + 'prefix': ['S_', 'I_', 'I'] + }, + // Enums + { + 'selector': 'enum', + 'format': ['PascalCase'], + 'prefix': ['E_', 'E'] + }, + { + 'selector': 'enumMember', + 'format': ['PascalCase'] + } + ], + + '@typescript-eslint/no-unsafe-member-access': 'off' + }, + settings: { + 'import/resolver': { + 'typescript': { + 'alwaysTryTypes': true, + 'project': './tsconfig.json' + }, + 'node': { + 'extensions': ['.js', '.ts', '.json'] + } + }, + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'] + } + }, + env: { + browser: true, + es2022: true, + node: true, + }, + ignorePatterns: [ + 'node_modules/', + 'dist/', + 'build/', + '**/*.d.ts' + ] +}; diff --git a/.gitignore b/.gitignore index de151b3..a48850b 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,13 @@ !/Config/** !/Plugins/** !/Documentation/** +!/.eslintignore +!/.eslintrc.js +!/.prettierignore +!/.prettierrc.js +!/package.json +!/package-lock.json +!/tsconfig.json # Only allow .uasset, .umap and .ts files from /Content dir. # .uasset and .umap tracked by git-lfs, don't forget to track diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a2eaf5b --- /dev/null +++ b/.prettierignore @@ -0,0 +1,26 @@ +# Dependencies +node_modules/ + +# Build outputs +dist/ +build/ +out/ + +# Logs +logs +*.log + +# IDE files +.vscode/ +.idea/ + +# OS files +.DS_Store +Thumbs.db + +# Package manager files +package-lock.json +yarn.lock + +# Generated files +**/*.d.ts diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..bc61afe --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,44 @@ +module.exports = { + // Basic formatting + printWidth: 80, + tabWidth: 2, + useTabs: false, + semi: true, + singleQuote: true, + quoteProps: 'as-needed', + trailingComma: 'es5', + bracketSpacing: true, + bracketSameLine: false, + arrowParens: 'avoid', + + // Line endings + endOfLine: 'lf', + + // TypeScript specific + parser: 'typescript', + + // File-specific overrides + overrides: [ + { + files: '*.json', + options: { + parser: 'json', + printWidth: 100, + }, + }, + { + files: '*.md', + options: { + parser: 'markdown', + printWidth: 100, + proseWrap: 'always', + }, + }, + { + files: '*.{js,ts}', + options: { + parser: 'typescript', + }, + }, + ], +}; diff --git a/Content/Blueprints/BP_MainCharacter.ts b/Content/Blueprints/BP_MainCharacter.ts index 8ae3a9b..ee34f7c 100644 --- a/Content/Blueprints/BP_MainCharacter.ts +++ b/Content/Blueprints/BP_MainCharacter.ts @@ -1,76 +1,129 @@ -// Content/Blueprints/BP_MainCharacter.ts +// Blueprints/BP_MainCharacter.ts -import {AC_Movement} from "../Movement/Components/AC_Movement.js"; -import type {Controller, Float} from "../types.js"; -import { - AddMappingContext, - CastToPlayController, - EnhancedInputLocalPlayerSubsystem, - GetGameTimeInSeconds, -} from "../functions.js"; -import {IMC_Default} from "../Input/IMC_Default.js"; -import {AC_DebugHUD} from "../Debug/Components/AC_DebugHUD.js"; -import {AC_ToastSystem} from "../Toasts/Compontents/AC_ToastSystem.js"; +import { AC_DebugHUD } from '#root/Debug/Components/AC_DebugHUD.ts'; +import { IMC_Default } from '#root/Input/IMC_Default.ts'; +import { AC_Movement } from '#root/Movement/Components/AC_Movement.ts'; +import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { Cast } from '#root/UE/Cast.ts'; +import type { Controller } from '#root/UE/Controller.ts'; +import { EnhancedInputLocalPlayerSubsystem } from '#root/UE/EnhancedInputLocalPlayerSubsystem.ts'; +import type { Float } from '#root/UE/Float.ts'; +import { Pawn } from '#root/UE/Pawn.ts'; +import type { PlayerController } from '#root/UE/PlayerController.ts'; +import { SystemLibrary } from '#root/UE/SystemLibrary.ts'; -export class BP_MainCharacter { - // Category: "Components" - MovementComponent = new AC_Movement(); - - // Category: "Components" - DebugHUDComponent = new AC_DebugHUD(); - - // Category: "Components" - ToastSystemComponent = new AC_ToastSystem(); - - // Category: "Debug" - // Instance Editable: true - ShowDebugInfo: boolean = true; +/** + * Main Character Blueprint + * Core player character with deterministic movement system + * Integrates debug HUD and toast notification systems + */ +export class BP_MainCharacter extends Pawn { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + // ──────────────────────────────────────────────────────────────────────────────────────── // EventGraph - EventReceiveControllerChanged(NewController: Controller): void { - const AsPlayerController = CastToPlayController(NewController); - const Target = EnhancedInputLocalPlayerSubsystem(AsPlayerController); + // ──────────────────────────────────────────────────────────────────────────────────────── - AddMappingContext(Target, IMC_Default); + /** + * Handle controller change events - sets up Enhanced Input mapping context + */ + EventReceiveControllerChanged(NewController: Controller): void { + const controller = Cast(NewController); + const system = new EnhancedInputLocalPlayerSubsystem(); + + if (controller) { + system.AddMappingContext(IMC_Default); + } } - EnhancedInputActionIA_PrevDebugMode() { + /** Navigate to previous debug page */ + EnhancedInputActionPrevDebugMode(): void { if (this.ShowDebugInfo) { this.DebugHUDComponent.PreviousPage(); } } - EnhancedInputActionIA_NextDebugMode() { + /** Navigate to next debug page */ + EnhancedInputActionINextDebugMode(): void { if (this.ShowDebugInfo) { this.DebugHUDComponent.NextPage(); } } - EnhancedInputActionToggleHUD() { + /** Toggle debug HUD visibility */ + EnhancedInputActionToggleHUD(): void { if (this.ShowDebugInfo) { this.DebugHUDComponent.ToggleDebugHUD(); } } - EnhancedInputActionIA_ToggleVisualDebug() { + /** Toggle visual debug rendering */ + EnhancedInputActionToggleVisualDebug(): void { if (this.ShowDebugInfo) { this.DebugHUDComponent.ToggleVisualDebug(); } } - EventBeginPlay() { - this.MovementComponent.InitializeMovementSystem(); - + /** + * Initialize all systems when character spawns + * Order: Toast → Debug → Movement (movement last as it may generate debug output) + */ + EventBeginPlay(): void { + // Initialize debug systems first if enabled if (this.ShowDebugInfo) { - this.DebugHUDComponent.InitializeDebugHUD(this.MovementComponent); this.ToastSystemComponent.InitializeToastSystem(); + this.DebugHUDComponent.InitializeDebugHUD( + this.MovementComponent, + this.ToastSystemComponent + ); } + + // Initialize movement system last (may generate debug output) + this.MovementComponent.InitializeMovementSystem(); } + /** + * Update all systems each frame + * Called by Unreal Engine game loop + */ EventTick(DeltaTime: Float): void { if (this.ShowDebugInfo) { - this.DebugHUDComponent.UpdateHUD(GetGameTimeInSeconds(), DeltaTime); + this.DebugHUDComponent.UpdateHUD( + SystemLibrary.GetGameTimeInSeconds(), + DeltaTime + ); this.ToastSystemComponent.UpdateToastSystem(); } } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Core movement system component - handles deterministic 3D platformer movement + * @category Components + */ + MovementComponent = new AC_Movement(); + + /** + * Debug HUD system - displays movement parameters and performance metrics + * @category Components + */ + DebugHUDComponent = new AC_DebugHUD(); + + /** + * Toast notification system - displays temporary status messages + * @category Components + */ + ToastSystemComponent = new AC_ToastSystem(); + + /** + * Master debug toggle - controls all debug systems (HUD, toasts, visual debug) + * @category Debug + * @instanceEditable true + */ + private ShowDebugInfo: boolean = true; } diff --git a/Content/Blueprints/BP_MainCharacter.uasset b/Content/Blueprints/BP_MainCharacter.uasset index cac4230..1dfb741 100644 --- a/Content/Blueprints/BP_MainCharacter.uasset +++ b/Content/Blueprints/BP_MainCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e09fd6d3d58d6f97356b42eee1a717a66298efc42cebe5b396983ed01578c3ac -size 240058 +oid sha256:210049f448ff6be2ea15d41fa673818dc6e9bd6a3d071f1bbeb1c33a24298e3e +size 241250 diff --git a/Content/Blueprints/BP_TengriGameMode.ts b/Content/Blueprints/BP_TengriGameMode.ts new file mode 100644 index 0000000..0f2e7d9 --- /dev/null +++ b/Content/Blueprints/BP_TengriGameMode.ts @@ -0,0 +1,8 @@ +// Blueprints/BP_TengriGameMode.ts + +import { BP_MainCharacter } from '#root/Blueprints/BP_MainCharacter.ts'; +import { GameModeBase } from '#root/UE/GameModeBase.ts'; + +export class BP_TengriGameMode extends GameModeBase { + DefaultPawnClass = BP_MainCharacter; +} diff --git a/Content/Debug/Components/AC_DebugHUD.ts b/Content/Debug/Components/AC_DebugHUD.ts index b3275b5..fa2182f 100644 --- a/Content/Debug/Components/AC_DebugHUD.ts +++ b/Content/Debug/Components/AC_DebugHUD.ts @@ -1,123 +1,81 @@ -// Content/Debug/Components/AC_DebugHUD.ts +// Debug/Components/AC_DebugHUD.ts -import type {AC_Movement} from "../../Movement/Components/AC_Movement.js"; -import type {Float, Integer} from "../../types.js"; -import type {S_DebugPage} from "../Structs/S_DebugPage.js"; -import {AddToArray, CreateWidget, GetFromArray, IsValid, Print, SetArrayElem} from "../../functions.js"; -import {E_DebugPageID} from "../Enums/E_DebugPageID.js"; -import {E_DebugUpdateFunction} from "../Enums/E_DebugUpdateFunction.js"; -import {WBP_DebugHUD} from "../UI/WBP_DebugHUD.js"; -import type {S_DebugSettings} from "../Structs/S_DebugSettings.js"; -import {E_DebugMode} from "../Enums/E_DebugMode.js"; -import {ESlateVisibility} from "../../enums.js"; +import { E_DebugUpdateFunction } from '#root/Debug/Enums/E_DebugUpdateFunction.ts'; +import type { S_DebugPage } from '#root/Debug/Structs/S_DebugPage.ts'; +import type { S_DebugSettings } from '#root/Debug/Structs/S_DebugSettings.ts'; +import { DT_DebugPages } from '#root/Debug/Tables/DT_DebugPages.ts'; +import { WBP_DebugHUD } from '#root/Debug/UI/WBP_DebugHUD.ts'; +import type { AC_Movement } from '#root/Movement/Components/AC_Movement.ts'; +import type { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { ActorComponent } from '#root/UE/ActorComponent.ts'; +import { CreateWidget } from '#root/UE/CteateWidget.ts'; +import type { DataTable } from '#root/UE/DataTable.ts'; +import { DataTableFunctionLibrary } from '#root/UE/DataTableFunctionLibrary.ts'; +import { ESlateVisibility } from '#root/UE/ESlateVisibility.ts'; +import type { Float } from '#root/UE/Float.ts'; +import type { Integer } from '#root/UE/Integer.ts'; +import { SystemLibrary } from '#root/UE/SystemLibrary.ts'; +import { UEArray } from '#root/UE/UEArray.ts'; +import { E_MessageType } from '#root/UI/Enums/E_MessageType.ts'; /** * Debug HUD Controller Component * Manages debug information display system for deterministic movement * Provides real-time performance monitoring and parameter visualization - * Part of Stage 2: Debug HUD system implementation */ -export class AC_DebugHUD { - // Category: "DebugConfig" - // Instance Editable: true - /** - * Debug system configuration settings - * Controls visibility, update frequency, and current page - * Instance editable for designer customization - */ - public DebugSettings: S_DebugSettings = { - CurrentMode: E_DebugMode.Visible, - CurrentPageIndex: 0, - ShowVisualDebug: false, - UpdateFrequency: 0.0, - } +export class AC_DebugHUD extends ActorComponent { + // ════════════════════════════════════════════════════════════════════════════════════════ + // FUNCTIONS + // ════════════════════════════════════════════════════════════════════════════════════════ - // Category: "DebugState" - /** - * System initialization state flag - * Set to true after successful InitializeDebugHUD call - */ - private IsInitialized: boolean = false; - - // Category: "DebugState" - /** - * Timestamp of last HUD update (seconds) - * Used for update frequency control - */ - private LastUpdateTime: Float = 0; - - // Category: "DebugState" - /** - * Current frame counter for performance tracking - * Incremented each update cycle - */ - private FrameCounter: Float = 0; - - // Category: "DebugState" - /** - * Current frames per second calculation - * Calculated as 1.0 / DeltaTime - */ - private FPS: Float = 0; - - // Category: "DebugState" - /** - * Reference to movement component being debugged - * Set during initialization, used for accessing movement data - */ - private MovementComponent: AC_Movement | null = null; - - // Category: "Widget Control" - /** - * Debug HUD widget instance - * Created during initialization, manages UI display - */ - private DebugWidget: WBP_DebugHUD | null = null; - - // Category: "Page System" - /** - * Array of registered debug pages - * Contains all available pages with their data and update functions - */ - private DebugPages: S_DebugPage[] = []; - - // Category: "HUD Control" - // Pure: true /** * Check if debug HUD should be visible * @returns True if system is initialized and mode is visible - * @pure Function has no side effects + * @category HUD Control + * @pure true */ - private ShouldShowDebugHUD() { - return this.IsInitialized && this.DebugSettings.CurrentMode === E_DebugMode.Visible; + private ShouldShowDebugHUD(): boolean { + const IsSystemReadyAndVisible = (modeIsVisible: boolean): boolean => + this.IsInitialized && modeIsVisible; + + return IsSystemReadyAndVisible( + this.DebugSettings.CurrentMode === ESlateVisibility.Visible + ); } - // Category: "HUD Control" - // Pure: true /** * Check if debug HUD should update this frame - * @param CurrentTime - Current game time in seconds - * @returns True if enough time has passed since last update - * @pure Function has no side effects * @example * // Update every frame (UpdateFrequency = 0) * ShouldUpdateDebugHUD(gameTime) // returns true * // Update at 30Hz (UpdateFrequency = 30) * ShouldUpdateDebugHUD(gameTime) // returns true every 1/30 seconds + * @param CurrentTime - Current game time in seconds + * @returns True if enough time has passed since last update + * @pure true + * @category HUD Control */ - private ShouldUpdateDebugHUD(CurrentTime: Float): boolean { - if (this.DebugSettings.UpdateFrequency <= 0) { - return true; // Update every frame + private ShouldUpdateDebugHUD(CurrentTime: Float = 0): boolean { + const IsFrequencyLimited = (updateFrequency: Float): boolean => + updateFrequency > 0; + + const IsUpdateIntervalReached = ( + currentTime: Float, + updateFrequency: Float + ): boolean => currentTime - this.LastUpdateTime >= 1 / updateFrequency; + + if (IsFrequencyLimited(this.DebugSettings.UpdateFrequency)) { + return IsUpdateIntervalReached( + CurrentTime, + this.DebugSettings.UpdateFrequency + ); } else { - return (CurrentTime - this.LastUpdateTime) >= (1.0 / this.DebugSettings.UpdateFrequency); + return true; // Update every frame } } - // Category: "Page Management" /** * Register or update a debug page in the system - * @param PageData - Page configuration and content data - * @private Internal page management method * @example * // Register movement constants page * RegisterDebugPage({ @@ -127,279 +85,333 @@ export class AC_DebugHUD { * IsVisible: true, * UpdateFunction: E_DebugUpdateFunction.UpdateMovementPage * }) + * @param PageData - Page configuration and content data + * @category Page Management */ private RegisterDebugPage(PageData: S_DebugPage): void { let existingIndex: Integer = -1; this.DebugPages.forEach((page, index) => { if (page.PageID === PageData.PageID) { - this.DebugPages[index] = PageData; + existingIndex = index; return; } - }) + }); - if (existingIndex >= 0) { - SetArrayElem(this.DebugPages, existingIndex, PageData); - } else{ - AddToArray(this.DebugPages, PageData); + const IsPageExists = (): boolean => existingIndex >= 0; + + if (IsPageExists()) { + this.DebugPages.SetArrayElem(existingIndex, PageData); + } else { + this.DebugPages.Add(PageData); } } - // Category: "Page Management" - // Pure: true /** * Get all currently visible debug pages * @returns Array of visible pages only - * @pure Function has no side effects + * @category Page Management + * @pure true */ - private GetVisiblePages(): S_DebugPage[] { - const filteredPages: S_DebugPage[] = []; + public GetVisiblePages(): UEArray { + const filteredPages: UEArray = new UEArray([]); - this.DebugPages.forEach((page) => { + this.DebugPages.forEach(page => { if (page.IsVisible) { - AddToArray(filteredPages, page); + filteredPages.Add(page); } - }) + }); return filteredPages; } - // Category: "Page Management" /** * Get currently selected debug page * @returns Object with page data and validity flag - * @pure Function has no side effects + * @category Page Management + * @pure true */ - private GetCurrentPage(): {Page: S_DebugPage | null, IsFound: boolean} { - const length = this.GetVisiblePages().length; + private GetCurrentPage(): + | { Page: S_DebugPage | null; IsFound: true } + | { Page: null; IsFound: false } { + const IsPageIndexInvalid = ( + length: Integer, + currentPageIndex: Integer + ): boolean => length === 0 || currentPageIndex >= length; - if (!((length === 0) || (this.DebugSettings.CurrentPageIndex >= length))) { - return {Page: GetFromArray(this.DebugPages, this.DebugSettings.CurrentPageIndex), IsFound: true}; - } else { - return {Page: null, IsFound: false}; - } + return IsPageIndexInvalid( + this.GetVisiblePages().length, + this.DebugSettings.CurrentPageIndex + ) + ? { Page: null, IsFound: false } + : { + Page: this.GetVisiblePages().Get(this.DebugSettings.CurrentPageIndex), + IsFound: true, + }; } - // Category: "Navigation" /** * Toggle debug HUD visibility between visible and hidden - * @public User input handler for F1 key or similar + * @category Navigation */ - public ToggleDebugHUD() { - this.DebugSettings.CurrentMode = this.DebugSettings.CurrentMode === E_DebugMode.Visible ? E_DebugMode.Hidden : E_DebugMode.Visible; + public ToggleDebugHUD(): void { + this.DebugSettings.CurrentMode = + this.DebugSettings.CurrentMode === ESlateVisibility.Visible + ? ESlateVisibility.Hidden + : ESlateVisibility.Visible; + this.UpdateWidgetVisibility(); } - // Category: "Navigation" /** * Navigate to previous debug page * Wraps around to last page if at beginning - * @public User input handler for PageUp key + * @category Navigation */ - public PreviousPage() { + public PreviousPage(): void { const length = this.GetVisiblePages().length; if (length > 1) { const currentPage = this.DebugSettings.CurrentPageIndex; - this.DebugSettings.CurrentPageIndex = currentPage - 1 < 0 ? length - 1 : currentPage - 1; + const isAtFirstPage = (): boolean => currentPage - 1 < 0; + const getLastPageIndex = (): Integer => length - 1; + const getPreviousPageIndex = (): Integer => currentPage - 1; + + this.DebugSettings.CurrentPageIndex = isAtFirstPage() + ? getLastPageIndex() + : getPreviousPageIndex(); + + this.UpdateCurrentPage(); } } - // Category: "Navigation" /** * Navigate to next debug page * Wraps around to first page if at end - * @public User input handler for PageDown key + * @category Navigation */ - public NextPage() { + public NextPage(): void { const length = this.GetVisiblePages().length; - if (length > 1) { - this.DebugSettings.CurrentPageIndex = (this.DebugSettings.CurrentPageIndex + 1) % length; + const HasMultiplePages = (): boolean => length > 1; + const GetNextPageIndex = (currentPageIndex: Integer): Integer => + (currentPageIndex + 1) % length; + + if (HasMultiplePages()) { + this.DebugSettings.CurrentPageIndex = GetNextPageIndex( + this.DebugSettings.CurrentPageIndex + ); + + this.UpdateCurrentPage(); } } - // Category: "Visual Debug" /** * Toggle visual debug rendering (collision shapes, rays, etc.) - * @public User input handler for visual debug toggle + * @category Visual Debug */ - public ToggleVisualDebug() { + public ToggleVisualDebug(): void { this.DebugSettings.ShowVisualDebug = !this.DebugSettings.ShowVisualDebug; + + if (SystemLibrary.IsValid(this.ToastComponent)) { + this.ToastComponent.ShowToast( + `Visual Debug ${this.DebugSettings.ShowVisualDebug ? 'Enabled' : 'Disabled'}` + ); + } } - // Category: "Page Updates" /** * Update content of currently selected page * Calls appropriate update function based on page type - * @private Internal update system method + * @category Page Updates */ - private UpdateCurrentPage() { - const {Page, IsFound}: {Page: S_DebugPage, IsFound: boolean} = this.GetCurrentPage(); - let CurrentPage = Page; + private UpdateCurrentPage(): void { + let CurrentPage = this.GetCurrentPage().Page; - if (IsFound) { + if (this.GetCurrentPage().IsFound && CurrentPage !== null) { switch (CurrentPage.UpdateFunction) { - case E_DebugUpdateFunction.UpdateMovementPage: + case E_DebugUpdateFunction.UpdateMovementPage: { CurrentPage = this.UpdateMovementPage(CurrentPage); break; - case E_DebugUpdateFunction.UpdateSurfacePage: + } + case E_DebugUpdateFunction.UpdateSurfacePage: { CurrentPage = this.UpdateSurfacePage(CurrentPage); break; - case E_DebugUpdateFunction.UpdatePerformancePage: + } + case E_DebugUpdateFunction.UpdatePerformancePage: { CurrentPage = this.UpdatePerformancePage(CurrentPage); - break; + } } - SetArrayElem(this.DebugPages, this.DebugSettings.CurrentPageIndex, CurrentPage); + this.DebugPages.SetArrayElem( + this.DebugSettings.CurrentPageIndex, + CurrentPage + ); + this.UpdateWidgetPage(); } } - // Category: "Page Updates" /** * Update movement constants page content * @param Page - Page structure to update * @returns Updated page with current movement data - * @private Page-specific update method + * @category Page Updates */ - private UpdateMovementPage(Page: S_DebugPage): S_DebugPage { - if (IsValid(this.MovementComponent)) { + public UpdateMovementPage(Page: S_DebugPage): S_DebugPage { + if (SystemLibrary.IsValid(this.MovementComponent)) { return { PageID: Page.PageID, Title: Page.Title, - Content: `Max Speed: ${this.MovementComponent.MovementConstants.MaxSpeed}\n` + - `Acceleration: ${this.MovementComponent.MovementConstants.Acceleration}\n` + - `Friction: ${this.MovementComponent.MovementConstants.Friction}\n` + - `Gravity: ${this.MovementComponent.MovementConstants.Gravity}`, + Content: + `Max Speed: ${this.MovementComponent.MovementConstants.MaxSpeed}\n` + + `Acceleration: ${this.MovementComponent.MovementConstants.Acceleration}\n` + + `Friction: ${this.MovementComponent.MovementConstants.Friction}\n` + + `Gravity: ${this.MovementComponent.MovementConstants.Gravity}`, IsVisible: Page.IsVisible, - UpdateFunction: Page.UpdateFunction - } + UpdateFunction: Page.UpdateFunction, + }; } else { return { PageID: Page.PageID, Title: Page.Title, Content: 'Movement Component Not Found', IsVisible: Page.IsVisible, - UpdateFunction: Page.UpdateFunction - } + UpdateFunction: Page.UpdateFunction, + }; } } - // Category: "Page Updates" /** * Update surface classification page content * @param Page - Page structure to update * @returns Updated page with current surface angle thresholds - * @private Page-specific update method + * @category Page Updates */ - private UpdateSurfacePage(Page: S_DebugPage): S_DebugPage { - if (IsValid(this.MovementComponent)) { + public UpdateSurfacePage(Page: S_DebugPage): S_DebugPage { + if (SystemLibrary.IsValid(this.MovementComponent)) { return { PageID: Page.PageID, Title: Page.Title, - Content: `Walkable: ≤${this.MovementComponent.AngleThresholdsDegrees.Walkable}°\n` + + Content: + `Walkable: ≤${this.MovementComponent.AngleThresholdsDegrees.Walkable}°\n` + `Steep Slope: ${this.MovementComponent.AngleThresholdsDegrees.Walkable}°-${this.MovementComponent.AngleThresholdsDegrees.SteepSlope}°\n` + `Wall: ${this.MovementComponent.AngleThresholdsDegrees.SteepSlope}°-${this.MovementComponent.AngleThresholdsDegrees.Wall}°\n` + `Ceiling: >${this.MovementComponent.AngleThresholdsDegrees.Wall}°`, IsVisible: Page.IsVisible, - UpdateFunction: Page.UpdateFunction - } + UpdateFunction: Page.UpdateFunction, + }; } else { return { PageID: Page.PageID, Title: Page.Title, Content: 'Movement Component Not Found', IsVisible: Page.IsVisible, - UpdateFunction: Page.UpdateFunction - } + UpdateFunction: Page.UpdateFunction, + }; } } - // Category: "Page Updates" /** * Update performance metrics page content * @param Page - Page structure to update * @returns Updated page with current performance data - * @private Page-specific update method + * @category Page Updates */ - private UpdatePerformancePage(Page: S_DebugPage): S_DebugPage { - if (IsValid(this.MovementComponent)) { + public UpdatePerformancePage(Page: S_DebugPage): S_DebugPage { + if (SystemLibrary.IsValid(this.MovementComponent)) { + const IsUpdatingEveryFrame = (updateFrequency: Float): boolean => + updateFrequency <= 0; + return { PageID: Page.PageID, Title: Page.Title, - Content: `Frame: ${this.FrameCounter}\n` + + Content: + `Frame: ${this.FrameCounter}\n` + `FPS: ${this.FPS}\n` + - `Update Rate: ${this.DebugSettings.UpdateFrequency <= 0 ? 'Every Frame' : (this.DebugSettings.UpdateFrequency + ' Hz')}\n` + + `Update Rate: ${IsUpdatingEveryFrame(this.DebugSettings.UpdateFrequency) ? 'Every Frame' : `${this.DebugSettings.UpdateFrequency} Hz`}\n` + `ActivePages: ${this.GetVisiblePages().length}`, IsVisible: Page.IsVisible, - UpdateFunction: Page.UpdateFunction - } + UpdateFunction: Page.UpdateFunction, + }; } else { return { PageID: Page.PageID, Title: Page.Title, Content: 'Movement Component Not Found', IsVisible: Page.IsVisible, - UpdateFunction: Page.UpdateFunction + UpdateFunction: Page.UpdateFunction, + }; + } + } + + /** + * Create debug widget instance and add to viewport + * @category Widget Control + */ + private CreateDebugWidget(): void { + this.DebugWidget = CreateWidget(WBP_DebugHUD); + this.DebugWidget.MovementComponent = this.MovementComponent; + + if (SystemLibrary.IsValid(this.DebugWidget)) { + this.DebugWidget.AddToViewport(); + } else { + if (SystemLibrary.IsValid(this.ToastComponent)) { + this.ToastComponent.ShowToast('Failed to create debug widget'); } } } - // Category: "Widget Control" - /** - * Create debug widget instance and add to viewport - * @private Internal widget management method - */ - private CreateDebugWidget() { - this.DebugWidget = CreateWidget(new WBP_DebugHUD); - this.DebugWidget.MovementComponent = this.MovementComponent; - - if (IsValid(this.DebugWidget)) { - this.DebugWidget.AddToViewport(); - } else { - Print('Failed to create debug widget'); - } - } - - // Category: "Widget Control" /** * Update widget visibility based on current debug mode - * @private Internal widget management method + * @category Widget Control */ - private UpdateWidgetVisibility() { - if (IsValid(this.DebugWidget)) { - this.DebugWidget.SetVisibility(this.ShouldShowDebugHUD() ? ESlateVisibility.Visible : ESlateVisibility.Hidden); + private UpdateWidgetVisibility(): void { + if (SystemLibrary.IsValid(this.DebugWidget)) { + this.DebugWidget.SetVisibility( + this.ShouldShowDebugHUD() + ? ESlateVisibility.Visible + : ESlateVisibility.Hidden + ); } } - // Category: "Widget Communication" /** * Send current page data to debug widget for display - * @private Internal widget communication method + * @category Widget Communication */ - private UpdateWidgetPage() { - const {Page, IsFound} = this.GetCurrentPage(); + private UpdateWidgetPage(): void { + if ( + this.GetCurrentPage().IsFound && + SystemLibrary.IsValid(this.DebugWidget) + ) { + const currentPage = this.GetCurrentPage().Page; + const visiblePages = this.GetVisiblePages(); - if (IsFound) { - this.DebugWidget.SetHeaderText(Page.Title); - this.DebugWidget.SetContentText(Page.Content); - this.DebugWidget.SetNavigationText(`Page ${this.DebugSettings.CurrentPageIndex + 1}/${this.GetVisiblePages().length} | PageUp/PageDown - Navigate`); + this.DebugWidget.SetHeaderText(currentPage!.Title); + this.DebugWidget.SetContentText(currentPage!.Content); + this.DebugWidget.SetNavigationText( + `Page ${this.DebugSettings.CurrentPageIndex + 1}/${visiblePages.length} | PageUp/PageDown - Navigate` + ); } } - // Category: "HUD Rendering" /** * Main update loop for debug HUD system * Called every frame from game loop * @param CurrentTime - Current game time in seconds * @param DeltaTime - Time since last frame in seconds - * @public Called by BP_MainCharacter or game framework + * @category HUD Rendering */ - public UpdateHUD(CurrentTime: Float, DeltaTime: Float) { - if (this.IsInitialized && this.ShouldUpdateDebugHUD(CurrentTime)) { + public UpdateHUD(CurrentTime: Float, DeltaTime: Float): void { + const IsReadyForUpdate = (shouldUpdateHUD: boolean): boolean => + this.IsInitialized && shouldUpdateHUD; + const IsValidDeltaTime = (deltaTime: Float): boolean => deltaTime > 0; + const CalculateFPS = (deltaTime: Float): Float => 1 / deltaTime; + + if (IsReadyForUpdate(this.ShouldUpdateDebugHUD(CurrentTime))) { this.FrameCounter++; - this.FPS = DeltaTime > 0.0 ? 1.0 / DeltaTime : 0.0; + this.FPS = IsValidDeltaTime(DeltaTime) ? CalculateFPS(DeltaTime) : 0; this.LastUpdateTime = CurrentTime; if (this.ShouldShowDebugHUD()) { @@ -409,223 +421,146 @@ export class AC_DebugHUD { } } - // Category: "System Setup" /** * Register default debug pages (Movement, Surface, Performance) - * @private Internal system setup method + * @category System Setup */ - private RegisterDefaultPages() { - this.RegisterDebugPage({ - PageID: E_DebugPageID.MovementInfo, - Title: "Movement Constants", - Content: '', - IsVisible: true, - UpdateFunction: E_DebugUpdateFunction.UpdateMovementPage - }); - - this.RegisterDebugPage({ - PageID: E_DebugPageID.SurfaceInfo, - Title: "Surface Classification", - Content: '', - IsVisible: true, - UpdateFunction: E_DebugUpdateFunction.UpdateSurfacePage - }); - - this.RegisterDebugPage({ - PageID: E_DebugPageID.PerformanceInfo, - Title: "Performance Metrics", - Content: '', - IsVisible: true, - UpdateFunction: E_DebugUpdateFunction.UpdatePerformancePage - }); - } - - // Category: "Testing" - /** - * Test basic debug system functionality - * @returns True if all basic tests pass - * @private Internal testing method - */ - private TestDebugSystem() { - Print('=== DEBUG SYSTEM TESTS ==='); - - if (this.IsInitialized) { - Print('✅ System initialized'); - - if (this.DebugPages.length === 3) { - Print('✅ All pages registered'); - - if (IsValid(this.MovementComponent)) { - Print('✅ Movement component valid'); - - if (IsValid(this.DebugWidget)) { - Print('✅ Debug widget created'); - Print('✅ ALL TESTS PASSED'); - return true; - } else { - Print('❌ Debug widget not created'); - return false; - } - } else { - Print('❌ Movement component not valid'); - return false; - } - } else { - Print(`❌ Expected 3 pages, got ${this.DebugPages.length}`); - return false; + private RegisterDefaultPages(): void { + DataTableFunctionLibrary.GetDataTableRowNames(this.DebugDataTable).forEach( + arrayElement => { + this.DebugDataTable.GetDataTableRow(arrayElement, row => { + this.RegisterDebugPage(row); + }); } - } else { - Print('❌ System not initialized'); - return false; - } + ); } - // Category: "Testing" /** - * Test page content generation for all registered pages - * @returns True if all pages generate non-empty content - * @private Internal testing method + * Get comprehensive test data for debug system validation + * @returns Object containing initialization status, DataTable reference, and pages array + * @category Testing */ - private TestPageContentGeneration() { - let allTestsPassed = true; - - this.DebugPages.forEach((page, index) => { - let updatedPage: S_DebugPage = page; - - switch (updatedPage.UpdateFunction) { - case E_DebugUpdateFunction.UpdateMovementPage: - updatedPage = this.UpdateMovementPage(updatedPage); - break; - case E_DebugUpdateFunction.UpdateSurfacePage: - updatedPage = this.UpdateSurfacePage(updatedPage); - break; - case E_DebugUpdateFunction.UpdatePerformancePage: - updatedPage = this.UpdatePerformancePage(updatedPage); - break; - } - - if (updatedPage.Content.length > 0) { - Print(`✅ Page ${index + 1} content generated`); - } else { - Print(`❌ Page ${index + 1} content empty`); - allTestsPassed = false; - return; - } - }) - - return allTestsPassed; + public GetTestData(): { + IsInitialized: boolean; + DebugDataTable: DataTable; + DebugPages: UEArray; + } { + return { + IsInitialized: this.IsInitialized, + DebugDataTable: this.DebugDataTable, + DebugPages: this.DebugPages, + }; } - // Category: "Testing" - // Pure: true - /** - * Validate current navigation state - * @returns True if current page index is valid - * @pure Function has no side effects - */ - private IsValidNavigationState() { - if (this.DebugSettings.CurrentPageIndex >= 0) { - const visiblePagesLength = this.GetVisiblePages().length; - - return !((visiblePagesLength > 0) && (this.DebugSettings.CurrentPageIndex >= visiblePagesLength)); - } else { - return false; - } - } - - // Category: "Testing" - /** - * Test page navigation functionality - * @param StartCurrentPage - Initial page index to restore after test - * @returns True if navigation works correctly - * @private Internal testing method - */ - private TestNavigation(StartCurrentPage: Integer) { - if (this.IsValidNavigationState()) { - if (this.IsValidNavigationState()) { - this.NextPage(); - - if (this.IsValidNavigationState()) { - if (this.IsValidNavigationState()) { - this.PreviousPage(); - - if (this.IsValidNavigationState()) { - this.DebugSettings.CurrentPageIndex = StartCurrentPage; - - if (this.IsValidNavigationState()) { - return true; - } else { - Print('❌ Navigation: Failed to restore valid state'); - return false; - } - } else { - Print('❌ Navigation: PrevPage failed — State became invalid after PreviousPage'); - return false; - } - } else { - Print('❌ Navigation: PreviousPage failed — Invalid state before PreviousPage'); - return false; - } - } else { - Print('❌ Navigation: NextPage failed — State became invalid after NextPage'); - return false; - } - } else { - Print('❌ Navigation: NextPage failed — Invalid state before NextPage'); - return false; - } - } else { - Print('❌ Navigation: Invalid initial state'); - return false; - } - } - - // Category: "Testing" - /** - * Run comprehensive test suite for debug system - * Tests initialization, page content generation, and navigation - * @private Called during initialization for validation - */ - private RunAllTests() { - Print('=== COMPREHENSIVE DEBUG SYSTEM TESTING ==='); - - if (this.TestDebugSystem()) { - if (this.TestPageContentGeneration()) { - if (this.TestNavigation(this.DebugSettings.CurrentPageIndex)) { - Print('✅ ALL TESTS PASSED'); - } else { - Print('❌ Navigation Tests: Failed'); - } - } else { - Print('❌ Page Content Generation Tests: Failed'); - } - } else { - Print('❌ System Tests: Failed'); - } - } - - // Category: "System Setup" /** * Initialize debug HUD system with movement component reference * Sets up pages, creates widget, runs tests, and starts display * @param MovementComponentRef - Reference to movement component to debug - * @public Called by BP_MainCharacter during initialization + * @param ToastComponentRef - Reference to toast system for notifications * @example * // Initialize debug HUD in main character * this.DebugHUDComponent.InitializeDebugHUD(this.MovementComponent); + * @category System Setup */ - public InitializeDebugHUD(MovementComponentRef: AC_Movement) { + public InitializeDebugHUD( + MovementComponentRef: AC_Movement, + ToastComponentRef: AC_ToastSystem + ): void { this.MovementComponent = MovementComponentRef; + this.ToastComponent = ToastComponentRef; this.IsInitialized = true; this.FrameCounter = 0; this.LastUpdateTime = 0; this.FPS = 0; this.RegisterDefaultPages(); this.CreateDebugWidget(); - this.RunAllTests(); this.DebugSettings.CurrentPageIndex = 0; this.UpdateWidgetVisibility(); - Print('=== DEBUG HUD INITIALIZED ==='); + this.ToastComponent.ShowToast( + 'Debug HUD Initialized', + E_MessageType.Success + ); this.UpdateCurrentPage(); } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Reference to movement component being debugged + * Set during initialization, used for accessing movement data + * @category Components + */ + private MovementComponent: AC_Movement | null = null; + + /** + * Reference to toast system component for debug messaging + * Set during initialization, used for displaying debug notifications + * @category Components + */ + public ToastComponent: AC_ToastSystem | null = null; + + /** + * Debug system configuration settings + * Controls visibility, update frequency, and current page + * Instance editable for designer customization + * @category DebugConfig + * @instanceEditable true + */ + public DebugSettings: S_DebugSettings = { + CurrentMode: ESlateVisibility.Visible, + CurrentPageIndex: 0, + ShowVisualDebug: false, + UpdateFrequency: 0, + }; + + /** + * System initialization state flag + * Set to true after successful InitializeDebugHUD call + * @category DebugState + */ + private IsInitialized: boolean = false; + + /** + * Timestamp of last HUD update (seconds) + * Used for update frequency control + * @category DebugState + */ + private LastUpdateTime: Float = 0; + + /** + * Current frame counter for performance tracking + * Incremented each update cycle + * @category DebugState + */ + private FrameCounter: Float = 0; + + /** + * Current frames per second calculation + * Calculated as 1.0 / DeltaTime + * @category DebugState + */ + private FPS: Float = 0; + + /** + * Debug HUD widget instance + * Created during initialization, manages UI display + * @category Widget Control + */ + private DebugWidget: WBP_DebugHUD | null = null; + + /** + * Array of registered debug pages + * Contains all available pages with their data and update functions + * @category Page System + */ + private DebugPages: UEArray = new UEArray([]); + + /** + * DataTable reference for debug pages storage + * Contains structured page data with Name-based indexing for efficient lookup + * @category Page System + */ + private DebugDataTable: DataTable = DT_DebugPages; } diff --git a/Content/Debug/Components/AC_DebugHUD.uasset b/Content/Debug/Components/AC_DebugHUD.uasset index 10e5901..8c6c54e 100644 --- a/Content/Debug/Components/AC_DebugHUD.uasset +++ b/Content/Debug/Components/AC_DebugHUD.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d63aa844350aa7dc9eab09b95b9e5e548f196e37c6c633f293afeb409f5bd4f -size 1063942 +oid sha256:aff46696327b37d17b056d8bfaa9d779673ef019a967c1b32ef5dc27ffb250de +size 818944 diff --git a/Content/Debug/Enums/E_DebugMode.ts b/Content/Debug/Enums/E_DebugMode.ts deleted file mode 100644 index 2bac04f..0000000 --- a/Content/Debug/Enums/E_DebugMode.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Content/Debug/Enums/E_DebugMode.ts - -export enum E_DebugMode { - Hidden = "Hidden", - Visible = "Visible", -} diff --git a/Content/Debug/Enums/E_DebugMode.uasset b/Content/Debug/Enums/E_DebugMode.uasset deleted file mode 100644 index cf2428b..0000000 --- a/Content/Debug/Enums/E_DebugMode.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d719549f173ec8a3cb41120e63b1bfed599d78e4087bfa5bd77cefb0850bde7c -size 2158 diff --git a/Content/Debug/Enums/E_DebugPageID.ts b/Content/Debug/Enums/E_DebugPageID.ts index 78f9813..86abbb4 100644 --- a/Content/Debug/Enums/E_DebugPageID.ts +++ b/Content/Debug/Enums/E_DebugPageID.ts @@ -1,7 +1,7 @@ -// Content/Debug/Enums/E_DebugPageID.ts +// Debug/Enums/E_DebugPageID.ts export enum E_DebugPageID { - MovementInfo = "MovementInfo", - SurfaceInfo = "SurfaceInfo", - PerformanceInfo = "PerformanceInfo" + MovementInfo = 'MovementInfo', + SurfaceInfo = 'SurfaceInfo', + PerformanceInfo = 'PerformanceInfo', } diff --git a/Content/Debug/Enums/E_DebugUpdateFunction.ts b/Content/Debug/Enums/E_DebugUpdateFunction.ts index 2998e34..0bc7568 100644 --- a/Content/Debug/Enums/E_DebugUpdateFunction.ts +++ b/Content/Debug/Enums/E_DebugUpdateFunction.ts @@ -1,7 +1,7 @@ -// Content/Enums/E_DebugUpdateFunction.ts +// Debug/Enums/E_DebugUpdateFunction.ts export enum E_DebugUpdateFunction { - UpdateMovementPage = "UpdateMovementPage", - UpdateSurfacePage = "UpdateSurfacePage", - UpdatePerformancePage = "UpdatePerformancePage" + UpdateMovementPage = 'UpdateMovementPage', + UpdateSurfacePage = 'UpdateSurfacePage', + UpdatePerformancePage = 'UpdatePerformancePage', } diff --git a/Content/Debug/Structs/S_DebugColors.uasset b/Content/Debug/Structs/S_DebugColors.uasset deleted file mode 100644 index 8d77606..0000000 --- a/Content/Debug/Structs/S_DebugColors.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:89a5d9121f4f55cd47b4aecf1e972b27bce8fb4145e7720075839c8a037e7b16 -size 11290 diff --git a/Content/Debug/Structs/S_DebugPage.ts b/Content/Debug/Structs/S_DebugPage.ts index a815b06..c579dba 100644 --- a/Content/Debug/Structs/S_DebugPage.ts +++ b/Content/Debug/Structs/S_DebugPage.ts @@ -1,8 +1,8 @@ -// Content/Debug/Structs/S_DebugPage.ts +// Debug/Structs/S_DebugPage.ts -import type {E_DebugPageID} from "../Enums/E_DebugPageID.js"; -import type {Text} from "../../types.js"; -import type {E_DebugUpdateFunction} from "../Enums/E_DebugUpdateFunction.js"; +import type { E_DebugPageID } from '#root/Debug/Enums/E_DebugPageID.js'; +import type { E_DebugUpdateFunction } from '#root/Debug/Enums/E_DebugUpdateFunction.js'; +import type { Text } from '#root/UE/Text.ts'; export interface S_DebugPage { PageID: E_DebugPageID; diff --git a/Content/Debug/Structs/S_DebugSettings.ts b/Content/Debug/Structs/S_DebugSettings.ts index bff4641..8eabc82 100644 --- a/Content/Debug/Structs/S_DebugSettings.ts +++ b/Content/Debug/Structs/S_DebugSettings.ts @@ -1,10 +1,11 @@ -// Content/Debug/Enums/S_DebugSettings.ts +// Debug/Enums/S_DebugSettings.ts -import type {E_DebugMode} from "../Enums/E_DebugMode.js"; -import type {Float, Integer} from "../../types.js"; +import type { ESlateVisibility } from '#root/UE/ESlateVisibility.ts'; +import type { Float } from '#root/UE/Float.ts'; +import type { Integer } from '#root/UE/Integer.ts'; export interface S_DebugSettings { - CurrentMode: E_DebugMode; + CurrentMode: ESlateVisibility; CurrentPageIndex: Integer; ShowVisualDebug: boolean; UpdateFrequency: Float; diff --git a/Content/Debug/Structs/S_DebugSettings.uasset b/Content/Debug/Structs/S_DebugSettings.uasset index 9760471..24fcb44 100644 --- a/Content/Debug/Structs/S_DebugSettings.uasset +++ b/Content/Debug/Structs/S_DebugSettings.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55f4e0069cf8c7e10df8d561b0542637f7cddf0eb04ffa883317ef784a482eb7 -size 7252 +oid sha256:fa26fc4986f100489a5e3d98b52bd748b3528ced5ebebfc03fb76db0c9f4750b +size 7276 diff --git a/Content/Debug/Tables/DT_DebugPages.ts b/Content/Debug/Tables/DT_DebugPages.ts new file mode 100644 index 0000000..d8acb06 --- /dev/null +++ b/Content/Debug/Tables/DT_DebugPages.ts @@ -0,0 +1,39 @@ +// Debug/Tables/DT_DebugPages.ts + +import { E_DebugPageID } from '#root/Debug/Enums/E_DebugPageID.ts'; +import { E_DebugUpdateFunction } from '#root/Debug/Enums/E_DebugUpdateFunction.ts'; +import type { S_DebugPage } from '#root/Debug/Structs/S_DebugPage.ts'; +import { DataTable } from '#root/UE/DataTable.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEArray } from '#root/UE/UEArray.ts'; + +export const DT_DebugPages = new DataTable( + null, + new Name('DT_DebugPages'), + new UEArray( + { + Name: new Name('MovementInfo'), + PageID: E_DebugPageID.MovementInfo, + Title: 'Movement Constants', + Content: '', + IsVisible: true, + UpdateFunction: E_DebugUpdateFunction.UpdateMovementPage, + }, + { + Name: new Name('SurfaceInfo'), + PageID: E_DebugPageID.SurfaceInfo, + Title: 'Surface Classification', + Content: '', + IsVisible: true, + UpdateFunction: E_DebugUpdateFunction.UpdateSurfacePage, + }, + { + Name: new Name('PerformanceInfo'), + PageID: E_DebugPageID.PerformanceInfo, + Title: 'Performance Metrics', + Content: '', + IsVisible: true, + UpdateFunction: E_DebugUpdateFunction.UpdatePerformancePage, + } + ) +); diff --git a/Content/Debug/Tables/DT_DebugPages.uasset b/Content/Debug/Tables/DT_DebugPages.uasset new file mode 100644 index 0000000..bb83c04 --- /dev/null +++ b/Content/Debug/Tables/DT_DebugPages.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f44d3c8d5e63a100a49af4c50408ca36350c2a3c8b0705f524b6666a35a8d74 +size 3863 diff --git a/Content/Debug/Tests/FT_DebugNavigation.ts b/Content/Debug/Tests/FT_DebugNavigation.ts new file mode 100644 index 0000000..e6a8066 --- /dev/null +++ b/Content/Debug/Tests/FT_DebugNavigation.ts @@ -0,0 +1,112 @@ +// Debug/Tests/FT_DebugNavigation.ts + +import { AC_DebugHUD } from '#root/Debug/Components/AC_DebugHUD.ts'; +import { AC_Movement } from '#root/Movement/Components/AC_Movement.ts'; +import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { FunctionalTest } from '#root/UE/FunctionalTest.ts'; +import type { Integer } from '#root/UE/Integer.ts'; + +/** + * Functional Test: Debug HUD Navigation System + * Tests page navigation state management during NextPage/PreviousPage operations + */ +export class FT_DebugNavigation extends FunctionalTest { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── + + /** + * Test entry point - validates navigation state during page operations + * Uses nested validation to ensure CurrentPageIndex stays valid + */ + EventStartTest(): void { + this.DebugHUDComponent.InitializeDebugHUD( + this.MovementComponent, + this.ToastSystemComponent + ); + + this.IfValid('Debug HUD: Navigation invalid initial state', () => { + this.IfValid( + 'Debug HUD: NextPage failed — Invalid state before NextPage', + () => { + this.DebugHUDComponent.NextPage(); + + this.IfValid( + 'Debug HUD: NextPage failed — State became invalid after NextPage', + () => { + this.DebugHUDComponent.PreviousPage(); + + this.IfValid( + 'Debug HUD: PrevPage failed — State became invalid after PreviousPage', + () => { + this.FinishTest(EFunctionalTestResult.Succeeded); + } + ); + } + ); + } + ); + }); + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // MACROS + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Validates current page index and executes callback if state is valid + * @param Message - Error message if validation fails + * @param Out - Callback to execute if state is valid + */ + private IfValid(Message: string, Out: () => void): void { + const IsPageIndexOutOfBounds = ( + visiblePagesLength: Integer, + currentPage: Integer + ): boolean => visiblePagesLength > 0 && currentPage >= visiblePagesLength; + + const IsPageIndexNonNegative = (currentPage: Integer): boolean => + currentPage >= 0; + + if ( + !IsPageIndexOutOfBounds( + this.DebugHUDComponent.GetVisiblePages().length, + this.DebugHUDComponent.DebugSettings.CurrentPageIndex + ) && + IsPageIndexNonNegative( + this.DebugHUDComponent.DebugSettings.CurrentPageIndex + ) + ) { + Out(); + } else { + this.FinishTest(EFunctionalTestResult.Failed, Message); + } + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Movement system component - required for debug HUD initialization + * @category Components + */ + MovementComponent = new AC_Movement(); + + /** + * Debug HUD system - primary component under test + * Tests page navigation state management + * @category Components + */ + DebugHUDComponent = new AC_DebugHUD(); + + /** + * Toast notification system - required for debug HUD initialization + * @category Components + */ + ToastSystemComponent = new AC_ToastSystem(); +} diff --git a/Content/Debug/Tests/FT_DebugNavigation.uasset b/Content/Debug/Tests/FT_DebugNavigation.uasset new file mode 100644 index 0000000..d02f20b --- /dev/null +++ b/Content/Debug/Tests/FT_DebugNavigation.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6bd0c16653ad8aa9d00142fb607e91d56ad0d93c7b0c7eef2666095109fd47d7 +size 111598 diff --git a/Content/Debug/Tests/FT_DebugPageContentGenerator.ts b/Content/Debug/Tests/FT_DebugPageContentGenerator.ts new file mode 100644 index 0000000..f700998 --- /dev/null +++ b/Content/Debug/Tests/FT_DebugPageContentGenerator.ts @@ -0,0 +1,109 @@ +// Debug/Tests/FT_DebugPageContentGenerator.ts + +import { AC_DebugHUD } from '#root/Debug/Components/AC_DebugHUD.ts'; +import { E_DebugPageID } from '#root/Debug/Enums/E_DebugPageID.ts'; +import { E_DebugUpdateFunction } from '#root/Debug/Enums/E_DebugUpdateFunction.ts'; +import type { S_DebugPage } from '#root/Debug/Structs/S_DebugPage.ts'; +import { AC_Movement } from '#root/Movement/Components/AC_Movement.ts'; +import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { FunctionalTest } from '#root/UE/FunctionalTest.ts'; + +/** + * Functional Test: Debug HUD Page Content Generation + * Validates that all registered debug pages generate non-empty content + */ +export class FT_DebugPageContentGenerator extends FunctionalTest { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── + + /** + * Test entry point - validates content generation for all debug pages + * Iterates through all pages and tests their update functions + */ + EventStartTest(): void { + this.DebugHUDComponent.InitializeDebugHUD( + this.MovementComponent, + this.ToastSystemComponent + ); + + this.DebugHUDComponent.GetTestData().DebugPages.forEach( + (arrayElement, arrayIndex) => { + this.UpdatedPage = arrayElement; + + switch (this.UpdatedPage.UpdateFunction) { + case E_DebugUpdateFunction.UpdateMovementPage: { + this.UpdatedPage = this.DebugHUDComponent.UpdateMovementPage( + this.UpdatedPage + ); + break; + } + + case E_DebugUpdateFunction.UpdateSurfacePage: { + this.UpdatedPage = this.DebugHUDComponent.UpdateSurfacePage( + this.UpdatedPage + ); + break; + } + + case E_DebugUpdateFunction.UpdatePerformancePage: { + this.UpdatedPage = this.DebugHUDComponent.UpdatePerformancePage( + this.UpdatedPage + ); + break; + } + } + + if (this.UpdatedPage.Content.length > 0) { + this.FinishTest(EFunctionalTestResult.Succeeded); + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + `DebugHUD: Page ${arrayIndex + 1} content empty` + ); + } + } + ); + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Movement system component - required for debug HUD initialization + * @category Components + */ + MovementComponent = new AC_Movement(); + + /** + * Debug HUD system - primary component under test + * Tests page content generation functionality + * @category Components + */ + DebugHUDComponent = new AC_DebugHUD(); + + /** + * Toast notification system - required for debug HUD initialization + * @category Components + */ + ToastSystemComponent = new AC_ToastSystem(); + + /** + * Working copy of debug page for content generation testing + * Updated during test execution for each page + * @category Test State + */ + UpdatedPage: S_DebugPage = { + PageID: E_DebugPageID.MovementInfo, + Title: '', + Content: '', + IsVisible: false, + UpdateFunction: E_DebugUpdateFunction.UpdateMovementPage, + }; +} diff --git a/Content/Debug/Tests/FT_DebugPageContentGenerator.uasset b/Content/Debug/Tests/FT_DebugPageContentGenerator.uasset new file mode 100644 index 0000000..8b6999a --- /dev/null +++ b/Content/Debug/Tests/FT_DebugPageContentGenerator.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c7ec30b1373ab53ddf56723fed86c888da5ec2491eaabc91555fa4d22033fe0 +size 121663 diff --git a/Content/Debug/Tests/FT_DebugSystem.ts b/Content/Debug/Tests/FT_DebugSystem.ts new file mode 100644 index 0000000..6c5accd --- /dev/null +++ b/Content/Debug/Tests/FT_DebugSystem.ts @@ -0,0 +1,95 @@ +// Debug/Tests/FT_DebugSystem.ts + +import { AC_DebugHUD } from '#root/Debug/Components/AC_DebugHUD.ts'; +import { AC_Movement } from '#root/Movement/Components/AC_Movement.ts'; +import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { DataTableFunctionLibrary } from '#root/UE/DataTableFunctionLibrary.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { FunctionalTest } from '#root/UE/FunctionalTest.ts'; +import { SystemLibrary } from '#root/UE/SystemLibrary.ts'; + +/** + * Functional Test: Debug System Basic Functionality + * Validates initialization, component validity, and data table consistency + */ +export class FT_DebugSystem extends FunctionalTest { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── + + /** + * Test entry point - validates basic debug system functionality + * Uses nested validation to check initialization, page count, and component validity + */ + EventStartTest(): void { + this.DebugHUDComponent.InitializeDebugHUD( + this.MovementComponent, + this.ToastSystemComponent + ); + + if (this.DebugHUDComponent.GetTestData().IsInitialized) { + if ( + DataTableFunctionLibrary.GetDataTableRowNames( + this.DebugHUDComponent.GetTestData().DebugDataTable + ).length === this.DebugHUDComponent.GetTestData().DebugPages.length + ) { + if (SystemLibrary.IsValid(this.MovementComponent)) { + if (SystemLibrary.IsValid(this.DebugHUDComponent)) { + this.FinishTest(EFunctionalTestResult.Succeeded); + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + 'DebugHUD component not valid' + ); + } + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + 'Debug HUD: Movement component not valid' + ); + } + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + `Debug HUD: Expected ${this.DebugHUDComponent.GetTestData().DebugPages.length} pages, got ${ + DataTableFunctionLibrary.GetDataTableRowNames( + this.DebugHUDComponent.GetTestData().DebugDataTable + ).length + }` + ); + } + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + 'Debug HUD failed to initialize' + ); + } + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Movement system component - required for debug HUD initialization + * @category Components + */ + MovementComponent = new AC_Movement(); + + /** + * Debug HUD system - primary component under test + * Tests basic system initialization and component validity + * @category Components + */ + DebugHUDComponent = new AC_DebugHUD(); + + /** + * Toast notification system - required for debug HUD initialization + * @category Components + */ + ToastSystemComponent = new AC_ToastSystem(); +} diff --git a/Content/Debug/Tests/FT_DebugSystem.uasset b/Content/Debug/Tests/FT_DebugSystem.uasset new file mode 100644 index 0000000..497df86 --- /dev/null +++ b/Content/Debug/Tests/FT_DebugSystem.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:485e923c52a0c5d8bbf1a553c555f02256a8c7867fb9c92017e6839292a37f83 +size 99168 diff --git a/Content/Debug/UI/WBP_DebugHUD.ts b/Content/Debug/UI/WBP_DebugHUD.ts index 548596c..7a94474 100644 --- a/Content/Debug/UI/WBP_DebugHUD.ts +++ b/Content/Debug/UI/WBP_DebugHUD.ts @@ -1,132 +1,158 @@ -// Content/Debug/UI/WBP_DebugHUD.ts +// Debug/UI/WBP_DebugHUD.ts -import type {AC_Movement} from "../../Movement/Components/AC_Movement.js"; -import {TextBox, Widget} from "../../classes.js"; -import type {Text} from "../../types.js"; -import {IsValid} from "../../functions.js"; +import type { AC_Movement } from '#root/Movement/Components/AC_Movement.js'; +import { SystemLibrary } from '#root/UE/SystemLibrary.ts'; +import type { Text } from '#root/UE/Text.ts'; +import { TextBlock } from '#root/UE/TextBlock.ts'; +import { UserWidget } from '#root/UE/UserWidget.ts'; /** * Debug HUD Widget for displaying system information * Provides real-time debug information display with multiple pages * Part of the deterministic movement system debug infrastructure */ -export class WBP_DebugHUD extends Widget{ - // Category: "Components" - /** - * Reference to movement component for accessing debug data - * Set by AC_DebugHUD during initialization - */ - public MovementComponent: AC_Movement | null = null; +export class WBP_DebugHUD extends UserWidget { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ - // Category: "PageData" - /** - * Current page title text - * Updated by AC_DebugHUD when switching pages - */ - private HeaderText: Text = "Debug HUD"; + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── - // Category: "PageData" /** - * Current page content text - * Contains the main debug information for current page + * Widget construction event - initializes all text displays + * Called automatically when widget is created */ - private ContentText: Text = "Text"; + EventConstruct(): void { + this.UpdateHeaderDisplay(); + this.UpdateContentDisplay(); + this.UpdateNavigationDisplay(); + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // FUNCTIONS + // ════════════════════════════════════════════════════════════════════════════════════════ - // Category: "PageData" /** - * Navigation instructions text - * Shows current page index and navigation controls + * Update header text box with current header text + * @category Display Updates */ - private NavigationText: Text = "Navigation"; - - // Category: "UI Components" - /** - * Text box widget for displaying page header/title - * Positioned at top of debug HUD - */ - private HeaderTextBox = new TextBox(); - - // Category: "UI Components" - /** - * Text box widget for displaying main debug content - * Contains multi-line debug information for current page - */ - private ContentTextBox = new TextBox(); - - // Category: "UI Components" - /** - * Text box widget for displaying navigation help - * Shows page counter and keyboard shortcuts - */ - private NavigationTextBox = new TextBox(); - - // Category: "Display Updates" - private UpdateHeaderDisplay() { - if (IsValid(this.HeaderTextBox)) { + private UpdateHeaderDisplay(): void { + if (SystemLibrary.IsValid(this.HeaderTextBox)) { this.HeaderTextBox.SetText(this.HeaderText); } } - // Category: "Display Updates" /** - * Update header text box with current header text - * Called automatically when header text changes - * @private Internal display update method + * Update content text box with current content text + * @category Display Updates */ - private UpdateContentDisplay() { - if (IsValid(this.ContentTextBox)) { + private UpdateContentDisplay(): void { + if (SystemLibrary.IsValid(this.ContentTextBox)) { this.ContentTextBox.SetText(this.ContentText); } } - // Category: "Display Updates" /** * Update navigation text box with current navigation text - * Called automatically when navigation text changes - * @private Internal display update method + * @category Display Updates */ - private UpdateNavigationDisplay() { - if (IsValid(this.NavigationTextBox)) { + private UpdateNavigationDisplay(): void { + if (SystemLibrary.IsValid(this.NavigationTextBox)) { this.NavigationTextBox.SetText(this.NavigationText); } } - // Category: "Public Interface" /** * Set new header text and update display * @param NewHeaderText - New title text for current debug page * @example * // Set movement page header * SetHeaderText("Movement Constants") + * @category Public Interface */ - public SetHeaderText(NewHeaderText: string): void { + public SetHeaderText(NewHeaderText: Text): void { this.HeaderText = NewHeaderText; this.UpdateHeaderDisplay(); } - // Category: "Public Interface" /** * Set new content text and update display * @param NewContentText - New debug content (supports multi-line text) * @example * // Set movement constants content * SetContentText("Max Speed: 600\nAcceleration: 2000\nFriction: 8.0") + * @category Public Interface */ - public SetContentText(NewContentText: string): void { + public SetContentText(NewContentText: Text): void { this.ContentText = NewContentText; this.UpdateContentDisplay(); } - // Category: "Public Interface" /** * Set new navigation text and update display * @param NewNavigationText - Navigation instructions and page info * @example * // Set navigation with page counter * SetNavigationText("Page 1/3 | PageUp/PageDown - Navigate") + * @category Public Interface */ - public SetNavigationText(NewNavigationText: string): void { + public SetNavigationText(NewNavigationText: Text): void { this.NavigationText = NewNavigationText; this.UpdateNavigationDisplay(); } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Reference to movement component for accessing debug data + * Set by AC_DebugHUD during initialization + * @category Components + */ + public MovementComponent: AC_Movement | null = null; + + /** + * Current page title text + * Updated by AC_DebugHUD when switching pages + * @category PageData + */ + private HeaderText: Text = 'Debug HUD'; + + /** + * Current page content text + * Contains the main debug information for current page + * @category PageData + */ + private ContentText: Text = 'Text'; + + /** + * Navigation instructions text + * Shows current page index and navigation controls + * @category PageData + */ + private NavigationText: Text = 'Navigation'; + + /** + * Text box widget for displaying page header/title + * Positioned at top of debug HUD + * @category UI Components + */ + private HeaderTextBox = new TextBlock(); + + /** + * Text box widget for displaying main debug content + * Contains multi-line debug information for current page + * @category UI Components + */ + private ContentTextBox = new TextBlock(); + + /** + * Text box widget for displaying navigation help + * Shows page counter and keyboard shortcuts + * @category UI Components + */ + private NavigationTextBox = new TextBlock(); } diff --git a/Content/Debug/UI/WBP_DebugHUD.uasset b/Content/Debug/UI/WBP_DebugHUD.uasset index fc13359..3ccfa30 100644 --- a/Content/Debug/UI/WBP_DebugHUD.uasset +++ b/Content/Debug/UI/WBP_DebugHUD.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3193b8a91278bd73017e070a8c3868653cea470b6942aca4da104f6ea4d207fb -size 140216 +oid sha256:81227a28a2d8fe6b5a83e4058015f0475e7f4cf7be75c8e8a3ef3565fe618d0e +size 111666 diff --git a/Content/Debug/UI/WBP_TestResult.uasset b/Content/Debug/UI/WBP_TestResult.uasset deleted file mode 100644 index bd540a3..0000000 --- a/Content/Debug/UI/WBP_TestResult.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f6c94085cc255fd470a3b4846d08a935f37326c18e6d9cdcf30d349a98acb3b0 -size 86508 diff --git a/Content/Input/Actions/IA_LeftTrigger.ts b/Content/Input/Actions/IA_LeftTrigger.ts index 3ae1530..bcbb59f 100644 --- a/Content/Input/Actions/IA_LeftTrigger.ts +++ b/Content/Input/Actions/IA_LeftTrigger.ts @@ -1,5 +1,6 @@ -// Content/Input/Actions/IA_LeftTrigger.ts +// Input/Actions/IA_LeftTrigger.ts -import type {InputMapping} from "../../types.js"; +import { InputAction } from '#root/UE/InputAction.ts'; +import { Name } from '#root/UE/Name.ts'; -export const IA_LeftTrigger: InputMapping = {} +export const IA_LeftTrigger = new InputAction(null, new Name('IA_LeftTrigger')); diff --git a/Content/Input/Actions/IA_Look.ts b/Content/Input/Actions/IA_Look.ts new file mode 100644 index 0000000..b480846 --- /dev/null +++ b/Content/Input/Actions/IA_Look.ts @@ -0,0 +1,6 @@ +// Input/Actions/IA_Look.ts + +import { InputAction } from '#root/UE/InputAction.ts'; +import { Name } from '#root/UE/Name.ts'; + +export const IA_Look = new InputAction(null, new Name('IA_Look')); diff --git a/Content/Input/Actions/IA_Move.ts b/Content/Input/Actions/IA_Move.ts new file mode 100644 index 0000000..b0462ae --- /dev/null +++ b/Content/Input/Actions/IA_Move.ts @@ -0,0 +1,6 @@ +// Input/Actions/IA_Move.ts + +import { InputAction } from '#root/UE/InputAction.ts'; +import { Name } from '#root/UE/Name.ts'; + +export const IA_Move = new InputAction(null, new Name('IA_Move')); diff --git a/Content/Input/Actions/IA_NextDebugMode.ts b/Content/Input/Actions/IA_NextDebugMode.ts index 9d00bf6..e6864d7 100644 --- a/Content/Input/Actions/IA_NextDebugMode.ts +++ b/Content/Input/Actions/IA_NextDebugMode.ts @@ -1,5 +1,5 @@ -// Content/Input/Actions/IA_NextDebugMode.ts +// Input/Actions/IA_NextDebugMode.ts -import type {InputMapping} from "../../types.js"; +import { InputAction } from '#root/UE/InputAction.ts'; -export const IA_NextDebugMode: InputMapping = {} +export const IA_NextDebugMode = new InputAction(null, 'IA_NextDebugMode'); diff --git a/Content/Input/Actions/IA_PrevDebugMode.ts b/Content/Input/Actions/IA_PrevDebugMode.ts index 4fcaf56..afef139 100644 --- a/Content/Input/Actions/IA_PrevDebugMode.ts +++ b/Content/Input/Actions/IA_PrevDebugMode.ts @@ -1,5 +1,5 @@ -// Content/Input/Actions/IA_PrevDebugMode.ts +// Input/Actions/IA_PrevDebugMode.ts -import type {InputMapping} from "../../types.js"; +import { InputAction } from '#root/UE/InputAction.ts'; -export const IA_PrevDebugMode: InputMapping = {} +export const IA_PrevDebugMode = new InputAction(null, 'IA_PrevDebugMode'); diff --git a/Content/Input/Actions/IA_RightTrigger.ts b/Content/Input/Actions/IA_RightTrigger.ts index 4dc7860..767ad84 100644 --- a/Content/Input/Actions/IA_RightTrigger.ts +++ b/Content/Input/Actions/IA_RightTrigger.ts @@ -1,5 +1,5 @@ -// Content/Input/Actions/IA_RightTrigger.ts +// Input/Actions/IA_RightTrigger.ts -import type {InputMapping} from "../../types.js"; +import { InputAction } from '#root/UE/InputAction.ts'; -export const IA_RightTrigger: InputMapping = {} +export const IA_RightTrigger = new InputAction(null, 'IA_RightTrigger'); diff --git a/Content/Input/Actions/IA_ToggleHUD.ts b/Content/Input/Actions/IA_ToggleHUD.ts index 67e895b..378c9b9 100644 --- a/Content/Input/Actions/IA_ToggleHUD.ts +++ b/Content/Input/Actions/IA_ToggleHUD.ts @@ -1,5 +1,5 @@ -// Content/Input/Actions/IA_ToggleHUD.ts +// Input/Actions/IA_ToggleHUD.ts -import type {InputMapping} from "../../types.js"; +import { InputAction } from '#root/UE/InputAction.ts'; -export const IA_ToggleHUD: InputMapping = {} +export const IA_ToggleHUD = new InputAction(null, 'IA_ToggleHUD'); diff --git a/Content/Input/Actions/IA_ToggleVisualDebug.ts b/Content/Input/Actions/IA_ToggleVisualDebug.ts index 4922158..ab1e377 100644 --- a/Content/Input/Actions/IA_ToggleVisualDebug.ts +++ b/Content/Input/Actions/IA_ToggleVisualDebug.ts @@ -1,5 +1,8 @@ -// Content/Input/Actions/IA_ToggleVisualDebug.ts +// Input/Actions/IA_ToggleVisualDebug.ts -import type {InputMapping} from "../../types.js"; +import { InputAction } from '#root/UE/InputAction.ts'; -export const IA_ToggleVisualDebug: InputMapping = {} +export const IA_ToggleVisualDebug = new InputAction( + null, + 'IA_ToggleVisualDebug' +); diff --git a/Content/Input/Enums/E_InputDeviceType.ts b/Content/Input/Enums/E_InputDeviceType.ts new file mode 100644 index 0000000..0fbf404 --- /dev/null +++ b/Content/Input/Enums/E_InputDeviceType.ts @@ -0,0 +1,7 @@ +// Input/Enums/E_InputDeviceType.ts + +export enum E_InputDeviceType { + Unknown = 'Unknown', + Keyboard = 'Keyboard', + Gamepad = 'Gamepad', +} diff --git a/Content/Input/IMC_Default.ts b/Content/Input/IMC_Default.ts index f9f13a9..7f8ae3b 100644 --- a/Content/Input/IMC_Default.ts +++ b/Content/Input/IMC_Default.ts @@ -1,18 +1,24 @@ -// Content/Input/IMC_Default.ts +// Input/IMC_Default.ts -import type {InputMappingContext} from "../types.js"; -import {IA_LeftTrigger} from "./Actions/IA_LeftTrigger.js"; -import {IA_RightTrigger} from "./Actions/IA_RightTrigger.js"; -import {IA_NextDebugMode} from "./Actions/IA_NextDebugMode.js"; -import {IA_PrevDebugMode} from "./Actions/IA_PrevDebugMode.js"; -import {IA_ToggleHUD} from "./Actions/IA_ToggleHUD.js"; -import {IA_ToggleVisualDebug} from "./Actions/IA_ToggleVisualDebug.js"; +import { IA_LeftTrigger } from '#root/Input/Actions/IA_LeftTrigger.ts'; +import { IA_Move } from '#root/Input/Actions/IA_Move.ts'; +import { IA_NextDebugMode } from '#root/Input/Actions/IA_NextDebugMode.ts'; +import { IA_PrevDebugMode } from '#root/Input/Actions/IA_PrevDebugMode.ts'; +import { IA_RightTrigger } from '#root/Input/Actions/IA_RightTrigger.ts'; +import { IA_ToggleHUD } from '#root/Input/Actions/IA_ToggleHUD.ts'; +import { IA_ToggleVisualDebug } from '#root/Input/Actions/IA_ToggleVisualDebug.ts'; +import { InputMappingContext } from '#root/UE/InputMappingContext.ts'; +import type { Key } from '#root/UE/Key.ts'; -export const IMC_Default: InputMappingContext = [ - IA_LeftTrigger, - IA_RightTrigger, - IA_NextDebugMode, - IA_PrevDebugMode, - IA_ToggleHUD, +export const IMC_Default = new InputMappingContext(); + +IMC_Default.mapKey(IA_LeftTrigger, 'IA_LeftTrigger' as unknown as Key); +IMC_Default.mapKey(IA_RightTrigger, 'IA_RightTrigger' as unknown as Key); +IMC_Default.mapKey(IA_NextDebugMode, 'IA_NextDebugMode' as unknown as Key); +IMC_Default.mapKey(IA_PrevDebugMode, 'IA_PrevDebugMode' as unknown as Key); +IMC_Default.mapKey(IA_ToggleHUD, 'IA_ToggleHUD' as unknown as Key); +IMC_Default.mapKey( IA_ToggleVisualDebug, -] + 'IA_ToggleVisualDebug' as unknown as Key +); +IMC_Default.mapKey(IA_Move, 'IA_Move' as unknown as Key); diff --git a/Content/Levels/TestLevel.ts b/Content/Levels/TestLevel.ts index a32d4bf..7028af0 100644 --- a/Content/Levels/TestLevel.ts +++ b/Content/Levels/TestLevel.ts @@ -1,5 +1,5 @@ -// Content/Levels/TestLevel.ts +// Levels/TestLevel.ts -import {BP_MainCharacter} from "../Blueprints/BP_MainCharacter.js"; +import { BP_MainCharacter } from '#root/Blueprints/BP_MainCharacter.ts'; -const MainCharacter = new BP_MainCharacter(); +new BP_MainCharacter(); diff --git a/Content/Levels/TestLevel.umap b/Content/Levels/TestLevel.umap index 5cdcd44..9e45837 100644 --- a/Content/Levels/TestLevel.umap +++ b/Content/Levels/TestLevel.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83b5cfd584e3db81228760464c784c1b506fb133af08530f4f953e27bd845fa7 -size 45112 +oid sha256:f4418e7ba726d3f1f74316e0be029f81b605afb08b35b6acdf49f34691ce0957 +size 78011 diff --git a/Content/Math/Libraries/BFL_Vectors.ts b/Content/Math/Libraries/BFL_Vectors.ts new file mode 100644 index 0000000..e99a4cd --- /dev/null +++ b/Content/Math/Libraries/BFL_Vectors.ts @@ -0,0 +1,85 @@ +// Math/Libraries/BFL_Vectors.ts + +import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts'; +import type { Float } from '#root/UE/Float.ts'; +import { MathLibrary } from '#root/UE/MathLibrary.ts'; +import { Vector } from '#root/UE/Vector.ts'; + +/** + * Blueprint Function Library: Vector Mathematics + * Pure mathematical functions for vector operations and surface angle calculations + * Used by movement system for deterministic surface classification + */ +export class BFL_VectorsClass extends BlueprintFunctionLibrary { + constructor( + outer: null | BlueprintFunctionLibrary = null, + name: string = 'BFL_Vectors' + ) { + super(outer, name); + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // FUNCTIONS + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Calculate angle between two normalized vectors + * @param Vector1 - First normalized vector + * @param Vector2 - Second normalized vector + * @returns Angle between vectors in radians (0 to π) + * @example + * // 90° angle between X and Z axes + * GetAngleBetweenVectors(new Vector(1,0,0), new Vector(0,0,1)) // returns π/2 + */ + public GetAngleBetweenVectors(Vector1: Vector, Vector2: Vector): Float { + /** + * Internal calculation using dot product and arccosine + */ + const CalculateAngleBetweenVectors = (v1: Vector, v2: Vector): Float => + MathLibrary.Acos(MathLibrary.Dot(v1, v2)); + + return CalculateAngleBetweenVectors(Vector1, Vector2); + } + + /** + * Generate surface normal vector from angle in degrees + * @param AngleDegrees - Angle from horizontal in degrees (0-180) + * @returns Normalized surface normal vector + * @example + * // Flat surface (0°) + * GetNormalFromAngle(0) // returns Vector(0,0,1) + * // Vertical wall (90°) + * GetNormalFromAngle(90) // returns Vector(1,0,0) + */ + public GetNormalFromAngle(AngleDegrees: Float): Vector { + /** + * Calculate X component using sine of angle + */ + const CalculateX = (angle: Float): Float => + MathLibrary.Sin(MathLibrary.DegreesToRadians(angle)); + + /** + * Calculate Z component using cosine of angle + */ + const CalculateZ = (angle: Float): Float => + MathLibrary.Cos(MathLibrary.DegreesToRadians(angle)); + + return new Vector(CalculateX(AngleDegrees), 0, CalculateZ(AngleDegrees)); + } + + /** + * Calculate angle between surface normal and up vector + * @param SurfaceNormal - Normalized surface normal vector + * @returns Angle from horizontal plane in radians (0 = flat, π/2 = vertical) + * @example + * // Flat surface + * GetSurfaceAngle(new Vector(0,0,1)) // returns 0 + * // Vertical wall + * GetSurfaceAngle(new Vector(1,0,0)) // returns π/2 + */ + public GetSurfaceAngle(SurfaceNormal: Vector): Float { + return this.GetAngleBetweenVectors(SurfaceNormal, new Vector(0, 0, 1)); + } +} + +export const BFL_Vectors = new BFL_VectorsClass(); diff --git a/Content/Math/Libraries/BFL_Vectors.uasset b/Content/Math/Libraries/BFL_Vectors.uasset new file mode 100644 index 0000000..3efffef --- /dev/null +++ b/Content/Math/Libraries/BFL_Vectors.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9e0f89814abc8e644f763ebdc906075af6dfa8d9b62f26a32478ed89b96517b +size 55476 diff --git a/Content/Movement/Components/AC_Movement.ts b/Content/Movement/Components/AC_Movement.ts index bb660d4..b7b94fe 100644 --- a/Content/Movement/Components/AC_Movement.ts +++ b/Content/Movement/Components/AC_Movement.ts @@ -1,94 +1,24 @@ -// Content/Movement/Components/AC_Movement.ts +// Movement/Components/AC_Movement.ts -import type {S_MovementConstants} from "../Structs/S_MovementConstants.js"; -import type {S_AngleThresholds} from "../Structs/S_AngleThresholds.js"; -import type {Float, Vector} from "../../types.js"; -import {acos, cos, D2R, Dot, Print, sin} from "../../functions.js"; -import {E_SurfaceType} from "../Enums/E_SurfaceType.js"; -import type {S_SurfaceTestCase} from "../Structs/S_SurfaceTestCase.js"; +import { BFL_Vectors } from '#root/Math/Libraries/BFL_Vectors.ts'; +import { E_SurfaceType } from '#root/Movement/Enums/E_SurfaceType.ts'; +import { S_AngleThresholds } from '#root/Movement/Structs/S_AngleThresholds.ts'; +import type { S_MovementConstants } from '#root/Movement/Structs/S_MovementConstants.ts'; +import { ActorComponent } from '#root/UE/ActorComponent.ts'; +import type { Float } from '#root/UE/Float.ts'; +import { MathLibrary } from '#root/UE/MathLibrary.ts'; +import type { Vector } from '#root/UE/Vector.ts'; -export class AC_Movement { - // === Movement configuration exposed to designers === - // Category: "Movement Config" - // Instance editable: true - public readonly MovementConstants: S_MovementConstants = { - MaxSpeed: 600.0, - Acceleration: 2000.0, - Friction: 8.0, - Gravity: 980.0, - } +/** + * Movement System Component + * Core deterministic movement system for 3D platformer + * Handles surface classification and movement physics calculations + */ +export class AC_Movement extends ActorComponent { + // ════════════════════════════════════════════════════════════════════════════════════════ + // FUNCTIONS + // ════════════════════════════════════════════════════════════════════════════════════════ - // Category: "Movement Config" - // Instance editable: true - readonly AngleThresholdsDegrees: S_AngleThresholds = { - Walkable: 50.0, // degrees - SteepSlope: 85.0, // degrees - Wall: 95.0, // degrees - }; - // ===================================================== - - // Category: "Debug" - IsInitialized: boolean = false; - - // Category: "Debug" - // Instance editable: true - ShowDebugInfo: boolean = true; - - // === Runtime cached values for performance (radians) === - // Category: "InternalCache" - AngleThresholdsRads: S_AngleThresholds; - // ===================================================== - - // Category: "Math" - // Pure: true - /** - * Calculate angle between two normalized vectors - * @param Vector1 - First normalized vector - * @param Vector2 - Second normalized vector - * @returns Angle between vectors in radians (0 to π) - * @example - * // 90° angle between X and Z axes - * GetAngleBetweenVectors([1,0,0], [0,0,1]) // returns π/2 - */ - GetAngleBetweenVectors(Vector1: Vector, Vector2: Vector) { - return acos(Dot(Vector1, Vector2)); - } - - // Category: "Math" - // Pure: true - /** - * Calculate angle between surface normal and up vector - * @param SurfaceNormal - Normalized surface normal vector - * @returns Angle from horizontal plane in radians (0 = flat, π/2 = vertical) - * @example - * // Flat surface - * GetSurfaceAngle([0,0,1]) // returns 0 - * // Vertical wall - * GetSurfaceAngle([1,0,0]) // returns π/2 - */ - GetSurfaceAngle(SurfaceNormal: Vector): Float { - return this.GetAngleBetweenVectors(SurfaceNormal, [0.0, 0.0, 1.0]); - } - - // Category: "Math" - // Pure: true - /** - * Generate surface normal vector from angle in degrees - * @param AngleDegrees - Angle from horizontal in degrees (0-180) - * @returns Normalized surface normal vector - * @example - * // Flat surface (0°) - * GenerateNormalFromAngle(0) // returns [0,0,1] - * // Vertical wall (90°) - * GenerateNormalFromAngle(90) // returns [1,0,0] - */ - GenerateNormalFromAngle(AngleDegrees: Float): Vector { - const AngleRads = D2R(AngleDegrees); - return [sin(AngleRads), 0.0, cos(AngleRads)]; - } - - // Category: "Surface Detection" - // Pure: true /** * Classify surface type based on normal vector * @param SurfaceNormal - Normalized surface normal vector @@ -96,140 +26,163 @@ export class AC_Movement { * @returns Surface type classification * @example * // Classify flat ground - * ClassifySurface([0,0,1], thresholds) // returns E_SurfaceType.Walkable + * ClassifySurface(new Vector(0,0,1), thresholds) // returns E_SurfaceType.Walkable + * @pure true + * @category Surface Detection */ - ClassifySurface(SurfaceNormal: Vector, AngleThresholds: S_AngleThresholds): E_SurfaceType { - const SurfaceAngle = this.GetSurfaceAngle(SurfaceNormal); + public ClassifySurface( + SurfaceNormal: Vector, + AngleThresholds: S_AngleThresholds + ): E_SurfaceType { + const SurfaceAngle = BFL_Vectors.GetSurfaceAngle(SurfaceNormal); - if (SurfaceAngle <= AngleThresholds.Walkable) { + /** + * Check if angle is within walkable range + */ + const IsWalkableAngle = (walkableAngle: Float): boolean => + SurfaceAngle <= walkableAngle; + + /** + * Check if angle is within steep slope range + */ + const IsSteepSlopeAngle = (steepSlopeAngle: Float): boolean => + SurfaceAngle <= steepSlopeAngle; + + /** + * Check if angle is within wall range + */ + const IsWallAngle = (wallAngle: Float): boolean => + SurfaceAngle <= wallAngle; + + if (IsWalkableAngle(AngleThresholds.Walkable)) { return E_SurfaceType.Walkable; - } else if (SurfaceAngle <= AngleThresholds.SteepSlope) { + } else if (IsSteepSlopeAngle(AngleThresholds.SteepSlope)) { return E_SurfaceType.SteepSlope; - } else if (SurfaceAngle <= AngleThresholds.Wall) { + } else if (IsWallAngle(AngleThresholds.Wall)) { return E_SurfaceType.Wall; } else { return E_SurfaceType.Ceiling; } } - // Category: "Surface Detection" - // Pure: true /** * Check if surface allows normal walking movement * @param SurfaceType - Surface type to check * @returns True if surface is walkable + * @pure true + * @category Surface Detection */ - IsSurfaceWalkable(SurfaceType: E_SurfaceType): boolean { + private IsSurfaceWalkable(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.Walkable; } - // Category: "Surface Detection" - // Pure: true /** * Check if surface causes sliding behavior * @param SurfaceType - Surface type to check * @returns True if surface is steep slope + * @pure true + * @category Surface Detection */ - IsSurfaceSteep(SurfaceType: E_SurfaceType): boolean { + private IsSurfaceSteep(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.SteepSlope; } - // Category: "Surface Detection" - // Pure: true /** * Check if surface blocks movement (collision) * @param SurfaceType - Surface type to check * @returns True if surface is a wall + * @pure true + * @category Surface Detection */ - IsSurfaceWall(SurfaceType: E_SurfaceType): boolean { + private IsSurfaceWall(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.Wall; } - // Category: "Surface Detection" - // Pure: true /** * Check if surface is overhead (ceiling) * @param SurfaceType - Surface type to check * @returns True if surface is ceiling + * @pure true + * @category Surface Detection */ - IsSurfaceCeiling(SurfaceType: E_SurfaceType): boolean { + private IsSurfaceCeiling(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.Ceiling; } - // Category: "Surface Detection" - // Pure: true /** * Check if no surface detected (airborne state) * @param SurfaceType - Surface type to check * @returns True if no surface contact + * @pure true + * @category Surface Detection */ - IsSurfaceNone(SurfaceType: E_SurfaceType): boolean { + private IsSurfaceNone(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.None; } - // Category: "Debug" - PrintDebugInfo() { - Print('=== Movement System Initialized ==='); - Print(`Walkable: ≤ ${this.AngleThresholdsDegrees.Walkable}°, Steep: ${this.AngleThresholdsDegrees.Walkable}°-${this.AngleThresholdsDegrees.SteepSlope}°, Wall: ${this.AngleThresholdsDegrees.SteepSlope}°-${this.AngleThresholdsDegrees.Wall}°, Ceiling: >${this.AngleThresholdsDegrees.Wall}°`); - Print(`Max Speed: ${this.MovementConstants.MaxSpeed}, Acceleration: ${this.MovementConstants.Acceleration}, Friction: ${this.MovementConstants.Friction}, Gravity: ${this.MovementConstants.Gravity}`); - Print('=================================='); - } - - // Category: "Debug" /** - * Run comprehensive surface classification test suite - * @returns True if all tests pass - */ - TestSurfaceClassification() { - let AllTestsPassed: boolean = true; - - const TestCases: S_SurfaceTestCase[] = [ - { AngleDegrees: 0.0, ExpectedType: E_SurfaceType.Walkable, Description: "Flat surface" }, - { AngleDegrees: 25.0, ExpectedType: E_SurfaceType.Walkable, Description: "Gentle slope" }, - { AngleDegrees: 49.0, ExpectedType: E_SurfaceType.Walkable, Description: "Max walkable" }, - { AngleDegrees: 51.0, ExpectedType: E_SurfaceType.SteepSlope, Description: "Steep slope" }, - { AngleDegrees: 70.0, ExpectedType: E_SurfaceType.SteepSlope, Description: "Very steep" }, - { AngleDegrees: 84.0, ExpectedType: E_SurfaceType.SteepSlope, Description: "Max steep" }, - { AngleDegrees: 90.0, ExpectedType: E_SurfaceType.Wall, Description: "Vertical wall" }, - { AngleDegrees: 94.0, ExpectedType: E_SurfaceType.Wall, Description: "Max wall" }, - { AngleDegrees: 120.0, ExpectedType: E_SurfaceType.Ceiling, Description: "Overhang" }, - { AngleDegrees: 180.0, ExpectedType: E_SurfaceType.Ceiling, Description: "Ceiling" } - ]; - - for (let i = 0; i < TestCases.length; i++) { - const testCase = TestCases[i]; - const normal = this.GenerateNormalFromAngle(testCase.AngleDegrees); - const result = this.ClassifySurface(normal, this.AngleThresholdsRads); - - if (result === testCase.ExpectedType) { - Print(`✅ Test ${i+1} PASS: ${testCase.Description} (${testCase.AngleDegrees}°) = ${testCase.ExpectedType}`); - } else { - Print(`❌ Test ${i+1} FAIL: ${testCase.Description} (${testCase.AngleDegrees}°) expected ${testCase.ExpectedType}, got ${result}`); - AllTestsPassed = false; - } - } - - return AllTestsPassed; - } - - // Category: "System" - /** - * Initialize movement system with angle conversion and testing + * Initialize movement system with angle conversion * Converts degree thresholds to radians for runtime performance - * Runs automated tests if debug mode enabled + * @category System */ - InitializeMovementSystem() { + public InitializeMovementSystem(): void { this.IsInitialized = true; this.AngleThresholdsRads = { - Walkable: D2R(this.AngleThresholdsDegrees.Walkable), - SteepSlope: D2R(this.AngleThresholdsDegrees.SteepSlope), - Wall: D2R(this.AngleThresholdsDegrees.Wall), + Walkable: MathLibrary.DegreesToRadians( + this.AngleThresholdsDegrees.Walkable + ), + SteepSlope: MathLibrary.DegreesToRadians( + this.AngleThresholdsDegrees.SteepSlope + ), + Wall: MathLibrary.DegreesToRadians(this.AngleThresholdsDegrees.Wall), }; - - if (this.ShowDebugInfo) { - this.PrintDebugInfo(); - this.TestSurfaceClassification(); - } } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Movement physics constants + * Controls speed, acceleration, friction, and gravity values + * @category Movement Config + * @instanceEditable true + */ + public readonly MovementConstants: S_MovementConstants = { + MaxSpeed: 600.0, + Acceleration: 2000.0, + Friction: 8.0, + Gravity: 980.0, + }; + + /** + * Surface classification angle thresholds in degrees + * Walkable ≤50°, SteepSlope ≤85°, Wall ≤95°, Ceiling >95° + * @category Movement Config + * @instanceEditable true + */ + public readonly AngleThresholdsDegrees: S_AngleThresholds = { + Walkable: 50.0, + SteepSlope: 85.0, + Wall: 95.0, + }; + + /** + * Runtime cached angle thresholds in radians + * Converted from degrees during initialization for performance + * @category Internal Cache + */ + private AngleThresholdsRads: S_AngleThresholds = { + Walkable: 0.0, + SteepSlope: 0.0, + Wall: 0.0, + }; + + /** + * Flag indicating if movement system has been initialized + * Ensures angle thresholds are converted before use + * @category Debug + */ + public IsInitialized = false; } diff --git a/Content/Movement/Components/AC_Movement.uasset b/Content/Movement/Components/AC_Movement.uasset index 358b46a..10b9cc8 100644 --- a/Content/Movement/Components/AC_Movement.uasset +++ b/Content/Movement/Components/AC_Movement.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21081fc27839294440fd9e7532ba677bdae7410e0178d17947c8896274f61d5b -size 283509 +oid sha256:96cf3e98faa437058bbdff3fb2d7f7658d6c6a6d4108ab73a454f2afd3a8583e +size 124704 diff --git a/Content/Movement/Enums/E_SurfaceType.ts b/Content/Movement/Enums/E_SurfaceType.ts index 191c414..0601161 100644 --- a/Content/Movement/Enums/E_SurfaceType.ts +++ b/Content/Movement/Enums/E_SurfaceType.ts @@ -1,9 +1,9 @@ -// Content/Movement/Enums/E_SurfaceType.ts +// Movement/Enums/E_SurfaceType.ts export enum E_SurfaceType { - None = "None", - Walkable = "Walkable", - SteepSlope = "SteepSlope", - Wall = "Wall", - Ceiling = "Ceiling" + None = 'None', + Walkable = 'Walkable', + SteepSlope = 'SteepSlope', + Wall = 'Wall', + Ceiling = 'Ceiling', } diff --git a/Content/Movement/Structs/S_AngleThresholds.ts b/Content/Movement/Structs/S_AngleThresholds.ts index cd5eb82..0cfe5d4 100644 --- a/Content/Movement/Structs/S_AngleThresholds.ts +++ b/Content/Movement/Structs/S_AngleThresholds.ts @@ -1,9 +1,9 @@ -// Content/Movement/Structs/S_AngleThresholds.ts +// Movement/Structs/S_AngleThresholds.ts -import type {Float} from "../../types.js"; +import type { Float } from '#root/UE/Float.ts'; export interface S_AngleThresholds { - Walkable: Float, - SteepSlope: Float, - Wall: Float, + Walkable: Float; + SteepSlope: Float; + Wall: Float; } diff --git a/Content/Movement/Structs/S_MovementConstants.ts b/Content/Movement/Structs/S_MovementConstants.ts index f951fe2..d38fd93 100644 --- a/Content/Movement/Structs/S_MovementConstants.ts +++ b/Content/Movement/Structs/S_MovementConstants.ts @@ -1,6 +1,6 @@ -// Content/Movement/Structs/S_MovementConstants.ts +// Movement/Structs/S_MovementConstants.ts -import type {Float} from "../../types.js"; +import type { Float } from '#root/UE/Float.ts'; export interface S_MovementConstants { MaxSpeed: Float; diff --git a/Content/Movement/Structs/S_SurfaceTestCase.ts b/Content/Movement/Structs/S_SurfaceTestCase.ts index 959442e..c7bc5aa 100644 --- a/Content/Movement/Structs/S_SurfaceTestCase.ts +++ b/Content/Movement/Structs/S_SurfaceTestCase.ts @@ -1,7 +1,7 @@ -// Content/Movement/Structs/S_SurfaceTestCase.ts +// Movement/Structs/S_SurfaceTestCase.ts -import type {Float} from "../../types.js"; -import type {E_SurfaceType} from "../Enums/E_SurfaceType.js"; +import type { E_SurfaceType } from '#root/Movement/Enums/E_SurfaceType.ts'; +import type { Float } from '#root/UE/Float.ts'; export interface S_SurfaceTestCase { AngleDegrees: Float; diff --git a/Content/Movement/Tests/FT_SurfaceClassification.ts b/Content/Movement/Tests/FT_SurfaceClassification.ts new file mode 100644 index 0000000..35a1cbd --- /dev/null +++ b/Content/Movement/Tests/FT_SurfaceClassification.ts @@ -0,0 +1,146 @@ +// Movement/Tests/FT_SurfaceClassification.ts + +import { BFL_Vectors } from '#root/Math/Libraries/BFL_Vectors.ts'; +import { AC_Movement } from '#root/Movement/Components/AC_Movement.ts'; +import { E_SurfaceType } from '#root/Movement/Enums/E_SurfaceType.ts'; +import { S_AngleThresholds } from '#root/Movement/Structs/S_AngleThresholds.ts'; +import type { S_SurfaceTestCase } from '#root/Movement/Structs/S_SurfaceTestCase.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { FunctionalTest } from '#root/UE/FunctionalTest.ts'; +import { MathLibrary } from '#root/UE/MathLibrary.ts'; + +/** + * Functional Test: Surface Classification System + * Tests angle-based surface type detection across all boundary conditions + * Validates Walkable/SteepSlope/Wall/Ceiling classification accuracy + */ +export class FT_SurfaceClassification extends FunctionalTest { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── + + /** + * Test preparation - converts angle thresholds to radians + * Called before main test execution to prepare test data + */ + EventPrepareTest(): void { + this.AngleThresholdsRads = { + Walkable: MathLibrary.DegreesToRadians( + this.MovementComponent.AngleThresholdsDegrees.Walkable + ), + SteepSlope: MathLibrary.DegreesToRadians( + this.MovementComponent.AngleThresholdsDegrees.SteepSlope + ), + Wall: MathLibrary.DegreesToRadians( + this.MovementComponent.AngleThresholdsDegrees.Wall + ), + }; + } + + /** + * Test execution - validates surface classification for all test cases + * Tests boundary conditions and edge cases for each surface type + */ + EventStartTest(): void { + this.TestCases.forEach( + ({ AngleDegrees, ExpectedType, Description }, arrayIndex) => { + const surfaceType = this.MovementComponent.ClassifySurface( + BFL_Vectors.GetNormalFromAngle(AngleDegrees), + this.AngleThresholdsRads + ); + + if (surfaceType === ExpectedType) { + this.FinishTest(EFunctionalTestResult.Succeeded); + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + `Movement Component test ${arrayIndex + 1} FAIL: ${Description} (${AngleDegrees}°) expected ${ExpectedType}, got ${surfaceType}` + ); + } + } + ); + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Movement system component - provides surface classification functionality + * @category Components + */ + private MovementComponent = new AC_Movement(); + + /** + * Comprehensive test cases covering all surface type boundaries + * Tests edge cases and typical angles for each classification + * @category Test Data + */ + private TestCases: S_SurfaceTestCase[] = [ + { + AngleDegrees: 0.0, + ExpectedType: E_SurfaceType.Walkable, + Description: 'Flat surface', + }, + { + AngleDegrees: 25.0, + ExpectedType: E_SurfaceType.Walkable, + Description: 'Gentle slope', + }, + { + AngleDegrees: 49.0, + ExpectedType: E_SurfaceType.Walkable, + Description: 'Max walkable', + }, + { + AngleDegrees: 51.0, + ExpectedType: E_SurfaceType.SteepSlope, + Description: 'Steep slope', + }, + { + AngleDegrees: 70.0, + ExpectedType: E_SurfaceType.SteepSlope, + Description: 'Very steep', + }, + { + AngleDegrees: 84.0, + ExpectedType: E_SurfaceType.SteepSlope, + Description: 'Max steep', + }, + { + AngleDegrees: 90.0, + ExpectedType: E_SurfaceType.Wall, + Description: 'Vertical wall', + }, + { + AngleDegrees: 94.0, + ExpectedType: E_SurfaceType.Wall, + Description: 'Max wall', + }, + { + AngleDegrees: 120.0, + ExpectedType: E_SurfaceType.Ceiling, + Description: 'Overhang', + }, + { + AngleDegrees: 180.0, + ExpectedType: E_SurfaceType.Ceiling, + Description: 'Ceiling', + }, + ]; + + /** + * Runtime cached angle thresholds in radians + * Converted during preparation for accurate classification testing + * @category Test State + */ + private AngleThresholdsRads: S_AngleThresholds = { + Walkable: 0.0, + SteepSlope: 0.0, + Wall: 0.0, + }; +} diff --git a/Content/Movement/Tests/FT_SurfaceClassification.uasset b/Content/Movement/Tests/FT_SurfaceClassification.uasset new file mode 100644 index 0000000..8cb95f4 --- /dev/null +++ b/Content/Movement/Tests/FT_SurfaceClassification.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c68ba8e62117f19f74ea3d85dc00411715a55ad46684492e80f959d025eae36f +size 118786 diff --git a/Content/Toasts/Components/AC_ToastSystem.ts b/Content/Toasts/Components/AC_ToastSystem.ts new file mode 100644 index 0000000..d1834b9 --- /dev/null +++ b/Content/Toasts/Components/AC_ToastSystem.ts @@ -0,0 +1,271 @@ +// Toasts/Components/AC_ToastSystem.ts + +import type { S_ToastMessage } from '#root/Toasts/Structs/S_ToastMessage.ts'; +import type { S_ToastSettings } from '#root/Toasts/Structs/S_ToastSettings.ts'; +import type { WBP_Toast } from '#root/Toasts/UI/WBP_Toast.ts'; +import { WBP_ToastContainer } from '#root/Toasts/UI/WBP_ToastContainer.ts'; +import { ActorComponent } from '#root/UE/ActorComponent.ts'; +import { CreateWidget } from '#root/UE/CteateWidget.ts'; +import type { Float } from '#root/UE/Float.ts'; +import type { Integer } from '#root/UE/Integer.ts'; +import { SystemLibrary } from '#root/UE/SystemLibrary.ts'; +import type { Text } from '#root/UE/Text.ts'; +import { UEArray } from '#root/UE/UEArray.ts'; +import { E_MessageType } from '#root/UI/Enums/E_MessageType.ts'; + +/** + * Toast Notification System Component + * Manages temporary status messages with automatic positioning and lifecycle + * Provides visual feedback for debug operations and system events + */ +export class AC_ToastSystem extends ActorComponent { + // ════════════════════════════════════════════════════════════════════════════════════════ + // FUNCTIONS + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Check if toast system should process updates this frame + * @returns True if system is initialized and enabled + * @pure + * @category Toast Management + */ + private ShouldProcessToasts(): boolean { + /** + * Validate system state and settings + */ + const function1 = (isEnabled: boolean): boolean => + this.IsInitialized && isEnabled; + + return function1(this.ToastSettings.IsEnabled); + } + + /** + * Remove expired toasts from the system + * @category Toast Lifecycle + */ + private RemoveExpiredToasts(): void { + let i = 0; + + /** + * Check if there are more toasts to process + */ + const HasMoreToastsToCheck = (activeToastsLength: Integer): boolean => + i < activeToastsLength; + + while (HasMoreToastsToCheck(this.ActiveToasts.length)) { + /** + * Check if toast has exceeded its display duration + */ + const IsToastExpired = ( + currentTime: Float, + createdTime: Float, + duration: Float + ): boolean => currentTime - createdTime > duration; + + const el = this.ActiveToasts.Get(i); + + if ( + IsToastExpired( + SystemLibrary.GetGameTimeInSeconds(), + el.CreatedTime, + el.Duration + ) + ) { + const widget = this.ToastWidgets.Get(i); + + if (SystemLibrary.IsValid(widget)) { + if (SystemLibrary.IsValid(this.ToastContainer)) { + this.ToastContainer.RemoveToast(widget); + } + } + + this.ActiveToasts.RemoveIndex(i); + this.ToastWidgets.RemoveIndex(i); + } else { + i++; + } + } + } + + /** + * Enforce maximum visible toasts limit + * Removes oldest toasts when limit is exceeded + * @category Toast Lifecycle + */ + private EnforceToastLimit(): void { + /** + * Check if current toast count exceeds maximum allowed + */ + const ExceedsToastLimit = ( + activeToastsLength: Integer, + maxVisibleToasts: Integer + ): boolean => activeToastsLength >= maxVisibleToasts; + + while ( + ExceedsToastLimit( + this.ActiveToasts.length, + this.ToastSettings.MaxVisibleToasts + ) + ) { + const widget = this.ToastWidgets.Get(0); + + if (SystemLibrary.IsValid(widget)) { + if (SystemLibrary.IsValid(this.ToastContainer)) { + this.ToastContainer.RemoveToast(widget); + } + } + + this.ActiveToasts.RemoveIndex(0); + this.ToastWidgets.RemoveIndex(0); + } + } + + /** + * Create and display a new toast message + * @param Message - Text to display in the toast + * @param Type - Type of toast (affects color and styling) + * @param Duration - How long to display toast (optional, uses default) + * @returns Toast ID for tracking + * @example + * // Create success toast + * ShowToast("Test passed!", E_MessageType.Success, 2.0) + * // Create error toast with default duration + * ShowToast("Test failed!", E_MessageType.Error) + * @category Toast Creation + */ + public ShowToast( + Message: Text = '', + Type: E_MessageType = E_MessageType.Info, + Duration: Float = 0 + ): Integer { + if (this.ShouldProcessToasts()) { + const toastDuration = + Duration !== 0 ? Duration : this.ToastSettings.DefaultDuration; + + const currentTime = SystemLibrary.GetGameTimeInSeconds(); + + const newToast: S_ToastMessage = { + ID: this.NextToastID++, + Message, + Type, + Duration: toastDuration, + CreatedTime: currentTime, + }; + + this.EnforceToastLimit(); + + if (SystemLibrary.IsValid(this.ToastContainer)) { + const toastWidget = this.ToastContainer.AddToast(Message, Type); + + if (SystemLibrary.IsValid(toastWidget)) { + this.ActiveToasts.Add(newToast); + this.ToastWidgets.Add(toastWidget); + this.LogToConsole(Type, Message); + return newToast.ID; + } else { + return -1; + } + } + } + + this.LogToConsole(Type, Message); + return -1; + } + + /** + * Main update loop for toast system + * Removes expired toasts automatically + * @category System Main Loop + */ + public UpdateToastSystem(): void { + if (this.ShouldProcessToasts()) { + this.RemoveExpiredToasts(); + } + } + + /** + * Get toast widgets for testing purposes + * @returns Array of active toast widgets + * @category Testing + */ + public GetTestData(): UEArray { + return this.ToastWidgets; + } + + /** + * Initialize toast system with container widget + * @example + * // Initialize toast system in main character + * this.ToastSystemComponent.InitializeToastSystem(); + * @category System Setup + */ + public InitializeToastSystem(): void { + this.ToastContainer = CreateWidget(WBP_ToastContainer); + this.ToastContainer.InitializeContainer(); + this.IsInitialized = true; + this.NextToastID = 1; + } + + /** + * Log toast message to console if enabled + * @param Type - Message type for formatting + * @param Message - Message text to log + * @category System Utilities + */ + public LogToConsole(Type: E_MessageType, Message: Text): void { + if (this.ToastSettings.AlsoLogToConsole) { + SystemLibrary.PrintString(`[${Type}] ${Message}`, false); + } + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Toast system configuration settings + * Controls capacity, duration, and logging behavior + * @category System Config + * @instanceEditable true + */ + public ToastSettings: S_ToastSettings = { + MaxVisibleToasts: 5, + DefaultDuration: 3.0, + AlsoLogToConsole: true, + IsEnabled: true, + }; + + /** + * System initialization state flag + * Set to true after successful InitializeToastSystem call + * @category System State + */ + private IsInitialized: boolean = false; + + /** + * Next unique ID for new toasts + * Incremented for each new toast + * @category System State + */ + private NextToastID: Integer = 1; + + /** + * Toast container widget that handles positioning and layout + * @category Container Management + */ + private ToastContainer: WBP_ToastContainer | null = null; + + /** + * Array of currently active toast messages + * Contains all visible toasts with metadata + * @category Toast Management + */ + private ActiveToasts: UEArray = new UEArray([]); + + /** + * Array of toast widget instances + * Corresponds to ActiveToasts array for UI display + * @category Widget Management + */ + private ToastWidgets: UEArray = new UEArray([]); +} diff --git a/Content/Toasts/Components/AC_ToastSystem.uasset b/Content/Toasts/Components/AC_ToastSystem.uasset new file mode 100644 index 0000000..2cd5771 --- /dev/null +++ b/Content/Toasts/Components/AC_ToastSystem.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0817e1d04b75968eb18976f0c1ead5efd23441f72a27008711fcc9fc3657cf70 +size 329214 diff --git a/Content/Toasts/Compontents/AC_ToastSystem.ts b/Content/Toasts/Compontents/AC_ToastSystem.ts deleted file mode 100644 index 729dafb..0000000 --- a/Content/Toasts/Compontents/AC_ToastSystem.ts +++ /dev/null @@ -1,192 +0,0 @@ -// Content/Toasts/Components/AC_ToastSystem.ts - -// TODO: Написать тесты - -import {AddToArray, CreateWidget, GetGameTimeInSeconds, IsValid, Print, RemoveIndexFromArray} from "../../functions.js"; -import {WBP_ToastContainer} from "../UI/WBP_ToastContainer.js"; -import type {Float, Integer, Text} from "../../types.js"; -import {E_MessageType} from "../../UI/Enums/E_MessageType.js"; -import type {S_ToastMessage} from "../Structs/S_ToastMessage.js"; -import type {S_ToastSettings} from "../Structs/S_ToastSettings.js"; -import type {WBP_Toast} from "../UI/WBP_Toast.js"; - -export class AC_ToastSystem { - // Category: "System Configuration" - // Instance Editable: true - /** - * Toast system configuration settings - * Simplified - no positioning settings needed - * Instance editable for designer customization - */ - public ToastSettings: S_ToastSettings = { - MaxVisibleToasts: 5, - DefaultDuration: 3.0, - AlsoLogToConsole: true, - IsEnabled: true - }; - - // Category: "System State" - /** - * System initialization state flag - * Set to true after successful InitializeToastSystem call - */ - private IsInitialized: boolean = false; - - // Category: "System State" - /** - * Next unique ID for new toasts - * Incremented for each new toast - */ - private NextToastID: Integer = 1; - - // Category: "Container Management" - /** - * Toast container widget that handles all positioning - * Replaces manual position management - */ - private ToastContainer: WBP_ToastContainer | null = null; - - // Category: "Toast Management" - /** - * Array of currently active toast messages - * Contains all visible toasts - */ - private ActiveToasts: S_ToastMessage[] = []; - - // Category: "Widget Management" - /** - * Array of toast widget instances - * Corresponds to ActiveToasts array - */ - private ToastWidgets: WBP_Toast[] = []; - - // Category: "Toast Management" - // Pure: true - /** - * Check if toast system should process updates this frame - * @returns True if system is initialized and enabled - * @pure Function has no side effects - */ - private ShouldProcessToasts(): boolean { - return this.IsInitialized && this.ToastSettings.IsEnabled && IsValid(this.ToastContainer); - } - - // Category: "Toast Lifecycle" - /** - * Remove expired toasts from the system - * @private Internal cleanup method - */ - private RemoveExpiredToasts(): void { - let i = 0; - - while (i < this.ActiveToasts.length) { - if ((GetGameTimeInSeconds() - this.ActiveToasts[i].CreatedTime) > this.ActiveToasts[i].Duration) { - if (IsValid(this.ToastWidgets[i]) && IsValid(this.ToastContainer)) { - this.ToastContainer.RemoveToast(this.ToastWidgets[i]); - } - - RemoveIndexFromArray(this.ActiveToasts, i); - RemoveIndexFromArray(this.ToastWidgets, i); - } else { - i++; - } - } - } - - // Category: "Toast Lifecycle" - /** - * Enforce maximum visible toasts limit - * Uses container's capacity management - * @private Internal management method - */ - private EnforceToastLimit(): void { - while(this.ActiveToasts.length >= this.ToastSettings.MaxVisibleToasts) { - if (IsValid(this.ToastWidgets[0])) { - this.ToastContainer.RemoveToast(this.ToastWidgets[0]); - } - - RemoveIndexFromArray(this.ActiveToasts, 0); - RemoveIndexFromArray(this.ToastWidgets, 0); - } - } - - // Category: "Toast Creation" - /** - * Create and display a new toast message - * Uses container for automatic positioning - * @param Message - Text to display in the toast - * @param Type - Type of toast (affects color and styling) - * @param Duration - How long to display toast (optional, uses default) - * @returns Toast ID for tracking - * @public Main interface for creating toasts - * @example - * // Create success toast - * ShowToast("Test passed!", E_ToastType.Success, 2.0) - * // Create error toast with default duration - * ShowToast("Test failed!", E_ToastType.Error) - */ - public ShowToast(Message: Text, Type: E_MessageType, Duration?: Float): Integer { - if (this.ShouldProcessToasts()) { - const toastDuration = Duration === 0 ? this.ToastSettings.DefaultDuration : Duration; - const currentTime = GetGameTimeInSeconds(); - const newToast: S_ToastMessage = { - ID: this.NextToastID++, - Message: Message, - Type: Type, - Duration: toastDuration, - CreatedTime: currentTime, - } - - this.EnforceToastLimit(); - - const toastWidget = this.ToastContainer.AddToast(Message, Type); - - if (IsValid(toastWidget)) { - AddToArray(this.ActiveToasts, newToast); - AddToArray(this.ToastWidgets, toastWidget); - - if (this.ToastSettings.AlsoLogToConsole) { - Print(`[${Type}] ${Message}`, false, true); - } - - return newToast.ID; - } else { - return -1; - } - } - - if (this.ToastSettings.AlsoLogToConsole) { - Print(`[${Type}] ${Message}`, false, true); - } - - return -1; - } - - // Category: "System Main Loop" - /** - * Simplified update loop for toast system - * Container handles positioning automatically - * @public Called by BP_MainCharacter or game framework - */ - public UpdateToastSystem(): void { - if (this.ShouldProcessToasts()) { - this.RemoveExpiredToasts(); - } - } - - // Category: "System Setup" - /** - * Initialize toast system with container - * @public Called by BP_MainCharacter during initialization - * @example - * // Initialize toast system in main character - * this.ToastSystemComponent.InitializeToastSystem(); - */ - public InitializeToastSystem(): void { - this.ToastContainer = CreateWidget(new WBP_ToastContainer); - this.ToastContainer.InitializeContainer(); - this.IsInitialized = true; - this.NextToastID = 1; - this.ShowToast(("Toast System Initialized" as Text), E_MessageType.Info); - } -} diff --git a/Content/Toasts/Compontents/AC_ToastSystem.uasset b/Content/Toasts/Compontents/AC_ToastSystem.uasset deleted file mode 100644 index e7405f8..0000000 --- a/Content/Toasts/Compontents/AC_ToastSystem.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bf3da10c44ab63f77715e9ed0303f725532527e65254a26732b8bb8ef258e62e -size 327091 diff --git a/Content/Toasts/Structs/S_ToastMessage.ts b/Content/Toasts/Structs/S_ToastMessage.ts index 6e2832b..4df5335 100644 --- a/Content/Toasts/Structs/S_ToastMessage.ts +++ b/Content/Toasts/Structs/S_ToastMessage.ts @@ -1,7 +1,9 @@ -// Content/Toasts/Structs/S_ToastMessage.ts +// Toasts/Structs/S_ToastMessage.ts -import type {Float, Integer, Text} from "../../types.js"; -import type {E_MessageType} from "../../UI/Enums/E_MessageType.js"; +import type { Float } from '#root/UE/Float.ts'; +import type { Integer } from '#root/UE/Integer.ts'; +import type { Text } from '#root/UE/Text.ts'; +import type { E_MessageType } from '#root/UI/Enums/E_MessageType.ts'; export interface S_ToastMessage { ID: Integer; diff --git a/Content/Toasts/Structs/S_ToastSettings.ts b/Content/Toasts/Structs/S_ToastSettings.ts index 1b7df8b..e0152c2 100644 --- a/Content/Toasts/Structs/S_ToastSettings.ts +++ b/Content/Toasts/Structs/S_ToastSettings.ts @@ -1,6 +1,7 @@ -// Content/Toasts/Structs/S_ToastSettings.ts +// Toasts/Structs/S_ToastSettings.ts -import type {Float, Integer} from "../../types.js"; +import type { Float } from '#root/UE/Float.ts'; +import type { Integer } from '#root/UE/Integer.ts'; export interface S_ToastSettings { MaxVisibleToasts: Integer; diff --git a/Content/Toasts/Tests/FT_ToastLimit.ts b/Content/Toasts/Tests/FT_ToastLimit.ts new file mode 100644 index 0000000..3de561f --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastLimit.ts @@ -0,0 +1,65 @@ +// Toasts/Tests/FT_ToastLimit.ts + +import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { FunctionalTest } from '#root/UE/FunctionalTest.ts'; +import { E_MessageType } from '#root/UI/Enums/E_MessageType.ts'; + +/** + * Functional Test: Toast System Capacity Management + * Validates that the toast system enforces MaxVisibleToasts limit correctly + * Tests that oldest toasts are removed when limit is exceeded + */ +export class FT_ToastLimit extends FunctionalTest { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── + + /** + * Test execution - validates toast limit enforcement + * Creates more toasts than allowed and verifies limit is enforced + */ + EventStartTest(): void { + this.ToastComponent.InitializeToastSystem(); + + // Create MaxVisibleToasts + 3 toasts to test overflow handling + for ( + let i = 1; + i <= this.ToastComponent.ToastSettings.MaxVisibleToasts + 3; + i++ + ) { + this.ToastComponent.ShowToast( + `Limit test toast ${i}`, + E_MessageType.Info, + 10 + ); + } + + // Verify that only MaxVisibleToasts are actually visible + if ( + this.ToastComponent.GetTestData().length === + this.ToastComponent.ToastSettings.MaxVisibleToasts + ) { + this.FinishTest(EFunctionalTestResult.Succeeded); + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + `Expected ${this.ToastComponent.ToastSettings.MaxVisibleToasts} to display, got ${this.ToastComponent.GetTestData().length}` + ); + } + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Toast notification system - component under test + * @category Components + */ + private ToastComponent = new AC_ToastSystem(); +} diff --git a/Content/Toasts/Tests/FT_ToastLimit.uasset b/Content/Toasts/Tests/FT_ToastLimit.uasset new file mode 100644 index 0000000..5d8d233 --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastLimit.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:625fea7bb0ee603082d5c3d05e9119aea890ae2f7eb55374c981348b5b230396 +size 92151 diff --git a/Content/Toasts/Tests/FT_ToastsDurationHandling.ts b/Content/Toasts/Tests/FT_ToastsDurationHandling.ts new file mode 100644 index 0000000..a841afe --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastsDurationHandling.ts @@ -0,0 +1,65 @@ +// Toasts/Tests/FT_ToastsDurationHandling.ts + +import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { FunctionalTest } from '#root/UE/FunctionalTest.ts'; +import type { Integer } from '#root/UE/Integer.ts'; + +/** + * Functional Test: Toast Duration and Lifecycle Management + * Validates basic toast creation and ID assignment functionality + * Tests that toasts return valid IDs when created successfully + */ +export class FT_ToastsDurationHandling extends FunctionalTest { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── + + /** + * Test execution - validates basic toast creation functionality + * Creates two toasts and verifies they return valid IDs + */ + EventStartTest(): void { + this.ToastComponent.InitializeToastSystem(); + this.toast1 = this.ToastComponent.ShowToast(); + this.toast2 = this.ToastComponent.ShowToast(); + + /** + * Check if both toasts were created successfully by verifying positive IDs + */ + const AreToastsCreatedSuccessfully = (): boolean => + this.toast1 > 0 && this.toast2 > 0; + + if (AreToastsCreatedSuccessfully()) { + this.FinishTest(EFunctionalTestResult.Succeeded); + } else { + this.FinishTest(EFunctionalTestResult.Failed, `Failed to create toasts`); + } + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Toast notification system - component under test + * @category Components + */ + private ToastComponent = new AC_ToastSystem(); + + /** + * ID of first test toast + * @category Test State + */ + private toast1: Integer = 0; + + /** + * ID of second test toast + * @category Test State + */ + private toast2: Integer = 0; +} diff --git a/Content/Toasts/Tests/FT_ToastsDurationHandling.uasset b/Content/Toasts/Tests/FT_ToastsDurationHandling.uasset new file mode 100644 index 0000000..2ce3173 --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastsDurationHandling.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf6944970af52a7862fd71666e8ae39830c754f382b60eb5af1e8cc282124d0e +size 71006 diff --git a/Content/Toasts/Tests/FT_ToastsEdgeCases.ts b/Content/Toasts/Tests/FT_ToastsEdgeCases.ts new file mode 100644 index 0000000..e806f71 --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastsEdgeCases.ts @@ -0,0 +1,105 @@ +// Toasts/Tests/FT_ToastsEdgeCases.ts + +import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { FunctionalTest } from '#root/UE/FunctionalTest.ts'; +import type { Integer } from '#root/UE/Integer.ts'; +import { StringLibrary } from '#root/UE/StringLibrary.ts'; +import type { Text } from '#root/UE/Text.ts'; +import { TextLibrary } from '#root/UE/TextLibrary.ts'; + +/** + * Functional Test: Toast System Edge Cases + * Tests toast system robustness with unusual input conditions + * Validates handling of empty, very long, and multiline messages + */ +export class FT_ToastsEdgeCases extends FunctionalTest { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── + + /** + * Test preparation - generates very long text for stress testing + * Creates 500-character string to test text handling limits + */ + EventPrepareTest(): void { + for (let i = 0; i < 500; i++) { + this.longText = TextLibrary.StringToText( + StringLibrary.Append(TextLibrary.TextToString(this.longText), 'A') + ); + } + } + + /** + * Test execution - validates edge case handling + * Tests empty text, very long text, and multiline text scenarios + */ + EventStartTest(): void { + this.ToastComponent.InitializeToastSystem(); + + // Test empty message handling + this.emptyToast = this.ToastComponent.ShowToast(); + + // Test very long message handling (500 characters) + this.longToast = this.ToastComponent.ShowToast(this.longText); + + // Test multiline message handling + this.specialToast = this.ToastComponent.ShowToast(`Test +Multiline +Message`); + + /** + * Check if all edge case toasts were created successfully + */ + const AreToastsCreatedSuccessfully = (): boolean => + this.emptyToast > 0 && this.longToast > 0 && this.specialToast > 0; + + if (AreToastsCreatedSuccessfully()) { + this.FinishTest(EFunctionalTestResult.Succeeded); + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + `Edge case failures: empty=${this.emptyToast}, long=${this.longToast}, special=${this.specialToast}` + ); + } + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Toast notification system - component under test + * @category Components + */ + private ToastComponent = new AC_ToastSystem(); + + /** + * ID of toast created with empty message + * @category Test State + */ + private emptyToast: Integer = 0; + + /** + * ID of toast created with very long message (500 chars) + * @category Test State + */ + private longToast: Integer = 0; + + /** + * ID of toast created with multiline message + * @category Test State + */ + private specialToast: Integer = 0; + + /** + * Generated long text string for stress testing + * Built during test preparation phase + * @category Test Data + */ + private longText: Text = ''; +} diff --git a/Content/Toasts/Tests/FT_ToastsEdgeCases.uasset b/Content/Toasts/Tests/FT_ToastsEdgeCases.uasset new file mode 100644 index 0000000..9ce63b6 --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastsEdgeCases.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5eb6c61c49c4b0f909138c0cfe77a7286572e2c7da5163b1e90fd0bc8f764464 +size 125581 diff --git a/Content/Toasts/Tests/FT_ToastsSystemInitialization.ts b/Content/Toasts/Tests/FT_ToastsSystemInitialization.ts new file mode 100644 index 0000000..7a477b3 --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastsSystemInitialization.ts @@ -0,0 +1,54 @@ +// Toasts/Tests/FT_ToastsSystemInitialization.ts + +import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { FunctionalTest } from '#root/UE/FunctionalTest.ts'; + +/** + * Functional Test: Toast System Initialization + * Validates that toast system initializes with correct default settings + * Tests IsEnabled state and MaxVisibleToasts configuration + */ +export class FT_ToastsSystemInitialization extends FunctionalTest { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── + + /** + * Test execution - validates initialization and default settings + * Uses nested validation to check system state after initialization + */ + EventStartTest(): void { + this.ToastComponent.InitializeToastSystem(); + + if (this.ToastComponent.ToastSettings.IsEnabled) { + if (this.ToastComponent.ToastSettings.MaxVisibleToasts > 0) { + this.FinishTest(EFunctionalTestResult.Succeeded); + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + 'Invalid state: max visible toasts less then 1' + ); + } + } else { + this.FinishTest( + EFunctionalTestResult.Failed, + 'Invalid state: enabled=false' + ); + } + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Toast notification system - component under test + * @category Components + */ + private ToastComponent = new AC_ToastSystem(); +} diff --git a/Content/Toasts/Tests/FT_ToastsSystemInitialization.uasset b/Content/Toasts/Tests/FT_ToastsSystemInitialization.uasset new file mode 100644 index 0000000..45c2bc6 --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastsSystemInitialization.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1869b30aa3779d6f0f8aa367bd431ce107ebd1ff3627011655977811d461bf16 +size 57319 diff --git a/Content/Toasts/Tests/FT_ToastsToastCreation.ts b/Content/Toasts/Tests/FT_ToastsToastCreation.ts new file mode 100644 index 0000000..da43053 --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastsToastCreation.ts @@ -0,0 +1,71 @@ +// Toasts/Tests/FT_ToastsToastCreation.ts + +import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { FunctionalTest } from '#root/UE/FunctionalTest.ts'; +import { UEArray } from '#root/UE/UEArray.ts'; +import { E_MessageType } from '#root/UI/Enums/E_MessageType.ts'; + +/** + * Functional Test: Toast Creation by Message Type + * Validates toast creation functionality for all message types + * Tests that each type (Info, Success, Warning, Error, Debug) creates valid toasts + */ +export class FT_ToastsToastCreation extends FunctionalTest { + // ════════════════════════════════════════════════════════════════════════════════════════ + // GRAPHS + // ════════════════════════════════════════════════════════════════════════════════════════ + + // ──────────────────────────────────────────────────────────────────────────────────────── + // EventGraph + // ──────────────────────────────────────────────────────────────────────────────────────── + + /** + * Test execution - validates toast creation for each message type + * Iterates through all message types and verifies successful creation + */ + EventStartTest(): void { + this.ToastComponent.InitializeToastSystem(); + + this.ToastTypes.forEach(arrayElement => { + // Create toast for current message type and check if valid ID is returned + if ( + this.ToastComponent.ShowToast( + `Test ${arrayElement} message`, + arrayElement, + 1 + ) <= 0 + ) { + this.FinishTest( + EFunctionalTestResult.Failed, + `Failed to create ${arrayElement} toast` + ); + } + }); + + this.FinishTest(EFunctionalTestResult.Succeeded); + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Toast notification system - component under test + * @category Components + */ + private ToastComponent = new AC_ToastSystem(); + + /** + * Array of all message types to test + * Covers complete range of supported toast types + * @category Test Data + */ + private ToastTypes: UEArray = new UEArray([ + E_MessageType.Info, + E_MessageType.Success, + E_MessageType.Warning, + E_MessageType.Error, + E_MessageType.Debug, + ]); +} diff --git a/Content/Toasts/Tests/FT_ToastsToastCreation.uasset b/Content/Toasts/Tests/FT_ToastsToastCreation.uasset new file mode 100644 index 0000000..d2fb19a --- /dev/null +++ b/Content/Toasts/Tests/FT_ToastsToastCreation.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad4d58eead90bcce5467acdcf352ccf040e5b00876f31288c0138ba6b0d904c7 +size 72433 diff --git a/Content/Toasts/UI/WBP_Toast.ts b/Content/Toasts/UI/WBP_Toast.ts index 5d6a9a8..b01e9ce 100644 --- a/Content/Toasts/UI/WBP_Toast.ts +++ b/Content/Toasts/UI/WBP_Toast.ts @@ -1,119 +1,113 @@ -// Content/Toasts/UI/WBP_Toast.ts +// Toasts/UI/WBP_Toast.ts -import {Border, TextBox, Widget} from "../../classes.js"; -import {E_MessageType} from "../../UI/Enums/E_MessageType.js"; -import type {Color, Text} from "../../types.js"; -import {IsValid} from "../../functions.js"; +import { Border } from '#root/UE/Border.ts'; +import { MathLibrary } from '#root/UE/MathLibrary.ts'; +import { SystemLibrary } from '#root/UE/SystemLibrary.ts'; +import type { Text } from '#root/UE/Text.ts'; +import { TextBlock } from '#root/UE/TextBlock.ts'; +import { UserWidget } from '#root/UE/UserWidget.ts'; +import { E_MessageType } from '#root/UI/Enums/E_MessageType.ts'; +import { BFL_Colors } from '#root/UI/Libraries/BFL_Colors.ts'; + +/** + * Individual Toast Notification Widget + * Displays a single toast message with type-based styling + * Managed by WBP_ToastContainer for positioning and lifecycle + */ +export class WBP_Toast extends UserWidget { + // ════════════════════════════════════════════════════════════════════════════════════════ + // FUNCTIONS + // ════════════════════════════════════════════════════════════════════════════════════════ -export class WBP_Toast extends Widget { - // Category: "Toast Data" /** - * Current message text displayed in this toast + * Update background styling based on toast type + * Uses color library to get appropriate color for message type + * @category Display Updates */ - private MessageText: Text = "" as Text; - - // Category: "Toast Data" - /** - * Toast type for color and styling - */ - private ToastType: E_MessageType = E_MessageType.Info; - - // Category: "UI Components" - /** - * Text box widget for displaying toast message - * Styled based on toast type - */ - private MessageTextBox = new TextBox(); - - // Category: "UI Components" - /** - * Background panel for toast styling - * Color changes based on toast type - */ - private BackgroundPanel = new Border(); - - // Category: "Toast Styling" - /** - * Get color based on toast type - * @param Type - Toast type - * @returns Color string in hex format - * @pure Function has no side effects - */ - private GetToastColor(Type: E_MessageType): Color { - switch (Type) { - case E_MessageType.Info: - return {R: 74, G: 144, B: 226, A: 100}; // Blue - case E_MessageType.Success: - return {R: 92, G: 184, B: 92, A: 100}; // Green - case E_MessageType.Warning: - return {R: 240, G: 173, B: 78, A: 100}; // Orange - case E_MessageType.Error: - return {R: 217, G: 83, B: 79, A: 100}; // Red - case E_MessageType.Debug: - return {R: 108, G: 177, B: 125, A: 100}; // Gray - case E_MessageType.Test: - return {R: 142, G: 68, B: 142, A: 100}; // Purple + private UpdateBackgroundStyling(): void { + if (SystemLibrary.IsValid(this.BackgroundPanel)) { + this.BackgroundPanel.SetBrushColor( + MathLibrary.ColorToLinearColor( + BFL_Colors.GetColorByMessageType(this.ToastType, 100) + ) + ); } } - // Category: "Display Updates" /** - * Update message text box with current message - * @private Internal display update method + * Update message text box with current message text + * @category Display Updates */ private UpdateMessageDisplay(): void { - if (IsValid(this.MessageTextBox)) { + if (SystemLibrary.IsValid(this.MessageTextBox)) { this.MessageTextBox.SetText(this.MessageText); } } - // Category: "Display Updates" - /** - * Update background styling based on toast type - * @private Internal display update method - */ - private UpdateBackgroundStyling(): void { - if (IsValid(this.BackgroundPanel)) { - this.BackgroundPanel.SetBrushColor(this.GetToastColor(this.ToastType)); - } - } - - // Category: "Public Interface" /** * Set toast message and update display * @param Message - New message text * @example * // Set success message * SetMessage("Test completed successfully!") + * @category Public Interface */ public SetMessage(Message: Text): void { this.MessageText = Message; this.UpdateMessageDisplay(); } - // Category: "Public Interface" /** * Set toast type and update styling * @param Type - New toast type * @example * // Set as error toast - * SetToastType(E_ToastType.Error) + * SetToastType(E_MessageType.Error) + * @category Public Interface */ public SetToastType(Type: E_MessageType): void { this.ToastType = Type; this.UpdateBackgroundStyling(); } - // Category: "Widget Lifecycle" /** * Initialize toast widget with message and type + * Adds widget to viewport for display * @param Message - Initial message text * @param Type - Initial toast type - * @public Called when creating new toast + * @category Widget Lifecycle */ public InitializeToast(Message: Text, Type: E_MessageType): void { this.SetMessage(Message); this.SetToastType(Type); this.AddToViewport(); } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Current message text displayed in this toast + * @category Toast Data + */ + private MessageText: Text = ''; + + /** + * Toast type for color and styling determination + * @category Toast Data + */ + private ToastType: E_MessageType = E_MessageType.Info; + + /** + * Text widget for displaying the toast message + * @category UI Components + */ + private MessageTextBox = new TextBlock(); + + /** + * Background border widget for toast styling and color + * @category UI Components + */ + private BackgroundPanel = new Border(); } diff --git a/Content/Toasts/UI/WBP_Toast.uasset b/Content/Toasts/UI/WBP_Toast.uasset index b3f85b4..6256e31 100644 --- a/Content/Toasts/UI/WBP_Toast.uasset +++ b/Content/Toasts/UI/WBP_Toast.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be3021b007accf4deaf92ebb84c4e8b56a983bdc2b3f3cbed4f38cc280fd54ff -size 88664 +oid sha256:8d1785d1a672f23900f5b2cc5d051f89ab2a3e276bd5ef2fb614a69345faa2b8 +size 85766 diff --git a/Content/Toasts/UI/WBP_ToastContainer.ts b/Content/Toasts/UI/WBP_ToastContainer.ts index 95ec2fd..2e89eb1 100644 --- a/Content/Toasts/UI/WBP_ToastContainer.ts +++ b/Content/Toasts/UI/WBP_ToastContainer.ts @@ -1,61 +1,76 @@ -// Content/Toasts/UI/WBP_ToastContainer.ts +// Toasts/UI/WBP_ToastContainer.ts -import {VerticalBox, Widget} from "../../classes.js"; -import {ESlateVisibility} from "../../enums.js"; -import type {Text} from "../../types.js"; -import type {E_MessageType} from "../../UI/Enums/E_MessageType.js"; -import {WBP_Toast} from "./WBP_Toast.js"; -import {AddToArray, CreateWidget, IsValid, RemoveItemFromArray} from "../../functions.js"; +import { WBP_Toast } from '#root/Toasts/UI/WBP_Toast.ts'; +import { CreateWidget } from '#root/UE/CteateWidget.ts'; +import { ESlateVisibility } from '#root/UE/ESlateVisibility.ts'; +import { SystemLibrary } from '#root/UE/SystemLibrary.ts'; +import type { Text } from '#root/UE/Text.ts'; +import { UEArray } from '#root/UE/UEArray.ts'; +import { UserWidget } from '#root/UE/UserWidget.ts'; +import { VerticalBox } from '#root/UE/VerticalBox.ts'; +import type { E_MessageType } from '#root/UI/Enums/E_MessageType.ts'; + +/** + * Toast Container Widget + * Manages layout and positioning of multiple toast notifications + * Automatically stacks toasts vertically with proper spacing + */ +export class WBP_ToastContainer extends UserWidget { + // ════════════════════════════════════════════════════════════════════════════════════════ + // FUNCTIONS + // ════════════════════════════════════════════════════════════════════════════════════════ -export class WBP_ToastContainer extends Widget { - // Category: "Layout" /** - * Vertical box container for automatic toast stacking - * Handles spacing and positioning automatically + * Create and add new toast to container + * @param Message - Toast message text + * @param Type - Toast type for styling + * @returns Created toast widget reference + * @category Toast Management */ - private ToastVerticalBox = new VerticalBox(); + public AddToast(Message: Text, Type: E_MessageType): WBP_Toast { + const toast = CreateWidget(WBP_Toast); + toast.InitializeToast(Message, Type); + this.ToastVerticalBox.AddChild(toast); + this.ChildToasts.Add(toast); + return toast; + } - // Category: "Container Management" /** - * Array of child toast widgets for management + * Remove toast from container and hide it + * @param Toast - Toast widget to remove + * @category Toast Management */ - private ChildToasts: WBP_Toast[] = []; + public RemoveToast(Toast: WBP_Toast): void { + if (SystemLibrary.IsValid(Toast)) { + this.ChildToasts.Remove(Toast); + Toast.SetVisibility(ESlateVisibility.Hidden); + Toast.RemoveFromParent(); + } + } - // Category: "Container Setup" /** - * Initialize toast container - * Sets up vertical box with proper spacing + * Initialize container widget and add to viewport + * @category Container Setup */ public InitializeContainer(): void { this.SetVisibility(ESlateVisibility.Visible); this.AddToViewport(); } - // Category: "Toast Management" - /** - * Add new toast to container - * @param Message - Toast message - * @param Type - Toast type - * @returns Created toast widget reference - */ - public AddToast(Message: Text, Type: E_MessageType): WBP_Toast { - const toast = CreateWidget(new WBP_Toast()); - toast.InitializeToast(Message, Type); - this.ToastVerticalBox.AddChild(toast); - AddToArray(this.ChildToasts, toast); - return toast; - } + // ════════════════════════════════════════════════════════════════════════════════════════ + // VARIABLES + // ════════════════════════════════════════════════════════════════════════════════════════ - // Category: "Toast Management" /** - * Remove toast from container - * @param Toast - Toast widget to remove + * Vertical layout container for automatic toast stacking + * Handles spacing and positioning automatically + * @category Layout */ - public RemoveToast(Toast: WBP_Toast): void { - if (IsValid(Toast)) { - RemoveItemFromArray(this.ChildToasts, Toast); - Toast.SetVisibility(ESlateVisibility.Hidden); - Toast.RemoveFromParent(); - } - } + private ToastVerticalBox = new VerticalBox(); + + /** + * Array of managed child toast widgets + * @category Container Management + */ + private ChildToasts: UEArray = new UEArray([]); } diff --git a/Content/Toasts/UI/WBP_ToastContainer.uasset b/Content/Toasts/UI/WBP_ToastContainer.uasset index 76ec014..2bc65fa 100644 --- a/Content/Toasts/UI/WBP_ToastContainer.uasset +++ b/Content/Toasts/UI/WBP_ToastContainer.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb70d90d6aa7a58883e2c70e40ff32dbdbd0275532aaf87d45990b6c9e3949d4 -size 98680 +oid sha256:8c341f575b0a472d38ffbba5115e98a75e594b62fa70d273b1e93db2a72fa75f +size 98816 diff --git a/Content/UE/Actor.ts b/Content/UE/Actor.ts new file mode 100644 index 0000000..a72eeb0 --- /dev/null +++ b/Content/UE/Actor.ts @@ -0,0 +1,10 @@ +// UE/Actor.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class Actor extends UEObject { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/ActorComponent.ts b/Content/UE/ActorComponent.ts new file mode 100644 index 0000000..77e7146 --- /dev/null +++ b/Content/UE/ActorComponent.ts @@ -0,0 +1,10 @@ +// UE/ActorComponent.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class ActorComponent extends UEObject { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/BlueprintFunctionLibrary.ts b/Content/UE/BlueprintFunctionLibrary.ts new file mode 100644 index 0000000..de111b3 --- /dev/null +++ b/Content/UE/BlueprintFunctionLibrary.ts @@ -0,0 +1,12 @@ +// UE/BlueprintFunctionLibrary.ts + +import { UEObject } from '#root/UE/UEObject.ts'; + +export class BlueprintFunctionLibrary extends UEObject { + constructor( + outer: UEObject | null = null, + name: string = 'BlueprintFunctionLibrary' + ) { + super(outer, name); + } +} diff --git a/Content/UE/Border.ts b/Content/UE/Border.ts new file mode 100644 index 0000000..157adef --- /dev/null +++ b/Content/UE/Border.ts @@ -0,0 +1,16 @@ +// UE/Border.ts + +import { ContentWidget } from '#root/UE/ContentWidget.ts'; +import type { LinearColor } from '#root/UE/LinearColor.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class Border extends ContentWidget { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } + + public SetBrushColor(color: LinearColor): void { + console.log(color); + } +} diff --git a/Content/UE/Byte.ts b/Content/UE/Byte.ts new file mode 100644 index 0000000..fac1342 --- /dev/null +++ b/Content/UE/Byte.ts @@ -0,0 +1,3 @@ +// UE/Byte.ts + +export type Byte = number; diff --git a/Content/UE/Cast.ts b/Content/UE/Cast.ts new file mode 100644 index 0000000..a238692 --- /dev/null +++ b/Content/UE/Cast.ts @@ -0,0 +1,5 @@ +// Content/Cast.ts + +export function Cast(obj: unknown): T | null { + return (obj as T) || null; +} diff --git a/Content/UE/Color.ts b/Content/UE/Color.ts new file mode 100644 index 0000000..a0c2343 --- /dev/null +++ b/Content/UE/Color.ts @@ -0,0 +1,15 @@ +// UE/Color.ts + +import { StructBase } from '#root/UE/StructBase.ts'; +import type { UInt8 } from '#root/UE/UInt8.ts'; + +export class Color extends StructBase { + constructor( + public B: UInt8 = 0, + public G: UInt8 = 0, + public R: UInt8 = 0, + public A: UInt8 = 0 + ) { + super(); + } +} diff --git a/Content/UE/ContentWidget.ts b/Content/UE/ContentWidget.ts new file mode 100644 index 0000000..7b92cba --- /dev/null +++ b/Content/UE/ContentWidget.ts @@ -0,0 +1,11 @@ +// UE/ContentWidget.ts + +import { Name } from '#root/UE/Name.ts'; +import { PanelWidget } from '#root/UE/PanelWidget.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class ContentWidget extends PanelWidget { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/Controller.ts b/Content/UE/Controller.ts new file mode 100644 index 0000000..37f57c0 --- /dev/null +++ b/Content/UE/Controller.ts @@ -0,0 +1,15 @@ +// UE/Controller.ts + +import { Actor } from '#root/UE/Actor.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class Controller extends Actor { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } + + public CastToPlayerController(): Controller { + return this; + } +} diff --git a/Content/UE/CteateWidget.ts b/Content/UE/CteateWidget.ts new file mode 100644 index 0000000..7f05d04 --- /dev/null +++ b/Content/UE/CteateWidget.ts @@ -0,0 +1,11 @@ +// UE/CreateWidget.ts + +import type { UserWidget } from '#root/UE/UserWidget.ts'; + +type WidgetConstructor = new () => T; + +export function CreateWidget( + widgetClass: WidgetConstructor +): T { + return new widgetClass(); +} diff --git a/Content/UE/DataAsset.ts b/Content/UE/DataAsset.ts new file mode 100644 index 0000000..4f1087a --- /dev/null +++ b/Content/UE/DataAsset.ts @@ -0,0 +1,10 @@ +// UE/DataAsset.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class DataAsset extends UEObject { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/DataTable.ts b/Content/UE/DataTable.ts new file mode 100644 index 0000000..413b366 --- /dev/null +++ b/Content/UE/DataTable.ts @@ -0,0 +1,41 @@ +// UE/DataTable.ts + +import { Name } from '#root/UE/Name.ts'; +import type { UEArray } from '#root/UE/UEArray.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class DataTable extends UEObject { + private rows: Map = new Map(); + + constructor( + outer: UEObject | null = null, + name: Name = Name.NONE, + initialData: UEArray = [] as unknown as UEArray< + T & { Name: Name } + > + ) { + super(outer, name); + + initialData.forEach(row => { + this.rows.set(row.Name, row); + }); + } + + public GetDataTableRow( + rowName: Name, + rowFound?: (row: T) => void, + rowNotFound?: () => void + ): void | T | undefined { + const row = this.rows.get(rowName); + + if (!rowFound && !rowNotFound) { + return row; + } + + if (row) { + rowFound?.(row); + } else { + rowNotFound?.(); + } + } +} diff --git a/Content/UE/DataTableFunctionLibrary.ts b/Content/UE/DataTableFunctionLibrary.ts new file mode 100644 index 0000000..48e3789 --- /dev/null +++ b/Content/UE/DataTableFunctionLibrary.ts @@ -0,0 +1,20 @@ +// UE/DataTableFunctionLibrary.ts + +import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts'; +import type { DataTable } from '#root/UE/DataTable.ts'; +import { Name } from '#root/UE/Name.ts'; + +class DataTableFunctionLibraryClass extends BlueprintFunctionLibrary { + constructor( + outer: null | BlueprintFunctionLibrary = null, + name: string = 'DataTableFunctionLibrary' + ) { + super(outer, name); + } + + public GetDataTableRowNames(table: DataTable): Name[] { + return Array.from(table['rows'].keys()); + } +} + +export const DataTableFunctionLibrary = new DataTableFunctionLibraryClass(); diff --git a/Content/UE/EFunctionalTestResult.ts b/Content/UE/EFunctionalTestResult.ts new file mode 100644 index 0000000..b014837 --- /dev/null +++ b/Content/UE/EFunctionalTestResult.ts @@ -0,0 +1,10 @@ +// UE/EFunctionalTestResult.ts + +export enum EFunctionalTestResult { + 'Default' = 'Default', + 'Invalid' = 'Invalid', + 'Error' = 'Error', + 'Running' = 'Running', + 'Failed' = 'Failed', + 'Succeeded' = 'Succeeded', +} diff --git a/Content/UE/ESlateVisibility.ts b/Content/UE/ESlateVisibility.ts new file mode 100644 index 0000000..5b3d21f --- /dev/null +++ b/Content/UE/ESlateVisibility.ts @@ -0,0 +1,9 @@ +// UE/ESlateVisibility.ts + +export enum ESlateVisibility { + Visible = 'Visible', + Collapsed = 'Collapsed', + Hidden = 'Hidden', + NotHitTestableSelfAndAllChildren = 'NotHitTestableSelfAndAllChildren', + NotHitTestableSelfOnly = 'NotHitTestableSelfOnly', +} diff --git a/Content/UE/EnhancedActionKeyMapping.ts b/Content/UE/EnhancedActionKeyMapping.ts new file mode 100644 index 0000000..fb762a3 --- /dev/null +++ b/Content/UE/EnhancedActionKeyMapping.ts @@ -0,0 +1,29 @@ +// UE/EnhancedActionKeyMapping.ts + +import type { InputAction } from '#root/UE/InputAction.ts'; +import type { InputModifier } from '#root/UE/InputModifier.ts'; +import type { InputTrigger } from '#root/UE/InputTrigger.ts'; +import type { Key } from '#root/UE/Key.ts'; +import { StructBase } from '#root/UE/StructBase.ts'; +import type { UEArray } from '#root/UE/UEArray.ts'; + +export class EnhancedActionKeyMapping extends StructBase { + public action: InputAction; + public key: Key; + public modifiers: UEArray; + public triggers: UEArray; + + constructor( + triggers: UEArray, + modifiers: UEArray, + action: InputAction, + key: Key + ) { + super(); + + this.action = action; + this.key = key; + this.modifiers = modifiers; + this.triggers = triggers; + } +} diff --git a/Content/UE/EnhancedInputLocalPlayerSubsystem.ts b/Content/UE/EnhancedInputLocalPlayerSubsystem.ts new file mode 100644 index 0000000..3eba426 --- /dev/null +++ b/Content/UE/EnhancedInputLocalPlayerSubsystem.ts @@ -0,0 +1,22 @@ +// UE/EnhancedInputLocalPlayerSubsystem.ts + +import type { InputMappingContext } from '#root/UE/InputMappingContext.ts'; +import type { Integer } from '#root/UE/Integer.ts'; +import { LocalPlayerSubsystem } from '#root/UE/LocalPlayerSubsystem.ts'; +import { ModifyContextOptions } from '#root/UE/ModifyContextOptions.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class EnhancedInputLocalPlayerSubsystem extends LocalPlayerSubsystem { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } + + public AddMappingContext( + mappingContent: InputMappingContext, + priority: Integer = 0, + options: ModifyContextOptions = new ModifyContextOptions(true, false, false) + ): void { + console.log(mappingContent, priority, options); + } +} diff --git a/Content/UE/Float.ts b/Content/UE/Float.ts new file mode 100644 index 0000000..826c3af --- /dev/null +++ b/Content/UE/Float.ts @@ -0,0 +1,3 @@ +// UE/Float.ts + +export type Float = number; diff --git a/Content/UE/FunctionalTest.ts b/Content/UE/FunctionalTest.ts new file mode 100644 index 0000000..54b6d6e --- /dev/null +++ b/Content/UE/FunctionalTest.ts @@ -0,0 +1,21 @@ +// UE/FunctionalTest.ts + +import { Actor } from '#root/UE/Actor.ts'; +import { EFunctionalTestResult } from '#root/UE/EFunctionalTestResult.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class FunctionalTest extends Actor { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } + + public FinishTest( + testResult: EFunctionalTestResult = EFunctionalTestResult.Default, + message: string = '' + ): void { + console.log( + `Test Finished with result: ${testResult}. Message: ${message}` + ); + } +} diff --git a/Content/UE/GameModeBase.ts b/Content/UE/GameModeBase.ts new file mode 100644 index 0000000..f83081b --- /dev/null +++ b/Content/UE/GameModeBase.ts @@ -0,0 +1,11 @@ +// Content/GameModeBase.ts + +import { Info } from '#root/UE/Info.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class GameModeBase extends Info { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/Info.ts b/Content/UE/Info.ts new file mode 100644 index 0000000..bb5b9ee --- /dev/null +++ b/Content/UE/Info.ts @@ -0,0 +1,11 @@ +// UE/Info.ts + +import { Actor } from '#root/UE/Actor.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class Info extends Actor { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/InputAction.ts b/Content/UE/InputAction.ts new file mode 100644 index 0000000..b5ec03a --- /dev/null +++ b/Content/UE/InputAction.ts @@ -0,0 +1,11 @@ +// UE/InputAction.ts + +import { DataAsset } from '#root/UE/DataAsset.ts'; +import { Name } from '#root/UE/Name.ts'; +import type { UEObject } from '#root/UE/UEObject.ts'; + +export class InputAction extends DataAsset { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/InputMappingContext.ts b/Content/UE/InputMappingContext.ts new file mode 100644 index 0000000..684aba6 --- /dev/null +++ b/Content/UE/InputMappingContext.ts @@ -0,0 +1,26 @@ +// UE/InputMappingContext.ts + +import { DataAsset } from '#root/UE/DataAsset.ts'; +import { EnhancedActionKeyMapping } from '#root/UE/EnhancedActionKeyMapping.ts'; +import type { InputAction } from '#root/UE/InputAction.ts'; +import type { InputModifier } from '#root/UE/InputModifier.ts'; +import type { InputTrigger } from '#root/UE/InputTrigger.ts'; +import type { Key } from '#root/UE/Key.ts'; +import { Name } from '#root/UE/Name.ts'; +import type { UEArray } from '#root/UE/UEArray.ts'; +import type { UEObject } from '#root/UE/UEObject.ts'; + +export class InputMappingContext extends DataAsset { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } + + public mapKey(action: InputAction, toKey: Key): EnhancedActionKeyMapping { + return new EnhancedActionKeyMapping( + [] as unknown as UEArray, + [] as unknown as UEArray, + action, + toKey + ); + } +} diff --git a/Content/UE/InputModifier.ts b/Content/UE/InputModifier.ts new file mode 100644 index 0000000..d99f732 --- /dev/null +++ b/Content/UE/InputModifier.ts @@ -0,0 +1,10 @@ +// UE/InputModifier.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class InputModifier extends UEObject { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/InputTrigger.ts b/Content/UE/InputTrigger.ts new file mode 100644 index 0000000..ff4173b --- /dev/null +++ b/Content/UE/InputTrigger.ts @@ -0,0 +1,10 @@ +// UE/InputTrigger.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class InputTrigger extends UEObject { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/Integer.ts b/Content/UE/Integer.ts new file mode 100644 index 0000000..d408e67 --- /dev/null +++ b/Content/UE/Integer.ts @@ -0,0 +1,3 @@ +// UE/Integer.ts + +export type Integer = number; diff --git a/Content/UE/Key.ts b/Content/UE/Key.ts new file mode 100644 index 0000000..2ce2acd --- /dev/null +++ b/Content/UE/Key.ts @@ -0,0 +1,18 @@ +// Content/UE/Key.ts + +import { Name } from '#root/UE/Name.ts'; +import { StructBase } from '#root/UE/StructBase.ts'; + +export class Key extends StructBase { + public keyName: Name; + + constructor(keyName: Name | string = Name.NONE) { + super(); + + if (keyName instanceof Name) { + this.keyName = keyName; + } else { + this.keyName = new Name(keyName); + } + } +} diff --git a/Content/UE/LinearColor.ts b/Content/UE/LinearColor.ts new file mode 100644 index 0000000..fc662c3 --- /dev/null +++ b/Content/UE/LinearColor.ts @@ -0,0 +1,19 @@ +// UE/LinearColor.ts + +import type { Float } from '#root/UE/Float.ts'; +import { StructBase } from '#root/UE/StructBase.ts'; + +export class LinearColor extends StructBase { + public A: Float = 0; + public R: Float = 0; + public G: Float = 0; + public B: Float = 0; + + constructor(r: Float = 0, g: Float = 0, b: Float = 0, a: Float = 0) { + super(); + this.A = a; + this.R = r; + this.G = g; + this.B = b; + } +} diff --git a/Content/UE/LocalPlayerSubsystem.ts b/Content/UE/LocalPlayerSubsystem.ts new file mode 100644 index 0000000..15ee963 --- /dev/null +++ b/Content/UE/LocalPlayerSubsystem.ts @@ -0,0 +1,11 @@ +// UE/LocalPlayerSubsystem.ts + +import { Name } from '#root/UE/Name.ts'; +import { Subsystem } from '#root/UE/Subsystem.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class LocalPlayerSubsystem extends Subsystem { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/MathLibrary.ts b/Content/UE/MathLibrary.ts new file mode 100644 index 0000000..f0c4a9d --- /dev/null +++ b/Content/UE/MathLibrary.ts @@ -0,0 +1,94 @@ +// UE/SystemLibrary.ts + +import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts'; +import type { Color } from '#root/UE/Color.ts'; +import type { Float } from '#root/UE/Float.ts'; +import { LinearColor } from '#root/UE/LinearColor.ts'; +import type { Vector } from '#root/UE/Vector.ts'; + +/** + * System Library: Core Mathematical Functions + * Wrapper for JavaScript Math functions with UE5 compatibility + * Provides deterministic mathematical operations for movement calculations + */ +class MathLibraryClass extends BlueprintFunctionLibrary { + constructor( + outer: null | BlueprintFunctionLibrary = null, + name: string = 'MathLibrary' + ) { + super(outer, name); + } + + // ════════════════════════════════════════════════════════════════════════════════════════ + // FUNCTIONS + // ════════════════════════════════════════════════════════════════════════════════════════ + + /** + * Convert degrees to radians + * @param Degrees - Angle in degrees + * @returns Angle in radians + * @example + * // Convert 90 degrees to radians + * DegreesToRadians(90) // returns π/2 + */ + public DegreesToRadians(Degrees: Float): Float { + return (Degrees * Math.PI) / 180; + } + + /** + * Calculate sine of angle in radians + * @param Value - Angle in radians + * @returns Sine value (-1 to 1) + */ + public Sin(Value: Float): Float { + return Math.sin(Value); + } + + /** + * Calculate cosine of angle in radians + * @param Value - Angle in radians + * @returns Cosine value (-1 to 1) + */ + public Cos(Value: Float): Float { + return Math.cos(Value); + } + + /** + * Calculate arccosine (inverse cosine) of value + * @param Value - Input value (-1 to 1) + * @returns Angle in radians (0 to π) + */ + public Acos(Value: Float): Float { + return Math.acos(Value); + } + + /** + * Calculate dot product of two vectors + * @param Vector1 - First vector + * @param Vector2 - Second vector + * @returns Dot product scalar value + * @example + * // Dot product of perpendicular vectors + * Dot(new Vector(1,0,0), new Vector(0,1,0)) // returns 0 + */ + public Dot(Vector1: Vector, Vector2: Vector): Float { + return ( + Vector1.X * Vector2.X + Vector1.Y * Vector2.Y + Vector1.Z * Vector2.Z + ); + } + + public ColorToLinearColor(color: Color): LinearColor { + return new LinearColor( + color.R / 255, + color.G / 255, + color.B / 255, + color.A / 255 + ); + } +} + +/** + * Global instance of math library + * Used throughout the movement system for mathematical calculations + */ +export const MathLibrary = new MathLibraryClass(); diff --git a/Content/UE/ModifyContextOptions.ts b/Content/UE/ModifyContextOptions.ts new file mode 100644 index 0000000..1db80ed --- /dev/null +++ b/Content/UE/ModifyContextOptions.ts @@ -0,0 +1,20 @@ +// UE/ModifyContextOptions.ts + +import { StructBase } from '#root/UE/StructBase.ts'; + +export class ModifyContextOptions extends StructBase { + public forceImmediately: boolean = false; + public ignoreAllPressedKeysUntilRelease: boolean = false; + public notifyUserSettings: boolean = false; + + constructor( + ignoreAllPressedKeysUntilRelease: boolean = false, + forceImmediately: boolean = false, + notifyUserSettings: boolean = false + ) { + super(); + this.forceImmediately = forceImmediately; + this.ignoreAllPressedKeysUntilRelease = ignoreAllPressedKeysUntilRelease; + this.notifyUserSettings = notifyUserSettings; + } +} diff --git a/Content/UE/Name.ts b/Content/UE/Name.ts new file mode 100644 index 0000000..6b648c7 --- /dev/null +++ b/Content/UE/Name.ts @@ -0,0 +1,18 @@ +// UE/Name.ts + +import { _WrapperBase } from '#root/UE/_WrapperBase.ts'; + +export class Name extends _WrapperBase { + private readonly value: string; + public static readonly NONE = new Name('None'); + + constructor(value: string | Name = 'None') { + super(); + + if (value instanceof Name) { + this.value = value.value; + } else { + this.value = value || 'None'; + } + } +} diff --git a/Content/UE/PanelSlot.ts b/Content/UE/PanelSlot.ts new file mode 100644 index 0000000..3713dc4 --- /dev/null +++ b/Content/UE/PanelSlot.ts @@ -0,0 +1,11 @@ +// UE/PanelSlot.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; +import { Visual } from '#root/UE/Visual.ts'; + +export class PanelSlot extends Visual { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/PanelWidget.ts b/Content/UE/PanelWidget.ts new file mode 100644 index 0000000..40b8f62 --- /dev/null +++ b/Content/UE/PanelWidget.ts @@ -0,0 +1,17 @@ +// UE/PanelWidget.ts + +import { Name } from '#root/UE/Name.ts'; +import { PanelSlot } from '#root/UE/PanelSlot.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; +import { Widget } from '#root/UE/Widget.ts'; + +export class PanelWidget extends Widget { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } + + public AddChild(content: Widget): PanelSlot { + console.log(content); + return new PanelSlot(); + } +} diff --git a/Content/UE/Pawn.ts b/Content/UE/Pawn.ts new file mode 100644 index 0000000..5be5b23 --- /dev/null +++ b/Content/UE/Pawn.ts @@ -0,0 +1,11 @@ +// UE/Pawn.ts + +import { Actor } from '#root/UE/Actor.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class Pawn extends Actor { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/PlayerController.ts b/Content/UE/PlayerController.ts new file mode 100644 index 0000000..93a8229 --- /dev/null +++ b/Content/UE/PlayerController.ts @@ -0,0 +1,11 @@ +// UE/PlayerController.ts + +import { Controller } from '#root/UE/Controller.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class PlayerController extends Controller { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/StringLibrary.ts b/Content/UE/StringLibrary.ts new file mode 100644 index 0000000..259b199 --- /dev/null +++ b/Content/UE/StringLibrary.ts @@ -0,0 +1,18 @@ +// UE/StringLibrary.ts + +import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts'; + +class StringLibraryClass extends BlueprintFunctionLibrary { + constructor( + outer: null | BlueprintFunctionLibrary = null, + name: string = 'StringLibrary' + ) { + super(outer, name); + } + + public Append(A: string, B: string): string { + return A + B; + } +} + +export const StringLibrary = new StringLibraryClass(); diff --git a/Content/UE/StructBase.ts b/Content/UE/StructBase.ts new file mode 100644 index 0000000..39fb8d4 --- /dev/null +++ b/Content/UE/StructBase.ts @@ -0,0 +1,11 @@ +// UE/StructBase.ts + +import { _WrapperBase } from '#root/UE/_WrapperBase.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class StructBase extends _WrapperBase { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/Subsystem.ts b/Content/UE/Subsystem.ts new file mode 100644 index 0000000..94cb308 --- /dev/null +++ b/Content/UE/Subsystem.ts @@ -0,0 +1,10 @@ +// UE/Subsystem.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class Subsystem extends UEObject { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/SystemLibrary.ts b/Content/UE/SystemLibrary.ts new file mode 100644 index 0000000..9e62c84 --- /dev/null +++ b/Content/UE/SystemLibrary.ts @@ -0,0 +1,55 @@ +// UE/SystemLibrary.ts + +import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts'; +import type { Float } from '#root/UE/Float.ts'; +import { LinearColor } from '#root/UE/LinearColor.ts'; +import { Name } from '#root/UE/Name.ts'; +import type { UEObject } from '#root/UE/UEObject.ts'; + +class SystemLibraryClass extends BlueprintFunctionLibrary { + constructor( + outer: null | BlueprintFunctionLibrary = null, + name: string = 'SystemLibrary' + ) { + super(outer, name); + } + + public IsValid( + object: T | null | undefined + ): object is T { + return object !== null && object !== undefined; + } + + public GetGameTimeInSeconds(): number { + // Placeholder implementation; replace with actual game time retrieval logic + return Date.now() / 1000; + } + + public PrintString( + string: string = 'Hello', + printToScreen: boolean = true, + printToLog: boolean = true, + textColor: LinearColor = new LinearColor(0, 0.66, 1, 1), + duration: Float = 2.0, + key: Name = Name.NONE + ): void { + if (printToScreen) { + console.log( + `%c${string}`, + `color: rgba(${textColor.R * 255}, ${textColor.G * 255}, ${ + textColor.B * 255 + }, ${textColor.A}); font-weight: bold;` + ); + // In a real game engine, this would display the string on the screen for the specified duration + } + if (printToLog) { + console.log(string); + // In a real game engine, this would log the string to the console or log file + } + + console.log(duration); + console.log(key); + } +} + +export const SystemLibrary = new SystemLibraryClass(); diff --git a/Content/UE/Text.ts b/Content/UE/Text.ts new file mode 100644 index 0000000..d6ecc68 --- /dev/null +++ b/Content/UE/Text.ts @@ -0,0 +1,3 @@ +// UE/Text.ts + +export type Text = string; diff --git a/Content/UE/TextBlock.ts b/Content/UE/TextBlock.ts new file mode 100644 index 0000000..8b3d26c --- /dev/null +++ b/Content/UE/TextBlock.ts @@ -0,0 +1,20 @@ +// UE/TextBlock.ts + +import { Name } from '#root/UE/Name.ts'; +import type { Text } from '#root/UE/Text.ts'; +import { TextLayoutWidget } from '#root/UE/TextLayoutWidget.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class TextBlock extends TextLayoutWidget { + private text: Text = '' as Text; + + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + + console.log(this.text); + } + + public SetText(text: Text): void { + this.text = text; + } +} diff --git a/Content/UE/TextLayoutWidget.ts b/Content/UE/TextLayoutWidget.ts new file mode 100644 index 0000000..2d0e140 --- /dev/null +++ b/Content/UE/TextLayoutWidget.ts @@ -0,0 +1,11 @@ +// UE/TextLayoutWidget.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; +import { Widget } from '#root/UE/Widget.ts'; + +export class TextLayoutWidget extends Widget { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/TextLibrary.ts b/Content/UE/TextLibrary.ts new file mode 100644 index 0000000..b1fd106 --- /dev/null +++ b/Content/UE/TextLibrary.ts @@ -0,0 +1,23 @@ +// UE/TextLibrary.ts + +import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts'; +import type { Text } from '#root/UE/Text.ts'; + +class TextLibraryClass extends BlueprintFunctionLibrary { + constructor( + outer: null | BlueprintFunctionLibrary = null, + name: string = 'SystemLibrary' + ) { + super(outer, name); + } + + public TextToString(text: Text): string { + return text; + } + + public StringToText(str: string): Text { + return str; + } +} + +export const TextLibrary = new TextLibraryClass(); diff --git a/Content/UE/UEArray.ts b/Content/UE/UEArray.ts new file mode 100644 index 0000000..de37d12 --- /dev/null +++ b/Content/UE/UEArray.ts @@ -0,0 +1,44 @@ +// UE/UEArray.ts + +import type { Integer } from '#root/UE/Integer.ts'; + +export class UEArray extends Array { + constructor(items?: T[]) { + super(); + if (items) { + this.push(...items); + } + Object.setPrototypeOf(this, UEArray.prototype); + } + + public SetArrayElem( + Index: Integer = 0, + Item: T, + SizeToFit: boolean = false + ): void { + this[Index] = Item; + if (SizeToFit && Index >= this.length) { + this.length = Index + 1; + } + } + + public Add(Item: T): Integer { + this.push(Item); + return this.length - 1; + } + + public Get(Index: Integer): T { + return this[Index]!; + } + + public RemoveIndex(Index: Integer): void { + this.splice(Index, 1); + } + + public Remove(Item: T): void { + const index = this.indexOf(Item); + if (index !== -1) { + this.splice(index, 1); + } + } +} diff --git a/Content/UE/UEObject.ts b/Content/UE/UEObject.ts new file mode 100644 index 0000000..ae7460b --- /dev/null +++ b/Content/UE/UEObject.ts @@ -0,0 +1,18 @@ +// UE/UEObject.ts + +import { Name } from '#root/UE/Name.ts'; + +export class UEObject { + protected outer: UEObject | null; + protected name: Name; + + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + this.outer = outer; + + if (name instanceof Name) { + this.name = name; + } else { + this.name = new Name(name); + } + } +} diff --git a/Content/UE/UInt8.ts b/Content/UE/UInt8.ts new file mode 100644 index 0000000..7f865fb --- /dev/null +++ b/Content/UE/UInt8.ts @@ -0,0 +1,3 @@ +// UE/UInt8.ts + +export type UInt8 = number; diff --git a/Content/UE/UserWidget.ts b/Content/UE/UserWidget.ts new file mode 100644 index 0000000..d412e8f --- /dev/null +++ b/Content/UE/UserWidget.ts @@ -0,0 +1,15 @@ +// UE/UserWidget.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; +import { Widget } from '#root/UE/Widget.ts'; + +export class UserWidget extends Widget { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } + + public AddToViewport(ZOrder: number = 0): void { + console.log(ZOrder); + } +} diff --git a/Content/UE/Vector.ts b/Content/UE/Vector.ts new file mode 100644 index 0000000..1918475 --- /dev/null +++ b/Content/UE/Vector.ts @@ -0,0 +1,18 @@ +// UE/Vector.ts + +import type { Float } from '#root/UE/Float.ts'; +import { Name } from '#root/UE/Name.ts'; +import { StructBase } from '#root/UE/StructBase.ts'; + +export class Vector extends StructBase { + public X: Float = 0; + public Y: Float = 0; + public Z: Float = 0; + + constructor(x: Float = 0, y: Float = 0, z: Float = 0) { + super(null, Name.NONE); + this.X = x; + this.Y = y; + this.Z = z; + } +} diff --git a/Content/UE/VerticalBox.ts b/Content/UE/VerticalBox.ts new file mode 100644 index 0000000..f584c8c --- /dev/null +++ b/Content/UE/VerticalBox.ts @@ -0,0 +1,11 @@ +// UE/VerticalBox.ts + +import { Name } from '#root/UE/Name.ts'; +import { PanelWidget } from '#root/UE/PanelWidget.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class VerticalBox extends PanelWidget { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/Visual.ts b/Content/UE/Visual.ts new file mode 100644 index 0000000..401bcd4 --- /dev/null +++ b/Content/UE/Visual.ts @@ -0,0 +1,10 @@ +// UE/Visual.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class Visual extends UEObject { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UE/Widget.ts b/Content/UE/Widget.ts new file mode 100644 index 0000000..447a38e --- /dev/null +++ b/Content/UE/Widget.ts @@ -0,0 +1,20 @@ +// UE/Widget.ts + +import type { ESlateVisibility } from '#root/UE/ESlateVisibility.ts'; +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; +import { Visual } from '#root/UE/Visual.ts'; + +export class Widget extends Visual { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } + + public SetVisibility(visibility: ESlateVisibility): void { + console.log(visibility); + } + + public RemoveFromParent(): void { + console.log('Removed from parent'); + } +} diff --git a/Content/UE/_WrapperBase.ts b/Content/UE/_WrapperBase.ts new file mode 100644 index 0000000..dffef30 --- /dev/null +++ b/Content/UE/_WrapperBase.ts @@ -0,0 +1,10 @@ +// UE/_WrapperBase.ts + +import { Name } from '#root/UE/Name.ts'; +import { UEObject } from '#root/UE/UEObject.ts'; + +export class _WrapperBase extends UEObject { + constructor(outer: UEObject | null = null, name: Name | string = Name.NONE) { + super(outer, name); + } +} diff --git a/Content/UI/Enums/E_MessageType.ts b/Content/UI/Enums/E_MessageType.ts index b7aeacf..c442387 100644 --- a/Content/UI/Enums/E_MessageType.ts +++ b/Content/UI/Enums/E_MessageType.ts @@ -1,10 +1,10 @@ -// Content/Toasts/Enums/E_MessageType.ts +// UI/Enums/E_MessageType.ts export enum E_MessageType { - Info = "Info", - Success = "Success", - Warning = "Warning", - Error = "Error", - Debug = "Debug", - Test = "Test" + Info = 'Info', + Success = 'Success', + Warning = 'Warning', + Error = 'Error', + Debug = 'Debug', + Test = 'Test', } diff --git a/Content/UI/Libraries/BFL_Colors.ts b/Content/UI/Libraries/BFL_Colors.ts new file mode 100644 index 0000000..5d5f098 --- /dev/null +++ b/Content/UI/Libraries/BFL_Colors.ts @@ -0,0 +1,27 @@ +// UI/Libraries/BFL_Colors.ts + +import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts'; +import type { Byte } from '#root/UE/Byte.ts'; +import { Color } from '#root/UE/Color.ts'; +import { E_MessageType } from '#root/UI/Enums/E_MessageType.ts'; + +class BFL_ColorsClass extends BlueprintFunctionLibrary { + public GetColorByMessageType(Type: E_MessageType, Alpha: Byte): Color { + switch (Type) { + case E_MessageType.Info: + return new Color(226, 144, 74, Alpha); + case E_MessageType.Success: + return new Color(92, 184, 92, Alpha); + case E_MessageType.Warning: + return new Color(78, 173, 240, Alpha); + case E_MessageType.Error: + return new Color(79, 83, 217, Alpha); + case E_MessageType.Debug: + return new Color(125, 117, 108, Alpha); + default: + return new Color(0, 0, 0, Alpha); + } + } +} + +export const BFL_Colors = new BFL_ColorsClass(); diff --git a/Content/UI/Libraries/BFL_Colors.uasset b/Content/UI/Libraries/BFL_Colors.uasset new file mode 100644 index 0000000..ff57fa2 --- /dev/null +++ b/Content/UI/Libraries/BFL_Colors.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85eac894d472505b469143ab480b344656a1455a1bcf9311c53735603f62fa64 +size 46042 diff --git a/Content/UI/Libraries/FL_Colors.uasset b/Content/UI/Libraries/FL_Colors.uasset deleted file mode 100644 index fff0a73..0000000 --- a/Content/UI/Libraries/FL_Colors.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:74749734ea2873101cbb79550690498d1eda67e7f9ed2c4e3b7380bcdf63d22b -size 43786 diff --git a/Content/classes.ts b/Content/classes.ts deleted file mode 100644 index 2350e5f..0000000 --- a/Content/classes.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Content/classes.ts - -import {ESlateVisibility} from "./enums.js"; -import type {Color, Text} from "./types.js"; - -export class Widget { - public AddToViewport(): void { - // Logic to add the widget to the viewport - } - - public SetVisibility(visibility: ESlateVisibility): void { - // Logic to set the visibility of the widget - } - - public RemoveFromParent(): void { - // Logic to remove the widget from its parent - } - - public AddChild(Child: Widget): void { - // Logic to add a child element - } -} - -export class TextBox extends Widget { - private Text: Text = ""; - - public SetText(NewText: Text): void { - this.Text = NewText; - } -} - -export class Border extends Widget { - public SetBrushColor(Color: Color): void { - // Logic to set the brush color of the border - } -} - -export class VerticalBox extends Widget{} diff --git a/Content/enums.ts b/Content/enums.ts deleted file mode 100644 index c1cc51e..0000000 --- a/Content/enums.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Content/enums.ts - -export enum ESlateVisibility { - Visible = "Visible", - Collapsed = "Collapsed", - Hidden = "Hidden", - NotHitTestableSelfAndAllChildren = "NotHitTestableSelfAndAllChildren", - NotHitTestableSelfOnly = "NotHitTestableSelfOnly" -} diff --git a/Content/functions.ts b/Content/functions.ts deleted file mode 100644 index f8e988f..0000000 --- a/Content/functions.ts +++ /dev/null @@ -1,86 +0,0 @@ -// Content/functions.ts - -import type {Color, Controller, Float, InputMappingContext, Integer, Vector} from "./types.js"; - -// Math -export function sin(x: Float): Float { - return Math.sin(x); -} - -export function cos(x: Float): Float { - return Math.cos(x); -} - -export function acos(x: Float): Float { - return Math.acos(x); -} - -export function Dot(v1: Vector, v2: Vector): Float { - return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; -} - -export function D2R(degrees: Float): Float { - return degrees * (Math.PI / 180); -} - -// Utilities -export function Print( - message: string = 'Hello', - printToScreen: boolean = true, - printToLog: boolean = true, - textColor: Color = {R: 0.0, G: 0.66, B: 1.0, A: 1.0}, - duration: Float = 2.0): void { - console.log(message); -} - -// Arrays - -export function SetArrayElem(targetArray: T[], index: Integer, value: T): void { - targetArray[index] = value; -} - -export function AddToArray(targetArray: T[], value: T): void { - targetArray.push(value); -} - -export function GetFromArray(targetArray: T[], index: Integer): T | null { - return index >= 0 && index < targetArray.length ? targetArray[index] : null; -} - -export function RemoveIndexFromArray(targetArray: T[], index: Integer): void { - if (index >= 0 && index < targetArray.length) { - targetArray.splice(index, 1); - } -} - -export function RemoveItemFromArray(targetArray: T[], item: T): void { - const index = targetArray.indexOf(item); - if (index !== -1) { - targetArray.splice(index, 1); - } -} - -// UE functions placeholders -export function CastToPlayController(controller: Controller): Controller { - return controller; -} - -export function EnhancedInputLocalPlayerSubsystem(playerController: Controller): Controller { - return playerController; -} - -export function AddMappingContext(Target: Controller, MappingContext: InputMappingContext, Priority: Integer = 0): void { - console.log(`Adding mapping context with priority ${Priority} to player controller ${Target}`); -} - -export function CreateWidget(widgetClass: T): T { - return widgetClass; -} - -export function IsValid(object: T | null): boolean { - return object !== null && object !== undefined; -} - -export function GetGameTimeInSeconds(): Float { - return Date.now() / 1000; // Simple placeholder for game time -} diff --git a/Content/types.ts b/Content/types.ts deleted file mode 100644 index 1f3b3f7..0000000 --- a/Content/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Content/types.ts - -export type Float = number; -export type Integer = number; -export type Text = string; - -export type Vector = [Float, Float, Float]; -export type Color = { R: Integer; G: Integer; B: Integer; A: Integer }; - -export type Controller = string; - -export type InputMapping = {} - -export type InputMappingContext = InputMapping[]; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4132214 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3634 @@ +{ + "name": "tengriplatformer", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "tengriplatformer", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^8.41.0", + "@typescript-eslint/parser": "^8.41.0", + "eslint": "^9.34.0", + "eslint-config-prettier": "^10.1.8", + "eslint-import-resolver-node": "^0.3.9", + "eslint-import-resolver-typescript": "^4.4.4", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-prefer-arrow": "^1.2.3", + "prettier": "^3.6.2", + "typescript": "^5.9.2" + } + }, + "node_modules/@emnapi/core": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", + "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.4", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", + "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "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" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz", + "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.41.0.tgz", + "integrity": "sha512-8fz6oa6wEKZrhXWro/S3n2eRJqlRcIa6SlDh59FXJ5Wp5XRZ8B9ixpJDcjadHq47hMx0u+HW6SNa6LjJQ6NLtw==", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.41.0", + "@typescript-eslint/type-utils": "8.41.0", + "@typescript-eslint/utils": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.41.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.41.0.tgz", + "integrity": "sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg==", + "dependencies": { + "@typescript-eslint/scope-manager": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/typescript-estree": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.41.0.tgz", + "integrity": "sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ==", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.41.0", + "@typescript-eslint/types": "^8.41.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.41.0.tgz", + "integrity": "sha512-n6m05bXn/Cd6DZDGyrpXrELCPVaTnLdPToyhBoFkLIMznRUQUEQdSp96s/pcWSQdqOhrgR1mzJ+yItK7T+WPMQ==", + "dependencies": { + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.41.0.tgz", + "integrity": "sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.41.0.tgz", + "integrity": "sha512-63qt1h91vg3KsjVVonFJWjgSK7pZHSQFKH6uwqxAH9bBrsyRhO6ONoKyXxyVBzG1lJnFAJcKAcxLS54N1ee1OQ==", + "dependencies": { + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/typescript-estree": "8.41.0", + "@typescript-eslint/utils": "8.41.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.41.0.tgz", + "integrity": "sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.41.0.tgz", + "integrity": "sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ==", + "dependencies": { + "@typescript-eslint/project-service": "8.41.0", + "@typescript-eslint/tsconfig-utils": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.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" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.41.0.tgz", + "integrity": "sha512-udbCVstxZ5jiPIXrdH+BZWnPatjlYwJuJkDA4Tbo3WyYLh8NvB+h/bKeSZHDOFKfphsZYJQqaFtLeXEqurQn1A==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/typescript-estree": "8.41.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.41.0.tgz", + "integrity": "sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg==", + "dependencies": { + "@typescript-eslint/types": "8.41.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "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" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz", + "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.34.0", + "@eslint/plugin-kit": "^0.3.5", + "@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" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-context": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz", + "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==", + "dependencies": { + "get-tsconfig": "^4.10.1", + "stable-hash-x": "^0.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-context" + }, + "peerDependencies": { + "unrs-resolver": "^1.0.0" + }, + "peerDependenciesMeta": { + "unrs-resolver": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.4.tgz", + "integrity": "sha512-1iM2zeBvrYmUNTj2vSC/90JTHDth+dfOfiNKkxApWRsTJYNrc8rOdxxIf5vazX+BiAXTeOT0UvWpGI/7qIWQOw==", + "dependencies": { + "debug": "^4.4.1", + "eslint-import-context": "^0.1.8", + "get-tsconfig": "^4.10.1", + "is-bun-module": "^2.0.0", + "stable-hash-x": "^0.2.0", + "tinyglobby": "^0.2.14", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^16.17.0 || >=18.6.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-prefer-arrow": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.3.tgz", + "integrity": "sha512-J9I5PKCOJretVuiZRGvPQxCbllxGAV/viI20JO3LYblAodofBxyMnZAJ+WGeClHgANnSJberTNoFWWjrWKBuXQ==", + "peerDependencies": { + "eslint": ">=2.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "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" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/napi-postinstall": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", + "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stable-hash-x": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", + "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "optional": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "hasInstallScript": true, + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "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" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7ee2d21 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "tengriplatformer", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "description": "", + "imports": { + "#root/*": "./Content/*" + }, + "dependencies": { + "@typescript-eslint/eslint-plugin": "^8.41.0", + "@typescript-eslint/parser": "^8.41.0", + "eslint": "^9.34.0", + "eslint-config-prettier": "^10.1.8", + "eslint-import-resolver-node": "^0.3.9", + "eslint-import-resolver-typescript": "^4.4.4", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-prefer-arrow": "^1.2.3", + "prettier": "^3.6.2", + "typescript": "^5.9.2" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8eefac9 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,64 @@ +{ + "compilerOptions": { + // Basic Options + "target": "ES2022", + "module": "ESNext", + "lib": ["ES2022", "DOM"], + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "noEmit": true, + + // Path Mapping + "baseUrl": ".", + "paths": { + "#root/*": ["./Content/*"] + }, + + // Strict Type Checking + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + + // Additional Checks + "noUnusedLocals": true, + "noUnusedParameters": true, + "exactOptionalPropertyTypes": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + + // Module Resolution + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "verbatimModuleSyntax": false, + + // Advanced Options + "skipLibCheck": true, + "declaration": false, + "declarationMap": false, + "sourceMap": false, + + // Experimental + "experimentalDecorators": true, + "emitDecoratorMetadata": true + }, + "include": [ + "Content/**/*" + ], + "exclude": [ + "node_modules", + "dist", + "build", + "**/*.test.ts", + "**/*.spec.ts" + ] +}