[{"data":1,"prerenderedAt":22769},["ShallowReactive",2],{"navigation_docs":3,"-web-development-nestjs-validation-pipeline-custom-exception-filters":5074,"-web-development-nestjs-validation-pipeline-custom-exception-filters-surround":22764},[4,1707,2040,2512,2693,2819,3026,3148,3198,3255,3289,3415,3492,3506,3645,3939,4016,4749,4924,5017,5070],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"C#","i-devicon-csharp","\u002Fcsharp","01.csharp",[10,13,60,90,120,202,219,253,379,404,457,650,1364,1654,1703],{"title":11,"path":7,"stem":12},"C# та .NET","01.csharp\u002Findex",{"title":14,"icon":15,"path":16,"stem":17,"children":18,"page":59},"Fundamentals","i-lucide-book-open","\u002Fcsharp\u002Ffundamentals","01.csharp\u002F01.fundamentals",[19,23,27,31,35,39,43,47,51,55],{"title":20,"path":21,"stem":22},"Вступ до екосистеми .NET","\u002Fcsharp\u002Ffundamentals\u002Fintroduction-to-ecosystem","01.csharp\u002F01.fundamentals\u002F01.introduction-to-ecosystem",{"title":24,"path":25,"stem":26},"Структура програми на C#","\u002Fcsharp\u002Ffundamentals\u002Fprogram-structure","01.csharp\u002F01.fundamentals\u002F02.program-structure",{"title":28,"path":29,"stem":30},"Змінні та Типи Даних","\u002Fcsharp\u002Ffundamentals\u002Fvariables-data-types","01.csharp\u002F01.fundamentals\u002F03.variables-data-types",{"title":32,"path":33,"stem":34},"Масиви","\u002Fcsharp\u002Ffundamentals\u002Farrays","01.csharp\u002F01.fundamentals\u002F04.arrays",{"title":36,"path":37,"stem":38},"Strings & Text Handling","\u002Fcsharp\u002Ffundamentals\u002Fstrings-text-handling","01.csharp\u002F01.fundamentals\u002F05.strings-text-handling",{"title":40,"path":41,"stem":42},"Дати і Час","\u002Fcsharp\u002Ffundamentals\u002Fdates-time-handling","01.csharp\u002F01.fundamentals\u002F06.dates-time-handling",{"title":44,"path":45,"stem":46},"Потік Керування","\u002Fcsharp\u002Ffundamentals\u002Fcontrol-flow","01.csharp\u002F01.fundamentals\u002F07.control-flow",{"title":48,"path":49,"stem":50},"Методи","\u002Fcsharp\u002Ffundamentals\u002Fmethods","01.csharp\u002F01.fundamentals\u002F08.methods",{"title":52,"path":53,"stem":54},"Основи Відлагодження","\u002Fcsharp\u002Ffundamentals\u002Fdebugging-basics","01.csharp\u002F01.fundamentals\u002F09.debugging-basics",{"title":56,"path":57,"stem":58},"Інтерактивна Консоль (Classic)","\u002Fcsharp\u002Ffundamentals\u002Finteractive-console","01.csharp\u002F01.fundamentals\u002F10.interactive-console",false,{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":59},"OOP","i-lucide-box","\u002Fcsharp\u002Foop","01.csharp\u002F02.oop",[66,70,74,78,82,86],{"title":67,"path":68,"stem":69},"Package Management (Управління Пакетами)","\u002Fcsharp\u002Foop\u002Fpackage-management","01.csharp\u002F02.oop\u002F01.package-management",{"title":71,"path":72,"stem":73},"Класи та Об'єкти","\u002Fcsharp\u002Foop\u002Fclasses-objects","01.csharp\u002F02.oop\u002F02.classes-objects",{"title":75,"path":76,"stem":77},"Властивості та Поля","\u002Fcsharp\u002Foop\u002Fproperties-fields","01.csharp\u002F02.oop\u002F03.properties-fields",{"title":79,"path":80,"stem":81},"Стовпи ООП","\u002Fcsharp\u002Foop\u002Foop-pillars","01.csharp\u002F02.oop\u002F04.oop-pillars",{"title":83,"path":84,"stem":85},"Advanced Types","\u002Fcsharp\u002Foop\u002Fadvanced-types","01.csharp\u002F02.oop\u002F05.advanced-types",{"title":87,"path":88,"stem":89},"Namespaces (Простори Імен)","\u002Fcsharp\u002Foop\u002Fnamespaces","01.csharp\u002F02.oop\u002F06.namespaces",{"title":91,"icon":92,"path":93,"stem":94,"children":95,"page":59},"Advanced Core","i-lucide-zap","\u002Fcsharp\u002Fadvanced-core","01.csharp\u002F03.advanced-core",[96,100,104,108,112,116],{"title":97,"path":98,"stem":99},"Generics (Узагальнення)","\u002Fcsharp\u002Fadvanced-core\u002Fgenerics","01.csharp\u002F03.advanced-core\u002F01.generics",{"title":101,"path":102,"stem":103},"Делегати, Події та Лямбда-вирази","\u002Fcsharp\u002Fadvanced-core\u002Fdelegates-events-lambdas","01.csharp\u002F03.advanced-core\u002F02.delegates-events-lambdas",{"title":105,"path":106,"stem":107},"Interfaces Deep Dive (Інтерфейси: Поглиблений Розгляд)","\u002Fcsharp\u002Fadvanced-core\u002Finterfaces-deep-dive","01.csharp\u002F03.advanced-core\u002F03.interfaces-deep-dive",{"title":109,"path":110,"stem":111},"Обробка Винятків","\u002Fcsharp\u002Fadvanced-core\u002Fexception-handling","01.csharp\u002F03.advanced-core\u002F04.exception-handling",{"title":113,"path":114,"stem":115},"Pattern Matching","\u002Fcsharp\u002Fadvanced-core\u002Fpattern-matching","01.csharp\u002F03.advanced-core\u002F05.pattern-matching",{"title":117,"path":118,"stem":119},"Додаткові Можливості C#","\u002Fcsharp\u002Fadvanced-core\u002Fadditional-features","01.csharp\u002F03.advanced-core\u002F06.additional-features",{"title":121,"icon":122,"path":123,"stem":124,"children":125,"page":59},"Architecture Best Practices","i-lucide-building-2","\u002Fcsharp\u002Farchitecture-best-practices","01.csharp\u002F04.architecture-best-practices",[126,130,149,153,157,161,165,169],{"title":127,"path":128,"stem":129},"Software Design Principles (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fsoftware-design-principles","01.csharp\u002F04.architecture-best-practices\u002F01.software-design-principles",{"title":131,"icon":132,"path":133,"stem":134,"children":135,"page":59},"Design Patterns","i-lucide-folder","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns",[136],{"title":137,"icon":132,"path":138,"stem":139,"children":140,"page":59},"Creational","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational",[141,145],{"title":142,"path":143,"stem":144},"Singleton (Одинак)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fsingleton","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F01.singleton",{"title":146,"path":147,"stem":148},"Builder (Будівельник)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fbuilder","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F02.builder",{"title":150,"path":151,"stem":152},"Building Professional CLIs","\u002Fcsharp\u002Farchitecture-best-practices\u002Fbuilding-professional-clis","01.csharp\u002F04.architecture-best-practices\u002F03.building-professional-clis",{"title":154,"path":155,"stem":156},"Validation & Flow Control","\u002Fcsharp\u002Farchitecture-best-practices\u002Fvalidation-flow-control","01.csharp\u002F04.architecture-best-practices\u002F04.validation-flow-control",{"title":158,"path":159,"stem":160},"The Modern .NET Host (Microsoft.Extensions)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fmodern-dotnet-host","01.csharp\u002F04.architecture-best-practices\u002F05.modern-dotnet-host",{"title":162,"path":163,"stem":164},"Data Mapper: Repository та DAO патерни (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part1","01.csharp\u002F04.architecture-best-practices\u002F06.data-mapper-part1",{"title":166,"path":167,"stem":168},"Data Mapper: Repository та DAO патерни (Частина 2)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part2","01.csharp\u002F04.architecture-best-practices\u002F07.data-mapper-part2",{"title":170,"icon":132,"path":171,"stem":172,"children":173,"page":59},"Di Ioc","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc",[174,178,182,186,190,194,198],{"title":175,"path":176,"stem":177},"Проблема залежностей та Інверсія Контролю","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fthe-dependency-problem","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F01.the-dependency-problem",{"title":179,"path":180,"stem":181},"Будуємо власний Service Container","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fbuild-your-own-container","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F02.build-your-own-container",{"title":183,"path":184,"stem":185},"Service Locator: Паттерн та Анти-паттерн","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-locator-pattern","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F03.service-locator-pattern",{"title":187,"path":188,"stem":189},"Паттерни Dependency Injection","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdependency-injection-patterns","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F04.dependency-injection-patterns",{"title":191,"path":192,"stem":193},"Microsoft DI: IServiceCollection та IServiceProvider","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fmicrosoft-di-deep-dive","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F05.microsoft-di-deep-dive",{"title":195,"path":196,"stem":197},"Service Lifetimes та Scopes","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-lifetimes-and-scopes","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F06.service-lifetimes-and-scopes",{"title":199,"path":200,"stem":201},"DI Анти-паттерни та Найкращі Практики","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdi-anti-patterns-and-best-practices","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F07.di-anti-patterns-and-best-practices",{"title":203,"icon":132,"path":204,"stem":205,"children":206,"page":59},"Standard Library","\u002Fcsharp\u002Fstandard-library","01.csharp\u002F05.standard-library",[207,211,215],{"title":208,"path":209,"stem":210},"Collections (Колекції)","\u002Fcsharp\u002Fstandard-library\u002Fcollections","01.csharp\u002F05.standard-library\u002F01.collections",{"title":212,"path":213,"stem":214},"High Performance Types (Високопродуктивні Типи)","\u002Fcsharp\u002Fstandard-library\u002Fhigh-performance-types","01.csharp\u002F05.standard-library\u002F02.high-performance-types",{"title":216,"path":217,"stem":218},"LINQ (Language Integrated Query)","\u002Fcsharp\u002Fstandard-library\u002Flinq","01.csharp\u002F05.standard-library\u002F03.linq",{"title":220,"icon":221,"path":222,"stem":223,"children":224,"page":59},"System Internals Concurrency","i-lucide-server","\u002Fcsharp\u002Fsystem-internals-concurrency","01.csharp\u002F06.system-internals-concurrency",[225,229,233,237,241,245,249],{"title":226,"path":227,"stem":228},"Memory Management","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmemory-management","01.csharp\u002F06.system-internals-concurrency\u002F01.memory-management",{"title":230,"path":231,"stem":232},"Reflection API: System.Type та Метадані","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Freflection-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F02.reflection-fundamentals",{"title":234,"path":235,"stem":236},"Attributes та Dynamic Language Runtime","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fattributes-dynamic","01.csharp\u002F06.system-internals-concurrency\u002F03.attributes-dynamic",{"title":238,"path":239,"stem":240},"Expression Trees: Швидка Альтернатива Рефлексії","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fexpression-trees-compiled","01.csharp\u002F06.system-internals-concurrency\u002F04.expression-trees-compiled",{"title":242,"path":243,"stem":244},"Source Generators: Compile-Time Code Generation","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsource-generators","01.csharp\u002F06.system-internals-concurrency\u002F05.source-generators",{"title":246,"path":247,"stem":248},"Multithreading Fundamentals","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmultithreading-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F06.multithreading-fundamentals",{"title":250,"path":251,"stem":252},"Synchronization Primitives","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsynchronization-primitives","01.csharp\u002F06.system-internals-concurrency\u002F07.synchronization-primitives",{"title":254,"icon":255,"path":256,"stem":257,"children":258,"page":59},"System Programming Windows","i-lucide-cpu","\u002Fcsharp\u002Fsystem-programming-windows","01.csharp\u002F07.system-programming-windows",[259,263,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327,331,335,339,343,347,351,355,359,363,367,371,375],{"title":260,"path":261,"stem":262},"Як Працює Операційна Система","\u002Fcsharp\u002Fsystem-programming-windows\u002Fhow-os-works","01.csharp\u002F07.system-programming-windows\u002F01.how-os-works",{"title":264,"path":265,"stem":266},"Процеси в .NET — API та Запуск","\u002Fcsharp\u002Fsystem-programming-windows\u002Fprocesses-in-dotnet","01.csharp\u002F07.system-programming-windows\u002F02.processes-in-dotnet",{"title":268,"path":269,"stem":270},"Процеси в .NET — IPC та Міжпроцесна Комунікація","\u002Fcsharp\u002Fsystem-programming-windows\u002F02a.processes-ipc","01.csharp\u002F07.system-programming-windows\u002F02a.processes-ipc",{"title":272,"path":273,"stem":274},"Application Domains та Збірки — AppDomain і AssemblyLoadContext","\u002Fcsharp\u002Fsystem-programming-windows\u002Fappdomains-assemblies","01.csharp\u002F07.system-programming-windows\u002F03.appdomains-assemblies",{"title":276,"path":277,"stem":278},"Application Domains та Збірки — Plug-in Система з Hot-Reload","\u002Fcsharp\u002Fsystem-programming-windows\u002F03a.appdomains-plugin-system","01.csharp\u002F07.system-programming-windows\u002F03a.appdomains-plugin-system",{"title":280,"path":281,"stem":282},"Потоки — Основи та API Thread","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-fundamentals","01.csharp\u002F07.system-programming-windows\u002F04.thread-fundamentals",{"title":284,"path":285,"stem":286},"Потоки — Lifecycle, Пріоритети та Безпечне Завершення","\u002Fcsharp\u002Fsystem-programming-windows\u002F04a.thread-lifecycle-priorities","01.csharp\u002F07.system-programming-windows\u002F04a.thread-lifecycle-priorities",{"title":288,"path":289,"stem":290},"Проблеми Спільного Стану — Race Condition та Data Race","\u002Fcsharp\u002Fsystem-programming-windows\u002Fshared-state-problems","01.csharp\u002F07.system-programming-windows\u002F05.shared-state-problems",{"title":292,"path":293,"stem":294},"Проблеми Спільного Стану — Memory Model та volatile","\u002Fcsharp\u002Fsystem-programming-windows\u002F05a.shared-state-memory-model","01.csharp\u002F07.system-programming-windows\u002F05a.shared-state-memory-model",{"title":296,"path":297,"stem":298},"Синхронізація — Monitor, lock та еволюція примітивів","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-fundamentals","01.csharp\u002F07.system-programming-windows\u002F06.synchronization-fundamentals",{"title":300,"path":301,"stem":302},"Синхронізація — Наскрізний Приклад та Deadlock Detection","\u002Fcsharp\u002Fsystem-programming-windows\u002F06a.synchronization-walkthrough","01.csharp\u002F07.system-programming-windows\u002F06a.synchronization-walkthrough",{"title":304,"path":305,"stem":306},"Синхронізація — Mutex, Semaphore та Event-Based Primitives","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-advanced","01.csharp\u002F07.system-programming-windows\u002F07.synchronization-advanced",{"title":308,"path":309,"stem":310},"Синхронізація — Interlocked, Volatile та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002F07a.synchronization-advanced-walkthrough","01.csharp\u002F07.system-programming-windows\u002F07a.synchronization-advanced-walkthrough",{"title":312,"path":313,"stem":314},"Interlocked, CAS та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002Finterlocked-cas-lockfree","01.csharp\u002F07.system-programming-windows\u002F08.interlocked-cas-lockfree",{"title":316,"path":317,"stem":318},"Volatile, Memory Model та Spinning","\u002Fcsharp\u002Fsystem-programming-windows\u002F08a.volatile-memory-model","01.csharp\u002F07.system-programming-windows\u002F08a.volatile-memory-model",{"title":320,"path":321,"stem":322},"ThreadPool — Пул Потоків для Ефективного Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-pool","01.csharp\u002F07.system-programming-windows\u002F09.thread-pool",{"title":324,"path":325,"stem":326},"ThreadPool — Просунуті Сценарії та Внутрішня Будова","\u002Fcsharp\u002Fsystem-programming-windows\u002F09a.thread-pool-advanced","01.csharp\u002F07.system-programming-windows\u002F09a.thread-pool-advanced",{"title":328,"path":329,"stem":330},"Concurrent та Immutable Collections","\u002Fcsharp\u002Fsystem-programming-windows\u002Fconcurrent-collections","01.csharp\u002F07.system-programming-windows\u002F10.concurrent-collections",{"title":332,"path":333,"stem":334},"TPL, Task та Композиція — Від Thread до Task","\u002Fcsharp\u002Fsystem-programming-windows\u002Ftpl-parallel-plinq","01.csharp\u002F07.system-programming-windows\u002F11.tpl-parallel-plinq",{"title":336,"path":337,"stem":338},"Parallel Class та PLINQ — Data Parallelism","\u002Fcsharp\u002Fsystem-programming-windows\u002F11a.tpl-parallel-plinq-advanced","01.csharp\u002F07.system-programming-windows\u002F11a.tpl-parallel-plinq-advanced",{"title":340,"path":341,"stem":342},"Async\u002FAwait — Фундамент Асинхронного Програмування","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-fundamentals","01.csharp\u002F07.system-programming-windows\u002F12.async-fundamentals",{"title":344,"path":345,"stem":346},"SynchronizationContext та ConfigureAwait — Контекст Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-context-configureawait","01.csharp\u002F07.system-programming-windows\u002F13.async-context-configureawait",{"title":348,"path":349,"stem":350},"Async — Просунуті Паттерни","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-advanced","01.csharp\u002F07.system-programming-windows\u002F14.async-advanced",{"title":352,"path":353,"stem":354},"System.Threading.Channels — Async Producer-Consumer","\u002Fcsharp\u002Fsystem-programming-windows\u002Fchannels","01.csharp\u002F07.system-programming-windows\u002F15.channels",{"title":356,"path":357,"stem":358},"Асинхронна Синхронізація","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-synchronization","01.csharp\u002F07.system-programming-windows\u002F16.async-synchronization",{"title":360,"path":361,"stem":362},"Unsafe Code та Вказівники","\u002Fcsharp\u002Fsystem-programming-windows\u002Funsafe-code","01.csharp\u002F07.system-programming-windows\u002F17.unsafe-code",{"title":364,"path":365,"stem":366},"P\u002FInvoke та Windows API — Міст між .NET та Native Code","\u002Fcsharp\u002Fsystem-programming-windows\u002Fpinvoke-winapi","01.csharp\u002F07.system-programming-windows\u002F18.pinvoke-winapi",{"title":368,"path":369,"stem":370},"Реєстр Windows — Центральна База Конфігурації Системи","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-registry","01.csharp\u002F07.system-programming-windows\u002F19.windows-registry",{"title":372,"path":373,"stem":374},"Windows Hooks, Hotkeys та Services — Глибока Інтеграція з ОС","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-hooks-services","01.csharp\u002F07.system-programming-windows\u002F20.windows-hooks-services",{"title":376,"path":377,"stem":378},"Системне Програмування C# (Windows) — 07.system-programming-windows","\u002Fcsharp\u002Fsystem-programming-windows\u002Fimplementation_plan","01.csharp\u002F07.system-programming-windows\u002Fimplementation_plan",{"title":380,"icon":132,"path":381,"stem":382,"children":383,"page":59},"Io","\u002Fcsharp\u002Fio","01.csharp\u002F08.io",[384,388,392,396,400],{"title":385,"path":386,"stem":387},"8.1.1. Основи роботи з файловою системою","\u002Fcsharp\u002Fio\u002Ffile-system-basics","01.csharp\u002F08.io\u002F01.file-system-basics",{"title":389,"path":390,"stem":391},"8.1.2. Потоки (Streams) та Серіалізація Даних","\u002Fcsharp\u002Fio\u002Fstreams-serialization","01.csharp\u002F08.io\u002F02.streams-serialization",{"title":393,"path":394,"stem":395},"8.2.1. JSON Serialization з System.Text.Json","\u002Fcsharp\u002Fio\u002Fjson-serialization","01.csharp\u002F08.io\u002F03.json-serialization",{"title":397,"path":398,"stem":399},"8.2.2. XML Serialization та LINQ to XML","\u002Fcsharp\u002Fio\u002Fxml-serialization","01.csharp\u002F08.io\u002F04.xml-serialization",{"title":401,"path":402,"stem":403},"8.2.3. Binary Serialization: MessagePack та Protocol Buffers","\u002Fcsharp\u002Fio\u002Fbinary-serialization","01.csharp\u002F08.io\u002F05.binary-serialization",{"title":405,"icon":132,"path":406,"stem":407,"children":408,"page":59},"Ado Net","\u002Fcsharp\u002Fado-net","01.csharp\u002F09.ado-net",[409,413,417,421,425,429,433,437,441,445,449,453],{"title":410,"path":411,"stem":412},"9.1. Введення в ADO.NET","\u002Fcsharp\u002Fado-net\u002Fintroduction-to-adonet","01.csharp\u002F09.ado-net\u002F01.introduction-to-adonet",{"title":414,"path":415,"stem":416},"9.2. Клас DbConnection — з'єднання з базою даних","\u002Fcsharp\u002Fado-net\u002Fconnection","01.csharp\u002F09.ado-net\u002F02.connection",{"title":418,"path":419,"stem":420},"9.3. Клас DbCommand — виконання SQL-запитів","\u002Fcsharp\u002Fado-net\u002Fcommand-and-queries","01.csharp\u002F09.ado-net\u002F03.command-and-queries",{"title":422,"path":423,"stem":424},"9.4. Клас DbDataReader — ефективне читання даних","\u002Fcsharp\u002Fado-net\u002Fdatareader","01.csharp\u002F09.ado-net\u002F04.datareader",{"title":426,"path":427,"stem":428},"9.5. Параметризовані запити та захист від SQL Injection","\u002Fcsharp\u002Fado-net\u002Fparameters-and-sql-injection","01.csharp\u002F09.ado-net\u002F05.parameters-and-sql-injection",{"title":430,"path":431,"stem":432},"9.6. Транзакції в ADO.NET","\u002Fcsharp\u002Fado-net\u002Ftransactions","01.csharp\u002F09.ado-net\u002F06.transactions",{"title":434,"path":435,"stem":436},"9.7. DbProviderFactory — провайдер-незалежний код","\u002Fcsharp\u002Fado-net\u002Fprovider-factory","01.csharp\u002F09.ado-net\u002F07.provider-factory",{"title":438,"path":439,"stem":440},"9.8. Асинхронний доступ до даних","\u002Fcsharp\u002Fado-net\u002Fasync-data-access","01.csharp\u002F09.ado-net\u002F08.async-data-access",{"title":442,"path":443,"stem":444},"9.9. Від'єднаний режим: DataSet, DataTable, DataRow","\u002Fcsharp\u002Fado-net\u002Fdisconnected-mode-dataset","01.csharp\u002F09.ado-net\u002F09.disconnected-mode-dataset",{"title":446,"path":447,"stem":448},"9.10. DataAdapter — міст між DataSet та базою даних","\u002Fcsharp\u002Fado-net\u002Fdata-adapter","01.csharp\u002F09.ado-net\u002F10.data-adapter",{"title":450,"path":451,"stem":452},"9.11. Data Mapper та Repository: Архітектура доступу до даних","\u002Fcsharp\u002Fado-net\u002Fdata-mapper-repository","01.csharp\u002F09.ado-net\u002F11.data-mapper-repository",{"title":454,"path":455,"stem":456},"9.12. Identity Map, Unit of Work та Specification Pattern","\u002Fcsharp\u002Fado-net\u002Fadvanced-patterns","01.csharp\u002F09.ado-net\u002F12.advanced-patterns",{"title":458,"icon":255,"path":459,"stem":460,"children":461,"page":59},"Ef Core","\u002Fcsharp\u002Fef-core","01.csharp\u002F10.ef-core",[462,466,470,474,478,482,486,490,494,498,502,506,510,514,518,522,526,532,538,542,546,550,554,558,562,566,570,574,578,582,586,590,594,598,602,606,610,614,618,622,626,630,634,638,642,646],{"title":463,"path":464,"stem":465},"Що таке ORM? Від SQL до об'єктів","\u002Fcsharp\u002Fef-core\u002Fwhat-is-orm","01.csharp\u002F10.ef-core\u002F01.what-is-orm",{"title":467,"path":468,"stem":469},"Перший проєкт — від нуля до CRUD","\u002Fcsharp\u002Fef-core\u002Ffirst-project","01.csharp\u002F10.ef-core\u002F02.first-project",{"title":471,"path":472,"stem":473},"DbContext — Серце EF Core","\u002Fcsharp\u002Fef-core\u002Fdbcontext-deep-dive","01.csharp\u002F10.ef-core\u002F03.dbcontext-deep-dive",{"title":475,"path":476,"stem":477},"Провайдери баз даних — Архітектура та Вибір СУБД","\u002Fcsharp\u002Fef-core\u002Fdatabase-providers","01.csharp\u002F10.ef-core\u002F04.database-providers",{"title":479,"path":480,"stem":481},"Конвенції EF Core — Магія без конфігурації","\u002Fcsharp\u002Fef-core\u002Fconventions","01.csharp\u002F10.ef-core\u002F05.conventions",{"title":483,"path":484,"stem":485},"Fluent API та Data Annotations — Явна конфігурація моделі","\u002Fcsharp\u002Fef-core\u002Ffluent-api-vs-annotations","01.csharp\u002F10.ef-core\u002F06.fluent-api-vs-annotations",{"title":487,"path":488,"stem":489},"Зв'язки — One-to-One та One-to-Many","\u002Fcsharp\u002Fef-core\u002Frelationships-basics","01.csharp\u002F10.ef-core\u002F07.relationships-basics",{"title":491,"path":492,"stem":493},"Зв'язки Advanced — Many-to-Many та Складні Сценарії","\u002Fcsharp\u002Fef-core\u002Frelationships-advanced","01.csharp\u002F10.ef-core\u002F08.relationships-advanced",{"title":495,"path":496,"stem":497},"Властивості — Типи, Конвертери, Компаратори (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part1","01.csharp\u002F10.ef-core\u002F09.property-configuration-part1",{"title":499,"path":500,"stem":501},"Властивості — Value Comparers, Generators, Shadow Properties (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part2","01.csharp\u002F10.ef-core\u002F09.property-configuration-part2",{"title":503,"path":504,"stem":505},"Складні типи — Owned Types та Complex Types (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part1","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part1",{"title":507,"path":508,"stem":509},"Складні типи — Complex Types, Keyless Entities, Порівняння (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part2","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part2",{"title":511,"path":512,"stem":513},"JSON Columns — Складні дані у JSON (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part1","01.csharp\u002F10.ef-core\u002F11.json-columns-part1",{"title":515,"path":516,"stem":517},"JSON Columns — Value Comparers, Індекси, Провайдери (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part2","01.csharp\u002F10.ef-core\u002F11.json-columns-part2",{"title":519,"path":520,"stem":521},"Успадкування — Абстрактні класи та TPH (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finheritance-part1","01.csharp\u002F10.ef-core\u002F12.inheritance-part1",{"title":523,"path":524,"stem":525},"Успадкування — TPT, TPC та Порівняння Стратегій (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finheritance-part2","01.csharp\u002F10.ef-core\u002F12.inheritance-part2",{"title":527,"path":528,"stem":529,"children":530},"Індекси, Обмеження та Схема (Частина 1)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part1","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part1",[531],{"title":527,"path":528,"stem":529},{"title":533,"path":534,"stem":535,"children":536},"Індекси, Обмеження та Схема (Частина 2)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part2","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part2",[537],{"title":533,"path":534,"stem":535},{"title":539,"path":540,"stem":541},"Seed Data — Початкові Дані (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fseeding-part1","01.csharp\u002F10.ef-core\u002F14.seeding-part1",{"title":543,"path":544,"stem":545},"Seed Data — SQL-скрипти, Bogus та Стратегії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fseeding-part2","01.csharp\u002F10.ef-core\u002F14.seeding-part2",{"title":547,"path":548,"stem":549},"Global Query Filters — Глобальні Фільтри (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part1","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part1",{"title":551,"path":552,"stem":553},"Global Query Filters — Підводні камені та Інтеграція (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part2","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part2",{"title":555,"path":556,"stem":557},"LINQ-запити в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part1","01.csharp\u002F10.ef-core\u002F16.linq-queries-part1",{"title":559,"path":560,"stem":561},"LINQ-запити в EF Core (Частина 2)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part2","01.csharp\u002F10.ef-core\u002F16.linq-queries-part2",{"title":563,"path":564,"stem":565},"Завантаження Пов'язаних Даних (Частина 1)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part1","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part1",{"title":567,"path":568,"stem":569},"Завантаження Пов'язаних Даних (Частина 2)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part2","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part2",{"title":571,"path":572,"stem":573},"Raw SQL, Views та Stored Procedures (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part1","01.csharp\u002F10.ef-core\u002F18.raw-sql-part1",{"title":575,"path":576,"stem":577},"Raw SQL — Stored Procedures, DbFunction та Bulk Operations (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part2","01.csharp\u002F10.ef-core\u002F18.raw-sql-part2",{"title":579,"path":580,"stem":581},"Продвинуті Запити — Compiled Queries, Bulk та Оптимізація (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part1","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part1",{"title":583,"path":584,"stem":585},"Продвинуті Запити — Query Tags, Bulk та Interceptors (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part2","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part2",{"title":587,"path":588,"stem":589},"Change Tracker — Відстеження Змін (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part1","01.csharp\u002F10.ef-core\u002F20.change-tracking-part1",{"title":591,"path":592,"stem":593},"Change Tracker — Графи Об'єктів та Disconnected (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part2","01.csharp\u002F10.ef-core\u002F20.change-tracking-part2",{"title":595,"path":596,"stem":597},"Збереження Даних та Транзакції (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part1","01.csharp\u002F10.ef-core\u002F21.saving-data-part1",{"title":599,"path":600,"stem":601},"Збереження Даних — Concurrency та Outbox (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part2","01.csharp\u002F10.ef-core\u002F21.saving-data-part2",{"title":603,"path":604,"stem":605},"Конкурентність та Блокування (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part1","01.csharp\u002F10.ef-core\u002F22.concurrency-part1",{"title":607,"path":608,"stem":609},"Конкурентність — Дедлоки та Queue Processing (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part2","01.csharp\u002F10.ef-core\u002F22.concurrency-part2",{"title":611,"path":612,"stem":613},"Міграції в EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part1","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part1",{"title":615,"path":616,"stem":617},"Міграції в EF Core — Основи (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part2","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part2",{"title":619,"path":620,"stem":621},"Міграції — Просунуті Сценарії (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part1","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part1",{"title":623,"path":624,"stem":625},"Міграції — Просунуті Сценарії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part2","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part2",{"title":627,"path":628,"stem":629},"Управління Схемою та Database-First (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part1","01.csharp\u002F10.ef-core\u002F25.schema-management-part1",{"title":631,"path":632,"stem":633},"Управління Схемою та Database-First (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part2","01.csharp\u002F10.ef-core\u002F25.schema-management-part2",{"title":635,"path":636,"stem":637},"Продуктивність EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fperformance-fundamentals-part1","01.csharp\u002F10.ef-core\u002F26.performance-fundamentals-part1",{"title":639,"path":640,"stem":641},"Interceptors в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part1","01.csharp\u002F10.ef-core\u002F29.interceptors-part1",{"title":643,"path":644,"stem":645},"Interceptors в EF Core — Connection, Transaction та Materialization (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part2","01.csharp\u002F10.ef-core\u002F29.interceptors-part2",{"title":647,"path":648,"stem":649},"План вивчення Entity Framework Core — Повний курс","\u002Fcsharp\u002Fef-core\u002Fimplementation_plan","01.csharp\u002F10.ef-core\u002Fimplementation_plan",{"title":651,"icon":652,"path":653,"stem":654,"children":655,"page":59},"ASP.NET","i-devicon-dotnetcore","\u002Fcsharp\u002Faspnet","01.csharp\u002F11.aspnet",[656,730,791,869,927,941,967,1057,1111,1182,1212,1289,1346],{"title":657,"icon":658,"path":659,"stem":660,"children":661,"page":59},"Minimal API","i-lucide-network","\u002Fcsharp\u002Faspnet\u002Fminimal-api","01.csharp\u002F11.aspnet\u002F01.minimal-api",[662,666,670,674,678,682,686,690,694,698,702,706,710,714,718,722,726],{"title":663,"path":664,"stem":665},"Вступ до ASP.NET та еволюція фреймворку","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fintroduction","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F01.introduction",{"title":667,"path":668,"stem":669},"Перший додаток на ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Ffirst-application","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F02.first-application",{"title":671,"path":672,"stem":673},"WebApplication, Builder та Dependency Injection","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fwebapplication-builder","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F03.webapplication-builder",{"title":675,"path":676,"stem":677},"Конвеєр запитів та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frequest-pipeline-middleware","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F04.request-pipeline-middleware",{"title":679,"path":680,"stem":681},"Маршрутизація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F05.routing-basics",{"title":683,"path":684,"stem":685},"Маршрутизація в ASP.NET Core: Розширені можливості","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F06.routing-advanced",{"title":687,"path":688,"stem":689},"Статичні файли в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-files","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F07.static-files",{"title":691,"path":692,"stem":693},"Статичні Активи: MapStaticAssets (ASP.NET Core 9.0)","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-assets","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F08.static-assets",{"title":695,"path":696,"stem":697},"Конфігурація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-fundamentals","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F09.configuration-fundamentals",{"title":699,"path":700,"stem":701},"Конфігурація: Паттерн Options","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-options","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F10.configuration-options",{"title":703,"path":704,"stem":705},"Логування в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F11.logging-basics",{"title":707,"path":708,"stem":709},"Логування: Serilog та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F12.logging-advanced",{"title":711,"path":712,"stem":713},"Управління станом: HttpContext.Items та Cookies","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstate-management","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F13.state-management",{"title":715,"path":716,"stem":717},"Стан сесії: Sessions","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fsession-state","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F14.session-state",{"title":719,"path":720,"stem":721},"Структура проєкту: від хаосу до архітектури","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fproject-structure","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F15.project-structure",{"title":723,"path":724,"stem":725},"Scalar у Minimal API: повний проєкт і Fluent OpenAPI","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fscalar-openapi-fluent","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F16.scalar-openapi-fluent",{"title":727,"path":728,"stem":729},"Swagger \u002F Swashbuckle у Minimal API: окремий класичний шлях","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fswagger-swashbuckle","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F17.swagger-swashbuckle",{"title":731,"icon":658,"path":732,"stem":733,"children":734,"page":59},"API","\u002Fcsharp\u002Faspnet\u002Fapi","01.csharp\u002F11.aspnet\u002F02.api",[735,739,743,747,751,755,759,763,767,771,775,779,783,787],{"title":736,"path":737,"stem":738},"Що таке API. Клієнт-серверна архітектура","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fwhat-is-api","01.csharp\u002F11.aspnet\u002F02.api\u002F01.what-is-api",{"title":740,"path":741,"stem":742},"Формати даних: JSON, XML, TOML та бінарні формати","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fdata-formats","01.csharp\u002F11.aspnet\u002F02.api\u002F02.data-formats",{"title":744,"path":745,"stem":746},"Парадигми API та концепція REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-paradigms-rest","01.csharp\u002F11.aspnet\u002F02.api\u002F03.api-paradigms-rest",{"title":748,"path":749,"stem":750},"HTTP-методи, статус-коди та заголовки","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fhttp-methods-status-codes","01.csharp\u002F11.aspnet\u002F02.api\u002F04.http-methods-status-codes",{"title":752,"path":753,"stem":754},"Організація HTTP API за принципами REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Frest-organizing","01.csharp\u002F11.aspnet\u002F02.api\u002F05.rest-organizing",{"title":756,"path":757,"stem":758},"Номенклатура URL та CRUD-операції","\u002Fcsharp\u002Faspnet\u002Fapi\u002Furl-nomenclature-crud","01.csharp\u002F11.aspnet\u002F02.api\u002F06.url-nomenclature-crud",{"title":760,"path":761,"stem":762},"Правила дизайну: іменування та стандарти","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-naming","01.csharp\u002F11.aspnet\u002F02.api\u002F07.api-design-naming",{"title":764,"path":765,"stem":766},"Валідація, ліміти та обробка помилок","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-validation","01.csharp\u002F11.aspnet\u002F02.api\u002F08.api-design-validation",{"title":768,"path":769,"stem":770},"Обробка помилок у Minimal API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Ferror-handling-http","01.csharp\u002F11.aspnet\u002F02.api\u002F09.error-handling-http",{"title":772,"path":773,"stem":774},"Ідемпотентність та синхронізація стану","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fidempotency-sync","01.csharp\u002F11.aspnet\u002F02.api\u002F10.idempotency-sync",{"title":776,"path":777,"stem":778},"Пагінація та організація списків","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fpagination-lists","01.csharp\u002F11.aspnet\u002F02.api\u002F11.pagination-lists",{"title":780,"path":781,"stem":782},"Безпека API, кешування та інтернаціоналізація","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fsecurity-auth","01.csharp\u002F11.aspnet\u002F02.api\u002F12.security-auth",{"title":784,"path":785,"stem":786},"Процес проєктування API та документування","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-process","01.csharp\u002F11.aspnet\u002F02.api\u002F13.api-design-process",{"title":788,"path":789,"stem":790},"OpenAPI: контракт, специфікація та документація API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fopenapi","01.csharp\u002F11.aspnet\u002F02.api\u002F14.openapi",{"title":792,"icon":793,"path":794,"stem":795,"children":796,"page":59},"Auth","i-lucide-shield-check","\u002Fcsharp\u002Faspnet\u002Fauth","01.csharp\u002F11.aspnet\u002F03.auth",[797,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865],{"title":798,"path":799,"stem":800},"Основи аутентифікації та авторизації","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauth-fundamentals","01.csharp\u002F11.aspnet\u002F03.auth\u002F01.auth-fundamentals",{"title":802,"path":803,"stem":804},"JWT-аутентифікація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fjwt-authentication","01.csharp\u002F11.aspnet\u002F03.auth\u002F02.jwt-authentication",{"title":806,"path":807,"stem":808},"Авторизація: ролі, політики та resource-based доступ","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauthorization-policies","01.csharp\u002F11.aspnet\u002F03.auth\u002F03.authorization-policies",{"title":810,"path":811,"stem":812},"Cookie-аутентифікація та ASP.NET Core Identity","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcookie-auth-identity","01.csharp\u002F11.aspnet\u002F03.auth\u002F04.cookie-auth-identity",{"title":814,"path":815,"stem":816},"JWT + Refresh Tokens (HttpOnly Cookie)","\u002Fcsharp\u002Faspnet\u002Fauth\u002F04b.identity-auth-jwt","01.csharp\u002F11.aspnet\u002F03.auth\u002F04b.identity-auth-jwt",{"title":818,"path":819,"stem":820},"Identity: Підтвердження Email та Скидання Пароля","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-email-confirmation","01.csharp\u002F11.aspnet\u002F03.auth\u002F05.identity-email-confirmation",{"title":822,"path":823,"stem":824},"Identity: Двофакторна Аутентифікація (2FA)","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-two-factor","01.csharp\u002F11.aspnet\u002F03.auth\u002F06.identity-two-factor",{"title":826,"path":827,"stem":828},"Identity: Внутрішня Архітектура та Кастомізація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-internals","01.csharp\u002F11.aspnet\u002F03.auth\u002F07.identity-internals",{"title":830,"path":831,"stem":832},"OAuth 2.0 та зовнішні провайдери","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-external-providers","01.csharp\u002F11.aspnet\u002F03.auth\u002F08.oauth-external-providers",{"title":834,"path":835,"stem":836},"Безпека на практиці: CORS, HTTPS та захист від атак","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fsecurity-hardening","01.csharp\u002F11.aspnet\u002F03.auth\u002F09.security-hardening",{"title":838,"path":839,"stem":840},"Теорія OAuth 2.0: Поняття, Аналогії та Флоу","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-theory","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oauth-theory",{"title":842,"path":843,"stem":844},"OIDC, OAuth 2.0 та Keycloak в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foidc-keycloak","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oidc-keycloak",{"title":846,"path":847,"stem":848},"API Keys аутентифікація в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fapi-keys","01.csharp\u002F11.aspnet\u002F03.auth\u002F11.api-keys",{"title":850,"path":851,"stem":852},"Rate Limiting та Throttling в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frate-limiting","01.csharp\u002F11.aspnet\u002F03.auth\u002F12.rate-limiting",{"title":854,"path":855,"stem":856},"Refresh Token Rotation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frefresh-token-rotation","01.csharp\u002F11.aspnet\u002F03.auth\u002F13.refresh-token-rotation",{"title":858,"path":859,"stem":860},"Certificate Authentication та mTLS в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcertificate-auth","01.csharp\u002F11.aspnet\u002F03.auth\u002F14.certificate-auth",{"title":862,"path":863,"stem":864},"RBAC, ABAC та ReBAC в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frbac-abac-rebac","01.csharp\u002F11.aspnet\u002F03.auth\u002F15.rbac-abac-rebac",{"title":866,"path":867,"stem":868},"Multi-tenancy та ізоляція даних в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fmulti-tenancy","01.csharp\u002F11.aspnet\u002F03.auth\u002F16.multi-tenancy",{"title":870,"icon":871,"path":872,"stem":873,"children":874,"page":59},"Нотифікації","i-lucide-bell","\u002Fcsharp\u002Faspnet\u002Fnotifications","01.csharp\u002F11.aspnet\u002F04.notifications",[875,879,883,887,891,895,899,903,907,911,915,919,923],{"title":876,"path":877,"stem":878},"In-App нотифікації через базу даних","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fin-app-database-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F01.in-app-database-notifications",{"title":880,"path":881,"stem":882},"Polling: Регулярний запит оновлень","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fpolling","01.csharp\u002F11.aspnet\u002F04.notifications\u002F02.polling",{"title":884,"path":885,"stem":886},"Server-Sent Events: Однострімовий push від сервера","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fserver-sent-events","01.csharp\u002F11.aspnet\u002F04.notifications\u002F03.server-sent-events",{"title":888,"path":889,"stem":890},"WebSockets: Двостороннє з'єднання в реальному часі","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fwebsockets","01.csharp\u002F11.aspnet\u002F04.notifications\u002F04.websockets",{"title":892,"path":893,"stem":894},"SignalR: Абстракція над транспортами реального часу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fsignalr","01.csharp\u002F11.aspnet\u002F04.notifications\u002F05.signalr",{"title":896,"path":897,"stem":898},"Background Services: Фонові задачі в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fbackground-services","01.csharp\u002F11.aspnet\u002F04.notifications\u002F06.background-services",{"title":900,"path":901,"stem":902},"Web Push нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fweb-push","01.csharp\u002F11.aspnet\u002F04.notifications\u002F07.web-push",{"title":904,"path":905,"stem":906},"Email нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Femail-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F08.email-notifications",{"title":908,"path":909,"stem":910},"Порівняння підходів: Як вибрати правильну технологію нотифікацій","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fchoosing-the-right-approach","01.csharp\u002F11.aspnet\u002F04.notifications\u002F09.choosing-the-right-approach",{"title":912,"path":913,"stem":914},"Hangfire: Надійне планування фонових задач","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire","01.csharp\u002F11.aspnet\u002F04.notifications\u002F10.hangfire",{"title":916,"path":917,"stem":918},"Практика: Конвертація зображень у WebP через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-image-webp","01.csharp\u002F11.aspnet\u002F04.notifications\u002F11.hangfire-image-webp",{"title":920,"path":921,"stem":922},"Практика: Підготовка відео до HLS-стрімінгу через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-video-hls","01.csharp\u002F11.aspnet\u002F04.notifications\u002F12.hangfire-video-hls",{"title":924,"path":925,"stem":926},"Telegram-нотифікації: від одного повідомлення до масових розсилок і мульти-канального підходу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Ftelegram-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F13.telegram-notifications",{"title":928,"icon":929,"path":930,"stem":931,"children":932,"page":59},"Інтернаціоналізація","i-lucide-languages","\u002Fcsharp\u002Faspnet\u002Fi18n","01.csharp\u002F11.aspnet\u002F05.i18n",[933,937],{"title":934,"path":935,"stem":936},"Інтернаціоналізація (i18n) у Minimal API: від A до Я","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Finternationalization","01.csharp\u002F11.aspnet\u002F05.i18n\u002F01.internationalization",{"title":938,"path":939,"stem":940},"Humanizer: людиномовні рядки у .NET","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Fhumanizer","01.csharp\u002F11.aspnet\u002F05.i18n\u002F02.humanizer",{"title":942,"icon":943,"path":944,"stem":945,"children":946,"page":59},"Кешування","i-lucide-layers","\u002Fcsharp\u002Faspnet\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching",[947,951,955,959,963],{"title":948,"path":949,"stem":950},"Огляд кешування: чотири рівні і коли що обирати","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching\u002F01.caching",{"title":952,"path":953,"stem":954},"IMemoryCache: кеш в оперативній пам'яті","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fmemory-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F02.memory-cache",{"title":956,"path":957,"stem":958},"IDistributedCache і Redis: розподілений кеш","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fdistributed-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F03.distributed-cache",{"title":960,"path":961,"stem":962},"Response Cache: HTTP-кешування через Cache-Control","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fresponse-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F04.response-cache",{"title":964,"path":965,"stem":966},"Output Cache: серверний кеш HTTP-відповідей (.NET 7+)","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Foutput-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F05.output-cache",{"title":968,"icon":969,"path":970,"stem":971,"children":972,"page":59},"Тестування","i-lucide-test-tube","\u002Fcsharp\u002Faspnet\u002Ftesting","01.csharp\u002F11.aspnet\u002F07.testing",[973,977,981,985,989,993,997,1001,1005,1009,1013,1017,1021,1025,1029,1033,1037,1041,1045,1049,1053],{"title":974,"path":975,"stem":976},"Що таке тестування? Від інтуїції до науки","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-is-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F01.what-is-testing",{"title":978,"path":979,"stem":980},"Піраміда тестування — Стратегія, а не Догма","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-pyramid","01.csharp\u002F11.aspnet\u002F07.testing\u002F02.testing-pyramid",{"title":982,"path":983,"stem":984},"Дві Школи Тестування — Лондон проти Детройту","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-schools","01.csharp\u002F11.aspnet\u002F07.testing\u002F03.testing-schools",{"title":986,"path":987,"stem":988},"TDD та BDD — Тести як Дизайн-інструмент","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftdd-and-bdd","01.csharp\u002F11.aspnet\u002F07.testing\u002F04.tdd-and-bdd",{"title":990,"path":991,"stem":992},"Що саме тестувати — Техніки аналізу та Циклomatична складність","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-to-test","01.csharp\u002F11.aspnet\u002F07.testing\u002F05.what-to-test",{"title":994,"path":995,"stem":996},"Тестові Фреймворки — Навіщо вони і що всередині","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftest-frameworks","01.csharp\u002F11.aspnet\u002F07.testing\u002F06.test-frameworks",{"title":998,"path":999,"stem":1000},"xUnit — Факти, Теорії та Lifecycle тестів","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-basics","01.csharp\u002F11.aspnet\u002F07.testing\u002F07.xunit-basics",{"title":1002,"path":1003,"stem":1004},"xUnit Advanced — Fixtures, Кастомізація та Розширення","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F08.xunit-advanced",{"title":1006,"path":1007,"stem":1008},"Moq — Глибоке занурення в мокування","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fmocking-with-moq","01.csharp\u002F11.aspnet\u002F07.testing\u002F09.mocking-with-moq",{"title":1010,"path":1011,"stem":1012},"Тестування Баз Даних — EF Core, SQLite та Testcontainers","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fdatabase-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F10.database-testing",{"title":1014,"path":1015,"stem":1016},"Integration Testing — Частина 1 [Теорія та WebApplicationFactory]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F11.integration-testing",{"title":1018,"path":1019,"stem":1020},"Інтеграційне тестування — Практика","\u002Fcsharp\u002Faspnet\u002Ftesting\u002F11a.integration-testing-practice","01.csharp\u002F11.aspnet\u002F07.testing\u002F11a.integration-testing-practice",{"title":1022,"path":1023,"stem":1024},"Integration Testing — Частина 2 [Просунуті Сценарії та Testcontainers]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F12.integration-testing-advanced",{"title":1026,"path":1027,"stem":1028},"Професійний Postman: Колекції, Змінні та GitHub Інтеграція","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fpostman-professional","01.csharp\u002F11.aspnet\u002F07.testing\u002F13.postman-professional",{"title":1030,"path":1031,"stem":1032},"HttpClient у Тестах Частина 1: Архітектура та MockHttpMessageHandler","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fhttpclient-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F14.httpclient-testing",{"title":1034,"path":1035,"stem":1036},"HttpClient у Тестах Частина 2: WireMock.Net та Resilience","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwiremock-net","01.csharp\u002F11.aspnet\u002F07.testing\u002F15.wiremock-net",{"title":1038,"path":1039,"stem":1040},"Патерни та Анти-патерни Тестування: Test Smells","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-patterns","01.csharp\u002F11.aspnet\u002F07.testing\u002F16.testing-patterns",{"title":1042,"path":1043,"stem":1044},"Просунуті інструменти: Time, Snapshots та Властивості","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fadvanced-testing-tools","01.csharp\u002F11.aspnet\u002F07.testing\u002F17.advanced-testing-tools",{"title":1046,"path":1047,"stem":1048},"Тестування Архітектури з NetArchTest","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Farchitecture-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F18.architecture-testing",{"title":1050,"path":1051,"stem":1052},"Тестування Продуктивності: BenchmarkDotNet, NBomber та k6","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fperformance-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F19.performance-testing",{"title":1054,"path":1055,"stem":1056},"Залишок плану для курсу \"Тестування ASP.NET Minimal API\"","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fremaining_plan","01.csharp\u002F11.aspnet\u002F07.testing\u002Fremaining_plan",{"title":1058,"icon":1059,"path":1060,"stem":1061,"children":1062,"page":59},"Платежі","i-lucide-credit-card","\u002Fcsharp\u002Faspnet\u002Fpayments","01.csharp\u002F11.aspnet\u002F08.payments",[1063,1067,1071,1075,1079,1083,1087,1091,1095,1099,1103,1107],{"title":1064,"path":1065,"stem":1066},"Основи платіжної інфраструктури","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-fundamentals","01.csharp\u002F11.aspnet\u002F08.payments\u002F01.payment-fundamentals",{"title":1068,"path":1069,"stem":1070},"Методи оплати в Україні","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-methods-ukraine","01.csharp\u002F11.aspnet\u002F08.payments\u002F02.payment-methods-ukraine",{"title":1072,"path":1073,"stem":1074},"PCI DSS та безпека платежів","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpci-dss-security","01.csharp\u002F11.aspnet\u002F08.payments\u002F03.pci-dss-security",{"title":1076,"path":1077,"stem":1078},"Архітектура платіжної підсистеми","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-architecture","01.csharp\u002F11.aspnet\u002F08.payments\u002F04.payment-architecture",{"title":1080,"path":1081,"stem":1082},"Інтеграція LiqPay (ПриватБанк)","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fliqpay-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F05.liqpay-integration",{"title":1084,"path":1085,"stem":1086},"Інтеграція Monobank Acquiring API","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fmonobank-acquiring","01.csharp\u002F11.aspnet\u002F08.payments\u002F06.monobank-acquiring",{"title":1088,"path":1089,"stem":1090},"Інтеграція Stripe","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fstripe-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F07.stripe-integration",{"title":1092,"path":1093,"stem":1094},"Webhooks — глибоке занурення","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fwebhooks-deep-dive","01.csharp\u002F11.aspnet\u002F08.payments\u002F08.webhooks-deep-dive",{"title":1096,"path":1097,"stem":1098},"Підписки та рекурентні платежі","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fsubscriptions-recurring","01.csharp\u002F11.aspnet\u002F08.payments\u002F09.subscriptions-recurring",{"title":1100,"path":1101,"stem":1102},"Повернення коштів та диспути","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Frefunds-disputes","01.csharp\u002F11.aspnet\u002F08.payments\u002F10.refunds-disputes",{"title":1104,"path":1105,"stem":1106},"Тестування платіжних інтеграцій","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Ftesting-payments","01.csharp\u002F11.aspnet\u002F08.payments\u002F11.testing-payments",{"title":1108,"path":1109,"stem":1110},"Чекліст виходу в Production","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fproduction-checklist","01.csharp\u002F11.aspnet\u002F08.payments\u002F12.production-checklist",{"title":1112,"icon":1113,"items":1114,"path":1127,"stem":1128,"children":1129,"page":59},"Популярні бібліотеки","lucide:box",[1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126],"01.fluent-validation","02.mapster","03.erroror-result-pattern","04.serilog","05.mediatr","06.polly","07.health-checks","08.feature-management","09.fluent-email","10.quest-pdf","11.bogus","12.humanizer-guard","\u002Fcsharp\u002Faspnet\u002Flibraries","01.csharp\u002F11.aspnet\u002F09.libraries",[1130,1134,1138,1142,1146,1150,1154,1158,1162,1166,1170,1174,1178],{"title":1131,"path":1132,"stem":1133},"Валідація з FluentValidation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-validation","01.csharp\u002F11.aspnet\u002F09.libraries\u002F01.fluent-validation",{"title":1135,"path":1136,"stem":1137},"Маппінг об","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmapster","01.csharp\u002F11.aspnet\u002F09.libraries\u002F02.mapster",{"title":1139,"path":1140,"stem":1141},"Обробка помилок з ErrorOr та Result Pattern в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ferroror-result-pattern","01.csharp\u002F11.aspnet\u002F09.libraries\u002F03.erroror-result-pattern",{"title":1143,"path":1144,"stem":1145},"Структуроване логування з Serilog в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fserilog","01.csharp\u002F11.aspnet\u002F09.libraries\u002F04.serilog",{"title":1147,"path":1148,"stem":1149},"CQRS та Mediator з MediatR в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmediatr","01.csharp\u002F11.aspnet\u002F09.libraries\u002F05.mediatr",{"title":1151,"path":1152,"stem":1153},"Відмовостійкість з Polly в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fpolly","01.csharp\u002F11.aspnet\u002F09.libraries\u002F06.polly",{"title":1155,"path":1156,"stem":1157},"Health Checks в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F09.libraries\u002F07.health-checks",{"title":1159,"path":1160,"stem":1161},"Feature Management та Feature Flags в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffeature-management","01.csharp\u002F11.aspnet\u002F09.libraries\u002F08.feature-management",{"title":1163,"path":1164,"stem":1165},"Відправка Email з FluentEmail в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-email","01.csharp\u002F11.aspnet\u002F09.libraries\u002F09.fluent-email",{"title":1167,"path":1168,"stem":1169},"Генерація PDF з QuestPDF в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fquest-pdf","01.csharp\u002F11.aspnet\u002F09.libraries\u002F10.quest-pdf",{"title":1171,"path":1172,"stem":1173},"Генерація тестових даних з Bogus в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fbogus","01.csharp\u002F11.aspnet\u002F09.libraries\u002F11.bogus",{"title":1175,"path":1176,"stem":1177},"Humanizer та Guard Clauses в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhumanizer-guard","01.csharp\u002F11.aspnet\u002F09.libraries\u002F12.humanizer-guard",{"title":1179,"path":1180,"stem":1181},"План модуля 10.libraries — Популярні бібліотеки ASP.NET","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fplan","01.csharp\u002F11.aspnet\u002F09.libraries\u002Fplan",{"title":1183,"icon":1184,"path":1185,"stem":1186,"children":1187,"page":59},"Razor Pages","i-lucide-layout-template","\u002Fcsharp\u002Faspnet\u002Frazor-pages","01.csharp\u002F11.aspnet\u002F10.razor-pages",[1188,1192,1196,1200,1204,1208],{"title":1189,"path":1190,"stem":1191},"Від Minimal API до Razor Pages: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ffrom-minimal-api","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F01.from-minimal-api",{"title":1193,"path":1194,"stem":1195},"PageModel: логіка сторінки Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fpage-model","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F02.page-model",{"title":1197,"path":1198,"stem":1199},"Razor синтаксис: шаблонізатор у .cshtml","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Frazor-syntax","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F03.razor-syntax",{"title":1201,"path":1202,"stem":1203},"Tag Helpers: типізований HTML","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ftag-helpers","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F04.tag-helpers",{"title":1205,"path":1206,"stem":1207},"Форми і валідація: повний цикл обробки даних","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fforms-validation","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F05.forms-validation",{"title":1209,"path":1210,"stem":1211},"Практичний проєкт: TaskManager на Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fproject-task-manager","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F06.project-task-manager",{"title":1213,"path":1214,"stem":1215,"children":1216,"page":59},"ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc","01.csharp\u002F11.aspnet\u002F11.mvc",[1217,1221,1225,1229,1233,1237,1241,1245,1249,1253,1257,1261,1265,1269,1273,1277,1281,1285],{"title":1218,"path":1219,"stem":1220},"Патерн MVC: архітектура, що змінила веб","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-pattern","01.csharp\u002F11.aspnet\u002F11.mvc\u002F01.mvc-pattern",{"title":1222,"path":1223,"stem":1224},"Від Razor Pages до MVC: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffrom-razor-pages","01.csharp\u002F11.aspnet\u002F11.mvc\u002F02.from-razor-pages",{"title":1226,"path":1227,"stem":1228},"Controllers та Actions: серце MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fcontrollers-actions","01.csharp\u002F11.aspnet\u002F11.mvc\u002F03.controllers-actions",{"title":1230,"path":1231,"stem":1232},"Маршрутизація в MVC: Convention vs Attribute Routing","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Frouting-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F04.routing-mvc",{"title":1234,"path":1235,"stem":1236},"Model Binding: від HTTP до C#","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmodel-binding","01.csharp\u002F11.aspnet\u002F11.mvc\u002F05.model-binding",{"title":1238,"path":1239,"stem":1240},"Views, ViewData, ViewBag, TempData і ViewModel","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fviews-viewdata-tempdata","01.csharp\u002F11.aspnet\u002F11.mvc\u002F06.views-viewdata-tempdata",{"title":1242,"path":1243,"stem":1244},"Filters: аспектно-орієнтоване програмування в MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffilters","01.csharp\u002F11.aspnet\u002F11.mvc\u002F07.filters",{"title":1246,"path":1247,"stem":1248},"Areas: структурування великих застосунків","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fareas","01.csharp\u002F11.aspnet\u002F11.mvc\u002F08.areas",{"title":1250,"path":1251,"stem":1252},"View Components: повторювані незалежні блоки UI","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fview-components","01.csharp\u002F11.aspnet\u002F11.mvc\u002F09.view-components",{"title":1254,"path":1255,"stem":1256},"Display та Editor Templates","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fdisplay-editor-templates","01.csharp\u002F11.aspnet\u002F11.mvc\u002F10.display-editor-templates",{"title":1258,"path":1259,"stem":1260},"Валідація: IValidatableObject та FluentValidation","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fvalidation-advanced","01.csharp\u002F11.aspnet\u002F11.mvc\u002F11.validation-advanced",{"title":1262,"path":1263,"stem":1264},"HTMX: інтерактивність через HTML-атрибути","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx","01.csharp\u002F11.aspnet\u002F11.mvc\u002F12.htmx",{"title":1266,"path":1267,"stem":1268},"HTMX у ASP.NET Core MVC: серверна інтеграція","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fajax-htmx-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F13.ajax-htmx-mvc",{"title":1270,"path":1271,"stem":1272},"Практичний проєкт: Каталог товарів з HTMX","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F14.htmx-project",{"title":1274,"path":1275,"stem":1276},"Завантаження та обробка файлів","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffile-upload","01.csharp\u002F11.aspnet\u002F11.mvc\u002F15.file-upload",{"title":1278,"path":1279,"stem":1280},"Глобалізація та Локалізація MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fglobalization-localization","01.csharp\u002F11.aspnet\u002F11.mvc\u002F16.globalization-localization",{"title":1282,"path":1283,"stem":1284},"Підсумковий проєкт: Блог-платформа","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F17.mvc-project",{"title":1286,"path":1287,"stem":1288},"План курсу: ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fplan","01.csharp\u002F11.aspnet\u002F11.mvc\u002Fplan",{"title":1290,"path":1291,"stem":1292,"children":1293,"page":59},"Web Api","\u002Fcsharp\u002Faspnet\u002Fweb-api","01.csharp\u002F11.aspnet\u002F12.web-api",[1294,1298,1302,1306,1310,1314,1318,1322,1326,1330,1334,1338,1342],{"title":1295,"path":1296,"stem":1297},"Від Minimal API до Controller-based API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffrom-minimal-api-to-controllers","01.csharp\u002F11.aspnet\u002F12.web-api\u002F01.from-minimal-api-to-controllers",{"title":1299,"path":1300,"stem":1301},"ControllerBase, ActionResult\u003CT> та Response Types","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontroller-base-actionresult","01.csharp\u002F11.aspnet\u002F12.web-api\u002F02.controller-base-actionresult",{"title":1303,"path":1304,"stem":1305},"Content Negotiation - JSON, XML та власні форматери","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontent-negotiation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F03.content-negotiation",{"title":1307,"path":1308,"stem":1309},"Версіонування API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-versioning","01.csharp\u002F11.aspnet\u002F12.web-api\u002F04.api-versioning",{"title":1311,"path":1312,"stem":1313},"ProblemDetails та структурована обробка помилок","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fproblemdetails-error-handling","01.csharp\u002F11.aspnet\u002F12.web-api\u002F05.problemdetails-error-handling",{"title":1315,"path":1316,"stem":1317},"Фільтри у Web API контексті","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffilters-for-api","01.csharp\u002F11.aspnet\u002F12.web-api\u002F06.filters-for-api",{"title":1319,"path":1320,"stem":1321},"Пагінація, фільтрація та сортування","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fpagination-filtering-sorting","01.csharp\u002F11.aspnet\u002F12.web-api\u002F07.pagination-filtering-sorting",{"title":1323,"path":1324,"stem":1325},"HATEOAS та Resource Expansion","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhateoas-resource-expansion","01.csharp\u002F11.aspnet\u002F12.web-api\u002F08.hateoas-resource-expansion",{"title":1327,"path":1328,"stem":1329},"Гібридна архітектура - Minimal API + Controllers","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fminimal-api-vs-controllers-hybrid","01.csharp\u002F11.aspnet\u002F12.web-api\u002F09.minimal-api-vs-controllers-hybrid",{"title":1331,"path":1332,"stem":1333},"Документація API - Swashbuckle, NSwag та генерація клієнтів","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-documentation-generation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F10.api-documentation-generation",{"title":1335,"path":1336,"stem":1337},"Health Checks та моніторинг API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhealth-checks-monitoring","01.csharp\u002F11.aspnet\u002F12.web-api\u002F11.health-checks-monitoring",{"title":1339,"path":1340,"stem":1341},"Підсумковий проєкт - Production-Ready REST API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fweb-api-project","01.csharp\u002F11.aspnet\u002F12.web-api\u002F12.web-api-project",{"title":1343,"path":1344,"stem":1345},"План курсу: ASP.NET Core Web API (Controllers)","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fplan","01.csharp\u002F11.aspnet\u002F12.web-api\u002Fplan",{"title":1347,"icon":1348,"path":1349,"stem":1350,"children":1351,"page":59},"Моніторинг","i-lucide-activity","\u002Fcsharp\u002Faspnet\u002Fmonitoring","01.csharp\u002F11.aspnet\u002F13.monitoring",[1352,1356,1360],{"title":1353,"path":1354,"stem":1355},"Спостережуваність: від console.log до production-систем","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fobservability-intro","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F01.observability-intro",{"title":1357,"path":1358,"stem":1359},"Health Checks: перший рівень observability","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F02.health-checks",{"title":1361,"path":1362,"stem":1363},"Вбудовані метрики .NET 10 та System.Diagnostics.Metrics","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fdotnet-metrics","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F03.dotnet-metrics",{"title":1365,"icon":1366,"path":1367,"stem":1368,"children":1369,"page":59},"Desktop UI","i-lucide-app-window","\u002Fcsharp\u002Fdesktop-ui","01.csharp\u002F12.desktop-ui",[1370,1374,1378,1382,1386,1390,1394,1398,1402,1406,1410,1414,1418,1422,1426,1430,1434,1438,1442,1446,1450,1454,1458,1462,1466,1470,1474,1478,1482,1486,1490,1494,1498,1502,1506,1510,1514,1518,1522,1526,1530,1534,1538,1542,1546,1550,1554,1558,1562,1566,1570,1574,1578,1582,1586,1590,1594,1598,1602,1606,1610,1614,1618,1622,1626,1630,1634,1638,1642,1646,1650],{"title":1371,"path":1372,"stem":1373},"Що таке десктопна розробка?","\u002Fcsharp\u002Fdesktop-ui\u002Fwhat-is-desktop-dev","01.csharp\u002F12.desktop-ui\u002F01.what-is-desktop-dev",{"title":1375,"path":1376,"stem":1377},"Архітектура WPF — як влаштований графічний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-architecture","01.csharp\u002F12.desktop-ui\u002F02.wpf-architecture",{"title":1379,"path":1380,"stem":1381},"Перший WPF-проєкт — від нуля до вікна","\u002Fcsharp\u002Fdesktop-ui\u002Ffirst-wpf-app","01.csharp\u002F12.desktop-ui\u002F03.first-wpf-app",{"title":1383,"path":1384,"stem":1385},"Перший Avalonia-проєкт: WPF для всіх платформ","\u002Fcsharp\u002Fdesktop-ui\u002F03a.first-avalonia-app","01.csharp\u002F12.desktop-ui\u002F03a.first-avalonia-app",{"title":1387,"path":1388,"stem":1389},"XAML: декларативний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-basics","01.csharp\u002F12.desktop-ui\u002F04.xaml-basics",{"title":1391,"path":1392,"stem":1393},"Fluent UI у WPF — сучасний дизайн Windows 11","\u002Fcsharp\u002Fdesktop-ui\u002F04a.wpf-fluent-ui","01.csharp\u002F12.desktop-ui\u002F04a.wpf-fluent-ui",{"title":1395,"path":1396,"stem":1397},"WPF UI — сучасна бібліотека Fluent контролів","\u002Fcsharp\u002Fdesktop-ui\u002F04b.wpf-ui-library","01.csharp\u002F12.desktop-ui\u002F04b.wpf-ui-library",{"title":1399,"path":1400,"stem":1401},"HandyControl — велика бібліотека UI контролів для WPF","\u002Fcsharp\u002Fdesktop-ui\u002F04c.handycontrol-library","01.csharp\u002F12.desktop-ui\u002F04c.handycontrol-library",{"title":1403,"path":1404,"stem":1405},"Простори імен та ресурси XAML","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-namespaces-resources","01.csharp\u002F12.desktop-ui\u002F05.xaml-namespaces-resources",{"title":1407,"path":1408,"stem":1409},"XAML в Avalonia: ключові відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F05a.avalonia-xaml-differences","01.csharp\u002F12.desktop-ui\u002F05a.avalonia-xaml-differences",{"title":1411,"path":1412,"stem":1413},"Розширення розмітки XAML (Markup Extensions)","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-markup-extensions","01.csharp\u002F12.desktop-ui\u002F06.xaml-markup-extensions",{"title":1415,"path":1416,"stem":1417},"Панелі Layout: StackPanel, WrapPanel, DockPanel","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part1","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part1",{"title":1419,"path":1420,"stem":1421},"Grid, Canvas, UniformGrid","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part2","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part2",{"title":1423,"path":1424,"stem":1425},"Просунуті техніки Layout","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-advanced","01.csharp\u002F12.desktop-ui\u002F08.layout-advanced",{"title":1427,"path":1428,"stem":1429},"Адаптивний Layout та найкращі практики","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-responsive","01.csharp\u002F12.desktop-ui\u002F09.layout-responsive",{"title":1431,"path":1432,"stem":1433},"Layout в Avalonia: відмінності та нові можливості","\u002Fcsharp\u002Fdesktop-ui\u002F09a.layout-avalonia","01.csharp\u002F12.desktop-ui\u002F09a.layout-avalonia",{"title":1435,"path":1436,"stem":1437},"Button, Image, ProgressBar та інші базові контроли","\u002Fcsharp\u002Fdesktop-ui\u002Fbasic-controls","01.csharp\u002F12.desktop-ui\u002F10.basic-controls",{"title":1439,"path":1440,"stem":1441},"Контроли в Avalonia: відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F10a.controls-avalonia","01.csharp\u002F12.desktop-ui\u002F10a.controls-avalonia",{"title":1443,"path":1444,"stem":1445},"Текстові контроли — TextBlock, TextBox, RichTextBox","\u002Fcsharp\u002Fdesktop-ui\u002Ftext-controls","01.csharp\u002F12.desktop-ui\u002F11.text-controls",{"title":1447,"path":1448,"stem":1449},"Контроли вибору — CheckBox, RadioButton, ComboBox, ListBox, DatePicker","\u002Fcsharp\u002Fdesktop-ui\u002Fselection-controls","01.csharp\u002F12.desktop-ui\u002F12.selection-controls",{"title":1451,"path":1452,"stem":1453},"Content Model — GroupBox, Expander, TabControl, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fcontent-controls","01.csharp\u002F12.desktop-ui\u002F13.content-controls",{"title":1455,"path":1456,"stem":1457},"UI\u002FUX принципи десктопних застосунків","\u002Fcsharp\u002Fdesktop-ui\u002F13a.ui-ux-principles","01.csharp\u002F12.desktop-ui\u002F13a.ui-ux-principles",{"title":1459,"path":1460,"stem":1461},"Dependency Properties — Концепція та Value Resolution","\u002Fcsharp\u002Fdesktop-ui\u002Fdependency-properties-part1","01.csharp\u002F12.desktop-ui\u002F14.dependency-properties-part1",{"title":1463,"path":1464,"stem":1465},"Avalonia Property System — StyledProperty та DirectProperty","\u002Fcsharp\u002Fdesktop-ui\u002F14a.avalonia-property-system","01.csharp\u002F12.desktop-ui\u002F14a.avalonia-property-system",{"title":1467,"path":1468,"stem":1469},"Attached Properties — Властивості без меж","\u002Fcsharp\u002Fdesktop-ui\u002Fattached-properties","01.csharp\u002F12.desktop-ui\u002F15.attached-properties",{"title":1471,"path":1472,"stem":1473},"Routed Events — Маршрутизація подій у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Frouted-events","01.csharp\u002F12.desktop-ui\u002F16.routed-events",{"title":1475,"path":1476,"stem":1477},"Data Binding — Від Code-Behind до Декларативності","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part1","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part1",{"title":1479,"path":1480,"stem":1481},"INotifyPropertyChanged — Живе оновлення UI","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part2","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part2",{"title":1483,"path":1484,"stem":1485},"Compiled Bindings в Avalonia — Безпека на етапі компіляції","\u002Fcsharp\u002Fdesktop-ui\u002F17a.avalonia-compiled-bindings","01.csharp\u002F12.desktop-ui\u002F17a.avalonia-compiled-bindings",{"title":1487,"path":1488,"stem":1489},"Просунутий Data Binding — ElementName, RelativeSource, MultiBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-advanced","01.csharp\u002F12.desktop-ui\u002F18.data-binding-advanced",{"title":1491,"path":1492,"stem":1493},"Value Converters — Перетворення типів даних у Data Binding","\u002Fcsharp\u002Fdesktop-ui\u002Fvalue-converters","01.csharp\u002F12.desktop-ui\u002F19.value-converters",{"title":1495,"path":1496,"stem":1497},"Data Templates — Візуалізація об'єктів у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-templates","01.csharp\u002F12.desktop-ui\u002F20.data-templates",{"title":1499,"path":1500,"stem":1501},"Collections Binding Part 1 — ObservableCollection та ItemsControl","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part1","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part1",{"title":1503,"path":1504,"stem":1505},"Collections Binding Part 2 — ICollectionView, Filtering, Sorting та Virtualization","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part2","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part2",{"title":1507,"path":1508,"stem":1509},"MVVM Pattern — Від Spaghetti Code до архітектури","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-pattern","01.csharp\u002F12.desktop-ui\u002F22.mvvm-pattern",{"title":1511,"path":1512,"stem":1513},"ViewModel Implementation — Від BaseViewModel до валідації","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-implementation","01.csharp\u002F12.desktop-ui\u002F23.viewmodel-implementation",{"title":1515,"path":1516,"stem":1517},"Commands — Від event handlers до декларативних команд","\u002Fcsharp\u002Fdesktop-ui\u002Fcommands","01.csharp\u002F12.desktop-ui\u002F24.commands",{"title":1519,"path":1520,"stem":1521},"MVVM Toolkit — MVVM без boilerplate через Source Generators","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-toolkit","01.csharp\u002F12.desktop-ui\u002F25.mvvm-toolkit",{"title":1523,"path":1524,"stem":1525},"Messenger Pattern — Комунікація між ViewModel без прямих посилань","\u002Fcsharp\u002Fdesktop-ui\u002Fmessenger-pattern","01.csharp\u002F12.desktop-ui\u002F26.messenger-pattern",{"title":1527,"path":1528,"stem":1529},"Стилі WPF — CSS для десктопу","\u002Fcsharp\u002Fdesktop-ui\u002Fstyles-basics","01.csharp\u002F12.desktop-ui\u002F27.styles-basics",{"title":1531,"path":1532,"stem":1533},"CSS-like стилі Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F27a.avalonia-css-styling","01.csharp\u002F12.desktop-ui\u002F27a.avalonia-css-styling",{"title":1535,"path":1536,"stem":1537},"Control Templates — Частина 1. Концепція та TemplateBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part1","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part1",{"title":1539,"path":1540,"stem":1541},"Control Templates — Частина 2. Named Parts та ContentPresenter","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part2","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part2",{"title":1543,"path":1544,"stem":1545},"Control Themes в Avalonia — нова ера стилізації","\u002Fcsharp\u002Fdesktop-ui\u002F28a.avalonia-control-themes","01.csharp\u002F12.desktop-ui\u002F28a.avalonia-control-themes",{"title":1547,"path":1548,"stem":1549},"Triggers та Visual State Manager у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Ftriggers-visual-states","01.csharp\u002F12.desktop-ui\u002F29.triggers-visual-states",{"title":1551,"path":1552,"stem":1553},"Pseudo-classes в Avalonia — замість WPF Triggers","\u002Fcsharp\u002Fdesktop-ui\u002F29a.avalonia-pseudo-classes","01.csharp\u002F12.desktop-ui\u002F29a.avalonia-pseudo-classes",{"title":1555,"path":1556,"stem":1557},"Теми та ресурсні словники у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fresources-themes","01.csharp\u002F12.desktop-ui\u002F30.resources-themes",{"title":1559,"path":1560,"stem":1561},"Avalonia Themes — Fluent Design та система тематизації","\u002Fcsharp\u002Fdesktop-ui\u002F30a.avalonia-themes-fluent","01.csharp\u002F12.desktop-ui\u002F30a.avalonia-themes-fluent",{"title":1563,"path":1564,"stem":1565},"Контроли колекцій — глибоке занурення","\u002Fcsharp\u002Fdesktop-ui\u002Fcollection-controls","01.csharp\u002F12.desktop-ui\u002F31.collection-controls",{"title":1567,"path":1568,"stem":1569},"DataGrid — колонки та базове відображення","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part1","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part1",{"title":1571,"path":1572,"stem":1573},"DataGrid — сортування, фільтрація, редагування","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part2","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part2",{"title":1575,"path":1576,"stem":1577},"TreeView та GridView","\u002Fcsharp\u002Fdesktop-ui\u002Ftreeview-listview","01.csharp\u002F12.desktop-ui\u002F33.treeview-listview",{"title":1579,"path":1580,"stem":1581},"Меню, Toolbar, ContextMenu, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fmenus-toolbars","01.csharp\u002F12.desktop-ui\u002F34.menus-toolbars",{"title":1583,"path":1584,"stem":1585},"Навігація та керування вікнами. Частина 1: вікна та сторінки","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part1","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part1",{"title":1587,"path":1588,"stem":1589},"Навігація та керування вікнами. Частина 2: MVVM-навігація","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part2","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part2",{"title":1591,"path":1592,"stem":1593},"Avalonia — Навігація та діалоги","\u002Fcsharp\u002Fdesktop-ui\u002F35a.avalonia-navigation-dialogs","01.csharp\u002F12.desktop-ui\u002F35a.avalonia-navigation-dialogs",{"title":1595,"path":1596,"stem":1597},"Діалоги та File Pickers у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdialogs-file-pickers","01.csharp\u002F12.desktop-ui\u002F36.dialogs-file-pickers",{"title":1599,"path":1600,"stem":1601},"UserControl: компонентний підхід у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fuser-controls","01.csharp\u002F12.desktop-ui\u002F37.user-controls",{"title":1603,"path":1604,"stem":1605},"Custom Controls: Lookless Controls у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fcustom-controls","01.csharp\u002F12.desktop-ui\u002F38.custom-controls",{"title":1607,"path":1608,"stem":1609},"Avalonia TemplatedControl — Lookless Controls","\u002Fcsharp\u002Fdesktop-ui\u002F38a.avalonia-templated-controls","01.csharp\u002F12.desktop-ui\u002F38a.avalonia-templated-controls",{"title":1611,"path":1612,"stem":1613},"Анімації у WPF: Storyboard та Easing Functions","\u002Fcsharp\u002Fdesktop-ui\u002Fanimations-transitions","01.csharp\u002F12.desktop-ui\u002F39.animations-transitions",{"title":1615,"path":1616,"stem":1617},"Анімації в Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F39a.avalonia-animations","01.csharp\u002F12.desktop-ui\u002F39a.avalonia-animations",{"title":1619,"path":1620,"stem":1621},"2D Графіка та Мультимедіа у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fmedia-graphics","01.csharp\u002F12.desktop-ui\u002F40.media-graphics",{"title":1623,"path":1624,"stem":1625},"Dependency Injection у WPF та Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Fdi-integration","01.csharp\u002F12.desktop-ui\u002F41.di-integration",{"title":1627,"path":1628,"stem":1629},"SQLite та EF Core у десктопних додатках","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part1","01.csharp\u002F12.desktop-ui\u002F42.data-persistence-part1",{"title":1631,"path":1632,"stem":1633},"Repository Pattern та Unit of Work","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part2","01.csharp\u002F12.desktop-ui\u002F43.data-persistence-part2",{"title":1635,"path":1636,"stem":1637},"Тестування ViewModels","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-testing","01.csharp\u002F12.desktop-ui\u002F44.viewmodel-testing",{"title":1639,"path":1640,"stem":1641},"Avalonia Headless Testing — тестування UI без вікон","\u002Fcsharp\u002Fdesktop-ui\u002F44a.avalonia-headless-testing","01.csharp\u002F12.desktop-ui\u002F44a.avalonia-headless-testing",{"title":1643,"path":1644,"stem":1645},"Кросплатформна розробка з Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-cross-platform","01.csharp\u002F12.desktop-ui\u002F45.avalonia-cross-platform",{"title":1647,"path":1648,"stem":1649},"Пакування та розгортання Avalonia додатків","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F46.avalonia-packaging-deployment",{"title":1651,"path":1652,"stem":1653},"Розгортання WPF застосунків","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F47.wpf-packaging-deployment",{"title":1655,"icon":658,"path":1656,"stem":1657,"children":1658,"page":59},"Network Programming","\u002Fcsharp\u002Fnetwork-programming","01.csharp\u002F13.network-programming",[1659,1663,1667,1671,1675,1679,1683,1687,1691,1695,1699],{"title":1660,"path":1661,"stem":1662},"Основи комп'ютерних мереж","\u002Fcsharp\u002Fnetwork-programming\u002Ffoundations","01.csharp\u002F13.network-programming\u002F01.foundations",{"title":1664,"path":1665,"stem":1666},"Модель OSI та стек TCP\u002FIP","\u002Fcsharp\u002Fnetwork-programming\u002Fosi-model","01.csharp\u002F13.network-programming\u002F02.osi-model",{"title":1668,"path":1669,"stem":1670},"IP-протокол та адресація","\u002Fcsharp\u002Fnetwork-programming\u002Fip-addressing","01.csharp\u002F13.network-programming\u002F03.ip-addressing",{"title":1672,"path":1673,"stem":1674},"UDP — протокол без з'єднання","\u002Fcsharp\u002Fnetwork-programming\u002Fudp","01.csharp\u002F13.network-programming\u002F05.udp",{"title":1676,"path":1677,"stem":1678},"UDP Broadcast та Multicast","\u002Fcsharp\u002Fnetwork-programming\u002Fudp-broadcast-multicast","01.csharp\u002F13.network-programming\u002F06.udp-broadcast-multicast",{"title":1680,"path":1681,"stem":1682},"HTTP — протокол вебу","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-fundamentals","01.csharp\u002F13.network-programming\u002F07.http-fundamentals",{"title":1684,"path":1685,"stem":1686},"HttpListener — вбудований HTTP-сервер .NET","\u002Fcsharp\u002Fnetwork-programming\u002F07a.http-listener","01.csharp\u002F13.network-programming\u002F07a.http-listener",{"title":1688,"path":1689,"stem":1690},"HTTP Advanced — cookies, аутентифікація та HTTPS","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-advanced","01.csharp\u002F13.network-programming\u002F08.http-advanced",{"title":1692,"path":1693,"stem":1694},"SMTP та протоколи електронної пошти","\u002Fcsharp\u002Fnetwork-programming\u002Fsmtp","01.csharp\u002F13.network-programming\u002F09.smtp",{"title":1696,"path":1697,"stem":1698},"WebSocket — повнодуплексний протокол реального часу","\u002Fcsharp\u002Fnetwork-programming\u002Fwebsockets","01.csharp\u002F13.network-programming\u002F10.websockets",{"title":1700,"path":1701,"stem":1702},"TLS\u002FSSL — криптографічний захист мережевих з'єднань","\u002Fcsharp\u002Fnetwork-programming\u002Ftls-ssl","01.csharp\u002F13.network-programming\u002F11.tls-ssl",{"title":1704,"path":1705,"stem":1706},"C# & .NET: The Ultimate Roadmap","\u002Fcsharp\u002Froadmap","01.csharp\u002Froadmap",{"title":1708,"icon":1709,"path":1710,"stem":1711,"children":1712,"page":59},"C++","i-devicon-cplusplus","\u002Fcpp","02.cpp",[1713,1717,1721,1725,1729,1733,1737,1741,1745,1748,1752,1756,1760,1764,1768,1772,1776,1780,1784,1788,1792,1796,1800,1804,1808,1812,1816,1820,1824,1828,1832,1836,1840,1844,1848,1852,1856,1860,1864,1868,1872,1876,1880,1884,1888,1892,1896,1900,1904,1908,1912,1916,1920,1924,1928,1932,1936,1940,1944,1948,1952,1956,1960,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004,2008,2012,2016,2020,2024,2028,2032,2036],{"title":1714,"path":1715,"stem":1716},"Вступ у програмування та алгоритми","\u002Fcpp\u002Fintro-algorithms","02.cpp\u002F01.intro-algorithms",{"title":1718,"path":1719,"stem":1720},"Code Style: угоди про оформлення коду","\u002Fcpp\u002Fcode-style","02.cpp\u002F02.code-style",{"title":1722,"path":1723,"stem":1724},"Середовище розробки та перший проєкт","\u002Fcpp\u002Fide-setup","02.cpp\u002F03.ide-setup",{"title":1726,"path":1727,"stem":1728},"Вивід даних на екран","\u002Fcpp\u002Fdata-output","02.cpp\u002F04.data-output",{"title":1730,"path":1731,"stem":1732},"Типи даних, змінні та константи","\u002Fcpp\u002Fdata-types-variables","02.cpp\u002F05.data-types-variables",{"title":1734,"path":1735,"stem":1736},"Ввід даних з клавіатури","\u002Fcpp\u002Fdata-input","02.cpp\u002F06.data-input",{"title":1738,"path":1739,"stem":1740},"Оператори, перетворення типів та логічні операції","\u002Fcpp\u002Foperators-type-conversion","02.cpp\u002F07.operators-type-conversion",{"title":1742,"path":1743,"stem":1744},"Цикли","\u002Fcpp\u002Floops","02.cpp\u002F08.loops",{"title":32,"path":1746,"stem":1747},"\u002Fcpp\u002Farrays","02.cpp\u002F09.arrays",{"title":1749,"path":1750,"stem":1751},"Алгоритми сортування та аналіз складності","\u002Fcpp\u002Fsorting","02.cpp\u002F10.sorting",{"title":1753,"path":1754,"stem":1755},"Алгоритми пошуку","\u002Fcpp\u002Fsearching","02.cpp\u002F11.searching",{"title":1757,"path":1758,"stem":1759},"Функції: основи","\u002Fcpp\u002Ffunctions-basics","02.cpp\u002F12.functions-basics",{"title":1761,"path":1762,"stem":1763},"Функції: прототипи, область видимості та додаткові можливості","\u002Fcpp\u002Ffunctions-scope","02.cpp\u002F13.functions-scope",{"title":1765,"path":1766,"stem":1767},"Функції: перевантаження та шаблони","\u002Fcpp\u002Ffunctions-overloading-templates","02.cpp\u002F14.functions-overloading-templates",{"title":1769,"path":1770,"stem":1771},"Вказівники: основи","\u002Fcpp\u002Fpointers-basics","02.cpp\u002F15.pointers-basics",{"title":1773,"path":1774,"stem":1775},"Посилання (References)","\u002Fcpp\u002Freferences","02.cpp\u002F16.references",{"title":1777,"path":1778,"stem":1779},"Вказівники, const і масиви","\u002Fcpp\u002Fpointers-const-arrays","02.cpp\u002F17.pointers-const-arrays",{"title":1781,"path":1782,"stem":1783},"Адресна арифметика","\u002Fcpp\u002Fpointer-arithmetic","02.cpp\u002F18.pointer-arithmetic",{"title":1785,"path":1786,"stem":1787},"Динамічна пам'ять","\u002Fcpp\u002Fdynamic-memory","02.cpp\u002F19.dynamic-memory",{"title":1789,"path":1790,"stem":1791},"Вказівники типу void","\u002Fcpp\u002Fvoid-pointers","02.cpp\u002F20.void-pointers",{"title":1793,"path":1794,"stem":1795},"Вказівники на вказівники","\u002Fcpp\u002Fpointers-to-pointers","02.cpp\u002F21.pointers-to-pointers",{"title":1797,"path":1798,"stem":1799},"Оператор доступу до членів через вказівник (->)","\u002Fcpp\u002Fmember-access-operator","02.cpp\u002F22.member-access-operator",{"title":1801,"path":1802,"stem":1803},"Цикл for-each (Range-based for)","\u002Fcpp\u002Fforeach-loop","02.cpp\u002F23.foreach-loop",{"title":1805,"path":1806,"stem":1807},"Вказівники на функції","\u002Fcpp\u002Ffunction-pointers","02.cpp\u002F24.function-pointers",{"title":1809,"path":1810,"stem":1811},"Лямбда-вирази","\u002Fcpp\u002Flambdas","02.cpp\u002F25.lambdas",{"title":1813,"path":1814,"stem":1815},"Лямбда-захоплення","\u002Fcpp\u002Flambda-captures","02.cpp\u002F26.lambda-captures",{"title":1817,"path":1818,"stem":1819},"Еліпсис","\u002Fcpp\u002Fellipsis","02.cpp\u002F27.ellipsis",{"title":1821,"path":1822,"stem":1823},"Безпечні альтернативи еліпсису","\u002Fcpp\u002F27a.ellipsis","02.cpp\u002F27a.ellipsis",{"title":1825,"path":1826,"stem":1827},"Аргументи командного рядка","\u002Fcpp\u002Fcommand-line-arguments","02.cpp\u002F28.command-line-arguments",{"title":1829,"path":1830,"stem":1831},"Перерахування (enum)","\u002Fcpp\u002Fenum","02.cpp\u002F29.enum",{"title":1833,"path":1834,"stem":1835},"Класи-перерахування (enum class)","\u002Fcpp\u002Fenum-class","02.cpp\u002F30.enum-class",{"title":1837,"path":1838,"stem":1839},"Псевдоніми типів (typedef і using)","\u002Fcpp\u002Ftype-aliases","02.cpp\u002F31.type-aliases",{"title":1841,"path":1842,"stem":1843},"Системи числення та двійкова арифметика","\u002Fcpp\u002Fnumber-systems","02.cpp\u002F32.number-systems",{"title":1845,"path":1846,"stem":1847},"Структури (struct): агрегування даних","\u002Fcpp\u002Fstruct","02.cpp\u002F33.struct",{"title":1849,"path":1850,"stem":1851},"Структури у функціях","\u002Fcpp\u002Fstruct-functions","02.cpp\u002F34.struct-functions",{"title":1853,"path":1854,"stem":1855},"Масиви структур і вкладені структури","\u002Fcpp\u002Fstruct-arrays","02.cpp\u002F35.struct-arrays",{"title":1857,"path":1858,"stem":1859},"Патерни struct та межі застосування","\u002Fcpp\u002Fstruct-patterns","02.cpp\u002F36.struct-patterns",{"title":1861,"path":1862,"stem":1863},"Символи та таблиця ASCII","\u002Fcpp\u002Fascii-characters","02.cpp\u002F37.ascii-characters",{"title":1865,"path":1866,"stem":1867},"Unicode та кодування UTF","\u002Fcpp\u002Funicode-utf","02.cpp\u002F38.unicode-utf",{"title":1869,"path":1870,"stem":1871},"C-style рядки","\u002Fcpp\u002Fc-strings","02.cpp\u002F39.c-strings",{"title":1873,"path":1874,"stem":1875},"Вступ до std::string","\u002Fcpp\u002Fstd-string-intro","02.cpp\u002F40.std-string-intro",{"title":1877,"path":1878,"stem":1879},"Довжина, ємність та доступ до символів std::string","\u002Fcpp\u002Fstd-string-capacity-access","02.cpp\u002F41.std-string-capacity-access",{"title":1881,"path":1882,"stem":1883},"Модифікація std::string: присвоювання, додавання, вставка, видалення та заміна","\u002Fcpp\u002Fstd-string-modification","02.cpp\u002F42.std-string-modification",{"title":1885,"path":1886,"stem":1887},"Пошук у std::string: find, npos та практичні патерни","\u002Fcpp\u002Fstd-string-search","02.cpp\u002F43.std-string-search",{"title":1889,"path":1890,"stem":1891},"std::string_view: невласницький погляд на рядок без копіювання","\u002Fcpp\u002Fstd-string-view","02.cpp\u002F44.std-string-view",{"title":1893,"path":1894,"stem":1895},"Об'єднання (union): один блок пам'яті, кілька інтерпретацій","\u002Fcpp\u002Funion","02.cpp\u002F45.union",{"title":1897,"path":1898,"stem":1899},"Організація коду: файли, препроцесор, простори імен","\u002Fcpp\u002Fmultifile-programs","02.cpp\u002F46.multifile-programs",{"title":1901,"path":1902,"stem":1903},"Робота з файлами: C-стиль (stdio.h)","\u002Fcpp\u002Fc-style-files","02.cpp\u002F47.c-style-files",{"title":1905,"path":1906,"stem":1907},"Робота з файлами: C++-стиль (fstream)","\u002Fcpp\u002Fcpp-style-files","02.cpp\u002F48.cpp-style-files",{"title":1909,"path":1910,"stem":1911},"Введення в ООП: від процедур до об'єктів","\u002Fcpp\u002Foop-intro","02.cpp\u002F49.oop-intro",{"title":1913,"path":1914,"stem":1915},"Класи, об'єкти та методи","\u002Fcpp\u002Fclasses-objects-methods","02.cpp\u002F50.classes-objects-methods",{"title":1917,"path":1918,"stem":1919},"Специфікатори доступу та інкапсуляція","\u002Fcpp\u002Faccess-specifiers-encapsulation","02.cpp\u002F51.access-specifiers-encapsulation",{"title":1921,"path":1922,"stem":1923},"Конструктори: гарантована ініціалізація об'єктів","\u002Fcpp\u002Fconstructors","02.cpp\u002F52.constructors",{"title":1925,"path":1926,"stem":1927},"Списки ініціалізації та делегуючі конструктори","\u002Fcpp\u002Finit-lists-delegating","02.cpp\u002F53.init-lists-delegating",{"title":1929,"path":1930,"stem":1931},"Деструктори та ідіома RAII","\u002Fcpp\u002Fdestructors-raii","02.cpp\u002F54.destructors-raii",{"title":1933,"path":1934,"stem":1935},"Прихований покажчик this","\u002Fcpp\u002Fthis-pointer","02.cpp\u002F55.this-pointer",{"title":1937,"path":1938,"stem":1939},"Розподіл класу на заголовковий файл та файл реалізації","\u002Fcpp\u002Fclass-header-source","02.cpp\u002F56.class-header-source",{"title":1941,"path":1942,"stem":1943},"Класи та const","\u002Fcpp\u002Fconst-classes","02.cpp\u002F57.const-classes",{"title":1945,"path":1946,"stem":1947},"Статичні члени класу","\u002Fcpp\u002Fstatic-members","02.cpp\u002F58.static-members",{"title":1949,"path":1950,"stem":1951},"Конструктор копіювання та запобігання копіюванню","\u002Fcpp\u002Fcopy-constructor","02.cpp\u002F59.copy-constructor",{"title":1953,"path":1954,"stem":1955},"Дружні функції та класи","\u002Fcpp\u002Ffriend-functions-classes","02.cpp\u002F60.friend-functions-classes",{"title":1957,"path":1958,"stem":1959},"Анонімні об'єкти та вкладені типи","\u002Fcpp\u002Fanonymous-objects-nested-types","02.cpp\u002F61.anonymous-objects-nested-types",{"title":1961,"path":1962,"stem":1963},"Вимірювання часу виконання: RAII-таймер","\u002Fcpp\u002Ftiming-raii-timer","02.cpp\u002F62.timing-raii-timer",{"title":1965,"path":1966,"stem":1967},"Перевантаження операторів: основи та арифметика","\u002Fcpp\u002Foperator-overloading-basics","02.cpp\u002F63.operator-overloading-basics",{"title":1969,"path":1970,"stem":1971},"Перевантаження операторів: методи класу та спеціальні оператори","\u002Fcpp\u002Foperator-overloading-methods","02.cpp\u002F64.operator-overloading-methods",{"title":1973,"path":1974,"stem":1975},"Приведення типів, explicit та delete","\u002Fcpp\u002Ftypecast-explicit-delete","02.cpp\u002F65.typecast-explicit-delete",{"title":1977,"path":1978,"stem":1979},"Глибоке копіювання та оператор присвоювання","\u002Fcpp\u002Fdeep-copy-assignment","02.cpp\u002F66.deep-copy-assignment",{"title":1981,"path":1982,"stem":1983},"Зв'язки між об'єктами: композиція та агрегація","\u002Fcpp\u002Fcomposition-aggregation","02.cpp\u002F67.composition-aggregation",{"title":1985,"path":1986,"stem":1987},"Асоціація та залежність між об","\u002Fcpp\u002Fassociation-dependency","02.cpp\u002F68.association-dependency",{"title":1989,"path":1990,"stem":1991},"Контейнерні класи та `std::initializer_list`","\u002Fcpp\u002Fcontainer-classes-initializer-list","02.cpp\u002F69.container-classes-initializer-list",{"title":1993,"path":1994,"stem":1995},"Конструктори, деструктори та порядок ініціалізації в ієрархіях","\u002Fcpp\u002Finheritance-constructors-destructors","02.cpp\u002F71.inheritance-constructors-destructors",{"title":1997,"path":1998,"stem":1999},"Специфікатор `protected` та види наслідування","\u002Fcpp\u002Finheritance-access-specifiers","02.cpp\u002F72.inheritance-access-specifiers",{"title":2001,"path":2002,"stem":2003},"Перевизначення методів та приховування імен","\u002Fcpp\u002Fmethod-overriding-hiding","02.cpp\u002F73.method-overriding-hiding",{"title":2005,"path":2006,"stem":2007},"Множинне наслідування та проблема ромба","\u002Fcpp\u002Fmultiple-inheritance-diamond","02.cpp\u002F74.multiple-inheritance-diamond",{"title":2009,"path":2010,"stem":2011},"Вказівники на базовий клас та віртуальні функції","\u002Fcpp\u002Fvirtual-functions-polymorphism","02.cpp\u002F75.virtual-functions-polymorphism",{"title":2013,"path":2014,"stem":2015},"Специфікатори override, final та віртуальні деструктори","\u002Fcpp\u002Foverride-final-virtual-destructors","02.cpp\u002F76.override-final-virtual-destructors",{"title":2017,"path":2018,"stem":2019},"Внутрішні механізми поліморфізму: vtable, vptr та зв'язування","\u002Fcpp\u002Fvirtual-table-binding","02.cpp\u002F77.virtual-table-binding",{"title":2021,"path":2022,"stem":2023},"Абстрактні класи та чисті віртуальні функції","\u002Fcpp\u002Fabstract-classes-interfaces","02.cpp\u002F78.abstract-classes-interfaces",{"title":2025,"path":2026,"stem":2027},"Зрізка об'єктів, віртуальне наслідування та поліморфний вивід","\u002Fcpp\u002Fslicing-virtual-base-io","02.cpp\u002F79.slicing-virtual-base-io",{"title":2029,"path":2030,"stem":2031},"Динамічне приведення типів (`dynamic_cast`) та RTTI","\u002Fcpp\u002Fdynamic-cast-rtti","02.cpp\u002F80.dynamic-cast-rtti",{"title":2033,"path":2034,"stem":2035},"Шаблони функцій: узагальнене програмування","\u002Fcpp\u002Ffunction-templates","02.cpp\u002F81.function-templates",{"title":2037,"path":2038,"stem":2039},"Шаблони класів та NTTP-параметри","\u002Fcpp\u002Fclass-templates-nttp","02.cpp\u002F82.class-templates-nttp",{"title":2041,"icon":2042,"path":2043,"stem":2044,"children":2045,"page":59},"JavaScript","i-devicon-javascript","\u002Fjavascript","03.javascript",[2046,2072,2126,2148,2452,2490,2508],{"title":2047,"icon":2048,"path":2049,"stem":2050,"children":2051,"page":59},"Events","i-lucide-mouse-pointer-click","\u002Fjavascript\u002Fevents","03.javascript\u002F01.events",[2052,2056,2060,2064,2068],{"title":2053,"path":2054,"stem":2055},"Вступ до подій браузера","\u002Fjavascript\u002Fevents\u002Fintro","03.javascript\u002F01.events\u002F01.intro",{"title":2057,"path":2058,"stem":2059},"Бульбашковий механізм (Bubbling) та занурення (Capturing)","\u002Fjavascript\u002Fevents\u002Fbubbling-capturing","03.javascript\u002F01.events\u002F02.bubbling-capturing",{"title":2061,"path":2062,"stem":2063},"Делегування подій (Event Delegation)","\u002Fjavascript\u002Fevents\u002Fdelegate-events","03.javascript\u002F01.events\u002F03.delegate-events",{"title":2065,"path":2066,"stem":2067},"Типові дії браузера та preventDefault()","\u002Fjavascript\u002Fevents\u002Fprevent-default","03.javascript\u002F01.events\u002F04.prevent-default",{"title":2069,"path":2070,"stem":2071},"Запуск користувацьких подій (Custom Events)","\u002Fjavascript\u002Fevents\u002Fcustom-events","03.javascript\u002F01.events\u002F05.custom-events",{"title":2073,"icon":2074,"path":2075,"stem":2076,"children":2077,"page":59},"Network","i-lucide-globe","\u002Fjavascript\u002Fnetwork","03.javascript\u002F02.network",[2078,2082,2086,2090,2094,2098,2102,2106,2110,2114,2118,2122],{"title":2079,"path":2080,"stem":2081},"Fetch API - Сучасний підхід до HTTP-запитів","\u002Fjavascript\u002Fnetwork\u002F01-fetch-api","03.javascript\u002F02.network\u002F01-fetch-api",{"title":2083,"path":2084,"stem":2085},"FormData - Робота з формами та файлами","\u002Fjavascript\u002Fnetwork\u002F02-formdata","03.javascript\u002F02.network\u002F02-formdata",{"title":2087,"path":2088,"stem":2089},"Відстеження прогресу завантаження","\u002Fjavascript\u002Fnetwork\u002F03-download-progress","03.javascript\u002F02.network\u002F03-download-progress",{"title":2091,"path":2092,"stem":2093},"Переривання fetch-запитів","\u002Fjavascript\u002Fnetwork\u002F04-abort-requests","03.javascript\u002F02.network\u002F04-abort-requests",{"title":2095,"path":2096,"stem":2097},"CORS - Запити між різними джерелами","\u002Fjavascript\u002Fnetwork\u002F05-cors","03.javascript\u002F02.network\u002F05-cors",{"title":2099,"path":2100,"stem":2101},"Fetch API - Повний довідник опцій","\u002Fjavascript\u002Fnetwork\u002F06-fetch-options","03.javascript\u002F02.network\u002F06-fetch-options",{"title":2103,"path":2104,"stem":2105},"URL Objects - Робота з посиланнями","\u002Fjavascript\u002Fnetwork\u002F07-url-objects","03.javascript\u002F02.network\u002F07-url-objects",{"title":2107,"path":2108,"stem":2109},"XMLHttpRequest - AJAX та низькорівневі запити","\u002Fjavascript\u002Fnetwork\u002F08-xmlhttprequest","03.javascript\u002F02.network\u002F08-xmlhttprequest",{"title":2111,"path":2112,"stem":2113},"Відновлюване завантаження файлів","\u002Fjavascript\u002Fnetwork\u002F09-resumable-upload","03.javascript\u002F02.network\u002F09-resumable-upload",{"title":2115,"path":2116,"stem":2117},"Cookies, document.cookie та світ після \"Cookiepocalypse\"","\u002Fjavascript\u002Fnetwork\u002F10-cookies","03.javascript\u002F02.network\u002F10-cookies",{"title":2119,"path":2120,"stem":2121},"js-cookie: Керування Cookies без Болю","\u002Fjavascript\u002Fnetwork\u002F11-js-cookie","03.javascript\u002F02.network\u002F11-js-cookie",{"title":2123,"path":2124,"stem":2125},"Axios: Потужний HTTP-клієнт для JavaScript","\u002Fjavascript\u002Fnetwork\u002F12-axios","03.javascript\u002F02.network\u002F12-axios",{"title":2127,"icon":2128,"path":2129,"stem":2130,"children":2131,"page":59},"Bom","i-lucide-monitor","\u002Fjavascript\u002Fbom","03.javascript\u002F03.bom",[2132,2136,2140,2144],{"title":2133,"path":2134,"stem":2135},"LocalStorage, SessionStorage та patterns збереження даних","\u002Fjavascript\u002Fbom\u002F01-localstorage","03.javascript\u002F03.bom\u002F01-localstorage",{"title":2137,"path":2138,"stem":2139},"Location Object - Керування адресою сторінки","\u002Fjavascript\u002Fbom\u002F02-location-object","03.javascript\u002F03.bom\u002F02-location-object",{"title":2141,"path":2142,"stem":2143},"History API - Керування історією браузера","\u002Fjavascript\u002Fbom\u002F03-history-api","03.javascript\u002F03.bom\u002F03-history-api",{"title":2145,"path":2146,"stem":2147},"Navigator Object - Ідентифікація та Можливості Пристрою","\u002Fjavascript\u002Fbom\u002F04-navigator-object","03.javascript\u002F03.bom\u002F04-navigator-object",{"title":2149,"icon":2150,"path":2151,"stem":2152,"children":2153},"React","i-devicon-react","\u002Fjavascript\u002Freact","03.javascript\u002F04.react\u002Findex",[2154,2155,2159,2163,2167,2171,2234,2269,2421],{"title":2149,"path":2151,"stem":2152},{"title":2156,"path":2157,"stem":2158},"Робота з Формами в React","\u002Fjavascript\u002Freact\u002Freact-forms","03.javascript\u002F04.react\u002F01.react-forms",{"title":2160,"path":2161,"stem":2162},"React Hook Form: Професійна Робота з Формами","\u002Fjavascript\u002Freact\u002Freact-hook-form","03.javascript\u002F04.react\u002F02.react-hook-form",{"title":2164,"path":2165,"stem":2166},"React Hook Form: Глибоке Розуміння Архітектури та Оптимізації","\u002Fjavascript\u002Freact\u002Freact-hook-form-new","03.javascript\u002F04.react\u002F02.react-hook-form-new",{"title":2168,"path":2169,"stem":2170},"Axios та React: Професійна Архітектура Запитів","\u002Fjavascript\u002Freact\u002Fdata-fetching-axios","03.javascript\u002F04.react\u002F03.data-fetching-axios",{"title":2172,"icon":132,"path":2173,"stem":2174,"children":2175},"Tanstack Query","\u002Fjavascript\u002Freact\u002Ftanstack-query","03.javascript\u002F04.react\u002F04.tanstack-query\u002Findex",[2176,2178,2182,2186,2190,2194,2198,2202,2206,2210,2214,2218,2222,2226,2230],{"title":2177,"path":2173,"stem":2174},"TanStack Query: Майстерність Керування Станом Сервера",{"title":2179,"path":2180,"stem":2181},"Парадигма Server State: Чому useEffect недостатньо","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-state-paradigm","03.javascript\u002F04.react\u002F04.tanstack-query\u002F01.server-state-paradigm",{"title":2183,"path":2184,"stem":2185},"Встановлення та Налаштування: Фундамент","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Finstallation-and-devtools","03.javascript\u002F04.react\u002F04.tanstack-query\u002F02.installation-and-devtools",{"title":2187,"path":2188,"stem":2189},"Основи Запитів та Магія Ключів","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fquery-basics-and-keys","03.javascript\u002F04.react\u002F04.tanstack-query\u002F03.query-basics-and-keys",{"title":2191,"path":2192,"stem":2193},"Синхронізація Даних: Життєвий Цикл Запиту","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fdata-synchronization","03.javascript\u002F04.react\u002F04.tanstack-query\u002F04.data-synchronization",{"title":2195,"path":2196,"stem":2197},"Мутації та Інвалідація: Зміна Даних","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fmutations-and-invalidation","03.javascript\u002F04.react\u002F04.tanstack-query\u002F05.mutations-and-invalidation",{"title":2199,"path":2200,"stem":2201},"Оптимістичні Оновлення: Швидше за Світло","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Foptimistic-updates","03.javascript\u002F04.react\u002F04.tanstack-query\u002F06.optimistic-updates",{"title":2203,"path":2204,"stem":2205},"Пагінація та Infinite Scroll","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fpagination-and-load-more","03.javascript\u002F04.react\u002F04.tanstack-query\u002F07.pagination-and-load-more",{"title":2207,"path":2208,"stem":2209},"Просунуті Патерни та Оптимізація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F04.tanstack-query\u002F08.advanced-patterns",{"title":2211,"path":2212,"stem":2213},"Архітектура та Best Practices","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Farchitecture-and-best-practices","03.javascript\u002F04.react\u002F04.tanstack-query\u002F09.architecture-and-best-practices",{"title":2215,"path":2216,"stem":2217},"Server-Side Rendering (SSR) та Гідратація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-side-rendering","03.javascript\u002F04.react\u002F04.tanstack-query\u002F10.server-side-rendering",{"title":2219,"path":2220,"stem":2221},"Стратегії Тестування","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Ftesting-strategies","03.javascript\u002F04.react\u002F04.tanstack-query\u002F11.testing-strategies",{"title":2223,"path":2224,"stem":2225},"Аутентифікація та Обробка Помилок","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fauthentication-and-errors","03.javascript\u002F04.react\u002F04.tanstack-query\u002F12.authentication-and-errors",{"title":2227,"path":2228,"stem":2229},"React Suspense та Майбутнє","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Freact-suspense","03.javascript\u002F04.react\u002F04.tanstack-query\u002F13.react-suspense",{"title":2231,"path":2232,"stem":2233},"Глибоке Занурення в Продуктивність","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fperformance-deep-dive","03.javascript\u002F04.react\u002F04.tanstack-query\u002F14.performance-deep-dive",{"title":2235,"icon":2150,"path":2236,"stem":2237,"children":2238},"React Router","\u002Fjavascript\u002Freact\u002Freact-router","03.javascript\u002F04.react\u002F05.react-router\u002Findex",[2239,2241,2245,2249,2253,2257,2261,2265],{"title":2240,"path":2236,"stem":2237},"React Router: Навігаційна система сучасного вебу",{"title":2242,"path":2243,"stem":2244},"Налаштування та Базовий Роутинг","\u002Fjavascript\u002Freact\u002Freact-router\u002Fsetup-and-basic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F01.setup-and-basic-routing",{"title":2246,"path":2247,"stem":2248},"Динамічна Навігація","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnavigation-and-links","03.javascript\u002F04.react\u002F05.react-router\u002F02.navigation-and-links",{"title":2250,"path":2251,"stem":2252},"Вкладені Маршрути та Макети","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnested-routes-and-layouts","03.javascript\u002F04.react\u002F05.react-router\u002F03.nested-routes-and-layouts",{"title":2254,"path":2255,"stem":2256},"Динамічні Маршрути та Параметри","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdynamic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F04.dynamic-routing",{"title":2258,"path":2259,"stem":2260},"Data APIs: Loaders та Actions","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdata-loading","03.javascript\u002F04.react\u002F05.react-router\u002F05.data-loading",{"title":2262,"path":2263,"stem":2264},"Просунуті Патерни","\u002Fjavascript\u002Freact\u002Freact-router\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F05.react-router\u002F06.advanced-patterns",{"title":2266,"path":2267,"stem":2268},"Legacy Routing: Компонентний підхід","\u002Fjavascript\u002Freact\u002Freact-router\u002Flegacy-routing","03.javascript\u002F04.react\u002F05.react-router\u002F07.legacy-routing",{"title":2270,"icon":132,"path":2271,"stem":2272,"children":2273},"Redux","\u002Fjavascript\u002Freact\u002Fredux","03.javascript\u002F04.react\u002F06.redux\u002Findex",[2274,2276,2292,2321,2330,2351,2367,2396],{"title":2275,"path":2271,"stem":2272},"Redux: Еволюція управління станом",{"title":14,"icon":15,"path":2277,"stem":2278,"children":2279,"page":59},"\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals",[2280,2284,2288],{"title":2281,"path":2282,"stem":2283},"Вступ до State Management","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fintro-state-management","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F01.intro-state-management",{"title":2285,"path":2286,"stem":2287},"Філософія Redux та Три Принципи","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fredux-philosophy","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F02.redux-philosophy",{"title":2289,"path":2290,"stem":2291},"Чисті функції та Іммутабельність","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fpure-functions-immutability","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F03.pure-functions-immutability",{"title":2293,"icon":132,"path":2294,"stem":2295,"children":2296,"page":59},"Classic Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux",[2297,2301,2305,2309,2313,2317],{"title":2298,"path":2299,"stem":2300},"Створення Store (Classic Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fstore-setup","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F01.store-setup",{"title":2302,"path":2303,"stem":2304},"Actions, Constants та Action Creators","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Factions-constants","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F02.actions-constants",{"title":2306,"path":2307,"stem":2308},"Логіка Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freducers","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F03.reducers",{"title":2310,"path":2311,"stem":2312},"Комбінування Reducers (Root Reducer)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fdata-flow","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F04.data-flow",{"title":2314,"path":2315,"stem":2316},"Підключення до React (React-Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freact-redux-connection","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F05.react-redux-connection",{"title":2318,"path":2319,"stem":2320},"Middleware та Асинхронність (Redux Thunk)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fmiddleware-thunk","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F06.middleware-thunk",{"title":2322,"icon":132,"path":2323,"stem":2324,"children":2325,"page":59},"Transition To Rtk","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk",[2326],{"title":2327,"path":2328,"stem":2329},"Проблеми класичного Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk\u002Fproblems-with-classic","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk\u002F01.problems-with-classic",{"title":2331,"icon":132,"path":2332,"stem":2333,"children":2334,"page":59},"Redux Toolkit","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit",[2335,2339,2343,2347],{"title":2336,"path":2337,"stem":2338},"Налаштування Store з configureStore","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fconfigure-store","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F01.configure-store",{"title":2340,"path":2341,"stem":2342},"createSlice: Революція в Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fcreate-slice","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F02.create-slice",{"title":2344,"path":2345,"stem":2346},"Асинхронність з createAsyncThunk","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fasync-thunks","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F03.async-thunks",{"title":2348,"path":2349,"stem":2350},"04. Entity Adapter: Керування нормалізованим станом","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fentity-adapter","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F04.entity-adapter",{"title":2352,"icon":92,"path":2353,"stem":2354,"children":2355,"page":59},"Advanced","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced",[2356,2360,2364],{"title":2357,"path":2358,"stem":2359},"Мемоізація та Селектори: Повний Гайд по Reselect","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Fselectors-reselect","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F01.selectors-reselect",{"title":2361,"path":2362,"stem":2363},"RTK Query: Архітектура Серверного Кешу","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Frtk-query-intro","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F02.rtk-query-intro",{"title":2211,"path":2365,"stem":2366},"\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Farchitecture-best-practices","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F03.architecture-best-practices",{"title":2368,"icon":132,"path":2369,"stem":2370,"children":2371,"page":59},"Project Kanban","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban",[2372,2376,2380,2384,2388,2392],{"title":2373,"path":2374,"stem":2375},"Проєкт: Kanban Board (Trello Clone)","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fproject-overview","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F01.project-overview",{"title":2377,"path":2378,"stem":2379},"Налаштування та Типізація","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fsetup-and-types","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F02.setup-and-types",{"title":2381,"path":2382,"stem":2383},"Board Slice: Серце Дошки","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fboard-slice","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F03.board-slice",{"title":2385,"path":2386,"stem":2387},"Логіка Drag & Drop","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fdrag-and-drop-logic","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F04.drag-and-drop-logic",{"title":2389,"path":2390,"stem":2391},"Інтеграція з RTK Query","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Frtk-query-integration","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F05.rtk-query-integration",{"title":2393,"path":2394,"stem":2395},"Optimistic Updates","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Foptimistic-updates","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F06.optimistic-updates",{"title":2397,"icon":132,"path":2398,"stem":2399,"children":2400,"page":59},"Testing","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting","03.javascript\u002F04.react\u002F06.redux\u002F07.testing",[2401,2405,2409,2413,2417],{"title":2402,"path":2403,"stem":2404},"Тестування Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Fintro-testing","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F01.intro-testing",{"title":2406,"path":2407,"stem":2408},"Тестування Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-reducers","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F02.testing-reducers",{"title":2410,"path":2411,"stem":2412},"Тестування Селекторів","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-selectors","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F03.testing-selectors",{"title":2414,"path":2415,"stem":2416},"Тестування Компонентів (Integration)","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-components","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F04.testing-components",{"title":2418,"path":2419,"stem":2420},"Тестування Async Thunks","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-thunks","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F05.testing-thunks",{"title":2422,"icon":132,"path":2423,"stem":2424,"children":2425},"Ui Libraries","\u002Fjavascript\u002Freact\u002Fui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002Findex",[2426,2428,2432,2436,2440,2444,2448],{"title":2427,"path":2423,"stem":2424},"UI Бібліотеки в React",{"title":2429,"path":2430,"stem":2431},"Вступ до UI Бібліотек: Навіщо Винаходити Велосипед Двічі?","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fintroduction-to-ui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002F01.introduction-to-ui-libraries",{"title":2433,"path":2434,"stem":2435},"Філософія shadcn\u002Fui: \"Not a Component Library\"","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-philosophy","03.javascript\u002F04.react\u002F07.ui-libraries\u002F02.shadcn-philosophy",{"title":2437,"path":2438,"stem":2439},"Установка та Налаштування shadcn\u002Fui","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-installation","03.javascript\u002F04.react\u002F07.ui-libraries\u002F03.shadcn-installation",{"title":2441,"path":2442,"stem":2443},"Базові Компоненти shadcn\u002Fui: Фундамент Інтерфейсу","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-basics","03.javascript\u002F04.react\u002F07.ui-libraries\u002F04.shadcn-components-basics",{"title":2445,"path":2446,"stem":2447},"Компоненти Форм: Побудова Інтерактивних Form","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-forms","03.javascript\u002F04.react\u002F07.ui-libraries\u002F05.shadcn-components-forms",{"title":2449,"path":2450,"stem":2451},"Складні Компоненти: Dialog, Dropdown, Table та Command","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-advanced","03.javascript\u002F04.react\u002F07.ui-libraries\u002F06.shadcn-components-advanced",{"title":2453,"icon":2454,"path":2455,"stem":2456,"children":2457,"page":59},"TypeScript","i-devicon-typescript","\u002Fjavascript\u002Ftypescript","03.javascript\u002F05.typescript",[2458,2462,2466,2470,2474,2478,2482,2486],{"title":2459,"path":2460,"stem":2461},"TypeScript: Броня для вашого коду","\u002Fjavascript\u002Ftypescript\u002Fintro-and-basic-types","03.javascript\u002F05.typescript\u002F01.intro-and-basic-types",{"title":2463,"path":2464,"stem":2465},"Майстерність Моделювання Даних: Інтерфейси та Просунуті Типи","\u002Fjavascript\u002Ftypescript\u002Finterfaces-and-advanced-types","03.javascript\u002F05.typescript\u002F02.interfaces-and-advanced-types",{"title":2467,"path":2468,"stem":2469},"Алхімія Типів: Generics та Utility Types","\u002Fjavascript\u002Ftypescript\u002Fgenerics-and-utilities","03.javascript\u002F05.typescript\u002F03.generics-and-utilities",{"title":2471,"path":2472,"stem":2473},"Архітектура та Шаблони: Класи в TypeScript","\u002Fjavascript\u002Ftypescript\u002Fclasses-and-oop","03.javascript\u002F05.typescript\u002F04.classes-and-oop",{"title":2475,"path":2476,"stem":2477},"Продакшн та Екосистема: Advanced Config & Workflow","\u002Fjavascript\u002Ftypescript\u002Fadvanced-patterns-and-config","03.javascript\u002F05.typescript\u002F05.advanced-patterns-and-config",{"title":2479,"path":2480,"stem":2481},"TypeScript у світі React","\u002Fjavascript\u002Ftypescript\u002Freact-basics","03.javascript\u002F05.typescript\u002F06.react-basics",{"title":2483,"path":2484,"stem":2485},"React + TypeScript: Продвинуті патерни","\u002Fjavascript\u002Ftypescript\u002Freact-advanced","03.javascript\u002F05.typescript\u002F07.react-advanced",{"title":2487,"path":2488,"stem":2489},"React + TypeScript: Екосистема та бібліотеки","\u002Fjavascript\u002Ftypescript\u002Freact-ecosystem","03.javascript\u002F05.typescript\u002F08.react-ecosystem",{"title":2491,"icon":2492,"path":2493,"stem":2494,"children":2495,"page":59},"Асинхронність","i-lucide-refresh-cw","\u002Fjavascript\u002Fasync-programming","03.javascript\u002F06.async-programming",[2496,2500,2504],{"title":2497,"path":2498,"stem":2499},"Event Loop: серце асинхронності в JavaScript","\u002Fjavascript\u002Fasync-programming\u002Fevent-loop-fundamentals","03.javascript\u002F06.async-programming\u002F01.event-loop-fundamentals",{"title":2501,"path":2502,"stem":2503},"Task Queue та Microtask Queue: пріоритети виконання","\u002Fjavascript\u002Fasync-programming\u002Ftask-queues","03.javascript\u002F06.async-programming\u002F02.task-queues",{"title":2505,"path":2506,"stem":2507},"Асинхронні патерни: від Callbacks до Async\u002FAwait","\u002Fjavascript\u002Fasync-programming\u002Fasync-patterns","03.javascript\u002F06.async-programming\u002F03.async-patterns",{"title":2509,"path":2510,"stem":2511},"Atomic Design","\u002Fjavascript\u002Fatomic-design","03.javascript\u002F2.atomic-design",{"title":2513,"icon":2514,"path":2515,"stem":2516,"children":2517,"page":59},"Java","i-devicon-java","\u002Fjava","04.java",[2518,2521,2524,2528,2532,2536,2540],{"title":162,"path":2519,"stem":2520},"\u002Fjava\u002Fdata-mapper-part1","04.java\u002F01.data-mapper-part1",{"title":166,"path":2522,"stem":2523},"\u002Fjava\u002Fdata-mapper-part2","04.java\u002F02.data-mapper-part2",{"title":2525,"path":2526,"stem":2527},"Service Layer: Організація бізнес-логіки","\u002Fjava\u002Fservice-layer","04.java\u002F03.service-layer",{"title":2529,"path":2530,"stem":2531},"Rich Domain Model та State Pattern","\u002Fjava\u002Frich-domain-model","04.java\u002F04.rich-domain-model",{"title":2533,"path":2534,"stem":2535},"Патерни для складної бізнес-логіки","\u002Fjava\u002Fbusiness-logic-patterns","04.java\u002F05.business-logic-patterns",{"title":2537,"path":2538,"stem":2539},"Обробка помилок та валідація","\u002Fjava\u002Ferror-handling-validation","04.java\u002F06.error-handling-validation",{"title":2541,"path":2542,"stem":2543,"children":2544,"page":59},"Проектування баз даних","\u002Fjava\u002Fpr2","04.java\u002Fpr2",[2545,2549,2553,2557,2561,2565,2569,2573,2577,2581,2585,2589,2593,2597,2601,2605,2609,2613,2617,2621,2625,2629,2633,2637,2641,2645,2649,2653,2657,2661,2665,2669,2673,2677,2681,2685,2689],{"title":2546,"path":2547,"stem":2548},"Концептуальне моделювання: Мистецтво розуміння предметної області","\u002Fjava\u002Fpr2\u002Fconceptual-modeling","04.java\u002Fpr2\u002F01.conceptual-modeling",{"title":2550,"path":2551,"stem":2552},"Логічне моделювання: Від бізнес-ідей до структур даних","\u002Fjava\u002Fpr2\u002Flogical-modeling","04.java\u002Fpr2\u002F02.logical-modeling",{"title":2554,"path":2555,"stem":2556},"Нормалізація: Гігієна даних та боротьба з аномаліями","\u002Fjava\u002Fpr2\u002Fnormalization","04.java\u002Fpr2\u002F03.normalization",{"title":2558,"path":2559,"stem":2560},"Фізична схема: Від абстракції до DDL","\u002Fjava\u002Fpr2\u002Fphysical-schema","04.java\u002Fpr2\u002F04.physical-schema",{"title":2562,"path":2563,"stem":2564},"Архітектурна класифікація таблиць","\u002Fjava\u002Fpr2\u002Ftable-classification","04.java\u002Fpr2\u002F05.table-classification",{"title":2566,"path":2567,"stem":2568},"Database Migrations: Версіонування схеми з Flyway","\u002Fjava\u002Fpr2\u002Fdatabase-migrations","04.java\u002Fpr2\u002F06.database-migrations",{"title":2570,"path":2571,"stem":2572},"А що, якби це була не реляційна БД?","\u002Fjava\u002Fpr2\u002Fbeyond-relational","04.java\u002Fpr2\u002F07.beyond-relational",{"title":2574,"path":2575,"stem":2576},"Object-Relational Impedance Mismatch: Два світи, що не хочуть дружити","\u002Fjava\u002Fpr2\u002Fimpedance-mismatch","04.java\u002Fpr2\u002F09.impedance-mismatch",{"title":2578,"path":2579,"stem":2580},"JDBC: Перший контакт із базою даних","\u002Fjava\u002Fpr2\u002Fjdbc-fundamentals","04.java\u002Fpr2\u002F10.jdbc-fundamentals",{"title":2582,"path":2583,"stem":2584},"Якість коду: Spotless, SpotBugs та SonarQube","\u002Fjava\u002Fpr2\u002F10a.code-quality","04.java\u002Fpr2\u002F10a.code-quality",{"title":2586,"path":2587,"stem":2588},"Connection Pool: Патерн Object Pool для JDBC-з'єднань","\u002Fjava\u002Fpr2\u002Fconnection-pool","04.java\u002Fpr2\u002F11.connection-pool",{"title":2590,"path":2591,"stem":2592},"Row Data Gateway: Об'єкт як обгортка рядка таблиці","\u002Fjava\u002Fpr2\u002Frow-data-gateway","04.java\u002Fpr2\u002F12.row-data-gateway",{"title":2594,"path":2595,"stem":2596},"Table Data Gateway: Фасад таблиці як архітектурний відступ","\u002Fjava\u002Fpr2\u002Ftable-data-gateway","04.java\u002Fpr2\u002F13.table-data-gateway",{"title":2598,"path":2599,"stem":2600},"Repository + Data Mapper: Правильна шарова архітектура з JDBC","\u002Fjava\u002Fpr2\u002Frepository-data-mapper","04.java\u002Fpr2\u002F14.repository-data-mapper",{"title":2602,"path":2603,"stem":2604},"Identity Map: Кешування сутностей у рамках сесії","\u002Fjava\u002Fpr2\u002Fidentity-map","04.java\u002Fpr2\u002F15.identity-map",{"title":2606,"path":2607,"stem":2608},"Unit of Work: Відстеження змін і координація JDBC-транзакцій","\u002Fjava\u002Fpr2\u002Funit-of-work","04.java\u002Fpr2\u002F16.unit-of-work",{"title":2610,"path":2611,"stem":2612},"Strategy: Замінювані SQL-стратегії для підтримки різних СУБД","\u002Fjava\u002Fpr2\u002Fstrategy-sql","04.java\u002Fpr2\u002F17.strategy-sql",{"title":2614,"path":2615,"stem":2616},"Proxy: Lazy Loading для One-To-Many колекцій","\u002Fjava\u002Fpr2\u002Fproxy-lazy-loading","04.java\u002Fpr2\u002F18.proxy-lazy-loading",{"title":2618,"path":2619,"stem":2620},"Generic Repository через Java Reflection: анотації та динамічний SQL","\u002Fjava\u002Fpr2\u002Fgeneric-repository-reflection","04.java\u002Fpr2\u002F19.generic-repository-reflection",{"title":2622,"path":2623,"stem":2624},"Specification Pattern: Композиція бізнес-правил для складних запитів","\u002Fjava\u002Fpr2\u002Fspecification-pattern","04.java\u002Fpr2\u002F20.specification-pattern",{"title":2626,"path":2627,"stem":2628},"Розширені можливості Specification Pattern: підзапити, агрегації та гібридний підхід","\u002Fjava\u002Fpr2\u002F20a.advanced-specifications","04.java\u002Fpr2\u002F20a.advanced-specifications",{"title":2630,"path":2631,"stem":2632},"Асинхронність у JDBC: Від блокуючих викликів до CompletableFuture","\u002Fjava\u002Fpr2\u002Fasynchronous-jdbc","04.java\u002Fpr2\u002F21.asynchronous-jdbc",{"title":2634,"path":2635,"stem":2636},"Інтеграційне тестування JDBC-репозиторіїв: Embedded H2 та патерн AAA","\u002Fjava\u002Fpr2\u002Fintegration-testing-h2","04.java\u002Fpr2\u002F22.integration-testing-h2",{"title":2638,"path":2639,"stem":2640},"Testcontainers: Тестування з реальною PostgreSQL у Docker-контейнерах","\u002Fjava\u002Fpr2\u002Fintegration-testing-testcontainers","04.java\u002Fpr2\u002F23.integration-testing-testcontainers",{"title":2642,"path":2643,"stem":2644},"Google Guice: Впровадження залежностей у JavaFX-проєкті","\u002Fjava\u002Fpr2\u002Fdependency-injection-guice","04.java\u002Fpr2\u002F24.dependency-injection-guice",{"title":2646,"path":2647,"stem":2648},"JavaFX: Основи побудови графічних інтерфейсів","\u002Fjava\u002Fpr2\u002Fjavafx-fundamentals","04.java\u002Fpr2\u002F25.javafx-fundamentals",{"title":2650,"path":2651,"stem":2652},"Properties та Bindings: Реактивність у JavaFX","\u002Fjava\u002Fpr2\u002Fjavafx-properties-bindings","04.java\u002Fpr2\u002F26.javafx-properties-bindings",{"title":2654,"path":2655,"stem":2656},"MVC vs MVP vs MVVM: Еволюція архітектурних патернів UI","\u002Fjava\u002Fpr2\u002Fui-architecture-patterns","04.java\u002Fpr2\u002F27.ui-architecture-patterns",{"title":2658,"path":2659,"stem":2660},"MVVM на практиці: Побудова ViewModel","\u002Fjava\u002Fpr2\u002Fmvvm-viewmodel-implementation","04.java\u002Fpr2\u002F28.mvvm-viewmodel-implementation",{"title":2662,"path":2663,"stem":2664},"View та Controller: Зв'язування з ViewModel через FXML","\u002Fjava\u002Fpr2\u002Fmvvm-view-controller","04.java\u002Fpr2\u002F29.mvvm-view-controller",{"title":2666,"path":2667,"stem":2668},"Інтеграція MVVM з Guice: Автоматична ін'єкція залежностей","\u002Fjava\u002Fpr2\u002Fmvvm-guice-integration","04.java\u002Fpr2\u002F30.mvvm-guice-integration",{"title":2670,"path":2671,"stem":2672},"Валідація та обробка помилок у MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-validation-error-handling","04.java\u002Fpr2\u002F31.mvvm-validation-error-handling",{"title":2674,"path":2675,"stem":2676},"Навігація та управління екранами у JavaFX MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-navigation-screen-management","04.java\u002Fpr2\u002F32.mvvm-navigation-screen-management",{"title":2678,"path":2679,"stem":2680},"Тестування JavaFX MVVM-додатків","\u002Fjava\u002Fpr2\u002Fmvvm-testing","04.java\u002Fpr2\u002F33.mvvm-testing",{"title":2682,"path":2683,"stem":2684},"Стилізація та теми у JavaFX: CSS та User Experience","\u002Fjava\u002Fpr2\u002Fjavafx-styling-themes","04.java\u002Fpr2\u002F34.javafx-styling-themes",{"title":2686,"path":2687,"stem":2688},"AtlantaFX: Сучасні теми для JavaFX додатків","\u002Fjava\u002Fpr2\u002Fatlantafx-modern-themes","04.java\u002Fpr2\u002F35.atlantafx-modern-themes",{"title":2690,"path":2691,"stem":2692},"Пакування та розповсюдження JavaFX-додатків","\u002Fjava\u002Fpr2\u002Fjar-packaging-distribution","04.java\u002Fpr2\u002F36.jar-packaging-distribution",{"title":2694,"icon":2695,"path":2696,"stem":2697,"children":2698,"page":59},"Python","i-devicon-python","\u002Fpython","05.python",[2699,2703,2706,2710,2714,2718,2722,2726,2730,2734,2738,2742,2746,2750,2754,2815],{"title":2700,"path":2701,"stem":2702},"Модулі, Пакети та Віртуальні Середовища","\u002Fpython\u002Fmodules-packages-venv","05.python\u002F00.modules-packages-venv",{"title":71,"path":2704,"stem":2705},"\u002Fpython\u002Fclasses-objects","05.python\u002F01.classes-objects",{"title":2707,"path":2708,"stem":2709},"Інкапсуляція, Керування Доступом та Властивості","\u002Fpython\u002Fencapsulation","05.python\u002F02.encapsulation",{"title":2711,"path":2712,"stem":2713},"Наслідування, MRO та суперсила super()","\u002Fpython\u002Finheritance-mro","05.python\u002F03.inheritance-mro",{"title":2715,"path":2716,"stem":2717},"Абстракція — ABC проти Статичних Протоколів (PEP 544)","\u002Fpython\u002Fabstraction-protocols","05.python\u002F04.abstraction-protocols",{"title":2719,"path":2720,"stem":2721},"Магічні методи (Dunder) та Емуляція протоколів","\u002Fpython\u002Fdunder-methods","05.python\u002F05.dunder-methods",{"title":2723,"path":2724,"stem":2725},"Декоратори та Керування життєвим циклом методів","\u002Fpython\u002Fdecorators-static-class","05.python\u002F06.decorators-static-class",{"title":2727,"path":2728,"stem":2729},"Дескриптори — Магія доступу до атрибутів","\u002Fpython\u002Fdescriptors","05.python\u002F07.descriptors",{"title":2731,"path":2732,"stem":2733},"Метакласи — Динамічне створення класів під капотом CPython","\u002Fpython\u002Fmetaclasses","05.python\u002F08.metaclasses",{"title":2735,"path":2736,"stem":2737},"Dataclasses, NamedTuple та сучасні контейнери Python","\u002Fpython\u002Fmodern-containers","05.python\u002F09.modern-containers",{"title":2739,"path":2740,"stem":2741},"GIL та модель конкурентності CPython — фундамент перед потоками і процесами","\u002Fpython\u002Fgil-concurrency-intro","05.python\u002F11.gil-concurrency-intro",{"title":2743,"path":2744,"stem":2745},"Threading — конкурентність для I\u002FO-bound задач","\u002Fpython\u002Fthreading","05.python\u002F12.threading",{"title":2747,"path":2748,"stem":2749},"Multiprocessing — справжній паралелізм для CPU-bound задач","\u002Fpython\u002Fmultiprocessing","05.python\u002F13.multiprocessing",{"title":2751,"path":2752,"stem":2753},"asyncio — кооперативна конкурентність та event loop","\u002Fpython\u002Fasyncio","05.python\u002F14.asyncio",{"title":2755,"icon":92,"path":2756,"stem":2757,"children":2758,"page":59},"FastAPI","\u002Fpython\u002Ffastapi","05.python\u002Ffastapi",[2759,2763,2767,2771,2775,2779,2783,2787,2791,2795,2799,2803,2807,2811],{"title":2760,"path":2761,"stem":2762},"Глибокий Typing та Pydantic v2 — від анотацій до валідації","\u002Fpython\u002Ffastapi\u002Ftyping-pydantic","05.python\u002Ffastapi\u002F15.typing-pydantic",{"title":2764,"path":2765,"stem":2766},"WSGI, ASGI та Python Web-екосистема","\u002Fpython\u002Ffastapi\u002Fwsgi-asgi-ecosystem","05.python\u002Ffastapi\u002F16.wsgi-asgi-ecosystem",{"title":2768,"path":2769,"stem":2770},"FastAPI: Перший додаток, Uvicorn та OpenAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-intro","05.python\u002Ffastapi\u002F17.fastapi-intro",{"title":2772,"path":2773,"stem":2774},"Маршрутизація, параметри запитів та APIRouter","\u002Fpython\u002Ffastapi\u002Ffastapi-routing-params","05.python\u002Ffastapi\u002F18.fastapi-routing-params",{"title":2776,"path":2777,"stem":2778},"Pydantic v2 у FastAPI — схеми, валідація та серіалізація","\u002Fpython\u002Ffastapi\u002Ffastapi-pydantic-schemas","05.python\u002Ffastapi\u002F19.fastapi-pydantic-schemas",{"title":2780,"path":2781,"stem":2782},"Dependency Injection — серце архітектури FastAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-dependency-injection","05.python\u002Ffastapi\u002F20.fastapi-dependency-injection",{"title":2784,"path":2785,"stem":2786},"Обробка помилок, Middleware та CORS у FastAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-errors-middleware","05.python\u002Ffastapi\u002F21.fastapi-errors-middleware",{"title":2788,"path":2789,"stem":2790},"SQLAlchemy 2.0 — ORM, Core та Async Engine","\u002Fpython\u002Ffastapi\u002Fsqlalchemy-orm","05.python\u002Ffastapi\u002F22.sqlalchemy-orm",{"title":2792,"path":2793,"stem":2794},"Alembic — міграції бази даних","\u002Fpython\u002Ffastapi\u002Falembic-migrations","05.python\u002Ffastapi\u002F23.alembic-migrations",{"title":2796,"path":2797,"stem":2798},"Repository Pattern та Clean Architecture у FastAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-repository-clean-arch","05.python\u002Ffastapi\u002F24.fastapi-repository-clean-arch",{"title":2800,"path":2801,"stem":2802},"Автентифікація та авторизація — JWT, OAuth2, RBAC","\u002Fpython\u002Ffastapi\u002Ffastapi-auth-security","05.python\u002Ffastapi\u002F25.fastapi-auth-security",{"title":2804,"path":2805,"stem":2806},"Тестування FastAPI — pytest, httpx, fixtures","\u002Fpython\u002Ffastapi\u002Ffastapi-testing","05.python\u002Ffastapi\u002F26.fastapi-testing",{"title":2808,"path":2809,"stem":2810},"Async на повну — Background Tasks, WebSockets, SSE та Celery","\u002Fpython\u002Ffastapi\u002Ffastapi-async-advanced","05.python\u002Ffastapi\u002F27.fastapi-async-advanced",{"title":2812,"path":2813,"stem":2814},"Deployment — Docker, CI\u002FCD, Monitoring","\u002Fpython\u002Ffastapi\u002Ffastapi-deployment","05.python\u002Ffastapi\u002F28.fastapi-deployment",{"title":2816,"path":2817,"stem":2818},"[object Object]","\u002Fpython\u002Foop-plan","05.python\u002Foop-plan",{"title":2820,"icon":2821,"path":2822,"stem":2823,"children":2824,"page":59},"Бази даних","i-lucide-database","\u002Fdatabases","06.databases",[2825,2855,2878,2915,2944,2962,2996,3008,3017],{"title":2826,"icon":2827,"path":2828,"stem":2829,"children":2830,"page":59},"Intro","i-lucide-play","\u002Fdatabases\u002Fintro","06.databases\u002F01.intro",[2831,2835,2839,2843,2847,2851],{"title":2832,"path":2833,"stem":2834},"Введення в теорію баз даних","\u002Fdatabases\u002Fintro\u002Fintroduction-to-databases","06.databases\u002F01.intro\u002F01.introduction-to-databases",{"title":2836,"path":2837,"stem":2838},"Реляційна модель даних","\u002Fdatabases\u002Fintro\u002Frelational-model-theory","06.databases\u002F01.intro\u002F02.relational-model-theory",{"title":2840,"path":2841,"stem":2842},"ER-моделювання","\u002Fdatabases\u002Fintro\u002Fer-modeling","06.databases\u002F01.intro\u002F03.er-modeling",{"title":2844,"path":2845,"stem":2846},"Логічне проектування БД","\u002Fdatabases\u002Fintro\u002Flogical-schema","06.databases\u002F01.intro\u002F04.logical-schema",{"title":2848,"path":2849,"stem":2850},"Класифікація таблиць","\u002Fdatabases\u002Fintro\u002Ftable-classification","06.databases\u002F01.intro\u002F05.table-classification",{"title":2852,"path":2853,"stem":2854},"PlantUML для баз даних","\u002Fdatabases\u002Fintro\u002Fplantuml-diagrams","06.databases\u002F01.intro\u002F06.plantuml-diagrams",{"title":2856,"icon":2821,"path":2857,"stem":2858,"children":2859,"page":59},"MS SQL Server Start","\u002Fdatabases\u002Fms-sql-server-start","06.databases\u002F02.ms-sql-server-start",[2860,2864,2870,2874],{"title":2861,"path":2862,"stem":2863},"Типи даних у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fdata-types","06.databases\u002F02.ms-sql-server-start\u002F01.data-types",{"title":2865,"path":2866,"stem":2867,"children":2868},"Індекси у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-indexes","06.databases\u002F02.ms-sql-server-start\u002F02.sql-indexes",[2869],{"title":2865,"path":2866,"stem":2867},{"title":2871,"path":2872,"stem":2873},"Системні бази даних MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsystem-databases","06.databases\u002F02.ms-sql-server-start\u002F03.system-databases",{"title":2875,"path":2876,"stem":2877},"Огляд мови SQL та запитів","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-queries-overview","06.databases\u002F02.ms-sql-server-start\u002F04.sql-queries-overview",{"title":2879,"icon":2821,"path":2880,"stem":2881,"children":2882,"page":59},"SQL","\u002Fdatabases\u002Fsql","06.databases\u002F03.sql",[2883,2887,2891,2895,2899,2903,2907,2911],{"title":2884,"path":2885,"stem":2886},"Налаштування демонстраційної бази даних","\u002Fdatabases\u002Fsql\u002Fsample-database-setup","06.databases\u002F03.sql\u002F00.sample-database-setup",{"title":2888,"path":2889,"stem":2890},"DDL - Створення таблиць (CREATE TABLE)","\u002Fdatabases\u002Fsql\u002Fddl-create-table","06.databases\u002F03.sql\u002F01.ddl-create-table",{"title":2892,"path":2893,"stem":2894},"DDL - Зміна та видалення таблиць (ALTER, DROP)","\u002Fdatabases\u002Fsql\u002Fddl-alter-drop-table","06.databases\u002F03.sql\u002F02.ddl-alter-drop-table",{"title":2896,"path":2897,"stem":2898},"SELECT запити - Основи","\u002Fdatabases\u002Fsql\u002Fselect-queries-fundamentals","06.databases\u002F03.sql\u002F03.select-queries-fundamentals",{"title":2900,"path":2901,"stem":2902},"SELECT запити - Розширені можливості","\u002Fdatabases\u002Fsql\u002Fselect-queries-advanced","06.databases\u002F03.sql\u002F04.select-queries-advanced",{"title":2904,"path":2905,"stem":2906},"INSERT запити - Додавання даних","\u002Fdatabases\u002Fsql\u002Finsert-queries","06.databases\u002F03.sql\u002F05.insert-queries",{"title":2908,"path":2909,"stem":2910},"UPDATE та DELETE запити","\u002Fdatabases\u002Fsql\u002Fupdate-delete-queries","06.databases\u002F03.sql\u002F06.update-delete-queries",{"title":2912,"path":2913,"stem":2914},"Транзакції в SQL","\u002Fdatabases\u002Fsql\u002Ftransactions","06.databases\u002F03.sql\u002F07.transactions",{"title":2916,"icon":2821,"path":2917,"stem":2918,"children":2919,"page":59},"Multi Table Databases","\u002Fdatabases\u002Fmulti-table-databases","06.databases\u002F04.multi-table-databases",[2920,2924,2928,2932,2936,2940],{"title":2921,"path":2922,"stem":2923},"Зв'язки та нормалізація БД","\u002Fdatabases\u002Fmulti-table-databases\u002Frelationships-and-normalization","06.databases\u002F04.multi-table-databases\u002F00.relationships-and-normalization",{"title":2925,"path":2926,"stem":2927},"INNER JOIN - З'єднання таблиць","\u002Fdatabases\u002Fmulti-table-databases\u002Finner-join","06.databases\u002F04.multi-table-databases\u002F01.inner-join",{"title":2929,"path":2930,"stem":2931},"OUTER JOINs - LEFT, RIGHT, FULL","\u002Fdatabases\u002Fmulti-table-databases\u002Fouter-joins","06.databases\u002F04.multi-table-databases\u002F02.outer-joins",{"title":2933,"path":2934,"stem":2935},"CROSS та SELF JOINs","\u002Fdatabases\u002Fmulti-table-databases\u002Fcross-self-joins","06.databases\u002F04.multi-table-databases\u002F03.cross-self-joins",{"title":2937,"path":2938,"stem":2939},"Підзапити (Subqueries)","\u002Fdatabases\u002Fmulti-table-databases\u002Fsubqueries","06.databases\u002F04.multi-table-databases\u002F04.subqueries",{"title":2941,"path":2942,"stem":2943},"Агрегації з JOIN","\u002Fdatabases\u002Fmulti-table-databases\u002Faggregations-with-joins","06.databases\u002F04.multi-table-databases\u002F05.aggregations-with-joins",{"title":2945,"icon":2946,"path":2947,"stem":2948,"children":2949,"page":59},"Aggregate Functions","i-lucide-calculator","\u002Fdatabases\u002Faggregate-functions","06.databases\u002F05.aggregate-functions",[2950,2954,2958],{"title":2951,"path":2952,"stem":2953},"Функції агрегування в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fintroduction-aggregate-functions","06.databases\u002F05.aggregate-functions\u002F01.introduction-aggregate-functions",{"title":2955,"path":2956,"stem":2957},"Групування даних в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fgrouping-data","06.databases\u002F05.aggregate-functions\u002F02.grouping-data",{"title":2959,"path":2960,"stem":2961},"Підзапити з агрегатними функціями","\u002Fdatabases\u002Faggregate-functions\u002Fsubqueries-aggregates","06.databases\u002F05.aggregate-functions\u002F03.subqueries-aggregates",{"title":2963,"icon":2964,"path":2965,"stem":2966,"children":2967,"page":59},"Тригери та зберігаємі процедури","i-lucide-database-zap","\u002Fdatabases\u002Ftriggers-stored-procedures","06.databases\u002F07.triggers-stored-procedures",[2968,2972,2976,2980,2984,2988,2992],{"title":2969,"path":2970,"stem":2971},"DML-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fdml-triggers","06.databases\u002F07.triggers-stored-procedures\u002F01.dml-triggers",{"title":2973,"path":2974,"stem":2975},"DDL-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fddl-triggers","06.databases\u002F07.triggers-stored-procedures\u002F02.ddl-triggers",{"title":2977,"path":2978,"stem":2979},"Transact-SQL розширення","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransact-sql-extensions","06.databases\u002F07.triggers-stored-procedures\u002F03.transact-sql-extensions",{"title":2981,"path":2982,"stem":2983},"Транзакції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransactions","06.databases\u002F07.triggers-stored-procedures\u002F04.transactions",{"title":2985,"path":2986,"stem":2987},"Зберігаємі процедури","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fstored-procedures","06.databases\u002F07.triggers-stored-procedures\u002F05.stored-procedures",{"title":2989,"path":2990,"stem":2991},"Користувацькі функції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fuser-defined-functions","06.databases\u002F07.triggers-stored-procedures\u002F06.user-defined-functions",{"title":2993,"path":2994,"stem":2995},"Безпека баз даних","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fsecurity","06.databases\u002F07.triggers-stored-procedures\u002F08.security",{"title":2993,"icon":793,"path":2997,"stem":2998,"children":2999,"page":59},"\u002Fdatabases\u002Fsecurity","06.databases\u002F08.security",[3000,3004],{"title":3001,"path":3002,"stem":3003},"Вступ до безпеки баз даних","\u002Fdatabases\u002Fsecurity\u002Fintroduction","06.databases\u002F08.security\u002F01.introduction",{"title":3005,"path":3006,"stem":3007},"Системні представлення та метадані","\u002Fdatabases\u002Fsecurity\u002Fsystem-views","06.databases\u002F08.security\u002F02.system-views",{"title":3009,"icon":3010,"path":3011,"stem":3012,"children":3013,"page":59},"Резервне копіювання та відновлення","i-lucide-database-backup","\u002Fdatabases\u002Fbackup-recovery","06.databases\u002F09.backup-recovery",[3014],{"title":3009,"path":3015,"stem":3016},"\u002Fdatabases\u002Fbackup-recovery\u002Fbackup-restore","06.databases\u002F09.backup-recovery\u002F01.backup-restore",{"title":3018,"icon":3019,"path":3020,"stem":3021,"children":3022,"page":59},"Повнотекстовий пошук","i-lucide-search","\u002Fdatabases\u002Ffull-text-search","06.databases\u002F10.full-text-search",[3023],{"title":3018,"path":3024,"stem":3025},"\u002Fdatabases\u002Ffull-text-search\u002Ffull-text-search","06.databases\u002F10.full-text-search\u002F01.full-text-search",{"title":3027,"icon":3028,"path":3029,"stem":3030,"children":3031,"page":59},"Tools","i-lucide-wrench","\u002Ftools","07.tools",[3032,3108],{"title":3033,"icon":3034,"path":3035,"stem":3036,"children":3037},"Docker","i-simple-icons-docker","\u002Ftools\u002Fdocker","07.tools\u002F01.docker\u002Findex",[3038,3040,3044,3048,3052,3056,3060,3064,3068,3072,3076,3080,3084,3088,3092,3096,3100,3104],{"title":3039,"path":3035,"stem":3036},"Docker: від нуля до production",{"title":3041,"path":3042,"stem":3043},"Контейнеризація — від проблеми до рішення","\u002Ftools\u002Fdocker\u002Fcontainerization-concept","07.tools\u002F01.docker\u002F01.containerization-concept",{"title":3045,"path":3046,"stem":3047},"Docker — що це і навіщо?","\u002Ftools\u002Fdocker\u002Fdocker-what-and-why","07.tools\u002F01.docker\u002F02.docker-what-and-why",{"title":3049,"path":3050,"stem":3051},"Архітектура Docker Engine","\u002Ftools\u002Fdocker\u002Fdocker-architecture","07.tools\u002F01.docker\u002F03.docker-architecture",{"title":3053,"path":3054,"stem":3055},"Встановлення Docker","\u002Ftools\u002Fdocker\u002Finstallation","07.tools\u002F01.docker\u002F04.installation",{"title":3057,"path":3058,"stem":3059},"Перший контейнер — docker run","\u002Ftools\u002Fdocker\u002Ffirst-container","07.tools\u002F01.docker\u002F05.first-container",{"title":3061,"path":3062,"stem":3063},"Життєвий цикл контейнера","\u002Ftools\u002Fdocker\u002Fcontainer-lifecycle","07.tools\u002F01.docker\u002F06.container-lifecycle",{"title":3065,"path":3066,"stem":3067},"Docker Images — фундаментальні концепції","\u002Ftools\u002Fdocker\u002Fdocker-images-fundamentals","07.tools\u002F01.docker\u002F07.docker-images-fundamentals",{"title":3069,"path":3070,"stem":3071},"Dockerfile — основи","\u002Ftools\u002Fdocker\u002Fdockerfile-basics","07.tools\u002F01.docker\u002F08.dockerfile-basics",{"title":3073,"path":3074,"stem":3075},"Dockerfile — просунуті техніки","\u002Ftools\u002Fdocker\u002Fdockerfile-advanced","07.tools\u002F01.docker\u002F09.dockerfile-advanced",{"title":3077,"path":3078,"stem":3079},"Build Context та кешування шарів","\u002Ftools\u002Fdocker\u002Fbuild-context-and-cache","07.tools\u002F01.docker\u002F10.build-context-and-cache",{"title":3081,"path":3082,"stem":3083},"Реєстри Docker-образів","\u002Ftools\u002Fdocker\u002Fimage-registries","07.tools\u002F01.docker\u002F11.image-registries",{"title":3085,"path":3086,"stem":3087},"Контейнеризація .NET додатків","\u002Ftools\u002Fdocker\u002Fdotnet-containerization","07.tools\u002F01.docker\u002F12.dotnet-containerization",{"title":3089,"path":3090,"stem":3091},"Томи та збереження даних","\u002Ftools\u002Fdocker\u002Fvolumes-and-data","07.tools\u002F01.docker\u002F13.volumes-and-data",{"title":3093,"path":3094,"stem":3095},"Основи мережі в Docker","\u002Ftools\u002Fdocker\u002Fnetworking-basics","07.tools\u002F01.docker\u002F14.networking-basics",{"title":3097,"path":3098,"stem":3099},"Змінні оточення та конфігурація","\u002Ftools\u002Fdocker\u002Fenvironment-and-configuration","07.tools\u002F01.docker\u002F15.environment-and-configuration",{"title":3101,"path":3102,"stem":3103},"Docker Compose — оркестрація контейнерів","\u002Ftools\u002Fdocker\u002Fdocker-compose-basics","07.tools\u002F01.docker\u002F16.docker-compose-basics",{"title":3105,"path":3106,"stem":3107},"Docker Compose — Multi-Service застосунки","\u002Ftools\u002Fdocker\u002Fcompose-multi-service","07.tools\u002F01.docker\u002F17.compose-multi-service",{"title":3109,"icon":3110,"path":3111,"stem":3112,"children":3113},"Kubernetes","simple-icons:kubernetes","\u002Ftools\u002Fkubernetes","07.tools\u002F02.kubernetes\u002Findex",[3114,3116,3120,3124,3128,3132,3136,3140,3144],{"title":3115,"path":3111,"stem":3112},"Kubernetes: від розробки до production",{"title":3117,"path":3118,"stem":3119},"Kubernetes — коли Docker Compose більше не вистачає","\u002Ftools\u002Fkubernetes\u002Fwhy-kubernetes","07.tools\u002F02.kubernetes\u002F01.why-kubernetes",{"title":3121,"path":3122,"stem":3123},"Архітектура Kubernetes — анатомія кластера","\u002Ftools\u002Fkubernetes\u002Fkubernetes-architecture","07.tools\u002F02.kubernetes\u002F02.kubernetes-architecture",{"title":3125,"path":3126,"stem":3127},"Локальне середовище — minikube, kind та k3s","\u002Ftools\u002Fkubernetes\u002Flocal-environment","07.tools\u002F02.kubernetes\u002F03.local-environment",{"title":3129,"path":3130,"stem":3131},"Pod — атомарна одиниця Kubernetes","\u002Ftools\u002Fkubernetes\u002Fpods-and-containers","07.tools\u002F02.kubernetes\u002F04.pods-and-containers",{"title":3133,"path":3134,"stem":3135},"Патерни використання Pod","\u002Ftools\u002Fkubernetes\u002Fpod-patterns","07.tools\u002F02.kubernetes\u002F05.pod-patterns",{"title":3137,"path":3138,"stem":3139},"Deployment — декларативне управління Pod","\u002Ftools\u002Fkubernetes\u002Fdeployment-basics","07.tools\u002F02.kubernetes\u002F06.deployment-basics",{"title":3141,"path":3142,"stem":3143},"Rolling Updates та управління життєвим циклом Deployment","\u002Ftools\u002Fkubernetes\u002Fdeployment-rolling-updates","07.tools\u002F02.kubernetes\u002F07.deployment-rolling-updates",{"title":3145,"path":3146,"stem":3147},"Service — мережева абстракція для Pod","\u002Ftools\u002Fkubernetes\u002Fservices-networking","07.tools\u002F02.kubernetes\u002F08.services-networking",{"title":3149,"icon":3150,"path":3151,"stem":3152,"children":3153,"page":59},"Software Engineering","i-lucide-code-2","\u002Fsoftware-engineering","09.software-engineering",[3154,3158,3162,3166,3170,3174,3178,3182,3186,3190,3194],{"title":3155,"path":3156,"stem":3157},"1. Аналіз предметної області. Експертні знання та складність","\u002Fsoftware-engineering\u002Fintro-subdomains","09.software-engineering\u002F01.intro-subdomains",{"title":3159,"path":3160,"stem":3161},"2. Обмежені контексти. Інтеграція обмежених контекстів","\u002Fsoftware-engineering\u002Fintegrating-limited-contexts","09.software-engineering\u002F02.integrating-limited-contexts",{"title":3163,"path":3164,"stem":3165},"3. Реалізація простої бізнес-логіки","\u002Fsoftware-engineering\u002Fsimple","09.software-engineering\u002F03.simple",{"title":3167,"path":3168,"stem":3169},"4. Опрацювання складної бізнес-логіки","\u002Fsoftware-engineering\u002Fcomplex-business-logic","09.software-engineering\u002F04.complex-business-logic",{"title":3171,"path":3172,"stem":3173},"5. Моделювання фактора часу. Подієво-орієнтована архітектура.","\u002Fsoftware-engineering\u002Fmodelling-the-time-factor","09.software-engineering\u002F05.modelling-the-time-factor",{"title":3175,"path":3176,"stem":3177},"6. Архітектурні патерни","\u002Fsoftware-engineering\u002Farchitectural-patterns","09.software-engineering\u002F06.architectural-patterns",{"title":3179,"path":3180,"stem":3181},"Паттерни взаємодії","\u002Fsoftware-engineering\u002Fpatterns-of-interaction","09.software-engineering\u002F07.patterns-of-interaction",{"title":3183,"path":3184,"stem":3185},"Евристика проєктування","\u002Fsoftware-engineering\u002Fdesign-heuristics","09.software-engineering\u002F08.design-heuristics",{"title":3187,"path":3188,"stem":3189},"Еволюція проєктних рішень","\u002Fsoftware-engineering\u002Fevolution-of-design-solutions","09.software-engineering\u002F09.evolution-of-design-solutions",{"title":3191,"path":3192,"stem":3193},"EventStorming","\u002Fsoftware-engineering\u002Feventstorming","09.software-engineering\u002F10.eventstorming",{"title":3195,"path":3196,"stem":3197},"DDD на практиці","\u002Fsoftware-engineering\u002Fddd-in-practice","09.software-engineering\u002F11.ddd-in-practice",{"title":3199,"icon":943,"path":3200,"stem":3201,"children":3202,"page":59},"DDD","\u002Fddd","10.ddd",[3203,3207,3211,3215,3219,3223,3227,3231,3235,3239,3243,3247,3251],{"title":3204,"path":3205,"stem":3206},"Аналіз предметної області","\u002Fddd\u002Fdomain-analysis","10.ddd\u002F01.domain-analysis",{"title":3208,"path":3209,"stem":3210},"Експертні знання про предметну область","\u002Fddd\u002Fdomain-expert-knowledge","10.ddd\u002F02.domain-expert-knowledge",{"title":3212,"path":3213,"stem":3214},"Як осмислити складність предметної області","\u002Fddd\u002Fmanaging-domain-complexity","10.ddd\u002F03.managing-domain-complexity",{"title":3216,"path":3217,"stem":3218},"Інтеграція обмежених контекстів","\u002Fddd\u002Fbounded-context-integration","10.ddd\u002F04.bounded-context-integration",{"title":3220,"path":3221,"stem":3222},"Реалізація простої бізнес-логіки","\u002Fddd\u002Fsimple-business-logic","10.ddd\u002F05.simple-business-logic",{"title":3224,"path":3225,"stem":3226},"Обробка складної бізнес-логіки","\u002Fddd\u002Fcomplex-business-logic","10.ddd\u002F06.complex-business-logic",{"title":3228,"path":3229,"stem":3230},"Моделювання фактора часу","\u002Fddd\u002Ftime-modeling","10.ddd\u002F07.time-modeling",{"title":3232,"path":3233,"stem":3234},"Глава 8. Архітектурні Патерни","\u002Fddd\u002Farchitectural-patterns","10.ddd\u002F08.architectural-patterns",{"title":3236,"path":3237,"stem":3238},"Глава 9. Патерни Взаємодії","\u002Fddd\u002Finteraction-patterns","10.ddd\u002F09.interaction-patterns",{"title":3240,"path":3241,"stem":3242},"Глава 10. Проектні Евристики","\u002Fddd\u002Fdesign-heuristics","10.ddd\u002F10.design-heuristics",{"title":3244,"path":3245,"stem":3246},"Глава 11. Еволюція Проектних Рішень","\u002Fddd\u002Fevolution-of-design-decisions","10.ddd\u002F11.evolution-of-design-decisions",{"title":3248,"path":3249,"stem":3250},"Глава 12. EventStorming","\u002Fddd\u002Fevent-storming","10.ddd\u002F12.event-storming",{"title":3252,"path":3253,"stem":3254},"Глава 13. DDD на Практиці","\u002Fddd\u002Fddd-in-practice","10.ddd\u002F13.ddd-in-practice",{"title":3256,"icon":3257,"path":3258,"stem":3259,"children":3260,"page":59},"Media Streaming","i-lucide-video","\u002Fmedia-streaming","11.media-streaming",[3261,3265,3269,3273,3277,3281,3285],{"title":3262,"path":3263,"stem":3264},"01. Магія Стрімінгу: Що відбувається, коли ви натискаєте \"Play\"","\u002Fmedia-streaming\u002Fintroduction","11.media-streaming\u002F01.introduction",{"title":3266,"path":3267,"stem":3268},"02. Анатомія Медіа: Кодеки, Контейнери та Стиснення","\u002Fmedia-streaming\u002Faudio-video-anatomy","11.media-streaming\u002F02.audio-video-anatomy",{"title":3270,"path":3271,"stem":3272},"03. The Gym: FFmpeg Deep Dive","\u002Fmedia-streaming\u002Fffmpeg-gym","11.media-streaming\u002F03.ffmpeg-gym",{"title":3274,"path":3275,"stem":3276},"04. HLS Protocol: HTTP Live Streaming у Деталях","\u002Fmedia-streaming\u002Fhls-protocol","11.media-streaming\u002F04.hls-protocol",{"title":3278,"path":3279,"stem":3280},"05. DASH Protocol: Відкритий Стандарт","\u002Fmedia-streaming\u002Fdash-protocol","11.media-streaming\u002F05.dash-protocol",{"title":3282,"path":3283,"stem":3284},"06. Масштабування: CDN та Adaptive Bitrate","\u002Fmedia-streaming\u002Fcdn-and-adaptive-bitrate","11.media-streaming\u002F06.cdn-and-adaptive-bitrate",{"title":3286,"path":3287,"stem":3288},"07. Війна із Затримкою (Latency)","\u002Fmedia-streaming\u002Frealtime-latency","11.media-streaming\u002F07.realtime-latency",{"title":3290,"icon":3291,"path":3292,"stem":3293,"children":3294,"page":59},"HTML & CSS","i-devicon-html5","\u002Fhtml-css","12.html-css",[3295,3299,3303,3307,3311,3315,3319,3323,3327,3331,3335,3339,3343,3347,3351,3355,3359,3363,3367,3371,3375,3379,3383,3387,3391,3395,3399,3403,3407,3411],{"title":3296,"path":3297,"stem":3298},"Вступ до HTML. Структура документа","\u002Fhtml-css\u002Fintro-html-structure","12.html-css\u002F01.intro-html-structure",{"title":3300,"path":3301,"stem":3302},"Форматування тексту в HTML","\u002Fhtml-css\u002Fhtml-text-formatting","12.html-css\u002F02.html-text-formatting",{"title":3304,"path":3305,"stem":3306},"Посилання та зображення в HTML","\u002Fhtml-css\u002Fhtml-links-images","12.html-css\u002F03.html-links-images",{"title":3308,"path":3309,"stem":3310},"Списки та таблиці в HTML","\u002Fhtml-css\u002Fhtml-lists-tables","12.html-css\u002F04.html-lists-tables",{"title":3312,"path":3313,"stem":3314},"Форми в HTML","\u002Fhtml-css\u002Fhtml-forms","12.html-css\u002F05.html-forms",{"title":3316,"path":3317,"stem":3318},"Семантичні елементи HTML5","\u002Fhtml-css\u002Fhtml-semantic-elements","12.html-css\u002F06.html-semantic-elements",{"title":3320,"path":3321,"stem":3322},"Мультимедіа та розширені елементи HTML","\u002Fhtml-css\u002Fhtml-multimedia-advanced","12.html-css\u002F07.html-multimedia-advanced",{"title":3324,"path":3325,"stem":3326},"Мікророзмітка та SEO в HTML","\u002Fhtml-css\u002Fhtml-microdata-seo","12.html-css\u002F08.html-microdata-seo",{"title":3328,"path":3329,"stem":3330},"Вступ до CSS. Селектори та специфічність","\u002Fhtml-css\u002Fcss-intro-selectors","12.html-css\u002F09.css-intro-selectors",{"title":3332,"path":3333,"stem":3334},"Блокова модель CSS. Відступи. Box Sizing","\u002Fhtml-css\u002Fcss-box-model","12.html-css\u002F10.css-box-model",{"title":3336,"path":3337,"stem":3338},"Розміри у CSS: повний довідник одиниць і ключових слів","\u002Fhtml-css\u002F10a.css-sizing","12.html-css\u002F10a.css-sizing",{"title":3340,"path":3341,"stem":3342},"Типографіка в CSS. Шрифти та текст","\u002Fhtml-css\u002Fcss-typography","12.html-css\u002F11.css-typography",{"title":3344,"path":3345,"stem":3346},"Кольори та фони в CSS","\u002Fhtml-css\u002Fcss-colors-backgrounds","12.html-css\u002F12.css-colors-backgrounds",{"title":3348,"path":3349,"stem":3350},"Тіні та фільтри в CSS","\u002Fhtml-css\u002F12b.css-shadows-filters","12.html-css\u002F12b.css-shadows-filters",{"title":3352,"path":3353,"stem":3354},"CSS Flexbox: Фундамент гнучких макетів","\u002Fhtml-css\u002Fcss-flexbox-fundamentals","12.html-css\u002F13.css-flexbox-fundamentals",{"title":3356,"path":3357,"stem":3358},"CSS Flexbox: Вирівнювання та Позиціонування","\u002Fhtml-css\u002Fcss-flexbox-alignment-sizing-and-patterns","12.html-css\u002F14.css-flexbox-alignment-sizing-and-patterns",{"title":3360,"path":3361,"stem":3362},"CSS Grid. Двовимірний макет. Частина 1","\u002Fhtml-css\u002Fcss-layout-grid","12.html-css\u002F15.css-layout-grid",{"title":3364,"path":3365,"stem":3366},"CSS Grid. Двовимірний макет. Частина 2","\u002Fhtml-css\u002Fcss-layout-grid-advanced","12.html-css\u002F16.css-layout-grid-advanced",{"title":3368,"path":3369,"stem":3370},"Позиціонування в CSS. Z-index. Stacking Context","\u002Fhtml-css\u002Fcss-positioning","12.html-css\u002F17.css-positioning",{"title":3372,"path":3373,"stem":3374},"CSS Анімації та Переходи","\u002Fhtml-css\u002Fcss-animations-transitions","12.html-css\u002F18.css-animations-transitions",{"title":3376,"path":3377,"stem":3378},"Адаптивний дизайн. Media Queries. Частина 1","\u002Fhtml-css\u002Fcss-responsive-media-queries","12.html-css\u002F19.css-responsive-media-queries",{"title":3380,"path":3381,"stem":3382},"Адаптивний дизайн. Частина 2: clamp(), Container Queries, @layer","\u002Fhtml-css\u002Fcss-responsive-advanced","12.html-css\u002F20.css-responsive-advanced",{"title":3384,"path":3385,"stem":3386},"CSS Custom Properties. Методології. Сучасний CSS","\u002Fhtml-css\u002Fcss-variables-methodologies","12.html-css\u002F21.css-variables-methodologies",{"title":3388,"path":3389,"stem":3390},"Сучасний CSS 2023–2025: Нові можливості","\u002Fhtml-css\u002Fcss-modern-features","12.html-css\u002F22.css-modern-features",{"title":3392,"path":3393,"stem":3394},"CSS Nesting, @layer, @scope та @property: нативний препроцесор","\u002Fhtml-css\u002F22a.css-nesting-modern-syntax","12.html-css\u002F22a.css-nesting-modern-syntax",{"title":3396,"path":3397,"stem":3398},"CSS для форм та інтерактивних станів","\u002Fhtml-css\u002Fcss-forms-interactive-states","12.html-css\u002F23.css-forms-interactive-states",{"title":3400,"path":3401,"stem":3402},"Доступність у CSS (CSS Accessibility)","\u002Fhtml-css\u002Fcss-accessibility","12.html-css\u002F24.css-accessibility",{"title":3404,"path":3405,"stem":3406},"CSS-функції та сучасні sizing primitives","\u002Fhtml-css\u002Fcss-functions-sizing","12.html-css\u002F25.css-functions-sizing",{"title":3408,"path":3409,"stem":3410},"Rendering Pipeline і CSS Performance","\u002Fhtml-css\u002Fcss-rendering-performance","12.html-css\u002F26.css-rendering-performance",{"title":3412,"path":3413,"stem":3414},"CSS Best Practices: типові ситуації та правильні рішення","\u002Fhtml-css\u002Fcss-best-practices","12.html-css\u002F27.css-best-practices",{"title":3416,"path":3417,"stem":3418,"children":3419,"page":59},"AWS","\u002Faws","13.aws",[3420,3424,3428,3432,3436,3440,3444,3448,3452,3456,3460,3464,3468,3472,3476,3480,3484,3488],{"title":3421,"path":3422,"stem":3423},"Реєстрація AWS акаунту та студентські програми","\u002Faws\u002Faccount-registration","13.aws\u002F00.account-registration",{"title":3425,"path":3426,"stem":3427},"Вступ до хмарних обчислень та AWS","\u002Faws\u002Fintroduction-to-cloud","13.aws\u002F01.introduction-to-cloud",{"title":3429,"path":3430,"stem":3431},"AWS IAM — Identity and Access Management","\u002Faws\u002Fiam","13.aws\u002F02.iam",{"title":3433,"path":3434,"stem":3435},"AWS IAM CLI — Довідник команд","\u002Faws\u002F02a.iam-doc","13.aws\u002F02a.iam-doc",{"title":3437,"path":3438,"stem":3439},"Docker та контейнеризація в AWS — ECR, ECS та Fargate","\u002Faws\u002Fdocker-ecs","13.aws\u002F03.docker-ecs",{"title":3441,"path":3442,"stem":3443},"AWS ECR \u002F ECS CLI — Довідник команд","\u002Faws\u002F03a.docker-ecs-doc","13.aws\u002F03a.docker-ecs-doc",{"title":3445,"path":3446,"stem":3447},"Amazon EC2 — Elastic Compute Cloud","\u002Faws\u002Fec2","13.aws\u002F04.ec2",{"title":3449,"path":3450,"stem":3451},"AWS EC2 CLI — Довідник команд","\u002Faws\u002F04a.ec2-doc","13.aws\u002F04a.ec2-doc",{"title":3453,"path":3454,"stem":3455},"Elastic Load Balancing та Auto Scaling","\u002Faws\u002Falb-asg","13.aws\u002F05.alb-asg",{"title":3457,"path":3458,"stem":3459},"Amazon S3 — Simple Storage Service","\u002Faws\u002Fs3","13.aws\u002F06.s3",{"title":3461,"path":3462,"stem":3463},"Amazon CloudFront — Content Delivery Network","\u002Faws\u002Fcloudfront","13.aws\u002F07.cloudfront",{"title":3465,"path":3466,"stem":3467},"Amazon RDS — Relational Database Service","\u002Faws\u002Frds","13.aws\u002F08.rds",{"title":3469,"path":3470,"stem":3471},"Amazon DynamoDB — NoSQL Database","\u002Faws\u002Fdynamodb","13.aws\u002F09.dynamodb",{"title":3473,"path":3474,"stem":3475},"AWS Lambda та Serverless Compute","\u002Faws\u002Flambda","13.aws\u002F10.lambda",{"title":3477,"path":3478,"stem":3479},"Amazon Bedrock - Foundation Models, RAG та Agents","\u002Faws\u002Fbedrock","13.aws\u002F22.bedrock",{"title":3481,"path":3482,"stem":3483},"Amazon Rekognition - Комп'ютерний зір","\u002Faws\u002Frekognition","13.aws\u002F23.rekognition",{"title":3485,"path":3486,"stem":3487},"Amazon Textract - Інтелектуальний аналіз документів","\u002Faws\u002Ftextract","13.aws\u002F24.textract",{"title":3489,"path":3490,"stem":3491},"Amazon Polly, Transcribe, Comprehend та Translate","\u002Faws\u002Faudio-nlp-services","13.aws\u002F25.audio-nlp-services",{"title":3493,"path":3494,"stem":3495,"children":3496,"page":59},"Ai Development","\u002Fai-development","14.ai-development",[3497],{"title":3498,"path":3499,"stem":3500,"children":3501,"page":59},"Foundations","\u002Fai-development\u002Ffoundations","14.ai-development\u002F00.foundations",[3502],{"title":3503,"path":3504,"stem":3505},"Модуль 0.1. Що таке Large Language Model (LLM)","\u002Fai-development\u002Ffoundations\u002Fwhat-is-llm","14.ai-development\u002F00.foundations\u002F01.what-is-llm",{"title":3507,"path":3508,"stem":3509,"children":3510,"page":59},"React Native","\u002Freact-native","15.react-native",[3511,3532],{"title":3512,"path":3513,"stem":3514,"children":3515,"page":59},"Version1","\u002Freact-native\u002Fversion1","15.react-native\u002Fversion1",[3516,3520,3524,3528],{"title":3517,"path":3518,"stem":3519},"Що таке React Native","\u002Freact-native\u002Fversion1\u002Fwhat-is-react-native","15.react-native\u002Fversion1\u002F01.what-is-react-native",{"title":3521,"path":3522,"stem":3523},"Як влаштований React Native «під капотом»","\u002Freact-native\u002Fversion1\u002Freact-native-architecture","15.react-native\u002Fversion1\u002F02.react-native-architecture",{"title":3525,"path":3526,"stem":3527},"Від React до React Native: ключові відмінності","\u002Freact-native\u002Fversion1\u002Freact-native-vs-react","15.react-native\u002Fversion1\u002F03.react-native-vs-react",{"title":3529,"path":3530,"stem":3531},"View та Text — фундаментальні будівельні блоки","\u002Freact-native\u002Fversion1\u002Fview-and-text","15.react-native\u002Fversion1\u002F04.view-and-text",{"title":3533,"path":3534,"stem":3535,"children":3536,"page":59},"Version2","\u002Freact-native\u002Fversion2","15.react-native\u002Fversion2",[3537,3541,3545,3549,3553,3557,3561,3565,3569,3573,3577,3581,3585,3589,3593,3597,3601,3605,3609,3613,3617,3621,3625,3629,3633,3637,3641],{"title":3538,"path":3539,"stem":3540},"React Native — навіщо він потрібен","\u002Freact-native\u002Fversion2\u002Fwhy-react-native","15.react-native\u002Fversion2\u002F01.why-react-native",{"title":3542,"path":3543,"stem":3544},"Налаштування середовища розробки","\u002Freact-native\u002Fversion2\u002Fenvironment-setup","15.react-native\u002Fversion2\u002F02.environment-setup",{"title":3546,"path":3547,"stem":3548},"Expo і класичний React Native — два шляхи одного фреймворку","\u002Freact-native\u002Fversion2\u002Fexpo-vs-cli-landscape","15.react-native\u002Fversion2\u002F03.expo-vs-cli-landscape",{"title":3550,"path":3551,"stem":3552},"Середовище Expo — перший запуск","\u002Freact-native\u002Fversion2\u002Fexpo-setup-and-tooling","15.react-native\u002Fversion2\u002F04.expo-setup-and-tooling",{"title":3554,"path":3555,"stem":3556},"Структура проєкту та перші UI-примітиви","\u002Freact-native\u002Fversion2\u002Fproject-structure-and-conventions","15.react-native\u002Fversion2\u002F05.project-structure-and-conventions",{"title":3558,"path":3559,"stem":3560},"Базові компоненти React Native","\u002Freact-native\u002Fversion2\u002Fcore-components","15.react-native\u002Fversion2\u002F06.core-components",{"title":3562,"path":3563,"stem":3564},"Flexbox і layout у React Native","\u002Freact-native\u002Fversion2\u002Fflexbox-and-layout","15.react-native\u002Fversion2\u002F07.flexbox-and-layout",{"title":3566,"path":3567,"stem":3568},"StyleSheet і теми (light \u002F dark)","\u002Freact-native\u002Fversion2\u002Fstylesheet-and-theming","15.react-native\u002Fversion2\u002F08.stylesheet-and-theming",{"title":3570,"path":3571,"stem":3572},"Списки та віртуалізація","\u002Freact-native\u002Fversion2\u002Flists-and-virtualization","15.react-native\u002Fversion2\u002F09.lists-and-virtualization",{"title":3574,"path":3575,"stem":3576},"Форми, ввід і валідація","\u002Freact-native\u002Fversion2\u002Fforms-input-validation","15.react-native\u002Fversion2\u002F10.forms-input-validation",{"title":3578,"path":3579,"stem":3580},"Основи Expo Router","\u002Freact-native\u002Fversion2\u002Fexpo-router-basics","15.react-native\u002Fversion2\u002F11.expo-router-basics",{"title":3582,"path":3583,"stem":3584},"Вкладені навігатори та модалки","\u002Freact-native\u002Fversion2\u002Fnested-navigators-and-modals","15.react-native\u002Fversion2\u002F12.nested-navigators-and-modals",{"title":3586,"path":3587,"stem":3588},"Deep linking і параметри маршрутів","\u002Freact-native\u002Fversion2\u002Fdeep-linking-and-params","15.react-native\u002Fversion2\u002F13.deep-linking-and-params",{"title":3590,"path":3591,"stem":3592},"Робота з мережею та життєвий цикл застосунку","\u002Freact-native\u002Fversion2\u002Fnetworking-and-app-lifecycle","15.react-native\u002Fversion2\u002F14.networking-and-app-lifecycle",{"title":3594,"path":3595,"stem":3596},"Redux Toolkit на мобільних платформах","\u002Freact-native\u002Fversion2\u002Fredux-toolkit-on-mobile","15.react-native\u002Fversion2\u002F15.redux-toolkit-on-mobile",{"title":3598,"path":3599,"stem":3600},"RTK Query на мобільних платформах","\u002Freact-native\u002Fversion2\u002Frtk-query-mobile","15.react-native\u002Fversion2\u002F16.rtk-query-mobile",{"title":3602,"path":3603,"stem":3604},"Автентифікація та Безпечне Зберігання","\u002Freact-native\u002Fversion2\u002Fauth-secure-storage","15.react-native\u002Fversion2\u002F18.auth-secure-storage",{"title":3606,"path":3607,"stem":3608},"Локальне сховище — AsyncStorage, MMKV, SQLite","\u002Freact-native\u002Fversion2\u002Flocal-storage-mmkv-sqlite","15.react-native\u002Fversion2\u002F19.local-storage-mmkv-sqlite",{"title":3610,"path":3611,"stem":3612},"Офлайн-First і синхронізація","\u002Freact-native\u002Fversion2\u002Foffline-first-sync","15.react-native\u002Fversion2\u002F20.offline-first-sync",{"title":3614,"path":3615,"stem":3616},"Камера, медіа та файлова система","\u002Freact-native\u002Fversion2\u002Fcamera-media-filesystem","15.react-native\u002Fversion2\u002F21.camera-media-filesystem",{"title":3618,"path":3619,"stem":3620},"Карти та геолокація","\u002Freact-native\u002Fversion2\u002Fmaps-and-location","15.react-native\u002Fversion2\u002F22.maps-and-location",{"title":3622,"path":3623,"stem":3624},"Жести та дотики","\u002Freact-native\u002Fversion2\u002Fgestures-and-touch","15.react-native\u002Fversion2\u002F23.gestures-and-touch",{"title":3626,"path":3627,"stem":3628},"Анімації з Reanimated","\u002Freact-native\u002Fversion2\u002Freanimated-animations","15.react-native\u002Fversion2\u002F24.reanimated-animations",{"title":3630,"path":3631,"stem":3632},"Push і локальні сповіщення","\u002Freact-native\u002Fversion2\u002Fpush-and-local-notifications","15.react-native\u002Fversion2\u002F25.push-and-local-notifications",{"title":3634,"path":3635,"stem":3636},"Інтернаціоналізація та доступність","\u002Freact-native\u002Fversion2\u002Faccessibility-and-i18n","15.react-native\u002Fversion2\u002F26.accessibility-and-i18n",{"title":3638,"path":3639,"stem":3640},"EAS Build та профілі збірки","\u002Freact-native\u002Fversion2\u002Feas-build-and-profiles","15.react-native\u002Fversion2\u002F29.eas-build-and-profiles",{"title":3642,"path":3643,"stem":3644},"Публікація в App Store та Google Play","\u002Freact-native\u002Fversion2\u002Fapp-store-play-release","15.react-native\u002Fversion2\u002F30.app-store-play-release",{"title":3646,"path":3647,"stem":3648,"children":3649,"page":59},"Ai Python","\u002Fai-python","16.ai-python",[3650,3659,3668,3677,3706,3732,3757,3790,3807,3820,3829,3842,3851,3872,3885,3906],{"title":3651,"path":3652,"stem":3653,"children":3654,"page":59},"Intro To Ai","\u002Fai-python\u002Fintro-to-ai","16.ai-python\u002F01.intro-to-ai",[3655],{"title":3656,"path":3657,"stem":3658},"Вступ до штучного інтелекту та машинного навчання","\u002Fai-python\u002Fintro-to-ai\u002Fintro-to-ai","16.ai-python\u002F01.intro-to-ai\u002F01.intro-to-ai",{"title":3660,"path":3661,"stem":3662,"children":3663,"page":59},"Jupyter Notebook","\u002Fai-python\u002Fjupyter-notebook","16.ai-python\u002F02.jupyter-notebook",[3664],{"title":3665,"path":3666,"stem":3667},"Знайомство з Jupyter Notebook та JupyterLab","\u002Fai-python\u002Fjupyter-notebook\u002Fjupyter-notebook","16.ai-python\u002F02.jupyter-notebook\u002F02.jupyter-notebook",{"title":3669,"path":3670,"stem":3671,"children":3672,"page":59},"Numpy Pandas","\u002Fai-python\u002Fnumpy-pandas","16.ai-python\u002F03.numpy-pandas",[3673],{"title":3674,"path":3675,"stem":3676},"Робота з даними з використанням NumPy і pandas","\u002Fai-python\u002Fnumpy-pandas\u002Fnumpy-pandas","16.ai-python\u002F03.numpy-pandas\u002F03.numpy-pandas",{"title":3678,"path":3679,"stem":3680,"children":3681,"page":59},"Statistics Basics","\u002Fai-python\u002Fstatistics-basics","16.ai-python\u002F04.statistics-basics",[3682,3686,3690,3694,3698,3702],{"title":3683,"path":3684,"stem":3685},"Випадкові величини та їх типи","\u002Fai-python\u002Fstatistics-basics\u002Frandom-variables","16.ai-python\u002F04.statistics-basics\u002F01.random-variables",{"title":3687,"path":3688,"stem":3689},"Міри центральної тенденції","\u002Fai-python\u002Fstatistics-basics\u002Fcentral-tendency","16.ai-python\u002F04.statistics-basics\u002F02.central-tendency",{"title":3691,"path":3692,"stem":3693},"Міри варіації (розсіювання)","\u002Fai-python\u002Fstatistics-basics\u002Fvariability","16.ai-python\u002F04.statistics-basics\u002F03.variability",{"title":3695,"path":3696,"stem":3697},"Розподіли випадкових величин","\u002Fai-python\u002Fstatistics-basics\u002Fdistributions","16.ai-python\u002F04.statistics-basics\u002F04.distributions",{"title":3699,"path":3700,"stem":3701},"Кореляція та взаємозв'язки","\u002Fai-python\u002Fstatistics-basics\u002Fcorrelation","16.ai-python\u002F04.statistics-basics\u002F05.correlation",{"title":3703,"path":3704,"stem":3705},"Викиди та аномалії","\u002Fai-python\u002Fstatistics-basics\u002Foutliers","16.ai-python\u002F04.statistics-basics\u002F06.outliers",{"title":3707,"path":3708,"stem":3709,"children":3710},"Візуалізація даних за допомогою matplotlib","\u002Fai-python\u002Fdata-visualization","16.ai-python\u002F05.data-visualization\u002Findex",[3711,3712,3716,3720,3724,3728],{"title":3707,"path":3708,"stem":3709},{"title":3713,"path":3714,"stem":3715},"Основи matplotlib — Figure, Axes та перший графік","\u002Fai-python\u002Fdata-visualization\u002Fmatplotlib-basics","16.ai-python\u002F05.data-visualization\u002F01.matplotlib-basics",{"title":3717,"path":3718,"stem":3719},"Візуалізація розподілів — гістограми та box plots","\u002Fai-python\u002Fdata-visualization\u002Fdistributions","16.ai-python\u002F05.data-visualization\u002F02.distributions",{"title":3721,"path":3722,"stem":3723},"Візуалізація залежностей — scatter plots та кореляція","\u002Fai-python\u002Fdata-visualization\u002Frelationships","16.ai-python\u002F05.data-visualization\u002F03.relationships",{"title":3725,"path":3726,"stem":3727},"Візуалізація категоріальних даних — bar charts та pie charts","\u002Fai-python\u002Fdata-visualization\u002Fcategorical","16.ai-python\u002F05.data-visualization\u002F04.categorical",{"title":3729,"path":3730,"stem":3731},"Композиції та стилізація — subplots та багатопанельні дашборди","\u002Fai-python\u002Fdata-visualization\u002Fsubplots-styling","16.ai-python\u002F05.data-visualization\u002F05.subplots-styling",{"title":3733,"path":3734,"stem":3735,"children":3736,"page":59},"Linear Regression","\u002Fai-python\u002Flinear-regression","16.ai-python\u002F06.linear-regression",[3737,3741,3745,3749,3753],{"title":3738,"path":3739,"stem":3740},"Регресійна задача та лінійна регресія з однією змінною","\u002Fai-python\u002Flinear-regression\u002Fregression-task","16.ai-python\u002F06.linear-regression\u002F01.regression-task",{"title":3742,"path":3743,"stem":3744},"Метрики якості регресії — як оцінити модель","\u002Fai-python\u002Flinear-regression\u002Fquality-metrics","16.ai-python\u002F06.linear-regression\u002F02.quality-metrics",{"title":3746,"path":3747,"stem":3748},"Градієнтний спуск — як модель навчається","\u002Fai-python\u002Flinear-regression\u002Fgradient-descent","16.ai-python\u002F06.linear-regression\u002F03.gradient-descent",{"title":3750,"path":3751,"stem":3752},"Множинна лінійна регресія — модель з багатьма ознаками","\u002Fai-python\u002Flinear-regression\u002Fmultiple-regression","16.ai-python\u002F06.linear-regression\u002F04.multiple-regression",{"title":3754,"path":3755,"stem":3756},"Практичні завдання та резюме модуля","\u002Fai-python\u002Flinear-regression\u002Fpractice","16.ai-python\u002F06.linear-regression\u002F05.practice",{"title":3758,"path":3759,"stem":3760,"children":3761,"page":59},"Practical Regression","\u002Fai-python\u002Fpractical-regression","16.ai-python\u002F07.practical-regression",[3762,3766,3770,3774,3778,3782,3786],{"title":3763,"path":3764,"stem":3765},"Знайомство з scikit-learn","\u002Fai-python\u002Fpractical-regression\u002Fintro-scikit-learn","16.ai-python\u002F07.practical-regression\u002F01.intro-scikit-learn",{"title":3767,"path":3768,"stem":3769},"Exploratory Data Analysis датасету Housing Prices","\u002Fai-python\u002Fpractical-regression\u002Fhousing-dataset-eda","16.ai-python\u002F07.practical-regression\u002F02.housing-dataset-eda",{"title":3771,"path":3772,"stem":3773},"Попередня обробка даних (Data Preprocessing)","\u002Fai-python\u002Fpractical-regression\u002Fdata-preprocessing","16.ai-python\u002F07.practical-regression\u002F03.data-preprocessing",{"title":3775,"path":3776,"stem":3777},"Train\u002FTest Split та перша повноцінна модель","\u002Fai-python\u002Fpractical-regression\u002Ftrain-test-split","16.ai-python\u002F07.practical-regression\u002F04.train-test-split",{"title":3779,"path":3780,"stem":3781},"Перенавчання та недонавчання","\u002Fai-python\u002Fpractical-regression\u002Foverfitting-underfitting","16.ai-python\u002F07.practical-regression\u002F05.overfitting-underfitting",{"title":3783,"path":3784,"stem":3785},"Крос-валідація (Cross-Validation)","\u002Fai-python\u002Fpractical-regression\u002Fcross-validation","16.ai-python\u002F07.practical-regression\u002F06.cross-validation",{"title":3787,"path":3788,"stem":3789},"Гіперпараметри та їх оптимізація","\u002Fai-python\u002Fpractical-regression\u002Fhyperparameter-tuning","16.ai-python\u002F07.practical-regression\u002F07.hyperparameter-tuning",{"title":3791,"path":3792,"stem":3793,"children":3794,"page":59},"Polynomial Regression","\u002Fai-python\u002Fpolynomial-regression","16.ai-python\u002F08.polynomial-regression",[3795,3799,3803],{"title":3796,"path":3797,"stem":3798},"Нелінійні залежності та поліноміальна регресія","\u002Fai-python\u002Fpolynomial-regression\u002Fnonlinear-patterns","16.ai-python\u002F08.polynomial-regression\u002F01.nonlinear-patterns",{"title":3800,"path":3801,"stem":3802},"Регуляризація в регресії — Ridge та Lasso","\u002Fai-python\u002Fpolynomial-regression\u002Fregularization-methods","16.ai-python\u002F08.polynomial-regression\u002F02.regularization-methods",{"title":3804,"path":3805,"stem":3806},"Практика — поліноміальна регресія та регуляризація на Housing Prices","\u002Fai-python\u002Fpolynomial-regression\u002Fhousing-prices-practice","16.ai-python\u002F08.polynomial-regression\u002F03.housing-prices-practice",{"title":3808,"path":3809,"stem":3810,"children":3811,"page":59},"Decision Trees Random Forest","\u002Fai-python\u002Fdecision-trees-random-forest","16.ai-python\u002F09.decision-trees-random-forest",[3812,3816],{"title":3813,"path":3814,"stem":3815},"Дерева рішень — інтерпретабельні моделі машинного навчання","\u002Fai-python\u002Fdecision-trees-random-forest\u002Fdecision-trees","16.ai-python\u002F09.decision-trees-random-forest\u002F01.decision-trees",{"title":3817,"path":3818,"stem":3819},"Random Forest — ансамблі дерев рішень","\u002Fai-python\u002Fdecision-trees-random-forest\u002Frandom-forest","16.ai-python\u002F09.decision-trees-random-forest\u002F02.random-forest",{"title":3821,"path":3822,"stem":3823,"children":3824,"page":59},"Gradient Boosting","\u002Fai-python\u002Fgradient-boosting","16.ai-python\u002F10.gradient-boosting",[3825],{"title":3826,"path":3827,"stem":3828},"Градієнтний бустинг та XGBoost — послідовне виправлення помилок","\u002Fai-python\u002Fgradient-boosting\u002Fgradient-boosting-xgboost","16.ai-python\u002F10.gradient-boosting\u002F01.gradient-boosting-xgboost",{"title":3830,"path":3831,"stem":3832,"children":3833,"page":59},"Logistic Regression Classification","\u002Fai-python\u002Flogistic-regression-classification","16.ai-python\u002F11.logistic-regression-classification",[3834,3838],{"title":3835,"path":3836,"stem":3837},"Вступ до класифікації та логістична регресія","\u002Fai-python\u002Flogistic-regression-classification\u002Fclassification-basics","16.ai-python\u002F11.logistic-regression-classification\u002F01.classification-basics",{"title":3839,"path":3840,"stem":3841},"Метрики якості класифікації — Confusion Matrix, Precision, Recall, F1","\u002Fai-python\u002Flogistic-regression-classification\u002Fclassification-metrics","16.ai-python\u002F11.logistic-regression-classification\u002F02.classification-metrics",{"title":3843,"path":3844,"stem":3845,"children":3846,"page":59},"Neural Networks Basics","\u002Fai-python\u002Fneural-networks-basics","16.ai-python\u002F12.neural-networks-basics",[3847],{"title":3848,"path":3849,"stem":3850},"Вступ до нейронних мереж — від персептрона до багатошарових мереж","\u002Fai-python\u002Fneural-networks-basics\u002Fperceptron-to-mlp","16.ai-python\u002F12.neural-networks-basics\u002F01.perceptron-to-mlp",{"title":3852,"path":3853,"stem":3854,"children":3855,"page":59},"Pytorch Intro","\u002Fai-python\u002Fpytorch-intro","16.ai-python\u002F13.pytorch-intro",[3856,3860,3864,3868],{"title":3857,"path":3858,"stem":3859},"Тензори та автоматичне диференціювання в PyTorch","\u002Fai-python\u002Fpytorch-intro\u002Ftensors-and-autograd","16.ai-python\u002F13.pytorch-intro\u002F01.tensors-and-autograd",{"title":3861,"path":3862,"stem":3863},"Побудова та тренування нейронних мереж у PyTorch","\u002Fai-python\u002Fpytorch-intro\u002Fbuilding-and-training","16.ai-python\u002F13.pytorch-intro\u002F02.building-and-training",{"title":3865,"path":3866,"stem":3867},"Робота з даними та регуляризація в PyTorch","\u002Fai-python\u002Fpytorch-intro\u002Fdata-and-regularization","16.ai-python\u002F13.pytorch-intro\u002F03.data-and-regularization",{"title":3869,"path":3870,"stem":3871},"Просунуті теми PyTorch — GPU, оптимізація та deployment","\u002Fai-python\u002Fpytorch-intro\u002Fadvanced-topics","16.ai-python\u002F13.pytorch-intro\u002F04.advanced-topics",{"title":3873,"path":3874,"stem":3875,"children":3876,"page":59},"Activation Functions Heart Disease","\u002Fai-python\u002Factivation-functions-heart-disease","16.ai-python\u002F14.activation-functions-heart-disease",[3877,3881],{"title":3878,"path":3879,"stem":3880},"Функції активації та побудова нейронної мережі для передбачення вад серця","\u002Fai-python\u002Factivation-functions-heart-disease\u002Fheart-disease-prediction","16.ai-python\u002F14.activation-functions-heart-disease\u002F01.heart-disease-prediction",{"title":3882,"path":3883,"stem":3884},"Бонус — Повний приклад Student Performance Prediction","\u002Fai-python\u002Factivation-functions-heart-disease\u002Fstudent-performance-bonus","16.ai-python\u002F14.activation-functions-heart-disease\u002F02.student-performance-bonus",{"title":3886,"path":3887,"stem":3888,"children":3889,"page":59},"Cnn Image Classification","\u002Fai-python\u002Fcnn-image-classification","16.ai-python\u002F15.cnn-image-classification",[3890,3894,3898,3902],{"title":3891,"path":3892,"stem":3893},"Основи згорткових нейронних мереж — чому не MLP?","\u002Fai-python\u002Fcnn-image-classification\u002Fcnn-fundamentals","16.ai-python\u002F15.cnn-image-classification\u002F01.cnn-fundamentals",{"title":3895,"path":3896,"stem":3897},"Практична імплементація CNN для класифікації MNIST","\u002Fai-python\u002Fcnn-image-classification\u002Fmnist-classification","16.ai-python\u002F15.cnn-image-classification\u002F02.mnist-classification",{"title":3899,"path":3900,"stem":3901},"Глибші CNN та аугментація даних для CIFAR-10","\u002Fai-python\u002Fcnn-image-classification\u002Fcifar10-and-data-augmentation","16.ai-python\u002F15.cnn-image-classification\u002F03.cifar10-and-data-augmentation",{"title":3903,"path":3904,"stem":3905},"Transfer Learning та візуалізація внутрішніх представлень CNN","\u002Fai-python\u002Fcnn-image-classification\u002Ftransfer-learning-and-visualization","16.ai-python\u002F15.cnn-image-classification\u002F04.transfer-learning-and-visualization",{"title":3907,"path":3908,"stem":3909,"children":3910,"page":59},"Batching Normalization Deep Networks","\u002Fai-python\u002Fbatching-normalization-deep-networks","16.ai-python\u002F16.batching-normalization-deep-networks",[3911,3915,3919,3923,3927,3931,3935],{"title":3912,"path":3913,"stem":3914},"Mini-batch Gradient Descent та ефективна обробка даних","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fmini-batch-gradient-descent","16.ai-python\u002F16.batching-normalization-deep-networks\u002F01.mini-batch-gradient-descent",{"title":3916,"path":3917,"stem":3918},"Ініціалізація ваг — фундамент стабільного навчання","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fweight-initialization","16.ai-python\u002F16.batching-normalization-deep-networks\u002F02.weight-initialization",{"title":3920,"path":3921,"stem":3922},"Batch Normalization — прорив у глибокому навчанні","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fbatch-normalization","16.ai-python\u002F16.batching-normalization-deep-networks\u002F03.batch-normalization",{"title":3924,"path":3925,"stem":3926},"Dropout та комбіновані стратегії регуляризації","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fdropout-and-regularization","16.ai-python\u002F16.batching-normalization-deep-networks\u002F04.dropout-and-regularization",{"title":3928,"path":3929,"stem":3930},"Проєктування глибоких мереж — від теорії до практики","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fdeep-networks-architectures","16.ai-python\u002F16.batching-normalization-deep-networks\u002F05.deep-networks-architectures",{"title":3932,"path":3933,"stem":3934},"Планування learning rate — коли та як зменшувати крок навчання","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Flearning-rate-scheduling","16.ai-python\u002F16.batching-normalization-deep-networks\u002F06.learning-rate-scheduling",{"title":3936,"path":3937,"stem":3938},"Підсумковий проєкт — побудова сучасного класифікатора зображень","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Ffinal-project-deep-classifier","16.ai-python\u002F16.batching-normalization-deep-networks\u002F07.final-project-deep-classifier",{"title":3940,"icon":658,"path":3941,"stem":3942,"children":3943,"page":59},"Клієнт-серверна архітектура","\u002Fclient-server-architecture","17.client-server-architecture",[3944,3948,3952,3956,3960,3964,3968,3972,3976,3980,3984,3988,3992,3996,4000,4004,4008,4012],{"title":3945,"path":3946,"stem":3947},"Архітектура клієнт-серверних систем та основи Go","\u002Fclient-server-architecture\u002Fclient-server-architecture-and-go","17.client-server-architecture\u002F01.client-server-architecture-and-go",{"title":3949,"path":3950,"stem":3951},"Система типів та модель пам’яті мови Go","\u002Fclient-server-architecture\u002Ftype-system-and-memory-model","17.client-server-architecture\u002F02.type-system-and-memory-model",{"title":3953,"path":3954,"stem":3955},"Інтерфейси та модель конкурентності мови Go","\u002Fclient-server-architecture\u002Finterfaces-and-concurrency-model","17.client-server-architecture\u002F03.interfaces-and-concurrency-model",{"title":3957,"path":3958,"stem":3959},"Сокетне програмування та протокол TCP у Go","\u002Fclient-server-architecture\u002Ftcp-socket-programming","17.client-server-architecture\u002F04.tcp-socket-programming",{"title":3961,"path":3962,"stem":3963},"Протокол UDP та датаграмна передача даних","\u002Fclient-server-architecture\u002Fudp-datagram-transmission","17.client-server-architecture\u002F05.udp-datagram-transmission",{"title":3965,"path":3966,"stem":3967},"Криптографічний захист каналів зв","\u002Fclient-server-architecture\u002Ftls-cryptographic-channel-protection","17.client-server-architecture\u002F06.tls-cryptographic-channel-protection",{"title":3969,"path":3970,"stem":3971},"Прикладні мережеві протоколи DNS та SMTP","\u002Fclient-server-architecture\u002Fdns-smtp-application-protocols","17.client-server-architecture\u002F07.dns-smtp-application-protocols",{"title":3973,"path":3974,"stem":3975},"Протокол HTTP та стандартний вебсервер Go","\u002Fclient-server-architecture\u002Fhttp-protocol-and-web-server","17.client-server-architecture\u002F08.http-protocol-and-web-server",{"title":3977,"path":3978,"stem":3979},"Проєктування REST API та маршрутизація засобами Chi","\u002Fclient-server-architecture\u002Frest-api-design-and-chi-routing","17.client-server-architecture\u002F09.rest-api-design-and-chi-routing",{"title":3981,"path":3982,"stem":3983},"Лекція 10. Шарувата архітектура та конвеєри обробки запитів","\u002Fclient-server-architecture\u002Flayered-architecture-and-middleware-pipelines","17.client-server-architecture\u002F10.layered-architecture-and-middleware-pipelines",{"title":3985,"path":3986,"stem":3987},"Лекція 11. Архітектура та маршрутизація фреймворку Gin","\u002Fclient-server-architecture\u002Fgin-framework-architecture-and-routing","17.client-server-architecture\u002F11.gin-framework-architecture-and-routing",{"title":3989,"path":3990,"stem":3991},"Лекція 12. Валідація даних, безпека та документування у Gin","\u002Fclient-server-architecture\u002Fdata-validation-security-and-documentation-in-gin","17.client-server-architecture\u002F12.data-validation-security-and-documentation-in-gin",{"title":3993,"path":3994,"stem":3995},"Лекція 13. Взаємодія з реляційними СУБД та технології ORM","\u002Fclient-server-architecture\u002Frelational-databases-and-orm","17.client-server-architecture\u002F13.relational-databases-and-orm",{"title":3997,"path":3998,"stem":3999},"Потокова передача даних та протокол WebSocket","\u002Fclient-server-architecture\u002Fstreaming-data-and-websockets","17.client-server-architecture\u002F14.streaming-data-and-websockets",{"title":4001,"path":4002,"stem":4003},"Міжсервісна взаємодія на основі протоколу gRPC","\u002Fclient-server-architecture\u002Fgrpc-inter-service-communication","17.client-server-architecture\u002F15.grpc-inter-service-communication",{"title":4005,"path":4006,"stem":4007},"Асинхронний обмін повідомленнями та протоколи черг","\u002Fclient-server-architecture\u002Fasynchronous-message-exchange-and-queue-protocols","17.client-server-architecture\u002F16.asynchronous-message-exchange-and-queue-protocols",{"title":4009,"path":4010,"stem":4011},"Протоколи потокового медіа та технологія WebRTC","\u002Fclient-server-architecture\u002Fstreaming-media-protocols-and-webrtc","17.client-server-architecture\u002F17.streaming-media-protocols-and-webrtc",{"title":4013,"path":4014,"stem":4015},"Моніторинг, безпека та контейнеризація застосунків","\u002Fclient-server-architecture\u002Fmonitoring-security-and-containerization","17.client-server-architecture\u002F18.monitoring-security-and-containerization",{"title":4017,"icon":2074,"path":4018,"stem":4019,"children":4020,"page":59},"Розробка WEB-застосувань","\u002Fweb-development","18.web-development",[4021,4066,4104,4133,4162,4219,4269,4363,4429,4511,4544,4572,4614,4660,4703],{"title":4022,"icon":658,"path":4023,"stem":4024,"children":4025,"page":59},"Архітектура комп'ютерних мереж та мережеві протоколи","\u002Fweb-development\u002Fnetwork-architecture-and-protocols","18.web-development\u002F01.network-architecture-and-protocols",[4026,4030,4034,4038,4042,4046,4050,4054,4058,4062],{"title":4027,"path":4028,"stem":4029},"Еволюція веброзробки та модель клієнт-сервер","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fweb-evolution-client-server","18.web-development\u002F01.network-architecture-and-protocols\u002F01.web-evolution-client-server",{"title":4031,"path":4032,"stem":4033},"Еталонна модель OSI","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fosi-model","18.web-development\u002F01.network-architecture-and-protocols\u002F02.osi-model",{"title":4035,"path":4036,"stem":4037},"Стек протоколів TCP\u002FIP","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Ftcp-ip-stack","18.web-development\u002F01.network-architecture-and-protocols\u002F03.tcp-ip-stack",{"title":4039,"path":4040,"stem":4041},"IP-адресація, порти та сокети","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fip-addressing-ports-sockets","18.web-development\u002F01.network-architecture-and-protocols\u002F04.ip-addressing-ports-sockets",{"title":4043,"path":4044,"stem":4045},"Протоколи TCP та UDP","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Ftcp-udp-protocols","18.web-development\u002F01.network-architecture-and-protocols\u002F05.tcp-udp-protocols",{"title":4047,"path":4048,"stem":4049},"Система доменних імен DNS","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fdns-system","18.web-development\u002F01.network-architecture-and-protocols\u002F06.dns-system",{"title":4051,"path":4052,"stem":4053},"Протокол SMTP та поштові протоколи","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fsmtp-email-protocols","18.web-development\u002F01.network-architecture-and-protocols\u002F07.smtp-email-protocols",{"title":4055,"path":4056,"stem":4057},"Протокол WebSocket","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fwebsocket-protocol","18.web-development\u002F01.network-architecture-and-protocols\u002F08.websocket-protocol",{"title":4059,"path":4060,"stem":4061},"Протокол SSH","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fssh-protocol","18.web-development\u002F01.network-architecture-and-protocols\u002F09.ssh-protocol",{"title":4063,"path":4064,"stem":4065},"Огляд сучасних серверних технологій","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fmodern-backend-technologies","18.web-development\u002F01.network-architecture-and-protocols\u002F10.modern-backend-technologies",{"title":4067,"icon":4068,"path":4069,"stem":4070,"children":4071,"page":59},"Протокол HTTP та захищена передача даних HTTPS","i-lucide-lock","\u002Fweb-development\u002Fhttp-and-https","18.web-development\u002F02.http-and-https",[4072,4076,4080,4084,4088,4092,4096,4100],{"title":4073,"path":4074,"stem":4075},"Вступ до протоколу HTTP та еволюція веб-технологій","\u002Fweb-development\u002Fhttp-and-https\u002Fintroduction-and-evolution","18.web-development\u002F02.http-and-https\u002F01.introduction-and-evolution",{"title":4077,"path":4078,"stem":4079},"Анатомія HTTP-запиту","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-request-structure","18.web-development\u002F02.http-and-https\u002F02.http-request-structure",{"title":4081,"path":4082,"stem":4083},"Анатомія HTTP-відповіді","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-response-structure","18.web-development\u002F02.http-and-https\u002F03.http-response-structure",{"title":4085,"path":4086,"stem":4087},"Методи HTTP та їхня семантика","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-methods","18.web-development\u002F02.http-and-https\u002F04.http-methods",{"title":4089,"path":4090,"stem":4091},"Коди статусу HTTP та їхнє призначення","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-status-codes","18.web-development\u002F02.http-and-https\u002F05.http-status-codes",{"title":4093,"path":4094,"stem":4095},"HTTP-заголовки та їхнє призначення","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-headers","18.web-development\u002F02.http-and-https\u002F06.http-headers",{"title":4097,"path":4098,"stem":4099},"CORS та механізми безпеки HTTP","\u002Fweb-development\u002Fhttp-and-https\u002Fcors-and-security","18.web-development\u002F02.http-and-https\u002F07.cors-and-security",{"title":4101,"path":4102,"stem":4103},"HTTPS та криптографічні основи TLS","\u002Fweb-development\u002Fhttp-and-https\u002Fhttps-and-tls","18.web-development\u002F02.http-and-https\u002F08.https-and-tls",{"title":4105,"icon":2454,"path":4106,"stem":4107,"children":4108,"page":59},"Система типів мови TypeScript","\u002Fweb-development\u002Ftypescript-type-system","18.web-development\u002F03.typescript-type-system",[4109,4113,4117,4121,4125,4129],{"title":4110,"path":4111,"stem":4112},"Знайомство з TypeScript Compiler","\u002Fweb-development\u002Ftypescript-type-system\u002Fintroduction-compiler-config","18.web-development\u002F03.typescript-type-system\u002F01.introduction-compiler-config",{"title":4114,"path":4115,"stem":4116},"Примітивні типи даних: string, number, boolean","\u002Fweb-development\u002Ftypescript-type-system\u002Fprimitive-special-types","18.web-development\u002F03.typescript-type-system\u002F02.primitive-special-types",{"title":4118,"path":4119,"stem":4120},"Масиви, кортежі та об","\u002Fweb-development\u002Ftypescript-type-system\u002Farrays-tuples-objects","18.web-development\u002F03.typescript-type-system\u002F03.arrays-tuples-objects",{"title":4122,"path":4123,"stem":4124},"Псевдоніми типів, Union типи, Intersection типи та літеральні типи","\u002Fweb-development\u002Ftypescript-type-system\u002Funion-intersection-literals","18.web-development\u002F03.typescript-type-system\u002F04.union-intersection-literals",{"title":4126,"path":4127,"stem":4128},"Type Narrowing (звуження типів)","\u002Fweb-development\u002Ftypescript-type-system\u002Ftype-narrowing","18.web-development\u002F03.typescript-type-system\u002F05.type-narrowing",{"title":4130,"path":4131,"stem":4132},"Типізація функцій","\u002Fweb-development\u002Ftypescript-type-system\u002Ffunctions-typing","18.web-development\u002F03.typescript-type-system\u002F06.functions-typing",{"title":4134,"icon":2454,"path":4135,"stem":4136,"children":4137,"page":59},"Розширені засоби мови TypeScript","\u002Fweb-development\u002Ftypescript-advanced","18.web-development\u002F04.typescript-advanced",[4138,4142,4146,4150,4154,4158],{"title":4139,"path":4140,"stem":4141},"Interfaces та Classes","\u002Fweb-development\u002Ftypescript-advanced\u002Finterfaces-classes","18.web-development\u002F04.typescript-advanced\u002F01.interfaces-classes",{"title":4143,"path":4144,"stem":4145},"Основи Generic типів","\u002Fweb-development\u002Ftypescript-advanced\u002Fgenerics-fundamentals","18.web-development\u002F04.typescript-advanced\u002F02.generics-fundamentals",{"title":4147,"path":4148,"stem":4149},"Enums та Decorators","\u002Fweb-development\u002Ftypescript-advanced\u002Fenums-decorators","18.web-development\u002F04.typescript-advanced\u002F03.enums-decorators",{"title":4151,"path":4152,"stem":4153},"Utility Types","\u002Fweb-development\u002Ftypescript-advanced\u002Futility-types","18.web-development\u002F04.typescript-advanced\u002F04.utility-types",{"title":4155,"path":4156,"stem":4157},"Mapped та Conditional Types","\u002Fweb-development\u002Ftypescript-advanced\u002Fmapped-conditional-types","18.web-development\u002F04.typescript-advanced\u002F05.mapped-conditional-types",{"title":4159,"path":4160,"stem":4161},"Модулі та Strict Mode","\u002Fweb-development\u002Ftypescript-advanced\u002Fmodules-strict-mode","18.web-development\u002F04.typescript-advanced\u002F06.modules-strict-mode",{"title":4163,"icon":4164,"path":4165,"stem":4166,"children":4167,"page":59},"Платформа Node.js як середовище виконання","i-devicon-nodejs","\u002Fweb-development\u002Fnodejs-platform","18.web-development\u002F05.nodejs-platform",[4168,4172,4176,4180,4184,4188,4192,4196,4200,4204,4208,4211,4215],{"title":4169,"path":4170,"stem":4171},"Що таке Node.js та його архітектура","\u002Fweb-development\u002Fnodejs-platform\u002Fwhat-is-nodejs","18.web-development\u002F05.nodejs-platform\u002F01.what-is-nodejs",{"title":4173,"path":4174,"stem":4175},"Event Loop — серце Node.js","\u002Fweb-development\u002Fnodejs-platform\u002Fevent-loop","18.web-development\u002F05.nodejs-platform\u002F02.event-loop",{"title":4177,"path":4178,"stem":4179},"Модульні системи: CommonJS vs ES Modules","\u002Fweb-development\u002Fnodejs-platform\u002Fmodule-systems","18.web-development\u002F05.nodejs-platform\u002F03.module-systems",{"title":4181,"path":4182,"stem":4183},"npm та package.json","\u002Fweb-development\u002Fnodejs-platform\u002Fnpm-package-json","18.web-development\u002F05.nodejs-platform\u002F04.npm-package-json",{"title":4185,"path":4186,"stem":4187},"Глобальні об\\","\u002Fweb-development\u002Fnodejs-platform\u002Fglobal-objects","18.web-development\u002F05.nodejs-platform\u002F05.global-objects",{"title":4189,"path":4190,"stem":4191},"Вбудований модуль fs (File System)","\u002Fweb-development\u002Fnodejs-platform\u002Fbuilt-in-modules-fs","18.web-development\u002F05.nodejs-platform\u002F06.built-in-modules-fs",{"title":4193,"path":4194,"stem":4195},"Вбудований модуль path","\u002Fweb-development\u002Fnodejs-platform\u002Fbuilt-in-modules-path","18.web-development\u002F05.nodejs-platform\u002F07.built-in-modules-path",{"title":4197,"path":4198,"stem":4199},"Вбудований модуль http","\u002Fweb-development\u002Fnodejs-platform\u002Fbuilt-in-modules-http","18.web-development\u002F05.nodejs-platform\u002F08.built-in-modules-http",{"title":4201,"path":4202,"stem":4203},"Streams — потоки даних у Node.js","\u002Fweb-development\u002Fnodejs-platform\u002Fstreams","18.web-development\u002F05.nodejs-platform\u002F09.streams",{"title":4205,"path":4206,"stem":4207},"Вбудований модуль util (Utilities)","\u002Fweb-development\u002Fnodejs-platform\u002Fbuilt-in-modules-util","18.web-development\u002F05.nodejs-platform\u002F10.built-in-modules-util",{"title":3097,"path":4209,"stem":4210},"\u002Fweb-development\u002Fnodejs-platform\u002Fenvironment-variables","18.web-development\u002F05.nodejs-platform\u002F11.environment-variables",{"title":4212,"path":4213,"stem":4214},"Інструменти налагодження та розробки","\u002Fweb-development\u002Fnodejs-platform\u002Fdebugging-tools","18.web-development\u002F05.nodejs-platform\u002F12.debugging-tools",{"title":4216,"path":4217,"stem":4218},"Продуктивність та Best Practices","\u002Fweb-development\u002Fnodejs-platform\u002Fperformance-best-practices","18.web-development\u002F05.nodejs-platform\u002F13.performance-best-practices",{"title":4220,"icon":4221,"path":4222,"stem":4223,"children":4224,"page":59},"Асинхронне програмування у Node.js","i-lucide-clock","\u002Fweb-development\u002Fasync-programming-nodejs","18.web-development\u002F06.async-programming-nodejs",[4225,4229,4233,4237,4241,4245,4249,4253,4257,4261,4265],{"title":4226,"path":4227,"stem":4228},"Синхронний vs асинхронний код","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fsync-vs-async","18.web-development\u002F06.async-programming-nodejs\u002F01.sync-vs-async",{"title":4230,"path":4231,"stem":4232},"Callbacks — перша парадигма асинхронності","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fcallbacks","18.web-development\u002F06.async-programming-nodejs\u002F02.callbacks",{"title":4234,"path":4235,"stem":4236},"Promises — стандарт асинхронності","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fpromises","18.web-development\u002F06.async-programming-nodejs\u002F03.promises",{"title":4238,"path":4239,"stem":4240},"Promise комбінатори","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fpromise-combinators","18.web-development\u002F06.async-programming-nodejs\u002F04.promise-combinators",{"title":4242,"path":4243,"stem":4244},"Async\u002FAwait — синтаксичний цукор над Promises","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fasync-await","18.web-development\u002F06.async-programming-nodejs\u002F05.async-await",{"title":4246,"path":4247,"stem":4248},"Паралельне vs послідовне виконання","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fparallel-vs-sequential","18.web-development\u002F06.async-programming-nodejs\u002F06.parallel-vs-sequential",{"title":4250,"path":4251,"stem":4252},"EventEmitter — подієва модель Node.js","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fevent-emitter","18.web-development\u002F06.async-programming-nodejs\u002F07.event-emitter",{"title":4254,"path":4255,"stem":4256},"Worker Threads — багатопотоковість у Node.js","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fworker-threads","18.web-development\u002F06.async-programming-nodejs\u002F08.worker-threads",{"title":4258,"path":4259,"stem":4260},"Child Processes — запуск зовнішніх процесів","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fchild-processes","18.web-development\u002F06.async-programming-nodejs\u002F09.child-processes",{"title":4262,"path":4263,"stem":4264},"Обробка помилок у асинхронному коді","\u002Fweb-development\u002Fasync-programming-nodejs\u002Ferror-handling","18.web-development\u002F06.async-programming-nodejs\u002F10.error-handling",{"title":4266,"path":4267,"stem":4268},"Порівняння Node.js фреймворків","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fnodejs-frameworks","18.web-development\u002F06.async-programming-nodejs\u002F11.nodejs-frameworks",{"title":4270,"icon":4271,"path":4272,"stem":4273,"children":4274,"page":59},"Тема 7. Фреймворк NestJS. Контролери та маршрутизація","i-lucide-route","\u002Fweb-development\u002Fnestjs-controllers-routing","18.web-development\u002F07.nestjs-controllers-routing",[4275,4279,4283,4287,4291,4295,4299,4303,4307,4311,4315,4319,4323,4327,4331,4335,4339,4343,4347,4351,4355,4359],{"title":4276,"path":4277,"stem":4278},"Філософія та архітектура NestJS","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fnestjs-philosophy","18.web-development\u002F07.nestjs-controllers-routing\u002F01.nestjs-philosophy",{"title":4280,"path":4281,"stem":4282},"Три стовпи архітектури: модулі, контролери, провайдери","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fthree-pillars","18.web-development\u002F07.nestjs-controllers-routing\u002F02.three-pillars",{"title":4284,"path":4285,"stem":4286},"Інверсія керування (IoC) та ін","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fioc-and-di","18.web-development\u002F07.nestjs-controllers-routing\u002F03.ioc-and-di",{"title":4288,"path":4289,"stem":4290},"Встановлення NestJS CLI та створення проєкту","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fnestjs-cli-setup","18.web-development\u002F07.nestjs-controllers-routing\u002F04.nestjs-cli-setup",{"title":4292,"path":4293,"stem":4294},"Структура проєкту NestJS та конвенції","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fproject-structure","18.web-development\u002F07.nestjs-controllers-routing\u002F05.project-structure",{"title":4296,"path":4297,"stem":4298},"Контролери: основи маршрутизації","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fcontrollers-basics","18.web-development\u002F07.nestjs-controllers-routing\u002F06.controllers-basics",{"title":4300,"path":4301,"stem":4302},"Декоратори маршрутизації HTTP-методів","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Froute-decorators","18.web-development\u002F07.nestjs-controllers-routing\u002F07.route-decorators",{"title":4304,"path":4305,"stem":4306},"Параметри маршруту та декоратор @Param","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Froute-parameters","18.web-development\u002F07.nestjs-controllers-routing\u002F08.route-parameters",{"title":4308,"path":4309,"stem":4310},"Query-параметри та декоратор @Query","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fquery-parameters","18.web-development\u002F07.nestjs-controllers-routing\u002F09.query-parameters",{"title":4312,"path":4313,"stem":4314},"Тіло запиту та декоратор @Body","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Frequest-body","18.web-development\u002F07.nestjs-controllers-routing\u002F10.request-body",{"title":4316,"path":4317,"stem":4318},"Робота з заголовками запиту та відповіді","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fheaders-decorators","18.web-development\u002F07.nestjs-controllers-routing\u002F11.headers-decorators",{"title":4320,"path":4321,"stem":4322},"Data Transfer Objects (DTO): визначення та призначення","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fdto-introduction","18.web-development\u002F07.nestjs-controllers-routing\u002F12.dto-introduction",{"title":4324,"path":4325,"stem":4326},"Об'єкти Request та Response","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Frequest-response-objects","18.web-development\u002F07.nestjs-controllers-routing\u002F13.request-response-objects",{"title":4328,"path":4329,"stem":4330},"HTTP-статус коди та декоратор @HttpCode","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fhttp-status-codes","18.web-development\u002F07.nestjs-controllers-routing\u002F14.http-status-codes",{"title":4332,"path":4333,"stem":4334},"Перенаправлення (Redirects) та декоратор @Redirect","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fredirects","18.web-development\u002F07.nestjs-controllers-routing\u002F15.redirects",{"title":4336,"path":4337,"stem":4338},"Асинхронні обробники та Observables","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fasync-handlers","18.web-development\u002F07.nestjs-controllers-routing\u002F16.async-handlers",{"title":4340,"path":4341,"stem":4342},"Маршрутизація за піддоменами та версіонування API","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fsub-domain-routing","18.web-development\u002F07.nestjs-controllers-routing\u002F17.sub-domain-routing",{"title":4344,"path":4345,"stem":4346},"Області видимості контролерів (Scopes)","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fcontroller-scopes","18.web-development\u002F07.nestjs-controllers-routing\u002F18.controller-scopes",{"title":4348,"path":4349,"stem":4350},"Основні команди NestJS CLI","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fnestjs-cli-commands","18.web-development\u002F07.nestjs-controllers-routing\u002F19.nestjs-cli-commands",{"title":4352,"path":4353,"stem":4354},"Практичний приклад: створення CRUD-контролера","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fcrud-example","18.web-development\u002F07.nestjs-controllers-routing\u002F20.crud-example",{"title":4356,"path":4357,"stem":4358},"Тестування контролерів","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Ftesting-controllers","18.web-development\u002F07.nestjs-controllers-routing\u002F21.testing-controllers",{"title":4360,"path":4361,"stem":4362},"Best Practices для контролерів та маршрутизації","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fbest-practices","18.web-development\u002F07.nestjs-controllers-routing\u002F22.best-practices",{"title":4364,"icon":4365,"path":4366,"stem":4367,"children":4368,"page":59},"Тема 8. Провайдери, сервіси та модульна система NestJS","i-lucide-package","\u002Fweb-development\u002Fnestjs-providers-modules","18.web-development\u002F08.nestjs-providers-modules",[4369,4373,4377,4381,4385,4389,4393,4397,4401,4405,4409,4413,4417,4421,4425],{"title":4370,"path":4371,"stem":4372},"Концепція провайдерів у NestJS","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fproviders-concept","18.web-development\u002F08.nestjs-providers-modules\u002F01.providers-concept",{"title":4374,"path":4375,"stem":4376},"Сервіси: інкапсуляція бізнес-логіки","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fservices-business-logic","18.web-development\u002F08.nestjs-providers-modules\u002F02.services-business-logic",{"title":4378,"path":4379,"stem":4380},"Практика ін","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fdependency-injection-practice","18.web-development\u002F08.nestjs-providers-modules\u002F03.dependency-injection-practice",{"title":4382,"path":4383,"stem":4384},"Custom Providers: useValue, useClass, useFactory, useExisting","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fcustom-providers","18.web-development\u002F08.nestjs-providers-modules\u002F04.custom-providers",{"title":4386,"path":4387,"stem":4388},"Injection Tokens: рядкові та символьні токени","\u002Fweb-development\u002Fnestjs-providers-modules\u002Finjection-tokens","18.web-development\u002F08.nestjs-providers-modules\u002F05.injection-tokens",{"title":4390,"path":4391,"stem":4392},"Опціональні провайдери та декоратор @Optional","\u002Fweb-development\u002Fnestjs-providers-modules\u002Foptional-providers","18.web-development\u002F08.nestjs-providers-modules\u002F07.optional-providers",{"title":4394,"path":4395,"stem":4396},"Структура модулів: imports, controllers, providers, exports","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fmodules-structure","18.web-development\u002F08.nestjs-providers-modules\u002F08.modules-structure",{"title":4398,"path":4399,"stem":4400},"Feature Modules: ізоляція функціональності","\u002Fweb-development\u002Fnestjs-providers-modules\u002Ffeature-modules","18.web-development\u002F08.nestjs-providers-modules\u002F09.feature-modules",{"title":4402,"path":4403,"stem":4404},"Shared Modules: перевикористання провайдерів","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fshared-modules","18.web-development\u002F08.nestjs-providers-modules\u002F10.shared-modules",{"title":4406,"path":4407,"stem":4408},"Global Modules та декоратор @Global","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fglobal-modules","18.web-development\u002F08.nestjs-providers-modules\u002F11.global-modules",{"title":4410,"path":4411,"stem":4412},"Dynamic Modules: конфігурація під час виконання","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fdynamic-modules","18.web-development\u002F08.nestjs-providers-modules\u002F12.dynamic-modules",{"title":4414,"path":4415,"stem":4416},"Циклічні залежності та forwardRef","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fcircular-dependencies","18.web-development\u002F08.nestjs-providers-modules\u002F13.circular-dependencies",{"title":4418,"path":4419,"stem":4420},"Lifecycle Hooks: хуки життєвого циклу","\u002Fweb-development\u002Fnestjs-providers-modules\u002Flifecycle-hooks","18.web-development\u002F08.nestjs-providers-modules\u002F14.lifecycle-hooks",{"title":4422,"path":4423,"stem":4424},"ModuleRef: динамічний доступ до провайдерів","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fmodule-reference","18.web-development\u002F08.nestjs-providers-modules\u002F15.module-reference",{"title":4426,"path":4427,"stem":4428},"Тестування сервісів та провайдерів","\u002Fweb-development\u002Fnestjs-providers-modules\u002Ftesting-services","18.web-development\u002F08.nestjs-providers-modules\u002F16.testing-services",{"title":4430,"icon":4431,"path":4432,"stem":4433,"children":4434,"page":59},"Тема 9. Валідація даних та конвеєр обробки запитів у NestJS","i-lucide-filter","\u002Fweb-development\u002Fnestjs-validation-pipeline","18.web-development\u002F09.nestjs-validation-pipeline",[4435,4439,4443,4447,4451,4455,4459,4463,4467,4471,4475,4479,4483,4487,4491,4495,4499,4503,4507],{"title":4436,"path":4437,"stem":4438},"Request Pipeline: конвеєр обробки запитів","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Frequest-pipeline","18.web-development\u002F09.nestjs-validation-pipeline\u002F01.request-pipeline",{"title":4440,"path":4441,"stem":4442},"Pipes: концепція трансформації та валідації","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fpipes-concept","18.web-development\u002F09.nestjs-validation-pipeline\u002F02.pipes-concept",{"title":4444,"path":4445,"stem":4446},"Вбудовані pipes: ParseIntPipe, ParseBoolPipe, ParseUUIDPipe","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fbuilt-in-pipes","18.web-development\u002F09.nestjs-validation-pipeline\u002F03.built-in-pipes",{"title":4448,"path":4449,"stem":4450},"ValidationPipe: автоматична валідація DTO","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fvalidation-pipe","18.web-development\u002F09.nestjs-validation-pipeline\u002F04.validation-pipe",{"title":4452,"path":4453,"stem":4454},"Декоратори class-validator для DTO","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fclass-validator-decorators","18.web-development\u002F09.nestjs-validation-pipeline\u002F05.class-validator-decorators",{"title":4456,"path":4457,"stem":4458},"Створення кастомних валідаторів","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-validators","18.web-development\u002F09.nestjs-validation-pipeline\u002F06.custom-validators",{"title":4460,"path":4461,"stem":4462},"Створення власних Pipes","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-pipes","18.web-development\u002F09.nestjs-validation-pipeline\u002F07.custom-pipes",{"title":4464,"path":4465,"stem":4466},"Основи Middleware","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fmiddleware-basics","18.web-development\u002F09.nestjs-validation-pipeline\u002F08.middleware-basics",{"title":4468,"path":4469,"stem":4470},"Практичні приклади Middleware","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fmiddleware-examples","18.web-development\u002F09.nestjs-validation-pipeline\u002F09.middleware-examples",{"title":4472,"path":4473,"stem":4474},"Guards: захисні перехоплювачі доступу","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fguards-concept","18.web-development\u002F09.nestjs-validation-pipeline\u002F10.guards-concept",{"title":4476,"path":4477,"stem":4478},"Створення кастомних Guards","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-guards","18.web-development\u002F09.nestjs-validation-pipeline\u002F11.custom-guards",{"title":4480,"path":4481,"stem":4482},"Interceptors: перехоплення та трансформація відповідей","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Finterceptors-concept","18.web-development\u002F09.nestjs-validation-pipeline\u002F12.interceptors-concept",{"title":4484,"path":4485,"stem":4486},"Практичні приклади Interceptors","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Finterceptor-examples","18.web-development\u002F09.nestjs-validation-pipeline\u002F13.interceptor-examples",{"title":4488,"path":4489,"stem":4490},"Exception Filters: обробка виключень","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fexception-filters","18.web-development\u002F09.nestjs-validation-pipeline\u002F14.exception-filters",{"title":4492,"path":4493,"stem":4494},"Custom Exception Filters: спеціалізовані фільтри","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-exception-filters","18.web-development\u002F09.nestjs-validation-pipeline\u002F15.custom-exception-filters",{"title":4496,"path":4497,"stem":4498},"Execution Context: контекст виконання","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fexecution-context","18.web-development\u002F09.nestjs-validation-pipeline\u002F16.execution-context",{"title":4500,"path":4501,"stem":4502},"Custom Decorators: власні декоратори","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-decorators","18.web-development\u002F09.nestjs-validation-pipeline\u002F17.custom-decorators",{"title":4504,"path":4505,"stem":4506},"Global Components: глобальні компоненти","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fglobal-components","18.web-development\u002F09.nestjs-validation-pipeline\u002F18.global-components",{"title":4508,"path":4509,"stem":4510},"Pipeline Best Practices: найкращі практики","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fpipeline-best-practices","18.web-development\u002F09.nestjs-validation-pipeline\u002F19.pipeline-best-practices",{"title":4512,"icon":2821,"path":4513,"stem":4514,"children":4515,"page":59},"Інтеграція реляційних баз даних засобами TypeORM","\u002Fweb-development\u002Ftypeorm-integration","18.web-development\u002F10.typeorm-integration",[4516,4520,4524,4528,4532,4536,4540],{"title":4517,"path":4518,"stem":4519},"Робота з базами даних у Node.js через нативні драйвери","\u002Fweb-development\u002Ftypeorm-integration\u002F01-nodejs-database-drivers","18.web-development\u002F10.typeorm-integration\u002F01-nodejs-database-drivers",{"title":4521,"path":4522,"stem":4523},"ORM та знайомство з TypeORM","\u002Fweb-development\u002Ftypeorm-integration\u002F02-orm-and-typeorm-intro","18.web-development\u002F10.typeorm-integration\u002F02-orm-and-typeorm-intro",{"title":4525,"path":4526,"stem":4527},"Налаштування TypeORM у NestJS проєкті","\u002Fweb-development\u002Ftypeorm-integration\u002F03-typeorm-setup-nestjs","18.web-development\u002F10.typeorm-integration\u002F03-typeorm-setup-nestjs",{"title":4529,"path":4530,"stem":4531},"Entity класи та декоратори TypeORM","\u002Fweb-development\u002Ftypeorm-integration\u002F04-entities-and-decorators","18.web-development\u002F10.typeorm-integration\u002F04-entities-and-decorators",{"title":4533,"path":4534,"stem":4535},"Repository Pattern та CRUD операції","\u002Fweb-development\u002Ftypeorm-integration\u002F05-repository-pattern-crud","18.web-development\u002F10.typeorm-integration\u002F05-repository-pattern-crud",{"title":4537,"path":4538,"stem":4539},"Пагінація та фільтрація даних","\u002Fweb-development\u002Ftypeorm-integration\u002F06-pagination-filtering","18.web-development\u002F10.typeorm-integration\u002F06-pagination-filtering",{"title":4541,"path":4542,"stem":4543},"QueryBuilder для складних запитів","\u002Fweb-development\u002Ftypeorm-integration\u002F07-query-builder","18.web-development\u002F10.typeorm-integration\u002F07-query-builder",{"title":4545,"icon":4546,"path":4547,"stem":4548,"children":4549,"page":59},"Зв'язки між сутностями, міграції та оптимізація запитів","i-lucide-git-branch","\u002Fweb-development\u002Fentity-relations-migrations","18.web-development\u002F11.entity-relations-migrations",[4550,4554,4558,4562,4566],{"title":4551,"path":4552,"stem":4553},"Зв'язки One-to-Many та Many-to-One","\u002Fweb-development\u002Fentity-relations-migrations\u002F01-one-to-many-many-to-one","18.web-development\u002F11.entity-relations-migrations\u002F01-one-to-many-many-to-one",{"title":4555,"path":4556,"stem":4557},"Зв'язки One-to-One та Many-to-Many","\u002Fweb-development\u002Fentity-relations-migrations\u002F02-one-to-one-many-to-many","18.web-development\u002F11.entity-relations-migrations\u002F02-one-to-one-many-to-many",{"title":4559,"path":4560,"stem":4561},"Керування міграціями бази даних","\u002Fweb-development\u002Fentity-relations-migrations\u002F03-migrations-management","18.web-development\u002F11.entity-relations-migrations\u002F03-migrations-management",{"title":4563,"path":4564,"stem":4565},"Транзакції у TypeORM","\u002Fweb-development\u002Fentity-relations-migrations\u002F04-transactions","18.web-development\u002F11.entity-relations-migrations\u002F04-transactions",{"title":4567,"path":4568,"stem":4569,"children":4570},"Індекси та оптимізація запитів","\u002Fweb-development\u002Fentity-relations-migrations\u002F05-indexes-optimization","18.web-development\u002F11.entity-relations-migrations\u002F05-indexes-optimization",[4571],{"title":4567,"path":4568,"stem":4569},{"title":4573,"icon":4574,"path":4575,"stem":4576,"children":4577,"page":59},"Механізми автентифікації у вебзастосунках","i-lucide-key","\u002Fweb-development\u002Fauthentication","18.web-development\u002F12.authentication",[4578,4582,4586,4590,4594,4598,4602,4606,4610],{"title":4579,"path":4580,"stem":4581},"Автентифікація vs Авторизація","\u002Fweb-development\u002Fauthentication\u002F01-authentication-vs-authorization","18.web-development\u002F12.authentication\u002F01-authentication-vs-authorization",{"title":4583,"path":4584,"stem":4585},"Стратегії автентифікації","\u002Fweb-development\u002Fauthentication\u002F02-authentication-strategies","18.web-development\u002F12.authentication\u002F02-authentication-strategies",{"title":4587,"path":4588,"stem":4589},"Автентифікація на основі сесій","\u002Fweb-development\u002Fauthentication\u002F03-session-based-authentication","18.web-development\u002F12.authentication\u002F03-session-based-authentication",{"title":4591,"path":4592,"stem":4593},"Структура JSON Web Token (JWT)","\u002Fweb-development\u002Fauthentication\u002F04-jwt-structure","18.web-development\u002F12.authentication\u002F04-jwt-structure",{"title":4595,"path":4596,"stem":4597},"Інтеграція JWT у NestJS","\u002Fweb-development\u002Fauthentication\u002F05-nestjs-jwt-integration","18.web-development\u002F12.authentication\u002F05-nestjs-jwt-integration",{"title":4599,"path":4600,"stem":4601},"Passport.js стратегії у NestJS","\u002Fweb-development\u002Fauthentication\u002F06-passport-strategies","18.web-development\u002F12.authentication\u002F06-passport-strategies",{"title":4603,"path":4604,"stem":4605},"Безпечне зберігання паролів: хешування та криптографічний захист","\u002Fweb-development\u002Fauthentication\u002F07-password-hashing","18.web-development\u002F12.authentication\u002F07-password-hashing",{"title":4607,"path":4608,"stem":4609},"Refresh Token та безпечне оновлення доступу","\u002Fweb-development\u002Fauthentication\u002F08-refresh-tokens","18.web-development\u002F12.authentication\u002F08-refresh-tokens",{"title":4611,"path":4612,"stem":4613},"OAuth 2.0 та OpenID Connect: делегована автентифікація","\u002Fweb-development\u002Fauthentication\u002F09-oauth2-openid","18.web-development\u002F12.authentication\u002F09-oauth2-openid",{"title":4615,"icon":4616,"path":4617,"stem":4618,"children":4619,"page":59},"Авторизація та безпека серверних застосунків","i-lucide-shield","\u002Fweb-development\u002Fauthorization-security","18.web-development\u002F13.authorization-security",[4620,4624,4628,4632,4636,4640,4644,4648,4652,4656],{"title":4621,"path":4622,"stem":4623},"Моделі авторизації","\u002Fweb-development\u002Fauthorization-security\u002F01-authorization-models","18.web-development\u002F13.authorization-security\u002F01-authorization-models",{"title":4625,"path":4626,"stem":4627},"Реалізація RBAC у NestJS","\u002Fweb-development\u002Fauthorization-security\u002F02-rbac-implementation","18.web-development\u002F13.authorization-security\u002F02-rbac-implementation",{"title":4629,"path":4630,"stem":4631},"Permission-Based Access Control","\u002Fweb-development\u002Fauthorization-security\u002F03-permission-based-access","18.web-development\u002F13.authorization-security\u002F03-permission-based-access",{"title":4633,"path":4634,"stem":4635},"ABAC та бібліотека CASL","\u002Fweb-development\u002Fauthorization-security\u002F04-abac-casl","18.web-development\u002F13.authorization-security\u002F04-abac-casl",{"title":4637,"path":4638,"stem":4639},"Кастомні декоратори та метадані","\u002Fweb-development\u002Fauthorization-security\u002F05-custom-decorators-metadata","18.web-development\u002F13.authorization-security\u002F05-custom-decorators-metadata",{"title":4641,"path":4642,"stem":4643},"Конфігурація CORS","\u002Fweb-development\u002Fauthorization-security\u002F06-cors-configuration","18.web-development\u002F13.authorization-security\u002F06-cors-configuration",{"title":4645,"path":4646,"stem":4647},"Захист через HTTP Security Headers (Helmet)","\u002Fweb-development\u002Fauthorization-security\u002F07-helmet-security-headers","18.web-development\u002F13.authorization-security\u002F07-helmet-security-headers",{"title":4649,"path":4650,"stem":4651},"Rate Limiting та Throttling","\u002Fweb-development\u002Fauthorization-security\u002F08-rate-limiting-throttling","18.web-development\u002F13.authorization-security\u002F08-rate-limiting-throttling",{"title":4653,"path":4654,"stem":4655},"Захист від поширених атак","\u002Fweb-development\u002Fauthorization-security\u002F09-common-attacks-protection","18.web-development\u002F13.authorization-security\u002F09-common-attacks-protection",{"title":4657,"path":4658,"stem":4659},"HTTPS у продакшені","\u002Fweb-development\u002Fauthorization-security\u002F10-https-production","18.web-development\u002F13.authorization-security\u002F10-https-production",{"title":4661,"icon":871,"path":4662,"stem":4663,"children":4664,"page":59},"Комунікація у реальному часі, нотифікації та фонові задачі","\u002Fweb-development\u002Frealtime-notifications-jobs","18.web-development\u002F14.realtime-notifications-jobs",[4665,4669,4673,4677,4681,4685,4688,4691,4695,4699],{"title":4666,"path":4667,"stem":4668},"Методи комунікації у реальному часі","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F01-realtime-communication-methods","18.web-development\u002F14.realtime-notifications-jobs\u002F01-realtime-communication-methods",{"title":4670,"path":4671,"stem":4672},"WebSocket Gateway у NestJS","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F02-websocket-gateway","18.web-development\u002F14.realtime-notifications-jobs\u002F02-websocket-gateway",{"title":4674,"path":4675,"stem":4676},"Lifecycle та Rooms у WebSocket","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F03-websocket-lifecycle-rooms","18.web-development\u002F14.realtime-notifications-jobs\u002F03-websocket-lifecycle-rooms",{"title":4678,"path":4679,"stem":4680},"Server-Sent Events (SSE)","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F04-server-sent-events","18.web-development\u002F14.realtime-notifications-jobs\u002F04-server-sent-events",{"title":4682,"path":4683,"stem":4684},"Архітектура системи нотифікацій","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F05-notification-system","18.web-development\u002F14.realtime-notifications-jobs\u002F05-notification-system",{"title":904,"path":4686,"stem":4687},"\u002Fweb-development\u002Frealtime-notifications-jobs\u002F06-email-notifications","18.web-development\u002F14.realtime-notifications-jobs\u002F06-email-notifications",{"title":900,"path":4689,"stem":4690},"\u002Fweb-development\u002Frealtime-notifications-jobs\u002F07-web-push-notifications","18.web-development\u002F14.realtime-notifications-jobs\u002F07-web-push-notifications",{"title":4692,"path":4693,"stem":4694},"Фонові задачі та черги","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F08-background-jobs-queues","18.web-development\u002F14.realtime-notifications-jobs\u002F08-background-jobs-queues",{"title":4696,"path":4697,"stem":4698},"Планувальники та Cron jobs","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F09-schedulers-cron","18.web-development\u002F14.realtime-notifications-jobs\u002F09-schedulers-cron",{"title":4700,"path":4701,"stem":4702},"Практичні сценарії застосування","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F10-practical-scenarios","18.web-development\u002F14.realtime-notifications-jobs\u002F10-practical-scenarios",{"title":4704,"icon":4705,"path":4706,"stem":4707,"children":4708,"page":59},"Тестування, документування та розгортання застосунків","i-lucide-rocket","\u002Fweb-development\u002Ftesting-documentation-deployment","18.web-development\u002F15.testing-documentation-deployment",[4709,4713,4717,4721,4725,4729,4733,4737,4741,4745],{"title":4710,"path":4711,"stem":4712},"Піраміда тестування та стратегія","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F01-testing-pyramid-strategy","18.web-development\u002F15.testing-documentation-deployment\u002F01-testing-pyramid-strategy",{"title":4714,"path":4715,"stem":4716},"Основи Jest у NestJS","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F02-jest-nestjs-basics","18.web-development\u002F15.testing-documentation-deployment\u002F02-jest-nestjs-basics",{"title":4718,"path":4719,"stem":4720},"Unit-тестування сервісів","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F03-unit-testing-services","18.web-development\u002F15.testing-documentation-deployment\u002F03-unit-testing-services",{"title":4722,"path":4723,"stem":4724},"E2E тестування та покриття коду","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F04-e2e-testing-coverage","18.web-development\u002F15.testing-documentation-deployment\u002F04-e2e-testing-coverage",{"title":4726,"path":4727,"stem":4728},"Swagger, OpenAPI, Scalar та Arazzo","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F05-swagger-openapi","18.web-development\u002F15.testing-documentation-deployment\u002F05-swagger-openapi",{"title":4730,"path":4731,"stem":4732},"Керування конфігурацією","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F06-configuration-management","18.web-development\u002F15.testing-documentation-deployment\u002F06-configuration-management",{"title":4734,"path":4735,"stem":4736},"Docker та контейнеризація","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F07-docker-containerization","18.web-development\u002F15.testing-documentation-deployment\u002F07-docker-containerization",{"title":4738,"path":4739,"stem":4740},"CI\u002FCD Pipelines","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F08-cicd-pipelines","18.web-development\u002F15.testing-documentation-deployment\u002F08-cicd-pipelines",{"title":4742,"path":4743,"stem":4744},"Логування та моніторинг","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F09-logging-monitoring","18.web-development\u002F15.testing-documentation-deployment\u002F09-logging-monitoring",{"title":4746,"path":4747,"stem":4748},"Серіалізація та компресія","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F10-serialization-compression","18.web-development\u002F15.testing-documentation-deployment\u002F10-serialization-compression",{"title":4750,"icon":4751,"path":4752,"stem":4753,"children":4754,"page":59},"AI Core: мислення AI","i-lucide-brain","\u002Fai-core","19.ai-core",[4755,4796,4845,4883],{"title":4756,"icon":4705,"path":4757,"stem":4758,"children":4759,"page":59},"Вхід у професію AI Native Developer","\u002Fai-core\u002Fai-native-developer","19.ai-core\u002F01.ai-native-developer",[4760,4764,4768,4772,4776,4780,4784,4788,4792],{"title":4761,"path":4762,"stem":4763},"Вступ до професії розробника цифрових продуктів","\u002Fai-core\u002Fai-native-developer\u002Fdigital-products","19.ai-core\u002F01.ai-native-developer\u002F01.digital-products",{"title":4765,"path":4766,"stem":4767},"Професія розробника програмного забезпечення","\u002Fai-core\u002Fai-native-developer\u002Fsoftware-developer","19.ai-core\u002F01.ai-native-developer\u002F02.software-developer",{"title":4769,"path":4770,"stem":4771},"Професія AI Native Developer","\u002Fai-core\u002Fai-native-developer\u002Fai-native-developer","19.ai-core\u002F01.ai-native-developer\u002F03.ai-native-developer",{"title":4773,"path":4774,"stem":4775},"Вплив AI на розробку програмного забезпечення","\u002Fai-core\u002Fai-native-developer\u002Fai-impact-on-development","19.ai-core\u002F01.ai-native-developer\u002F04.ai-impact-on-development",{"title":4777,"path":4778,"stem":4779},"Життєвий цикл цифрового продукту","\u002Fai-core\u002Fai-native-developer\u002Fproduct-lifecycle","19.ai-core\u002F01.ai-native-developer\u002F05.product-lifecycle",{"title":4781,"path":4782,"stem":4783},"Застосування AI на етапах створення цифрового продукту","\u002Fai-core\u002Fai-native-developer\u002Fai-in-product-creation","19.ai-core\u002F01.ai-native-developer\u002F06.ai-in-product-creation",{"title":4785,"path":4786,"stem":4787},"Розподіл завдань між людиною та AI","\u002Fai-core\u002Fai-native-developer\u002Fhuman-vs-ai-tasks","19.ai-core\u002F01.ai-native-developer\u002F07.human-vs-ai-tasks",{"title":4789,"path":4790,"stem":4791},"Компетенції AI Native Developer","\u002Fai-core\u002Fai-native-developer\u002Fcompetencies","19.ai-core\u002F01.ai-native-developer\u002F08.competencies",{"title":4793,"path":4794,"stem":4795},"Карта професійного розвитку AI Native Developer","\u002Fai-core\u002Fai-native-developer\u002Fcareer-roadmap","19.ai-core\u002F01.ai-native-developer\u002F09.career-roadmap",{"title":4797,"icon":255,"path":4798,"stem":4799,"children":4800,"page":59},"Штучний інтелект і машинне навчання","\u002Fai-core\u002Fai-and-machine-learning","19.ai-core\u002F02.ai-and-machine-learning",[4801,4805,4809,4813,4817,4821,4825,4829,4833,4837,4841],{"title":4802,"path":4803,"stem":4804},"Штучний інтелект","\u002Fai-core\u002Fai-and-machine-learning\u002Fwhat-is-ai","19.ai-core\u002F02.ai-and-machine-learning\u002F01.what-is-ai",{"title":4806,"path":4807,"stem":4808},"Відмінність AI від інших програмних систем","\u002Fai-core\u002Fai-and-machine-learning\u002Fai-vs-automation","19.ai-core\u002F02.ai-and-machine-learning\u002F02.ai-vs-automation",{"title":4810,"path":4811,"stem":4812},"Завдання штучного інтелекту","\u002Fai-core\u002Fai-and-machine-learning\u002Fai-tasks","19.ai-core\u002F02.ai-and-machine-learning\u002F03.ai-tasks",{"title":4814,"path":4815,"stem":4816},"Machine Learning","\u002Fai-core\u002Fai-and-machine-learning\u002Fmachine-learning","19.ai-core\u002F02.ai-and-machine-learning\u002F04.machine-learning",{"title":4818,"path":4819,"stem":4820},"Machine Learning Workflow","\u002Fai-core\u002Fai-and-machine-learning\u002Fml-workflow","19.ai-core\u002F02.ai-and-machine-learning\u002F05.ml-workflow",{"title":4822,"path":4823,"stem":4824},"Типи машинного навчання","\u002Fai-core\u002Fai-and-machine-learning\u002Fml-types","19.ai-core\u002F02.ai-and-machine-learning\u002F06.ml-types",{"title":4826,"path":4827,"stem":4828},"Generative AI","\u002Fai-core\u002Fai-and-machine-learning\u002Fgenerative-ai","19.ai-core\u002F02.ai-and-machine-learning\u002F07.generative-ai",{"title":4830,"path":4831,"stem":4832},"Типи контенту, створюваного AI","\u002Fai-core\u002Fai-and-machine-learning\u002Fai-content-types","19.ai-core\u002F02.ai-and-machine-learning\u002F08.ai-content-types",{"title":4834,"path":4835,"stem":4836},"Великі мовні моделі","\u002Fai-core\u002Fai-and-machine-learning\u002Flarge-language-models","19.ai-core\u002F02.ai-and-machine-learning\u002F09.large-language-models",{"title":4838,"path":4839,"stem":4840},"Можливості та обмеження Generative AI","\u002Fai-core\u002Fai-and-machine-learning\u002Fcapabilities-and-limitations","19.ai-core\u002F02.ai-and-machine-learning\u002F10.capabilities-and-limitations",{"title":4842,"path":4843,"stem":4844},"Сучасні AI-асистенти","\u002Fai-core\u002Fai-and-machine-learning\u002Fmodern-ai-assistants","19.ai-core\u002F02.ai-and-machine-learning\u002F11.modern-ai-assistants",{"title":4846,"icon":4847,"path":4848,"stem":4849,"children":4850,"page":59},"Постановка завдань для AI: принципи створення промптів","i-lucide-message-square-text","\u002Fai-core\u002Fprompt-engineering","19.ai-core\u002F03.prompt-engineering",[4851,4855,4859,4863,4867,4871,4875,4879],{"title":4852,"path":4853,"stem":4854},"Промпт як інструмент","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-as-tool","19.ai-core\u002F03.prompt-engineering\u002F01.prompt-as-tool",{"title":4856,"path":4857,"stem":4858},"Принципи створення промптів","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-principles","19.ai-core\u002F03.prompt-engineering\u002F02.prompt-principles",{"title":4860,"path":4861,"stem":4862},"Структура промпта","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-structure","19.ai-core\u002F03.prompt-engineering\u002F03.prompt-structure",{"title":4864,"path":4865,"stem":4866},"Види промптів за типом задачі","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-types","19.ai-core\u002F03.prompt-engineering\u002F04.prompt-types",{"title":4868,"path":4869,"stem":4870},"Прийоми посилення промпта","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-enhancement","19.ai-core\u002F03.prompt-engineering\u002F05.prompt-enhancement",{"title":4872,"path":4873,"stem":4874},"Розбір і покращення промпта","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-analysis","19.ai-core\u002F03.prompt-engineering\u002F06.prompt-analysis",{"title":4876,"path":4877,"stem":4878},"Типові помилки під час створення промптів","\u002Fai-core\u002Fprompt-engineering\u002Fcommon-mistakes","19.ai-core\u002F03.prompt-engineering\u002F07.common-mistakes",{"title":4880,"path":4881,"stem":4882},"Практикум: особиста бібліотека промптів","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-library","19.ai-core\u002F03.prompt-engineering\u002F08.prompt-library",{"title":4884,"icon":793,"path":4885,"stem":4886,"children":4887,"page":59},"Перевірка результатів, безпека та AI Native Workflow","\u002Fai-core\u002Fverification-security-workflow","19.ai-core\u002F04.verification-security-workflow",[4888,4892,4896,4900,4904,4908,4912,4916,4920],{"title":4889,"path":4890,"stem":4891},"Межі можливостей AI","\u002Fai-core\u002Fverification-security-workflow\u002Fai-limitations","19.ai-core\u002F04.verification-security-workflow\u002F01.ai-limitations",{"title":4893,"path":4894,"stem":4895},"Галюцинації AI","\u002Fai-core\u002Fverification-security-workflow\u002Fai-hallucinations","19.ai-core\u002F04.verification-security-workflow\u002F02.ai-hallucinations",{"title":4897,"path":4898,"stem":4899},"Критичне мислення під час роботи з AI","\u002Fai-core\u002Fverification-security-workflow\u002Fcritical-thinking","19.ai-core\u002F04.verification-security-workflow\u002F03.critical-thinking",{"title":4901,"path":4902,"stem":4903},"Перевірка результатів роботи AI","\u002Fai-core\u002Fverification-security-workflow\u002Fresult-verification","19.ai-core\u002F04.verification-security-workflow\u002F04.result-verification",{"title":4905,"path":4906,"stem":4907},"Захист даних під час роботи з AI","\u002Fai-core\u002Fverification-security-workflow\u002Fdata-protection","19.ai-core\u002F04.verification-security-workflow\u002F05.data-protection",{"title":4909,"path":4910,"stem":4911},"Авторське право та навчальна доброчесність","\u002Fai-core\u002Fverification-security-workflow\u002Fcopyright-integrity","19.ai-core\u002F04.verification-security-workflow\u002F06.copyright-integrity",{"title":4913,"path":4914,"stem":4915},"Відповідальне використання AI","\u002Fai-core\u002Fverification-security-workflow\u002Fresponsible-use","19.ai-core\u002F04.verification-security-workflow\u002F07.responsible-use",{"title":4917,"path":4918,"stem":4919},"AI Native Workflow","\u002Fai-core\u002Fverification-security-workflow\u002Fai-native-workflow","19.ai-core\u002F04.verification-security-workflow\u002F08.ai-native-workflow",{"title":4921,"path":4922,"stem":4923},"Застосування AI Native Workflow під час створення цифрового продукту","\u002Fai-core\u002Fverification-security-workflow\u002Fworkflow-in-practice","19.ai-core\u002F04.verification-security-workflow\u002F09.workflow-in-practice",{"title":4925,"icon":4926,"path":4927,"stem":4928,"children":4929,"page":59},"AI Developer: Vibe Coding Sprint","i-lucide-code-xml","\u002Fai-developer","20.ai-developer",[4930,4956,4978,4999],{"title":4931,"icon":4932,"path":4933,"stem":4934,"children":4935,"page":59},"Проєктування і чорнова версія","i-lucide-pencil-ruler","\u002Fai-developer\u002Fdraft-creation","20.ai-developer\u002F01.draft-creation",[4936,4940,4944,4948,4952],{"title":4937,"path":4938,"stem":4939},"Парадигма Vibe Coding Workflow","\u002Fai-developer\u002Fdraft-creation\u002Fvibe-coding-workflow","20.ai-developer\u002F01.draft-creation\u002F01.vibe-coding-workflow",{"title":4941,"path":4942,"stem":4943},"AI-середовище швидкої розробки","\u002Fai-developer\u002Fdraft-creation\u002Fai-ide-environment","20.ai-developer\u002F01.draft-creation\u002F02.ai-ide-environment",{"title":4945,"path":4946,"stem":4947},"Користувацьке завдання та межі першої версії","\u002Fai-developer\u002Fdraft-creation\u002Fproduct-scope-and-mvp","20.ai-developer\u002F01.draft-creation\u002F03.product-scope-and-mvp",{"title":4949,"path":4950,"stem":4951},"Архітектура інтерфейсу та стани застосунку","\u002Fai-developer\u002Fdraft-creation\u002Fapplication-architecture-and-states","20.ai-developer\u002F01.draft-creation\u002F04.application-architecture-and-states",{"title":4953,"path":4954,"stem":4955},"Генерація та фіксація чорнової версії","\u002Fai-developer\u002Fdraft-creation\u002Fgenerating-draft-version","20.ai-developer\u002F01.draft-creation\u002F05.generating-draft-version",{"title":4957,"icon":4958,"path":4959,"stem":4960,"children":4961,"page":59},"Перша робоча версія","i-lucide-play-circle","\u002Fai-developer\u002Ffirst-working-version","20.ai-developer\u002F02.first-working-version",[4962,4966,4970,4974],{"title":4963,"path":4964,"stem":4965},"Уточнення контексту проєкту для AI","\u002Fai-developer\u002Ffirst-working-version\u002Frefining-project-context","20.ai-developer\u002F02.first-working-version\u002F01.refining-project-context",{"title":4967,"path":4968,"stem":4969},"Стратегія завдань для AI-розробки","\u002Fai-developer\u002Ffirst-working-version\u002Fai-prompting-strategy","20.ai-developer\u002F02.first-working-version\u002F02.ai-prompting-strategy",{"title":4971,"path":4972,"stem":4973},"Доопрацювання до першої робочої версії","\u002Fai-developer\u002Ffirst-working-version\u002Frefining-to-working-version","20.ai-developer\u002F02.first-working-version\u002F03.refining-to-working-version",{"title":4975,"path":4976,"stem":4977},"Перевірка першої робочої версії","\u002Fai-developer\u002Ffirst-working-version\u002Ftesting-first-working-version","20.ai-developer\u002F02.first-working-version\u002F04.testing-first-working-version",{"title":4979,"icon":3028,"path":4980,"stem":4981,"children":4982,"page":59},"Ітерації, дебагінг та відновлення","\u002Fai-developer\u002Fiteration-debugging-recovery","20.ai-developer\u002F03.iteration-debugging-recovery",[4983,4987,4991,4995],{"title":4984,"path":4985,"stem":4986},"Управління точковими змінами продукту","\u002Fai-developer\u002Fiteration-debugging-recovery\u002Fchange-management","20.ai-developer\u002F03.iteration-debugging-recovery\u002F01.change-management",{"title":4988,"path":4989,"stem":4990},"Надійність інтерфейсу та обробка помилок","\u002Fai-developer\u002Fiteration-debugging-recovery\u002Fscenario-reliability-and-errors","20.ai-developer\u002F03.iteration-debugging-recovery\u002F02.scenario-reliability-and-errors",{"title":4992,"path":4993,"stem":4994},"Керування контекстом і збереження версій","\u002Fai-developer\u002Fiteration-debugging-recovery\u002Fproject-context-and-versions","20.ai-developer\u002F03.iteration-debugging-recovery\u002F03.project-context-and-versions",{"title":4996,"path":4997,"stem":4998},"Збої AI-розробки, ліміти та аварійне відновлення","\u002Fai-developer\u002Fiteration-debugging-recovery\u002Fai-breakdowns-and-recovery","20.ai-developer\u002F03.iteration-debugging-recovery\u002F04.ai-breakdowns-and-recovery",{"title":5000,"icon":5001,"path":5002,"stem":5003,"children":5004,"page":59},"Перевірка та завершення продукту","i-lucide-check-check","\u002Fai-developer\u002Fverification-and-completion","20.ai-developer\u002F04.verification-and-completion",[5005,5009,5013],{"title":5006,"path":5007,"stem":5008},"Комплексний аудит та підсумкове тестування","\u002Fai-developer\u002Fverification-and-completion\u002Ffinal-product-testing","20.ai-developer\u002F04.verification-and-completion\u002F01.final-product-testing",{"title":5010,"path":5011,"stem":5012},"Підготовка підсумкової версії коду","\u002Fai-developer\u002Fverification-and-completion\u002Fpreparing-release-version","20.ai-developer\u002F04.verification-and-completion\u002F02.preparing-release-version",{"title":5014,"path":5015,"stem":5016},"Демонстрація, публікація та критерії оцінювання","\u002Fai-developer\u002Fverification-and-completion\u002Fproduct-showcase-and-publishing","20.ai-developer\u002F04.verification-and-completion\u002F03.product-showcase-and-publishing",{"title":5018,"path":5019,"stem":5020,"children":5021,"page":59},"Tailwind","\u002Ftailwind","21.tailwind",[5022,5026,5030,5034,5038,5042,5046,5050,5054,5058,5062,5066],{"title":5023,"path":5024,"stem":5025},"Що таке Tailwind CSS і навіщо він потрібен","\u002Ftailwind\u002Ftailwind-intro-philosophy","21.tailwind\u002F01.tailwind-intro-philosophy",{"title":5027,"path":5028,"stem":5029},"Встановлення та налаштування Tailwind CSS v4","\u002Ftailwind\u002Ftailwind-installation-setup","21.tailwind\u002F02.tailwind-installation-setup",{"title":5031,"path":5032,"stem":5033},"Utility-класи: основи та система Tailwind","\u002Ftailwind\u002Ftailwind-utility-classes-core","21.tailwind\u002F03.tailwind-utility-classes-core",{"title":5035,"path":5036,"stem":5037},"Layout: Flexbox та Grid через Tailwind","\u002Ftailwind\u002Ftailwind-flexbox-grid","21.tailwind\u002F04.tailwind-flexbox-grid",{"title":5039,"path":5040,"stem":5041},"Кастомізація теми через @theme у Tailwind v4","\u002Ftailwind\u002Ftailwind-theme-customization","21.tailwind\u002F05.tailwind-theme-customization",{"title":5043,"path":5044,"stem":5045},"Варіанти: hover, focus, responsive, dark mode та нові v4","\u002Ftailwind\u002Ftailwind-variants-states","21.tailwind\u002F06.tailwind-variants-states",{"title":5047,"path":5048,"stem":5049},"Типографіка та система кольорів у Tailwind v4","\u002Ftailwind\u002Ftailwind-typography-colors","21.tailwind\u002F07.tailwind-typography-colors",{"title":5051,"path":5052,"stem":5053},"Компоненти та повторюваність: @apply, @utility та патерни","\u002Ftailwind\u002Ftailwind-components-patterns","21.tailwind\u002F08.tailwind-components-patterns",{"title":5055,"path":5056,"stem":5057},"Темна тема та система дизайн-токенів у Tailwind v4","\u002Ftailwind\u002Ftailwind-dark-mode-theming","21.tailwind\u002F09.tailwind-dark-mode-theming",{"title":5059,"path":5060,"stem":5061},"Довільні значення та контейнерні запити у Tailwind v4","\u002Ftailwind\u002Ftailwind-arbitrary-container-queries","21.tailwind\u002F10.tailwind-arbitrary-container-queries",{"title":5063,"path":5064,"stem":5065},"Анімації, трансформації та 3D у Tailwind v4","\u002Ftailwind\u002Ftailwind-animations-transforms","21.tailwind\u002F11.tailwind-animations-transforms",{"title":5067,"path":5068,"stem":5069},"Tailwind CLI, PostCSS та інтеграція з фреймворками","\u002Ftailwind\u002Ftailwind-cli-tooling","21.tailwind\u002F12.tailwind-cli-tooling",{"title":5071,"path":5072,"stem":5073},"Тестування компонентів діаграм","\u002Ftest-components","98.test-components",{"id":5075,"title":4492,"body":5076,"description":22758,"extension":22759,"links":22760,"meta":22761,"navigation":5472,"path":4493,"seo":22762,"stem":4494,"__hash__":22763},"docs\u002F18.web-development\u002F09.nestjs-validation-pipeline\u002F15.custom-exception-filters.md",{"type":5077,"value":5078,"toc":22711},"minimark",[5079,5083,5200,5205,5213,5245,5250,5543,5555,5559,5571,5576,6186,6191,6515,6520,6603,6608,6835,6839,7352,7357,7467,7481,7485,7495,7499,8768,8772,9046,9051,9108,9113,9158,9163,9229,9233,9846,9859,9863,9870,10476,10481,10595,10599,10602,10606,10627,10631,10842,10846,11668,11673,11701,11710,11714,12145,12149,12175,12179,12182,12507,12512,12852,12856,12859,13389,13393,13814,13818,13821,13825,14099,14104,14155,14181,14185,14376,14380,14383,14387,14401,14405,14615,14619,15342,15355,15359,15363,16008,16012,16817,16821,17732,17736,18002,18007,18051,18055,18059,18286,18290,18513,18517,18802,18806,18942,18946,19109,19113,19474,19478,19771,19775,20183,20187,22687,22690,22707],[5080,5081,4492],"h1",{"id":5082},"custom-exception-filters-спеціалізовані-фільтри",[5084,5085,5086,5136],"card-group",{},[5087,5088,5091],"card",{"icon":5089,"title":5090},"i-lucide-target","🎯 Мета лекції",[5092,5093,5094,5098,5106,5113,5120,5123,5133],"ul",{},[5095,5096,5097],"li",{},"Зрозуміти необхідність спеціалізованих exception filters для різних типів помилок",[5095,5099,5100,5101,5105],{},"Опанувати створення ",[5102,5103,5104],"code",{},"ValidationExceptionFilter"," для детальної обробки помилок валідації DTO",[5095,5107,5108,5109,5112],{},"Навчитися розробляти ",[5102,5110,5111],{},"DatabaseExceptionFilter"," для трансформації помилок TypeORM\u002FSequelize",[5095,5114,5115,5116,5119],{},"Вивчити ",[5102,5117,5118],{},"HttpExceptionFilter"," для форматування стандартних HTTP-виключень",[5095,5121,5122],{},"Засвоїти інтеграцію з Sentry\u002FDatadog для централізованого моніторингу помилок",[5095,5124,5125,5126,5129,5130],{},"Практикувати створення ",[5102,5127,5128],{},"TimeoutExceptionFilter"," та ",[5102,5131,5132],{},"UnauthorizedExceptionFilter",[5095,5134,5135],{},"Розуміти композицію filters та їх пріоритетність виконання",[5087,5137,5139],{"icon":4574,"title":5138},"🔑 Ключові терміни",[5092,5140,5141,5156,5164,5173,5182,5191],{},[5095,5142,5143,5146,5147,5151,5152,5155],{},[5144,5145,5104],"strong",{}," (",[5148,5149,5150],"em",{},"фільтр валідації","): filter для обробки помилок ",[5102,5153,5154],{},"class-validator"," з деталями про поля",[5095,5157,5158,5146,5160,5163],{},[5144,5159,5111],{},[5148,5161,5162],{},"фільтр БД","): filter для трансформації помилок ORM у зрозумілі HTTP-відповіді",[5095,5165,5166,5146,5169,5172],{},[5144,5167,5168],{},"Exception Transformation",[5148,5170,5171],{},"трансформація виключень","): перетворення низькорівневих помилок у структуровані відповіді",[5095,5174,5175,5146,5178,5181],{},[5144,5176,5177],{},"Sentry Integration",[5148,5179,5180],{},"інтеграція Sentry","): автоматична відправка помилок у систему моніторингу",[5095,5183,5184,5146,5187,5190],{},[5144,5185,5186],{},"Error Context Enrichment",[5148,5188,5189],{},"збагачення контексту","): додавання метаданих (user, request, trace) до логів помилок",[5095,5192,5193,5146,5196,5199],{},[5144,5194,5195],{},"Filter Composition",[5148,5197,5198],{},"композиція фільтрів","): комбінування кількох filters для різних типів виключень",[5201,5202,5204],"h2",{"id":5203},"необхідність-спеціалізованих-exception-filters","Необхідність спеціалізованих exception filters",[5206,5207,5208,5209,5212],"p",{},"Різні типи помилок вимагають ",[5144,5210,5211],{},"різної обробки",":",[5092,5214,5215,5221,5227,5233,5239],{},[5095,5216,5217,5220],{},[5144,5218,5219],{},"Валідаційні помилки",": потребують списку полів з constraints",[5095,5222,5223,5226],{},[5144,5224,5225],{},"Помилки бази даних",": приховують SQL-деталі, перетворюють коди помилок",[5095,5228,5229,5232],{},[5144,5230,5231],{},"Помилки зовнішніх API",": обробляють timeout, connection refused, 503",[5095,5234,5235,5238],{},[5144,5236,5237],{},"Помилки аутентифікації",": додають WWW-Authenticate заголовки",[5095,5240,5241,5244],{},[5144,5242,5243],{},"Помилки авторизації",": логують спроби несанкціонованого доступу",[5206,5246,5247],{},[5144,5248,5249],{},"Загальний filter vs спеціалізовані:",[5251,5252,5253,5432],"code-group",{},[5254,5255,5261],"pre",{"className":5256,"code":5257,"filename":5258,"language":5259,"meta":5260,"style":5260},"language-typescript shiki shiki-themes light-plus dark-plus dark-plus","@Catch()\nexport class GeneralFilter implements ExceptionFilter {\n  catch(exception: unknown, host: ArgumentsHost) {\n    \u002F\u002F Складна логіка if-else для кожного типу\n    if (exception instanceof ValidationError) { \u002F* ... *\u002F }\n    else if (exception instanceof QueryFailedError) { \u002F* ... *\u002F }\n    else if (exception instanceof UnauthorizedException) { \u002F* ... *\u002F }\n    \u002F\u002F 100+ рядків коду\n  }\n}\n","❌ Один filter для всього","typescript","",[5102,5262,5263,5279,5303,5336,5343,5368,5392,5414,5420,5426],{"__ignoreMap":5260},[5264,5265,5268,5272,5276],"span",{"class":5266,"line":5267},"line",1,[5264,5269,5271],{"class":5270},"sHH4Y","@",[5264,5273,5275],{"class":5274},"s8Opu","Catch",[5264,5277,5278],{"class":5270},"()\n",[5264,5280,5282,5286,5290,5294,5297,5300],{"class":5266,"line":5281},2,[5264,5283,5285],{"class":5284},"s8xlr","export",[5264,5287,5289],{"class":5288},"su1O8"," class",[5264,5291,5293],{"class":5292},"sN1BT"," GeneralFilter",[5264,5295,5296],{"class":5288}," implements",[5264,5298,5299],{"class":5292}," ExceptionFilter",[5264,5301,5302],{"class":5270}," {\n",[5264,5304,5306,5309,5312,5316,5319,5322,5325,5328,5330,5333],{"class":5266,"line":5305},3,[5264,5307,5308],{"class":5274},"  catch",[5264,5310,5311],{"class":5270},"(",[5264,5313,5315],{"class":5314},"siwwj","exception",[5264,5317,5318],{"class":5270},": ",[5264,5320,5321],{"class":5292},"unknown",[5264,5323,5324],{"class":5270},", ",[5264,5326,5327],{"class":5314},"host",[5264,5329,5318],{"class":5270},[5264,5331,5332],{"class":5292},"ArgumentsHost",[5264,5334,5335],{"class":5270},") {\n",[5264,5337,5339],{"class":5266,"line":5338},4,[5264,5340,5342],{"class":5341},"spJ8K","    \u002F\u002F Складна логіка if-else для кожного типу\n",[5264,5344,5346,5349,5351,5353,5356,5359,5362,5365],{"class":5266,"line":5345},5,[5264,5347,5348],{"class":5284},"    if",[5264,5350,5146],{"class":5270},[5264,5352,5315],{"class":5314},[5264,5354,5355],{"class":5288}," instanceof",[5264,5357,5358],{"class":5292}," ValidationError",[5264,5360,5361],{"class":5270},") { ",[5264,5363,5364],{"class":5341},"\u002F* ... *\u002F",[5264,5366,5367],{"class":5270}," }\n",[5264,5369,5371,5374,5377,5379,5381,5383,5386,5388,5390],{"class":5266,"line":5370},6,[5264,5372,5373],{"class":5284},"    else",[5264,5375,5376],{"class":5284}," if",[5264,5378,5146],{"class":5270},[5264,5380,5315],{"class":5314},[5264,5382,5355],{"class":5288},[5264,5384,5385],{"class":5292}," QueryFailedError",[5264,5387,5361],{"class":5270},[5264,5389,5364],{"class":5341},[5264,5391,5367],{"class":5270},[5264,5393,5395,5397,5399,5401,5403,5405,5408,5410,5412],{"class":5266,"line":5394},7,[5264,5396,5373],{"class":5284},[5264,5398,5376],{"class":5284},[5264,5400,5146],{"class":5270},[5264,5402,5315],{"class":5314},[5264,5404,5355],{"class":5288},[5264,5406,5407],{"class":5292}," UnauthorizedException",[5264,5409,5361],{"class":5270},[5264,5411,5364],{"class":5341},[5264,5413,5367],{"class":5270},[5264,5415,5417],{"class":5266,"line":5416},8,[5264,5418,5419],{"class":5341},"    \u002F\u002F 100+ рядків коду\n",[5264,5421,5423],{"class":5266,"line":5422},9,[5264,5424,5425],{"class":5270},"  }\n",[5264,5427,5429],{"class":5266,"line":5428},10,[5264,5430,5431],{"class":5270},"}\n",[5254,5433,5436],{"className":5256,"code":5434,"filename":5435,"language":5259,"meta":5260,"style":5260},"@Catch(BadRequestException)\nexport class ValidationExceptionFilter { \u002F* ... *\u002F }\n\n@Catch(QueryFailedError)\nexport class DatabaseExceptionFilter { \u002F* ... *\u002F }\n\n@Catch(UnauthorizedException)\nexport class AuthExceptionFilter { \u002F* ... *\u002F }\n\n\u002F\u002F Кожен filter фокусується на одному типі\n","✅ Спеціалізовані filters",[5102,5437,5438,5452,5468,5474,5487,5502,5506,5519,5534,5538],{"__ignoreMap":5260},[5264,5439,5440,5442,5444,5446,5449],{"class":5266,"line":5267},[5264,5441,5271],{"class":5270},[5264,5443,5275],{"class":5274},[5264,5445,5311],{"class":5270},[5264,5447,5448],{"class":5314},"BadRequestException",[5264,5450,5451],{"class":5270},")\n",[5264,5453,5454,5456,5458,5461,5464,5466],{"class":5266,"line":5281},[5264,5455,5285],{"class":5284},[5264,5457,5289],{"class":5288},[5264,5459,5460],{"class":5292}," ValidationExceptionFilter",[5264,5462,5463],{"class":5270}," { ",[5264,5465,5364],{"class":5341},[5264,5467,5367],{"class":5270},[5264,5469,5470],{"class":5266,"line":5305},[5264,5471,5473],{"emptyLinePlaceholder":5472},true,"\n",[5264,5475,5476,5478,5480,5482,5485],{"class":5266,"line":5338},[5264,5477,5271],{"class":5270},[5264,5479,5275],{"class":5274},[5264,5481,5311],{"class":5270},[5264,5483,5484],{"class":5314},"QueryFailedError",[5264,5486,5451],{"class":5270},[5264,5488,5489,5491,5493,5496,5498,5500],{"class":5266,"line":5345},[5264,5490,5285],{"class":5284},[5264,5492,5289],{"class":5288},[5264,5494,5495],{"class":5292}," DatabaseExceptionFilter",[5264,5497,5463],{"class":5270},[5264,5499,5364],{"class":5341},[5264,5501,5367],{"class":5270},[5264,5503,5504],{"class":5266,"line":5370},[5264,5505,5473],{"emptyLinePlaceholder":5472},[5264,5507,5508,5510,5512,5514,5517],{"class":5266,"line":5394},[5264,5509,5271],{"class":5270},[5264,5511,5275],{"class":5274},[5264,5513,5311],{"class":5270},[5264,5515,5516],{"class":5314},"UnauthorizedException",[5264,5518,5451],{"class":5270},[5264,5520,5521,5523,5525,5528,5530,5532],{"class":5266,"line":5416},[5264,5522,5285],{"class":5284},[5264,5524,5289],{"class":5288},[5264,5526,5527],{"class":5292}," AuthExceptionFilter",[5264,5529,5463],{"class":5270},[5264,5531,5364],{"class":5341},[5264,5533,5367],{"class":5270},[5264,5535,5536],{"class":5266,"line":5422},[5264,5537,5473],{"emptyLinePlaceholder":5472},[5264,5539,5540],{"class":5266,"line":5428},[5264,5541,5542],{"class":5341},"\u002F\u002F Кожен filter фокусується на одному типі\n",[5544,5545,5546,5547,5550,5551,5554],"note",{},"Спеціалізовані filters дотримуються принципу ",[5144,5548,5549],{},"Single Responsibility"," (SOLID): кожен filter відповідає за ",[5144,5552,5553],{},"один тип"," помилок, що спрощує підтримку та тестування.",[5201,5556,5558],{"id":5557},"validationexceptionfilter-обробка-помилок-валідації","ValidationExceptionFilter: обробка помилок валідації",[5206,5560,5561,5564,5565,5567,5568,5570],{},[5102,5562,5563],{},"ValidationPipe"," автоматично викидає ",[5102,5566,5448],{}," при помилках ",[5102,5569,5154],{},". Створимо filter для детального форматування:",[5572,5573,5575],"h3",{"id":5574},"базова-версія-validationexceptionfilter","Базова версія ValidationExceptionFilter",[5254,5577,5579],{"className":5256,"code":5578,"language":5259,"meta":5260,"style":5260},"import { ExceptionFilter, Catch, ArgumentsHost, BadRequestException } from '@nestjs\u002Fcommon';\nimport { Request, Response } from 'express';\n\n@Catch(BadRequestException)\nexport class ValidationExceptionFilter implements ExceptionFilter {\n  catch(exception: BadRequestException, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse\u003CResponse>();\n    const request = ctx.getRequest\u003CRequest>();\n    const status = exception.getStatus();\n    const exceptionResponse: any = exception.getResponse();\n\n    \u002F\u002F Витягування помилок валідації\n    const validationErrors = exceptionResponse.message;\n\n    \u002F\u002F Структурування відповіді\n    const errorResponse = {\n      statusCode: status,\n      error: 'Validation Failed',\n      message: 'Request validation failed',\n      timestamp: new Date().toISOString(),\n      path: request.url,\n      method: request.method,\n      errors: this.formatValidationErrors(validationErrors),\n    };\n\n    response.status(status).json(errorResponse);\n  }\n\n  private formatValidationErrors(errors: any): any[] {\n    if (!Array.isArray(errors)) {\n      return [{ message: errors }];\n    }\n\n    return errors.map(error => ({\n      field: error.property,\n      value: error.value,\n      constraints: Object.values(error.constraints || {}),\n    }));\n  }\n}\n",[5102,5580,5581,5616,5639,5643,5655,5669,5691,5714,5739,5761,5779,5802,5807,5813,5833,5838,5844,5855,5866,5877,5888,5909,5924,5939,5961,5967,5972,6001,6006,6011,6037,6060,6078,6084,6089,6113,6129,6144,6170,6176,6181],{"__ignoreMap":5260},[5264,5582,5583,5586,5588,5591,5593,5595,5597,5599,5601,5603,5606,5609,5613],{"class":5266,"line":5267},[5264,5584,5585],{"class":5284},"import",[5264,5587,5463],{"class":5270},[5264,5589,5590],{"class":5314},"ExceptionFilter",[5264,5592,5324],{"class":5270},[5264,5594,5275],{"class":5314},[5264,5596,5324],{"class":5270},[5264,5598,5332],{"class":5314},[5264,5600,5324],{"class":5270},[5264,5602,5448],{"class":5314},[5264,5604,5605],{"class":5270}," } ",[5264,5607,5608],{"class":5284},"from",[5264,5610,5612],{"class":5611},"sbdoH"," '@nestjs\u002Fcommon'",[5264,5614,5615],{"class":5270},";\n",[5264,5617,5618,5620,5622,5625,5627,5630,5632,5634,5637],{"class":5266,"line":5281},[5264,5619,5585],{"class":5284},[5264,5621,5463],{"class":5270},[5264,5623,5624],{"class":5314},"Request",[5264,5626,5324],{"class":5270},[5264,5628,5629],{"class":5314},"Response",[5264,5631,5605],{"class":5270},[5264,5633,5608],{"class":5284},[5264,5635,5636],{"class":5611}," 'express'",[5264,5638,5615],{"class":5270},[5264,5640,5641],{"class":5266,"line":5305},[5264,5642,5473],{"emptyLinePlaceholder":5472},[5264,5644,5645,5647,5649,5651,5653],{"class":5266,"line":5338},[5264,5646,5271],{"class":5270},[5264,5648,5275],{"class":5274},[5264,5650,5311],{"class":5270},[5264,5652,5448],{"class":5314},[5264,5654,5451],{"class":5270},[5264,5656,5657,5659,5661,5663,5665,5667],{"class":5266,"line":5345},[5264,5658,5285],{"class":5284},[5264,5660,5289],{"class":5288},[5264,5662,5460],{"class":5292},[5264,5664,5296],{"class":5288},[5264,5666,5299],{"class":5292},[5264,5668,5302],{"class":5270},[5264,5670,5671,5673,5675,5677,5679,5681,5683,5685,5687,5689],{"class":5266,"line":5370},[5264,5672,5308],{"class":5274},[5264,5674,5311],{"class":5270},[5264,5676,5315],{"class":5314},[5264,5678,5318],{"class":5270},[5264,5680,5448],{"class":5292},[5264,5682,5324],{"class":5270},[5264,5684,5327],{"class":5314},[5264,5686,5318],{"class":5270},[5264,5688,5332],{"class":5292},[5264,5690,5335],{"class":5270},[5264,5692,5693,5696,5700,5703,5705,5708,5711],{"class":5266,"line":5394},[5264,5694,5695],{"class":5288},"    const",[5264,5697,5699],{"class":5698},"s-QsJ"," ctx",[5264,5701,5702],{"class":5270}," = ",[5264,5704,5327],{"class":5314},[5264,5706,5707],{"class":5270},".",[5264,5709,5710],{"class":5274},"switchToHttp",[5264,5712,5713],{"class":5270},"();\n",[5264,5715,5716,5718,5721,5723,5726,5728,5731,5734,5736],{"class":5266,"line":5416},[5264,5717,5695],{"class":5288},[5264,5719,5720],{"class":5698}," response",[5264,5722,5702],{"class":5270},[5264,5724,5725],{"class":5314},"ctx",[5264,5727,5707],{"class":5270},[5264,5729,5730],{"class":5274},"getResponse",[5264,5732,5733],{"class":5270},"\u003C",[5264,5735,5629],{"class":5292},[5264,5737,5738],{"class":5270},">();\n",[5264,5740,5741,5743,5746,5748,5750,5752,5755,5757,5759],{"class":5266,"line":5422},[5264,5742,5695],{"class":5288},[5264,5744,5745],{"class":5698}," request",[5264,5747,5702],{"class":5270},[5264,5749,5725],{"class":5314},[5264,5751,5707],{"class":5270},[5264,5753,5754],{"class":5274},"getRequest",[5264,5756,5733],{"class":5270},[5264,5758,5624],{"class":5292},[5264,5760,5738],{"class":5270},[5264,5762,5763,5765,5768,5770,5772,5774,5777],{"class":5266,"line":5428},[5264,5764,5695],{"class":5288},[5264,5766,5767],{"class":5698}," status",[5264,5769,5702],{"class":5270},[5264,5771,5315],{"class":5314},[5264,5773,5707],{"class":5270},[5264,5775,5776],{"class":5274},"getStatus",[5264,5778,5713],{"class":5270},[5264,5780,5782,5784,5787,5789,5792,5794,5796,5798,5800],{"class":5266,"line":5781},11,[5264,5783,5695],{"class":5288},[5264,5785,5786],{"class":5698}," exceptionResponse",[5264,5788,5318],{"class":5270},[5264,5790,5791],{"class":5292},"any",[5264,5793,5702],{"class":5270},[5264,5795,5315],{"class":5314},[5264,5797,5707],{"class":5270},[5264,5799,5730],{"class":5274},[5264,5801,5713],{"class":5270},[5264,5803,5805],{"class":5266,"line":5804},12,[5264,5806,5473],{"emptyLinePlaceholder":5472},[5264,5808,5810],{"class":5266,"line":5809},13,[5264,5811,5812],{"class":5341},"    \u002F\u002F Витягування помилок валідації\n",[5264,5814,5816,5818,5821,5823,5826,5828,5831],{"class":5266,"line":5815},14,[5264,5817,5695],{"class":5288},[5264,5819,5820],{"class":5698}," validationErrors",[5264,5822,5702],{"class":5270},[5264,5824,5825],{"class":5314},"exceptionResponse",[5264,5827,5707],{"class":5270},[5264,5829,5830],{"class":5314},"message",[5264,5832,5615],{"class":5270},[5264,5834,5836],{"class":5266,"line":5835},15,[5264,5837,5473],{"emptyLinePlaceholder":5472},[5264,5839,5841],{"class":5266,"line":5840},16,[5264,5842,5843],{"class":5341},"    \u002F\u002F Структурування відповіді\n",[5264,5845,5847,5849,5852],{"class":5266,"line":5846},17,[5264,5848,5695],{"class":5288},[5264,5850,5851],{"class":5698}," errorResponse",[5264,5853,5854],{"class":5270}," = {\n",[5264,5856,5858,5861,5863],{"class":5266,"line":5857},18,[5264,5859,5860],{"class":5314},"      statusCode:",[5264,5862,5767],{"class":5314},[5264,5864,5865],{"class":5270},",\n",[5264,5867,5869,5872,5875],{"class":5266,"line":5868},19,[5264,5870,5871],{"class":5314},"      error:",[5264,5873,5874],{"class":5611}," 'Validation Failed'",[5264,5876,5865],{"class":5270},[5264,5878,5880,5883,5886],{"class":5266,"line":5879},20,[5264,5881,5882],{"class":5314},"      message:",[5264,5884,5885],{"class":5611}," 'Request validation failed'",[5264,5887,5865],{"class":5270},[5264,5889,5891,5894,5897,5900,5903,5906],{"class":5266,"line":5890},21,[5264,5892,5893],{"class":5314},"      timestamp:",[5264,5895,5896],{"class":5288}," new",[5264,5898,5899],{"class":5274}," Date",[5264,5901,5902],{"class":5270},"().",[5264,5904,5905],{"class":5274},"toISOString",[5264,5907,5908],{"class":5270},"(),\n",[5264,5910,5912,5915,5917,5919,5922],{"class":5266,"line":5911},22,[5264,5913,5914],{"class":5314},"      path:",[5264,5916,5745],{"class":5314},[5264,5918,5707],{"class":5270},[5264,5920,5921],{"class":5314},"url",[5264,5923,5865],{"class":5270},[5264,5925,5927,5930,5932,5934,5937],{"class":5266,"line":5926},23,[5264,5928,5929],{"class":5314},"      method:",[5264,5931,5745],{"class":5314},[5264,5933,5707],{"class":5270},[5264,5935,5936],{"class":5314},"method",[5264,5938,5865],{"class":5270},[5264,5940,5942,5945,5948,5950,5953,5955,5958],{"class":5266,"line":5941},24,[5264,5943,5944],{"class":5314},"      errors:",[5264,5946,5947],{"class":5288}," this",[5264,5949,5707],{"class":5270},[5264,5951,5952],{"class":5274},"formatValidationErrors",[5264,5954,5311],{"class":5270},[5264,5956,5957],{"class":5314},"validationErrors",[5264,5959,5960],{"class":5270},"),\n",[5264,5962,5964],{"class":5266,"line":5963},25,[5264,5965,5966],{"class":5270},"    };\n",[5264,5968,5970],{"class":5266,"line":5969},26,[5264,5971,5473],{"emptyLinePlaceholder":5472},[5264,5973,5975,5978,5980,5983,5985,5987,5990,5993,5995,5998],{"class":5266,"line":5974},27,[5264,5976,5977],{"class":5314},"    response",[5264,5979,5707],{"class":5270},[5264,5981,5982],{"class":5274},"status",[5264,5984,5311],{"class":5270},[5264,5986,5982],{"class":5314},[5264,5988,5989],{"class":5270},").",[5264,5991,5992],{"class":5274},"json",[5264,5994,5311],{"class":5270},[5264,5996,5997],{"class":5314},"errorResponse",[5264,5999,6000],{"class":5270},");\n",[5264,6002,6004],{"class":5266,"line":6003},28,[5264,6005,5425],{"class":5270},[5264,6007,6009],{"class":5266,"line":6008},29,[5264,6010,5473],{"emptyLinePlaceholder":5472},[5264,6012,6014,6017,6020,6022,6025,6027,6029,6032,6034],{"class":5266,"line":6013},30,[5264,6015,6016],{"class":5288},"  private",[5264,6018,6019],{"class":5274}," formatValidationErrors",[5264,6021,5311],{"class":5270},[5264,6023,6024],{"class":5314},"errors",[5264,6026,5318],{"class":5270},[5264,6028,5791],{"class":5292},[5264,6030,6031],{"class":5270},"): ",[5264,6033,5791],{"class":5292},[5264,6035,6036],{"class":5270},"[] {\n",[5264,6038,6040,6042,6045,6048,6050,6053,6055,6057],{"class":5266,"line":6039},31,[5264,6041,5348],{"class":5284},[5264,6043,6044],{"class":5270}," (!",[5264,6046,6047],{"class":5314},"Array",[5264,6049,5707],{"class":5270},[5264,6051,6052],{"class":5274},"isArray",[5264,6054,5311],{"class":5270},[5264,6056,6024],{"class":5314},[5264,6058,6059],{"class":5270},")) {\n",[5264,6061,6063,6066,6069,6072,6075],{"class":5266,"line":6062},32,[5264,6064,6065],{"class":5284},"      return",[5264,6067,6068],{"class":5270}," [{ ",[5264,6070,6071],{"class":5314},"message:",[5264,6073,6074],{"class":5314}," errors",[5264,6076,6077],{"class":5270}," }];\n",[5264,6079,6081],{"class":5266,"line":6080},33,[5264,6082,6083],{"class":5270},"    }\n",[5264,6085,6087],{"class":5266,"line":6086},34,[5264,6088,5473],{"emptyLinePlaceholder":5472},[5264,6090,6092,6095,6097,6099,6102,6104,6107,6110],{"class":5266,"line":6091},35,[5264,6093,6094],{"class":5284},"    return",[5264,6096,6074],{"class":5314},[5264,6098,5707],{"class":5270},[5264,6100,6101],{"class":5274},"map",[5264,6103,5311],{"class":5270},[5264,6105,6106],{"class":5314},"error",[5264,6108,6109],{"class":5288}," =>",[5264,6111,6112],{"class":5270}," ({\n",[5264,6114,6116,6119,6122,6124,6127],{"class":5266,"line":6115},36,[5264,6117,6118],{"class":5314},"      field:",[5264,6120,6121],{"class":5314}," error",[5264,6123,5707],{"class":5270},[5264,6125,6126],{"class":5314},"property",[5264,6128,5865],{"class":5270},[5264,6130,6132,6135,6137,6139,6142],{"class":5266,"line":6131},37,[5264,6133,6134],{"class":5314},"      value:",[5264,6136,6121],{"class":5314},[5264,6138,5707],{"class":5270},[5264,6140,6141],{"class":5314},"value",[5264,6143,5865],{"class":5270},[5264,6145,6147,6150,6153,6155,6158,6160,6162,6164,6167],{"class":5266,"line":6146},38,[5264,6148,6149],{"class":5314},"      constraints:",[5264,6151,6152],{"class":5314}," Object",[5264,6154,5707],{"class":5270},[5264,6156,6157],{"class":5274},"values",[5264,6159,5311],{"class":5270},[5264,6161,6106],{"class":5314},[5264,6163,5707],{"class":5270},[5264,6165,6166],{"class":5314},"constraints",[5264,6168,6169],{"class":5270}," || {}),\n",[5264,6171,6173],{"class":5266,"line":6172},39,[5264,6174,6175],{"class":5270},"    }));\n",[5264,6177,6179],{"class":5266,"line":6178},40,[5264,6180,5425],{"class":5270},[5264,6182,6184],{"class":5266,"line":6183},41,[5264,6185,5431],{"class":5270},[5206,6187,6188],{},[5144,6189,6190],{},"Приклад використання:",[5254,6192,6194],{"className":5256,"code":6193,"language":5259,"meta":5260,"style":5260},"\u002F\u002F create-user.dto.ts\nimport { IsEmail, IsString, MinLength, IsInt, Min, Max } from 'class-validator';\n\nexport class CreateUserDto {\n  @IsEmail({}, { message: 'Invalid email format' })\n  email: string;\n\n  @IsString()\n  @MinLength(8, { message: 'Password must be at least 8 characters' })\n  password: string;\n\n  @IsInt()\n  @Min(18, { message: 'Must be at least 18 years old' })\n  @Max(120, { message: 'Invalid age' })\n  age: number;\n}\n\n\u002F\u002F users.controller.ts\n@Controller('users')\n@UseFilters(ValidationExceptionFilter)\nexport class UsersController {\n  @Post()\n  async create(@Body() dto: CreateUserDto) {\n    return this.usersService.create(dto);\n  }\n}\n",[5102,6195,6196,6201,6244,6248,6259,6277,6289,6293,6301,6323,6334,6338,6346,6366,6386,6398,6402,6406,6411,6425,6438,6449,6458,6485,6507,6511],{"__ignoreMap":5260},[5264,6197,6198],{"class":5266,"line":5267},[5264,6199,6200],{"class":5341},"\u002F\u002F create-user.dto.ts\n",[5264,6202,6203,6205,6207,6210,6212,6215,6217,6220,6222,6225,6227,6230,6232,6235,6237,6239,6242],{"class":5266,"line":5281},[5264,6204,5585],{"class":5284},[5264,6206,5463],{"class":5270},[5264,6208,6209],{"class":5314},"IsEmail",[5264,6211,5324],{"class":5270},[5264,6213,6214],{"class":5314},"IsString",[5264,6216,5324],{"class":5270},[5264,6218,6219],{"class":5314},"MinLength",[5264,6221,5324],{"class":5270},[5264,6223,6224],{"class":5314},"IsInt",[5264,6226,5324],{"class":5270},[5264,6228,6229],{"class":5314},"Min",[5264,6231,5324],{"class":5270},[5264,6233,6234],{"class":5314},"Max",[5264,6236,5605],{"class":5270},[5264,6238,5608],{"class":5284},[5264,6240,6241],{"class":5611}," 'class-validator'",[5264,6243,5615],{"class":5270},[5264,6245,6246],{"class":5266,"line":5305},[5264,6247,5473],{"emptyLinePlaceholder":5472},[5264,6249,6250,6252,6254,6257],{"class":5266,"line":5338},[5264,6251,5285],{"class":5284},[5264,6253,5289],{"class":5288},[5264,6255,6256],{"class":5292}," CreateUserDto",[5264,6258,5302],{"class":5270},[5264,6260,6261,6264,6266,6269,6271,6274],{"class":5266,"line":5345},[5264,6262,6263],{"class":5270},"  @",[5264,6265,6209],{"class":5274},[5264,6267,6268],{"class":5270},"({}, { ",[5264,6270,6071],{"class":5314},[5264,6272,6273],{"class":5611}," 'Invalid email format'",[5264,6275,6276],{"class":5270}," })\n",[5264,6278,6279,6282,6284,6287],{"class":5266,"line":5370},[5264,6280,6281],{"class":5314},"  email",[5264,6283,5318],{"class":5270},[5264,6285,6286],{"class":5292},"string",[5264,6288,5615],{"class":5270},[5264,6290,6291],{"class":5266,"line":5394},[5264,6292,5473],{"emptyLinePlaceholder":5472},[5264,6294,6295,6297,6299],{"class":5266,"line":5416},[5264,6296,6263],{"class":5270},[5264,6298,6214],{"class":5274},[5264,6300,5278],{"class":5270},[5264,6302,6303,6305,6307,6309,6313,6316,6318,6321],{"class":5266,"line":5422},[5264,6304,6263],{"class":5270},[5264,6306,6219],{"class":5274},[5264,6308,5311],{"class":5270},[5264,6310,6312],{"class":6311},"sJj4R","8",[5264,6314,6315],{"class":5270},", { ",[5264,6317,6071],{"class":5314},[5264,6319,6320],{"class":5611}," 'Password must be at least 8 characters'",[5264,6322,6276],{"class":5270},[5264,6324,6325,6328,6330,6332],{"class":5266,"line":5428},[5264,6326,6327],{"class":5314},"  password",[5264,6329,5318],{"class":5270},[5264,6331,6286],{"class":5292},[5264,6333,5615],{"class":5270},[5264,6335,6336],{"class":5266,"line":5781},[5264,6337,5473],{"emptyLinePlaceholder":5472},[5264,6339,6340,6342,6344],{"class":5266,"line":5804},[5264,6341,6263],{"class":5270},[5264,6343,6224],{"class":5274},[5264,6345,5278],{"class":5270},[5264,6347,6348,6350,6352,6354,6357,6359,6361,6364],{"class":5266,"line":5809},[5264,6349,6263],{"class":5270},[5264,6351,6229],{"class":5274},[5264,6353,5311],{"class":5270},[5264,6355,6356],{"class":6311},"18",[5264,6358,6315],{"class":5270},[5264,6360,6071],{"class":5314},[5264,6362,6363],{"class":5611}," 'Must be at least 18 years old'",[5264,6365,6276],{"class":5270},[5264,6367,6368,6370,6372,6374,6377,6379,6381,6384],{"class":5266,"line":5815},[5264,6369,6263],{"class":5270},[5264,6371,6234],{"class":5274},[5264,6373,5311],{"class":5270},[5264,6375,6376],{"class":6311},"120",[5264,6378,6315],{"class":5270},[5264,6380,6071],{"class":5314},[5264,6382,6383],{"class":5611}," 'Invalid age'",[5264,6385,6276],{"class":5270},[5264,6387,6388,6391,6393,6396],{"class":5266,"line":5835},[5264,6389,6390],{"class":5314},"  age",[5264,6392,5318],{"class":5270},[5264,6394,6395],{"class":5292},"number",[5264,6397,5615],{"class":5270},[5264,6399,6400],{"class":5266,"line":5840},[5264,6401,5431],{"class":5270},[5264,6403,6404],{"class":5266,"line":5846},[5264,6405,5473],{"emptyLinePlaceholder":5472},[5264,6407,6408],{"class":5266,"line":5857},[5264,6409,6410],{"class":5341},"\u002F\u002F users.controller.ts\n",[5264,6412,6413,6415,6418,6420,6423],{"class":5266,"line":5868},[5264,6414,5271],{"class":5270},[5264,6416,6417],{"class":5274},"Controller",[5264,6419,5311],{"class":5270},[5264,6421,6422],{"class":5611},"'users'",[5264,6424,5451],{"class":5270},[5264,6426,6427,6429,6432,6434,6436],{"class":5266,"line":5879},[5264,6428,5271],{"class":5270},[5264,6430,6431],{"class":5274},"UseFilters",[5264,6433,5311],{"class":5270},[5264,6435,5104],{"class":5314},[5264,6437,5451],{"class":5270},[5264,6439,6440,6442,6444,6447],{"class":5266,"line":5890},[5264,6441,5285],{"class":5284},[5264,6443,5289],{"class":5288},[5264,6445,6446],{"class":5292}," UsersController",[5264,6448,5302],{"class":5270},[5264,6450,6451,6453,6456],{"class":5266,"line":5911},[5264,6452,6263],{"class":5270},[5264,6454,6455],{"class":5274},"Post",[5264,6457,5278],{"class":5270},[5264,6459,6460,6463,6466,6469,6472,6475,6478,6480,6483],{"class":5266,"line":5926},[5264,6461,6462],{"class":5288},"  async",[5264,6464,6465],{"class":5274}," create",[5264,6467,6468],{"class":5270},"(@",[5264,6470,6471],{"class":5274},"Body",[5264,6473,6474],{"class":5270},"() ",[5264,6476,6477],{"class":5314},"dto",[5264,6479,5318],{"class":5270},[5264,6481,6482],{"class":5292},"CreateUserDto",[5264,6484,5335],{"class":5270},[5264,6486,6487,6489,6491,6493,6496,6498,6501,6503,6505],{"class":5266,"line":5941},[5264,6488,6094],{"class":5284},[5264,6490,5947],{"class":5288},[5264,6492,5707],{"class":5270},[5264,6494,6495],{"class":5314},"usersService",[5264,6497,5707],{"class":5270},[5264,6499,6500],{"class":5274},"create",[5264,6502,5311],{"class":5270},[5264,6504,6477],{"class":5314},[5264,6506,6000],{"class":5270},[5264,6508,6509],{"class":5266,"line":5963},[5264,6510,5425],{"class":5270},[5264,6512,6513],{"class":5266,"line":5969},[5264,6514,5431],{"class":5270},[5206,6516,6517],{},[5144,6518,6519],{},"HTTP-запит з невалідними даними:",[5254,6521,6525],{"className":6522,"code":6523,"language":6524,"meta":5260,"style":5260},"language-http shiki shiki-themes light-plus dark-plus dark-plus","POST \u002Fusers HTTP\u002F1.1\nContent-Type: application\u002Fjson\n\n{\n  \"email\": \"invalid-email\",\n  \"password\": \"123\",\n  \"age\": 15\n}\n","http",[5102,6526,6527,6544,6555,6559,6564,6577,6589,6599],{"__ignoreMap":5260},[5264,6528,6529,6532,6535,6538,6541],{"class":5266,"line":5267},[5264,6530,6531],{"class":5284},"POST",[5264,6533,6534],{"class":5270}," \u002Fusers ",[5264,6536,6537],{"class":5288},"HTTP",[5264,6539,6540],{"class":5270},"\u002F",[5264,6542,6543],{"class":6311},"1.1\n",[5264,6545,6546,6550,6552],{"class":5266,"line":5281},[5264,6547,6549],{"class":6548},"sKtos","Content-Type",[5264,6551,5212],{"class":5288},[5264,6553,6554],{"class":5611}," application\u002Fjson\n",[5264,6556,6557],{"class":5266,"line":5305},[5264,6558,5473],{"emptyLinePlaceholder":5472},[5264,6560,6561],{"class":5266,"line":5338},[5264,6562,6563],{"class":5270},"{\n",[5264,6565,6566,6570,6572,6575],{"class":5266,"line":5345},[5264,6567,6569],{"class":6568},"sLwNe","  \"email\"",[5264,6571,5318],{"class":5270},[5264,6573,6574],{"class":5611},"\"invalid-email\"",[5264,6576,5865],{"class":5270},[5264,6578,6579,6582,6584,6587],{"class":5266,"line":5370},[5264,6580,6581],{"class":6568},"  \"password\"",[5264,6583,5318],{"class":5270},[5264,6585,6586],{"class":5611},"\"123\"",[5264,6588,5865],{"class":5270},[5264,6590,6591,6594,6596],{"class":5266,"line":5394},[5264,6592,6593],{"class":6568},"  \"age\"",[5264,6595,5318],{"class":5270},[5264,6597,6598],{"class":6311},"15\n",[5264,6600,6601],{"class":5266,"line":5416},[5264,6602,5431],{"class":5270},[5206,6604,6605],{},[5144,6606,6607],{},"JSON-відповідь:",[5254,6609,6612],{"className":6610,"code":6611,"language":5992,"meta":5260,"style":5260},"language-json shiki shiki-themes light-plus dark-plus dark-plus","{\n  \"statusCode\": 400,\n  \"error\": \"Validation Failed\",\n  \"message\": \"Request validation failed\",\n  \"timestamp\": \"2026-09-05T18:00:00.123Z\",\n  \"path\": \"\u002Fusers\",\n  \"method\": \"POST\",\n  \"errors\": [\n    {\n      \"field\": \"email\",\n      \"value\": \"invalid-email\",\n      \"constraints\": [\"Invalid email format\"]\n    },\n    {\n      \"field\": \"password\",\n      \"value\": \"123\",\n      \"constraints\": [\"Password must be at least 8 characters\"]\n    },\n    {\n      \"field\": \"age\",\n      \"value\": 15,\n      \"constraints\": [\"Must be at least 18 years old\"]\n    }\n  ]\n}\n",[5102,6613,6614,6618,6630,6642,6654,6666,6678,6690,6698,6703,6715,6726,6740,6745,6749,6760,6770,6781,6785,6789,6800,6811,6822,6826,6831],{"__ignoreMap":5260},[5264,6615,6616],{"class":5266,"line":5267},[5264,6617,6563],{"class":5270},[5264,6619,6620,6623,6625,6628],{"class":5266,"line":5281},[5264,6621,6622],{"class":6568},"  \"statusCode\"",[5264,6624,5318],{"class":5270},[5264,6626,6627],{"class":6311},"400",[5264,6629,5865],{"class":5270},[5264,6631,6632,6635,6637,6640],{"class":5266,"line":5305},[5264,6633,6634],{"class":6568},"  \"error\"",[5264,6636,5318],{"class":5270},[5264,6638,6639],{"class":5611},"\"Validation Failed\"",[5264,6641,5865],{"class":5270},[5264,6643,6644,6647,6649,6652],{"class":5266,"line":5338},[5264,6645,6646],{"class":6568},"  \"message\"",[5264,6648,5318],{"class":5270},[5264,6650,6651],{"class":5611},"\"Request validation failed\"",[5264,6653,5865],{"class":5270},[5264,6655,6656,6659,6661,6664],{"class":5266,"line":5345},[5264,6657,6658],{"class":6568},"  \"timestamp\"",[5264,6660,5318],{"class":5270},[5264,6662,6663],{"class":5611},"\"2026-09-05T18:00:00.123Z\"",[5264,6665,5865],{"class":5270},[5264,6667,6668,6671,6673,6676],{"class":5266,"line":5370},[5264,6669,6670],{"class":6568},"  \"path\"",[5264,6672,5318],{"class":5270},[5264,6674,6675],{"class":5611},"\"\u002Fusers\"",[5264,6677,5865],{"class":5270},[5264,6679,6680,6683,6685,6688],{"class":5266,"line":5394},[5264,6681,6682],{"class":6568},"  \"method\"",[5264,6684,5318],{"class":5270},[5264,6686,6687],{"class":5611},"\"POST\"",[5264,6689,5865],{"class":5270},[5264,6691,6692,6695],{"class":5266,"line":5416},[5264,6693,6694],{"class":6568},"  \"errors\"",[5264,6696,6697],{"class":5270},": [\n",[5264,6699,6700],{"class":5266,"line":5422},[5264,6701,6702],{"class":5270},"    {\n",[5264,6704,6705,6708,6710,6713],{"class":5266,"line":5428},[5264,6706,6707],{"class":6568},"      \"field\"",[5264,6709,5318],{"class":5270},[5264,6711,6712],{"class":5611},"\"email\"",[5264,6714,5865],{"class":5270},[5264,6716,6717,6720,6722,6724],{"class":5266,"line":5781},[5264,6718,6719],{"class":6568},"      \"value\"",[5264,6721,5318],{"class":5270},[5264,6723,6574],{"class":5611},[5264,6725,5865],{"class":5270},[5264,6727,6728,6731,6734,6737],{"class":5266,"line":5804},[5264,6729,6730],{"class":6568},"      \"constraints\"",[5264,6732,6733],{"class":5270},": [",[5264,6735,6736],{"class":5611},"\"Invalid email format\"",[5264,6738,6739],{"class":5270},"]\n",[5264,6741,6742],{"class":5266,"line":5809},[5264,6743,6744],{"class":5270},"    },\n",[5264,6746,6747],{"class":5266,"line":5815},[5264,6748,6702],{"class":5270},[5264,6750,6751,6753,6755,6758],{"class":5266,"line":5835},[5264,6752,6707],{"class":6568},[5264,6754,5318],{"class":5270},[5264,6756,6757],{"class":5611},"\"password\"",[5264,6759,5865],{"class":5270},[5264,6761,6762,6764,6766,6768],{"class":5266,"line":5840},[5264,6763,6719],{"class":6568},[5264,6765,5318],{"class":5270},[5264,6767,6586],{"class":5611},[5264,6769,5865],{"class":5270},[5264,6771,6772,6774,6776,6779],{"class":5266,"line":5846},[5264,6773,6730],{"class":6568},[5264,6775,6733],{"class":5270},[5264,6777,6778],{"class":5611},"\"Password must be at least 8 characters\"",[5264,6780,6739],{"class":5270},[5264,6782,6783],{"class":5266,"line":5857},[5264,6784,6744],{"class":5270},[5264,6786,6787],{"class":5266,"line":5868},[5264,6788,6702],{"class":5270},[5264,6790,6791,6793,6795,6798],{"class":5266,"line":5879},[5264,6792,6707],{"class":6568},[5264,6794,5318],{"class":5270},[5264,6796,6797],{"class":5611},"\"age\"",[5264,6799,5865],{"class":5270},[5264,6801,6802,6804,6806,6809],{"class":5266,"line":5890},[5264,6803,6719],{"class":6568},[5264,6805,5318],{"class":5270},[5264,6807,6808],{"class":6311},"15",[5264,6810,5865],{"class":5270},[5264,6812,6813,6815,6817,6820],{"class":5266,"line":5911},[5264,6814,6730],{"class":6568},[5264,6816,6733],{"class":5270},[5264,6818,6819],{"class":5611},"\"Must be at least 18 years old\"",[5264,6821,6739],{"class":5270},[5264,6823,6824],{"class":5266,"line":5926},[5264,6825,6083],{"class":5270},[5264,6827,6828],{"class":5266,"line":5941},[5264,6829,6830],{"class":5270},"  ]\n",[5264,6832,6833],{"class":5266,"line":5963},[5264,6834,5431],{"class":5270},[5572,6836,6838],{"id":6837},"розширена-версія-з-групуванням-помилок","Розширена версія з групуванням помилок",[5254,6840,6842],{"className":5256,"code":6841,"language":5259,"meta":5260,"style":5260},"@Catch(BadRequestException)\nexport class AdvancedValidationExceptionFilter implements ExceptionFilter {\n  catch(exception: BadRequestException, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse();\n    const request = ctx.getRequest();\n    const exceptionResponse: any = exception.getResponse();\n\n    const validationErrors = exceptionResponse.message;\n\n    \u002F\u002F Групування помилок за полями\n    const fieldErrors = this.groupErrorsByField(validationErrors);\n\n    response.status(400).json({\n      statusCode: 400,\n      error: 'Validation Failed',\n      message: `${Object.keys(fieldErrors).length} field(s) failed validation`,\n      timestamp: new Date().toISOString(),\n      path: request.url,\n      fields: fieldErrors,\n    });\n  }\n\n  private groupErrorsByField(errors: any): Record\u003Cstring, string[]> {\n    if (!Array.isArray(errors)) {\n      return { general: [errors] };\n    }\n\n    const grouped: Record\u003Cstring, string[]> = {};\n\n    errors.forEach(error => {\n      const field = error.property;\n      const messages = Object.values(error.constraints || {}) as string[];\n      grouped[field] = messages;\n    });\n\n    return grouped;\n  }\n}\n",[5102,6843,6844,6856,6871,6893,6909,6925,6941,6961,6965,6981,6985,6990,7013,7017,7036,7045,7053,7090,7104,7116,7125,7130,7134,7138,7169,7187,7204,7208,7212,7234,7238,7256,7274,7309,7328,7332,7336,7344,7348],{"__ignoreMap":5260},[5264,6845,6846,6848,6850,6852,6854],{"class":5266,"line":5267},[5264,6847,5271],{"class":5270},[5264,6849,5275],{"class":5274},[5264,6851,5311],{"class":5270},[5264,6853,5448],{"class":5314},[5264,6855,5451],{"class":5270},[5264,6857,6858,6860,6862,6865,6867,6869],{"class":5266,"line":5281},[5264,6859,5285],{"class":5284},[5264,6861,5289],{"class":5288},[5264,6863,6864],{"class":5292}," AdvancedValidationExceptionFilter",[5264,6866,5296],{"class":5288},[5264,6868,5299],{"class":5292},[5264,6870,5302],{"class":5270},[5264,6872,6873,6875,6877,6879,6881,6883,6885,6887,6889,6891],{"class":5266,"line":5305},[5264,6874,5308],{"class":5274},[5264,6876,5311],{"class":5270},[5264,6878,5315],{"class":5314},[5264,6880,5318],{"class":5270},[5264,6882,5448],{"class":5292},[5264,6884,5324],{"class":5270},[5264,6886,5327],{"class":5314},[5264,6888,5318],{"class":5270},[5264,6890,5332],{"class":5292},[5264,6892,5335],{"class":5270},[5264,6894,6895,6897,6899,6901,6903,6905,6907],{"class":5266,"line":5338},[5264,6896,5695],{"class":5288},[5264,6898,5699],{"class":5698},[5264,6900,5702],{"class":5270},[5264,6902,5327],{"class":5314},[5264,6904,5707],{"class":5270},[5264,6906,5710],{"class":5274},[5264,6908,5713],{"class":5270},[5264,6910,6911,6913,6915,6917,6919,6921,6923],{"class":5266,"line":5345},[5264,6912,5695],{"class":5288},[5264,6914,5720],{"class":5698},[5264,6916,5702],{"class":5270},[5264,6918,5725],{"class":5314},[5264,6920,5707],{"class":5270},[5264,6922,5730],{"class":5274},[5264,6924,5713],{"class":5270},[5264,6926,6927,6929,6931,6933,6935,6937,6939],{"class":5266,"line":5370},[5264,6928,5695],{"class":5288},[5264,6930,5745],{"class":5698},[5264,6932,5702],{"class":5270},[5264,6934,5725],{"class":5314},[5264,6936,5707],{"class":5270},[5264,6938,5754],{"class":5274},[5264,6940,5713],{"class":5270},[5264,6942,6943,6945,6947,6949,6951,6953,6955,6957,6959],{"class":5266,"line":5394},[5264,6944,5695],{"class":5288},[5264,6946,5786],{"class":5698},[5264,6948,5318],{"class":5270},[5264,6950,5791],{"class":5292},[5264,6952,5702],{"class":5270},[5264,6954,5315],{"class":5314},[5264,6956,5707],{"class":5270},[5264,6958,5730],{"class":5274},[5264,6960,5713],{"class":5270},[5264,6962,6963],{"class":5266,"line":5416},[5264,6964,5473],{"emptyLinePlaceholder":5472},[5264,6966,6967,6969,6971,6973,6975,6977,6979],{"class":5266,"line":5422},[5264,6968,5695],{"class":5288},[5264,6970,5820],{"class":5698},[5264,6972,5702],{"class":5270},[5264,6974,5825],{"class":5314},[5264,6976,5707],{"class":5270},[5264,6978,5830],{"class":5314},[5264,6980,5615],{"class":5270},[5264,6982,6983],{"class":5266,"line":5428},[5264,6984,5473],{"emptyLinePlaceholder":5472},[5264,6986,6987],{"class":5266,"line":5781},[5264,6988,6989],{"class":5341},"    \u002F\u002F Групування помилок за полями\n",[5264,6991,6992,6994,6997,6999,7002,7004,7007,7009,7011],{"class":5266,"line":5804},[5264,6993,5695],{"class":5288},[5264,6995,6996],{"class":5698}," fieldErrors",[5264,6998,5702],{"class":5270},[5264,7000,7001],{"class":5288},"this",[5264,7003,5707],{"class":5270},[5264,7005,7006],{"class":5274},"groupErrorsByField",[5264,7008,5311],{"class":5270},[5264,7010,5957],{"class":5314},[5264,7012,6000],{"class":5270},[5264,7014,7015],{"class":5266,"line":5809},[5264,7016,5473],{"emptyLinePlaceholder":5472},[5264,7018,7019,7021,7023,7025,7027,7029,7031,7033],{"class":5266,"line":5815},[5264,7020,5977],{"class":5314},[5264,7022,5707],{"class":5270},[5264,7024,5982],{"class":5274},[5264,7026,5311],{"class":5270},[5264,7028,6627],{"class":6311},[5264,7030,5989],{"class":5270},[5264,7032,5992],{"class":5274},[5264,7034,7035],{"class":5270},"({\n",[5264,7037,7038,7040,7043],{"class":5266,"line":5835},[5264,7039,5860],{"class":5314},[5264,7041,7042],{"class":6311}," 400",[5264,7044,5865],{"class":5270},[5264,7046,7047,7049,7051],{"class":5266,"line":5840},[5264,7048,5871],{"class":5314},[5264,7050,5874],{"class":5611},[5264,7052,5865],{"class":5270},[5264,7054,7055,7057,7060,7063,7066,7069,7072,7074,7077,7079,7082,7085,7088],{"class":5266,"line":5846},[5264,7056,5882],{"class":5314},[5264,7058,7059],{"class":5611}," `",[5264,7061,7062],{"class":5288},"${",[5264,7064,7065],{"class":5314},"Object",[5264,7067,5707],{"class":7068},"sD7JJ",[5264,7070,7071],{"class":5274},"keys",[5264,7073,5311],{"class":7068},[5264,7075,7076],{"class":5314},"fieldErrors",[5264,7078,5989],{"class":7068},[5264,7080,7081],{"class":5314},"length",[5264,7083,7084],{"class":5288},"}",[5264,7086,7087],{"class":5611}," field(s) failed validation`",[5264,7089,5865],{"class":5270},[5264,7091,7092,7094,7096,7098,7100,7102],{"class":5266,"line":5857},[5264,7093,5893],{"class":5314},[5264,7095,5896],{"class":5288},[5264,7097,5899],{"class":5274},[5264,7099,5902],{"class":5270},[5264,7101,5905],{"class":5274},[5264,7103,5908],{"class":5270},[5264,7105,7106,7108,7110,7112,7114],{"class":5266,"line":5868},[5264,7107,5914],{"class":5314},[5264,7109,5745],{"class":5314},[5264,7111,5707],{"class":5270},[5264,7113,5921],{"class":5314},[5264,7115,5865],{"class":5270},[5264,7117,7118,7121,7123],{"class":5266,"line":5879},[5264,7119,7120],{"class":5314},"      fields:",[5264,7122,6996],{"class":5314},[5264,7124,5865],{"class":5270},[5264,7126,7127],{"class":5266,"line":5890},[5264,7128,7129],{"class":5270},"    });\n",[5264,7131,7132],{"class":5266,"line":5911},[5264,7133,5425],{"class":5270},[5264,7135,7136],{"class":5266,"line":5926},[5264,7137,5473],{"emptyLinePlaceholder":5472},[5264,7139,7140,7142,7145,7147,7149,7151,7153,7155,7158,7160,7162,7164,7166],{"class":5266,"line":5941},[5264,7141,6016],{"class":5288},[5264,7143,7144],{"class":5274}," groupErrorsByField",[5264,7146,5311],{"class":5270},[5264,7148,6024],{"class":5314},[5264,7150,5318],{"class":5270},[5264,7152,5791],{"class":5292},[5264,7154,6031],{"class":5270},[5264,7156,7157],{"class":5292},"Record",[5264,7159,5733],{"class":5270},[5264,7161,6286],{"class":5292},[5264,7163,5324],{"class":5270},[5264,7165,6286],{"class":5292},[5264,7167,7168],{"class":5270},"[]> {\n",[5264,7170,7171,7173,7175,7177,7179,7181,7183,7185],{"class":5266,"line":5963},[5264,7172,5348],{"class":5284},[5264,7174,6044],{"class":5270},[5264,7176,6047],{"class":5314},[5264,7178,5707],{"class":5270},[5264,7180,6052],{"class":5274},[5264,7182,5311],{"class":5270},[5264,7184,6024],{"class":5314},[5264,7186,6059],{"class":5270},[5264,7188,7189,7191,7193,7196,7199,7201],{"class":5266,"line":5969},[5264,7190,6065],{"class":5284},[5264,7192,5463],{"class":5270},[5264,7194,7195],{"class":5314},"general:",[5264,7197,7198],{"class":5270}," [",[5264,7200,6024],{"class":5314},[5264,7202,7203],{"class":5270},"] };\n",[5264,7205,7206],{"class":5266,"line":5974},[5264,7207,6083],{"class":5270},[5264,7209,7210],{"class":5266,"line":6003},[5264,7211,5473],{"emptyLinePlaceholder":5472},[5264,7213,7214,7216,7219,7221,7223,7225,7227,7229,7231],{"class":5266,"line":6008},[5264,7215,5695],{"class":5288},[5264,7217,7218],{"class":5698}," grouped",[5264,7220,5318],{"class":5270},[5264,7222,7157],{"class":5292},[5264,7224,5733],{"class":5270},[5264,7226,6286],{"class":5292},[5264,7228,5324],{"class":5270},[5264,7230,6286],{"class":5292},[5264,7232,7233],{"class":5270},"[]> = {};\n",[5264,7235,7236],{"class":5266,"line":6013},[5264,7237,5473],{"emptyLinePlaceholder":5472},[5264,7239,7240,7243,7245,7248,7250,7252,7254],{"class":5266,"line":6039},[5264,7241,7242],{"class":5314},"    errors",[5264,7244,5707],{"class":5270},[5264,7246,7247],{"class":5274},"forEach",[5264,7249,5311],{"class":5270},[5264,7251,6106],{"class":5314},[5264,7253,6109],{"class":5288},[5264,7255,5302],{"class":5270},[5264,7257,7258,7261,7264,7266,7268,7270,7272],{"class":5266,"line":6062},[5264,7259,7260],{"class":5288},"      const",[5264,7262,7263],{"class":5698}," field",[5264,7265,5702],{"class":5270},[5264,7267,6106],{"class":5314},[5264,7269,5707],{"class":5270},[5264,7271,6126],{"class":5314},[5264,7273,5615],{"class":5270},[5264,7275,7276,7278,7281,7283,7285,7287,7289,7291,7293,7295,7297,7300,7303,7306],{"class":5266,"line":6080},[5264,7277,7260],{"class":5288},[5264,7279,7280],{"class":5698}," messages",[5264,7282,5702],{"class":5270},[5264,7284,7065],{"class":5314},[5264,7286,5707],{"class":5270},[5264,7288,6157],{"class":5274},[5264,7290,5311],{"class":5270},[5264,7292,6106],{"class":5314},[5264,7294,5707],{"class":5270},[5264,7296,6166],{"class":5314},[5264,7298,7299],{"class":5270}," || {}) ",[5264,7301,7302],{"class":5284},"as",[5264,7304,7305],{"class":5292}," string",[5264,7307,7308],{"class":5270},"[];\n",[5264,7310,7311,7314,7317,7320,7323,7326],{"class":5266,"line":6086},[5264,7312,7313],{"class":5314},"      grouped",[5264,7315,7316],{"class":5270},"[",[5264,7318,7319],{"class":5314},"field",[5264,7321,7322],{"class":5270},"] = ",[5264,7324,7325],{"class":5314},"messages",[5264,7327,5615],{"class":5270},[5264,7329,7330],{"class":5266,"line":6091},[5264,7331,7129],{"class":5270},[5264,7333,7334],{"class":5266,"line":6115},[5264,7335,5473],{"emptyLinePlaceholder":5472},[5264,7337,7338,7340,7342],{"class":5266,"line":6131},[5264,7339,6094],{"class":5284},[5264,7341,7218],{"class":5314},[5264,7343,5615],{"class":5270},[5264,7345,7346],{"class":5266,"line":6146},[5264,7347,5425],{"class":5270},[5264,7349,7350],{"class":5266,"line":6172},[5264,7351,5431],{"class":5270},[5206,7353,7354],{},[5144,7355,7356],{},"JSON-відповідь (згруповано):",[5254,7358,7360],{"className":6610,"code":7359,"language":5992,"meta":5260,"style":5260},"{\n  \"statusCode\": 400,\n  \"error\": \"Validation Failed\",\n  \"message\": \"3 field(s) failed validation\",\n  \"timestamp\": \"2026-09-05T18:00:00.123Z\",\n  \"path\": \"\u002Fusers\",\n  \"fields\": {\n    \"email\": [\"Invalid email format\"],\n    \"password\": [\"Password must be at least 8 characters\"],\n    \"age\": [\"Must be at least 18 years old\"]\n  }\n}\n",[5102,7361,7362,7366,7376,7386,7397,7407,7417,7425,7437,7448,7459,7463],{"__ignoreMap":5260},[5264,7363,7364],{"class":5266,"line":5267},[5264,7365,6563],{"class":5270},[5264,7367,7368,7370,7372,7374],{"class":5266,"line":5281},[5264,7369,6622],{"class":6568},[5264,7371,5318],{"class":5270},[5264,7373,6627],{"class":6311},[5264,7375,5865],{"class":5270},[5264,7377,7378,7380,7382,7384],{"class":5266,"line":5305},[5264,7379,6634],{"class":6568},[5264,7381,5318],{"class":5270},[5264,7383,6639],{"class":5611},[5264,7385,5865],{"class":5270},[5264,7387,7388,7390,7392,7395],{"class":5266,"line":5338},[5264,7389,6646],{"class":6568},[5264,7391,5318],{"class":5270},[5264,7393,7394],{"class":5611},"\"3 field(s) failed validation\"",[5264,7396,5865],{"class":5270},[5264,7398,7399,7401,7403,7405],{"class":5266,"line":5345},[5264,7400,6658],{"class":6568},[5264,7402,5318],{"class":5270},[5264,7404,6663],{"class":5611},[5264,7406,5865],{"class":5270},[5264,7408,7409,7411,7413,7415],{"class":5266,"line":5370},[5264,7410,6670],{"class":6568},[5264,7412,5318],{"class":5270},[5264,7414,6675],{"class":5611},[5264,7416,5865],{"class":5270},[5264,7418,7419,7422],{"class":5266,"line":5394},[5264,7420,7421],{"class":6568},"  \"fields\"",[5264,7423,7424],{"class":5270},": {\n",[5264,7426,7427,7430,7432,7434],{"class":5266,"line":5416},[5264,7428,7429],{"class":6568},"    \"email\"",[5264,7431,6733],{"class":5270},[5264,7433,6736],{"class":5611},[5264,7435,7436],{"class":5270},"],\n",[5264,7438,7439,7442,7444,7446],{"class":5266,"line":5422},[5264,7440,7441],{"class":6568},"    \"password\"",[5264,7443,6733],{"class":5270},[5264,7445,6778],{"class":5611},[5264,7447,7436],{"class":5270},[5264,7449,7450,7453,7455,7457],{"class":5266,"line":5428},[5264,7451,7452],{"class":6568},"    \"age\"",[5264,7454,6733],{"class":5270},[5264,7456,6819],{"class":5611},[5264,7458,6739],{"class":5270},[5264,7460,7461],{"class":5266,"line":5781},[5264,7462,5425],{"class":5270},[5264,7464,7465],{"class":5266,"line":5804},[5264,7466,5431],{"class":5270},[7468,7469,7470,7473,7474,7477,7478,5707],"tip",{},[5144,7471,7472],{},"Порада:"," групування помилок за полями спрощує відображення в UI-формах. Frontend може безпосередньо прив'язати помилки до інпутів: ",[5102,7475,7476],{},"fields['email']"," → ",[5102,7479,7480],{},"\u003Cinput name=\"email\" error=\"...\">",[5201,7482,7484],{"id":7483},"databaseexceptionfilter-трансформація-помилок-orm","DatabaseExceptionFilter: трансформація помилок ORM",[5206,7486,7487,7488,7491,7492,7494],{},"Помилки бази даних (TypeORM, Sequelize, Prisma) містять SQL-деталі, які ",[5144,7489,7490],{},"не повинні"," потрапляти до клієнта. ",[5102,7493,5111],{}," трансформує їх у зрозумілі повідомлення:",[5572,7496,7498],{"id":7497},"filter-для-typeorm","Filter для TypeORM",[5254,7500,7502],{"className":5256,"code":7501,"language":5259,"meta":5260,"style":5260},"import { ExceptionFilter, Catch, ArgumentsHost, HttpStatus, Logger } from '@nestjs\u002Fcommon';\nimport { QueryFailedError } from 'typeorm';\nimport { Response } from 'express';\n\n@Catch(QueryFailedError)\nexport class DatabaseExceptionFilter implements ExceptionFilter {\n  private readonly logger = new Logger(DatabaseExceptionFilter.name);\n\n  catch(exception: QueryFailedError, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse\u003CResponse>();\n    const request = ctx.getRequest();\n\n    \u002F\u002F Логування повної помилки (для дебагу)\n    this.logger.error('Database error', {\n      message: exception.message,\n      query: exception.query,\n      parameters: exception.parameters,\n      driverError: exception.driverError,\n    });\n\n    \u002F\u002F Витягування коду помилки (PostgreSQL)\n    const errorCode = (exception.driverError as any)?.code;\n    const constraint = (exception.driverError as any)?.constraint;\n\n    \u002F\u002F Трансформація у HTTP-відповідь\n    const { statusCode, message } = this.mapDatabaseError(errorCode, constraint, exception);\n\n    response.status(statusCode).json({\n      statusCode,\n      error: 'Database Error',\n      message,\n      timestamp: new Date().toISOString(),\n      path: request.url,\n    });\n  }\n\n  private mapDatabaseError(\n    code: string,\n    constraint: string,\n    exception: QueryFailedError\n  ): { statusCode: number; message: string } {\n    switch (code) {\n      case '23505': \u002F\u002F unique_violation\n        return {\n          statusCode: HttpStatus.CONFLICT,\n          message: this.extractUniqueViolationMessage(constraint, exception),\n        };\n\n      case '23503': \u002F\u002F foreign_key_violation\n        return {\n          statusCode: HttpStatus.BAD_REQUEST,\n          message: 'Referenced record does not exist',\n        };\n\n      case '23502': \u002F\u002F not_null_violation\n        return {\n          statusCode: HttpStatus.BAD_REQUEST,\n          message: this.extractNotNullViolationMessage(exception),\n        };\n\n      case '22P02': \u002F\u002F invalid_text_representation\n        return {\n          statusCode: HttpStatus.BAD_REQUEST,\n          message: 'Invalid data format',\n        };\n\n      case '22001': \u002F\u002F string_data_right_truncation\n        return {\n          statusCode: HttpStatus.BAD_REQUEST,\n          message: 'Data too long for field',\n        };\n\n      case '42P01': \u002F\u002F undefined_table\n        return {\n          statusCode: HttpStatus.INTERNAL_SERVER_ERROR,\n          message: 'Database configuration error',\n        };\n\n      default:\n        return {\n          statusCode: HttpStatus.INTERNAL_SERVER_ERROR,\n          message: 'An unexpected database error occurred',\n        };\n    }\n  }\n\n  private extractUniqueViolationMessage(constraint: string, exception: QueryFailedError): string {\n    \u002F\u002F Витягування назви поля з constraint name\n    \u002F\u002F Наприклад: \"users_email_key\" → \"email\"\n    const match = constraint?.match(\u002F^(.+?)_(.+?)_key$\u002F);\n    const field = match ? match[2] : 'field';\n\n    return `Duplicate value: ${field} already exists`;\n  }\n\n  private extractNotNullViolationMessage(exception: QueryFailedError): string {\n    \u002F\u002F Витягування назви колонки з повідомлення помилки\n    const match = exception.message.match(\u002Fcolumn \"(.+?)\"\u002F);\n    const column = match ? match[1] : 'field';\n\n    return `Required field missing: ${column}`;\n  }\n}\n",[5102,7503,7504,7538,7555,7571,7575,7587,7601,7630,7634,7656,7672,7692,7708,7712,7717,7739,7752,7766,7780,7794,7798,7802,7807,7836,7862,7866,7871,7909,7913,7931,7938,7947,7954,7968,7980,7984,7988,7992,8002,8013,8024,8034,8058,8070,8084,8092,8108,8131,8137,8142,8155,8162,8176,8186,8191,8196,8209,8216,8229,8247,8252,8257,8270,8277,8290,8300,8305,8310,8323,8330,8343,8353,8358,8363,8376,8383,8397,8407,8412,8417,8426,8433,8446,8456,8461,8466,8471,8476,8506,8512,8518,8578,8607,8612,8631,8636,8641,8663,8669,8706,8733,8738,8758,8763],{"__ignoreMap":5260},[5264,7505,7506,7508,7510,7512,7514,7516,7518,7520,7522,7525,7527,7530,7532,7534,7536],{"class":5266,"line":5267},[5264,7507,5585],{"class":5284},[5264,7509,5463],{"class":5270},[5264,7511,5590],{"class":5314},[5264,7513,5324],{"class":5270},[5264,7515,5275],{"class":5314},[5264,7517,5324],{"class":5270},[5264,7519,5332],{"class":5314},[5264,7521,5324],{"class":5270},[5264,7523,7524],{"class":5314},"HttpStatus",[5264,7526,5324],{"class":5270},[5264,7528,7529],{"class":5314},"Logger",[5264,7531,5605],{"class":5270},[5264,7533,5608],{"class":5284},[5264,7535,5612],{"class":5611},[5264,7537,5615],{"class":5270},[5264,7539,7540,7542,7544,7546,7548,7550,7553],{"class":5266,"line":5281},[5264,7541,5585],{"class":5284},[5264,7543,5463],{"class":5270},[5264,7545,5484],{"class":5314},[5264,7547,5605],{"class":5270},[5264,7549,5608],{"class":5284},[5264,7551,7552],{"class":5611}," 'typeorm'",[5264,7554,5615],{"class":5270},[5264,7556,7557,7559,7561,7563,7565,7567,7569],{"class":5266,"line":5305},[5264,7558,5585],{"class":5284},[5264,7560,5463],{"class":5270},[5264,7562,5629],{"class":5314},[5264,7564,5605],{"class":5270},[5264,7566,5608],{"class":5284},[5264,7568,5636],{"class":5611},[5264,7570,5615],{"class":5270},[5264,7572,7573],{"class":5266,"line":5338},[5264,7574,5473],{"emptyLinePlaceholder":5472},[5264,7576,7577,7579,7581,7583,7585],{"class":5266,"line":5345},[5264,7578,5271],{"class":5270},[5264,7580,5275],{"class":5274},[5264,7582,5311],{"class":5270},[5264,7584,5484],{"class":5314},[5264,7586,5451],{"class":5270},[5264,7588,7589,7591,7593,7595,7597,7599],{"class":5266,"line":5370},[5264,7590,5285],{"class":5284},[5264,7592,5289],{"class":5288},[5264,7594,5495],{"class":5292},[5264,7596,5296],{"class":5288},[5264,7598,5299],{"class":5292},[5264,7600,5302],{"class":5270},[5264,7602,7603,7605,7608,7611,7613,7616,7619,7621,7623,7625,7628],{"class":5266,"line":5394},[5264,7604,6016],{"class":5288},[5264,7606,7607],{"class":5288}," readonly",[5264,7609,7610],{"class":5314}," logger",[5264,7612,5702],{"class":5270},[5264,7614,7615],{"class":5288},"new",[5264,7617,7618],{"class":5274}," Logger",[5264,7620,5311],{"class":5270},[5264,7622,5111],{"class":5314},[5264,7624,5707],{"class":5270},[5264,7626,7627],{"class":5314},"name",[5264,7629,6000],{"class":5270},[5264,7631,7632],{"class":5266,"line":5416},[5264,7633,5473],{"emptyLinePlaceholder":5472},[5264,7635,7636,7638,7640,7642,7644,7646,7648,7650,7652,7654],{"class":5266,"line":5422},[5264,7637,5308],{"class":5274},[5264,7639,5311],{"class":5270},[5264,7641,5315],{"class":5314},[5264,7643,5318],{"class":5270},[5264,7645,5484],{"class":5292},[5264,7647,5324],{"class":5270},[5264,7649,5327],{"class":5314},[5264,7651,5318],{"class":5270},[5264,7653,5332],{"class":5292},[5264,7655,5335],{"class":5270},[5264,7657,7658,7660,7662,7664,7666,7668,7670],{"class":5266,"line":5428},[5264,7659,5695],{"class":5288},[5264,7661,5699],{"class":5698},[5264,7663,5702],{"class":5270},[5264,7665,5327],{"class":5314},[5264,7667,5707],{"class":5270},[5264,7669,5710],{"class":5274},[5264,7671,5713],{"class":5270},[5264,7673,7674,7676,7678,7680,7682,7684,7686,7688,7690],{"class":5266,"line":5781},[5264,7675,5695],{"class":5288},[5264,7677,5720],{"class":5698},[5264,7679,5702],{"class":5270},[5264,7681,5725],{"class":5314},[5264,7683,5707],{"class":5270},[5264,7685,5730],{"class":5274},[5264,7687,5733],{"class":5270},[5264,7689,5629],{"class":5292},[5264,7691,5738],{"class":5270},[5264,7693,7694,7696,7698,7700,7702,7704,7706],{"class":5266,"line":5804},[5264,7695,5695],{"class":5288},[5264,7697,5745],{"class":5698},[5264,7699,5702],{"class":5270},[5264,7701,5725],{"class":5314},[5264,7703,5707],{"class":5270},[5264,7705,5754],{"class":5274},[5264,7707,5713],{"class":5270},[5264,7709,7710],{"class":5266,"line":5809},[5264,7711,5473],{"emptyLinePlaceholder":5472},[5264,7713,7714],{"class":5266,"line":5815},[5264,7715,7716],{"class":5341},"    \u002F\u002F Логування повної помилки (для дебагу)\n",[5264,7718,7719,7722,7724,7727,7729,7731,7733,7736],{"class":5266,"line":5835},[5264,7720,7721],{"class":5288},"    this",[5264,7723,5707],{"class":5270},[5264,7725,7726],{"class":5314},"logger",[5264,7728,5707],{"class":5270},[5264,7730,6106],{"class":5274},[5264,7732,5311],{"class":5270},[5264,7734,7735],{"class":5611},"'Database error'",[5264,7737,7738],{"class":5270},", {\n",[5264,7740,7741,7743,7746,7748,7750],{"class":5266,"line":5840},[5264,7742,5882],{"class":5314},[5264,7744,7745],{"class":5314}," exception",[5264,7747,5707],{"class":5270},[5264,7749,5830],{"class":5314},[5264,7751,5865],{"class":5270},[5264,7753,7754,7757,7759,7761,7764],{"class":5266,"line":5846},[5264,7755,7756],{"class":5314},"      query:",[5264,7758,7745],{"class":5314},[5264,7760,5707],{"class":5270},[5264,7762,7763],{"class":5314},"query",[5264,7765,5865],{"class":5270},[5264,7767,7768,7771,7773,7775,7778],{"class":5266,"line":5857},[5264,7769,7770],{"class":5314},"      parameters:",[5264,7772,7745],{"class":5314},[5264,7774,5707],{"class":5270},[5264,7776,7777],{"class":5314},"parameters",[5264,7779,5865],{"class":5270},[5264,7781,7782,7785,7787,7789,7792],{"class":5266,"line":5868},[5264,7783,7784],{"class":5314},"      driverError:",[5264,7786,7745],{"class":5314},[5264,7788,5707],{"class":5270},[5264,7790,7791],{"class":5314},"driverError",[5264,7793,5865],{"class":5270},[5264,7795,7796],{"class":5266,"line":5879},[5264,7797,7129],{"class":5270},[5264,7799,7800],{"class":5266,"line":5890},[5264,7801,5473],{"emptyLinePlaceholder":5472},[5264,7803,7804],{"class":5266,"line":5911},[5264,7805,7806],{"class":5341},"    \u002F\u002F Витягування коду помилки (PostgreSQL)\n",[5264,7808,7809,7811,7814,7817,7819,7821,7823,7826,7829,7832,7834],{"class":5266,"line":5926},[5264,7810,5695],{"class":5288},[5264,7812,7813],{"class":5698}," errorCode",[5264,7815,7816],{"class":5270}," = (",[5264,7818,5315],{"class":5314},[5264,7820,5707],{"class":5270},[5264,7822,7791],{"class":5314},[5264,7824,7825],{"class":5284}," as",[5264,7827,7828],{"class":5292}," any",[5264,7830,7831],{"class":5270},")?.",[5264,7833,5102],{"class":5314},[5264,7835,5615],{"class":5270},[5264,7837,7838,7840,7843,7845,7847,7849,7851,7853,7855,7857,7860],{"class":5266,"line":5941},[5264,7839,5695],{"class":5288},[5264,7841,7842],{"class":5698}," constraint",[5264,7844,7816],{"class":5270},[5264,7846,5315],{"class":5314},[5264,7848,5707],{"class":5270},[5264,7850,7791],{"class":5314},[5264,7852,7825],{"class":5284},[5264,7854,7828],{"class":5292},[5264,7856,7831],{"class":5270},[5264,7858,7859],{"class":5314},"constraint",[5264,7861,5615],{"class":5270},[5264,7863,7864],{"class":5266,"line":5963},[5264,7865,5473],{"emptyLinePlaceholder":5472},[5264,7867,7868],{"class":5266,"line":5969},[5264,7869,7870],{"class":5341},"    \u002F\u002F Трансформація у HTTP-відповідь\n",[5264,7872,7873,7875,7877,7880,7882,7884,7887,7889,7891,7894,7896,7899,7901,7903,7905,7907],{"class":5266,"line":5974},[5264,7874,5695],{"class":5288},[5264,7876,5463],{"class":5270},[5264,7878,7879],{"class":5698},"statusCode",[5264,7881,5324],{"class":5270},[5264,7883,5830],{"class":5698},[5264,7885,7886],{"class":5270}," } = ",[5264,7888,7001],{"class":5288},[5264,7890,5707],{"class":5270},[5264,7892,7893],{"class":5274},"mapDatabaseError",[5264,7895,5311],{"class":5270},[5264,7897,7898],{"class":5314},"errorCode",[5264,7900,5324],{"class":5270},[5264,7902,7859],{"class":5314},[5264,7904,5324],{"class":5270},[5264,7906,5315],{"class":5314},[5264,7908,6000],{"class":5270},[5264,7910,7911],{"class":5266,"line":6003},[5264,7912,5473],{"emptyLinePlaceholder":5472},[5264,7914,7915,7917,7919,7921,7923,7925,7927,7929],{"class":5266,"line":6008},[5264,7916,5977],{"class":5314},[5264,7918,5707],{"class":5270},[5264,7920,5982],{"class":5274},[5264,7922,5311],{"class":5270},[5264,7924,7879],{"class":5314},[5264,7926,5989],{"class":5270},[5264,7928,5992],{"class":5274},[5264,7930,7035],{"class":5270},[5264,7932,7933,7936],{"class":5266,"line":6013},[5264,7934,7935],{"class":5314},"      statusCode",[5264,7937,5865],{"class":5270},[5264,7939,7940,7942,7945],{"class":5266,"line":6039},[5264,7941,5871],{"class":5314},[5264,7943,7944],{"class":5611}," 'Database Error'",[5264,7946,5865],{"class":5270},[5264,7948,7949,7952],{"class":5266,"line":6062},[5264,7950,7951],{"class":5314},"      message",[5264,7953,5865],{"class":5270},[5264,7955,7956,7958,7960,7962,7964,7966],{"class":5266,"line":6080},[5264,7957,5893],{"class":5314},[5264,7959,5896],{"class":5288},[5264,7961,5899],{"class":5274},[5264,7963,5902],{"class":5270},[5264,7965,5905],{"class":5274},[5264,7967,5908],{"class":5270},[5264,7969,7970,7972,7974,7976,7978],{"class":5266,"line":6086},[5264,7971,5914],{"class":5314},[5264,7973,5745],{"class":5314},[5264,7975,5707],{"class":5270},[5264,7977,5921],{"class":5314},[5264,7979,5865],{"class":5270},[5264,7981,7982],{"class":5266,"line":6091},[5264,7983,7129],{"class":5270},[5264,7985,7986],{"class":5266,"line":6115},[5264,7987,5425],{"class":5270},[5264,7989,7990],{"class":5266,"line":6131},[5264,7991,5473],{"emptyLinePlaceholder":5472},[5264,7993,7994,7996,7999],{"class":5266,"line":6146},[5264,7995,6016],{"class":5288},[5264,7997,7998],{"class":5274}," mapDatabaseError",[5264,8000,8001],{"class":5270},"(\n",[5264,8003,8004,8007,8009,8011],{"class":5266,"line":6172},[5264,8005,8006],{"class":5314},"    code",[5264,8008,5318],{"class":5270},[5264,8010,6286],{"class":5292},[5264,8012,5865],{"class":5270},[5264,8014,8015,8018,8020,8022],{"class":5266,"line":6178},[5264,8016,8017],{"class":5314},"    constraint",[5264,8019,5318],{"class":5270},[5264,8021,6286],{"class":5292},[5264,8023,5865],{"class":5270},[5264,8025,8026,8029,8031],{"class":5266,"line":6183},[5264,8027,8028],{"class":5314},"    exception",[5264,8030,5318],{"class":5270},[5264,8032,8033],{"class":5292},"QueryFailedError\n",[5264,8035,8037,8040,8042,8044,8046,8049,8051,8053,8055],{"class":5266,"line":8036},42,[5264,8038,8039],{"class":5270},"  ): { ",[5264,8041,7879],{"class":5314},[5264,8043,5318],{"class":5270},[5264,8045,6395],{"class":5292},[5264,8047,8048],{"class":5270},"; ",[5264,8050,5830],{"class":5314},[5264,8052,5318],{"class":5270},[5264,8054,6286],{"class":5292},[5264,8056,8057],{"class":5270}," } {\n",[5264,8059,8061,8064,8066,8068],{"class":5266,"line":8060},43,[5264,8062,8063],{"class":5284},"    switch",[5264,8065,5146],{"class":5270},[5264,8067,5102],{"class":5314},[5264,8069,5335],{"class":5270},[5264,8071,8073,8076,8079,8081],{"class":5266,"line":8072},44,[5264,8074,8075],{"class":5284},"      case",[5264,8077,8078],{"class":5611}," '23505'",[5264,8080,5318],{"class":5270},[5264,8082,8083],{"class":5341},"\u002F\u002F unique_violation\n",[5264,8085,8087,8090],{"class":5266,"line":8086},45,[5264,8088,8089],{"class":5284},"        return",[5264,8091,5302],{"class":5270},[5264,8093,8095,8098,8101,8103,8106],{"class":5266,"line":8094},46,[5264,8096,8097],{"class":5314},"          statusCode:",[5264,8099,8100],{"class":5314}," HttpStatus",[5264,8102,5707],{"class":5270},[5264,8104,8105],{"class":5698},"CONFLICT",[5264,8107,5865],{"class":5270},[5264,8109,8111,8114,8116,8118,8121,8123,8125,8127,8129],{"class":5266,"line":8110},47,[5264,8112,8113],{"class":5314},"          message:",[5264,8115,5947],{"class":5288},[5264,8117,5707],{"class":5270},[5264,8119,8120],{"class":5274},"extractUniqueViolationMessage",[5264,8122,5311],{"class":5270},[5264,8124,7859],{"class":5314},[5264,8126,5324],{"class":5270},[5264,8128,5315],{"class":5314},[5264,8130,5960],{"class":5270},[5264,8132,8134],{"class":5266,"line":8133},48,[5264,8135,8136],{"class":5270},"        };\n",[5264,8138,8140],{"class":5266,"line":8139},49,[5264,8141,5473],{"emptyLinePlaceholder":5472},[5264,8143,8145,8147,8150,8152],{"class":5266,"line":8144},50,[5264,8146,8075],{"class":5284},[5264,8148,8149],{"class":5611}," '23503'",[5264,8151,5318],{"class":5270},[5264,8153,8154],{"class":5341},"\u002F\u002F foreign_key_violation\n",[5264,8156,8158,8160],{"class":5266,"line":8157},51,[5264,8159,8089],{"class":5284},[5264,8161,5302],{"class":5270},[5264,8163,8165,8167,8169,8171,8174],{"class":5266,"line":8164},52,[5264,8166,8097],{"class":5314},[5264,8168,8100],{"class":5314},[5264,8170,5707],{"class":5270},[5264,8172,8173],{"class":5698},"BAD_REQUEST",[5264,8175,5865],{"class":5270},[5264,8177,8179,8181,8184],{"class":5266,"line":8178},53,[5264,8180,8113],{"class":5314},[5264,8182,8183],{"class":5611}," 'Referenced record does not exist'",[5264,8185,5865],{"class":5270},[5264,8187,8189],{"class":5266,"line":8188},54,[5264,8190,8136],{"class":5270},[5264,8192,8194],{"class":5266,"line":8193},55,[5264,8195,5473],{"emptyLinePlaceholder":5472},[5264,8197,8199,8201,8204,8206],{"class":5266,"line":8198},56,[5264,8200,8075],{"class":5284},[5264,8202,8203],{"class":5611}," '23502'",[5264,8205,5318],{"class":5270},[5264,8207,8208],{"class":5341},"\u002F\u002F not_null_violation\n",[5264,8210,8212,8214],{"class":5266,"line":8211},57,[5264,8213,8089],{"class":5284},[5264,8215,5302],{"class":5270},[5264,8217,8219,8221,8223,8225,8227],{"class":5266,"line":8218},58,[5264,8220,8097],{"class":5314},[5264,8222,8100],{"class":5314},[5264,8224,5707],{"class":5270},[5264,8226,8173],{"class":5698},[5264,8228,5865],{"class":5270},[5264,8230,8232,8234,8236,8238,8241,8243,8245],{"class":5266,"line":8231},59,[5264,8233,8113],{"class":5314},[5264,8235,5947],{"class":5288},[5264,8237,5707],{"class":5270},[5264,8239,8240],{"class":5274},"extractNotNullViolationMessage",[5264,8242,5311],{"class":5270},[5264,8244,5315],{"class":5314},[5264,8246,5960],{"class":5270},[5264,8248,8250],{"class":5266,"line":8249},60,[5264,8251,8136],{"class":5270},[5264,8253,8255],{"class":5266,"line":8254},61,[5264,8256,5473],{"emptyLinePlaceholder":5472},[5264,8258,8260,8262,8265,8267],{"class":5266,"line":8259},62,[5264,8261,8075],{"class":5284},[5264,8263,8264],{"class":5611}," '22P02'",[5264,8266,5318],{"class":5270},[5264,8268,8269],{"class":5341},"\u002F\u002F invalid_text_representation\n",[5264,8271,8273,8275],{"class":5266,"line":8272},63,[5264,8274,8089],{"class":5284},[5264,8276,5302],{"class":5270},[5264,8278,8280,8282,8284,8286,8288],{"class":5266,"line":8279},64,[5264,8281,8097],{"class":5314},[5264,8283,8100],{"class":5314},[5264,8285,5707],{"class":5270},[5264,8287,8173],{"class":5698},[5264,8289,5865],{"class":5270},[5264,8291,8293,8295,8298],{"class":5266,"line":8292},65,[5264,8294,8113],{"class":5314},[5264,8296,8297],{"class":5611}," 'Invalid data format'",[5264,8299,5865],{"class":5270},[5264,8301,8303],{"class":5266,"line":8302},66,[5264,8304,8136],{"class":5270},[5264,8306,8308],{"class":5266,"line":8307},67,[5264,8309,5473],{"emptyLinePlaceholder":5472},[5264,8311,8313,8315,8318,8320],{"class":5266,"line":8312},68,[5264,8314,8075],{"class":5284},[5264,8316,8317],{"class":5611}," '22001'",[5264,8319,5318],{"class":5270},[5264,8321,8322],{"class":5341},"\u002F\u002F string_data_right_truncation\n",[5264,8324,8326,8328],{"class":5266,"line":8325},69,[5264,8327,8089],{"class":5284},[5264,8329,5302],{"class":5270},[5264,8331,8333,8335,8337,8339,8341],{"class":5266,"line":8332},70,[5264,8334,8097],{"class":5314},[5264,8336,8100],{"class":5314},[5264,8338,5707],{"class":5270},[5264,8340,8173],{"class":5698},[5264,8342,5865],{"class":5270},[5264,8344,8346,8348,8351],{"class":5266,"line":8345},71,[5264,8347,8113],{"class":5314},[5264,8349,8350],{"class":5611}," 'Data too long for field'",[5264,8352,5865],{"class":5270},[5264,8354,8356],{"class":5266,"line":8355},72,[5264,8357,8136],{"class":5270},[5264,8359,8361],{"class":5266,"line":8360},73,[5264,8362,5473],{"emptyLinePlaceholder":5472},[5264,8364,8366,8368,8371,8373],{"class":5266,"line":8365},74,[5264,8367,8075],{"class":5284},[5264,8369,8370],{"class":5611}," '42P01'",[5264,8372,5318],{"class":5270},[5264,8374,8375],{"class":5341},"\u002F\u002F undefined_table\n",[5264,8377,8379,8381],{"class":5266,"line":8378},75,[5264,8380,8089],{"class":5284},[5264,8382,5302],{"class":5270},[5264,8384,8386,8388,8390,8392,8395],{"class":5266,"line":8385},76,[5264,8387,8097],{"class":5314},[5264,8389,8100],{"class":5314},[5264,8391,5707],{"class":5270},[5264,8393,8394],{"class":5698},"INTERNAL_SERVER_ERROR",[5264,8396,5865],{"class":5270},[5264,8398,8400,8402,8405],{"class":5266,"line":8399},77,[5264,8401,8113],{"class":5314},[5264,8403,8404],{"class":5611}," 'Database configuration error'",[5264,8406,5865],{"class":5270},[5264,8408,8410],{"class":5266,"line":8409},78,[5264,8411,8136],{"class":5270},[5264,8413,8415],{"class":5266,"line":8414},79,[5264,8416,5473],{"emptyLinePlaceholder":5472},[5264,8418,8420,8423],{"class":5266,"line":8419},80,[5264,8421,8422],{"class":5284},"      default",[5264,8424,8425],{"class":5270},":\n",[5264,8427,8429,8431],{"class":5266,"line":8428},81,[5264,8430,8089],{"class":5284},[5264,8432,5302],{"class":5270},[5264,8434,8436,8438,8440,8442,8444],{"class":5266,"line":8435},82,[5264,8437,8097],{"class":5314},[5264,8439,8100],{"class":5314},[5264,8441,5707],{"class":5270},[5264,8443,8394],{"class":5698},[5264,8445,5865],{"class":5270},[5264,8447,8449,8451,8454],{"class":5266,"line":8448},83,[5264,8450,8113],{"class":5314},[5264,8452,8453],{"class":5611}," 'An unexpected database error occurred'",[5264,8455,5865],{"class":5270},[5264,8457,8459],{"class":5266,"line":8458},84,[5264,8460,8136],{"class":5270},[5264,8462,8464],{"class":5266,"line":8463},85,[5264,8465,6083],{"class":5270},[5264,8467,8469],{"class":5266,"line":8468},86,[5264,8470,5425],{"class":5270},[5264,8472,8474],{"class":5266,"line":8473},87,[5264,8475,5473],{"emptyLinePlaceholder":5472},[5264,8477,8479,8481,8484,8486,8488,8490,8492,8494,8496,8498,8500,8502,8504],{"class":5266,"line":8478},88,[5264,8480,6016],{"class":5288},[5264,8482,8483],{"class":5274}," extractUniqueViolationMessage",[5264,8485,5311],{"class":5270},[5264,8487,7859],{"class":5314},[5264,8489,5318],{"class":5270},[5264,8491,6286],{"class":5292},[5264,8493,5324],{"class":5270},[5264,8495,5315],{"class":5314},[5264,8497,5318],{"class":5270},[5264,8499,5484],{"class":5292},[5264,8501,6031],{"class":5270},[5264,8503,6286],{"class":5292},[5264,8505,5302],{"class":5270},[5264,8507,8509],{"class":5266,"line":8508},89,[5264,8510,8511],{"class":5341},"    \u002F\u002F Витягування назви поля з constraint name\n",[5264,8513,8515],{"class":5266,"line":8514},90,[5264,8516,8517],{"class":5341},"    \u002F\u002F Наприклад: \"users_email_key\" → \"email\"\n",[5264,8519,8521,8523,8526,8528,8530,8533,8536,8538,8541,8545,8548,8550,8554,8557,8560,8562,8564,8566,8568,8571,8574,8576],{"class":5266,"line":8520},91,[5264,8522,5695],{"class":5288},[5264,8524,8525],{"class":5698}," match",[5264,8527,5702],{"class":5270},[5264,8529,7859],{"class":5314},[5264,8531,8532],{"class":5270},"?.",[5264,8534,8535],{"class":5274},"match",[5264,8537,5311],{"class":5270},[5264,8539,6540],{"class":8540},"shsrj",[5264,8542,8544],{"class":8543},"siofk","^",[5264,8546,5311],{"class":8547},"sAV2Q",[5264,8549,5707],{"class":8540},[5264,8551,8553],{"class":8552},"sYsli","+?",[5264,8555,8556],{"class":8547},")",[5264,8558,8559],{"class":8540},"_",[5264,8561,5311],{"class":8547},[5264,8563,5707],{"class":8540},[5264,8565,8553],{"class":8552},[5264,8567,8556],{"class":8547},[5264,8569,8570],{"class":8540},"_key",[5264,8572,8573],{"class":8543},"$",[5264,8575,6540],{"class":8540},[5264,8577,6000],{"class":5270},[5264,8579,8581,8583,8585,8587,8589,8592,8594,8596,8599,8602,8605],{"class":5266,"line":8580},92,[5264,8582,5695],{"class":5288},[5264,8584,7263],{"class":5698},[5264,8586,5702],{"class":5270},[5264,8588,8535],{"class":5314},[5264,8590,8591],{"class":5270}," ? ",[5264,8593,8535],{"class":5314},[5264,8595,7316],{"class":5270},[5264,8597,8598],{"class":6311},"2",[5264,8600,8601],{"class":5270},"] : ",[5264,8603,8604],{"class":5611},"'field'",[5264,8606,5615],{"class":5270},[5264,8608,8610],{"class":5266,"line":8609},93,[5264,8611,5473],{"emptyLinePlaceholder":5472},[5264,8613,8615,8617,8620,8622,8624,8626,8629],{"class":5266,"line":8614},94,[5264,8616,6094],{"class":5284},[5264,8618,8619],{"class":5611}," `Duplicate value: ",[5264,8621,7062],{"class":5288},[5264,8623,7319],{"class":5314},[5264,8625,7084],{"class":5288},[5264,8627,8628],{"class":5611}," already exists`",[5264,8630,5615],{"class":5270},[5264,8632,8634],{"class":5266,"line":8633},95,[5264,8635,5425],{"class":5270},[5264,8637,8639],{"class":5266,"line":8638},96,[5264,8640,5473],{"emptyLinePlaceholder":5472},[5264,8642,8644,8646,8649,8651,8653,8655,8657,8659,8661],{"class":5266,"line":8643},97,[5264,8645,6016],{"class":5288},[5264,8647,8648],{"class":5274}," extractNotNullViolationMessage",[5264,8650,5311],{"class":5270},[5264,8652,5315],{"class":5314},[5264,8654,5318],{"class":5270},[5264,8656,5484],{"class":5292},[5264,8658,6031],{"class":5270},[5264,8660,6286],{"class":5292},[5264,8662,5302],{"class":5270},[5264,8664,8666],{"class":5266,"line":8665},98,[5264,8667,8668],{"class":5341},"    \u002F\u002F Витягування назви колонки з повідомлення помилки\n",[5264,8670,8672,8674,8676,8678,8680,8682,8684,8686,8688,8690,8693,8695,8697,8699,8701,8704],{"class":5266,"line":8671},99,[5264,8673,5695],{"class":5288},[5264,8675,8525],{"class":5698},[5264,8677,5702],{"class":5270},[5264,8679,5315],{"class":5314},[5264,8681,5707],{"class":5270},[5264,8683,5830],{"class":5314},[5264,8685,5707],{"class":5270},[5264,8687,8535],{"class":5274},[5264,8689,5311],{"class":5270},[5264,8691,8692],{"class":8540},"\u002Fcolumn \"",[5264,8694,5311],{"class":8547},[5264,8696,5707],{"class":8540},[5264,8698,8553],{"class":8552},[5264,8700,8556],{"class":8547},[5264,8702,8703],{"class":8540},"\"\u002F",[5264,8705,6000],{"class":5270},[5264,8707,8709,8711,8714,8716,8718,8720,8722,8724,8727,8729,8731],{"class":5266,"line":8708},100,[5264,8710,5695],{"class":5288},[5264,8712,8713],{"class":5698}," column",[5264,8715,5702],{"class":5270},[5264,8717,8535],{"class":5314},[5264,8719,8591],{"class":5270},[5264,8721,8535],{"class":5314},[5264,8723,7316],{"class":5270},[5264,8725,8726],{"class":6311},"1",[5264,8728,8601],{"class":5270},[5264,8730,8604],{"class":5611},[5264,8732,5615],{"class":5270},[5264,8734,8736],{"class":5266,"line":8735},101,[5264,8737,5473],{"emptyLinePlaceholder":5472},[5264,8739,8741,8743,8746,8748,8751,8753,8756],{"class":5266,"line":8740},102,[5264,8742,6094],{"class":5284},[5264,8744,8745],{"class":5611}," `Required field missing: ",[5264,8747,7062],{"class":5288},[5264,8749,8750],{"class":5314},"column",[5264,8752,7084],{"class":5288},[5264,8754,8755],{"class":5611},"`",[5264,8757,5615],{"class":5270},[5264,8759,8761],{"class":5266,"line":8760},103,[5264,8762,5425],{"class":5270},[5264,8764,8766],{"class":5266,"line":8765},104,[5264,8767,5431],{"class":5270},[5206,8769,8770],{},[5144,8771,6190],{},[5254,8773,8775],{"className":5256,"code":8774,"language":5259,"meta":5260,"style":5260},"\u002F\u002F users.service.ts\n@Injectable()\nexport class UsersService {\n  constructor(\n    @InjectRepository(User)\n    private usersRepository: Repository\u003CUser>,\n  ) {}\n\n  async create(dto: CreateUserDto): Promise\u003CUser> {\n    const user = this.usersRepository.create(dto);\n    \n    \u002F\u002F Якщо email вже існує, TypeORM викине QueryFailedError з кодом 23505\n    return await this.usersRepository.save(user);\n  }\n}\n\n\u002F\u002F users.controller.ts\n@Controller('users')\n@UseFilters(DatabaseExceptionFilter)\nexport class UsersController {\n  @Post()\n  async create(@Body() dto: CreateUserDto) {\n    return this.usersService.create(dto);\n  }\n}\n",[5102,8776,8777,8782,8791,8802,8809,8824,8844,8849,8853,8879,8905,8910,8915,8940,8944,8948,8952,8956,8968,8980,8990,8998,9018,9038,9042],{"__ignoreMap":5260},[5264,8778,8779],{"class":5266,"line":5267},[5264,8780,8781],{"class":5341},"\u002F\u002F users.service.ts\n",[5264,8783,8784,8786,8789],{"class":5266,"line":5281},[5264,8785,5271],{"class":5270},[5264,8787,8788],{"class":5274},"Injectable",[5264,8790,5278],{"class":5270},[5264,8792,8793,8795,8797,8800],{"class":5266,"line":5305},[5264,8794,5285],{"class":5284},[5264,8796,5289],{"class":5288},[5264,8798,8799],{"class":5292}," UsersService",[5264,8801,5302],{"class":5270},[5264,8803,8804,8807],{"class":5266,"line":5338},[5264,8805,8806],{"class":5288},"  constructor",[5264,8808,8001],{"class":5270},[5264,8810,8811,8814,8817,8819,8822],{"class":5266,"line":5345},[5264,8812,8813],{"class":5270},"    @",[5264,8815,8816],{"class":5274},"InjectRepository",[5264,8818,5311],{"class":5270},[5264,8820,8821],{"class":5314},"User",[5264,8823,5451],{"class":5270},[5264,8825,8826,8829,8832,8834,8837,8839,8841],{"class":5266,"line":5370},[5264,8827,8828],{"class":5288},"    private",[5264,8830,8831],{"class":5314}," usersRepository",[5264,8833,5318],{"class":5270},[5264,8835,8836],{"class":5292},"Repository",[5264,8838,5733],{"class":5270},[5264,8840,8821],{"class":5292},[5264,8842,8843],{"class":5270},">,\n",[5264,8845,8846],{"class":5266,"line":5394},[5264,8847,8848],{"class":5270},"  ) {}\n",[5264,8850,8851],{"class":5266,"line":5416},[5264,8852,5473],{"emptyLinePlaceholder":5472},[5264,8854,8855,8857,8859,8861,8863,8865,8867,8869,8872,8874,8876],{"class":5266,"line":5422},[5264,8856,6462],{"class":5288},[5264,8858,6465],{"class":5274},[5264,8860,5311],{"class":5270},[5264,8862,6477],{"class":5314},[5264,8864,5318],{"class":5270},[5264,8866,6482],{"class":5292},[5264,8868,6031],{"class":5270},[5264,8870,8871],{"class":5292},"Promise",[5264,8873,5733],{"class":5270},[5264,8875,8821],{"class":5292},[5264,8877,8878],{"class":5270},"> {\n",[5264,8880,8881,8883,8886,8888,8890,8892,8895,8897,8899,8901,8903],{"class":5266,"line":5428},[5264,8882,5695],{"class":5288},[5264,8884,8885],{"class":5698}," user",[5264,8887,5702],{"class":5270},[5264,8889,7001],{"class":5288},[5264,8891,5707],{"class":5270},[5264,8893,8894],{"class":5314},"usersRepository",[5264,8896,5707],{"class":5270},[5264,8898,6500],{"class":5274},[5264,8900,5311],{"class":5270},[5264,8902,6477],{"class":5314},[5264,8904,6000],{"class":5270},[5264,8906,8907],{"class":5266,"line":5781},[5264,8908,8909],{"class":5270},"    \n",[5264,8911,8912],{"class":5266,"line":5804},[5264,8913,8914],{"class":5341},"    \u002F\u002F Якщо email вже існує, TypeORM викине QueryFailedError з кодом 23505\n",[5264,8916,8917,8919,8922,8924,8926,8928,8930,8933,8935,8938],{"class":5266,"line":5809},[5264,8918,6094],{"class":5284},[5264,8920,8921],{"class":5284}," await",[5264,8923,5947],{"class":5288},[5264,8925,5707],{"class":5270},[5264,8927,8894],{"class":5314},[5264,8929,5707],{"class":5270},[5264,8931,8932],{"class":5274},"save",[5264,8934,5311],{"class":5270},[5264,8936,8937],{"class":5314},"user",[5264,8939,6000],{"class":5270},[5264,8941,8942],{"class":5266,"line":5815},[5264,8943,5425],{"class":5270},[5264,8945,8946],{"class":5266,"line":5835},[5264,8947,5431],{"class":5270},[5264,8949,8950],{"class":5266,"line":5840},[5264,8951,5473],{"emptyLinePlaceholder":5472},[5264,8953,8954],{"class":5266,"line":5846},[5264,8955,6410],{"class":5341},[5264,8957,8958,8960,8962,8964,8966],{"class":5266,"line":5857},[5264,8959,5271],{"class":5270},[5264,8961,6417],{"class":5274},[5264,8963,5311],{"class":5270},[5264,8965,6422],{"class":5611},[5264,8967,5451],{"class":5270},[5264,8969,8970,8972,8974,8976,8978],{"class":5266,"line":5868},[5264,8971,5271],{"class":5270},[5264,8973,6431],{"class":5274},[5264,8975,5311],{"class":5270},[5264,8977,5111],{"class":5314},[5264,8979,5451],{"class":5270},[5264,8981,8982,8984,8986,8988],{"class":5266,"line":5879},[5264,8983,5285],{"class":5284},[5264,8985,5289],{"class":5288},[5264,8987,6446],{"class":5292},[5264,8989,5302],{"class":5270},[5264,8991,8992,8994,8996],{"class":5266,"line":5890},[5264,8993,6263],{"class":5270},[5264,8995,6455],{"class":5274},[5264,8997,5278],{"class":5270},[5264,8999,9000,9002,9004,9006,9008,9010,9012,9014,9016],{"class":5266,"line":5911},[5264,9001,6462],{"class":5288},[5264,9003,6465],{"class":5274},[5264,9005,6468],{"class":5270},[5264,9007,6471],{"class":5274},[5264,9009,6474],{"class":5270},[5264,9011,6477],{"class":5314},[5264,9013,5318],{"class":5270},[5264,9015,6482],{"class":5292},[5264,9017,5335],{"class":5270},[5264,9019,9020,9022,9024,9026,9028,9030,9032,9034,9036],{"class":5266,"line":5926},[5264,9021,6094],{"class":5284},[5264,9023,5947],{"class":5288},[5264,9025,5707],{"class":5270},[5264,9027,6495],{"class":5314},[5264,9029,5707],{"class":5270},[5264,9031,6500],{"class":5274},[5264,9033,5311],{"class":5270},[5264,9035,6477],{"class":5314},[5264,9037,6000],{"class":5270},[5264,9039,9040],{"class":5266,"line":5941},[5264,9041,5425],{"class":5270},[5264,9043,9044],{"class":5266,"line":5963},[5264,9045,5431],{"class":5270},[5206,9047,9048],{},[5144,9049,9050],{},"HTTP-запит (дублікат email):",[5254,9052,9054],{"className":6522,"code":9053,"language":6524,"meta":5260,"style":5260},"POST \u002Fusers HTTP\u002F1.1\nContent-Type: application\u002Fjson\n\n{\n  \"email\": \"john@example.com\",\n  \"password\": \"password123\"\n}\n",[5102,9055,9056,9068,9076,9080,9084,9095,9104],{"__ignoreMap":5260},[5264,9057,9058,9060,9062,9064,9066],{"class":5266,"line":5267},[5264,9059,6531],{"class":5284},[5264,9061,6534],{"class":5270},[5264,9063,6537],{"class":5288},[5264,9065,6540],{"class":5270},[5264,9067,6543],{"class":6311},[5264,9069,9070,9072,9074],{"class":5266,"line":5281},[5264,9071,6549],{"class":6548},[5264,9073,5212],{"class":5288},[5264,9075,6554],{"class":5611},[5264,9077,9078],{"class":5266,"line":5305},[5264,9079,5473],{"emptyLinePlaceholder":5472},[5264,9081,9082],{"class":5266,"line":5338},[5264,9083,6563],{"class":5270},[5264,9085,9086,9088,9090,9093],{"class":5266,"line":5345},[5264,9087,6569],{"class":6568},[5264,9089,5318],{"class":5270},[5264,9091,9092],{"class":5611},"\"john@example.com\"",[5264,9094,5865],{"class":5270},[5264,9096,9097,9099,9101],{"class":5266,"line":5370},[5264,9098,6581],{"class":6568},[5264,9100,5318],{"class":5270},[5264,9102,9103],{"class":5611},"\"password123\"\n",[5264,9105,9106],{"class":5266,"line":5394},[5264,9107,5431],{"class":5270},[5206,9109,9110],{},[5144,9111,9112],{},"JSON-відповідь (без фільтра - розкриває SQL):",[5254,9114,9116],{"className":6610,"code":9115,"language":5992,"meta":5260,"style":5260},"{\n  \"statusCode\": 500,\n  \"message\": \"duplicate key value violates unique constraint \\\"users_email_key\\\"\"\n}\n",[5102,9117,9118,9122,9133,9154],{"__ignoreMap":5260},[5264,9119,9120],{"class":5266,"line":5267},[5264,9121,6563],{"class":5270},[5264,9123,9124,9126,9128,9131],{"class":5266,"line":5281},[5264,9125,6622],{"class":6568},[5264,9127,5318],{"class":5270},[5264,9129,9130],{"class":6311},"500",[5264,9132,5865],{"class":5270},[5264,9134,9135,9137,9139,9142,9146,9149,9151],{"class":5266,"line":5305},[5264,9136,6646],{"class":6568},[5264,9138,5318],{"class":5270},[5264,9140,9141],{"class":5611},"\"duplicate key value violates unique constraint ",[5264,9143,9145],{"class":9144},"sjcCO","\\\"",[5264,9147,9148],{"class":5611},"users_email_key",[5264,9150,9145],{"class":9144},[5264,9152,9153],{"class":5611},"\"\n",[5264,9155,9156],{"class":5266,"line":5338},[5264,9157,5431],{"class":5270},[5206,9159,9160],{},[5144,9161,9162],{},"JSON-відповідь (з фільтром - зрозуміло клієнту):",[5254,9164,9166],{"className":6610,"code":9165,"language":5992,"meta":5260,"style":5260},"{\n  \"statusCode\": 409,\n  \"error\": \"Database Error\",\n  \"message\": \"Duplicate value: email already exists\",\n  \"timestamp\": \"2026-09-05T18:30:00.000Z\",\n  \"path\": \"\u002Fusers\"\n}\n",[5102,9167,9168,9172,9183,9194,9205,9216,9225],{"__ignoreMap":5260},[5264,9169,9170],{"class":5266,"line":5267},[5264,9171,6563],{"class":5270},[5264,9173,9174,9176,9178,9181],{"class":5266,"line":5281},[5264,9175,6622],{"class":6568},[5264,9177,5318],{"class":5270},[5264,9179,9180],{"class":6311},"409",[5264,9182,5865],{"class":5270},[5264,9184,9185,9187,9189,9192],{"class":5266,"line":5305},[5264,9186,6634],{"class":6568},[5264,9188,5318],{"class":5270},[5264,9190,9191],{"class":5611},"\"Database Error\"",[5264,9193,5865],{"class":5270},[5264,9195,9196,9198,9200,9203],{"class":5266,"line":5338},[5264,9197,6646],{"class":6568},[5264,9199,5318],{"class":5270},[5264,9201,9202],{"class":5611},"\"Duplicate value: email already exists\"",[5264,9204,5865],{"class":5270},[5264,9206,9207,9209,9211,9214],{"class":5266,"line":5345},[5264,9208,6658],{"class":6568},[5264,9210,5318],{"class":5270},[5264,9212,9213],{"class":5611},"\"2026-09-05T18:30:00.000Z\"",[5264,9215,5865],{"class":5270},[5264,9217,9218,9220,9222],{"class":5266,"line":5370},[5264,9219,6670],{"class":6568},[5264,9221,5318],{"class":5270},[5264,9223,9224],{"class":5611},"\"\u002Fusers\"\n",[5264,9226,9227],{"class":5266,"line":5394},[5264,9228,5431],{"class":5270},[5572,9230,9232],{"id":9231},"filter-для-prisma","Filter для Prisma",[5254,9234,9236],{"className":5256,"code":9235,"language":5259,"meta":5260,"style":5260},"import { ExceptionFilter, Catch, ArgumentsHost, HttpStatus } from '@nestjs\u002Fcommon';\nimport { Prisma } from '@prisma\u002Fclient';\n\n@Catch(Prisma.PrismaClientKnownRequestError)\nexport class PrismaExceptionFilter implements ExceptionFilter {\n  catch(exception: Prisma.PrismaClientKnownRequestError, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse();\n    const request = ctx.getRequest();\n\n    const { statusCode, message } = this.mapPrismaError(exception);\n\n    response.status(statusCode).json({\n      statusCode,\n      error: 'Database Error',\n      message,\n      timestamp: new Date().toISOString(),\n      path: request.url,\n    });\n  }\n\n  private mapPrismaError(\n    exception: Prisma.PrismaClientKnownRequestError\n  ): { statusCode: number; message: string } {\n    switch (exception.code) {\n      case 'P2002': \u002F\u002F Unique constraint failed\n        const target = (exception.meta?.target as string[]) || [];\n        return {\n          statusCode: HttpStatus.CONFLICT,\n          message: `Duplicate value: ${target.join(', ')} already exists`,\n        };\n\n      case 'P2003': \u002F\u002F Foreign key constraint failed\n        return {\n          statusCode: HttpStatus.BAD_REQUEST,\n          message: 'Referenced record does not exist',\n        };\n\n      case 'P2025': \u002F\u002F Record not found\n        return {\n          statusCode: HttpStatus.NOT_FOUND,\n          message: 'Record not found',\n        };\n\n      case 'P2014': \u002F\u002F Invalid ID\n        return {\n          statusCode: HttpStatus.BAD_REQUEST,\n          message: 'Invalid identifier',\n        };\n\n      default:\n        return {\n          statusCode: HttpStatus.INTERNAL_SERVER_ERROR,\n          message: 'Database error occurred',\n        };\n    }\n  }\n}\n",[5102,9237,9238,9266,9284,9288,9305,9320,9346,9362,9378,9394,9398,9425,9429,9447,9453,9461,9467,9481,9493,9497,9501,9505,9514,9527,9547,9561,9573,9602,9608,9620,9648,9652,9656,9668,9674,9686,9694,9698,9702,9714,9720,9733,9742,9746,9750,9762,9768,9780,9789,9793,9797,9803,9809,9821,9830,9834,9838,9842],{"__ignoreMap":5260},[5264,9239,9240,9242,9244,9246,9248,9250,9252,9254,9256,9258,9260,9262,9264],{"class":5266,"line":5267},[5264,9241,5585],{"class":5284},[5264,9243,5463],{"class":5270},[5264,9245,5590],{"class":5314},[5264,9247,5324],{"class":5270},[5264,9249,5275],{"class":5314},[5264,9251,5324],{"class":5270},[5264,9253,5332],{"class":5314},[5264,9255,5324],{"class":5270},[5264,9257,7524],{"class":5314},[5264,9259,5605],{"class":5270},[5264,9261,5608],{"class":5284},[5264,9263,5612],{"class":5611},[5264,9265,5615],{"class":5270},[5264,9267,9268,9270,9272,9275,9277,9279,9282],{"class":5266,"line":5281},[5264,9269,5585],{"class":5284},[5264,9271,5463],{"class":5270},[5264,9273,9274],{"class":5314},"Prisma",[5264,9276,5605],{"class":5270},[5264,9278,5608],{"class":5284},[5264,9280,9281],{"class":5611}," '@prisma\u002Fclient'",[5264,9283,5615],{"class":5270},[5264,9285,9286],{"class":5266,"line":5305},[5264,9287,5473],{"emptyLinePlaceholder":5472},[5264,9289,9290,9292,9294,9296,9298,9300,9303],{"class":5266,"line":5338},[5264,9291,5271],{"class":5270},[5264,9293,5275],{"class":5274},[5264,9295,5311],{"class":5270},[5264,9297,9274],{"class":5314},[5264,9299,5707],{"class":5270},[5264,9301,9302],{"class":5314},"PrismaClientKnownRequestError",[5264,9304,5451],{"class":5270},[5264,9306,9307,9309,9311,9314,9316,9318],{"class":5266,"line":5345},[5264,9308,5285],{"class":5284},[5264,9310,5289],{"class":5288},[5264,9312,9313],{"class":5292}," PrismaExceptionFilter",[5264,9315,5296],{"class":5288},[5264,9317,5299],{"class":5292},[5264,9319,5302],{"class":5270},[5264,9321,9322,9324,9326,9328,9330,9332,9334,9336,9338,9340,9342,9344],{"class":5266,"line":5370},[5264,9323,5308],{"class":5274},[5264,9325,5311],{"class":5270},[5264,9327,5315],{"class":5314},[5264,9329,5318],{"class":5270},[5264,9331,9274],{"class":5292},[5264,9333,5707],{"class":5270},[5264,9335,9302],{"class":5292},[5264,9337,5324],{"class":5270},[5264,9339,5327],{"class":5314},[5264,9341,5318],{"class":5270},[5264,9343,5332],{"class":5292},[5264,9345,5335],{"class":5270},[5264,9347,9348,9350,9352,9354,9356,9358,9360],{"class":5266,"line":5394},[5264,9349,5695],{"class":5288},[5264,9351,5699],{"class":5698},[5264,9353,5702],{"class":5270},[5264,9355,5327],{"class":5314},[5264,9357,5707],{"class":5270},[5264,9359,5710],{"class":5274},[5264,9361,5713],{"class":5270},[5264,9363,9364,9366,9368,9370,9372,9374,9376],{"class":5266,"line":5416},[5264,9365,5695],{"class":5288},[5264,9367,5720],{"class":5698},[5264,9369,5702],{"class":5270},[5264,9371,5725],{"class":5314},[5264,9373,5707],{"class":5270},[5264,9375,5730],{"class":5274},[5264,9377,5713],{"class":5270},[5264,9379,9380,9382,9384,9386,9388,9390,9392],{"class":5266,"line":5422},[5264,9381,5695],{"class":5288},[5264,9383,5745],{"class":5698},[5264,9385,5702],{"class":5270},[5264,9387,5725],{"class":5314},[5264,9389,5707],{"class":5270},[5264,9391,5754],{"class":5274},[5264,9393,5713],{"class":5270},[5264,9395,9396],{"class":5266,"line":5428},[5264,9397,5473],{"emptyLinePlaceholder":5472},[5264,9399,9400,9402,9404,9406,9408,9410,9412,9414,9416,9419,9421,9423],{"class":5266,"line":5781},[5264,9401,5695],{"class":5288},[5264,9403,5463],{"class":5270},[5264,9405,7879],{"class":5698},[5264,9407,5324],{"class":5270},[5264,9409,5830],{"class":5698},[5264,9411,7886],{"class":5270},[5264,9413,7001],{"class":5288},[5264,9415,5707],{"class":5270},[5264,9417,9418],{"class":5274},"mapPrismaError",[5264,9420,5311],{"class":5270},[5264,9422,5315],{"class":5314},[5264,9424,6000],{"class":5270},[5264,9426,9427],{"class":5266,"line":5804},[5264,9428,5473],{"emptyLinePlaceholder":5472},[5264,9430,9431,9433,9435,9437,9439,9441,9443,9445],{"class":5266,"line":5809},[5264,9432,5977],{"class":5314},[5264,9434,5707],{"class":5270},[5264,9436,5982],{"class":5274},[5264,9438,5311],{"class":5270},[5264,9440,7879],{"class":5314},[5264,9442,5989],{"class":5270},[5264,9444,5992],{"class":5274},[5264,9446,7035],{"class":5270},[5264,9448,9449,9451],{"class":5266,"line":5815},[5264,9450,7935],{"class":5314},[5264,9452,5865],{"class":5270},[5264,9454,9455,9457,9459],{"class":5266,"line":5835},[5264,9456,5871],{"class":5314},[5264,9458,7944],{"class":5611},[5264,9460,5865],{"class":5270},[5264,9462,9463,9465],{"class":5266,"line":5840},[5264,9464,7951],{"class":5314},[5264,9466,5865],{"class":5270},[5264,9468,9469,9471,9473,9475,9477,9479],{"class":5266,"line":5846},[5264,9470,5893],{"class":5314},[5264,9472,5896],{"class":5288},[5264,9474,5899],{"class":5274},[5264,9476,5902],{"class":5270},[5264,9478,5905],{"class":5274},[5264,9480,5908],{"class":5270},[5264,9482,9483,9485,9487,9489,9491],{"class":5266,"line":5857},[5264,9484,5914],{"class":5314},[5264,9486,5745],{"class":5314},[5264,9488,5707],{"class":5270},[5264,9490,5921],{"class":5314},[5264,9492,5865],{"class":5270},[5264,9494,9495],{"class":5266,"line":5868},[5264,9496,7129],{"class":5270},[5264,9498,9499],{"class":5266,"line":5879},[5264,9500,5425],{"class":5270},[5264,9502,9503],{"class":5266,"line":5890},[5264,9504,5473],{"emptyLinePlaceholder":5472},[5264,9506,9507,9509,9512],{"class":5266,"line":5911},[5264,9508,6016],{"class":5288},[5264,9510,9511],{"class":5274}," mapPrismaError",[5264,9513,8001],{"class":5270},[5264,9515,9516,9518,9520,9522,9524],{"class":5266,"line":5926},[5264,9517,8028],{"class":5314},[5264,9519,5318],{"class":5270},[5264,9521,9274],{"class":5292},[5264,9523,5707],{"class":5270},[5264,9525,9526],{"class":5292},"PrismaClientKnownRequestError\n",[5264,9528,9529,9531,9533,9535,9537,9539,9541,9543,9545],{"class":5266,"line":5941},[5264,9530,8039],{"class":5270},[5264,9532,7879],{"class":5314},[5264,9534,5318],{"class":5270},[5264,9536,6395],{"class":5292},[5264,9538,8048],{"class":5270},[5264,9540,5830],{"class":5314},[5264,9542,5318],{"class":5270},[5264,9544,6286],{"class":5292},[5264,9546,8057],{"class":5270},[5264,9548,9549,9551,9553,9555,9557,9559],{"class":5266,"line":5963},[5264,9550,8063],{"class":5284},[5264,9552,5146],{"class":5270},[5264,9554,5315],{"class":5314},[5264,9556,5707],{"class":5270},[5264,9558,5102],{"class":5314},[5264,9560,5335],{"class":5270},[5264,9562,9563,9565,9568,9570],{"class":5266,"line":5969},[5264,9564,8075],{"class":5284},[5264,9566,9567],{"class":5611}," 'P2002'",[5264,9569,5318],{"class":5270},[5264,9571,9572],{"class":5341},"\u002F\u002F Unique constraint failed\n",[5264,9574,9575,9578,9581,9583,9585,9587,9590,9592,9595,9597,9599],{"class":5266,"line":5974},[5264,9576,9577],{"class":5288},"        const",[5264,9579,9580],{"class":5698}," target",[5264,9582,7816],{"class":5270},[5264,9584,5315],{"class":5314},[5264,9586,5707],{"class":5270},[5264,9588,9589],{"class":5314},"meta",[5264,9591,8532],{"class":5270},[5264,9593,9594],{"class":5314},"target",[5264,9596,7825],{"class":5284},[5264,9598,7305],{"class":5292},[5264,9600,9601],{"class":5270},"[]) || [];\n",[5264,9603,9604,9606],{"class":5266,"line":6003},[5264,9605,8089],{"class":5284},[5264,9607,5302],{"class":5270},[5264,9609,9610,9612,9614,9616,9618],{"class":5266,"line":6008},[5264,9611,8097],{"class":5314},[5264,9613,8100],{"class":5314},[5264,9615,5707],{"class":5270},[5264,9617,8105],{"class":5698},[5264,9619,5865],{"class":5270},[5264,9621,9622,9624,9626,9628,9630,9632,9635,9637,9640,9642,9644,9646],{"class":5266,"line":6013},[5264,9623,8113],{"class":5314},[5264,9625,8619],{"class":5611},[5264,9627,7062],{"class":5288},[5264,9629,9594],{"class":5314},[5264,9631,5707],{"class":7068},[5264,9633,9634],{"class":5274},"join",[5264,9636,5311],{"class":7068},[5264,9638,9639],{"class":5611},"', '",[5264,9641,8556],{"class":7068},[5264,9643,7084],{"class":5288},[5264,9645,8628],{"class":5611},[5264,9647,5865],{"class":5270},[5264,9649,9650],{"class":5266,"line":6039},[5264,9651,8136],{"class":5270},[5264,9653,9654],{"class":5266,"line":6062},[5264,9655,5473],{"emptyLinePlaceholder":5472},[5264,9657,9658,9660,9663,9665],{"class":5266,"line":6080},[5264,9659,8075],{"class":5284},[5264,9661,9662],{"class":5611}," 'P2003'",[5264,9664,5318],{"class":5270},[5264,9666,9667],{"class":5341},"\u002F\u002F Foreign key constraint failed\n",[5264,9669,9670,9672],{"class":5266,"line":6086},[5264,9671,8089],{"class":5284},[5264,9673,5302],{"class":5270},[5264,9675,9676,9678,9680,9682,9684],{"class":5266,"line":6091},[5264,9677,8097],{"class":5314},[5264,9679,8100],{"class":5314},[5264,9681,5707],{"class":5270},[5264,9683,8173],{"class":5698},[5264,9685,5865],{"class":5270},[5264,9687,9688,9690,9692],{"class":5266,"line":6115},[5264,9689,8113],{"class":5314},[5264,9691,8183],{"class":5611},[5264,9693,5865],{"class":5270},[5264,9695,9696],{"class":5266,"line":6131},[5264,9697,8136],{"class":5270},[5264,9699,9700],{"class":5266,"line":6146},[5264,9701,5473],{"emptyLinePlaceholder":5472},[5264,9703,9704,9706,9709,9711],{"class":5266,"line":6172},[5264,9705,8075],{"class":5284},[5264,9707,9708],{"class":5611}," 'P2025'",[5264,9710,5318],{"class":5270},[5264,9712,9713],{"class":5341},"\u002F\u002F Record not found\n",[5264,9715,9716,9718],{"class":5266,"line":6178},[5264,9717,8089],{"class":5284},[5264,9719,5302],{"class":5270},[5264,9721,9722,9724,9726,9728,9731],{"class":5266,"line":6183},[5264,9723,8097],{"class":5314},[5264,9725,8100],{"class":5314},[5264,9727,5707],{"class":5270},[5264,9729,9730],{"class":5698},"NOT_FOUND",[5264,9732,5865],{"class":5270},[5264,9734,9735,9737,9740],{"class":5266,"line":8036},[5264,9736,8113],{"class":5314},[5264,9738,9739],{"class":5611}," 'Record not found'",[5264,9741,5865],{"class":5270},[5264,9743,9744],{"class":5266,"line":8060},[5264,9745,8136],{"class":5270},[5264,9747,9748],{"class":5266,"line":8072},[5264,9749,5473],{"emptyLinePlaceholder":5472},[5264,9751,9752,9754,9757,9759],{"class":5266,"line":8086},[5264,9753,8075],{"class":5284},[5264,9755,9756],{"class":5611}," 'P2014'",[5264,9758,5318],{"class":5270},[5264,9760,9761],{"class":5341},"\u002F\u002F Invalid ID\n",[5264,9763,9764,9766],{"class":5266,"line":8094},[5264,9765,8089],{"class":5284},[5264,9767,5302],{"class":5270},[5264,9769,9770,9772,9774,9776,9778],{"class":5266,"line":8110},[5264,9771,8097],{"class":5314},[5264,9773,8100],{"class":5314},[5264,9775,5707],{"class":5270},[5264,9777,8173],{"class":5698},[5264,9779,5865],{"class":5270},[5264,9781,9782,9784,9787],{"class":5266,"line":8133},[5264,9783,8113],{"class":5314},[5264,9785,9786],{"class":5611}," 'Invalid identifier'",[5264,9788,5865],{"class":5270},[5264,9790,9791],{"class":5266,"line":8139},[5264,9792,8136],{"class":5270},[5264,9794,9795],{"class":5266,"line":8144},[5264,9796,5473],{"emptyLinePlaceholder":5472},[5264,9798,9799,9801],{"class":5266,"line":8157},[5264,9800,8422],{"class":5284},[5264,9802,8425],{"class":5270},[5264,9804,9805,9807],{"class":5266,"line":8164},[5264,9806,8089],{"class":5284},[5264,9808,5302],{"class":5270},[5264,9810,9811,9813,9815,9817,9819],{"class":5266,"line":8178},[5264,9812,8097],{"class":5314},[5264,9814,8100],{"class":5314},[5264,9816,5707],{"class":5270},[5264,9818,8394],{"class":5698},[5264,9820,5865],{"class":5270},[5264,9822,9823,9825,9828],{"class":5266,"line":8188},[5264,9824,8113],{"class":5314},[5264,9826,9827],{"class":5611}," 'Database error occurred'",[5264,9829,5865],{"class":5270},[5264,9831,9832],{"class":5266,"line":8193},[5264,9833,8136],{"class":5270},[5264,9835,9836],{"class":5266,"line":8198},[5264,9837,6083],{"class":5270},[5264,9839,9840],{"class":5266,"line":8211},[5264,9841,5425],{"class":5270},[5264,9843,9844],{"class":5266,"line":8218},[5264,9845,5431],{"class":5270},[5544,9847,9848,9851,9852,9855,9856,9858],{},[5144,9849,9850],{},"Важливо:"," завжди логуйте повну помилку бази даних (з SQL, параметрами) для дебагу, але ",[5144,9853,9854],{},"не відправляйте"," клієнту. Використовуйте ",[5102,9857,7529],{}," або Sentry для збереження деталей.",[5201,9860,9862],{"id":9861},"httpexceptionfilter-форматування-стандартних-виключень","HttpExceptionFilter: форматування стандартних виключень",[5206,9864,9865,9866,9869],{},"Універсальний filter для всіх ",[5102,9867,9868],{},"HttpException"," з додаванням метаданих:",[5254,9871,9873],{"className":5256,"code":9872,"language":5259,"meta":5260,"style":5260},"import { ExceptionFilter, Catch, ArgumentsHost, HttpException, Logger } from '@nestjs\u002Fcommon';\nimport { Request, Response } from 'express';\n\n@Catch(HttpException)\nexport class HttpExceptionFilter implements ExceptionFilter {\n  private readonly logger = new Logger(HttpExceptionFilter.name);\n\n  catch(exception: HttpException, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse\u003CResponse>();\n    const request = ctx.getRequest\u003CRequest>();\n    const status = exception.getStatus();\n    const exceptionResponse = exception.getResponse();\n\n    \u002F\u002F Витягування повідомлення\n    let message: string | object;\n    if (typeof exceptionResponse === 'string') {\n      message = exceptionResponse;\n    } else {\n      message = (exceptionResponse as any).message || exceptionResponse;\n    }\n\n    \u002F\u002F Логування з контекстом\n    this.logger.warn(`HTTP ${status} - ${request.method} ${request.url}`, {\n      statusCode: status,\n      message,\n      user: request['user']?.id,\n      ip: request.ip,\n      userAgent: request.get('user-agent'),\n    });\n\n    \u002F\u002F Формування відповіді\n    const errorResponse = {\n      statusCode: status,\n      timestamp: new Date().toISOString(),\n      path: request.url,\n      method: request.method,\n      message,\n      ...(process.env.NODE_ENV === 'development' && {\n        stack: exception.stack,\n      }),\n    };\n\n    response.status(status).json(errorResponse);\n  }\n}\n",[5102,9874,9875,9907,9927,9931,9943,9958,9982,9986,10008,10024,10044,10064,10080,10096,10100,10105,10125,10144,10154,10164,10187,10191,10195,10200,10253,10261,10267,10287,10301,10320,10324,10328,10333,10341,10349,10363,10375,10387,10393,10419,10433,10438,10442,10446,10468,10472],{"__ignoreMap":5260},[5264,9876,9877,9879,9881,9883,9885,9887,9889,9891,9893,9895,9897,9899,9901,9903,9905],{"class":5266,"line":5267},[5264,9878,5585],{"class":5284},[5264,9880,5463],{"class":5270},[5264,9882,5590],{"class":5314},[5264,9884,5324],{"class":5270},[5264,9886,5275],{"class":5314},[5264,9888,5324],{"class":5270},[5264,9890,5332],{"class":5314},[5264,9892,5324],{"class":5270},[5264,9894,9868],{"class":5314},[5264,9896,5324],{"class":5270},[5264,9898,7529],{"class":5314},[5264,9900,5605],{"class":5270},[5264,9902,5608],{"class":5284},[5264,9904,5612],{"class":5611},[5264,9906,5615],{"class":5270},[5264,9908,9909,9911,9913,9915,9917,9919,9921,9923,9925],{"class":5266,"line":5281},[5264,9910,5585],{"class":5284},[5264,9912,5463],{"class":5270},[5264,9914,5624],{"class":5314},[5264,9916,5324],{"class":5270},[5264,9918,5629],{"class":5314},[5264,9920,5605],{"class":5270},[5264,9922,5608],{"class":5284},[5264,9924,5636],{"class":5611},[5264,9926,5615],{"class":5270},[5264,9928,9929],{"class":5266,"line":5305},[5264,9930,5473],{"emptyLinePlaceholder":5472},[5264,9932,9933,9935,9937,9939,9941],{"class":5266,"line":5338},[5264,9934,5271],{"class":5270},[5264,9936,5275],{"class":5274},[5264,9938,5311],{"class":5270},[5264,9940,9868],{"class":5314},[5264,9942,5451],{"class":5270},[5264,9944,9945,9947,9949,9952,9954,9956],{"class":5266,"line":5345},[5264,9946,5285],{"class":5284},[5264,9948,5289],{"class":5288},[5264,9950,9951],{"class":5292}," HttpExceptionFilter",[5264,9953,5296],{"class":5288},[5264,9955,5299],{"class":5292},[5264,9957,5302],{"class":5270},[5264,9959,9960,9962,9964,9966,9968,9970,9972,9974,9976,9978,9980],{"class":5266,"line":5370},[5264,9961,6016],{"class":5288},[5264,9963,7607],{"class":5288},[5264,9965,7610],{"class":5314},[5264,9967,5702],{"class":5270},[5264,9969,7615],{"class":5288},[5264,9971,7618],{"class":5274},[5264,9973,5311],{"class":5270},[5264,9975,5118],{"class":5314},[5264,9977,5707],{"class":5270},[5264,9979,7627],{"class":5314},[5264,9981,6000],{"class":5270},[5264,9983,9984],{"class":5266,"line":5394},[5264,9985,5473],{"emptyLinePlaceholder":5472},[5264,9987,9988,9990,9992,9994,9996,9998,10000,10002,10004,10006],{"class":5266,"line":5416},[5264,9989,5308],{"class":5274},[5264,9991,5311],{"class":5270},[5264,9993,5315],{"class":5314},[5264,9995,5318],{"class":5270},[5264,9997,9868],{"class":5292},[5264,9999,5324],{"class":5270},[5264,10001,5327],{"class":5314},[5264,10003,5318],{"class":5270},[5264,10005,5332],{"class":5292},[5264,10007,5335],{"class":5270},[5264,10009,10010,10012,10014,10016,10018,10020,10022],{"class":5266,"line":5422},[5264,10011,5695],{"class":5288},[5264,10013,5699],{"class":5698},[5264,10015,5702],{"class":5270},[5264,10017,5327],{"class":5314},[5264,10019,5707],{"class":5270},[5264,10021,5710],{"class":5274},[5264,10023,5713],{"class":5270},[5264,10025,10026,10028,10030,10032,10034,10036,10038,10040,10042],{"class":5266,"line":5428},[5264,10027,5695],{"class":5288},[5264,10029,5720],{"class":5698},[5264,10031,5702],{"class":5270},[5264,10033,5725],{"class":5314},[5264,10035,5707],{"class":5270},[5264,10037,5730],{"class":5274},[5264,10039,5733],{"class":5270},[5264,10041,5629],{"class":5292},[5264,10043,5738],{"class":5270},[5264,10045,10046,10048,10050,10052,10054,10056,10058,10060,10062],{"class":5266,"line":5781},[5264,10047,5695],{"class":5288},[5264,10049,5745],{"class":5698},[5264,10051,5702],{"class":5270},[5264,10053,5725],{"class":5314},[5264,10055,5707],{"class":5270},[5264,10057,5754],{"class":5274},[5264,10059,5733],{"class":5270},[5264,10061,5624],{"class":5292},[5264,10063,5738],{"class":5270},[5264,10065,10066,10068,10070,10072,10074,10076,10078],{"class":5266,"line":5804},[5264,10067,5695],{"class":5288},[5264,10069,5767],{"class":5698},[5264,10071,5702],{"class":5270},[5264,10073,5315],{"class":5314},[5264,10075,5707],{"class":5270},[5264,10077,5776],{"class":5274},[5264,10079,5713],{"class":5270},[5264,10081,10082,10084,10086,10088,10090,10092,10094],{"class":5266,"line":5809},[5264,10083,5695],{"class":5288},[5264,10085,5786],{"class":5698},[5264,10087,5702],{"class":5270},[5264,10089,5315],{"class":5314},[5264,10091,5707],{"class":5270},[5264,10093,5730],{"class":5274},[5264,10095,5713],{"class":5270},[5264,10097,10098],{"class":5266,"line":5815},[5264,10099,5473],{"emptyLinePlaceholder":5472},[5264,10101,10102],{"class":5266,"line":5835},[5264,10103,10104],{"class":5341},"    \u002F\u002F Витягування повідомлення\n",[5264,10106,10107,10110,10113,10115,10117,10120,10123],{"class":5266,"line":5840},[5264,10108,10109],{"class":5288},"    let",[5264,10111,10112],{"class":5314}," message",[5264,10114,5318],{"class":5270},[5264,10116,6286],{"class":5292},[5264,10118,10119],{"class":5270}," | ",[5264,10121,10122],{"class":5292},"object",[5264,10124,5615],{"class":5270},[5264,10126,10127,10129,10131,10134,10136,10139,10142],{"class":5266,"line":5846},[5264,10128,5348],{"class":5284},[5264,10130,5146],{"class":5270},[5264,10132,10133],{"class":5288},"typeof",[5264,10135,5786],{"class":5314},[5264,10137,10138],{"class":5270}," === ",[5264,10140,10141],{"class":5611},"'string'",[5264,10143,5335],{"class":5270},[5264,10145,10146,10148,10150,10152],{"class":5266,"line":5857},[5264,10147,7951],{"class":5314},[5264,10149,5702],{"class":5270},[5264,10151,5825],{"class":5314},[5264,10153,5615],{"class":5270},[5264,10155,10156,10159,10162],{"class":5266,"line":5868},[5264,10157,10158],{"class":5270},"    } ",[5264,10160,10161],{"class":5284},"else",[5264,10163,5302],{"class":5270},[5264,10165,10166,10168,10170,10172,10174,10176,10178,10180,10183,10185],{"class":5266,"line":5879},[5264,10167,7951],{"class":5314},[5264,10169,7816],{"class":5270},[5264,10171,5825],{"class":5314},[5264,10173,7825],{"class":5284},[5264,10175,7828],{"class":5292},[5264,10177,5989],{"class":5270},[5264,10179,5830],{"class":5314},[5264,10181,10182],{"class":5270}," || ",[5264,10184,5825],{"class":5314},[5264,10186,5615],{"class":5270},[5264,10188,10189],{"class":5266,"line":5890},[5264,10190,6083],{"class":5270},[5264,10192,10193],{"class":5266,"line":5911},[5264,10194,5473],{"emptyLinePlaceholder":5472},[5264,10196,10197],{"class":5266,"line":5926},[5264,10198,10199],{"class":5341},"    \u002F\u002F Логування з контекстом\n",[5264,10201,10202,10204,10206,10208,10210,10213,10215,10218,10220,10222,10224,10227,10229,10232,10234,10236,10238,10241,10243,10245,10247,10249,10251],{"class":5266,"line":5941},[5264,10203,7721],{"class":5288},[5264,10205,5707],{"class":5270},[5264,10207,7726],{"class":5314},[5264,10209,5707],{"class":5270},[5264,10211,10212],{"class":5274},"warn",[5264,10214,5311],{"class":5270},[5264,10216,10217],{"class":5611},"`HTTP ",[5264,10219,7062],{"class":5288},[5264,10221,5982],{"class":5314},[5264,10223,7084],{"class":5288},[5264,10225,10226],{"class":5611}," - ",[5264,10228,7062],{"class":5288},[5264,10230,10231],{"class":5314},"request",[5264,10233,5707],{"class":7068},[5264,10235,5936],{"class":5314},[5264,10237,7084],{"class":5288},[5264,10239,10240],{"class":5288}," ${",[5264,10242,10231],{"class":5314},[5264,10244,5707],{"class":7068},[5264,10246,5921],{"class":5314},[5264,10248,7084],{"class":5288},[5264,10250,8755],{"class":5611},[5264,10252,7738],{"class":5270},[5264,10254,10255,10257,10259],{"class":5266,"line":5963},[5264,10256,5860],{"class":5314},[5264,10258,5767],{"class":5314},[5264,10260,5865],{"class":5270},[5264,10262,10263,10265],{"class":5266,"line":5969},[5264,10264,7951],{"class":5314},[5264,10266,5865],{"class":5270},[5264,10268,10269,10272,10274,10276,10279,10282,10285],{"class":5266,"line":5974},[5264,10270,10271],{"class":5314},"      user:",[5264,10273,5745],{"class":5314},[5264,10275,7316],{"class":5270},[5264,10277,10278],{"class":5611},"'user'",[5264,10280,10281],{"class":5270},"]?.",[5264,10283,10284],{"class":5314},"id",[5264,10286,5865],{"class":5270},[5264,10288,10289,10292,10294,10296,10299],{"class":5266,"line":6003},[5264,10290,10291],{"class":5314},"      ip:",[5264,10293,5745],{"class":5314},[5264,10295,5707],{"class":5270},[5264,10297,10298],{"class":5314},"ip",[5264,10300,5865],{"class":5270},[5264,10302,10303,10306,10308,10310,10313,10315,10318],{"class":5266,"line":6008},[5264,10304,10305],{"class":5314},"      userAgent:",[5264,10307,5745],{"class":5314},[5264,10309,5707],{"class":5270},[5264,10311,10312],{"class":5274},"get",[5264,10314,5311],{"class":5270},[5264,10316,10317],{"class":5611},"'user-agent'",[5264,10319,5960],{"class":5270},[5264,10321,10322],{"class":5266,"line":6013},[5264,10323,7129],{"class":5270},[5264,10325,10326],{"class":5266,"line":6039},[5264,10327,5473],{"emptyLinePlaceholder":5472},[5264,10329,10330],{"class":5266,"line":6062},[5264,10331,10332],{"class":5341},"    \u002F\u002F Формування відповіді\n",[5264,10334,10335,10337,10339],{"class":5266,"line":6080},[5264,10336,5695],{"class":5288},[5264,10338,5851],{"class":5698},[5264,10340,5854],{"class":5270},[5264,10342,10343,10345,10347],{"class":5266,"line":6086},[5264,10344,5860],{"class":5314},[5264,10346,5767],{"class":5314},[5264,10348,5865],{"class":5270},[5264,10350,10351,10353,10355,10357,10359,10361],{"class":5266,"line":6091},[5264,10352,5893],{"class":5314},[5264,10354,5896],{"class":5288},[5264,10356,5899],{"class":5274},[5264,10358,5902],{"class":5270},[5264,10360,5905],{"class":5274},[5264,10362,5908],{"class":5270},[5264,10364,10365,10367,10369,10371,10373],{"class":5266,"line":6115},[5264,10366,5914],{"class":5314},[5264,10368,5745],{"class":5314},[5264,10370,5707],{"class":5270},[5264,10372,5921],{"class":5314},[5264,10374,5865],{"class":5270},[5264,10376,10377,10379,10381,10383,10385],{"class":5266,"line":6131},[5264,10378,5929],{"class":5314},[5264,10380,5745],{"class":5314},[5264,10382,5707],{"class":5270},[5264,10384,5936],{"class":5314},[5264,10386,5865],{"class":5270},[5264,10388,10389,10391],{"class":5266,"line":6146},[5264,10390,7951],{"class":5314},[5264,10392,5865],{"class":5270},[5264,10394,10395,10398,10401,10403,10406,10408,10411,10413,10416],{"class":5266,"line":6172},[5264,10396,10397],{"class":5270},"      ...(",[5264,10399,10400],{"class":5314},"process",[5264,10402,5707],{"class":5270},[5264,10404,10405],{"class":5314},"env",[5264,10407,5707],{"class":5270},[5264,10409,10410],{"class":5698},"NODE_ENV",[5264,10412,10138],{"class":5270},[5264,10414,10415],{"class":5611},"'development'",[5264,10417,10418],{"class":5270}," && {\n",[5264,10420,10421,10424,10426,10428,10431],{"class":5266,"line":6178},[5264,10422,10423],{"class":5314},"        stack:",[5264,10425,7745],{"class":5314},[5264,10427,5707],{"class":5270},[5264,10429,10430],{"class":5314},"stack",[5264,10432,5865],{"class":5270},[5264,10434,10435],{"class":5266,"line":6183},[5264,10436,10437],{"class":5270},"      }),\n",[5264,10439,10440],{"class":5266,"line":8036},[5264,10441,5966],{"class":5270},[5264,10443,10444],{"class":5266,"line":8060},[5264,10445,5473],{"emptyLinePlaceholder":5472},[5264,10447,10448,10450,10452,10454,10456,10458,10460,10462,10464,10466],{"class":5266,"line":8072},[5264,10449,5977],{"class":5314},[5264,10451,5707],{"class":5270},[5264,10453,5982],{"class":5274},[5264,10455,5311],{"class":5270},[5264,10457,5982],{"class":5314},[5264,10459,5989],{"class":5270},[5264,10461,5992],{"class":5274},[5264,10463,5311],{"class":5270},[5264,10465,5997],{"class":5314},[5264,10467,6000],{"class":5270},[5264,10469,10470],{"class":5266,"line":8086},[5264,10471,5425],{"class":5270},[5264,10473,10474],{"class":5266,"line":8094},[5264,10475,5431],{"class":5270},[5206,10477,10478],{},[5144,10479,10480],{},"Реєстрація глобально:",[5254,10482,10484],{"className":5256,"code":10483,"language":5259,"meta":5260,"style":5260},"\u002F\u002F app.module.ts\nimport { Module } from '@nestjs\u002Fcommon';\nimport { APP_FILTER } from '@nestjs\u002Fcore';\n\n@Module({\n  providers: [\n    {\n      provide: APP_FILTER,\n      useClass: HttpExceptionFilter,\n    },\n  ],\n})\nexport class AppModule {}\n",[5102,10485,10486,10491,10508,10526,10530,10538,10546,10550,10560,10569,10573,10578,10583],{"__ignoreMap":5260},[5264,10487,10488],{"class":5266,"line":5267},[5264,10489,10490],{"class":5341},"\u002F\u002F app.module.ts\n",[5264,10492,10493,10495,10497,10500,10502,10504,10506],{"class":5266,"line":5281},[5264,10494,5585],{"class":5284},[5264,10496,5463],{"class":5270},[5264,10498,10499],{"class":5314},"Module",[5264,10501,5605],{"class":5270},[5264,10503,5608],{"class":5284},[5264,10505,5612],{"class":5611},[5264,10507,5615],{"class":5270},[5264,10509,10510,10512,10514,10517,10519,10521,10524],{"class":5266,"line":5305},[5264,10511,5585],{"class":5284},[5264,10513,5463],{"class":5270},[5264,10515,10516],{"class":5314},"APP_FILTER",[5264,10518,5605],{"class":5270},[5264,10520,5608],{"class":5284},[5264,10522,10523],{"class":5611}," '@nestjs\u002Fcore'",[5264,10525,5615],{"class":5270},[5264,10527,10528],{"class":5266,"line":5338},[5264,10529,5473],{"emptyLinePlaceholder":5472},[5264,10531,10532,10534,10536],{"class":5266,"line":5345},[5264,10533,5271],{"class":5270},[5264,10535,10499],{"class":5274},[5264,10537,7035],{"class":5270},[5264,10539,10540,10543],{"class":5266,"line":5370},[5264,10541,10542],{"class":5314},"  providers:",[5264,10544,10545],{"class":5270}," [\n",[5264,10547,10548],{"class":5266,"line":5394},[5264,10549,6702],{"class":5270},[5264,10551,10552,10555,10558],{"class":5266,"line":5416},[5264,10553,10554],{"class":5314},"      provide:",[5264,10556,10557],{"class":5698}," APP_FILTER",[5264,10559,5865],{"class":5270},[5264,10561,10562,10565,10567],{"class":5266,"line":5422},[5264,10563,10564],{"class":5314},"      useClass:",[5264,10566,9951],{"class":5314},[5264,10568,5865],{"class":5270},[5264,10570,10571],{"class":5266,"line":5428},[5264,10572,6744],{"class":5270},[5264,10574,10575],{"class":5266,"line":5781},[5264,10576,10577],{"class":5270},"  ],\n",[5264,10579,10580],{"class":5266,"line":5804},[5264,10581,10582],{"class":5270},"})\n",[5264,10584,10585,10587,10589,10592],{"class":5266,"line":5809},[5264,10586,5285],{"class":5284},[5264,10588,5289],{"class":5288},[5264,10590,10591],{"class":5292}," AppModule",[5264,10593,10594],{"class":5270}," {}\n",[5201,10596,10598],{"id":10597},"інтеграція-з-sentry-моніторинг-помилок","Інтеграція з Sentry: моніторинг помилок",[5206,10600,10601],{},"Sentry — це платформа для відстеження помилок у production. Інтегруємо її з exception filter:",[5572,10603,10605],{"id":10604},"встановлення-sentry","Встановлення Sentry",[5254,10607,10611],{"className":10608,"code":10609,"language":10610,"meta":5260,"style":5260},"language-bash shiki shiki-themes light-plus dark-plus dark-plus","npm install @sentry\u002Fnode @sentry\u002Ftracing\n","bash",[5102,10612,10613],{"__ignoreMap":5260},[5264,10614,10615,10618,10621,10624],{"class":5266,"line":5267},[5264,10616,10617],{"class":5274},"npm",[5264,10619,10620],{"class":5611}," install",[5264,10622,10623],{"class":5611}," @sentry\u002Fnode",[5264,10625,10626],{"class":5611}," @sentry\u002Ftracing\n",[5572,10628,10630],{"id":10629},"ініціалізація-sentry","Ініціалізація Sentry",[5254,10632,10634],{"className":5256,"code":10633,"language":5259,"meta":5260,"style":5260},"\u002F\u002F main.ts\nimport { NestFactory } from '@nestjs\u002Fcore';\nimport * as Sentry from '@sentry\u002Fnode';\nimport { AppModule } from '.\u002Fapp.module';\n\nasync function bootstrap() {\n  \u002F\u002F Ініціалізація Sentry\n  Sentry.init({\n    dsn: process.env.SENTRY_DSN,\n    environment: process.env.NODE_ENV,\n    tracesSampleRate: 1.0,\n  });\n\n  const app = await NestFactory.create(AppModule);\n  await app.listen(3000);\n}\nbootstrap();\n",[5102,10635,10636,10641,10658,10678,10696,10700,10714,10719,10731,10750,10767,10777,10782,10786,10812,10831,10835],{"__ignoreMap":5260},[5264,10637,10638],{"class":5266,"line":5267},[5264,10639,10640],{"class":5341},"\u002F\u002F main.ts\n",[5264,10642,10643,10645,10647,10650,10652,10654,10656],{"class":5266,"line":5281},[5264,10644,5585],{"class":5284},[5264,10646,5463],{"class":5270},[5264,10648,10649],{"class":5314},"NestFactory",[5264,10651,5605],{"class":5270},[5264,10653,5608],{"class":5284},[5264,10655,10523],{"class":5611},[5264,10657,5615],{"class":5270},[5264,10659,10660,10662,10665,10667,10670,10673,10676],{"class":5266,"line":5305},[5264,10661,5585],{"class":5284},[5264,10663,10664],{"class":5288}," *",[5264,10666,7825],{"class":5284},[5264,10668,10669],{"class":5314}," Sentry",[5264,10671,10672],{"class":5284}," from",[5264,10674,10675],{"class":5611}," '@sentry\u002Fnode'",[5264,10677,5615],{"class":5270},[5264,10679,10680,10682,10684,10687,10689,10691,10694],{"class":5266,"line":5338},[5264,10681,5585],{"class":5284},[5264,10683,5463],{"class":5270},[5264,10685,10686],{"class":5314},"AppModule",[5264,10688,5605],{"class":5270},[5264,10690,5608],{"class":5284},[5264,10692,10693],{"class":5611}," '.\u002Fapp.module'",[5264,10695,5615],{"class":5270},[5264,10697,10698],{"class":5266,"line":5345},[5264,10699,5473],{"emptyLinePlaceholder":5472},[5264,10701,10702,10705,10708,10711],{"class":5266,"line":5370},[5264,10703,10704],{"class":5288},"async",[5264,10706,10707],{"class":5288}," function",[5264,10709,10710],{"class":5274}," bootstrap",[5264,10712,10713],{"class":5270},"() {\n",[5264,10715,10716],{"class":5266,"line":5394},[5264,10717,10718],{"class":5341},"  \u002F\u002F Ініціалізація Sentry\n",[5264,10720,10721,10724,10726,10729],{"class":5266,"line":5416},[5264,10722,10723],{"class":5314},"  Sentry",[5264,10725,5707],{"class":5270},[5264,10727,10728],{"class":5274},"init",[5264,10730,7035],{"class":5270},[5264,10732,10733,10736,10739,10741,10743,10745,10748],{"class":5266,"line":5422},[5264,10734,10735],{"class":5314},"    dsn:",[5264,10737,10738],{"class":5314}," process",[5264,10740,5707],{"class":5270},[5264,10742,10405],{"class":5314},[5264,10744,5707],{"class":5270},[5264,10746,10747],{"class":5698},"SENTRY_DSN",[5264,10749,5865],{"class":5270},[5264,10751,10752,10755,10757,10759,10761,10763,10765],{"class":5266,"line":5428},[5264,10753,10754],{"class":5314},"    environment:",[5264,10756,10738],{"class":5314},[5264,10758,5707],{"class":5270},[5264,10760,10405],{"class":5314},[5264,10762,5707],{"class":5270},[5264,10764,10410],{"class":5698},[5264,10766,5865],{"class":5270},[5264,10768,10769,10772,10775],{"class":5266,"line":5781},[5264,10770,10771],{"class":5314},"    tracesSampleRate:",[5264,10773,10774],{"class":6311}," 1.0",[5264,10776,5865],{"class":5270},[5264,10778,10779],{"class":5266,"line":5804},[5264,10780,10781],{"class":5270},"  });\n",[5264,10783,10784],{"class":5266,"line":5809},[5264,10785,5473],{"emptyLinePlaceholder":5472},[5264,10787,10788,10791,10794,10796,10799,10802,10804,10806,10808,10810],{"class":5266,"line":5815},[5264,10789,10790],{"class":5288},"  const",[5264,10792,10793],{"class":5698}," app",[5264,10795,5702],{"class":5270},[5264,10797,10798],{"class":5284},"await",[5264,10800,10801],{"class":5314}," NestFactory",[5264,10803,5707],{"class":5270},[5264,10805,6500],{"class":5274},[5264,10807,5311],{"class":5270},[5264,10809,10686],{"class":5314},[5264,10811,6000],{"class":5270},[5264,10813,10814,10817,10819,10821,10824,10826,10829],{"class":5266,"line":5835},[5264,10815,10816],{"class":5284},"  await",[5264,10818,10793],{"class":5314},[5264,10820,5707],{"class":5270},[5264,10822,10823],{"class":5274},"listen",[5264,10825,5311],{"class":5270},[5264,10827,10828],{"class":6311},"3000",[5264,10830,6000],{"class":5270},[5264,10832,10833],{"class":5266,"line":5840},[5264,10834,5431],{"class":5270},[5264,10836,10837,10840],{"class":5266,"line":5846},[5264,10838,10839],{"class":5274},"bootstrap",[5264,10841,5713],{"class":5270},[5572,10843,10845],{"id":10844},"sentryexceptionfilter","SentryExceptionFilter",[5254,10847,10849],{"className":5256,"code":10848,"language":5259,"meta":5260,"style":5260},"import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus } from '@nestjs\u002Fcommon';\nimport * as Sentry from '@sentry\u002Fnode';\nimport { Request, Response } from 'express';\n\n@Catch()\nexport class SentryExceptionFilter implements ExceptionFilter {\n  catch(exception: unknown, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse\u003CResponse>();\n    const request = ctx.getRequest\u003CRequest>();\n\n    \u002F\u002F Визначення статусу\n    const status = exception instanceof HttpException\n      ? exception.getStatus()\n      : HttpStatus.INTERNAL_SERVER_ERROR;\n\n    \u002F\u002F Відправлення в Sentry (лише 5xx помилки)\n    if (status >= 500) {\n      Sentry.withScope(scope => {\n        \u002F\u002F Додавання контексту запиту\n        scope.setExtra('request', {\n          method: request.method,\n          url: request.url,\n          headers: request.headers,\n          body: request.body,\n          query: request.query,\n          params: request.params,\n        });\n\n        \u002F\u002F Додавання користувача\n        if (request['user']) {\n          scope.setUser({\n            id: request['user'].id,\n            email: request['user'].email,\n            username: request['user'].username,\n          });\n        }\n\n        \u002F\u002F Додавання тегів\n        scope.setTag('http.status_code', status);\n        scope.setTag('http.method', request.method);\n        scope.setTag('http.url', request.url);\n\n        \u002F\u002F Встановлення рівня severity\n        scope.setLevel(status >= 500 ? 'error' : 'warning');\n\n        \u002F\u002F Відправлення помилки\n        if (exception instanceof Error) {\n          Sentry.captureException(exception);\n        } else {\n          Sentry.captureMessage(`Non-error exception: ${JSON.stringify(exception)}`);\n        }\n      });\n    }\n\n    \u002F\u002F Формування відповіді\n    const message = exception instanceof HttpException\n      ? exception.message\n      : 'Internal server error';\n\n    response.status(status).json({\n      statusCode: status,\n      message: status >= 500 ? 'Internal server error' : message,\n      timestamp: new Date().toISOString(),\n      path: request.url,\n    });\n  }\n}\n",[5102,10850,10851,10883,10899,10919,10923,10931,10946,10968,10984,11004,11024,11028,11033,11048,11061,11074,11078,11083,11098,11117,11122,11139,11152,11165,11179,11193,11206,11220,11225,11229,11234,11250,11262,11280,11298,11316,11321,11326,11330,11335,11355,11378,11401,11405,11410,11440,11444,11449,11464,11480,11489,11525,11529,11534,11538,11542,11546,11560,11571,11580,11584,11602,11610,11630,11644,11656,11660,11664],{"__ignoreMap":5260},[5264,10852,10853,10855,10857,10859,10861,10863,10865,10867,10869,10871,10873,10875,10877,10879,10881],{"class":5266,"line":5267},[5264,10854,5585],{"class":5284},[5264,10856,5463],{"class":5270},[5264,10858,5590],{"class":5314},[5264,10860,5324],{"class":5270},[5264,10862,5275],{"class":5314},[5264,10864,5324],{"class":5270},[5264,10866,5332],{"class":5314},[5264,10868,5324],{"class":5270},[5264,10870,9868],{"class":5314},[5264,10872,5324],{"class":5270},[5264,10874,7524],{"class":5314},[5264,10876,5605],{"class":5270},[5264,10878,5608],{"class":5284},[5264,10880,5612],{"class":5611},[5264,10882,5615],{"class":5270},[5264,10884,10885,10887,10889,10891,10893,10895,10897],{"class":5266,"line":5281},[5264,10886,5585],{"class":5284},[5264,10888,10664],{"class":5288},[5264,10890,7825],{"class":5284},[5264,10892,10669],{"class":5314},[5264,10894,10672],{"class":5284},[5264,10896,10675],{"class":5611},[5264,10898,5615],{"class":5270},[5264,10900,10901,10903,10905,10907,10909,10911,10913,10915,10917],{"class":5266,"line":5305},[5264,10902,5585],{"class":5284},[5264,10904,5463],{"class":5270},[5264,10906,5624],{"class":5314},[5264,10908,5324],{"class":5270},[5264,10910,5629],{"class":5314},[5264,10912,5605],{"class":5270},[5264,10914,5608],{"class":5284},[5264,10916,5636],{"class":5611},[5264,10918,5615],{"class":5270},[5264,10920,10921],{"class":5266,"line":5338},[5264,10922,5473],{"emptyLinePlaceholder":5472},[5264,10924,10925,10927,10929],{"class":5266,"line":5345},[5264,10926,5271],{"class":5270},[5264,10928,5275],{"class":5274},[5264,10930,5278],{"class":5270},[5264,10932,10933,10935,10937,10940,10942,10944],{"class":5266,"line":5370},[5264,10934,5285],{"class":5284},[5264,10936,5289],{"class":5288},[5264,10938,10939],{"class":5292}," SentryExceptionFilter",[5264,10941,5296],{"class":5288},[5264,10943,5299],{"class":5292},[5264,10945,5302],{"class":5270},[5264,10947,10948,10950,10952,10954,10956,10958,10960,10962,10964,10966],{"class":5266,"line":5394},[5264,10949,5308],{"class":5274},[5264,10951,5311],{"class":5270},[5264,10953,5315],{"class":5314},[5264,10955,5318],{"class":5270},[5264,10957,5321],{"class":5292},[5264,10959,5324],{"class":5270},[5264,10961,5327],{"class":5314},[5264,10963,5318],{"class":5270},[5264,10965,5332],{"class":5292},[5264,10967,5335],{"class":5270},[5264,10969,10970,10972,10974,10976,10978,10980,10982],{"class":5266,"line":5416},[5264,10971,5695],{"class":5288},[5264,10973,5699],{"class":5698},[5264,10975,5702],{"class":5270},[5264,10977,5327],{"class":5314},[5264,10979,5707],{"class":5270},[5264,10981,5710],{"class":5274},[5264,10983,5713],{"class":5270},[5264,10985,10986,10988,10990,10992,10994,10996,10998,11000,11002],{"class":5266,"line":5422},[5264,10987,5695],{"class":5288},[5264,10989,5720],{"class":5698},[5264,10991,5702],{"class":5270},[5264,10993,5725],{"class":5314},[5264,10995,5707],{"class":5270},[5264,10997,5730],{"class":5274},[5264,10999,5733],{"class":5270},[5264,11001,5629],{"class":5292},[5264,11003,5738],{"class":5270},[5264,11005,11006,11008,11010,11012,11014,11016,11018,11020,11022],{"class":5266,"line":5428},[5264,11007,5695],{"class":5288},[5264,11009,5745],{"class":5698},[5264,11011,5702],{"class":5270},[5264,11013,5725],{"class":5314},[5264,11015,5707],{"class":5270},[5264,11017,5754],{"class":5274},[5264,11019,5733],{"class":5270},[5264,11021,5624],{"class":5292},[5264,11023,5738],{"class":5270},[5264,11025,11026],{"class":5266,"line":5781},[5264,11027,5473],{"emptyLinePlaceholder":5472},[5264,11029,11030],{"class":5266,"line":5804},[5264,11031,11032],{"class":5341},"    \u002F\u002F Визначення статусу\n",[5264,11034,11035,11037,11039,11041,11043,11045],{"class":5266,"line":5809},[5264,11036,5695],{"class":5288},[5264,11038,5767],{"class":5698},[5264,11040,5702],{"class":5270},[5264,11042,5315],{"class":5314},[5264,11044,5355],{"class":5288},[5264,11046,11047],{"class":5292}," HttpException\n",[5264,11049,11050,11053,11055,11057,11059],{"class":5266,"line":5815},[5264,11051,11052],{"class":5270},"      ? ",[5264,11054,5315],{"class":5314},[5264,11056,5707],{"class":5270},[5264,11058,5776],{"class":5274},[5264,11060,5278],{"class":5270},[5264,11062,11063,11066,11068,11070,11072],{"class":5266,"line":5835},[5264,11064,11065],{"class":5270},"      : ",[5264,11067,7524],{"class":5314},[5264,11069,5707],{"class":5270},[5264,11071,8394],{"class":5698},[5264,11073,5615],{"class":5270},[5264,11075,11076],{"class":5266,"line":5840},[5264,11077,5473],{"emptyLinePlaceholder":5472},[5264,11079,11080],{"class":5266,"line":5846},[5264,11081,11082],{"class":5341},"    \u002F\u002F Відправлення в Sentry (лише 5xx помилки)\n",[5264,11084,11085,11087,11089,11091,11094,11096],{"class":5266,"line":5857},[5264,11086,5348],{"class":5284},[5264,11088,5146],{"class":5270},[5264,11090,5982],{"class":5314},[5264,11092,11093],{"class":5270}," >= ",[5264,11095,9130],{"class":6311},[5264,11097,5335],{"class":5270},[5264,11099,11100,11103,11105,11108,11110,11113,11115],{"class":5266,"line":5868},[5264,11101,11102],{"class":5314},"      Sentry",[5264,11104,5707],{"class":5270},[5264,11106,11107],{"class":5274},"withScope",[5264,11109,5311],{"class":5270},[5264,11111,11112],{"class":5314},"scope",[5264,11114,6109],{"class":5288},[5264,11116,5302],{"class":5270},[5264,11118,11119],{"class":5266,"line":5879},[5264,11120,11121],{"class":5341},"        \u002F\u002F Додавання контексту запиту\n",[5264,11123,11124,11127,11129,11132,11134,11137],{"class":5266,"line":5890},[5264,11125,11126],{"class":5314},"        scope",[5264,11128,5707],{"class":5270},[5264,11130,11131],{"class":5274},"setExtra",[5264,11133,5311],{"class":5270},[5264,11135,11136],{"class":5611},"'request'",[5264,11138,7738],{"class":5270},[5264,11140,11141,11144,11146,11148,11150],{"class":5266,"line":5911},[5264,11142,11143],{"class":5314},"          method:",[5264,11145,5745],{"class":5314},[5264,11147,5707],{"class":5270},[5264,11149,5936],{"class":5314},[5264,11151,5865],{"class":5270},[5264,11153,11154,11157,11159,11161,11163],{"class":5266,"line":5926},[5264,11155,11156],{"class":5314},"          url:",[5264,11158,5745],{"class":5314},[5264,11160,5707],{"class":5270},[5264,11162,5921],{"class":5314},[5264,11164,5865],{"class":5270},[5264,11166,11167,11170,11172,11174,11177],{"class":5266,"line":5941},[5264,11168,11169],{"class":5314},"          headers:",[5264,11171,5745],{"class":5314},[5264,11173,5707],{"class":5270},[5264,11175,11176],{"class":5314},"headers",[5264,11178,5865],{"class":5270},[5264,11180,11181,11184,11186,11188,11191],{"class":5266,"line":5963},[5264,11182,11183],{"class":5314},"          body:",[5264,11185,5745],{"class":5314},[5264,11187,5707],{"class":5270},[5264,11189,11190],{"class":5314},"body",[5264,11192,5865],{"class":5270},[5264,11194,11195,11198,11200,11202,11204],{"class":5266,"line":5969},[5264,11196,11197],{"class":5314},"          query:",[5264,11199,5745],{"class":5314},[5264,11201,5707],{"class":5270},[5264,11203,7763],{"class":5314},[5264,11205,5865],{"class":5270},[5264,11207,11208,11211,11213,11215,11218],{"class":5266,"line":5974},[5264,11209,11210],{"class":5314},"          params:",[5264,11212,5745],{"class":5314},[5264,11214,5707],{"class":5270},[5264,11216,11217],{"class":5314},"params",[5264,11219,5865],{"class":5270},[5264,11221,11222],{"class":5266,"line":6003},[5264,11223,11224],{"class":5270},"        });\n",[5264,11226,11227],{"class":5266,"line":6008},[5264,11228,5473],{"emptyLinePlaceholder":5472},[5264,11230,11231],{"class":5266,"line":6013},[5264,11232,11233],{"class":5341},"        \u002F\u002F Додавання користувача\n",[5264,11235,11236,11239,11241,11243,11245,11247],{"class":5266,"line":6039},[5264,11237,11238],{"class":5284},"        if",[5264,11240,5146],{"class":5270},[5264,11242,10231],{"class":5314},[5264,11244,7316],{"class":5270},[5264,11246,10278],{"class":5611},[5264,11248,11249],{"class":5270},"]) {\n",[5264,11251,11252,11255,11257,11260],{"class":5266,"line":6062},[5264,11253,11254],{"class":5314},"          scope",[5264,11256,5707],{"class":5270},[5264,11258,11259],{"class":5274},"setUser",[5264,11261,7035],{"class":5270},[5264,11263,11264,11267,11269,11271,11273,11276,11278],{"class":5266,"line":6080},[5264,11265,11266],{"class":5314},"            id:",[5264,11268,5745],{"class":5314},[5264,11270,7316],{"class":5270},[5264,11272,10278],{"class":5611},[5264,11274,11275],{"class":5270},"].",[5264,11277,10284],{"class":5314},[5264,11279,5865],{"class":5270},[5264,11281,11282,11285,11287,11289,11291,11293,11296],{"class":5266,"line":6086},[5264,11283,11284],{"class":5314},"            email:",[5264,11286,5745],{"class":5314},[5264,11288,7316],{"class":5270},[5264,11290,10278],{"class":5611},[5264,11292,11275],{"class":5270},[5264,11294,11295],{"class":5314},"email",[5264,11297,5865],{"class":5270},[5264,11299,11300,11303,11305,11307,11309,11311,11314],{"class":5266,"line":6091},[5264,11301,11302],{"class":5314},"            username:",[5264,11304,5745],{"class":5314},[5264,11306,7316],{"class":5270},[5264,11308,10278],{"class":5611},[5264,11310,11275],{"class":5270},[5264,11312,11313],{"class":5314},"username",[5264,11315,5865],{"class":5270},[5264,11317,11318],{"class":5266,"line":6115},[5264,11319,11320],{"class":5270},"          });\n",[5264,11322,11323],{"class":5266,"line":6131},[5264,11324,11325],{"class":5270},"        }\n",[5264,11327,11328],{"class":5266,"line":6146},[5264,11329,5473],{"emptyLinePlaceholder":5472},[5264,11331,11332],{"class":5266,"line":6172},[5264,11333,11334],{"class":5341},"        \u002F\u002F Додавання тегів\n",[5264,11336,11337,11339,11341,11344,11346,11349,11351,11353],{"class":5266,"line":6178},[5264,11338,11126],{"class":5314},[5264,11340,5707],{"class":5270},[5264,11342,11343],{"class":5274},"setTag",[5264,11345,5311],{"class":5270},[5264,11347,11348],{"class":5611},"'http.status_code'",[5264,11350,5324],{"class":5270},[5264,11352,5982],{"class":5314},[5264,11354,6000],{"class":5270},[5264,11356,11357,11359,11361,11363,11365,11368,11370,11372,11374,11376],{"class":5266,"line":6183},[5264,11358,11126],{"class":5314},[5264,11360,5707],{"class":5270},[5264,11362,11343],{"class":5274},[5264,11364,5311],{"class":5270},[5264,11366,11367],{"class":5611},"'http.method'",[5264,11369,5324],{"class":5270},[5264,11371,10231],{"class":5314},[5264,11373,5707],{"class":5270},[5264,11375,5936],{"class":5314},[5264,11377,6000],{"class":5270},[5264,11379,11380,11382,11384,11386,11388,11391,11393,11395,11397,11399],{"class":5266,"line":8036},[5264,11381,11126],{"class":5314},[5264,11383,5707],{"class":5270},[5264,11385,11343],{"class":5274},[5264,11387,5311],{"class":5270},[5264,11389,11390],{"class":5611},"'http.url'",[5264,11392,5324],{"class":5270},[5264,11394,10231],{"class":5314},[5264,11396,5707],{"class":5270},[5264,11398,5921],{"class":5314},[5264,11400,6000],{"class":5270},[5264,11402,11403],{"class":5266,"line":8060},[5264,11404,5473],{"emptyLinePlaceholder":5472},[5264,11406,11407],{"class":5266,"line":8072},[5264,11408,11409],{"class":5341},"        \u002F\u002F Встановлення рівня severity\n",[5264,11411,11412,11414,11416,11419,11421,11423,11425,11427,11429,11432,11435,11438],{"class":5266,"line":8086},[5264,11413,11126],{"class":5314},[5264,11415,5707],{"class":5270},[5264,11417,11418],{"class":5274},"setLevel",[5264,11420,5311],{"class":5270},[5264,11422,5982],{"class":5314},[5264,11424,11093],{"class":5270},[5264,11426,9130],{"class":6311},[5264,11428,8591],{"class":5270},[5264,11430,11431],{"class":5611},"'error'",[5264,11433,11434],{"class":5270}," : ",[5264,11436,11437],{"class":5611},"'warning'",[5264,11439,6000],{"class":5270},[5264,11441,11442],{"class":5266,"line":8094},[5264,11443,5473],{"emptyLinePlaceholder":5472},[5264,11445,11446],{"class":5266,"line":8110},[5264,11447,11448],{"class":5341},"        \u002F\u002F Відправлення помилки\n",[5264,11450,11451,11453,11455,11457,11459,11462],{"class":5266,"line":8133},[5264,11452,11238],{"class":5284},[5264,11454,5146],{"class":5270},[5264,11456,5315],{"class":5314},[5264,11458,5355],{"class":5288},[5264,11460,11461],{"class":5292}," Error",[5264,11463,5335],{"class":5270},[5264,11465,11466,11469,11471,11474,11476,11478],{"class":5266,"line":8139},[5264,11467,11468],{"class":5314},"          Sentry",[5264,11470,5707],{"class":5270},[5264,11472,11473],{"class":5274},"captureException",[5264,11475,5311],{"class":5270},[5264,11477,5315],{"class":5314},[5264,11479,6000],{"class":5270},[5264,11481,11482,11485,11487],{"class":5266,"line":8144},[5264,11483,11484],{"class":5270},"        } ",[5264,11486,10161],{"class":5284},[5264,11488,5302],{"class":5270},[5264,11490,11491,11493,11495,11498,11500,11503,11505,11508,11510,11513,11515,11517,11519,11521,11523],{"class":5266,"line":8157},[5264,11492,11468],{"class":5314},[5264,11494,5707],{"class":5270},[5264,11496,11497],{"class":5274},"captureMessage",[5264,11499,5311],{"class":5270},[5264,11501,11502],{"class":5611},"`Non-error exception: ",[5264,11504,7062],{"class":5288},[5264,11506,11507],{"class":5698},"JSON",[5264,11509,5707],{"class":7068},[5264,11511,11512],{"class":5274},"stringify",[5264,11514,5311],{"class":7068},[5264,11516,5315],{"class":5314},[5264,11518,8556],{"class":7068},[5264,11520,7084],{"class":5288},[5264,11522,8755],{"class":5611},[5264,11524,6000],{"class":5270},[5264,11526,11527],{"class":5266,"line":8164},[5264,11528,11325],{"class":5270},[5264,11530,11531],{"class":5266,"line":8178},[5264,11532,11533],{"class":5270},"      });\n",[5264,11535,11536],{"class":5266,"line":8188},[5264,11537,6083],{"class":5270},[5264,11539,11540],{"class":5266,"line":8193},[5264,11541,5473],{"emptyLinePlaceholder":5472},[5264,11543,11544],{"class":5266,"line":8198},[5264,11545,10332],{"class":5341},[5264,11547,11548,11550,11552,11554,11556,11558],{"class":5266,"line":8211},[5264,11549,5695],{"class":5288},[5264,11551,10112],{"class":5698},[5264,11553,5702],{"class":5270},[5264,11555,5315],{"class":5314},[5264,11557,5355],{"class":5288},[5264,11559,11047],{"class":5292},[5264,11561,11562,11564,11566,11568],{"class":5266,"line":8218},[5264,11563,11052],{"class":5270},[5264,11565,5315],{"class":5314},[5264,11567,5707],{"class":5270},[5264,11569,11570],{"class":5314},"message\n",[5264,11572,11573,11575,11578],{"class":5266,"line":8231},[5264,11574,11065],{"class":5270},[5264,11576,11577],{"class":5611},"'Internal server error'",[5264,11579,5615],{"class":5270},[5264,11581,11582],{"class":5266,"line":8249},[5264,11583,5473],{"emptyLinePlaceholder":5472},[5264,11585,11586,11588,11590,11592,11594,11596,11598,11600],{"class":5266,"line":8254},[5264,11587,5977],{"class":5314},[5264,11589,5707],{"class":5270},[5264,11591,5982],{"class":5274},[5264,11593,5311],{"class":5270},[5264,11595,5982],{"class":5314},[5264,11597,5989],{"class":5270},[5264,11599,5992],{"class":5274},[5264,11601,7035],{"class":5270},[5264,11603,11604,11606,11608],{"class":5266,"line":8259},[5264,11605,5860],{"class":5314},[5264,11607,5767],{"class":5314},[5264,11609,5865],{"class":5270},[5264,11611,11612,11614,11616,11618,11620,11622,11624,11626,11628],{"class":5266,"line":8272},[5264,11613,5882],{"class":5314},[5264,11615,5767],{"class":5314},[5264,11617,11093],{"class":5270},[5264,11619,9130],{"class":6311},[5264,11621,8591],{"class":5270},[5264,11623,11577],{"class":5611},[5264,11625,11434],{"class":5270},[5264,11627,5830],{"class":5314},[5264,11629,5865],{"class":5270},[5264,11631,11632,11634,11636,11638,11640,11642],{"class":5266,"line":8279},[5264,11633,5893],{"class":5314},[5264,11635,5896],{"class":5288},[5264,11637,5899],{"class":5274},[5264,11639,5902],{"class":5270},[5264,11641,5905],{"class":5274},[5264,11643,5908],{"class":5270},[5264,11645,11646,11648,11650,11652,11654],{"class":5266,"line":8292},[5264,11647,5914],{"class":5314},[5264,11649,5745],{"class":5314},[5264,11651,5707],{"class":5270},[5264,11653,5921],{"class":5314},[5264,11655,5865],{"class":5270},[5264,11657,11658],{"class":5266,"line":8302},[5264,11659,7129],{"class":5270},[5264,11661,11662],{"class":5266,"line":8307},[5264,11663,5425],{"class":5270},[5264,11665,11666],{"class":5266,"line":8312},[5264,11667,5431],{"class":5270},[5206,11669,11670],{},[5144,11671,11672],{},"Реєстрація:",[5254,11674,11676],{"className":5256,"code":11675,"language":5259,"meta":5260,"style":5260},"\u002F\u002F main.ts\napp.useGlobalFilters(new SentryExceptionFilter());\n",[5102,11677,11678,11682],{"__ignoreMap":5260},[5264,11679,11680],{"class":5266,"line":5267},[5264,11681,10640],{"class":5341},[5264,11683,11684,11687,11689,11692,11694,11696,11698],{"class":5266,"line":5281},[5264,11685,11686],{"class":5314},"app",[5264,11688,5707],{"class":5270},[5264,11690,11691],{"class":5274},"useGlobalFilters",[5264,11693,5311],{"class":5270},[5264,11695,7615],{"class":5288},[5264,11697,10939],{"class":5274},[5264,11699,11700],{"class":5270},"());\n",[7468,11702,11703,11705,11706,11709],{},[5144,11704,7472],{}," у Sentry додайте ",[5144,11707,11708],{},"Breadcrumbs"," (сліди виконання) для кращого розуміння контексту помилки. Наприклад, логуйте кожен HTTP-запит як breadcrumb перед обробкою.",[5572,11711,11713],{"id":11712},"додавання-breadcrumbs","Додавання Breadcrumbs",[5254,11715,11717],{"className":5256,"code":11716,"language":5259,"meta":5260,"style":5260},"\u002F\u002F logging.interceptor.ts\nimport { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs\u002Fcommon';\nimport * as Sentry from '@sentry\u002Fnode';\nimport { Observable } from 'rxjs';\nimport { tap } from 'rxjs\u002Foperators';\n\n@Injectable()\nexport class SentryBreadcrumbsInterceptor implements NestInterceptor {\n  intercept(context: ExecutionContext, next: CallHandler): Observable\u003Cany> {\n    const request = context.switchToHttp().getRequest();\n\n    \u002F\u002F Додавання breadcrumb для кожного запиту\n    Sentry.addBreadcrumb({\n      category: 'http',\n      message: `${request.method} ${request.url}`,\n      level: 'info',\n      data: {\n        method: request.method,\n        url: request.url,\n        params: request.params,\n        query: request.query,\n      },\n    });\n\n    return next.handle().pipe(\n      tap(() => {\n        Sentry.addBreadcrumb({\n          category: 'http',\n          message: `${request.method} ${request.url} - Success`,\n          level: 'info',\n        });\n      })\n    );\n  }\n}\n",[5102,11718,11719,11724,11755,11771,11789,11807,11811,11819,11835,11868,11888,11892,11897,11909,11919,11949,11959,11966,11979,11992,12005,12018,12023,12027,12031,12050,12063,12074,12083,12114,12123,12127,12132,12137,12141],{"__ignoreMap":5260},[5264,11720,11721],{"class":5266,"line":5267},[5264,11722,11723],{"class":5341},"\u002F\u002F logging.interceptor.ts\n",[5264,11725,11726,11728,11730,11732,11734,11737,11739,11742,11744,11747,11749,11751,11753],{"class":5266,"line":5281},[5264,11727,5585],{"class":5284},[5264,11729,5463],{"class":5270},[5264,11731,8788],{"class":5314},[5264,11733,5324],{"class":5270},[5264,11735,11736],{"class":5314},"NestInterceptor",[5264,11738,5324],{"class":5270},[5264,11740,11741],{"class":5314},"ExecutionContext",[5264,11743,5324],{"class":5270},[5264,11745,11746],{"class":5314},"CallHandler",[5264,11748,5605],{"class":5270},[5264,11750,5608],{"class":5284},[5264,11752,5612],{"class":5611},[5264,11754,5615],{"class":5270},[5264,11756,11757,11759,11761,11763,11765,11767,11769],{"class":5266,"line":5305},[5264,11758,5585],{"class":5284},[5264,11760,10664],{"class":5288},[5264,11762,7825],{"class":5284},[5264,11764,10669],{"class":5314},[5264,11766,10672],{"class":5284},[5264,11768,10675],{"class":5611},[5264,11770,5615],{"class":5270},[5264,11772,11773,11775,11777,11780,11782,11784,11787],{"class":5266,"line":5338},[5264,11774,5585],{"class":5284},[5264,11776,5463],{"class":5270},[5264,11778,11779],{"class":5314},"Observable",[5264,11781,5605],{"class":5270},[5264,11783,5608],{"class":5284},[5264,11785,11786],{"class":5611}," 'rxjs'",[5264,11788,5615],{"class":5270},[5264,11790,11791,11793,11795,11798,11800,11802,11805],{"class":5266,"line":5345},[5264,11792,5585],{"class":5284},[5264,11794,5463],{"class":5270},[5264,11796,11797],{"class":5314},"tap",[5264,11799,5605],{"class":5270},[5264,11801,5608],{"class":5284},[5264,11803,11804],{"class":5611}," 'rxjs\u002Foperators'",[5264,11806,5615],{"class":5270},[5264,11808,11809],{"class":5266,"line":5370},[5264,11810,5473],{"emptyLinePlaceholder":5472},[5264,11812,11813,11815,11817],{"class":5266,"line":5394},[5264,11814,5271],{"class":5270},[5264,11816,8788],{"class":5274},[5264,11818,5278],{"class":5270},[5264,11820,11821,11823,11825,11828,11830,11833],{"class":5266,"line":5416},[5264,11822,5285],{"class":5284},[5264,11824,5289],{"class":5288},[5264,11826,11827],{"class":5292}," SentryBreadcrumbsInterceptor",[5264,11829,5296],{"class":5288},[5264,11831,11832],{"class":5292}," NestInterceptor",[5264,11834,5302],{"class":5270},[5264,11836,11837,11840,11842,11845,11847,11849,11851,11854,11856,11858,11860,11862,11864,11866],{"class":5266,"line":5422},[5264,11838,11839],{"class":5274},"  intercept",[5264,11841,5311],{"class":5270},[5264,11843,11844],{"class":5314},"context",[5264,11846,5318],{"class":5270},[5264,11848,11741],{"class":5292},[5264,11850,5324],{"class":5270},[5264,11852,11853],{"class":5314},"next",[5264,11855,5318],{"class":5270},[5264,11857,11746],{"class":5292},[5264,11859,6031],{"class":5270},[5264,11861,11779],{"class":5292},[5264,11863,5733],{"class":5270},[5264,11865,5791],{"class":5292},[5264,11867,8878],{"class":5270},[5264,11869,11870,11872,11874,11876,11878,11880,11882,11884,11886],{"class":5266,"line":5428},[5264,11871,5695],{"class":5288},[5264,11873,5745],{"class":5698},[5264,11875,5702],{"class":5270},[5264,11877,11844],{"class":5314},[5264,11879,5707],{"class":5270},[5264,11881,5710],{"class":5274},[5264,11883,5902],{"class":5270},[5264,11885,5754],{"class":5274},[5264,11887,5713],{"class":5270},[5264,11889,11890],{"class":5266,"line":5781},[5264,11891,5473],{"emptyLinePlaceholder":5472},[5264,11893,11894],{"class":5266,"line":5804},[5264,11895,11896],{"class":5341},"    \u002F\u002F Додавання breadcrumb для кожного запиту\n",[5264,11898,11899,11902,11904,11907],{"class":5266,"line":5809},[5264,11900,11901],{"class":5314},"    Sentry",[5264,11903,5707],{"class":5270},[5264,11905,11906],{"class":5274},"addBreadcrumb",[5264,11908,7035],{"class":5270},[5264,11910,11911,11914,11917],{"class":5266,"line":5815},[5264,11912,11913],{"class":5314},"      category:",[5264,11915,11916],{"class":5611}," 'http'",[5264,11918,5865],{"class":5270},[5264,11920,11921,11923,11925,11927,11929,11931,11933,11935,11937,11939,11941,11943,11945,11947],{"class":5266,"line":5835},[5264,11922,5882],{"class":5314},[5264,11924,7059],{"class":5611},[5264,11926,7062],{"class":5288},[5264,11928,10231],{"class":5314},[5264,11930,5707],{"class":7068},[5264,11932,5936],{"class":5314},[5264,11934,7084],{"class":5288},[5264,11936,10240],{"class":5288},[5264,11938,10231],{"class":5314},[5264,11940,5707],{"class":7068},[5264,11942,5921],{"class":5314},[5264,11944,7084],{"class":5288},[5264,11946,8755],{"class":5611},[5264,11948,5865],{"class":5270},[5264,11950,11951,11954,11957],{"class":5266,"line":5840},[5264,11952,11953],{"class":5314},"      level:",[5264,11955,11956],{"class":5611}," 'info'",[5264,11958,5865],{"class":5270},[5264,11960,11961,11964],{"class":5266,"line":5846},[5264,11962,11963],{"class":5314},"      data:",[5264,11965,5302],{"class":5270},[5264,11967,11968,11971,11973,11975,11977],{"class":5266,"line":5857},[5264,11969,11970],{"class":5314},"        method:",[5264,11972,5745],{"class":5314},[5264,11974,5707],{"class":5270},[5264,11976,5936],{"class":5314},[5264,11978,5865],{"class":5270},[5264,11980,11981,11984,11986,11988,11990],{"class":5266,"line":5868},[5264,11982,11983],{"class":5314},"        url:",[5264,11985,5745],{"class":5314},[5264,11987,5707],{"class":5270},[5264,11989,5921],{"class":5314},[5264,11991,5865],{"class":5270},[5264,11993,11994,11997,11999,12001,12003],{"class":5266,"line":5879},[5264,11995,11996],{"class":5314},"        params:",[5264,11998,5745],{"class":5314},[5264,12000,5707],{"class":5270},[5264,12002,11217],{"class":5314},[5264,12004,5865],{"class":5270},[5264,12006,12007,12010,12012,12014,12016],{"class":5266,"line":5890},[5264,12008,12009],{"class":5314},"        query:",[5264,12011,5745],{"class":5314},[5264,12013,5707],{"class":5270},[5264,12015,7763],{"class":5314},[5264,12017,5865],{"class":5270},[5264,12019,12020],{"class":5266,"line":5911},[5264,12021,12022],{"class":5270},"      },\n",[5264,12024,12025],{"class":5266,"line":5926},[5264,12026,7129],{"class":5270},[5264,12028,12029],{"class":5266,"line":5941},[5264,12030,5473],{"emptyLinePlaceholder":5472},[5264,12032,12033,12035,12038,12040,12043,12045,12048],{"class":5266,"line":5963},[5264,12034,6094],{"class":5284},[5264,12036,12037],{"class":5314}," next",[5264,12039,5707],{"class":5270},[5264,12041,12042],{"class":5274},"handle",[5264,12044,5902],{"class":5270},[5264,12046,12047],{"class":5274},"pipe",[5264,12049,8001],{"class":5270},[5264,12051,12052,12055,12058,12061],{"class":5266,"line":5969},[5264,12053,12054],{"class":5274},"      tap",[5264,12056,12057],{"class":5270},"(() ",[5264,12059,12060],{"class":5288},"=>",[5264,12062,5302],{"class":5270},[5264,12064,12065,12068,12070,12072],{"class":5266,"line":5974},[5264,12066,12067],{"class":5314},"        Sentry",[5264,12069,5707],{"class":5270},[5264,12071,11906],{"class":5274},[5264,12073,7035],{"class":5270},[5264,12075,12076,12079,12081],{"class":5266,"line":6003},[5264,12077,12078],{"class":5314},"          category:",[5264,12080,11916],{"class":5611},[5264,12082,5865],{"class":5270},[5264,12084,12085,12087,12089,12091,12093,12095,12097,12099,12101,12103,12105,12107,12109,12112],{"class":5266,"line":6008},[5264,12086,8113],{"class":5314},[5264,12088,7059],{"class":5611},[5264,12090,7062],{"class":5288},[5264,12092,10231],{"class":5314},[5264,12094,5707],{"class":7068},[5264,12096,5936],{"class":5314},[5264,12098,7084],{"class":5288},[5264,12100,10240],{"class":5288},[5264,12102,10231],{"class":5314},[5264,12104,5707],{"class":7068},[5264,12106,5921],{"class":5314},[5264,12108,7084],{"class":5288},[5264,12110,12111],{"class":5611}," - Success`",[5264,12113,5865],{"class":5270},[5264,12115,12116,12119,12121],{"class":5266,"line":6013},[5264,12117,12118],{"class":5314},"          level:",[5264,12120,11956],{"class":5611},[5264,12122,5865],{"class":5270},[5264,12124,12125],{"class":5266,"line":6039},[5264,12126,11224],{"class":5270},[5264,12128,12129],{"class":5266,"line":6062},[5264,12130,12131],{"class":5270},"      })\n",[5264,12133,12134],{"class":5266,"line":6080},[5264,12135,12136],{"class":5270},"    );\n",[5264,12138,12139],{"class":5266,"line":6086},[5264,12140,5425],{"class":5270},[5264,12142,12143],{"class":5266,"line":6091},[5264,12144,5431],{"class":5270},[5206,12146,12147],{},[5144,12148,10480],{},[5254,12150,12152],{"className":5256,"code":12151,"language":5259,"meta":5260,"style":5260},"\u002F\u002F main.ts\napp.useGlobalInterceptors(new SentryBreadcrumbsInterceptor());\n",[5102,12153,12154,12158],{"__ignoreMap":5260},[5264,12155,12156],{"class":5266,"line":5267},[5264,12157,10640],{"class":5341},[5264,12159,12160,12162,12164,12167,12169,12171,12173],{"class":5266,"line":5281},[5264,12161,11686],{"class":5314},[5264,12163,5707],{"class":5270},[5264,12165,12166],{"class":5274},"useGlobalInterceptors",[5264,12168,5311],{"class":5270},[5264,12170,7615],{"class":5288},[5264,12172,11827],{"class":5274},[5264,12174,11700],{"class":5270},[5201,12176,12178],{"id":12177},"timeoutexceptionfilter-обробка-таймаутів","TimeoutExceptionFilter: обробка таймаутів",[5206,12180,12181],{},"Обробка помилок при перевищенні часу виконання запиту:",[5254,12183,12185],{"className":5256,"code":12184,"language":5259,"meta":5260,"style":5260},"import { ExceptionFilter, Catch, ArgumentsHost, RequestTimeoutException, HttpStatus } from '@nestjs\u002Fcommon';\nimport { Request, Response } from 'express';\nimport { TimeoutError } from 'rxjs';\n\n@Catch(TimeoutError, RequestTimeoutException)\nexport class TimeoutExceptionFilter implements ExceptionFilter {\n  catch(exception: TimeoutError | RequestTimeoutException, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse\u003CResponse>();\n    const request = ctx.getRequest\u003CRequest>();\n\n    const errorResponse = {\n      statusCode: HttpStatus.REQUEST_TIMEOUT,\n      error: 'Request Timeout',\n      message: 'The request took too long to process. Please try again later.',\n      timestamp: new Date().toISOString(),\n      path: request.url,\n      method: request.method,\n      suggestion: 'Consider reducing the complexity of the request or checking the server status',\n    };\n\n    response.status(HttpStatus.REQUEST_TIMEOUT).json(errorResponse);\n  }\n}\n",[5102,12186,12187,12220,12240,12257,12261,12277,12292,12318,12334,12354,12374,12378,12386,12399,12408,12417,12431,12443,12455,12465,12469,12473,12499,12503],{"__ignoreMap":5260},[5264,12188,12189,12191,12193,12195,12197,12199,12201,12203,12205,12208,12210,12212,12214,12216,12218],{"class":5266,"line":5267},[5264,12190,5585],{"class":5284},[5264,12192,5463],{"class":5270},[5264,12194,5590],{"class":5314},[5264,12196,5324],{"class":5270},[5264,12198,5275],{"class":5314},[5264,12200,5324],{"class":5270},[5264,12202,5332],{"class":5314},[5264,12204,5324],{"class":5270},[5264,12206,12207],{"class":5314},"RequestTimeoutException",[5264,12209,5324],{"class":5270},[5264,12211,7524],{"class":5314},[5264,12213,5605],{"class":5270},[5264,12215,5608],{"class":5284},[5264,12217,5612],{"class":5611},[5264,12219,5615],{"class":5270},[5264,12221,12222,12224,12226,12228,12230,12232,12234,12236,12238],{"class":5266,"line":5281},[5264,12223,5585],{"class":5284},[5264,12225,5463],{"class":5270},[5264,12227,5624],{"class":5314},[5264,12229,5324],{"class":5270},[5264,12231,5629],{"class":5314},[5264,12233,5605],{"class":5270},[5264,12235,5608],{"class":5284},[5264,12237,5636],{"class":5611},[5264,12239,5615],{"class":5270},[5264,12241,12242,12244,12246,12249,12251,12253,12255],{"class":5266,"line":5305},[5264,12243,5585],{"class":5284},[5264,12245,5463],{"class":5270},[5264,12247,12248],{"class":5314},"TimeoutError",[5264,12250,5605],{"class":5270},[5264,12252,5608],{"class":5284},[5264,12254,11786],{"class":5611},[5264,12256,5615],{"class":5270},[5264,12258,12259],{"class":5266,"line":5338},[5264,12260,5473],{"emptyLinePlaceholder":5472},[5264,12262,12263,12265,12267,12269,12271,12273,12275],{"class":5266,"line":5345},[5264,12264,5271],{"class":5270},[5264,12266,5275],{"class":5274},[5264,12268,5311],{"class":5270},[5264,12270,12248],{"class":5314},[5264,12272,5324],{"class":5270},[5264,12274,12207],{"class":5314},[5264,12276,5451],{"class":5270},[5264,12278,12279,12281,12283,12286,12288,12290],{"class":5266,"line":5370},[5264,12280,5285],{"class":5284},[5264,12282,5289],{"class":5288},[5264,12284,12285],{"class":5292}," TimeoutExceptionFilter",[5264,12287,5296],{"class":5288},[5264,12289,5299],{"class":5292},[5264,12291,5302],{"class":5270},[5264,12293,12294,12296,12298,12300,12302,12304,12306,12308,12310,12312,12314,12316],{"class":5266,"line":5394},[5264,12295,5308],{"class":5274},[5264,12297,5311],{"class":5270},[5264,12299,5315],{"class":5314},[5264,12301,5318],{"class":5270},[5264,12303,12248],{"class":5292},[5264,12305,10119],{"class":5270},[5264,12307,12207],{"class":5292},[5264,12309,5324],{"class":5270},[5264,12311,5327],{"class":5314},[5264,12313,5318],{"class":5270},[5264,12315,5332],{"class":5292},[5264,12317,5335],{"class":5270},[5264,12319,12320,12322,12324,12326,12328,12330,12332],{"class":5266,"line":5416},[5264,12321,5695],{"class":5288},[5264,12323,5699],{"class":5698},[5264,12325,5702],{"class":5270},[5264,12327,5327],{"class":5314},[5264,12329,5707],{"class":5270},[5264,12331,5710],{"class":5274},[5264,12333,5713],{"class":5270},[5264,12335,12336,12338,12340,12342,12344,12346,12348,12350,12352],{"class":5266,"line":5422},[5264,12337,5695],{"class":5288},[5264,12339,5720],{"class":5698},[5264,12341,5702],{"class":5270},[5264,12343,5725],{"class":5314},[5264,12345,5707],{"class":5270},[5264,12347,5730],{"class":5274},[5264,12349,5733],{"class":5270},[5264,12351,5629],{"class":5292},[5264,12353,5738],{"class":5270},[5264,12355,12356,12358,12360,12362,12364,12366,12368,12370,12372],{"class":5266,"line":5428},[5264,12357,5695],{"class":5288},[5264,12359,5745],{"class":5698},[5264,12361,5702],{"class":5270},[5264,12363,5725],{"class":5314},[5264,12365,5707],{"class":5270},[5264,12367,5754],{"class":5274},[5264,12369,5733],{"class":5270},[5264,12371,5624],{"class":5292},[5264,12373,5738],{"class":5270},[5264,12375,12376],{"class":5266,"line":5781},[5264,12377,5473],{"emptyLinePlaceholder":5472},[5264,12379,12380,12382,12384],{"class":5266,"line":5804},[5264,12381,5695],{"class":5288},[5264,12383,5851],{"class":5698},[5264,12385,5854],{"class":5270},[5264,12387,12388,12390,12392,12394,12397],{"class":5266,"line":5809},[5264,12389,5860],{"class":5314},[5264,12391,8100],{"class":5314},[5264,12393,5707],{"class":5270},[5264,12395,12396],{"class":5698},"REQUEST_TIMEOUT",[5264,12398,5865],{"class":5270},[5264,12400,12401,12403,12406],{"class":5266,"line":5815},[5264,12402,5871],{"class":5314},[5264,12404,12405],{"class":5611}," 'Request Timeout'",[5264,12407,5865],{"class":5270},[5264,12409,12410,12412,12415],{"class":5266,"line":5835},[5264,12411,5882],{"class":5314},[5264,12413,12414],{"class":5611}," 'The request took too long to process. Please try again later.'",[5264,12416,5865],{"class":5270},[5264,12418,12419,12421,12423,12425,12427,12429],{"class":5266,"line":5840},[5264,12420,5893],{"class":5314},[5264,12422,5896],{"class":5288},[5264,12424,5899],{"class":5274},[5264,12426,5902],{"class":5270},[5264,12428,5905],{"class":5274},[5264,12430,5908],{"class":5270},[5264,12432,12433,12435,12437,12439,12441],{"class":5266,"line":5846},[5264,12434,5914],{"class":5314},[5264,12436,5745],{"class":5314},[5264,12438,5707],{"class":5270},[5264,12440,5921],{"class":5314},[5264,12442,5865],{"class":5270},[5264,12444,12445,12447,12449,12451,12453],{"class":5266,"line":5857},[5264,12446,5929],{"class":5314},[5264,12448,5745],{"class":5314},[5264,12450,5707],{"class":5270},[5264,12452,5936],{"class":5314},[5264,12454,5865],{"class":5270},[5264,12456,12457,12460,12463],{"class":5266,"line":5868},[5264,12458,12459],{"class":5314},"      suggestion:",[5264,12461,12462],{"class":5611}," 'Consider reducing the complexity of the request or checking the server status'",[5264,12464,5865],{"class":5270},[5264,12466,12467],{"class":5266,"line":5879},[5264,12468,5966],{"class":5270},[5264,12470,12471],{"class":5266,"line":5890},[5264,12472,5473],{"emptyLinePlaceholder":5472},[5264,12474,12475,12477,12479,12481,12483,12485,12487,12489,12491,12493,12495,12497],{"class":5266,"line":5911},[5264,12476,5977],{"class":5314},[5264,12478,5707],{"class":5270},[5264,12480,5982],{"class":5274},[5264,12482,5311],{"class":5270},[5264,12484,7524],{"class":5314},[5264,12486,5707],{"class":5270},[5264,12488,12396],{"class":5698},[5264,12490,5989],{"class":5270},[5264,12492,5992],{"class":5274},[5264,12494,5311],{"class":5270},[5264,12496,5997],{"class":5314},[5264,12498,6000],{"class":5270},[5264,12500,12501],{"class":5266,"line":5926},[5264,12502,5425],{"class":5270},[5264,12504,12505],{"class":5266,"line":5941},[5264,12506,5431],{"class":5270},[5206,12508,12509],{},[5144,12510,12511],{},"Використання з Timeout Interceptor:",[5254,12513,12515],{"className":5256,"code":12514,"language":5259,"meta":5260,"style":5260},"\u002F\u002F timeout.interceptor.ts\nimport { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs\u002Fcommon';\nimport { Observable, throwError, TimeoutError } from 'rxjs';\nimport { catchError, timeout } from 'rxjs\u002Foperators';\n\n@Injectable()\nexport class TimeoutInterceptor implements NestInterceptor {\n  intercept(context: ExecutionContext, next: CallHandler): Observable\u003Cany> {\n    return next.handle().pipe(\n      timeout(5000), \u002F\u002F 5 секунд\n      catchError(err => {\n        if (err instanceof TimeoutError) {\n          return throwError(() => new RequestTimeoutException('Operation timed out'));\n        }\n        return throwError(() => err);\n      }),\n    );\n  }\n}\n\n\u002F\u002F app.module.ts\n@Module({\n  providers: [\n    { provide: APP_INTERCEPTOR, useClass: TimeoutInterceptor },\n    { provide: APP_FILTER, useClass: TimeoutExceptionFilter },\n  ],\n})\nexport class AppModule {}\n",[5102,12516,12517,12522,12550,12575,12597,12601,12609,12624,12654,12670,12686,12700,12715,12740,12744,12759,12763,12767,12771,12775,12779,12783,12791,12797,12818,12834,12838,12842],{"__ignoreMap":5260},[5264,12518,12519],{"class":5266,"line":5267},[5264,12520,12521],{"class":5341},"\u002F\u002F timeout.interceptor.ts\n",[5264,12523,12524,12526,12528,12530,12532,12534,12536,12538,12540,12542,12544,12546,12548],{"class":5266,"line":5281},[5264,12525,5585],{"class":5284},[5264,12527,5463],{"class":5270},[5264,12529,8788],{"class":5314},[5264,12531,5324],{"class":5270},[5264,12533,11736],{"class":5314},[5264,12535,5324],{"class":5270},[5264,12537,11741],{"class":5314},[5264,12539,5324],{"class":5270},[5264,12541,11746],{"class":5314},[5264,12543,5605],{"class":5270},[5264,12545,5608],{"class":5284},[5264,12547,5612],{"class":5611},[5264,12549,5615],{"class":5270},[5264,12551,12552,12554,12556,12558,12560,12563,12565,12567,12569,12571,12573],{"class":5266,"line":5305},[5264,12553,5585],{"class":5284},[5264,12555,5463],{"class":5270},[5264,12557,11779],{"class":5314},[5264,12559,5324],{"class":5270},[5264,12561,12562],{"class":5314},"throwError",[5264,12564,5324],{"class":5270},[5264,12566,12248],{"class":5314},[5264,12568,5605],{"class":5270},[5264,12570,5608],{"class":5284},[5264,12572,11786],{"class":5611},[5264,12574,5615],{"class":5270},[5264,12576,12577,12579,12581,12584,12586,12589,12591,12593,12595],{"class":5266,"line":5338},[5264,12578,5585],{"class":5284},[5264,12580,5463],{"class":5270},[5264,12582,12583],{"class":5314},"catchError",[5264,12585,5324],{"class":5270},[5264,12587,12588],{"class":5314},"timeout",[5264,12590,5605],{"class":5270},[5264,12592,5608],{"class":5284},[5264,12594,11804],{"class":5611},[5264,12596,5615],{"class":5270},[5264,12598,12599],{"class":5266,"line":5345},[5264,12600,5473],{"emptyLinePlaceholder":5472},[5264,12602,12603,12605,12607],{"class":5266,"line":5370},[5264,12604,5271],{"class":5270},[5264,12606,8788],{"class":5274},[5264,12608,5278],{"class":5270},[5264,12610,12611,12613,12615,12618,12620,12622],{"class":5266,"line":5394},[5264,12612,5285],{"class":5284},[5264,12614,5289],{"class":5288},[5264,12616,12617],{"class":5292}," TimeoutInterceptor",[5264,12619,5296],{"class":5288},[5264,12621,11832],{"class":5292},[5264,12623,5302],{"class":5270},[5264,12625,12626,12628,12630,12632,12634,12636,12638,12640,12642,12644,12646,12648,12650,12652],{"class":5266,"line":5416},[5264,12627,11839],{"class":5274},[5264,12629,5311],{"class":5270},[5264,12631,11844],{"class":5314},[5264,12633,5318],{"class":5270},[5264,12635,11741],{"class":5292},[5264,12637,5324],{"class":5270},[5264,12639,11853],{"class":5314},[5264,12641,5318],{"class":5270},[5264,12643,11746],{"class":5292},[5264,12645,6031],{"class":5270},[5264,12647,11779],{"class":5292},[5264,12649,5733],{"class":5270},[5264,12651,5791],{"class":5292},[5264,12653,8878],{"class":5270},[5264,12655,12656,12658,12660,12662,12664,12666,12668],{"class":5266,"line":5422},[5264,12657,6094],{"class":5284},[5264,12659,12037],{"class":5314},[5264,12661,5707],{"class":5270},[5264,12663,12042],{"class":5274},[5264,12665,5902],{"class":5270},[5264,12667,12047],{"class":5274},[5264,12669,8001],{"class":5270},[5264,12671,12672,12675,12677,12680,12683],{"class":5266,"line":5428},[5264,12673,12674],{"class":5274},"      timeout",[5264,12676,5311],{"class":5270},[5264,12678,12679],{"class":6311},"5000",[5264,12681,12682],{"class":5270},"), ",[5264,12684,12685],{"class":5341},"\u002F\u002F 5 секунд\n",[5264,12687,12688,12691,12693,12696,12698],{"class":5266,"line":5781},[5264,12689,12690],{"class":5274},"      catchError",[5264,12692,5311],{"class":5270},[5264,12694,12695],{"class":5314},"err",[5264,12697,6109],{"class":5288},[5264,12699,5302],{"class":5270},[5264,12701,12702,12704,12706,12708,12710,12713],{"class":5266,"line":5804},[5264,12703,11238],{"class":5284},[5264,12705,5146],{"class":5270},[5264,12707,12695],{"class":5314},[5264,12709,5355],{"class":5288},[5264,12711,12712],{"class":5292}," TimeoutError",[5264,12714,5335],{"class":5270},[5264,12716,12717,12720,12723,12725,12727,12729,12732,12734,12737],{"class":5266,"line":5809},[5264,12718,12719],{"class":5284},"          return",[5264,12721,12722],{"class":5274}," throwError",[5264,12724,12057],{"class":5270},[5264,12726,12060],{"class":5288},[5264,12728,5896],{"class":5288},[5264,12730,12731],{"class":5274}," RequestTimeoutException",[5264,12733,5311],{"class":5270},[5264,12735,12736],{"class":5611},"'Operation timed out'",[5264,12738,12739],{"class":5270},"));\n",[5264,12741,12742],{"class":5266,"line":5815},[5264,12743,11325],{"class":5270},[5264,12745,12746,12748,12750,12752,12754,12757],{"class":5266,"line":5835},[5264,12747,8089],{"class":5284},[5264,12749,12722],{"class":5274},[5264,12751,12057],{"class":5270},[5264,12753,12060],{"class":5288},[5264,12755,12756],{"class":5314}," err",[5264,12758,6000],{"class":5270},[5264,12760,12761],{"class":5266,"line":5840},[5264,12762,10437],{"class":5270},[5264,12764,12765],{"class":5266,"line":5846},[5264,12766,12136],{"class":5270},[5264,12768,12769],{"class":5266,"line":5857},[5264,12770,5425],{"class":5270},[5264,12772,12773],{"class":5266,"line":5868},[5264,12774,5431],{"class":5270},[5264,12776,12777],{"class":5266,"line":5879},[5264,12778,5473],{"emptyLinePlaceholder":5472},[5264,12780,12781],{"class":5266,"line":5890},[5264,12782,10490],{"class":5341},[5264,12784,12785,12787,12789],{"class":5266,"line":5911},[5264,12786,5271],{"class":5270},[5264,12788,10499],{"class":5274},[5264,12790,7035],{"class":5270},[5264,12792,12793,12795],{"class":5266,"line":5926},[5264,12794,10542],{"class":5314},[5264,12796,10545],{"class":5270},[5264,12798,12799,12802,12805,12808,12810,12813,12815],{"class":5266,"line":5941},[5264,12800,12801],{"class":5270},"    { ",[5264,12803,12804],{"class":5314},"provide:",[5264,12806,12807],{"class":5698}," APP_INTERCEPTOR",[5264,12809,5324],{"class":5270},[5264,12811,12812],{"class":5314},"useClass:",[5264,12814,12617],{"class":5314},[5264,12816,12817],{"class":5270}," },\n",[5264,12819,12820,12822,12824,12826,12828,12830,12832],{"class":5266,"line":5963},[5264,12821,12801],{"class":5270},[5264,12823,12804],{"class":5314},[5264,12825,10557],{"class":5698},[5264,12827,5324],{"class":5270},[5264,12829,12812],{"class":5314},[5264,12831,12285],{"class":5314},[5264,12833,12817],{"class":5270},[5264,12835,12836],{"class":5266,"line":5969},[5264,12837,10577],{"class":5270},[5264,12839,12840],{"class":5266,"line":5974},[5264,12841,10582],{"class":5270},[5264,12843,12844,12846,12848,12850],{"class":5266,"line":6003},[5264,12845,5285],{"class":5284},[5264,12847,5289],{"class":5288},[5264,12849,10591],{"class":5292},[5264,12851,10594],{"class":5270},[5201,12853,12855],{"id":12854},"unauthorizedexceptionfilter-спеціалізована-обробка-401","UnauthorizedExceptionFilter: спеціалізована обробка 401",[5206,12857,12858],{},"Додавання WWW-Authenticate заголовків для помилок аутентифікації:",[5254,12860,12862],{"className":5256,"code":12861,"language":5259,"meta":5260,"style":5260},"import { ExceptionFilter, Catch, ArgumentsHost, UnauthorizedException, Logger } from '@nestjs\u002Fcommon';\nimport { Request, Response } from 'express';\n\n@Catch(UnauthorizedException)\nexport class UnauthorizedExceptionFilter implements ExceptionFilter {\n  private readonly logger = new Logger(UnauthorizedExceptionFilter.name);\n\n  catch(exception: UnauthorizedException, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse\u003CResponse>();\n    const request = ctx.getRequest\u003CRequest>();\n\n    \u002F\u002F Логування спроб несанкціонованого доступу\n    this.logger.warn('Unauthorized access attempt', {\n      path: request.url,\n      method: request.method,\n      ip: request.ip,\n      userAgent: request.get('user-agent'),\n      authHeader: request.headers.authorization ? 'present' : 'missing',\n    });\n\n    \u002F\u002F Додавання WWW-Authenticate заголовку\n    response.setHeader('WWW-Authenticate', 'Bearer realm=\"api\"');\n\n    \u002F\u002F Формування відповіді\n    const errorResponse = {\n      statusCode: 401,\n      error: 'Unauthorized',\n      message: 'Authentication is required to access this resource',\n      timestamp: new Date().toISOString(),\n      path: request.url,\n      actions: [\n        {\n          type: 'login',\n          label: 'Login',\n          url: '\u002Fauth\u002Flogin',\n        },\n        {\n          type: 'register',\n          label: 'Create Account',\n          url: '\u002Fauth\u002Fregister',\n        },\n      ],\n    };\n\n    response.status(401).json(errorResponse);\n  }\n}\n",[5102,12863,12864,12896,12916,12920,12932,12947,12971,12975,12997,13013,13033,13053,13057,13062,13081,13093,13105,13117,13133,13161,13165,13169,13174,13195,13199,13203,13211,13220,13229,13238,13252,13264,13271,13276,13286,13296,13305,13310,13314,13323,13332,13341,13345,13350,13354,13358,13381,13385],{"__ignoreMap":5260},[5264,12865,12866,12868,12870,12872,12874,12876,12878,12880,12882,12884,12886,12888,12890,12892,12894],{"class":5266,"line":5267},[5264,12867,5585],{"class":5284},[5264,12869,5463],{"class":5270},[5264,12871,5590],{"class":5314},[5264,12873,5324],{"class":5270},[5264,12875,5275],{"class":5314},[5264,12877,5324],{"class":5270},[5264,12879,5332],{"class":5314},[5264,12881,5324],{"class":5270},[5264,12883,5516],{"class":5314},[5264,12885,5324],{"class":5270},[5264,12887,7529],{"class":5314},[5264,12889,5605],{"class":5270},[5264,12891,5608],{"class":5284},[5264,12893,5612],{"class":5611},[5264,12895,5615],{"class":5270},[5264,12897,12898,12900,12902,12904,12906,12908,12910,12912,12914],{"class":5266,"line":5281},[5264,12899,5585],{"class":5284},[5264,12901,5463],{"class":5270},[5264,12903,5624],{"class":5314},[5264,12905,5324],{"class":5270},[5264,12907,5629],{"class":5314},[5264,12909,5605],{"class":5270},[5264,12911,5608],{"class":5284},[5264,12913,5636],{"class":5611},[5264,12915,5615],{"class":5270},[5264,12917,12918],{"class":5266,"line":5305},[5264,12919,5473],{"emptyLinePlaceholder":5472},[5264,12921,12922,12924,12926,12928,12930],{"class":5266,"line":5338},[5264,12923,5271],{"class":5270},[5264,12925,5275],{"class":5274},[5264,12927,5311],{"class":5270},[5264,12929,5516],{"class":5314},[5264,12931,5451],{"class":5270},[5264,12933,12934,12936,12938,12941,12943,12945],{"class":5266,"line":5345},[5264,12935,5285],{"class":5284},[5264,12937,5289],{"class":5288},[5264,12939,12940],{"class":5292}," UnauthorizedExceptionFilter",[5264,12942,5296],{"class":5288},[5264,12944,5299],{"class":5292},[5264,12946,5302],{"class":5270},[5264,12948,12949,12951,12953,12955,12957,12959,12961,12963,12965,12967,12969],{"class":5266,"line":5370},[5264,12950,6016],{"class":5288},[5264,12952,7607],{"class":5288},[5264,12954,7610],{"class":5314},[5264,12956,5702],{"class":5270},[5264,12958,7615],{"class":5288},[5264,12960,7618],{"class":5274},[5264,12962,5311],{"class":5270},[5264,12964,5132],{"class":5314},[5264,12966,5707],{"class":5270},[5264,12968,7627],{"class":5314},[5264,12970,6000],{"class":5270},[5264,12972,12973],{"class":5266,"line":5394},[5264,12974,5473],{"emptyLinePlaceholder":5472},[5264,12976,12977,12979,12981,12983,12985,12987,12989,12991,12993,12995],{"class":5266,"line":5416},[5264,12978,5308],{"class":5274},[5264,12980,5311],{"class":5270},[5264,12982,5315],{"class":5314},[5264,12984,5318],{"class":5270},[5264,12986,5516],{"class":5292},[5264,12988,5324],{"class":5270},[5264,12990,5327],{"class":5314},[5264,12992,5318],{"class":5270},[5264,12994,5332],{"class":5292},[5264,12996,5335],{"class":5270},[5264,12998,12999,13001,13003,13005,13007,13009,13011],{"class":5266,"line":5422},[5264,13000,5695],{"class":5288},[5264,13002,5699],{"class":5698},[5264,13004,5702],{"class":5270},[5264,13006,5327],{"class":5314},[5264,13008,5707],{"class":5270},[5264,13010,5710],{"class":5274},[5264,13012,5713],{"class":5270},[5264,13014,13015,13017,13019,13021,13023,13025,13027,13029,13031],{"class":5266,"line":5428},[5264,13016,5695],{"class":5288},[5264,13018,5720],{"class":5698},[5264,13020,5702],{"class":5270},[5264,13022,5725],{"class":5314},[5264,13024,5707],{"class":5270},[5264,13026,5730],{"class":5274},[5264,13028,5733],{"class":5270},[5264,13030,5629],{"class":5292},[5264,13032,5738],{"class":5270},[5264,13034,13035,13037,13039,13041,13043,13045,13047,13049,13051],{"class":5266,"line":5781},[5264,13036,5695],{"class":5288},[5264,13038,5745],{"class":5698},[5264,13040,5702],{"class":5270},[5264,13042,5725],{"class":5314},[5264,13044,5707],{"class":5270},[5264,13046,5754],{"class":5274},[5264,13048,5733],{"class":5270},[5264,13050,5624],{"class":5292},[5264,13052,5738],{"class":5270},[5264,13054,13055],{"class":5266,"line":5804},[5264,13056,5473],{"emptyLinePlaceholder":5472},[5264,13058,13059],{"class":5266,"line":5809},[5264,13060,13061],{"class":5341},"    \u002F\u002F Логування спроб несанкціонованого доступу\n",[5264,13063,13064,13066,13068,13070,13072,13074,13076,13079],{"class":5266,"line":5815},[5264,13065,7721],{"class":5288},[5264,13067,5707],{"class":5270},[5264,13069,7726],{"class":5314},[5264,13071,5707],{"class":5270},[5264,13073,10212],{"class":5274},[5264,13075,5311],{"class":5270},[5264,13077,13078],{"class":5611},"'Unauthorized access attempt'",[5264,13080,7738],{"class":5270},[5264,13082,13083,13085,13087,13089,13091],{"class":5266,"line":5835},[5264,13084,5914],{"class":5314},[5264,13086,5745],{"class":5314},[5264,13088,5707],{"class":5270},[5264,13090,5921],{"class":5314},[5264,13092,5865],{"class":5270},[5264,13094,13095,13097,13099,13101,13103],{"class":5266,"line":5840},[5264,13096,5929],{"class":5314},[5264,13098,5745],{"class":5314},[5264,13100,5707],{"class":5270},[5264,13102,5936],{"class":5314},[5264,13104,5865],{"class":5270},[5264,13106,13107,13109,13111,13113,13115],{"class":5266,"line":5846},[5264,13108,10291],{"class":5314},[5264,13110,5745],{"class":5314},[5264,13112,5707],{"class":5270},[5264,13114,10298],{"class":5314},[5264,13116,5865],{"class":5270},[5264,13118,13119,13121,13123,13125,13127,13129,13131],{"class":5266,"line":5857},[5264,13120,10305],{"class":5314},[5264,13122,5745],{"class":5314},[5264,13124,5707],{"class":5270},[5264,13126,10312],{"class":5274},[5264,13128,5311],{"class":5270},[5264,13130,10317],{"class":5611},[5264,13132,5960],{"class":5270},[5264,13134,13135,13138,13140,13142,13144,13146,13149,13151,13154,13156,13159],{"class":5266,"line":5868},[5264,13136,13137],{"class":5314},"      authHeader:",[5264,13139,5745],{"class":5314},[5264,13141,5707],{"class":5270},[5264,13143,11176],{"class":5314},[5264,13145,5707],{"class":5270},[5264,13147,13148],{"class":5314},"authorization",[5264,13150,8591],{"class":5270},[5264,13152,13153],{"class":5611},"'present'",[5264,13155,11434],{"class":5270},[5264,13157,13158],{"class":5611},"'missing'",[5264,13160,5865],{"class":5270},[5264,13162,13163],{"class":5266,"line":5879},[5264,13164,7129],{"class":5270},[5264,13166,13167],{"class":5266,"line":5890},[5264,13168,5473],{"emptyLinePlaceholder":5472},[5264,13170,13171],{"class":5266,"line":5911},[5264,13172,13173],{"class":5341},"    \u002F\u002F Додавання WWW-Authenticate заголовку\n",[5264,13175,13176,13178,13180,13183,13185,13188,13190,13193],{"class":5266,"line":5926},[5264,13177,5977],{"class":5314},[5264,13179,5707],{"class":5270},[5264,13181,13182],{"class":5274},"setHeader",[5264,13184,5311],{"class":5270},[5264,13186,13187],{"class":5611},"'WWW-Authenticate'",[5264,13189,5324],{"class":5270},[5264,13191,13192],{"class":5611},"'Bearer realm=\"api\"'",[5264,13194,6000],{"class":5270},[5264,13196,13197],{"class":5266,"line":5941},[5264,13198,5473],{"emptyLinePlaceholder":5472},[5264,13200,13201],{"class":5266,"line":5963},[5264,13202,10332],{"class":5341},[5264,13204,13205,13207,13209],{"class":5266,"line":5969},[5264,13206,5695],{"class":5288},[5264,13208,5851],{"class":5698},[5264,13210,5854],{"class":5270},[5264,13212,13213,13215,13218],{"class":5266,"line":5974},[5264,13214,5860],{"class":5314},[5264,13216,13217],{"class":6311}," 401",[5264,13219,5865],{"class":5270},[5264,13221,13222,13224,13227],{"class":5266,"line":6003},[5264,13223,5871],{"class":5314},[5264,13225,13226],{"class":5611}," 'Unauthorized'",[5264,13228,5865],{"class":5270},[5264,13230,13231,13233,13236],{"class":5266,"line":6008},[5264,13232,5882],{"class":5314},[5264,13234,13235],{"class":5611}," 'Authentication is required to access this resource'",[5264,13237,5865],{"class":5270},[5264,13239,13240,13242,13244,13246,13248,13250],{"class":5266,"line":6013},[5264,13241,5893],{"class":5314},[5264,13243,5896],{"class":5288},[5264,13245,5899],{"class":5274},[5264,13247,5902],{"class":5270},[5264,13249,5905],{"class":5274},[5264,13251,5908],{"class":5270},[5264,13253,13254,13256,13258,13260,13262],{"class":5266,"line":6039},[5264,13255,5914],{"class":5314},[5264,13257,5745],{"class":5314},[5264,13259,5707],{"class":5270},[5264,13261,5921],{"class":5314},[5264,13263,5865],{"class":5270},[5264,13265,13266,13269],{"class":5266,"line":6062},[5264,13267,13268],{"class":5314},"      actions:",[5264,13270,10545],{"class":5270},[5264,13272,13273],{"class":5266,"line":6080},[5264,13274,13275],{"class":5270},"        {\n",[5264,13277,13278,13281,13284],{"class":5266,"line":6086},[5264,13279,13280],{"class":5314},"          type:",[5264,13282,13283],{"class":5611}," 'login'",[5264,13285,5865],{"class":5270},[5264,13287,13288,13291,13294],{"class":5266,"line":6091},[5264,13289,13290],{"class":5314},"          label:",[5264,13292,13293],{"class":5611}," 'Login'",[5264,13295,5865],{"class":5270},[5264,13297,13298,13300,13303],{"class":5266,"line":6115},[5264,13299,11156],{"class":5314},[5264,13301,13302],{"class":5611}," '\u002Fauth\u002Flogin'",[5264,13304,5865],{"class":5270},[5264,13306,13307],{"class":5266,"line":6131},[5264,13308,13309],{"class":5270},"        },\n",[5264,13311,13312],{"class":5266,"line":6146},[5264,13313,13275],{"class":5270},[5264,13315,13316,13318,13321],{"class":5266,"line":6172},[5264,13317,13280],{"class":5314},[5264,13319,13320],{"class":5611}," 'register'",[5264,13322,5865],{"class":5270},[5264,13324,13325,13327,13330],{"class":5266,"line":6178},[5264,13326,13290],{"class":5314},[5264,13328,13329],{"class":5611}," 'Create Account'",[5264,13331,5865],{"class":5270},[5264,13333,13334,13336,13339],{"class":5266,"line":6183},[5264,13335,11156],{"class":5314},[5264,13337,13338],{"class":5611}," '\u002Fauth\u002Fregister'",[5264,13340,5865],{"class":5270},[5264,13342,13343],{"class":5266,"line":8036},[5264,13344,13309],{"class":5270},[5264,13346,13347],{"class":5266,"line":8060},[5264,13348,13349],{"class":5270},"      ],\n",[5264,13351,13352],{"class":5266,"line":8072},[5264,13353,5966],{"class":5270},[5264,13355,13356],{"class":5266,"line":8086},[5264,13357,5473],{"emptyLinePlaceholder":5472},[5264,13359,13360,13362,13364,13366,13368,13371,13373,13375,13377,13379],{"class":5266,"line":8094},[5264,13361,5977],{"class":5314},[5264,13363,5707],{"class":5270},[5264,13365,5982],{"class":5274},[5264,13367,5311],{"class":5270},[5264,13369,13370],{"class":6311},"401",[5264,13372,5989],{"class":5270},[5264,13374,5992],{"class":5274},[5264,13376,5311],{"class":5270},[5264,13378,5997],{"class":5314},[5264,13380,6000],{"class":5270},[5264,13382,13383],{"class":5266,"line":8110},[5264,13384,5425],{"class":5270},[5264,13386,13387],{"class":5266,"line":8133},[5264,13388,5431],{"class":5270},[5201,13390,13392],{"id":13391},"forbiddenexceptionfilter-обробка-403-з-логуванням","ForbiddenExceptionFilter: обробка 403 з логуванням",[5254,13394,13396],{"className":5256,"code":13395,"language":5259,"meta":5260,"style":5260},"import { ExceptionFilter, Catch, ArgumentsHost, ForbiddenException, Logger } from '@nestjs\u002Fcommon';\nimport { Request, Response } from 'express';\n\n@Catch(ForbiddenException)\nexport class ForbiddenExceptionFilter implements ExceptionFilter {\n  private readonly logger = new Logger(ForbiddenExceptionFilter.name);\n\n  catch(exception: ForbiddenException, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse\u003CResponse>();\n    const request = ctx.getRequest\u003CRequest>();\n\n    \u002F\u002F Логування спроб доступу до заборонених ресурсів\n    this.logger.warn('Forbidden access attempt', {\n      userId: request['user']?.id,\n      path: request.url,\n      method: request.method,\n      roles: request['user']?.roles,\n      ip: request.ip,\n    });\n\n    const errorResponse = {\n      statusCode: 403,\n      error: 'Forbidden',\n      message: 'You do not have permission to access this resource',\n      timestamp: new Date().toISOString(),\n      path: request.url,\n      requiredPermissions: exception['requiredPermissions'], \u002F\u002F З метаданих Guard\n    };\n\n    response.status(403).json(errorResponse);\n  }\n}\n",[5102,13397,13398,13431,13451,13455,13467,13482,13507,13511,13533,13549,13569,13589,13593,13598,13617,13634,13646,13658,13676,13688,13692,13696,13704,13713,13722,13731,13745,13757,13775,13779,13783,13806,13810],{"__ignoreMap":5260},[5264,13399,13400,13402,13404,13406,13408,13410,13412,13414,13416,13419,13421,13423,13425,13427,13429],{"class":5266,"line":5267},[5264,13401,5585],{"class":5284},[5264,13403,5463],{"class":5270},[5264,13405,5590],{"class":5314},[5264,13407,5324],{"class":5270},[5264,13409,5275],{"class":5314},[5264,13411,5324],{"class":5270},[5264,13413,5332],{"class":5314},[5264,13415,5324],{"class":5270},[5264,13417,13418],{"class":5314},"ForbiddenException",[5264,13420,5324],{"class":5270},[5264,13422,7529],{"class":5314},[5264,13424,5605],{"class":5270},[5264,13426,5608],{"class":5284},[5264,13428,5612],{"class":5611},[5264,13430,5615],{"class":5270},[5264,13432,13433,13435,13437,13439,13441,13443,13445,13447,13449],{"class":5266,"line":5281},[5264,13434,5585],{"class":5284},[5264,13436,5463],{"class":5270},[5264,13438,5624],{"class":5314},[5264,13440,5324],{"class":5270},[5264,13442,5629],{"class":5314},[5264,13444,5605],{"class":5270},[5264,13446,5608],{"class":5284},[5264,13448,5636],{"class":5611},[5264,13450,5615],{"class":5270},[5264,13452,13453],{"class":5266,"line":5305},[5264,13454,5473],{"emptyLinePlaceholder":5472},[5264,13456,13457,13459,13461,13463,13465],{"class":5266,"line":5338},[5264,13458,5271],{"class":5270},[5264,13460,5275],{"class":5274},[5264,13462,5311],{"class":5270},[5264,13464,13418],{"class":5314},[5264,13466,5451],{"class":5270},[5264,13468,13469,13471,13473,13476,13478,13480],{"class":5266,"line":5345},[5264,13470,5285],{"class":5284},[5264,13472,5289],{"class":5288},[5264,13474,13475],{"class":5292}," ForbiddenExceptionFilter",[5264,13477,5296],{"class":5288},[5264,13479,5299],{"class":5292},[5264,13481,5302],{"class":5270},[5264,13483,13484,13486,13488,13490,13492,13494,13496,13498,13501,13503,13505],{"class":5266,"line":5370},[5264,13485,6016],{"class":5288},[5264,13487,7607],{"class":5288},[5264,13489,7610],{"class":5314},[5264,13491,5702],{"class":5270},[5264,13493,7615],{"class":5288},[5264,13495,7618],{"class":5274},[5264,13497,5311],{"class":5270},[5264,13499,13500],{"class":5314},"ForbiddenExceptionFilter",[5264,13502,5707],{"class":5270},[5264,13504,7627],{"class":5314},[5264,13506,6000],{"class":5270},[5264,13508,13509],{"class":5266,"line":5394},[5264,13510,5473],{"emptyLinePlaceholder":5472},[5264,13512,13513,13515,13517,13519,13521,13523,13525,13527,13529,13531],{"class":5266,"line":5416},[5264,13514,5308],{"class":5274},[5264,13516,5311],{"class":5270},[5264,13518,5315],{"class":5314},[5264,13520,5318],{"class":5270},[5264,13522,13418],{"class":5292},[5264,13524,5324],{"class":5270},[5264,13526,5327],{"class":5314},[5264,13528,5318],{"class":5270},[5264,13530,5332],{"class":5292},[5264,13532,5335],{"class":5270},[5264,13534,13535,13537,13539,13541,13543,13545,13547],{"class":5266,"line":5422},[5264,13536,5695],{"class":5288},[5264,13538,5699],{"class":5698},[5264,13540,5702],{"class":5270},[5264,13542,5327],{"class":5314},[5264,13544,5707],{"class":5270},[5264,13546,5710],{"class":5274},[5264,13548,5713],{"class":5270},[5264,13550,13551,13553,13555,13557,13559,13561,13563,13565,13567],{"class":5266,"line":5428},[5264,13552,5695],{"class":5288},[5264,13554,5720],{"class":5698},[5264,13556,5702],{"class":5270},[5264,13558,5725],{"class":5314},[5264,13560,5707],{"class":5270},[5264,13562,5730],{"class":5274},[5264,13564,5733],{"class":5270},[5264,13566,5629],{"class":5292},[5264,13568,5738],{"class":5270},[5264,13570,13571,13573,13575,13577,13579,13581,13583,13585,13587],{"class":5266,"line":5781},[5264,13572,5695],{"class":5288},[5264,13574,5745],{"class":5698},[5264,13576,5702],{"class":5270},[5264,13578,5725],{"class":5314},[5264,13580,5707],{"class":5270},[5264,13582,5754],{"class":5274},[5264,13584,5733],{"class":5270},[5264,13586,5624],{"class":5292},[5264,13588,5738],{"class":5270},[5264,13590,13591],{"class":5266,"line":5804},[5264,13592,5473],{"emptyLinePlaceholder":5472},[5264,13594,13595],{"class":5266,"line":5809},[5264,13596,13597],{"class":5341},"    \u002F\u002F Логування спроб доступу до заборонених ресурсів\n",[5264,13599,13600,13602,13604,13606,13608,13610,13612,13615],{"class":5266,"line":5815},[5264,13601,7721],{"class":5288},[5264,13603,5707],{"class":5270},[5264,13605,7726],{"class":5314},[5264,13607,5707],{"class":5270},[5264,13609,10212],{"class":5274},[5264,13611,5311],{"class":5270},[5264,13613,13614],{"class":5611},"'Forbidden access attempt'",[5264,13616,7738],{"class":5270},[5264,13618,13619,13622,13624,13626,13628,13630,13632],{"class":5266,"line":5835},[5264,13620,13621],{"class":5314},"      userId:",[5264,13623,5745],{"class":5314},[5264,13625,7316],{"class":5270},[5264,13627,10278],{"class":5611},[5264,13629,10281],{"class":5270},[5264,13631,10284],{"class":5314},[5264,13633,5865],{"class":5270},[5264,13635,13636,13638,13640,13642,13644],{"class":5266,"line":5840},[5264,13637,5914],{"class":5314},[5264,13639,5745],{"class":5314},[5264,13641,5707],{"class":5270},[5264,13643,5921],{"class":5314},[5264,13645,5865],{"class":5270},[5264,13647,13648,13650,13652,13654,13656],{"class":5266,"line":5846},[5264,13649,5929],{"class":5314},[5264,13651,5745],{"class":5314},[5264,13653,5707],{"class":5270},[5264,13655,5936],{"class":5314},[5264,13657,5865],{"class":5270},[5264,13659,13660,13663,13665,13667,13669,13671,13674],{"class":5266,"line":5857},[5264,13661,13662],{"class":5314},"      roles:",[5264,13664,5745],{"class":5314},[5264,13666,7316],{"class":5270},[5264,13668,10278],{"class":5611},[5264,13670,10281],{"class":5270},[5264,13672,13673],{"class":5314},"roles",[5264,13675,5865],{"class":5270},[5264,13677,13678,13680,13682,13684,13686],{"class":5266,"line":5868},[5264,13679,10291],{"class":5314},[5264,13681,5745],{"class":5314},[5264,13683,5707],{"class":5270},[5264,13685,10298],{"class":5314},[5264,13687,5865],{"class":5270},[5264,13689,13690],{"class":5266,"line":5879},[5264,13691,7129],{"class":5270},[5264,13693,13694],{"class":5266,"line":5890},[5264,13695,5473],{"emptyLinePlaceholder":5472},[5264,13697,13698,13700,13702],{"class":5266,"line":5911},[5264,13699,5695],{"class":5288},[5264,13701,5851],{"class":5698},[5264,13703,5854],{"class":5270},[5264,13705,13706,13708,13711],{"class":5266,"line":5926},[5264,13707,5860],{"class":5314},[5264,13709,13710],{"class":6311}," 403",[5264,13712,5865],{"class":5270},[5264,13714,13715,13717,13720],{"class":5266,"line":5941},[5264,13716,5871],{"class":5314},[5264,13718,13719],{"class":5611}," 'Forbidden'",[5264,13721,5865],{"class":5270},[5264,13723,13724,13726,13729],{"class":5266,"line":5963},[5264,13725,5882],{"class":5314},[5264,13727,13728],{"class":5611}," 'You do not have permission to access this resource'",[5264,13730,5865],{"class":5270},[5264,13732,13733,13735,13737,13739,13741,13743],{"class":5266,"line":5969},[5264,13734,5893],{"class":5314},[5264,13736,5896],{"class":5288},[5264,13738,5899],{"class":5274},[5264,13740,5902],{"class":5270},[5264,13742,5905],{"class":5274},[5264,13744,5908],{"class":5270},[5264,13746,13747,13749,13751,13753,13755],{"class":5266,"line":5974},[5264,13748,5914],{"class":5314},[5264,13750,5745],{"class":5314},[5264,13752,5707],{"class":5270},[5264,13754,5921],{"class":5314},[5264,13756,5865],{"class":5270},[5264,13758,13759,13762,13764,13766,13769,13772],{"class":5266,"line":6003},[5264,13760,13761],{"class":5314},"      requiredPermissions:",[5264,13763,7745],{"class":5314},[5264,13765,7316],{"class":5270},[5264,13767,13768],{"class":5611},"'requiredPermissions'",[5264,13770,13771],{"class":5270},"], ",[5264,13773,13774],{"class":5341},"\u002F\u002F З метаданих Guard\n",[5264,13776,13777],{"class":5266,"line":6008},[5264,13778,5966],{"class":5270},[5264,13780,13781],{"class":5266,"line":6013},[5264,13782,5473],{"emptyLinePlaceholder":5472},[5264,13784,13785,13787,13789,13791,13793,13796,13798,13800,13802,13804],{"class":5266,"line":6039},[5264,13786,5977],{"class":5314},[5264,13788,5707],{"class":5270},[5264,13790,5982],{"class":5274},[5264,13792,5311],{"class":5270},[5264,13794,13795],{"class":6311},"403",[5264,13797,5989],{"class":5270},[5264,13799,5992],{"class":5274},[5264,13801,5311],{"class":5270},[5264,13803,5997],{"class":5314},[5264,13805,6000],{"class":5270},[5264,13807,13808],{"class":5266,"line":6062},[5264,13809,5425],{"class":5270},[5264,13811,13812],{"class":5266,"line":6080},[5264,13813,5431],{"class":5270},[5201,13815,13817],{"id":13816},"композиція-exception-filters-комбінування","Композиція exception filters: комбінування",[5206,13819,13820],{},"Реєстрація кількох filters для різних типів помилок:",[5572,13822,13824],{"id":13823},"глобальна-реєстрація-через-модуль","Глобальна реєстрація через модуль",[5254,13826,13828],{"className":5256,"code":13827,"language":5259,"meta":5260,"style":5260},"\u002F\u002F app.module.ts\nimport { Module } from '@nestjs\u002Fcommon';\nimport { APP_FILTER } from '@nestjs\u002Fcore';\nimport {\n  ValidationExceptionFilter,\n  DatabaseExceptionFilter,\n  HttpExceptionFilter,\n  TimeoutExceptionFilter,\n  UnauthorizedExceptionFilter,\n  ForbiddenExceptionFilter,\n  SentryExceptionFilter,\n} from '.\u002Ffilters';\n\n@Module({\n  providers: [\n    \u002F\u002F Специфічні filters (виконуються першими)\n    { provide: APP_FILTER, useClass: ValidationExceptionFilter },\n    { provide: APP_FILTER, useClass: DatabaseExceptionFilter },\n    { provide: APP_FILTER, useClass: TimeoutExceptionFilter },\n    { provide: APP_FILTER, useClass: UnauthorizedExceptionFilter },\n    { provide: APP_FILTER, useClass: ForbiddenExceptionFilter },\n    \n    \u002F\u002F Загальні filters (виконуються останніми)\n    { provide: APP_FILTER, useClass: HttpExceptionFilter },\n    { provide: APP_FILTER, useClass: SentryExceptionFilter }, \u002F\u002F Catch-all\n  ],\n})\nexport class AppModule {}\n",[5102,13829,13830,13834,13850,13866,13872,13879,13886,13893,13900,13907,13914,13921,13933,13937,13945,13951,13956,13972,13988,14004,14020,14036,14040,14045,14061,14081,14085,14089],{"__ignoreMap":5260},[5264,13831,13832],{"class":5266,"line":5267},[5264,13833,10490],{"class":5341},[5264,13835,13836,13838,13840,13842,13844,13846,13848],{"class":5266,"line":5281},[5264,13837,5585],{"class":5284},[5264,13839,5463],{"class":5270},[5264,13841,10499],{"class":5314},[5264,13843,5605],{"class":5270},[5264,13845,5608],{"class":5284},[5264,13847,5612],{"class":5611},[5264,13849,5615],{"class":5270},[5264,13851,13852,13854,13856,13858,13860,13862,13864],{"class":5266,"line":5305},[5264,13853,5585],{"class":5284},[5264,13855,5463],{"class":5270},[5264,13857,10516],{"class":5314},[5264,13859,5605],{"class":5270},[5264,13861,5608],{"class":5284},[5264,13863,10523],{"class":5611},[5264,13865,5615],{"class":5270},[5264,13867,13868,13870],{"class":5266,"line":5338},[5264,13869,5585],{"class":5284},[5264,13871,5302],{"class":5270},[5264,13873,13874,13877],{"class":5266,"line":5345},[5264,13875,13876],{"class":5314},"  ValidationExceptionFilter",[5264,13878,5865],{"class":5270},[5264,13880,13881,13884],{"class":5266,"line":5370},[5264,13882,13883],{"class":5314},"  DatabaseExceptionFilter",[5264,13885,5865],{"class":5270},[5264,13887,13888,13891],{"class":5266,"line":5394},[5264,13889,13890],{"class":5314},"  HttpExceptionFilter",[5264,13892,5865],{"class":5270},[5264,13894,13895,13898],{"class":5266,"line":5416},[5264,13896,13897],{"class":5314},"  TimeoutExceptionFilter",[5264,13899,5865],{"class":5270},[5264,13901,13902,13905],{"class":5266,"line":5422},[5264,13903,13904],{"class":5314},"  UnauthorizedExceptionFilter",[5264,13906,5865],{"class":5270},[5264,13908,13909,13912],{"class":5266,"line":5428},[5264,13910,13911],{"class":5314},"  ForbiddenExceptionFilter",[5264,13913,5865],{"class":5270},[5264,13915,13916,13919],{"class":5266,"line":5781},[5264,13917,13918],{"class":5314},"  SentryExceptionFilter",[5264,13920,5865],{"class":5270},[5264,13922,13923,13926,13928,13931],{"class":5266,"line":5804},[5264,13924,13925],{"class":5270},"} ",[5264,13927,5608],{"class":5284},[5264,13929,13930],{"class":5611}," '.\u002Ffilters'",[5264,13932,5615],{"class":5270},[5264,13934,13935],{"class":5266,"line":5809},[5264,13936,5473],{"emptyLinePlaceholder":5472},[5264,13938,13939,13941,13943],{"class":5266,"line":5815},[5264,13940,5271],{"class":5270},[5264,13942,10499],{"class":5274},[5264,13944,7035],{"class":5270},[5264,13946,13947,13949],{"class":5266,"line":5835},[5264,13948,10542],{"class":5314},[5264,13950,10545],{"class":5270},[5264,13952,13953],{"class":5266,"line":5840},[5264,13954,13955],{"class":5341},"    \u002F\u002F Специфічні filters (виконуються першими)\n",[5264,13957,13958,13960,13962,13964,13966,13968,13970],{"class":5266,"line":5846},[5264,13959,12801],{"class":5270},[5264,13961,12804],{"class":5314},[5264,13963,10557],{"class":5698},[5264,13965,5324],{"class":5270},[5264,13967,12812],{"class":5314},[5264,13969,5460],{"class":5314},[5264,13971,12817],{"class":5270},[5264,13973,13974,13976,13978,13980,13982,13984,13986],{"class":5266,"line":5857},[5264,13975,12801],{"class":5270},[5264,13977,12804],{"class":5314},[5264,13979,10557],{"class":5698},[5264,13981,5324],{"class":5270},[5264,13983,12812],{"class":5314},[5264,13985,5495],{"class":5314},[5264,13987,12817],{"class":5270},[5264,13989,13990,13992,13994,13996,13998,14000,14002],{"class":5266,"line":5868},[5264,13991,12801],{"class":5270},[5264,13993,12804],{"class":5314},[5264,13995,10557],{"class":5698},[5264,13997,5324],{"class":5270},[5264,13999,12812],{"class":5314},[5264,14001,12285],{"class":5314},[5264,14003,12817],{"class":5270},[5264,14005,14006,14008,14010,14012,14014,14016,14018],{"class":5266,"line":5879},[5264,14007,12801],{"class":5270},[5264,14009,12804],{"class":5314},[5264,14011,10557],{"class":5698},[5264,14013,5324],{"class":5270},[5264,14015,12812],{"class":5314},[5264,14017,12940],{"class":5314},[5264,14019,12817],{"class":5270},[5264,14021,14022,14024,14026,14028,14030,14032,14034],{"class":5266,"line":5890},[5264,14023,12801],{"class":5270},[5264,14025,12804],{"class":5314},[5264,14027,10557],{"class":5698},[5264,14029,5324],{"class":5270},[5264,14031,12812],{"class":5314},[5264,14033,13475],{"class":5314},[5264,14035,12817],{"class":5270},[5264,14037,14038],{"class":5266,"line":5911},[5264,14039,8909],{"class":5270},[5264,14041,14042],{"class":5266,"line":5926},[5264,14043,14044],{"class":5341},"    \u002F\u002F Загальні filters (виконуються останніми)\n",[5264,14046,14047,14049,14051,14053,14055,14057,14059],{"class":5266,"line":5941},[5264,14048,12801],{"class":5270},[5264,14050,12804],{"class":5314},[5264,14052,10557],{"class":5698},[5264,14054,5324],{"class":5270},[5264,14056,12812],{"class":5314},[5264,14058,9951],{"class":5314},[5264,14060,12817],{"class":5270},[5264,14062,14063,14065,14067,14069,14071,14073,14075,14078],{"class":5266,"line":5963},[5264,14064,12801],{"class":5270},[5264,14066,12804],{"class":5314},[5264,14068,10557],{"class":5698},[5264,14070,5324],{"class":5270},[5264,14072,12812],{"class":5314},[5264,14074,10939],{"class":5314},[5264,14076,14077],{"class":5270}," }, ",[5264,14079,14080],{"class":5341},"\u002F\u002F Catch-all\n",[5264,14082,14083],{"class":5266,"line":5969},[5264,14084,10577],{"class":5270},[5264,14086,14087],{"class":5266,"line":5974},[5264,14088,10582],{"class":5270},[5264,14090,14091,14093,14095,14097],{"class":5266,"line":6003},[5264,14092,5285],{"class":5284},[5264,14094,5289],{"class":5288},[5264,14096,10591],{"class":5292},[5264,14098,10594],{"class":5270},[5206,14100,14101],{},[5144,14102,14103],{},"Порядок виконання:",[14105,14106,14107,14115,14122,14128,14134,14140,14147],"ol",{},[5095,14108,14109,14111,14112,14114],{},[5144,14110,5104],{}," → перехоплює ",[5102,14113,5448],{}," з помилками валідації",[5095,14116,14117,14111,14119,14121],{},[5144,14118,5111],{},[5102,14120,5484],{}," з TypeORM",[5095,14123,14124,14111,14126],{},[5144,14125,5128],{},[5102,14127,12207],{},[5095,14129,14130,14111,14132],{},[5144,14131,5132],{},[5102,14133,5516],{},[5095,14135,14136,14111,14138],{},[5144,14137,13500],{},[5102,14139,13418],{},[5095,14141,14142,14144,14145],{},[5144,14143,5118],{}," → перехоплює всі інші ",[5102,14146,9868],{},[5095,14148,14149,14111,14151,14154],{},[5144,14150,10845],{},[5144,14152,14153],{},"всі"," необроблені виключення (catch-all)",[5544,14156,14157,14159,14160,14163,14164,14167,14168,14171,14172,5146,14175,14177,14178,5707],{},[5144,14158,9850],{}," якщо filter ",[5144,14161,14162],{},"не відповідає"," типу виключення у ",[5102,14165,14166],{},"@Catch()",", виключення ",[5144,14169,14170],{},"передається"," наступному filter. Тому ",[5144,14173,14174],{},"catch-all filter",[5102,14176,14166],{},") має бути ",[5144,14179,14180],{},"останнім",[5572,14182,14184],{"id":14183},"умовна-реєстрація-залежно-від-середовища","Умовна реєстрація залежно від середовища",[5254,14186,14188],{"className":5256,"code":14187,"language":5259,"meta":5260,"style":5260},"\u002F\u002F filters.provider.ts\nimport { Provider } from '@nestjs\u002Fcommon';\nimport { APP_FILTER } from '@nestjs\u002Fcore';\nimport { DevelopmentExceptionFilter } from '.\u002Fdevelopment-exception.filter';\nimport { ProductionExceptionFilter } from '.\u002Fproduction-exception.filter';\n\nexport const exceptionsFilterProvider: Provider = {\n  provide: APP_FILTER,\n  useClass: process.env.NODE_ENV === 'production'\n    ? ProductionExceptionFilter\n    : DevelopmentExceptionFilter,\n};\n\n\u002F\u002F app.module.ts\n@Module({\n  providers: [exceptionsFilterProvider],\n})\nexport class AppModule {}\n",[5102,14189,14190,14195,14212,14228,14246,14264,14268,14284,14293,14313,14321,14330,14335,14339,14343,14351,14362,14366],{"__ignoreMap":5260},[5264,14191,14192],{"class":5266,"line":5267},[5264,14193,14194],{"class":5341},"\u002F\u002F filters.provider.ts\n",[5264,14196,14197,14199,14201,14204,14206,14208,14210],{"class":5266,"line":5281},[5264,14198,5585],{"class":5284},[5264,14200,5463],{"class":5270},[5264,14202,14203],{"class":5314},"Provider",[5264,14205,5605],{"class":5270},[5264,14207,5608],{"class":5284},[5264,14209,5612],{"class":5611},[5264,14211,5615],{"class":5270},[5264,14213,14214,14216,14218,14220,14222,14224,14226],{"class":5266,"line":5305},[5264,14215,5585],{"class":5284},[5264,14217,5463],{"class":5270},[5264,14219,10516],{"class":5314},[5264,14221,5605],{"class":5270},[5264,14223,5608],{"class":5284},[5264,14225,10523],{"class":5611},[5264,14227,5615],{"class":5270},[5264,14229,14230,14232,14234,14237,14239,14241,14244],{"class":5266,"line":5338},[5264,14231,5585],{"class":5284},[5264,14233,5463],{"class":5270},[5264,14235,14236],{"class":5314},"DevelopmentExceptionFilter",[5264,14238,5605],{"class":5270},[5264,14240,5608],{"class":5284},[5264,14242,14243],{"class":5611}," '.\u002Fdevelopment-exception.filter'",[5264,14245,5615],{"class":5270},[5264,14247,14248,14250,14252,14255,14257,14259,14262],{"class":5266,"line":5345},[5264,14249,5585],{"class":5284},[5264,14251,5463],{"class":5270},[5264,14253,14254],{"class":5314},"ProductionExceptionFilter",[5264,14256,5605],{"class":5270},[5264,14258,5608],{"class":5284},[5264,14260,14261],{"class":5611}," '.\u002Fproduction-exception.filter'",[5264,14263,5615],{"class":5270},[5264,14265,14266],{"class":5266,"line":5370},[5264,14267,5473],{"emptyLinePlaceholder":5472},[5264,14269,14270,14272,14275,14278,14280,14282],{"class":5266,"line":5394},[5264,14271,5285],{"class":5284},[5264,14273,14274],{"class":5288}," const",[5264,14276,14277],{"class":5698}," exceptionsFilterProvider",[5264,14279,5318],{"class":5270},[5264,14281,14203],{"class":5292},[5264,14283,5854],{"class":5270},[5264,14285,14286,14289,14291],{"class":5266,"line":5416},[5264,14287,14288],{"class":5314},"  provide:",[5264,14290,10557],{"class":5698},[5264,14292,5865],{"class":5270},[5264,14294,14295,14298,14300,14302,14304,14306,14308,14310],{"class":5266,"line":5422},[5264,14296,14297],{"class":5314},"  useClass:",[5264,14299,10738],{"class":5314},[5264,14301,5707],{"class":5270},[5264,14303,10405],{"class":5314},[5264,14305,5707],{"class":5270},[5264,14307,10410],{"class":5698},[5264,14309,10138],{"class":5270},[5264,14311,14312],{"class":5611},"'production'\n",[5264,14314,14315,14318],{"class":5266,"line":5428},[5264,14316,14317],{"class":5270},"    ? ",[5264,14319,14320],{"class":5314},"ProductionExceptionFilter\n",[5264,14322,14323,14326,14328],{"class":5266,"line":5781},[5264,14324,14325],{"class":5270},"    : ",[5264,14327,14236],{"class":5314},[5264,14329,5865],{"class":5270},[5264,14331,14332],{"class":5266,"line":5804},[5264,14333,14334],{"class":5270},"};\n",[5264,14336,14337],{"class":5266,"line":5809},[5264,14338,5473],{"emptyLinePlaceholder":5472},[5264,14340,14341],{"class":5266,"line":5815},[5264,14342,10490],{"class":5341},[5264,14344,14345,14347,14349],{"class":5266,"line":5835},[5264,14346,5271],{"class":5270},[5264,14348,10499],{"class":5274},[5264,14350,7035],{"class":5270},[5264,14352,14353,14355,14357,14360],{"class":5266,"line":5840},[5264,14354,10542],{"class":5314},[5264,14356,7198],{"class":5270},[5264,14358,14359],{"class":5314},"exceptionsFilterProvider",[5264,14361,7436],{"class":5270},[5264,14363,14364],{"class":5266,"line":5846},[5264,14365,10582],{"class":5270},[5264,14367,14368,14370,14372,14374],{"class":5266,"line":5857},[5264,14369,5285],{"class":5284},[5264,14371,5289],{"class":5288},[5264,14373,10591],{"class":5292},[5264,14375,10594],{"class":5270},[5201,14377,14379],{"id":14378},"інтеграція-з-datadog-apm-та-логування","Інтеграція з Datadog: APM та логування",[5206,14381,14382],{},"Datadog — це платформа для моніторингу та APM (Application Performance Monitoring):",[5572,14384,14386],{"id":14385},"встановлення-datadog","Встановлення Datadog",[5254,14388,14390],{"className":10608,"code":14389,"language":10610,"meta":5260,"style":5260},"npm install dd-trace\n",[5102,14391,14392],{"__ignoreMap":5260},[5264,14393,14394,14396,14398],{"class":5266,"line":5267},[5264,14395,10617],{"class":5274},[5264,14397,10620],{"class":5611},[5264,14399,14400],{"class":5611}," dd-trace\n",[5572,14402,14404],{"id":14403},"ініціалізація-datadog","Ініціалізація Datadog",[5254,14406,14408],{"className":5256,"code":14407,"language":5259,"meta":5260,"style":5260},"\u002F\u002F tracer.ts\nimport tracer from 'dd-trace';\n\ntracer.init({\n  service: 'nestjs-app',\n  env: process.env.NODE_ENV,\n  logInjection: true,\n});\n\nexport default tracer;\n\n\u002F\u002F main.ts\nimport '.\u002Ftracer'; \u002F\u002F Імпортувати першим рядком\nimport { NestFactory } from '@nestjs\u002Fcore';\nimport { AppModule } from '.\u002Fapp.module';\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule);\n  await app.listen(3000);\n}\nbootstrap();\n",[5102,14409,14410,14415,14429,14433,14444,14454,14471,14481,14486,14490,14501,14505,14509,14521,14537,14553,14557,14567,14589,14605,14609],{"__ignoreMap":5260},[5264,14411,14412],{"class":5266,"line":5267},[5264,14413,14414],{"class":5341},"\u002F\u002F tracer.ts\n",[5264,14416,14417,14419,14422,14424,14427],{"class":5266,"line":5281},[5264,14418,5585],{"class":5284},[5264,14420,14421],{"class":5314}," tracer",[5264,14423,10672],{"class":5284},[5264,14425,14426],{"class":5611}," 'dd-trace'",[5264,14428,5615],{"class":5270},[5264,14430,14431],{"class":5266,"line":5305},[5264,14432,5473],{"emptyLinePlaceholder":5472},[5264,14434,14435,14438,14440,14442],{"class":5266,"line":5338},[5264,14436,14437],{"class":5314},"tracer",[5264,14439,5707],{"class":5270},[5264,14441,10728],{"class":5274},[5264,14443,7035],{"class":5270},[5264,14445,14446,14449,14452],{"class":5266,"line":5345},[5264,14447,14448],{"class":5314},"  service:",[5264,14450,14451],{"class":5611}," 'nestjs-app'",[5264,14453,5865],{"class":5270},[5264,14455,14456,14459,14461,14463,14465,14467,14469],{"class":5266,"line":5370},[5264,14457,14458],{"class":5314},"  env:",[5264,14460,10738],{"class":5314},[5264,14462,5707],{"class":5270},[5264,14464,10405],{"class":5314},[5264,14466,5707],{"class":5270},[5264,14468,10410],{"class":5698},[5264,14470,5865],{"class":5270},[5264,14472,14473,14476,14479],{"class":5266,"line":5394},[5264,14474,14475],{"class":5314},"  logInjection:",[5264,14477,14478],{"class":5288}," true",[5264,14480,5865],{"class":5270},[5264,14482,14483],{"class":5266,"line":5416},[5264,14484,14485],{"class":5270},"});\n",[5264,14487,14488],{"class":5266,"line":5422},[5264,14489,5473],{"emptyLinePlaceholder":5472},[5264,14491,14492,14494,14497,14499],{"class":5266,"line":5428},[5264,14493,5285],{"class":5284},[5264,14495,14496],{"class":5284}," default",[5264,14498,14421],{"class":5314},[5264,14500,5615],{"class":5270},[5264,14502,14503],{"class":5266,"line":5781},[5264,14504,5473],{"emptyLinePlaceholder":5472},[5264,14506,14507],{"class":5266,"line":5804},[5264,14508,10640],{"class":5341},[5264,14510,14511,14513,14516,14518],{"class":5266,"line":5809},[5264,14512,5585],{"class":5284},[5264,14514,14515],{"class":5611}," '.\u002Ftracer'",[5264,14517,8048],{"class":5270},[5264,14519,14520],{"class":5341},"\u002F\u002F Імпортувати першим рядком\n",[5264,14522,14523,14525,14527,14529,14531,14533,14535],{"class":5266,"line":5815},[5264,14524,5585],{"class":5284},[5264,14526,5463],{"class":5270},[5264,14528,10649],{"class":5314},[5264,14530,5605],{"class":5270},[5264,14532,5608],{"class":5284},[5264,14534,10523],{"class":5611},[5264,14536,5615],{"class":5270},[5264,14538,14539,14541,14543,14545,14547,14549,14551],{"class":5266,"line":5835},[5264,14540,5585],{"class":5284},[5264,14542,5463],{"class":5270},[5264,14544,10686],{"class":5314},[5264,14546,5605],{"class":5270},[5264,14548,5608],{"class":5284},[5264,14550,10693],{"class":5611},[5264,14552,5615],{"class":5270},[5264,14554,14555],{"class":5266,"line":5840},[5264,14556,5473],{"emptyLinePlaceholder":5472},[5264,14558,14559,14561,14563,14565],{"class":5266,"line":5846},[5264,14560,10704],{"class":5288},[5264,14562,10707],{"class":5288},[5264,14564,10710],{"class":5274},[5264,14566,10713],{"class":5270},[5264,14568,14569,14571,14573,14575,14577,14579,14581,14583,14585,14587],{"class":5266,"line":5857},[5264,14570,10790],{"class":5288},[5264,14572,10793],{"class":5698},[5264,14574,5702],{"class":5270},[5264,14576,10798],{"class":5284},[5264,14578,10801],{"class":5314},[5264,14580,5707],{"class":5270},[5264,14582,6500],{"class":5274},[5264,14584,5311],{"class":5270},[5264,14586,10686],{"class":5314},[5264,14588,6000],{"class":5270},[5264,14590,14591,14593,14595,14597,14599,14601,14603],{"class":5266,"line":5868},[5264,14592,10816],{"class":5284},[5264,14594,10793],{"class":5314},[5264,14596,5707],{"class":5270},[5264,14598,10823],{"class":5274},[5264,14600,5311],{"class":5270},[5264,14602,10828],{"class":6311},[5264,14604,6000],{"class":5270},[5264,14606,14607],{"class":5266,"line":5879},[5264,14608,5431],{"class":5270},[5264,14610,14611,14613],{"class":5266,"line":5890},[5264,14612,10839],{"class":5274},[5264,14614,5713],{"class":5270},[5572,14616,14618],{"id":14617},"datadogexceptionfilter","DatadogExceptionFilter",[5254,14620,14622],{"className":5256,"code":14621,"language":5259,"meta":5260,"style":5260},"import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus, Logger } from '@nestjs\u002Fcommon';\nimport tracer from 'dd-trace';\nimport { Request, Response } from 'express';\n\n@Catch()\nexport class DatadogExceptionFilter implements ExceptionFilter {\n  private readonly logger = new Logger(DatadogExceptionFilter.name);\n\n  catch(exception: unknown, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse\u003CResponse>();\n    const request = ctx.getRequest\u003CRequest>();\n\n    const status = exception instanceof HttpException\n      ? exception.getStatus()\n      : HttpStatus.INTERNAL_SERVER_ERROR;\n\n    \u002F\u002F Отримання активного span з Datadog APM\n    const span = tracer.scope().active();\n    if (span) {\n      span.setTag('error', true);\n      span.setTag('http.status_code', status);\n      span.setTag('error.message', exception instanceof Error ? exception.message : 'Unknown error');\n      span.setTag('error.type', exception?.constructor?.name || 'UnknownError');\n      \n      if (exception instanceof Error) {\n        span.setTag('error.stack', exception.stack);\n      }\n    }\n\n    \u002F\u002F Логування у Datadog Logs\n    this.logger.error('Exception occurred', {\n      statusCode: status,\n      message: exception instanceof Error ? exception.message : 'Unknown error',\n      stack: exception instanceof Error ? exception.stack : undefined,\n      userId: request['user']?.id,\n      path: request.url,\n      method: request.method,\n      dd: {\n        trace_id: span?.context().toTraceId(),\n        span_id: span?.context().toSpanId(),\n      },\n    });\n\n    \u002F\u002F Формування відповіді\n    response.status(status).json({\n      statusCode: status,\n      message: status >= 500 ? 'Internal server error' : exception['message'],\n      timestamp: new Date().toISOString(),\n      path: request.url,\n    });\n  }\n}\n",[5102,14623,14624,14660,14672,14692,14696,14704,14719,14743,14747,14769,14785,14805,14825,14829,14843,14855,14867,14871,14876,14898,14908,14928,14946,14982,15015,15020,15035,15059,15064,15068,15072,15077,15096,15104,15128,15154,15170,15182,15194,15201,15219,15237,15241,15245,15249,15253,15271,15279,15304,15318,15330,15334,15338],{"__ignoreMap":5260},[5264,14625,14626,14628,14630,14632,14634,14636,14638,14640,14642,14644,14646,14648,14650,14652,14654,14656,14658],{"class":5266,"line":5267},[5264,14627,5585],{"class":5284},[5264,14629,5463],{"class":5270},[5264,14631,5590],{"class":5314},[5264,14633,5324],{"class":5270},[5264,14635,5275],{"class":5314},[5264,14637,5324],{"class":5270},[5264,14639,5332],{"class":5314},[5264,14641,5324],{"class":5270},[5264,14643,9868],{"class":5314},[5264,14645,5324],{"class":5270},[5264,14647,7524],{"class":5314},[5264,14649,5324],{"class":5270},[5264,14651,7529],{"class":5314},[5264,14653,5605],{"class":5270},[5264,14655,5608],{"class":5284},[5264,14657,5612],{"class":5611},[5264,14659,5615],{"class":5270},[5264,14661,14662,14664,14666,14668,14670],{"class":5266,"line":5281},[5264,14663,5585],{"class":5284},[5264,14665,14421],{"class":5314},[5264,14667,10672],{"class":5284},[5264,14669,14426],{"class":5611},[5264,14671,5615],{"class":5270},[5264,14673,14674,14676,14678,14680,14682,14684,14686,14688,14690],{"class":5266,"line":5305},[5264,14675,5585],{"class":5284},[5264,14677,5463],{"class":5270},[5264,14679,5624],{"class":5314},[5264,14681,5324],{"class":5270},[5264,14683,5629],{"class":5314},[5264,14685,5605],{"class":5270},[5264,14687,5608],{"class":5284},[5264,14689,5636],{"class":5611},[5264,14691,5615],{"class":5270},[5264,14693,14694],{"class":5266,"line":5338},[5264,14695,5473],{"emptyLinePlaceholder":5472},[5264,14697,14698,14700,14702],{"class":5266,"line":5345},[5264,14699,5271],{"class":5270},[5264,14701,5275],{"class":5274},[5264,14703,5278],{"class":5270},[5264,14705,14706,14708,14710,14713,14715,14717],{"class":5266,"line":5370},[5264,14707,5285],{"class":5284},[5264,14709,5289],{"class":5288},[5264,14711,14712],{"class":5292}," DatadogExceptionFilter",[5264,14714,5296],{"class":5288},[5264,14716,5299],{"class":5292},[5264,14718,5302],{"class":5270},[5264,14720,14721,14723,14725,14727,14729,14731,14733,14735,14737,14739,14741],{"class":5266,"line":5394},[5264,14722,6016],{"class":5288},[5264,14724,7607],{"class":5288},[5264,14726,7610],{"class":5314},[5264,14728,5702],{"class":5270},[5264,14730,7615],{"class":5288},[5264,14732,7618],{"class":5274},[5264,14734,5311],{"class":5270},[5264,14736,14618],{"class":5314},[5264,14738,5707],{"class":5270},[5264,14740,7627],{"class":5314},[5264,14742,6000],{"class":5270},[5264,14744,14745],{"class":5266,"line":5416},[5264,14746,5473],{"emptyLinePlaceholder":5472},[5264,14748,14749,14751,14753,14755,14757,14759,14761,14763,14765,14767],{"class":5266,"line":5422},[5264,14750,5308],{"class":5274},[5264,14752,5311],{"class":5270},[5264,14754,5315],{"class":5314},[5264,14756,5318],{"class":5270},[5264,14758,5321],{"class":5292},[5264,14760,5324],{"class":5270},[5264,14762,5327],{"class":5314},[5264,14764,5318],{"class":5270},[5264,14766,5332],{"class":5292},[5264,14768,5335],{"class":5270},[5264,14770,14771,14773,14775,14777,14779,14781,14783],{"class":5266,"line":5428},[5264,14772,5695],{"class":5288},[5264,14774,5699],{"class":5698},[5264,14776,5702],{"class":5270},[5264,14778,5327],{"class":5314},[5264,14780,5707],{"class":5270},[5264,14782,5710],{"class":5274},[5264,14784,5713],{"class":5270},[5264,14786,14787,14789,14791,14793,14795,14797,14799,14801,14803],{"class":5266,"line":5781},[5264,14788,5695],{"class":5288},[5264,14790,5720],{"class":5698},[5264,14792,5702],{"class":5270},[5264,14794,5725],{"class":5314},[5264,14796,5707],{"class":5270},[5264,14798,5730],{"class":5274},[5264,14800,5733],{"class":5270},[5264,14802,5629],{"class":5292},[5264,14804,5738],{"class":5270},[5264,14806,14807,14809,14811,14813,14815,14817,14819,14821,14823],{"class":5266,"line":5804},[5264,14808,5695],{"class":5288},[5264,14810,5745],{"class":5698},[5264,14812,5702],{"class":5270},[5264,14814,5725],{"class":5314},[5264,14816,5707],{"class":5270},[5264,14818,5754],{"class":5274},[5264,14820,5733],{"class":5270},[5264,14822,5624],{"class":5292},[5264,14824,5738],{"class":5270},[5264,14826,14827],{"class":5266,"line":5809},[5264,14828,5473],{"emptyLinePlaceholder":5472},[5264,14830,14831,14833,14835,14837,14839,14841],{"class":5266,"line":5815},[5264,14832,5695],{"class":5288},[5264,14834,5767],{"class":5698},[5264,14836,5702],{"class":5270},[5264,14838,5315],{"class":5314},[5264,14840,5355],{"class":5288},[5264,14842,11047],{"class":5292},[5264,14844,14845,14847,14849,14851,14853],{"class":5266,"line":5835},[5264,14846,11052],{"class":5270},[5264,14848,5315],{"class":5314},[5264,14850,5707],{"class":5270},[5264,14852,5776],{"class":5274},[5264,14854,5278],{"class":5270},[5264,14856,14857,14859,14861,14863,14865],{"class":5266,"line":5840},[5264,14858,11065],{"class":5270},[5264,14860,7524],{"class":5314},[5264,14862,5707],{"class":5270},[5264,14864,8394],{"class":5698},[5264,14866,5615],{"class":5270},[5264,14868,14869],{"class":5266,"line":5846},[5264,14870,5473],{"emptyLinePlaceholder":5472},[5264,14872,14873],{"class":5266,"line":5857},[5264,14874,14875],{"class":5341},"    \u002F\u002F Отримання активного span з Datadog APM\n",[5264,14877,14878,14880,14883,14885,14887,14889,14891,14893,14896],{"class":5266,"line":5868},[5264,14879,5695],{"class":5288},[5264,14881,14882],{"class":5698}," span",[5264,14884,5702],{"class":5270},[5264,14886,14437],{"class":5314},[5264,14888,5707],{"class":5270},[5264,14890,11112],{"class":5274},[5264,14892,5902],{"class":5270},[5264,14894,14895],{"class":5274},"active",[5264,14897,5713],{"class":5270},[5264,14899,14900,14902,14904,14906],{"class":5266,"line":5879},[5264,14901,5348],{"class":5284},[5264,14903,5146],{"class":5270},[5264,14905,5264],{"class":5314},[5264,14907,5335],{"class":5270},[5264,14909,14910,14913,14915,14917,14919,14921,14923,14926],{"class":5266,"line":5890},[5264,14911,14912],{"class":5314},"      span",[5264,14914,5707],{"class":5270},[5264,14916,11343],{"class":5274},[5264,14918,5311],{"class":5270},[5264,14920,11431],{"class":5611},[5264,14922,5324],{"class":5270},[5264,14924,14925],{"class":5288},"true",[5264,14927,6000],{"class":5270},[5264,14929,14930,14932,14934,14936,14938,14940,14942,14944],{"class":5266,"line":5911},[5264,14931,14912],{"class":5314},[5264,14933,5707],{"class":5270},[5264,14935,11343],{"class":5274},[5264,14937,5311],{"class":5270},[5264,14939,11348],{"class":5611},[5264,14941,5324],{"class":5270},[5264,14943,5982],{"class":5314},[5264,14945,6000],{"class":5270},[5264,14947,14948,14950,14952,14954,14956,14959,14961,14963,14965,14967,14969,14971,14973,14975,14977,14980],{"class":5266,"line":5926},[5264,14949,14912],{"class":5314},[5264,14951,5707],{"class":5270},[5264,14953,11343],{"class":5274},[5264,14955,5311],{"class":5270},[5264,14957,14958],{"class":5611},"'error.message'",[5264,14960,5324],{"class":5270},[5264,14962,5315],{"class":5314},[5264,14964,5355],{"class":5288},[5264,14966,11461],{"class":5292},[5264,14968,8591],{"class":5270},[5264,14970,5315],{"class":5314},[5264,14972,5707],{"class":5270},[5264,14974,5830],{"class":5314},[5264,14976,11434],{"class":5270},[5264,14978,14979],{"class":5611},"'Unknown error'",[5264,14981,6000],{"class":5270},[5264,14983,14984,14986,14988,14990,14992,14995,14997,14999,15001,15004,15006,15008,15010,15013],{"class":5266,"line":5941},[5264,14985,14912],{"class":5314},[5264,14987,5707],{"class":5270},[5264,14989,11343],{"class":5274},[5264,14991,5311],{"class":5270},[5264,14993,14994],{"class":5611},"'error.type'",[5264,14996,5324],{"class":5270},[5264,14998,5315],{"class":5314},[5264,15000,8532],{"class":5270},[5264,15002,15003],{"class":5314},"constructor",[5264,15005,8532],{"class":5270},[5264,15007,7627],{"class":5314},[5264,15009,10182],{"class":5270},[5264,15011,15012],{"class":5611},"'UnknownError'",[5264,15014,6000],{"class":5270},[5264,15016,15017],{"class":5266,"line":5963},[5264,15018,15019],{"class":5270},"      \n",[5264,15021,15022,15025,15027,15029,15031,15033],{"class":5266,"line":5969},[5264,15023,15024],{"class":5284},"      if",[5264,15026,5146],{"class":5270},[5264,15028,5315],{"class":5314},[5264,15030,5355],{"class":5288},[5264,15032,11461],{"class":5292},[5264,15034,5335],{"class":5270},[5264,15036,15037,15040,15042,15044,15046,15049,15051,15053,15055,15057],{"class":5266,"line":5974},[5264,15038,15039],{"class":5314},"        span",[5264,15041,5707],{"class":5270},[5264,15043,11343],{"class":5274},[5264,15045,5311],{"class":5270},[5264,15047,15048],{"class":5611},"'error.stack'",[5264,15050,5324],{"class":5270},[5264,15052,5315],{"class":5314},[5264,15054,5707],{"class":5270},[5264,15056,10430],{"class":5314},[5264,15058,6000],{"class":5270},[5264,15060,15061],{"class":5266,"line":6003},[5264,15062,15063],{"class":5270},"      }\n",[5264,15065,15066],{"class":5266,"line":6008},[5264,15067,6083],{"class":5270},[5264,15069,15070],{"class":5266,"line":6013},[5264,15071,5473],{"emptyLinePlaceholder":5472},[5264,15073,15074],{"class":5266,"line":6039},[5264,15075,15076],{"class":5341},"    \u002F\u002F Логування у Datadog Logs\n",[5264,15078,15079,15081,15083,15085,15087,15089,15091,15094],{"class":5266,"line":6062},[5264,15080,7721],{"class":5288},[5264,15082,5707],{"class":5270},[5264,15084,7726],{"class":5314},[5264,15086,5707],{"class":5270},[5264,15088,6106],{"class":5274},[5264,15090,5311],{"class":5270},[5264,15092,15093],{"class":5611},"'Exception occurred'",[5264,15095,7738],{"class":5270},[5264,15097,15098,15100,15102],{"class":5266,"line":6080},[5264,15099,5860],{"class":5314},[5264,15101,5767],{"class":5314},[5264,15103,5865],{"class":5270},[5264,15105,15106,15108,15110,15112,15114,15116,15118,15120,15122,15124,15126],{"class":5266,"line":6086},[5264,15107,5882],{"class":5314},[5264,15109,7745],{"class":5314},[5264,15111,5355],{"class":5288},[5264,15113,11461],{"class":5292},[5264,15115,8591],{"class":5270},[5264,15117,5315],{"class":5314},[5264,15119,5707],{"class":5270},[5264,15121,5830],{"class":5314},[5264,15123,11434],{"class":5270},[5264,15125,14979],{"class":5611},[5264,15127,5865],{"class":5270},[5264,15129,15130,15133,15135,15137,15139,15141,15143,15145,15147,15149,15152],{"class":5266,"line":6091},[5264,15131,15132],{"class":5314},"      stack:",[5264,15134,7745],{"class":5314},[5264,15136,5355],{"class":5288},[5264,15138,11461],{"class":5292},[5264,15140,8591],{"class":5270},[5264,15142,5315],{"class":5314},[5264,15144,5707],{"class":5270},[5264,15146,10430],{"class":5314},[5264,15148,11434],{"class":5270},[5264,15150,15151],{"class":5288},"undefined",[5264,15153,5865],{"class":5270},[5264,15155,15156,15158,15160,15162,15164,15166,15168],{"class":5266,"line":6115},[5264,15157,13621],{"class":5314},[5264,15159,5745],{"class":5314},[5264,15161,7316],{"class":5270},[5264,15163,10278],{"class":5611},[5264,15165,10281],{"class":5270},[5264,15167,10284],{"class":5314},[5264,15169,5865],{"class":5270},[5264,15171,15172,15174,15176,15178,15180],{"class":5266,"line":6131},[5264,15173,5914],{"class":5314},[5264,15175,5745],{"class":5314},[5264,15177,5707],{"class":5270},[5264,15179,5921],{"class":5314},[5264,15181,5865],{"class":5270},[5264,15183,15184,15186,15188,15190,15192],{"class":5266,"line":6146},[5264,15185,5929],{"class":5314},[5264,15187,5745],{"class":5314},[5264,15189,5707],{"class":5270},[5264,15191,5936],{"class":5314},[5264,15193,5865],{"class":5270},[5264,15195,15196,15199],{"class":5266,"line":6172},[5264,15197,15198],{"class":5314},"      dd:",[5264,15200,5302],{"class":5270},[5264,15202,15203,15206,15208,15210,15212,15214,15217],{"class":5266,"line":6178},[5264,15204,15205],{"class":5314},"        trace_id:",[5264,15207,14882],{"class":5314},[5264,15209,8532],{"class":5270},[5264,15211,11844],{"class":5274},[5264,15213,5902],{"class":5270},[5264,15215,15216],{"class":5274},"toTraceId",[5264,15218,5908],{"class":5270},[5264,15220,15221,15224,15226,15228,15230,15232,15235],{"class":5266,"line":6183},[5264,15222,15223],{"class":5314},"        span_id:",[5264,15225,14882],{"class":5314},[5264,15227,8532],{"class":5270},[5264,15229,11844],{"class":5274},[5264,15231,5902],{"class":5270},[5264,15233,15234],{"class":5274},"toSpanId",[5264,15236,5908],{"class":5270},[5264,15238,15239],{"class":5266,"line":8036},[5264,15240,12022],{"class":5270},[5264,15242,15243],{"class":5266,"line":8060},[5264,15244,7129],{"class":5270},[5264,15246,15247],{"class":5266,"line":8072},[5264,15248,5473],{"emptyLinePlaceholder":5472},[5264,15250,15251],{"class":5266,"line":8086},[5264,15252,10332],{"class":5341},[5264,15254,15255,15257,15259,15261,15263,15265,15267,15269],{"class":5266,"line":8094},[5264,15256,5977],{"class":5314},[5264,15258,5707],{"class":5270},[5264,15260,5982],{"class":5274},[5264,15262,5311],{"class":5270},[5264,15264,5982],{"class":5314},[5264,15266,5989],{"class":5270},[5264,15268,5992],{"class":5274},[5264,15270,7035],{"class":5270},[5264,15272,15273,15275,15277],{"class":5266,"line":8110},[5264,15274,5860],{"class":5314},[5264,15276,5767],{"class":5314},[5264,15278,5865],{"class":5270},[5264,15280,15281,15283,15285,15287,15289,15291,15293,15295,15297,15299,15302],{"class":5266,"line":8133},[5264,15282,5882],{"class":5314},[5264,15284,5767],{"class":5314},[5264,15286,11093],{"class":5270},[5264,15288,9130],{"class":6311},[5264,15290,8591],{"class":5270},[5264,15292,11577],{"class":5611},[5264,15294,11434],{"class":5270},[5264,15296,5315],{"class":5314},[5264,15298,7316],{"class":5270},[5264,15300,15301],{"class":5611},"'message'",[5264,15303,7436],{"class":5270},[5264,15305,15306,15308,15310,15312,15314,15316],{"class":5266,"line":8139},[5264,15307,5893],{"class":5314},[5264,15309,5896],{"class":5288},[5264,15311,5899],{"class":5274},[5264,15313,5902],{"class":5270},[5264,15315,5905],{"class":5274},[5264,15317,5908],{"class":5270},[5264,15319,15320,15322,15324,15326,15328],{"class":5266,"line":8144},[5264,15321,5914],{"class":5314},[5264,15323,5745],{"class":5314},[5264,15325,5707],{"class":5270},[5264,15327,5921],{"class":5314},[5264,15329,5865],{"class":5270},[5264,15331,15332],{"class":5266,"line":8157},[5264,15333,7129],{"class":5270},[5264,15335,15336],{"class":5266,"line":8164},[5264,15337,5425],{"class":5270},[5264,15339,15340],{"class":5266,"line":8178},[5264,15341,5431],{"class":5270},[7468,15343,15344,15346,15347,15350,15351,15354],{},[5144,15345,7472],{}," Datadog APM автоматично створює ",[5144,15348,15349],{},"traces"," (сліди виконання) для HTTP-запитів. У exception filter додайте тег ",[5102,15352,15353],{},"error: true"," до span, щоб помилкові запити виділялися в інтерфейсі Datadog.",[5201,15356,15358],{"id":15357},"тестування-спеціалізованих-filters","Тестування спеціалізованих filters",[5572,15360,15362],{"id":15361},"unit-тестування-validationexceptionfilter","Unit-тестування ValidationExceptionFilter",[5254,15364,15366],{"className":5256,"code":15365,"language":5259,"meta":5260,"style":5260},"import { BadRequestException } from '@nestjs\u002Fcommon';\nimport { Test } from '@nestjs\u002Ftesting';\nimport { ValidationExceptionFilter } from '.\u002Fvalidation-exception.filter';\n\ndescribe('ValidationExceptionFilter', () => {\n  let filter: ValidationExceptionFilter;\n\n  beforeEach(async () => {\n    const module = await Test.createTestingModule({\n      providers: [ValidationExceptionFilter],\n    }).compile();\n\n    filter = module.get(ValidationExceptionFilter);\n  });\n\n  it('should format validation errors correctly', () => {\n    const exception = new BadRequestException({\n      message: [\n        {\n          property: 'email',\n          value: 'invalid',\n          constraints: { isEmail: 'email must be an email' },\n        },\n        {\n          property: 'age',\n          value: 15,\n          constraints: { min: 'age must not be less than 18' },\n        },\n      ],\n    });\n\n    const mockJson = jest.fn();\n    const mockStatus = jest.fn().mockReturnValue({ json: mockJson });\n    const mockResponse = { status: mockStatus };\n    const mockRequest = { url: '\u002Fusers', method: 'POST' };\n\n    const host = {\n      switchToHttp: () => ({\n        getResponse: () => mockResponse,\n        getRequest: () => mockRequest,\n      }),\n    } as any;\n\n    filter.catch(exception, host);\n\n    expect(mockStatus).toHaveBeenCalledWith(400);\n    expect(mockJson).toHaveBeenCalledWith(\n      expect.objectContaining({\n        statusCode: 400,\n        error: 'Validation Failed',\n        errors: expect.arrayContaining([\n          expect.objectContaining({ field: 'email' }),\n          expect.objectContaining({ field: 'age' }),\n        ]),\n      })\n    );\n  });\n});\n",[5102,15367,15368,15384,15402,15419,15423,15440,15454,15458,15474,15495,15506,15516,15520,15540,15544,15548,15564,15579,15585,15589,15599,15609,15624,15628,15632,15641,15650,15664,15668,15672,15676,15680,15699,15730,15748,15773,15777,15786,15799,15814,15829,15833,15843,15847,15866,15870,15891,15906,15918,15927,15936,15952,15971,15987,15992,15996,16000,16004],{"__ignoreMap":5260},[5264,15369,15370,15372,15374,15376,15378,15380,15382],{"class":5266,"line":5267},[5264,15371,5585],{"class":5284},[5264,15373,5463],{"class":5270},[5264,15375,5448],{"class":5314},[5264,15377,5605],{"class":5270},[5264,15379,5608],{"class":5284},[5264,15381,5612],{"class":5611},[5264,15383,5615],{"class":5270},[5264,15385,15386,15388,15390,15393,15395,15397,15400],{"class":5266,"line":5281},[5264,15387,5585],{"class":5284},[5264,15389,5463],{"class":5270},[5264,15391,15392],{"class":5314},"Test",[5264,15394,5605],{"class":5270},[5264,15396,5608],{"class":5284},[5264,15398,15399],{"class":5611}," '@nestjs\u002Ftesting'",[5264,15401,5615],{"class":5270},[5264,15403,15404,15406,15408,15410,15412,15414,15417],{"class":5266,"line":5305},[5264,15405,5585],{"class":5284},[5264,15407,5463],{"class":5270},[5264,15409,5104],{"class":5314},[5264,15411,5605],{"class":5270},[5264,15413,5608],{"class":5284},[5264,15415,15416],{"class":5611}," '.\u002Fvalidation-exception.filter'",[5264,15418,5615],{"class":5270},[5264,15420,15421],{"class":5266,"line":5338},[5264,15422,5473],{"emptyLinePlaceholder":5472},[5264,15424,15425,15428,15430,15433,15436,15438],{"class":5266,"line":5345},[5264,15426,15427],{"class":5274},"describe",[5264,15429,5311],{"class":5270},[5264,15431,15432],{"class":5611},"'ValidationExceptionFilter'",[5264,15434,15435],{"class":5270},", () ",[5264,15437,12060],{"class":5288},[5264,15439,5302],{"class":5270},[5264,15441,15442,15445,15448,15450,15452],{"class":5266,"line":5370},[5264,15443,15444],{"class":5288},"  let",[5264,15446,15447],{"class":5314}," filter",[5264,15449,5318],{"class":5270},[5264,15451,5104],{"class":5292},[5264,15453,5615],{"class":5270},[5264,15455,15456],{"class":5266,"line":5394},[5264,15457,5473],{"emptyLinePlaceholder":5472},[5264,15459,15460,15463,15465,15467,15470,15472],{"class":5266,"line":5416},[5264,15461,15462],{"class":5274},"  beforeEach",[5264,15464,5311],{"class":5270},[5264,15466,10704],{"class":5288},[5264,15468,15469],{"class":5270}," () ",[5264,15471,12060],{"class":5288},[5264,15473,5302],{"class":5270},[5264,15475,15476,15478,15481,15483,15485,15488,15490,15493],{"class":5266,"line":5422},[5264,15477,5695],{"class":5288},[5264,15479,15480],{"class":5698}," module",[5264,15482,5702],{"class":5270},[5264,15484,10798],{"class":5284},[5264,15486,15487],{"class":5314}," Test",[5264,15489,5707],{"class":5270},[5264,15491,15492],{"class":5274},"createTestingModule",[5264,15494,7035],{"class":5270},[5264,15496,15497,15500,15502,15504],{"class":5266,"line":5428},[5264,15498,15499],{"class":5314},"      providers:",[5264,15501,7198],{"class":5270},[5264,15503,5104],{"class":5314},[5264,15505,7436],{"class":5270},[5264,15507,15508,15511,15514],{"class":5266,"line":5781},[5264,15509,15510],{"class":5270},"    }).",[5264,15512,15513],{"class":5274},"compile",[5264,15515,5713],{"class":5270},[5264,15517,15518],{"class":5266,"line":5804},[5264,15519,5473],{"emptyLinePlaceholder":5472},[5264,15521,15522,15525,15527,15530,15532,15534,15536,15538],{"class":5266,"line":5809},[5264,15523,15524],{"class":5314},"    filter",[5264,15526,5702],{"class":5270},[5264,15528,15529],{"class":5292},"module",[5264,15531,5707],{"class":5270},[5264,15533,10312],{"class":5274},[5264,15535,5311],{"class":5270},[5264,15537,5104],{"class":5314},[5264,15539,6000],{"class":5270},[5264,15541,15542],{"class":5266,"line":5815},[5264,15543,10781],{"class":5270},[5264,15545,15546],{"class":5266,"line":5835},[5264,15547,5473],{"emptyLinePlaceholder":5472},[5264,15549,15550,15553,15555,15558,15560,15562],{"class":5266,"line":5840},[5264,15551,15552],{"class":5274},"  it",[5264,15554,5311],{"class":5270},[5264,15556,15557],{"class":5611},"'should format validation errors correctly'",[5264,15559,15435],{"class":5270},[5264,15561,12060],{"class":5288},[5264,15563,5302],{"class":5270},[5264,15565,15566,15568,15570,15572,15574,15577],{"class":5266,"line":5846},[5264,15567,5695],{"class":5288},[5264,15569,7745],{"class":5698},[5264,15571,5702],{"class":5270},[5264,15573,7615],{"class":5288},[5264,15575,15576],{"class":5274}," BadRequestException",[5264,15578,7035],{"class":5270},[5264,15580,15581,15583],{"class":5266,"line":5857},[5264,15582,5882],{"class":5314},[5264,15584,10545],{"class":5270},[5264,15586,15587],{"class":5266,"line":5868},[5264,15588,13275],{"class":5270},[5264,15590,15591,15594,15597],{"class":5266,"line":5879},[5264,15592,15593],{"class":5314},"          property:",[5264,15595,15596],{"class":5611}," 'email'",[5264,15598,5865],{"class":5270},[5264,15600,15601,15604,15607],{"class":5266,"line":5890},[5264,15602,15603],{"class":5314},"          value:",[5264,15605,15606],{"class":5611}," 'invalid'",[5264,15608,5865],{"class":5270},[5264,15610,15611,15614,15616,15619,15622],{"class":5266,"line":5911},[5264,15612,15613],{"class":5314},"          constraints:",[5264,15615,5463],{"class":5270},[5264,15617,15618],{"class":5314},"isEmail:",[5264,15620,15621],{"class":5611}," 'email must be an email'",[5264,15623,12817],{"class":5270},[5264,15625,15626],{"class":5266,"line":5926},[5264,15627,13309],{"class":5270},[5264,15629,15630],{"class":5266,"line":5941},[5264,15631,13275],{"class":5270},[5264,15633,15634,15636,15639],{"class":5266,"line":5963},[5264,15635,15593],{"class":5314},[5264,15637,15638],{"class":5611}," 'age'",[5264,15640,5865],{"class":5270},[5264,15642,15643,15645,15648],{"class":5266,"line":5969},[5264,15644,15603],{"class":5314},[5264,15646,15647],{"class":6311}," 15",[5264,15649,5865],{"class":5270},[5264,15651,15652,15654,15656,15659,15662],{"class":5266,"line":5974},[5264,15653,15613],{"class":5314},[5264,15655,5463],{"class":5270},[5264,15657,15658],{"class":5314},"min:",[5264,15660,15661],{"class":5611}," 'age must not be less than 18'",[5264,15663,12817],{"class":5270},[5264,15665,15666],{"class":5266,"line":6003},[5264,15667,13309],{"class":5270},[5264,15669,15670],{"class":5266,"line":6008},[5264,15671,13349],{"class":5270},[5264,15673,15674],{"class":5266,"line":6013},[5264,15675,7129],{"class":5270},[5264,15677,15678],{"class":5266,"line":6039},[5264,15679,5473],{"emptyLinePlaceholder":5472},[5264,15681,15682,15684,15687,15689,15692,15694,15697],{"class":5266,"line":6062},[5264,15683,5695],{"class":5288},[5264,15685,15686],{"class":5698}," mockJson",[5264,15688,5702],{"class":5270},[5264,15690,15691],{"class":5314},"jest",[5264,15693,5707],{"class":5270},[5264,15695,15696],{"class":5274},"fn",[5264,15698,5713],{"class":5270},[5264,15700,15701,15703,15706,15708,15710,15712,15714,15716,15719,15722,15725,15727],{"class":5266,"line":6080},[5264,15702,5695],{"class":5288},[5264,15704,15705],{"class":5698}," mockStatus",[5264,15707,5702],{"class":5270},[5264,15709,15691],{"class":5314},[5264,15711,5707],{"class":5270},[5264,15713,15696],{"class":5274},[5264,15715,5902],{"class":5270},[5264,15717,15718],{"class":5274},"mockReturnValue",[5264,15720,15721],{"class":5270},"({ ",[5264,15723,15724],{"class":5314},"json:",[5264,15726,15686],{"class":5314},[5264,15728,15729],{"class":5270}," });\n",[5264,15731,15732,15734,15737,15740,15743,15745],{"class":5266,"line":6086},[5264,15733,5695],{"class":5288},[5264,15735,15736],{"class":5698}," mockResponse",[5264,15738,15739],{"class":5270}," = { ",[5264,15741,15742],{"class":5314},"status:",[5264,15744,15705],{"class":5314},[5264,15746,15747],{"class":5270}," };\n",[5264,15749,15750,15752,15755,15757,15760,15763,15765,15768,15771],{"class":5266,"line":6091},[5264,15751,5695],{"class":5288},[5264,15753,15754],{"class":5698}," mockRequest",[5264,15756,15739],{"class":5270},[5264,15758,15759],{"class":5314},"url:",[5264,15761,15762],{"class":5611}," '\u002Fusers'",[5264,15764,5324],{"class":5270},[5264,15766,15767],{"class":5314},"method:",[5264,15769,15770],{"class":5611}," 'POST'",[5264,15772,15747],{"class":5270},[5264,15774,15775],{"class":5266,"line":6115},[5264,15776,5473],{"emptyLinePlaceholder":5472},[5264,15778,15779,15781,15784],{"class":5266,"line":6131},[5264,15780,5695],{"class":5288},[5264,15782,15783],{"class":5698}," host",[5264,15785,5854],{"class":5270},[5264,15787,15788,15791,15793,15795,15797],{"class":5266,"line":6146},[5264,15789,15790],{"class":5274},"      switchToHttp",[5264,15792,5212],{"class":5314},[5264,15794,15469],{"class":5270},[5264,15796,12060],{"class":5288},[5264,15798,6112],{"class":5270},[5264,15800,15801,15804,15806,15808,15810,15812],{"class":5266,"line":6172},[5264,15802,15803],{"class":5274},"        getResponse",[5264,15805,5212],{"class":5314},[5264,15807,15469],{"class":5270},[5264,15809,12060],{"class":5288},[5264,15811,15736],{"class":5314},[5264,15813,5865],{"class":5270},[5264,15815,15816,15819,15821,15823,15825,15827],{"class":5266,"line":6178},[5264,15817,15818],{"class":5274},"        getRequest",[5264,15820,5212],{"class":5314},[5264,15822,15469],{"class":5270},[5264,15824,12060],{"class":5288},[5264,15826,15754],{"class":5314},[5264,15828,5865],{"class":5270},[5264,15830,15831],{"class":5266,"line":6183},[5264,15832,10437],{"class":5270},[5264,15834,15835,15837,15839,15841],{"class":5266,"line":8036},[5264,15836,10158],{"class":5270},[5264,15838,7302],{"class":5284},[5264,15840,7828],{"class":5292},[5264,15842,5615],{"class":5270},[5264,15844,15845],{"class":5266,"line":8060},[5264,15846,5473],{"emptyLinePlaceholder":5472},[5264,15848,15849,15851,15853,15856,15858,15860,15862,15864],{"class":5266,"line":8072},[5264,15850,15524],{"class":5314},[5264,15852,5707],{"class":5270},[5264,15854,15855],{"class":5274},"catch",[5264,15857,5311],{"class":5270},[5264,15859,5315],{"class":5314},[5264,15861,5324],{"class":5270},[5264,15863,5327],{"class":5314},[5264,15865,6000],{"class":5270},[5264,15867,15868],{"class":5266,"line":8086},[5264,15869,5473],{"emptyLinePlaceholder":5472},[5264,15871,15872,15875,15877,15880,15882,15885,15887,15889],{"class":5266,"line":8094},[5264,15873,15874],{"class":5274},"    expect",[5264,15876,5311],{"class":5270},[5264,15878,15879],{"class":5314},"mockStatus",[5264,15881,5989],{"class":5270},[5264,15883,15884],{"class":5274},"toHaveBeenCalledWith",[5264,15886,5311],{"class":5270},[5264,15888,6627],{"class":6311},[5264,15890,6000],{"class":5270},[5264,15892,15893,15895,15897,15900,15902,15904],{"class":5266,"line":8110},[5264,15894,15874],{"class":5274},[5264,15896,5311],{"class":5270},[5264,15898,15899],{"class":5314},"mockJson",[5264,15901,5989],{"class":5270},[5264,15903,15884],{"class":5274},[5264,15905,8001],{"class":5270},[5264,15907,15908,15911,15913,15916],{"class":5266,"line":8133},[5264,15909,15910],{"class":5314},"      expect",[5264,15912,5707],{"class":5270},[5264,15914,15915],{"class":5274},"objectContaining",[5264,15917,7035],{"class":5270},[5264,15919,15920,15923,15925],{"class":5266,"line":8139},[5264,15921,15922],{"class":5314},"        statusCode:",[5264,15924,7042],{"class":6311},[5264,15926,5865],{"class":5270},[5264,15928,15929,15932,15934],{"class":5266,"line":8144},[5264,15930,15931],{"class":5314},"        error:",[5264,15933,5874],{"class":5611},[5264,15935,5865],{"class":5270},[5264,15937,15938,15941,15944,15946,15949],{"class":5266,"line":8157},[5264,15939,15940],{"class":5314},"        errors:",[5264,15942,15943],{"class":5314}," expect",[5264,15945,5707],{"class":5270},[5264,15947,15948],{"class":5274},"arrayContaining",[5264,15950,15951],{"class":5270},"([\n",[5264,15953,15954,15957,15959,15961,15963,15966,15968],{"class":5266,"line":8164},[5264,15955,15956],{"class":5314},"          expect",[5264,15958,5707],{"class":5270},[5264,15960,15915],{"class":5274},[5264,15962,15721],{"class":5270},[5264,15964,15965],{"class":5314},"field:",[5264,15967,15596],{"class":5611},[5264,15969,15970],{"class":5270}," }),\n",[5264,15972,15973,15975,15977,15979,15981,15983,15985],{"class":5266,"line":8178},[5264,15974,15956],{"class":5314},[5264,15976,5707],{"class":5270},[5264,15978,15915],{"class":5274},[5264,15980,15721],{"class":5270},[5264,15982,15965],{"class":5314},[5264,15984,15638],{"class":5611},[5264,15986,15970],{"class":5270},[5264,15988,15989],{"class":5266,"line":8188},[5264,15990,15991],{"class":5270},"        ]),\n",[5264,15993,15994],{"class":5266,"line":8193},[5264,15995,12131],{"class":5270},[5264,15997,15998],{"class":5266,"line":8198},[5264,15999,12136],{"class":5270},[5264,16001,16002],{"class":5266,"line":8211},[5264,16003,10781],{"class":5270},[5264,16005,16006],{"class":5266,"line":8218},[5264,16007,14485],{"class":5270},[5572,16009,16011],{"id":16010},"unit-тестування-databaseexceptionfilter","Unit-тестування DatabaseExceptionFilter",[5254,16013,16015],{"className":5256,"code":16014,"language":5259,"meta":5260,"style":5260},"import { Test } from '@nestjs\u002Ftesting';\nimport { QueryFailedError } from 'typeorm';\nimport { DatabaseExceptionFilter } from '.\u002Fdatabase-exception.filter';\n\ndescribe('DatabaseExceptionFilter', () => {\n  let filter: DatabaseExceptionFilter;\n\n  beforeEach(async () => {\n    const module = await Test.createTestingModule({\n      providers: [DatabaseExceptionFilter],\n    }).compile();\n\n    filter = module.get(DatabaseExceptionFilter);\n  });\n\n  it('should handle unique constraint violation (23505)', () => {\n    const exception = new QueryFailedError(\n      'INSERT INTO users ...',\n      [],\n      {\n        code: '23505',\n        constraint: 'users_email_key',\n      } as any\n    );\n\n    const mockJson = jest.fn();\n    const mockStatus = jest.fn().mockReturnValue({ json: mockJson });\n    const mockResponse = { status: mockStatus };\n    const mockRequest = { url: '\u002Fusers', method: 'POST' };\n\n    const host = {\n      switchToHttp: () => ({\n        getResponse: () => mockResponse,\n        getRequest: () => mockRequest,\n      }),\n    } as any;\n\n    filter.catch(exception, host);\n\n    expect(mockStatus).toHaveBeenCalledWith(409);\n    expect(mockJson).toHaveBeenCalledWith(\n      expect.objectContaining({\n        statusCode: 409,\n        message: expect.stringContaining('email'),\n      })\n    );\n  });\n\n  it('should handle foreign key violation (23503)', () => {\n    const exception = new QueryFailedError(\n      'INSERT INTO posts ...',\n      [],\n      { code: '23503' } as any\n    );\n\n    const mockJson = jest.fn();\n    const mockStatus = jest.fn().mockReturnValue({ json: mockJson });\n    const mockResponse = { status: mockStatus };\n    const mockRequest = { url: '\u002Fposts', method: 'POST' };\n\n    const host = {\n      switchToHttp: () => ({\n        getResponse: () => mockResponse,\n        getRequest: () => mockRequest,\n      }),\n    } as any;\n\n    filter.catch(exception, host);\n\n    expect(mockStatus).toHaveBeenCalledWith(400);\n    expect(mockJson).toHaveBeenCalledWith(\n      expect.objectContaining({\n        message: 'Referenced record does not exist',\n      })\n    );\n  });\n});\n",[5102,16016,16017,16033,16049,16066,16070,16085,16097,16101,16115,16133,16143,16151,16155,16173,16177,16181,16196,16210,16217,16222,16227,16236,16246,16256,16260,16264,16280,16306,16320,16340,16344,16352,16364,16378,16392,16396,16406,16410,16428,16432,16450,16464,16474,16483,16502,16506,16510,16514,16518,16533,16547,16554,16558,16574,16578,16582,16598,16624,16638,16659,16663,16671,16683,16697,16711,16715,16725,16729,16747,16751,16769,16783,16793,16801,16805,16809,16813],{"__ignoreMap":5260},[5264,16018,16019,16021,16023,16025,16027,16029,16031],{"class":5266,"line":5267},[5264,16020,5585],{"class":5284},[5264,16022,5463],{"class":5270},[5264,16024,15392],{"class":5314},[5264,16026,5605],{"class":5270},[5264,16028,5608],{"class":5284},[5264,16030,15399],{"class":5611},[5264,16032,5615],{"class":5270},[5264,16034,16035,16037,16039,16041,16043,16045,16047],{"class":5266,"line":5281},[5264,16036,5585],{"class":5284},[5264,16038,5463],{"class":5270},[5264,16040,5484],{"class":5314},[5264,16042,5605],{"class":5270},[5264,16044,5608],{"class":5284},[5264,16046,7552],{"class":5611},[5264,16048,5615],{"class":5270},[5264,16050,16051,16053,16055,16057,16059,16061,16064],{"class":5266,"line":5305},[5264,16052,5585],{"class":5284},[5264,16054,5463],{"class":5270},[5264,16056,5111],{"class":5314},[5264,16058,5605],{"class":5270},[5264,16060,5608],{"class":5284},[5264,16062,16063],{"class":5611}," '.\u002Fdatabase-exception.filter'",[5264,16065,5615],{"class":5270},[5264,16067,16068],{"class":5266,"line":5338},[5264,16069,5473],{"emptyLinePlaceholder":5472},[5264,16071,16072,16074,16076,16079,16081,16083],{"class":5266,"line":5345},[5264,16073,15427],{"class":5274},[5264,16075,5311],{"class":5270},[5264,16077,16078],{"class":5611},"'DatabaseExceptionFilter'",[5264,16080,15435],{"class":5270},[5264,16082,12060],{"class":5288},[5264,16084,5302],{"class":5270},[5264,16086,16087,16089,16091,16093,16095],{"class":5266,"line":5370},[5264,16088,15444],{"class":5288},[5264,16090,15447],{"class":5314},[5264,16092,5318],{"class":5270},[5264,16094,5111],{"class":5292},[5264,16096,5615],{"class":5270},[5264,16098,16099],{"class":5266,"line":5394},[5264,16100,5473],{"emptyLinePlaceholder":5472},[5264,16102,16103,16105,16107,16109,16111,16113],{"class":5266,"line":5416},[5264,16104,15462],{"class":5274},[5264,16106,5311],{"class":5270},[5264,16108,10704],{"class":5288},[5264,16110,15469],{"class":5270},[5264,16112,12060],{"class":5288},[5264,16114,5302],{"class":5270},[5264,16116,16117,16119,16121,16123,16125,16127,16129,16131],{"class":5266,"line":5422},[5264,16118,5695],{"class":5288},[5264,16120,15480],{"class":5698},[5264,16122,5702],{"class":5270},[5264,16124,10798],{"class":5284},[5264,16126,15487],{"class":5314},[5264,16128,5707],{"class":5270},[5264,16130,15492],{"class":5274},[5264,16132,7035],{"class":5270},[5264,16134,16135,16137,16139,16141],{"class":5266,"line":5428},[5264,16136,15499],{"class":5314},[5264,16138,7198],{"class":5270},[5264,16140,5111],{"class":5314},[5264,16142,7436],{"class":5270},[5264,16144,16145,16147,16149],{"class":5266,"line":5781},[5264,16146,15510],{"class":5270},[5264,16148,15513],{"class":5274},[5264,16150,5713],{"class":5270},[5264,16152,16153],{"class":5266,"line":5804},[5264,16154,5473],{"emptyLinePlaceholder":5472},[5264,16156,16157,16159,16161,16163,16165,16167,16169,16171],{"class":5266,"line":5809},[5264,16158,15524],{"class":5314},[5264,16160,5702],{"class":5270},[5264,16162,15529],{"class":5292},[5264,16164,5707],{"class":5270},[5264,16166,10312],{"class":5274},[5264,16168,5311],{"class":5270},[5264,16170,5111],{"class":5314},[5264,16172,6000],{"class":5270},[5264,16174,16175],{"class":5266,"line":5815},[5264,16176,10781],{"class":5270},[5264,16178,16179],{"class":5266,"line":5835},[5264,16180,5473],{"emptyLinePlaceholder":5472},[5264,16182,16183,16185,16187,16190,16192,16194],{"class":5266,"line":5840},[5264,16184,15552],{"class":5274},[5264,16186,5311],{"class":5270},[5264,16188,16189],{"class":5611},"'should handle unique constraint violation (23505)'",[5264,16191,15435],{"class":5270},[5264,16193,12060],{"class":5288},[5264,16195,5302],{"class":5270},[5264,16197,16198,16200,16202,16204,16206,16208],{"class":5266,"line":5846},[5264,16199,5695],{"class":5288},[5264,16201,7745],{"class":5698},[5264,16203,5702],{"class":5270},[5264,16205,7615],{"class":5288},[5264,16207,5385],{"class":5274},[5264,16209,8001],{"class":5270},[5264,16211,16212,16215],{"class":5266,"line":5857},[5264,16213,16214],{"class":5611},"      'INSERT INTO users ...'",[5264,16216,5865],{"class":5270},[5264,16218,16219],{"class":5266,"line":5868},[5264,16220,16221],{"class":5270},"      [],\n",[5264,16223,16224],{"class":5266,"line":5879},[5264,16225,16226],{"class":5270},"      {\n",[5264,16228,16229,16232,16234],{"class":5266,"line":5890},[5264,16230,16231],{"class":5314},"        code:",[5264,16233,8078],{"class":5611},[5264,16235,5865],{"class":5270},[5264,16237,16238,16241,16244],{"class":5266,"line":5911},[5264,16239,16240],{"class":5314},"        constraint:",[5264,16242,16243],{"class":5611}," 'users_email_key'",[5264,16245,5865],{"class":5270},[5264,16247,16248,16251,16253],{"class":5266,"line":5926},[5264,16249,16250],{"class":5270},"      } ",[5264,16252,7302],{"class":5284},[5264,16254,16255],{"class":5292}," any\n",[5264,16257,16258],{"class":5266,"line":5941},[5264,16259,12136],{"class":5270},[5264,16261,16262],{"class":5266,"line":5963},[5264,16263,5473],{"emptyLinePlaceholder":5472},[5264,16265,16266,16268,16270,16272,16274,16276,16278],{"class":5266,"line":5969},[5264,16267,5695],{"class":5288},[5264,16269,15686],{"class":5698},[5264,16271,5702],{"class":5270},[5264,16273,15691],{"class":5314},[5264,16275,5707],{"class":5270},[5264,16277,15696],{"class":5274},[5264,16279,5713],{"class":5270},[5264,16281,16282,16284,16286,16288,16290,16292,16294,16296,16298,16300,16302,16304],{"class":5266,"line":5974},[5264,16283,5695],{"class":5288},[5264,16285,15705],{"class":5698},[5264,16287,5702],{"class":5270},[5264,16289,15691],{"class":5314},[5264,16291,5707],{"class":5270},[5264,16293,15696],{"class":5274},[5264,16295,5902],{"class":5270},[5264,16297,15718],{"class":5274},[5264,16299,15721],{"class":5270},[5264,16301,15724],{"class":5314},[5264,16303,15686],{"class":5314},[5264,16305,15729],{"class":5270},[5264,16307,16308,16310,16312,16314,16316,16318],{"class":5266,"line":6003},[5264,16309,5695],{"class":5288},[5264,16311,15736],{"class":5698},[5264,16313,15739],{"class":5270},[5264,16315,15742],{"class":5314},[5264,16317,15705],{"class":5314},[5264,16319,15747],{"class":5270},[5264,16321,16322,16324,16326,16328,16330,16332,16334,16336,16338],{"class":5266,"line":6008},[5264,16323,5695],{"class":5288},[5264,16325,15754],{"class":5698},[5264,16327,15739],{"class":5270},[5264,16329,15759],{"class":5314},[5264,16331,15762],{"class":5611},[5264,16333,5324],{"class":5270},[5264,16335,15767],{"class":5314},[5264,16337,15770],{"class":5611},[5264,16339,15747],{"class":5270},[5264,16341,16342],{"class":5266,"line":6013},[5264,16343,5473],{"emptyLinePlaceholder":5472},[5264,16345,16346,16348,16350],{"class":5266,"line":6039},[5264,16347,5695],{"class":5288},[5264,16349,15783],{"class":5698},[5264,16351,5854],{"class":5270},[5264,16353,16354,16356,16358,16360,16362],{"class":5266,"line":6062},[5264,16355,15790],{"class":5274},[5264,16357,5212],{"class":5314},[5264,16359,15469],{"class":5270},[5264,16361,12060],{"class":5288},[5264,16363,6112],{"class":5270},[5264,16365,16366,16368,16370,16372,16374,16376],{"class":5266,"line":6080},[5264,16367,15803],{"class":5274},[5264,16369,5212],{"class":5314},[5264,16371,15469],{"class":5270},[5264,16373,12060],{"class":5288},[5264,16375,15736],{"class":5314},[5264,16377,5865],{"class":5270},[5264,16379,16380,16382,16384,16386,16388,16390],{"class":5266,"line":6086},[5264,16381,15818],{"class":5274},[5264,16383,5212],{"class":5314},[5264,16385,15469],{"class":5270},[5264,16387,12060],{"class":5288},[5264,16389,15754],{"class":5314},[5264,16391,5865],{"class":5270},[5264,16393,16394],{"class":5266,"line":6091},[5264,16395,10437],{"class":5270},[5264,16397,16398,16400,16402,16404],{"class":5266,"line":6115},[5264,16399,10158],{"class":5270},[5264,16401,7302],{"class":5284},[5264,16403,7828],{"class":5292},[5264,16405,5615],{"class":5270},[5264,16407,16408],{"class":5266,"line":6131},[5264,16409,5473],{"emptyLinePlaceholder":5472},[5264,16411,16412,16414,16416,16418,16420,16422,16424,16426],{"class":5266,"line":6146},[5264,16413,15524],{"class":5314},[5264,16415,5707],{"class":5270},[5264,16417,15855],{"class":5274},[5264,16419,5311],{"class":5270},[5264,16421,5315],{"class":5314},[5264,16423,5324],{"class":5270},[5264,16425,5327],{"class":5314},[5264,16427,6000],{"class":5270},[5264,16429,16430],{"class":5266,"line":6172},[5264,16431,5473],{"emptyLinePlaceholder":5472},[5264,16433,16434,16436,16438,16440,16442,16444,16446,16448],{"class":5266,"line":6178},[5264,16435,15874],{"class":5274},[5264,16437,5311],{"class":5270},[5264,16439,15879],{"class":5314},[5264,16441,5989],{"class":5270},[5264,16443,15884],{"class":5274},[5264,16445,5311],{"class":5270},[5264,16447,9180],{"class":6311},[5264,16449,6000],{"class":5270},[5264,16451,16452,16454,16456,16458,16460,16462],{"class":5266,"line":6183},[5264,16453,15874],{"class":5274},[5264,16455,5311],{"class":5270},[5264,16457,15899],{"class":5314},[5264,16459,5989],{"class":5270},[5264,16461,15884],{"class":5274},[5264,16463,8001],{"class":5270},[5264,16465,16466,16468,16470,16472],{"class":5266,"line":8036},[5264,16467,15910],{"class":5314},[5264,16469,5707],{"class":5270},[5264,16471,15915],{"class":5274},[5264,16473,7035],{"class":5270},[5264,16475,16476,16478,16481],{"class":5266,"line":8060},[5264,16477,15922],{"class":5314},[5264,16479,16480],{"class":6311}," 409",[5264,16482,5865],{"class":5270},[5264,16484,16485,16488,16490,16492,16495,16497,16500],{"class":5266,"line":8072},[5264,16486,16487],{"class":5314},"        message:",[5264,16489,15943],{"class":5314},[5264,16491,5707],{"class":5270},[5264,16493,16494],{"class":5274},"stringContaining",[5264,16496,5311],{"class":5270},[5264,16498,16499],{"class":5611},"'email'",[5264,16501,5960],{"class":5270},[5264,16503,16504],{"class":5266,"line":8086},[5264,16505,12131],{"class":5270},[5264,16507,16508],{"class":5266,"line":8094},[5264,16509,12136],{"class":5270},[5264,16511,16512],{"class":5266,"line":8110},[5264,16513,10781],{"class":5270},[5264,16515,16516],{"class":5266,"line":8133},[5264,16517,5473],{"emptyLinePlaceholder":5472},[5264,16519,16520,16522,16524,16527,16529,16531],{"class":5266,"line":8139},[5264,16521,15552],{"class":5274},[5264,16523,5311],{"class":5270},[5264,16525,16526],{"class":5611},"'should handle foreign key violation (23503)'",[5264,16528,15435],{"class":5270},[5264,16530,12060],{"class":5288},[5264,16532,5302],{"class":5270},[5264,16534,16535,16537,16539,16541,16543,16545],{"class":5266,"line":8144},[5264,16536,5695],{"class":5288},[5264,16538,7745],{"class":5698},[5264,16540,5702],{"class":5270},[5264,16542,7615],{"class":5288},[5264,16544,5385],{"class":5274},[5264,16546,8001],{"class":5270},[5264,16548,16549,16552],{"class":5266,"line":8157},[5264,16550,16551],{"class":5611},"      'INSERT INTO posts ...'",[5264,16553,5865],{"class":5270},[5264,16555,16556],{"class":5266,"line":8164},[5264,16557,16221],{"class":5270},[5264,16559,16560,16563,16566,16568,16570,16572],{"class":5266,"line":8178},[5264,16561,16562],{"class":5270},"      { ",[5264,16564,16565],{"class":5314},"code:",[5264,16567,8149],{"class":5611},[5264,16569,5605],{"class":5270},[5264,16571,7302],{"class":5284},[5264,16573,16255],{"class":5292},[5264,16575,16576],{"class":5266,"line":8188},[5264,16577,12136],{"class":5270},[5264,16579,16580],{"class":5266,"line":8193},[5264,16581,5473],{"emptyLinePlaceholder":5472},[5264,16583,16584,16586,16588,16590,16592,16594,16596],{"class":5266,"line":8198},[5264,16585,5695],{"class":5288},[5264,16587,15686],{"class":5698},[5264,16589,5702],{"class":5270},[5264,16591,15691],{"class":5314},[5264,16593,5707],{"class":5270},[5264,16595,15696],{"class":5274},[5264,16597,5713],{"class":5270},[5264,16599,16600,16602,16604,16606,16608,16610,16612,16614,16616,16618,16620,16622],{"class":5266,"line":8211},[5264,16601,5695],{"class":5288},[5264,16603,15705],{"class":5698},[5264,16605,5702],{"class":5270},[5264,16607,15691],{"class":5314},[5264,16609,5707],{"class":5270},[5264,16611,15696],{"class":5274},[5264,16613,5902],{"class":5270},[5264,16615,15718],{"class":5274},[5264,16617,15721],{"class":5270},[5264,16619,15724],{"class":5314},[5264,16621,15686],{"class":5314},[5264,16623,15729],{"class":5270},[5264,16625,16626,16628,16630,16632,16634,16636],{"class":5266,"line":8218},[5264,16627,5695],{"class":5288},[5264,16629,15736],{"class":5698},[5264,16631,15739],{"class":5270},[5264,16633,15742],{"class":5314},[5264,16635,15705],{"class":5314},[5264,16637,15747],{"class":5270},[5264,16639,16640,16642,16644,16646,16648,16651,16653,16655,16657],{"class":5266,"line":8231},[5264,16641,5695],{"class":5288},[5264,16643,15754],{"class":5698},[5264,16645,15739],{"class":5270},[5264,16647,15759],{"class":5314},[5264,16649,16650],{"class":5611}," '\u002Fposts'",[5264,16652,5324],{"class":5270},[5264,16654,15767],{"class":5314},[5264,16656,15770],{"class":5611},[5264,16658,15747],{"class":5270},[5264,16660,16661],{"class":5266,"line":8249},[5264,16662,5473],{"emptyLinePlaceholder":5472},[5264,16664,16665,16667,16669],{"class":5266,"line":8254},[5264,16666,5695],{"class":5288},[5264,16668,15783],{"class":5698},[5264,16670,5854],{"class":5270},[5264,16672,16673,16675,16677,16679,16681],{"class":5266,"line":8259},[5264,16674,15790],{"class":5274},[5264,16676,5212],{"class":5314},[5264,16678,15469],{"class":5270},[5264,16680,12060],{"class":5288},[5264,16682,6112],{"class":5270},[5264,16684,16685,16687,16689,16691,16693,16695],{"class":5266,"line":8272},[5264,16686,15803],{"class":5274},[5264,16688,5212],{"class":5314},[5264,16690,15469],{"class":5270},[5264,16692,12060],{"class":5288},[5264,16694,15736],{"class":5314},[5264,16696,5865],{"class":5270},[5264,16698,16699,16701,16703,16705,16707,16709],{"class":5266,"line":8279},[5264,16700,15818],{"class":5274},[5264,16702,5212],{"class":5314},[5264,16704,15469],{"class":5270},[5264,16706,12060],{"class":5288},[5264,16708,15754],{"class":5314},[5264,16710,5865],{"class":5270},[5264,16712,16713],{"class":5266,"line":8292},[5264,16714,10437],{"class":5270},[5264,16716,16717,16719,16721,16723],{"class":5266,"line":8302},[5264,16718,10158],{"class":5270},[5264,16720,7302],{"class":5284},[5264,16722,7828],{"class":5292},[5264,16724,5615],{"class":5270},[5264,16726,16727],{"class":5266,"line":8307},[5264,16728,5473],{"emptyLinePlaceholder":5472},[5264,16730,16731,16733,16735,16737,16739,16741,16743,16745],{"class":5266,"line":8312},[5264,16732,15524],{"class":5314},[5264,16734,5707],{"class":5270},[5264,16736,15855],{"class":5274},[5264,16738,5311],{"class":5270},[5264,16740,5315],{"class":5314},[5264,16742,5324],{"class":5270},[5264,16744,5327],{"class":5314},[5264,16746,6000],{"class":5270},[5264,16748,16749],{"class":5266,"line":8325},[5264,16750,5473],{"emptyLinePlaceholder":5472},[5264,16752,16753,16755,16757,16759,16761,16763,16765,16767],{"class":5266,"line":8332},[5264,16754,15874],{"class":5274},[5264,16756,5311],{"class":5270},[5264,16758,15879],{"class":5314},[5264,16760,5989],{"class":5270},[5264,16762,15884],{"class":5274},[5264,16764,5311],{"class":5270},[5264,16766,6627],{"class":6311},[5264,16768,6000],{"class":5270},[5264,16770,16771,16773,16775,16777,16779,16781],{"class":5266,"line":8345},[5264,16772,15874],{"class":5274},[5264,16774,5311],{"class":5270},[5264,16776,15899],{"class":5314},[5264,16778,5989],{"class":5270},[5264,16780,15884],{"class":5274},[5264,16782,8001],{"class":5270},[5264,16784,16785,16787,16789,16791],{"class":5266,"line":8355},[5264,16786,15910],{"class":5314},[5264,16788,5707],{"class":5270},[5264,16790,15915],{"class":5274},[5264,16792,7035],{"class":5270},[5264,16794,16795,16797,16799],{"class":5266,"line":8360},[5264,16796,16487],{"class":5314},[5264,16798,8183],{"class":5611},[5264,16800,5865],{"class":5270},[5264,16802,16803],{"class":5266,"line":8365},[5264,16804,12131],{"class":5270},[5264,16806,16807],{"class":5266,"line":8378},[5264,16808,12136],{"class":5270},[5264,16810,16811],{"class":5266,"line":8385},[5264,16812,10781],{"class":5270},[5264,16814,16815],{"class":5266,"line":8399},[5264,16816,14485],{"class":5270},[5572,16818,16820],{"id":16819},"e2e-тестування-з-композицією-filters","E2E-тестування з композицією filters",[5254,16822,16824],{"className":5256,"code":16823,"language":5259,"meta":5260,"style":5260},"import { Test, TestingModule } from '@nestjs\u002Ftesting';\nimport { INestApplication, HttpStatus } from '@nestjs\u002Fcommon';\nimport * as request from 'supertest';\nimport { AppModule } from '.\u002F..\u002Fsrc\u002Fapp.module';\n\ndescribe('Exception Filters Composition (e2e)', () => {\n  let app: INestApplication;\n\n  beforeAll(async () => {\n    const moduleFixture: TestingModule = await Test.createTestingModule({\n      imports: [AppModule],\n    }).compile();\n\n    app = moduleFixture.createNestApplication();\n    await app.init();\n  });\n\n  afterAll(async () => {\n    await app.close();\n  });\n\n  it('ValidationExceptionFilter should handle validation errors', () => {\n    return request(app.getHttpServer())\n      .post('\u002Fusers')\n      .send({ email: 'invalid', age: 15 })\n      .expect(HttpStatus.BAD_REQUEST)\n      .expect(res => {\n        expect(res.body.error).toBe('Validation Failed');\n        expect(res.body.errors).toHaveLength(2);\n      });\n  });\n\n  it('DatabaseExceptionFilter should handle duplicate email', async () => {\n    \u002F\u002F Створення користувача\n    await request(app.getHttpServer())\n      .post('\u002Fusers')\n      .send({ email: 'test@example.com', password: '12345678', age: 25 });\n\n    \u002F\u002F Спроба дублікату\n    return request(app.getHttpServer())\n      .post('\u002Fusers')\n      .send({ email: 'test@example.com', password: '12345678', age: 25 })\n      .expect(HttpStatus.CONFLICT)\n      .expect(res => {\n        expect(res.body.message).toContain('email');\n      });\n  });\n\n  it('UnauthorizedExceptionFilter should handle missing token', () => {\n    return request(app.getHttpServer())\n      .get('\u002Fprofile')\n      .expect(HttpStatus.UNAUTHORIZED)\n      .expect(res => {\n        expect(res.body.error).toBe('Unauthorized');\n        expect(res.headers['www-authenticate']).toBeDefined();\n      });\n  });\n\n  it('HttpExceptionFilter should handle 404', () => {\n    return request(app.getHttpServer())\n      .get('\u002Fusers\u002F999')\n      .expect(HttpStatus.NOT_FOUND)\n      .expect(res => {\n        expect(res.body.statusCode).toBe(404);\n        expect(res.body.timestamp).toBeDefined();\n      });\n  });\n});\n",[5102,16825,16826,16847,16868,16885,16902,16906,16921,16933,16937,16952,16975,16986,16994,16998,17015,17028,17032,17036,17051,17064,17068,17072,17087,17105,17120,17143,17160,17175,17204,17231,17235,17239,17243,17262,17267,17283,17295,17325,17329,17334,17350,17362,17388,17404,17418,17445,17449,17453,17457,17472,17488,17501,17518,17532,17559,17584,17588,17592,17596,17611,17627,17640,17656,17670,17697,17720,17724,17728],{"__ignoreMap":5260},[5264,16827,16828,16830,16832,16834,16836,16839,16841,16843,16845],{"class":5266,"line":5267},[5264,16829,5585],{"class":5284},[5264,16831,5463],{"class":5270},[5264,16833,15392],{"class":5314},[5264,16835,5324],{"class":5270},[5264,16837,16838],{"class":5314},"TestingModule",[5264,16840,5605],{"class":5270},[5264,16842,5608],{"class":5284},[5264,16844,15399],{"class":5611},[5264,16846,5615],{"class":5270},[5264,16848,16849,16851,16853,16856,16858,16860,16862,16864,16866],{"class":5266,"line":5281},[5264,16850,5585],{"class":5284},[5264,16852,5463],{"class":5270},[5264,16854,16855],{"class":5314},"INestApplication",[5264,16857,5324],{"class":5270},[5264,16859,7524],{"class":5314},[5264,16861,5605],{"class":5270},[5264,16863,5608],{"class":5284},[5264,16865,5612],{"class":5611},[5264,16867,5615],{"class":5270},[5264,16869,16870,16872,16874,16876,16878,16880,16883],{"class":5266,"line":5305},[5264,16871,5585],{"class":5284},[5264,16873,10664],{"class":5288},[5264,16875,7825],{"class":5284},[5264,16877,5745],{"class":5314},[5264,16879,10672],{"class":5284},[5264,16881,16882],{"class":5611}," 'supertest'",[5264,16884,5615],{"class":5270},[5264,16886,16887,16889,16891,16893,16895,16897,16900],{"class":5266,"line":5338},[5264,16888,5585],{"class":5284},[5264,16890,5463],{"class":5270},[5264,16892,10686],{"class":5314},[5264,16894,5605],{"class":5270},[5264,16896,5608],{"class":5284},[5264,16898,16899],{"class":5611}," '.\u002F..\u002Fsrc\u002Fapp.module'",[5264,16901,5615],{"class":5270},[5264,16903,16904],{"class":5266,"line":5345},[5264,16905,5473],{"emptyLinePlaceholder":5472},[5264,16907,16908,16910,16912,16915,16917,16919],{"class":5266,"line":5370},[5264,16909,15427],{"class":5274},[5264,16911,5311],{"class":5270},[5264,16913,16914],{"class":5611},"'Exception Filters Composition (e2e)'",[5264,16916,15435],{"class":5270},[5264,16918,12060],{"class":5288},[5264,16920,5302],{"class":5270},[5264,16922,16923,16925,16927,16929,16931],{"class":5266,"line":5394},[5264,16924,15444],{"class":5288},[5264,16926,10793],{"class":5314},[5264,16928,5318],{"class":5270},[5264,16930,16855],{"class":5292},[5264,16932,5615],{"class":5270},[5264,16934,16935],{"class":5266,"line":5416},[5264,16936,5473],{"emptyLinePlaceholder":5472},[5264,16938,16939,16942,16944,16946,16948,16950],{"class":5266,"line":5422},[5264,16940,16941],{"class":5274},"  beforeAll",[5264,16943,5311],{"class":5270},[5264,16945,10704],{"class":5288},[5264,16947,15469],{"class":5270},[5264,16949,12060],{"class":5288},[5264,16951,5302],{"class":5270},[5264,16953,16954,16956,16959,16961,16963,16965,16967,16969,16971,16973],{"class":5266,"line":5428},[5264,16955,5695],{"class":5288},[5264,16957,16958],{"class":5698}," moduleFixture",[5264,16960,5318],{"class":5270},[5264,16962,16838],{"class":5292},[5264,16964,5702],{"class":5270},[5264,16966,10798],{"class":5284},[5264,16968,15487],{"class":5314},[5264,16970,5707],{"class":5270},[5264,16972,15492],{"class":5274},[5264,16974,7035],{"class":5270},[5264,16976,16977,16980,16982,16984],{"class":5266,"line":5781},[5264,16978,16979],{"class":5314},"      imports:",[5264,16981,7198],{"class":5270},[5264,16983,10686],{"class":5314},[5264,16985,7436],{"class":5270},[5264,16987,16988,16990,16992],{"class":5266,"line":5804},[5264,16989,15510],{"class":5270},[5264,16991,15513],{"class":5274},[5264,16993,5713],{"class":5270},[5264,16995,16996],{"class":5266,"line":5809},[5264,16997,5473],{"emptyLinePlaceholder":5472},[5264,16999,17000,17003,17005,17008,17010,17013],{"class":5266,"line":5815},[5264,17001,17002],{"class":5314},"    app",[5264,17004,5702],{"class":5270},[5264,17006,17007],{"class":5314},"moduleFixture",[5264,17009,5707],{"class":5270},[5264,17011,17012],{"class":5274},"createNestApplication",[5264,17014,5713],{"class":5270},[5264,17016,17017,17020,17022,17024,17026],{"class":5266,"line":5835},[5264,17018,17019],{"class":5284},"    await",[5264,17021,10793],{"class":5314},[5264,17023,5707],{"class":5270},[5264,17025,10728],{"class":5274},[5264,17027,5713],{"class":5270},[5264,17029,17030],{"class":5266,"line":5840},[5264,17031,10781],{"class":5270},[5264,17033,17034],{"class":5266,"line":5846},[5264,17035,5473],{"emptyLinePlaceholder":5472},[5264,17037,17038,17041,17043,17045,17047,17049],{"class":5266,"line":5857},[5264,17039,17040],{"class":5274},"  afterAll",[5264,17042,5311],{"class":5270},[5264,17044,10704],{"class":5288},[5264,17046,15469],{"class":5270},[5264,17048,12060],{"class":5288},[5264,17050,5302],{"class":5270},[5264,17052,17053,17055,17057,17059,17062],{"class":5266,"line":5868},[5264,17054,17019],{"class":5284},[5264,17056,10793],{"class":5314},[5264,17058,5707],{"class":5270},[5264,17060,17061],{"class":5274},"close",[5264,17063,5713],{"class":5270},[5264,17065,17066],{"class":5266,"line":5879},[5264,17067,10781],{"class":5270},[5264,17069,17070],{"class":5266,"line":5890},[5264,17071,5473],{"emptyLinePlaceholder":5472},[5264,17073,17074,17076,17078,17081,17083,17085],{"class":5266,"line":5911},[5264,17075,15552],{"class":5274},[5264,17077,5311],{"class":5270},[5264,17079,17080],{"class":5611},"'ValidationExceptionFilter should handle validation errors'",[5264,17082,15435],{"class":5270},[5264,17084,12060],{"class":5288},[5264,17086,5302],{"class":5270},[5264,17088,17089,17091,17093,17095,17097,17099,17102],{"class":5266,"line":5926},[5264,17090,6094],{"class":5284},[5264,17092,5745],{"class":5274},[5264,17094,5311],{"class":5270},[5264,17096,11686],{"class":5314},[5264,17098,5707],{"class":5270},[5264,17100,17101],{"class":5274},"getHttpServer",[5264,17103,17104],{"class":5270},"())\n",[5264,17106,17107,17110,17113,17115,17118],{"class":5266,"line":5941},[5264,17108,17109],{"class":5270},"      .",[5264,17111,17112],{"class":5274},"post",[5264,17114,5311],{"class":5270},[5264,17116,17117],{"class":5611},"'\u002Fusers'",[5264,17119,5451],{"class":5270},[5264,17121,17122,17124,17127,17129,17132,17134,17136,17139,17141],{"class":5266,"line":5963},[5264,17123,17109],{"class":5270},[5264,17125,17126],{"class":5274},"send",[5264,17128,15721],{"class":5270},[5264,17130,17131],{"class":5314},"email:",[5264,17133,15606],{"class":5611},[5264,17135,5324],{"class":5270},[5264,17137,17138],{"class":5314},"age:",[5264,17140,15647],{"class":6311},[5264,17142,6276],{"class":5270},[5264,17144,17145,17147,17150,17152,17154,17156,17158],{"class":5266,"line":5969},[5264,17146,17109],{"class":5270},[5264,17148,17149],{"class":5274},"expect",[5264,17151,5311],{"class":5270},[5264,17153,7524],{"class":5314},[5264,17155,5707],{"class":5270},[5264,17157,8173],{"class":5698},[5264,17159,5451],{"class":5270},[5264,17161,17162,17164,17166,17168,17171,17173],{"class":5266,"line":5974},[5264,17163,17109],{"class":5270},[5264,17165,17149],{"class":5274},[5264,17167,5311],{"class":5270},[5264,17169,17170],{"class":5314},"res",[5264,17172,6109],{"class":5288},[5264,17174,5302],{"class":5270},[5264,17176,17177,17180,17182,17184,17186,17188,17190,17192,17194,17197,17199,17202],{"class":5266,"line":6003},[5264,17178,17179],{"class":5274},"        expect",[5264,17181,5311],{"class":5270},[5264,17183,17170],{"class":5314},[5264,17185,5707],{"class":5270},[5264,17187,11190],{"class":5314},[5264,17189,5707],{"class":5270},[5264,17191,6106],{"class":5314},[5264,17193,5989],{"class":5270},[5264,17195,17196],{"class":5274},"toBe",[5264,17198,5311],{"class":5270},[5264,17200,17201],{"class":5611},"'Validation Failed'",[5264,17203,6000],{"class":5270},[5264,17205,17206,17208,17210,17212,17214,17216,17218,17220,17222,17225,17227,17229],{"class":5266,"line":6008},[5264,17207,17179],{"class":5274},[5264,17209,5311],{"class":5270},[5264,17211,17170],{"class":5314},[5264,17213,5707],{"class":5270},[5264,17215,11190],{"class":5314},[5264,17217,5707],{"class":5270},[5264,17219,6024],{"class":5314},[5264,17221,5989],{"class":5270},[5264,17223,17224],{"class":5274},"toHaveLength",[5264,17226,5311],{"class":5270},[5264,17228,8598],{"class":6311},[5264,17230,6000],{"class":5270},[5264,17232,17233],{"class":5266,"line":6013},[5264,17234,11533],{"class":5270},[5264,17236,17237],{"class":5266,"line":6039},[5264,17238,10781],{"class":5270},[5264,17240,17241],{"class":5266,"line":6062},[5264,17242,5473],{"emptyLinePlaceholder":5472},[5264,17244,17245,17247,17249,17252,17254,17256,17258,17260],{"class":5266,"line":6080},[5264,17246,15552],{"class":5274},[5264,17248,5311],{"class":5270},[5264,17250,17251],{"class":5611},"'DatabaseExceptionFilter should handle duplicate email'",[5264,17253,5324],{"class":5270},[5264,17255,10704],{"class":5288},[5264,17257,15469],{"class":5270},[5264,17259,12060],{"class":5288},[5264,17261,5302],{"class":5270},[5264,17263,17264],{"class":5266,"line":6086},[5264,17265,17266],{"class":5341},"    \u002F\u002F Створення користувача\n",[5264,17268,17269,17271,17273,17275,17277,17279,17281],{"class":5266,"line":6091},[5264,17270,17019],{"class":5284},[5264,17272,5745],{"class":5274},[5264,17274,5311],{"class":5270},[5264,17276,11686],{"class":5314},[5264,17278,5707],{"class":5270},[5264,17280,17101],{"class":5274},[5264,17282,17104],{"class":5270},[5264,17284,17285,17287,17289,17291,17293],{"class":5266,"line":6115},[5264,17286,17109],{"class":5270},[5264,17288,17112],{"class":5274},[5264,17290,5311],{"class":5270},[5264,17292,17117],{"class":5611},[5264,17294,5451],{"class":5270},[5264,17296,17297,17299,17301,17303,17305,17308,17310,17313,17316,17318,17320,17323],{"class":5266,"line":6131},[5264,17298,17109],{"class":5270},[5264,17300,17126],{"class":5274},[5264,17302,15721],{"class":5270},[5264,17304,17131],{"class":5314},[5264,17306,17307],{"class":5611}," 'test@example.com'",[5264,17309,5324],{"class":5270},[5264,17311,17312],{"class":5314},"password:",[5264,17314,17315],{"class":5611}," '12345678'",[5264,17317,5324],{"class":5270},[5264,17319,17138],{"class":5314},[5264,17321,17322],{"class":6311}," 25",[5264,17324,15729],{"class":5270},[5264,17326,17327],{"class":5266,"line":6146},[5264,17328,5473],{"emptyLinePlaceholder":5472},[5264,17330,17331],{"class":5266,"line":6172},[5264,17332,17333],{"class":5341},"    \u002F\u002F Спроба дублікату\n",[5264,17335,17336,17338,17340,17342,17344,17346,17348],{"class":5266,"line":6178},[5264,17337,6094],{"class":5284},[5264,17339,5745],{"class":5274},[5264,17341,5311],{"class":5270},[5264,17343,11686],{"class":5314},[5264,17345,5707],{"class":5270},[5264,17347,17101],{"class":5274},[5264,17349,17104],{"class":5270},[5264,17351,17352,17354,17356,17358,17360],{"class":5266,"line":6183},[5264,17353,17109],{"class":5270},[5264,17355,17112],{"class":5274},[5264,17357,5311],{"class":5270},[5264,17359,17117],{"class":5611},[5264,17361,5451],{"class":5270},[5264,17363,17364,17366,17368,17370,17372,17374,17376,17378,17380,17382,17384,17386],{"class":5266,"line":8036},[5264,17365,17109],{"class":5270},[5264,17367,17126],{"class":5274},[5264,17369,15721],{"class":5270},[5264,17371,17131],{"class":5314},[5264,17373,17307],{"class":5611},[5264,17375,5324],{"class":5270},[5264,17377,17312],{"class":5314},[5264,17379,17315],{"class":5611},[5264,17381,5324],{"class":5270},[5264,17383,17138],{"class":5314},[5264,17385,17322],{"class":6311},[5264,17387,6276],{"class":5270},[5264,17389,17390,17392,17394,17396,17398,17400,17402],{"class":5266,"line":8060},[5264,17391,17109],{"class":5270},[5264,17393,17149],{"class":5274},[5264,17395,5311],{"class":5270},[5264,17397,7524],{"class":5314},[5264,17399,5707],{"class":5270},[5264,17401,8105],{"class":5698},[5264,17403,5451],{"class":5270},[5264,17405,17406,17408,17410,17412,17414,17416],{"class":5266,"line":8072},[5264,17407,17109],{"class":5270},[5264,17409,17149],{"class":5274},[5264,17411,5311],{"class":5270},[5264,17413,17170],{"class":5314},[5264,17415,6109],{"class":5288},[5264,17417,5302],{"class":5270},[5264,17419,17420,17422,17424,17426,17428,17430,17432,17434,17436,17439,17441,17443],{"class":5266,"line":8086},[5264,17421,17179],{"class":5274},[5264,17423,5311],{"class":5270},[5264,17425,17170],{"class":5314},[5264,17427,5707],{"class":5270},[5264,17429,11190],{"class":5314},[5264,17431,5707],{"class":5270},[5264,17433,5830],{"class":5314},[5264,17435,5989],{"class":5270},[5264,17437,17438],{"class":5274},"toContain",[5264,17440,5311],{"class":5270},[5264,17442,16499],{"class":5611},[5264,17444,6000],{"class":5270},[5264,17446,17447],{"class":5266,"line":8094},[5264,17448,11533],{"class":5270},[5264,17450,17451],{"class":5266,"line":8110},[5264,17452,10781],{"class":5270},[5264,17454,17455],{"class":5266,"line":8133},[5264,17456,5473],{"emptyLinePlaceholder":5472},[5264,17458,17459,17461,17463,17466,17468,17470],{"class":5266,"line":8139},[5264,17460,15552],{"class":5274},[5264,17462,5311],{"class":5270},[5264,17464,17465],{"class":5611},"'UnauthorizedExceptionFilter should handle missing token'",[5264,17467,15435],{"class":5270},[5264,17469,12060],{"class":5288},[5264,17471,5302],{"class":5270},[5264,17473,17474,17476,17478,17480,17482,17484,17486],{"class":5266,"line":8144},[5264,17475,6094],{"class":5284},[5264,17477,5745],{"class":5274},[5264,17479,5311],{"class":5270},[5264,17481,11686],{"class":5314},[5264,17483,5707],{"class":5270},[5264,17485,17101],{"class":5274},[5264,17487,17104],{"class":5270},[5264,17489,17490,17492,17494,17496,17499],{"class":5266,"line":8157},[5264,17491,17109],{"class":5270},[5264,17493,10312],{"class":5274},[5264,17495,5311],{"class":5270},[5264,17497,17498],{"class":5611},"'\u002Fprofile'",[5264,17500,5451],{"class":5270},[5264,17502,17503,17505,17507,17509,17511,17513,17516],{"class":5266,"line":8164},[5264,17504,17109],{"class":5270},[5264,17506,17149],{"class":5274},[5264,17508,5311],{"class":5270},[5264,17510,7524],{"class":5314},[5264,17512,5707],{"class":5270},[5264,17514,17515],{"class":5698},"UNAUTHORIZED",[5264,17517,5451],{"class":5270},[5264,17519,17520,17522,17524,17526,17528,17530],{"class":5266,"line":8178},[5264,17521,17109],{"class":5270},[5264,17523,17149],{"class":5274},[5264,17525,5311],{"class":5270},[5264,17527,17170],{"class":5314},[5264,17529,6109],{"class":5288},[5264,17531,5302],{"class":5270},[5264,17533,17534,17536,17538,17540,17542,17544,17546,17548,17550,17552,17554,17557],{"class":5266,"line":8188},[5264,17535,17179],{"class":5274},[5264,17537,5311],{"class":5270},[5264,17539,17170],{"class":5314},[5264,17541,5707],{"class":5270},[5264,17543,11190],{"class":5314},[5264,17545,5707],{"class":5270},[5264,17547,6106],{"class":5314},[5264,17549,5989],{"class":5270},[5264,17551,17196],{"class":5274},[5264,17553,5311],{"class":5270},[5264,17555,17556],{"class":5611},"'Unauthorized'",[5264,17558,6000],{"class":5270},[5264,17560,17561,17563,17565,17567,17569,17571,17573,17576,17579,17582],{"class":5266,"line":8193},[5264,17562,17179],{"class":5274},[5264,17564,5311],{"class":5270},[5264,17566,17170],{"class":5314},[5264,17568,5707],{"class":5270},[5264,17570,11176],{"class":5314},[5264,17572,7316],{"class":5270},[5264,17574,17575],{"class":5611},"'www-authenticate'",[5264,17577,17578],{"class":5270},"]).",[5264,17580,17581],{"class":5274},"toBeDefined",[5264,17583,5713],{"class":5270},[5264,17585,17586],{"class":5266,"line":8198},[5264,17587,11533],{"class":5270},[5264,17589,17590],{"class":5266,"line":8211},[5264,17591,10781],{"class":5270},[5264,17593,17594],{"class":5266,"line":8218},[5264,17595,5473],{"emptyLinePlaceholder":5472},[5264,17597,17598,17600,17602,17605,17607,17609],{"class":5266,"line":8231},[5264,17599,15552],{"class":5274},[5264,17601,5311],{"class":5270},[5264,17603,17604],{"class":5611},"'HttpExceptionFilter should handle 404'",[5264,17606,15435],{"class":5270},[5264,17608,12060],{"class":5288},[5264,17610,5302],{"class":5270},[5264,17612,17613,17615,17617,17619,17621,17623,17625],{"class":5266,"line":8249},[5264,17614,6094],{"class":5284},[5264,17616,5745],{"class":5274},[5264,17618,5311],{"class":5270},[5264,17620,11686],{"class":5314},[5264,17622,5707],{"class":5270},[5264,17624,17101],{"class":5274},[5264,17626,17104],{"class":5270},[5264,17628,17629,17631,17633,17635,17638],{"class":5266,"line":8254},[5264,17630,17109],{"class":5270},[5264,17632,10312],{"class":5274},[5264,17634,5311],{"class":5270},[5264,17636,17637],{"class":5611},"'\u002Fusers\u002F999'",[5264,17639,5451],{"class":5270},[5264,17641,17642,17644,17646,17648,17650,17652,17654],{"class":5266,"line":8259},[5264,17643,17109],{"class":5270},[5264,17645,17149],{"class":5274},[5264,17647,5311],{"class":5270},[5264,17649,7524],{"class":5314},[5264,17651,5707],{"class":5270},[5264,17653,9730],{"class":5698},[5264,17655,5451],{"class":5270},[5264,17657,17658,17660,17662,17664,17666,17668],{"class":5266,"line":8272},[5264,17659,17109],{"class":5270},[5264,17661,17149],{"class":5274},[5264,17663,5311],{"class":5270},[5264,17665,17170],{"class":5314},[5264,17667,6109],{"class":5288},[5264,17669,5302],{"class":5270},[5264,17671,17672,17674,17676,17678,17680,17682,17684,17686,17688,17690,17692,17695],{"class":5266,"line":8279},[5264,17673,17179],{"class":5274},[5264,17675,5311],{"class":5270},[5264,17677,17170],{"class":5314},[5264,17679,5707],{"class":5270},[5264,17681,11190],{"class":5314},[5264,17683,5707],{"class":5270},[5264,17685,7879],{"class":5314},[5264,17687,5989],{"class":5270},[5264,17689,17196],{"class":5274},[5264,17691,5311],{"class":5270},[5264,17693,17694],{"class":6311},"404",[5264,17696,6000],{"class":5270},[5264,17698,17699,17701,17703,17705,17707,17709,17711,17714,17716,17718],{"class":5266,"line":8292},[5264,17700,17179],{"class":5274},[5264,17702,5311],{"class":5270},[5264,17704,17170],{"class":5314},[5264,17706,5707],{"class":5270},[5264,17708,11190],{"class":5314},[5264,17710,5707],{"class":5270},[5264,17712,17713],{"class":5314},"timestamp",[5264,17715,5989],{"class":5270},[5264,17717,17581],{"class":5274},[5264,17719,5713],{"class":5270},[5264,17721,17722],{"class":5266,"line":8302},[5264,17723,11533],{"class":5270},[5264,17725,17726],{"class":5266,"line":8307},[5264,17727,10781],{"class":5270},[5264,17729,17730],{"class":5266,"line":8312},[5264,17731,14485],{"class":5270},[5201,17733,17735],{"id":17734},"візуалізація-потоку-виконання-спеціалізованих-filters","Візуалізація потоку виконання спеціалізованих filters",[5254,17737,17741],{"className":17738,"code":17739,"language":17740,"meta":5260,"style":5260},"language-plantuml shiki shiki-themes light-plus dark-plus dark-plus","@startuml\n!theme plain\nskinparam backgroundColor #FEFEFE\nskinparam handwritten false\n\nparticipant \"Controller\" as Controller\nparticipant \"Service\" as Service\nparticipant \"TypeORM\" as ORM\nparticipant \"ValidationFilter\" as VF\nparticipant \"DatabaseFilter\" as DF\nparticipant \"HttpFilter\" as HF\nparticipant \"SentryFilter\" as SF\nparticipant \"Response\" as Response\n\n== Scenario 1: Validation Error ==\nController -> Service: create(dto)\nService -> Service: Invalid DTO data\nService --x VF: throw BadRequestException\nactivate VF\nVF -> VF: Format validation errors\nVF -> Response: 400 + errors list\ndeactivate VF\n\n== Scenario 2: Database Error ==\nController -> Service: create(validDto)\nService -> ORM: save(user)\nORM -> ORM: Unique constraint violation\nORM --x DF: throw QueryFailedError (23505)\nactivate DF\nDF -> DF: Map error code 23505 → 409\nDF -> Response: 409 \"Email exists\"\ndeactivate DF\n\n== Scenario 3: HTTP Exception ==\nController -> Service: findById(id)\nService -> Service: User not found\nService --x HF: throw NotFoundException\nactivate HF\nHF -> HF: Format HTTP exception\nHF -> Response: 404 + metadata\ndeactivate HF\n\n== Scenario 4: Unexpected Error ==\nController -> Service: complexOperation()\nService -> Service: Unhandled Error\nService --x SF: throw Error\nactivate SF\nSF -> SF: Log to Sentry\nSF -> SF: Send error report\nSF -> Response: 500 \"Internal error\"\ndeactivate SF\n\n@enduml\n","plantuml",[5102,17742,17743,17748,17753,17758,17763,17767,17772,17777,17782,17787,17792,17797,17802,17807,17811,17816,17821,17826,17831,17836,17841,17846,17851,17855,17860,17865,17870,17875,17880,17885,17890,17895,17900,17904,17909,17914,17919,17924,17929,17934,17939,17944,17948,17953,17958,17963,17968,17973,17978,17983,17988,17993,17997],{"__ignoreMap":5260},[5264,17744,17745],{"class":5266,"line":5267},[5264,17746,17747],{},"@startuml\n",[5264,17749,17750],{"class":5266,"line":5281},[5264,17751,17752],{},"!theme plain\n",[5264,17754,17755],{"class":5266,"line":5305},[5264,17756,17757],{},"skinparam backgroundColor #FEFEFE\n",[5264,17759,17760],{"class":5266,"line":5338},[5264,17761,17762],{},"skinparam handwritten false\n",[5264,17764,17765],{"class":5266,"line":5345},[5264,17766,5473],{"emptyLinePlaceholder":5472},[5264,17768,17769],{"class":5266,"line":5370},[5264,17770,17771],{},"participant \"Controller\" as Controller\n",[5264,17773,17774],{"class":5266,"line":5394},[5264,17775,17776],{},"participant \"Service\" as Service\n",[5264,17778,17779],{"class":5266,"line":5416},[5264,17780,17781],{},"participant \"TypeORM\" as ORM\n",[5264,17783,17784],{"class":5266,"line":5422},[5264,17785,17786],{},"participant \"ValidationFilter\" as VF\n",[5264,17788,17789],{"class":5266,"line":5428},[5264,17790,17791],{},"participant \"DatabaseFilter\" as DF\n",[5264,17793,17794],{"class":5266,"line":5781},[5264,17795,17796],{},"participant \"HttpFilter\" as HF\n",[5264,17798,17799],{"class":5266,"line":5804},[5264,17800,17801],{},"participant \"SentryFilter\" as SF\n",[5264,17803,17804],{"class":5266,"line":5809},[5264,17805,17806],{},"participant \"Response\" as Response\n",[5264,17808,17809],{"class":5266,"line":5815},[5264,17810,5473],{"emptyLinePlaceholder":5472},[5264,17812,17813],{"class":5266,"line":5835},[5264,17814,17815],{},"== Scenario 1: Validation Error ==\n",[5264,17817,17818],{"class":5266,"line":5840},[5264,17819,17820],{},"Controller -> Service: create(dto)\n",[5264,17822,17823],{"class":5266,"line":5846},[5264,17824,17825],{},"Service -> Service: Invalid DTO data\n",[5264,17827,17828],{"class":5266,"line":5857},[5264,17829,17830],{},"Service --x VF: throw BadRequestException\n",[5264,17832,17833],{"class":5266,"line":5868},[5264,17834,17835],{},"activate VF\n",[5264,17837,17838],{"class":5266,"line":5879},[5264,17839,17840],{},"VF -> VF: Format validation errors\n",[5264,17842,17843],{"class":5266,"line":5890},[5264,17844,17845],{},"VF -> Response: 400 + errors list\n",[5264,17847,17848],{"class":5266,"line":5911},[5264,17849,17850],{},"deactivate VF\n",[5264,17852,17853],{"class":5266,"line":5926},[5264,17854,5473],{"emptyLinePlaceholder":5472},[5264,17856,17857],{"class":5266,"line":5941},[5264,17858,17859],{},"== Scenario 2: Database Error ==\n",[5264,17861,17862],{"class":5266,"line":5963},[5264,17863,17864],{},"Controller -> Service: create(validDto)\n",[5264,17866,17867],{"class":5266,"line":5969},[5264,17868,17869],{},"Service -> ORM: save(user)\n",[5264,17871,17872],{"class":5266,"line":5974},[5264,17873,17874],{},"ORM -> ORM: Unique constraint violation\n",[5264,17876,17877],{"class":5266,"line":6003},[5264,17878,17879],{},"ORM --x DF: throw QueryFailedError (23505)\n",[5264,17881,17882],{"class":5266,"line":6008},[5264,17883,17884],{},"activate DF\n",[5264,17886,17887],{"class":5266,"line":6013},[5264,17888,17889],{},"DF -> DF: Map error code 23505 → 409\n",[5264,17891,17892],{"class":5266,"line":6039},[5264,17893,17894],{},"DF -> Response: 409 \"Email exists\"\n",[5264,17896,17897],{"class":5266,"line":6062},[5264,17898,17899],{},"deactivate DF\n",[5264,17901,17902],{"class":5266,"line":6080},[5264,17903,5473],{"emptyLinePlaceholder":5472},[5264,17905,17906],{"class":5266,"line":6086},[5264,17907,17908],{},"== Scenario 3: HTTP Exception ==\n",[5264,17910,17911],{"class":5266,"line":6091},[5264,17912,17913],{},"Controller -> Service: findById(id)\n",[5264,17915,17916],{"class":5266,"line":6115},[5264,17917,17918],{},"Service -> Service: User not found\n",[5264,17920,17921],{"class":5266,"line":6131},[5264,17922,17923],{},"Service --x HF: throw NotFoundException\n",[5264,17925,17926],{"class":5266,"line":6146},[5264,17927,17928],{},"activate HF\n",[5264,17930,17931],{"class":5266,"line":6172},[5264,17932,17933],{},"HF -> HF: Format HTTP exception\n",[5264,17935,17936],{"class":5266,"line":6178},[5264,17937,17938],{},"HF -> Response: 404 + metadata\n",[5264,17940,17941],{"class":5266,"line":6183},[5264,17942,17943],{},"deactivate HF\n",[5264,17945,17946],{"class":5266,"line":8036},[5264,17947,5473],{"emptyLinePlaceholder":5472},[5264,17949,17950],{"class":5266,"line":8060},[5264,17951,17952],{},"== Scenario 4: Unexpected Error ==\n",[5264,17954,17955],{"class":5266,"line":8072},[5264,17956,17957],{},"Controller -> Service: complexOperation()\n",[5264,17959,17960],{"class":5266,"line":8086},[5264,17961,17962],{},"Service -> Service: Unhandled Error\n",[5264,17964,17965],{"class":5266,"line":8094},[5264,17966,17967],{},"Service --x SF: throw Error\n",[5264,17969,17970],{"class":5266,"line":8110},[5264,17971,17972],{},"activate SF\n",[5264,17974,17975],{"class":5266,"line":8133},[5264,17976,17977],{},"SF -> SF: Log to Sentry\n",[5264,17979,17980],{"class":5266,"line":8139},[5264,17981,17982],{},"SF -> SF: Send error report\n",[5264,17984,17985],{"class":5266,"line":8144},[5264,17986,17987],{},"SF -> Response: 500 \"Internal error\"\n",[5264,17989,17990],{"class":5266,"line":8157},[5264,17991,17992],{},"deactivate SF\n",[5264,17994,17995],{"class":5266,"line":8164},[5264,17996,5473],{"emptyLinePlaceholder":5472},[5264,17998,17999],{"class":5266,"line":8178},[5264,18000,18001],{},"@enduml\n",[5206,18003,18004],{},[5144,18005,18006],{},"Опис сценаріїв:",[14105,18008,18009,18019,18029,18040],{},[5095,18010,18011,5318,18014,7477,18016,18018],{},[5144,18012,18013],{},"Validation Error",[5102,18015,5448],{},[5102,18017,5104],{}," → 400 з деталями полів",[5095,18020,18021,5318,18024,7477,18026,18028],{},[5144,18022,18023],{},"Database Error",[5102,18025,5484],{},[5102,18027,5111],{}," → 409\u002F400 з читабельним повідомленням",[5095,18030,18031,5318,18034,7477,18037,18039],{},[5144,18032,18033],{},"HTTP Exception",[5102,18035,18036],{},"NotFoundException",[5102,18038,5118],{}," → 404 з метаданими",[5095,18041,18042,5318,18045,7477,18048,18050],{},[5144,18043,18044],{},"Unexpected Error",[5102,18046,18047],{},"Error",[5102,18049,10845],{}," (catch-all) → логування + 500",[5201,18052,18054],{"id":18053},"найкращі-практики-спеціалізованих-filters","Найкращі практики спеціалізованих filters",[5572,18056,18058],{"id":18057},"_1-один-filter-один-тип-помилки","1. Один filter — один тип помилки",[5251,18060,18061,18194],{},[5254,18062,18065],{"className":5256,"code":18063,"filename":18064,"language":5259,"meta":5260,"style":5260},"@Catch()\nexport class MegaFilter implements ExceptionFilter {\n  catch(exception: unknown, host: ArgumentsHost) {\n    if (exception instanceof BadRequestException) {\n      \u002F\u002F 50 рядків обробки валідації\n    } else if (exception instanceof QueryFailedError) {\n      \u002F\u002F 80 рядків обробки БД\n    } else if (exception instanceof UnauthorizedException) {\n      \u002F\u002F 40 рядків обробки авторизації\n    }\n    \u002F\u002F 300+ рядків коду\n  }\n}\n","❌ Погано - все в одному",[5102,18066,18067,18075,18090,18112,18126,18131,18149,18154,18172,18177,18181,18186,18190],{"__ignoreMap":5260},[5264,18068,18069,18071,18073],{"class":5266,"line":5267},[5264,18070,5271],{"class":5270},[5264,18072,5275],{"class":5274},[5264,18074,5278],{"class":5270},[5264,18076,18077,18079,18081,18084,18086,18088],{"class":5266,"line":5281},[5264,18078,5285],{"class":5284},[5264,18080,5289],{"class":5288},[5264,18082,18083],{"class":5292}," MegaFilter",[5264,18085,5296],{"class":5288},[5264,18087,5299],{"class":5292},[5264,18089,5302],{"class":5270},[5264,18091,18092,18094,18096,18098,18100,18102,18104,18106,18108,18110],{"class":5266,"line":5305},[5264,18093,5308],{"class":5274},[5264,18095,5311],{"class":5270},[5264,18097,5315],{"class":5314},[5264,18099,5318],{"class":5270},[5264,18101,5321],{"class":5292},[5264,18103,5324],{"class":5270},[5264,18105,5327],{"class":5314},[5264,18107,5318],{"class":5270},[5264,18109,5332],{"class":5292},[5264,18111,5335],{"class":5270},[5264,18113,18114,18116,18118,18120,18122,18124],{"class":5266,"line":5338},[5264,18115,5348],{"class":5284},[5264,18117,5146],{"class":5270},[5264,18119,5315],{"class":5314},[5264,18121,5355],{"class":5288},[5264,18123,15576],{"class":5292},[5264,18125,5335],{"class":5270},[5264,18127,18128],{"class":5266,"line":5345},[5264,18129,18130],{"class":5341},"      \u002F\u002F 50 рядків обробки валідації\n",[5264,18132,18133,18135,18137,18139,18141,18143,18145,18147],{"class":5266,"line":5370},[5264,18134,10158],{"class":5270},[5264,18136,10161],{"class":5284},[5264,18138,5376],{"class":5284},[5264,18140,5146],{"class":5270},[5264,18142,5315],{"class":5314},[5264,18144,5355],{"class":5288},[5264,18146,5385],{"class":5292},[5264,18148,5335],{"class":5270},[5264,18150,18151],{"class":5266,"line":5394},[5264,18152,18153],{"class":5341},"      \u002F\u002F 80 рядків обробки БД\n",[5264,18155,18156,18158,18160,18162,18164,18166,18168,18170],{"class":5266,"line":5416},[5264,18157,10158],{"class":5270},[5264,18159,10161],{"class":5284},[5264,18161,5376],{"class":5284},[5264,18163,5146],{"class":5270},[5264,18165,5315],{"class":5314},[5264,18167,5355],{"class":5288},[5264,18169,5407],{"class":5292},[5264,18171,5335],{"class":5270},[5264,18173,18174],{"class":5266,"line":5422},[5264,18175,18176],{"class":5341},"      \u002F\u002F 40 рядків обробки авторизації\n",[5264,18178,18179],{"class":5266,"line":5428},[5264,18180,6083],{"class":5270},[5264,18182,18183],{"class":5266,"line":5781},[5264,18184,18185],{"class":5341},"    \u002F\u002F 300+ рядків коду\n",[5264,18187,18188],{"class":5266,"line":5804},[5264,18189,5425],{"class":5270},[5264,18191,18192],{"class":5266,"line":5809},[5264,18193,5431],{"class":5270},[5254,18195,18198],{"className":5256,"code":18196,"filename":18197,"language":5259,"meta":5260,"style":5260},"@Catch(BadRequestException)\nexport class ValidationExceptionFilter { \u002F* ... *\u002F }\n\n@Catch(QueryFailedError)\nexport class DatabaseExceptionFilter { \u002F* ... *\u002F }\n\n@Catch(UnauthorizedException)\nexport class AuthExceptionFilter { \u002F* ... *\u002F }\n","✅ Добре - спеціалізовані filters",[5102,18199,18200,18212,18226,18230,18242,18256,18260,18272],{"__ignoreMap":5260},[5264,18201,18202,18204,18206,18208,18210],{"class":5266,"line":5267},[5264,18203,5271],{"class":5270},[5264,18205,5275],{"class":5274},[5264,18207,5311],{"class":5270},[5264,18209,5448],{"class":5314},[5264,18211,5451],{"class":5270},[5264,18213,18214,18216,18218,18220,18222,18224],{"class":5266,"line":5281},[5264,18215,5285],{"class":5284},[5264,18217,5289],{"class":5288},[5264,18219,5460],{"class":5292},[5264,18221,5463],{"class":5270},[5264,18223,5364],{"class":5341},[5264,18225,5367],{"class":5270},[5264,18227,18228],{"class":5266,"line":5305},[5264,18229,5473],{"emptyLinePlaceholder":5472},[5264,18231,18232,18234,18236,18238,18240],{"class":5266,"line":5338},[5264,18233,5271],{"class":5270},[5264,18235,5275],{"class":5274},[5264,18237,5311],{"class":5270},[5264,18239,5484],{"class":5314},[5264,18241,5451],{"class":5270},[5264,18243,18244,18246,18248,18250,18252,18254],{"class":5266,"line":5345},[5264,18245,5285],{"class":5284},[5264,18247,5289],{"class":5288},[5264,18249,5495],{"class":5292},[5264,18251,5463],{"class":5270},[5264,18253,5364],{"class":5341},[5264,18255,5367],{"class":5270},[5264,18257,18258],{"class":5266,"line":5370},[5264,18259,5473],{"emptyLinePlaceholder":5472},[5264,18261,18262,18264,18266,18268,18270],{"class":5266,"line":5394},[5264,18263,5271],{"class":5270},[5264,18265,5275],{"class":5274},[5264,18267,5311],{"class":5270},[5264,18269,5516],{"class":5314},[5264,18271,5451],{"class":5270},[5264,18273,18274,18276,18278,18280,18282,18284],{"class":5266,"line":5416},[5264,18275,5285],{"class":5284},[5264,18277,5289],{"class":5288},[5264,18279,5527],{"class":5292},[5264,18281,5463],{"class":5270},[5264,18283,5364],{"class":5341},[5264,18285,5367],{"class":5270},[5572,18287,18289],{"id":18288},"_2-не-розкривати-чутливу-інформацію","2. Не розкривати чутливу інформацію",[5251,18291,18292,18388],{},[5254,18293,18296],{"className":5256,"code":18294,"filename":18295,"language":5259,"meta":5260,"style":5260},"catch(exception: QueryFailedError, host: ArgumentsHost) {\n  response.json({\n    message: exception.message, \u002F\u002F \"duplicate key value violates unique constraint \\\"users_email_key\\\"\"\n    query: exception.query,     \u002F\u002F SQL-запит\n    parameters: exception.parameters, \u002F\u002F Параметри запиту\n  });\n}\n","❌ Погано",[5102,18297,18298,18320,18331,18347,18364,18380,18384],{"__ignoreMap":5260},[5264,18299,18300,18302,18304,18306,18308,18310,18312,18314,18316,18318],{"class":5266,"line":5267},[5264,18301,15855],{"class":5284},[5264,18303,5311],{"class":5270},[5264,18305,5315],{"class":5314},[5264,18307,5318],{"class":5270},[5264,18309,5484],{"class":5292},[5264,18311,5324],{"class":5270},[5264,18313,5327],{"class":5314},[5264,18315,5318],{"class":5270},[5264,18317,5332],{"class":5292},[5264,18319,5335],{"class":5270},[5264,18321,18322,18325,18327,18329],{"class":5266,"line":5281},[5264,18323,18324],{"class":5314},"  response",[5264,18326,5707],{"class":5270},[5264,18328,5992],{"class":5274},[5264,18330,7035],{"class":5270},[5264,18332,18333,18336,18338,18340,18342,18344],{"class":5266,"line":5305},[5264,18334,18335],{"class":5314},"    message:",[5264,18337,7745],{"class":5314},[5264,18339,5707],{"class":5270},[5264,18341,5830],{"class":5314},[5264,18343,5324],{"class":5270},[5264,18345,18346],{"class":5341},"\u002F\u002F \"duplicate key value violates unique constraint \\\"users_email_key\\\"\"\n",[5264,18348,18349,18352,18354,18356,18358,18361],{"class":5266,"line":5338},[5264,18350,18351],{"class":5314},"    query:",[5264,18353,7745],{"class":5314},[5264,18355,5707],{"class":5270},[5264,18357,7763],{"class":5314},[5264,18359,18360],{"class":5270},",     ",[5264,18362,18363],{"class":5341},"\u002F\u002F SQL-запит\n",[5264,18365,18366,18369,18371,18373,18375,18377],{"class":5266,"line":5345},[5264,18367,18368],{"class":5314},"    parameters:",[5264,18370,7745],{"class":5314},[5264,18372,5707],{"class":5270},[5264,18374,7777],{"class":5314},[5264,18376,5324],{"class":5270},[5264,18378,18379],{"class":5341},"\u002F\u002F Параметри запиту\n",[5264,18381,18382],{"class":5266,"line":5370},[5264,18383,10781],{"class":5270},[5264,18385,18386],{"class":5266,"line":5394},[5264,18387,5431],{"class":5270},[5254,18389,18392],{"className":5256,"code":18390,"filename":18391,"language":5259,"meta":5260,"style":5260},"catch(exception: QueryFailedError, host: ArgumentsHost) {\n  \u002F\u002F Логування повної помилки для дебагу\n  this.logger.error('Database error', {\n    message: exception.message,\n    query: exception.query,\n  });\n\n  \u002F\u002F Клієнту лише загальне повідомлення\n  response.json({\n    statusCode: 409,\n    message: 'Duplicate value: email already exists',\n  });\n}\n","✅ Добре",[5102,18393,18394,18416,18421,18440,18452,18464,18468,18472,18477,18487,18496,18505,18509],{"__ignoreMap":5260},[5264,18395,18396,18398,18400,18402,18404,18406,18408,18410,18412,18414],{"class":5266,"line":5267},[5264,18397,15855],{"class":5284},[5264,18399,5311],{"class":5270},[5264,18401,5315],{"class":5314},[5264,18403,5318],{"class":5270},[5264,18405,5484],{"class":5292},[5264,18407,5324],{"class":5270},[5264,18409,5327],{"class":5314},[5264,18411,5318],{"class":5270},[5264,18413,5332],{"class":5292},[5264,18415,5335],{"class":5270},[5264,18417,18418],{"class":5266,"line":5281},[5264,18419,18420],{"class":5341},"  \u002F\u002F Логування повної помилки для дебагу\n",[5264,18422,18423,18426,18428,18430,18432,18434,18436,18438],{"class":5266,"line":5305},[5264,18424,18425],{"class":5288},"  this",[5264,18427,5707],{"class":5270},[5264,18429,7726],{"class":5314},[5264,18431,5707],{"class":5270},[5264,18433,6106],{"class":5274},[5264,18435,5311],{"class":5270},[5264,18437,7735],{"class":5611},[5264,18439,7738],{"class":5270},[5264,18441,18442,18444,18446,18448,18450],{"class":5266,"line":5338},[5264,18443,18335],{"class":5314},[5264,18445,7745],{"class":5314},[5264,18447,5707],{"class":5270},[5264,18449,5830],{"class":5314},[5264,18451,5865],{"class":5270},[5264,18453,18454,18456,18458,18460,18462],{"class":5266,"line":5345},[5264,18455,18351],{"class":5314},[5264,18457,7745],{"class":5314},[5264,18459,5707],{"class":5270},[5264,18461,7763],{"class":5314},[5264,18463,5865],{"class":5270},[5264,18465,18466],{"class":5266,"line":5370},[5264,18467,10781],{"class":5270},[5264,18469,18470],{"class":5266,"line":5394},[5264,18471,5473],{"emptyLinePlaceholder":5472},[5264,18473,18474],{"class":5266,"line":5416},[5264,18475,18476],{"class":5341},"  \u002F\u002F Клієнту лише загальне повідомлення\n",[5264,18478,18479,18481,18483,18485],{"class":5266,"line":5422},[5264,18480,18324],{"class":5314},[5264,18482,5707],{"class":5270},[5264,18484,5992],{"class":5274},[5264,18486,7035],{"class":5270},[5264,18488,18489,18492,18494],{"class":5266,"line":5428},[5264,18490,18491],{"class":5314},"    statusCode:",[5264,18493,16480],{"class":6311},[5264,18495,5865],{"class":5270},[5264,18497,18498,18500,18503],{"class":5266,"line":5781},[5264,18499,18335],{"class":5314},[5264,18501,18502],{"class":5611}," 'Duplicate value: email already exists'",[5264,18504,5865],{"class":5270},[5264,18506,18507],{"class":5266,"line":5804},[5264,18508,10781],{"class":5270},[5264,18510,18511],{"class":5266,"line":5809},[5264,18512,5431],{"class":5270},[5572,18514,18516],{"id":18515},"_3-логування-з-контекстом-для-дебагу","3. Логування з контекстом для дебагу",[5254,18518,18520],{"className":5256,"code":18519,"language":5259,"meta":5260,"style":5260},"this.logger.error('Exception occurred', {\n  \u002F\u002F Деталі помилки\n  message: exception.message,\n  stack: exception.stack,\n  type: exception.constructor.name,\n  \n  \u002F\u002F Контекст запиту\n  method: request.method,\n  url: request.url,\n  params: request.params,\n  query: request.query,\n  body: request.body, \u002F\u002F Обережно з паролями!\n  \n  \u002F\u002F Контекст користувача\n  userId: request.user?.id,\n  userEmail: request.user?.email,\n  userRoles: request.user?.roles,\n  \n  \u002F\u002F Технічний контекст\n  ip: request.ip,\n  userAgent: request.get('user-agent'),\n  requestId: request.headers['x-request-id'],\n  timestamp: new Date().toISOString(),\n});\n",[5102,18521,18522,18540,18545,18558,18571,18588,18593,18598,18611,18624,18637,18650,18666,18670,18675,18692,18709,18726,18730,18735,18748,18765,18783,18798],{"__ignoreMap":5260},[5264,18523,18524,18526,18528,18530,18532,18534,18536,18538],{"class":5266,"line":5267},[5264,18525,7001],{"class":5288},[5264,18527,5707],{"class":5270},[5264,18529,7726],{"class":5314},[5264,18531,5707],{"class":5270},[5264,18533,6106],{"class":5274},[5264,18535,5311],{"class":5270},[5264,18537,15093],{"class":5611},[5264,18539,7738],{"class":5270},[5264,18541,18542],{"class":5266,"line":5281},[5264,18543,18544],{"class":5341},"  \u002F\u002F Деталі помилки\n",[5264,18546,18547,18550,18552,18554,18556],{"class":5266,"line":5305},[5264,18548,18549],{"class":5314},"  message:",[5264,18551,7745],{"class":5314},[5264,18553,5707],{"class":5270},[5264,18555,5830],{"class":5314},[5264,18557,5865],{"class":5270},[5264,18559,18560,18563,18565,18567,18569],{"class":5266,"line":5338},[5264,18561,18562],{"class":5314},"  stack:",[5264,18564,7745],{"class":5314},[5264,18566,5707],{"class":5270},[5264,18568,10430],{"class":5314},[5264,18570,5865],{"class":5270},[5264,18572,18573,18576,18578,18580,18582,18584,18586],{"class":5266,"line":5345},[5264,18574,18575],{"class":5314},"  type:",[5264,18577,7745],{"class":5314},[5264,18579,5707],{"class":5270},[5264,18581,15003],{"class":5314},[5264,18583,5707],{"class":5270},[5264,18585,7627],{"class":5314},[5264,18587,5865],{"class":5270},[5264,18589,18590],{"class":5266,"line":5370},[5264,18591,18592],{"class":5270},"  \n",[5264,18594,18595],{"class":5266,"line":5394},[5264,18596,18597],{"class":5341},"  \u002F\u002F Контекст запиту\n",[5264,18599,18600,18603,18605,18607,18609],{"class":5266,"line":5416},[5264,18601,18602],{"class":5314},"  method:",[5264,18604,5745],{"class":5314},[5264,18606,5707],{"class":5270},[5264,18608,5936],{"class":5314},[5264,18610,5865],{"class":5270},[5264,18612,18613,18616,18618,18620,18622],{"class":5266,"line":5422},[5264,18614,18615],{"class":5314},"  url:",[5264,18617,5745],{"class":5314},[5264,18619,5707],{"class":5270},[5264,18621,5921],{"class":5314},[5264,18623,5865],{"class":5270},[5264,18625,18626,18629,18631,18633,18635],{"class":5266,"line":5428},[5264,18627,18628],{"class":5314},"  params:",[5264,18630,5745],{"class":5314},[5264,18632,5707],{"class":5270},[5264,18634,11217],{"class":5314},[5264,18636,5865],{"class":5270},[5264,18638,18639,18642,18644,18646,18648],{"class":5266,"line":5781},[5264,18640,18641],{"class":5314},"  query:",[5264,18643,5745],{"class":5314},[5264,18645,5707],{"class":5270},[5264,18647,7763],{"class":5314},[5264,18649,5865],{"class":5270},[5264,18651,18652,18655,18657,18659,18661,18663],{"class":5266,"line":5804},[5264,18653,18654],{"class":5314},"  body:",[5264,18656,5745],{"class":5314},[5264,18658,5707],{"class":5270},[5264,18660,11190],{"class":5314},[5264,18662,5324],{"class":5270},[5264,18664,18665],{"class":5341},"\u002F\u002F Обережно з паролями!\n",[5264,18667,18668],{"class":5266,"line":5809},[5264,18669,18592],{"class":5270},[5264,18671,18672],{"class":5266,"line":5815},[5264,18673,18674],{"class":5341},"  \u002F\u002F Контекст користувача\n",[5264,18676,18677,18680,18682,18684,18686,18688,18690],{"class":5266,"line":5835},[5264,18678,18679],{"class":5314},"  userId:",[5264,18681,5745],{"class":5314},[5264,18683,5707],{"class":5270},[5264,18685,8937],{"class":5314},[5264,18687,8532],{"class":5270},[5264,18689,10284],{"class":5314},[5264,18691,5865],{"class":5270},[5264,18693,18694,18697,18699,18701,18703,18705,18707],{"class":5266,"line":5840},[5264,18695,18696],{"class":5314},"  userEmail:",[5264,18698,5745],{"class":5314},[5264,18700,5707],{"class":5270},[5264,18702,8937],{"class":5314},[5264,18704,8532],{"class":5270},[5264,18706,11295],{"class":5314},[5264,18708,5865],{"class":5270},[5264,18710,18711,18714,18716,18718,18720,18722,18724],{"class":5266,"line":5846},[5264,18712,18713],{"class":5314},"  userRoles:",[5264,18715,5745],{"class":5314},[5264,18717,5707],{"class":5270},[5264,18719,8937],{"class":5314},[5264,18721,8532],{"class":5270},[5264,18723,13673],{"class":5314},[5264,18725,5865],{"class":5270},[5264,18727,18728],{"class":5266,"line":5857},[5264,18729,18592],{"class":5270},[5264,18731,18732],{"class":5266,"line":5868},[5264,18733,18734],{"class":5341},"  \u002F\u002F Технічний контекст\n",[5264,18736,18737,18740,18742,18744,18746],{"class":5266,"line":5879},[5264,18738,18739],{"class":5314},"  ip:",[5264,18741,5745],{"class":5314},[5264,18743,5707],{"class":5270},[5264,18745,10298],{"class":5314},[5264,18747,5865],{"class":5270},[5264,18749,18750,18753,18755,18757,18759,18761,18763],{"class":5266,"line":5890},[5264,18751,18752],{"class":5314},"  userAgent:",[5264,18754,5745],{"class":5314},[5264,18756,5707],{"class":5270},[5264,18758,10312],{"class":5274},[5264,18760,5311],{"class":5270},[5264,18762,10317],{"class":5611},[5264,18764,5960],{"class":5270},[5264,18766,18767,18770,18772,18774,18776,18778,18781],{"class":5266,"line":5911},[5264,18768,18769],{"class":5314},"  requestId:",[5264,18771,5745],{"class":5314},[5264,18773,5707],{"class":5270},[5264,18775,11176],{"class":5314},[5264,18777,7316],{"class":5270},[5264,18779,18780],{"class":5611},"'x-request-id'",[5264,18782,7436],{"class":5270},[5264,18784,18785,18788,18790,18792,18794,18796],{"class":5266,"line":5926},[5264,18786,18787],{"class":5314},"  timestamp:",[5264,18789,5896],{"class":5288},[5264,18791,5899],{"class":5274},[5264,18793,5902],{"class":5270},[5264,18795,5905],{"class":5274},[5264,18797,5908],{"class":5270},[5264,18799,18800],{"class":5266,"line":5941},[5264,18801,14485],{"class":5270},[5572,18803,18805],{"id":18804},"_4-різні-відповіді-для-development-та-production","4. Різні відповіді для development та production",[5254,18807,18809],{"className":5256,"code":18808,"language":5259,"meta":5260,"style":5260},"const errorResponse = {\n  statusCode: status,\n  message: exception.message,\n  timestamp: new Date().toISOString(),\n  path: request.url,\n  \n  \u002F\u002F Деталі лише у development\n  ...(process.env.NODE_ENV === 'development' && {\n    stack: exception.stack,\n    query: exception['query'],\n    details: exception,\n  }),\n};\n",[5102,18810,18811,18820,18829,18841,18855,18868,18872,18877,18898,18911,18924,18933,18938],{"__ignoreMap":5260},[5264,18812,18813,18816,18818],{"class":5266,"line":5267},[5264,18814,18815],{"class":5288},"const",[5264,18817,5851],{"class":5698},[5264,18819,5854],{"class":5270},[5264,18821,18822,18825,18827],{"class":5266,"line":5281},[5264,18823,18824],{"class":5314},"  statusCode:",[5264,18826,5767],{"class":5314},[5264,18828,5865],{"class":5270},[5264,18830,18831,18833,18835,18837,18839],{"class":5266,"line":5305},[5264,18832,18549],{"class":5314},[5264,18834,7745],{"class":5314},[5264,18836,5707],{"class":5270},[5264,18838,5830],{"class":5314},[5264,18840,5865],{"class":5270},[5264,18842,18843,18845,18847,18849,18851,18853],{"class":5266,"line":5338},[5264,18844,18787],{"class":5314},[5264,18846,5896],{"class":5288},[5264,18848,5899],{"class":5274},[5264,18850,5902],{"class":5270},[5264,18852,5905],{"class":5274},[5264,18854,5908],{"class":5270},[5264,18856,18857,18860,18862,18864,18866],{"class":5266,"line":5345},[5264,18858,18859],{"class":5314},"  path:",[5264,18861,5745],{"class":5314},[5264,18863,5707],{"class":5270},[5264,18865,5921],{"class":5314},[5264,18867,5865],{"class":5270},[5264,18869,18870],{"class":5266,"line":5370},[5264,18871,18592],{"class":5270},[5264,18873,18874],{"class":5266,"line":5394},[5264,18875,18876],{"class":5341},"  \u002F\u002F Деталі лише у development\n",[5264,18878,18879,18882,18884,18886,18888,18890,18892,18894,18896],{"class":5266,"line":5416},[5264,18880,18881],{"class":5270},"  ...(",[5264,18883,10400],{"class":5314},[5264,18885,5707],{"class":5270},[5264,18887,10405],{"class":5314},[5264,18889,5707],{"class":5270},[5264,18891,10410],{"class":5698},[5264,18893,10138],{"class":5270},[5264,18895,10415],{"class":5611},[5264,18897,10418],{"class":5270},[5264,18899,18900,18903,18905,18907,18909],{"class":5266,"line":5422},[5264,18901,18902],{"class":5314},"    stack:",[5264,18904,7745],{"class":5314},[5264,18906,5707],{"class":5270},[5264,18908,10430],{"class":5314},[5264,18910,5865],{"class":5270},[5264,18912,18913,18915,18917,18919,18922],{"class":5266,"line":5428},[5264,18914,18351],{"class":5314},[5264,18916,7745],{"class":5314},[5264,18918,7316],{"class":5270},[5264,18920,18921],{"class":5611},"'query'",[5264,18923,7436],{"class":5270},[5264,18925,18926,18929,18931],{"class":5266,"line":5781},[5264,18927,18928],{"class":5314},"    details:",[5264,18930,7745],{"class":5314},[5264,18932,5865],{"class":5270},[5264,18934,18935],{"class":5266,"line":5804},[5264,18936,18937],{"class":5270},"  }),\n",[5264,18939,18940],{"class":5266,"line":5809},[5264,18941,14334],{"class":5270},[5572,18943,18945],{"id":18944},"_5-структуровані-відповіді-з-action-hints","5. Структуровані відповіді з action hints",[5254,18947,18949],{"className":5256,"code":18948,"language":5259,"meta":5260,"style":5260},"response.json({\n  statusCode: 409,\n  error: 'Conflict',\n  message: 'Email already registered',\n  timestamp: new Date().toISOString(),\n  \n  \u002F\u002F Підказки для клієнта\n  actions: [\n    { type: 'login', label: 'Login with this email', url: '\u002Fauth\u002Flogin' },\n    { type: 'reset', label: 'Reset password', url: '\u002Fauth\u002Freset-password' },\n  ],\n  \n  \u002F\u002F Додаткові деталі\n  field: 'email',\n  value: dto.email,\n});\n",[5102,18950,18951,18962,18970,18980,18989,19003,19007,19012,19019,19044,19069,19073,19077,19082,19091,19105],{"__ignoreMap":5260},[5264,18952,18953,18956,18958,18960],{"class":5266,"line":5267},[5264,18954,18955],{"class":5314},"response",[5264,18957,5707],{"class":5270},[5264,18959,5992],{"class":5274},[5264,18961,7035],{"class":5270},[5264,18963,18964,18966,18968],{"class":5266,"line":5281},[5264,18965,18824],{"class":5314},[5264,18967,16480],{"class":6311},[5264,18969,5865],{"class":5270},[5264,18971,18972,18975,18978],{"class":5266,"line":5305},[5264,18973,18974],{"class":5314},"  error:",[5264,18976,18977],{"class":5611}," 'Conflict'",[5264,18979,5865],{"class":5270},[5264,18981,18982,18984,18987],{"class":5266,"line":5338},[5264,18983,18549],{"class":5314},[5264,18985,18986],{"class":5611}," 'Email already registered'",[5264,18988,5865],{"class":5270},[5264,18990,18991,18993,18995,18997,18999,19001],{"class":5266,"line":5345},[5264,18992,18787],{"class":5314},[5264,18994,5896],{"class":5288},[5264,18996,5899],{"class":5274},[5264,18998,5902],{"class":5270},[5264,19000,5905],{"class":5274},[5264,19002,5908],{"class":5270},[5264,19004,19005],{"class":5266,"line":5370},[5264,19006,18592],{"class":5270},[5264,19008,19009],{"class":5266,"line":5394},[5264,19010,19011],{"class":5341},"  \u002F\u002F Підказки для клієнта\n",[5264,19013,19014,19017],{"class":5266,"line":5416},[5264,19015,19016],{"class":5314},"  actions:",[5264,19018,10545],{"class":5270},[5264,19020,19021,19023,19026,19028,19030,19033,19036,19038,19040,19042],{"class":5266,"line":5422},[5264,19022,12801],{"class":5270},[5264,19024,19025],{"class":5314},"type:",[5264,19027,13283],{"class":5611},[5264,19029,5324],{"class":5270},[5264,19031,19032],{"class":5314},"label:",[5264,19034,19035],{"class":5611}," 'Login with this email'",[5264,19037,5324],{"class":5270},[5264,19039,15759],{"class":5314},[5264,19041,13302],{"class":5611},[5264,19043,12817],{"class":5270},[5264,19045,19046,19048,19050,19053,19055,19057,19060,19062,19064,19067],{"class":5266,"line":5428},[5264,19047,12801],{"class":5270},[5264,19049,19025],{"class":5314},[5264,19051,19052],{"class":5611}," 'reset'",[5264,19054,5324],{"class":5270},[5264,19056,19032],{"class":5314},[5264,19058,19059],{"class":5611}," 'Reset password'",[5264,19061,5324],{"class":5270},[5264,19063,15759],{"class":5314},[5264,19065,19066],{"class":5611}," '\u002Fauth\u002Freset-password'",[5264,19068,12817],{"class":5270},[5264,19070,19071],{"class":5266,"line":5781},[5264,19072,10577],{"class":5270},[5264,19074,19075],{"class":5266,"line":5804},[5264,19076,18592],{"class":5270},[5264,19078,19079],{"class":5266,"line":5809},[5264,19080,19081],{"class":5341},"  \u002F\u002F Додаткові деталі\n",[5264,19083,19084,19087,19089],{"class":5266,"line":5815},[5264,19085,19086],{"class":5314},"  field:",[5264,19088,15596],{"class":5611},[5264,19090,5865],{"class":5270},[5264,19092,19093,19096,19099,19101,19103],{"class":5266,"line":5835},[5264,19094,19095],{"class":5314},"  value:",[5264,19097,19098],{"class":5314}," dto",[5264,19100,5707],{"class":5270},[5264,19102,11295],{"class":5314},[5264,19104,5865],{"class":5270},[5264,19106,19107],{"class":5266,"line":5840},[5264,19108,14485],{"class":5270},[5572,19110,19112],{"id":19111},"_6-centralізація-mapping-помилок-бд","6. Centralізація mapping помилок БД",[5254,19114,19116],{"className":5256,"code":19115,"language":5259,"meta":5260,"style":5260},"\u002F\u002F database-error.mapper.ts\nexport class DatabaseErrorMapper {\n  static mapPostgresError(code: string, constraint: string): { statusCode: number; message: string } {\n    const errorMap = {\n      '23505': { statusCode: 409, message: 'Duplicate entry' },\n      '23503': { statusCode: 400, message: 'Referenced record does not exist' },\n      '23502': { statusCode: 400, message: 'Required field missing' },\n      '22P02': { statusCode: 400, message: 'Invalid data format' },\n    };\n\n    return errorMap[code] || { statusCode: 500, message: 'Database error' };\n  }\n}\n\n\u002F\u002F database-exception.filter.ts\n@Catch(QueryFailedError)\nexport class DatabaseExceptionFilter implements ExceptionFilter {\n  catch(exception: QueryFailedError, host: ArgumentsHost) {\n    const errorCode = (exception.driverError as any)?.code;\n    const constraint = (exception.driverError as any)?.constraint;\n    \n    const { statusCode, message } = DatabaseErrorMapper.mapPostgresError(errorCode, constraint);\n    \n    \u002F\u002F ...\n  }\n}\n",[5102,19117,19118,19123,19134,19177,19186,19209,19230,19252,19273,19277,19281,19308,19312,19316,19320,19325,19337,19351,19373,19397,19421,19425,19457,19461,19466,19470],{"__ignoreMap":5260},[5264,19119,19120],{"class":5266,"line":5267},[5264,19121,19122],{"class":5341},"\u002F\u002F database-error.mapper.ts\n",[5264,19124,19125,19127,19129,19132],{"class":5266,"line":5281},[5264,19126,5285],{"class":5284},[5264,19128,5289],{"class":5288},[5264,19130,19131],{"class":5292}," DatabaseErrorMapper",[5264,19133,5302],{"class":5270},[5264,19135,19136,19139,19142,19144,19146,19148,19150,19152,19154,19156,19158,19161,19163,19165,19167,19169,19171,19173,19175],{"class":5266,"line":5305},[5264,19137,19138],{"class":5288},"  static",[5264,19140,19141],{"class":5274}," mapPostgresError",[5264,19143,5311],{"class":5270},[5264,19145,5102],{"class":5314},[5264,19147,5318],{"class":5270},[5264,19149,6286],{"class":5292},[5264,19151,5324],{"class":5270},[5264,19153,7859],{"class":5314},[5264,19155,5318],{"class":5270},[5264,19157,6286],{"class":5292},[5264,19159,19160],{"class":5270},"): { ",[5264,19162,7879],{"class":5314},[5264,19164,5318],{"class":5270},[5264,19166,6395],{"class":5292},[5264,19168,8048],{"class":5270},[5264,19170,5830],{"class":5314},[5264,19172,5318],{"class":5270},[5264,19174,6286],{"class":5292},[5264,19176,8057],{"class":5270},[5264,19178,19179,19181,19184],{"class":5266,"line":5338},[5264,19180,5695],{"class":5288},[5264,19182,19183],{"class":5698}," errorMap",[5264,19185,5854],{"class":5270},[5264,19187,19188,19191,19193,19195,19198,19200,19202,19204,19207],{"class":5266,"line":5345},[5264,19189,19190],{"class":5611},"      '23505'",[5264,19192,5212],{"class":5314},[5264,19194,5463],{"class":5270},[5264,19196,19197],{"class":5314},"statusCode:",[5264,19199,16480],{"class":6311},[5264,19201,5324],{"class":5270},[5264,19203,6071],{"class":5314},[5264,19205,19206],{"class":5611}," 'Duplicate entry'",[5264,19208,12817],{"class":5270},[5264,19210,19211,19214,19216,19218,19220,19222,19224,19226,19228],{"class":5266,"line":5370},[5264,19212,19213],{"class":5611},"      '23503'",[5264,19215,5212],{"class":5314},[5264,19217,5463],{"class":5270},[5264,19219,19197],{"class":5314},[5264,19221,7042],{"class":6311},[5264,19223,5324],{"class":5270},[5264,19225,6071],{"class":5314},[5264,19227,8183],{"class":5611},[5264,19229,12817],{"class":5270},[5264,19231,19232,19235,19237,19239,19241,19243,19245,19247,19250],{"class":5266,"line":5394},[5264,19233,19234],{"class":5611},"      '23502'",[5264,19236,5212],{"class":5314},[5264,19238,5463],{"class":5270},[5264,19240,19197],{"class":5314},[5264,19242,7042],{"class":6311},[5264,19244,5324],{"class":5270},[5264,19246,6071],{"class":5314},[5264,19248,19249],{"class":5611}," 'Required field missing'",[5264,19251,12817],{"class":5270},[5264,19253,19254,19257,19259,19261,19263,19265,19267,19269,19271],{"class":5266,"line":5416},[5264,19255,19256],{"class":5611},"      '22P02'",[5264,19258,5212],{"class":5314},[5264,19260,5463],{"class":5270},[5264,19262,19197],{"class":5314},[5264,19264,7042],{"class":6311},[5264,19266,5324],{"class":5270},[5264,19268,6071],{"class":5314},[5264,19270,8297],{"class":5611},[5264,19272,12817],{"class":5270},[5264,19274,19275],{"class":5266,"line":5422},[5264,19276,5966],{"class":5270},[5264,19278,19279],{"class":5266,"line":5428},[5264,19280,5473],{"emptyLinePlaceholder":5472},[5264,19282,19283,19285,19287,19289,19291,19294,19296,19299,19301,19303,19306],{"class":5266,"line":5781},[5264,19284,6094],{"class":5284},[5264,19286,19183],{"class":5314},[5264,19288,7316],{"class":5270},[5264,19290,5102],{"class":5314},[5264,19292,19293],{"class":5270},"] || { ",[5264,19295,19197],{"class":5314},[5264,19297,19298],{"class":6311}," 500",[5264,19300,5324],{"class":5270},[5264,19302,6071],{"class":5314},[5264,19304,19305],{"class":5611}," 'Database error'",[5264,19307,15747],{"class":5270},[5264,19309,19310],{"class":5266,"line":5804},[5264,19311,5425],{"class":5270},[5264,19313,19314],{"class":5266,"line":5809},[5264,19315,5431],{"class":5270},[5264,19317,19318],{"class":5266,"line":5815},[5264,19319,5473],{"emptyLinePlaceholder":5472},[5264,19321,19322],{"class":5266,"line":5835},[5264,19323,19324],{"class":5341},"\u002F\u002F database-exception.filter.ts\n",[5264,19326,19327,19329,19331,19333,19335],{"class":5266,"line":5840},[5264,19328,5271],{"class":5270},[5264,19330,5275],{"class":5274},[5264,19332,5311],{"class":5270},[5264,19334,5484],{"class":5314},[5264,19336,5451],{"class":5270},[5264,19338,19339,19341,19343,19345,19347,19349],{"class":5266,"line":5846},[5264,19340,5285],{"class":5284},[5264,19342,5289],{"class":5288},[5264,19344,5495],{"class":5292},[5264,19346,5296],{"class":5288},[5264,19348,5299],{"class":5292},[5264,19350,5302],{"class":5270},[5264,19352,19353,19355,19357,19359,19361,19363,19365,19367,19369,19371],{"class":5266,"line":5857},[5264,19354,5308],{"class":5274},[5264,19356,5311],{"class":5270},[5264,19358,5315],{"class":5314},[5264,19360,5318],{"class":5270},[5264,19362,5484],{"class":5292},[5264,19364,5324],{"class":5270},[5264,19366,5327],{"class":5314},[5264,19368,5318],{"class":5270},[5264,19370,5332],{"class":5292},[5264,19372,5335],{"class":5270},[5264,19374,19375,19377,19379,19381,19383,19385,19387,19389,19391,19393,19395],{"class":5266,"line":5868},[5264,19376,5695],{"class":5288},[5264,19378,7813],{"class":5698},[5264,19380,7816],{"class":5270},[5264,19382,5315],{"class":5314},[5264,19384,5707],{"class":5270},[5264,19386,7791],{"class":5314},[5264,19388,7825],{"class":5284},[5264,19390,7828],{"class":5292},[5264,19392,7831],{"class":5270},[5264,19394,5102],{"class":5314},[5264,19396,5615],{"class":5270},[5264,19398,19399,19401,19403,19405,19407,19409,19411,19413,19415,19417,19419],{"class":5266,"line":5879},[5264,19400,5695],{"class":5288},[5264,19402,7842],{"class":5698},[5264,19404,7816],{"class":5270},[5264,19406,5315],{"class":5314},[5264,19408,5707],{"class":5270},[5264,19410,7791],{"class":5314},[5264,19412,7825],{"class":5284},[5264,19414,7828],{"class":5292},[5264,19416,7831],{"class":5270},[5264,19418,7859],{"class":5314},[5264,19420,5615],{"class":5270},[5264,19422,19423],{"class":5266,"line":5890},[5264,19424,8909],{"class":5270},[5264,19426,19427,19429,19431,19433,19435,19437,19439,19442,19444,19447,19449,19451,19453,19455],{"class":5266,"line":5911},[5264,19428,5695],{"class":5288},[5264,19430,5463],{"class":5270},[5264,19432,7879],{"class":5698},[5264,19434,5324],{"class":5270},[5264,19436,5830],{"class":5698},[5264,19438,7886],{"class":5270},[5264,19440,19441],{"class":5314},"DatabaseErrorMapper",[5264,19443,5707],{"class":5270},[5264,19445,19446],{"class":5274},"mapPostgresError",[5264,19448,5311],{"class":5270},[5264,19450,7898],{"class":5314},[5264,19452,5324],{"class":5270},[5264,19454,7859],{"class":5314},[5264,19456,6000],{"class":5270},[5264,19458,19459],{"class":5266,"line":5926},[5264,19460,8909],{"class":5270},[5264,19462,19463],{"class":5266,"line":5941},[5264,19464,19465],{"class":5341},"    \u002F\u002F ...\n",[5264,19467,19468],{"class":5266,"line":5963},[5264,19469,5425],{"class":5270},[5264,19471,19472],{"class":5266,"line":5969},[5264,19473,5431],{"class":5270},[5572,19475,19477],{"id":19476},"_7-інтеграція-з-apm-через-interceptor","7. Інтеграція з APM через interceptor",[5254,19479,19481],{"className":5256,"code":19480,"language":5259,"meta":5260,"style":5260},"\u002F\u002F apm.interceptor.ts\n@Injectable()\nexport class ApmInterceptor implements NestInterceptor {\n  intercept(context: ExecutionContext, next: CallHandler): Observable\u003Cany> {\n    const request = context.switchToHttp().getRequest();\n    \n    return next.handle().pipe(\n      catchError(error => {\n        \u002F\u002F Додавання метаданих до помилки\n        error['metadata'] = {\n          controller: context.getClass().name,\n          handler: context.getHandler().name,\n          method: request.method,\n          url: request.url,\n          userId: request.user?.id,\n        };\n        \n        throw error;\n      }),\n    );\n  }\n}\n\n\u002F\u002F В exception filter витягуйте метадані\nconst metadata = exception['metadata'];\nSentry.setContext('request', metadata);\n",[5102,19482,19483,19488,19496,19511,19541,19561,19565,19581,19593,19598,19611,19630,19648,19660,19672,19689,19693,19698,19707,19711,19715,19719,19723,19727,19732,19750],{"__ignoreMap":5260},[5264,19484,19485],{"class":5266,"line":5267},[5264,19486,19487],{"class":5341},"\u002F\u002F apm.interceptor.ts\n",[5264,19489,19490,19492,19494],{"class":5266,"line":5281},[5264,19491,5271],{"class":5270},[5264,19493,8788],{"class":5274},[5264,19495,5278],{"class":5270},[5264,19497,19498,19500,19502,19505,19507,19509],{"class":5266,"line":5305},[5264,19499,5285],{"class":5284},[5264,19501,5289],{"class":5288},[5264,19503,19504],{"class":5292}," ApmInterceptor",[5264,19506,5296],{"class":5288},[5264,19508,11832],{"class":5292},[5264,19510,5302],{"class":5270},[5264,19512,19513,19515,19517,19519,19521,19523,19525,19527,19529,19531,19533,19535,19537,19539],{"class":5266,"line":5338},[5264,19514,11839],{"class":5274},[5264,19516,5311],{"class":5270},[5264,19518,11844],{"class":5314},[5264,19520,5318],{"class":5270},[5264,19522,11741],{"class":5292},[5264,19524,5324],{"class":5270},[5264,19526,11853],{"class":5314},[5264,19528,5318],{"class":5270},[5264,19530,11746],{"class":5292},[5264,19532,6031],{"class":5270},[5264,19534,11779],{"class":5292},[5264,19536,5733],{"class":5270},[5264,19538,5791],{"class":5292},[5264,19540,8878],{"class":5270},[5264,19542,19543,19545,19547,19549,19551,19553,19555,19557,19559],{"class":5266,"line":5345},[5264,19544,5695],{"class":5288},[5264,19546,5745],{"class":5698},[5264,19548,5702],{"class":5270},[5264,19550,11844],{"class":5314},[5264,19552,5707],{"class":5270},[5264,19554,5710],{"class":5274},[5264,19556,5902],{"class":5270},[5264,19558,5754],{"class":5274},[5264,19560,5713],{"class":5270},[5264,19562,19563],{"class":5266,"line":5370},[5264,19564,8909],{"class":5270},[5264,19566,19567,19569,19571,19573,19575,19577,19579],{"class":5266,"line":5394},[5264,19568,6094],{"class":5284},[5264,19570,12037],{"class":5314},[5264,19572,5707],{"class":5270},[5264,19574,12042],{"class":5274},[5264,19576,5902],{"class":5270},[5264,19578,12047],{"class":5274},[5264,19580,8001],{"class":5270},[5264,19582,19583,19585,19587,19589,19591],{"class":5266,"line":5416},[5264,19584,12690],{"class":5274},[5264,19586,5311],{"class":5270},[5264,19588,6106],{"class":5314},[5264,19590,6109],{"class":5288},[5264,19592,5302],{"class":5270},[5264,19594,19595],{"class":5266,"line":5422},[5264,19596,19597],{"class":5341},"        \u002F\u002F Додавання метаданих до помилки\n",[5264,19599,19600,19603,19605,19608],{"class":5266,"line":5428},[5264,19601,19602],{"class":5314},"        error",[5264,19604,7316],{"class":5270},[5264,19606,19607],{"class":5611},"'metadata'",[5264,19609,19610],{"class":5270},"] = {\n",[5264,19612,19613,19616,19619,19621,19624,19626,19628],{"class":5266,"line":5781},[5264,19614,19615],{"class":5314},"          controller:",[5264,19617,19618],{"class":5314}," context",[5264,19620,5707],{"class":5270},[5264,19622,19623],{"class":5274},"getClass",[5264,19625,5902],{"class":5270},[5264,19627,7627],{"class":5314},[5264,19629,5865],{"class":5270},[5264,19631,19632,19635,19637,19639,19642,19644,19646],{"class":5266,"line":5804},[5264,19633,19634],{"class":5314},"          handler:",[5264,19636,19618],{"class":5314},[5264,19638,5707],{"class":5270},[5264,19640,19641],{"class":5274},"getHandler",[5264,19643,5902],{"class":5270},[5264,19645,7627],{"class":5314},[5264,19647,5865],{"class":5270},[5264,19649,19650,19652,19654,19656,19658],{"class":5266,"line":5809},[5264,19651,11143],{"class":5314},[5264,19653,5745],{"class":5314},[5264,19655,5707],{"class":5270},[5264,19657,5936],{"class":5314},[5264,19659,5865],{"class":5270},[5264,19661,19662,19664,19666,19668,19670],{"class":5266,"line":5815},[5264,19663,11156],{"class":5314},[5264,19665,5745],{"class":5314},[5264,19667,5707],{"class":5270},[5264,19669,5921],{"class":5314},[5264,19671,5865],{"class":5270},[5264,19673,19674,19677,19679,19681,19683,19685,19687],{"class":5266,"line":5835},[5264,19675,19676],{"class":5314},"          userId:",[5264,19678,5745],{"class":5314},[5264,19680,5707],{"class":5270},[5264,19682,8937],{"class":5314},[5264,19684,8532],{"class":5270},[5264,19686,10284],{"class":5314},[5264,19688,5865],{"class":5270},[5264,19690,19691],{"class":5266,"line":5840},[5264,19692,8136],{"class":5270},[5264,19694,19695],{"class":5266,"line":5846},[5264,19696,19697],{"class":5270},"        \n",[5264,19699,19700,19703,19705],{"class":5266,"line":5857},[5264,19701,19702],{"class":5284},"        throw",[5264,19704,6121],{"class":5314},[5264,19706,5615],{"class":5270},[5264,19708,19709],{"class":5266,"line":5868},[5264,19710,10437],{"class":5270},[5264,19712,19713],{"class":5266,"line":5879},[5264,19714,12136],{"class":5270},[5264,19716,19717],{"class":5266,"line":5890},[5264,19718,5425],{"class":5270},[5264,19720,19721],{"class":5266,"line":5911},[5264,19722,5431],{"class":5270},[5264,19724,19725],{"class":5266,"line":5926},[5264,19726,5473],{"emptyLinePlaceholder":5472},[5264,19728,19729],{"class":5266,"line":5941},[5264,19730,19731],{"class":5341},"\u002F\u002F В exception filter витягуйте метадані\n",[5264,19733,19734,19736,19739,19741,19743,19745,19747],{"class":5266,"line":5963},[5264,19735,18815],{"class":5288},[5264,19737,19738],{"class":5698}," metadata",[5264,19740,5702],{"class":5270},[5264,19742,5315],{"class":5314},[5264,19744,7316],{"class":5270},[5264,19746,19607],{"class":5611},[5264,19748,19749],{"class":5270},"];\n",[5264,19751,19752,19755,19757,19760,19762,19764,19766,19769],{"class":5266,"line":5969},[5264,19753,19754],{"class":5314},"Sentry",[5264,19756,5707],{"class":5270},[5264,19758,19759],{"class":5274},"setContext",[5264,19761,5311],{"class":5270},[5264,19763,11136],{"class":5611},[5264,19765,5324],{"class":5270},[5264,19767,19768],{"class":5314},"metadata",[5264,19770,6000],{"class":5270},[5201,19772,19774],{"id":19773},"підсумок","Підсумок",[5084,19776,19777,19826,19870,19914,19966,19999,20067,20125],{},[5087,19778,19781,19790,19795],{"icon":19779,"title":19780},"i-lucide-check-circle","🎯 ValidationExceptionFilter",[5206,19782,19783,19784,19786,19787,19789],{},"Обробляє ",[5102,19785,5448],{}," з помилками ",[5102,19788,5154],{},". Форматує список полів з constraints у структурований JSON. Групує помилки за полями для зручності відображення у формах.",[5206,19791,19792],{},[5144,19793,19794],{},"Приклад:",[5254,19796,19798],{"className":5256,"code":19797,"language":5259,"meta":5260,"style":5260},"@Catch(BadRequestException)\nexport class ValidationExceptionFilter { \u002F* ... *\u002F }\n",[5102,19799,19800,19812],{"__ignoreMap":5260},[5264,19801,19802,19804,19806,19808,19810],{"class":5266,"line":5267},[5264,19803,5271],{"class":5270},[5264,19805,5275],{"class":5274},[5264,19807,5311],{"class":5270},[5264,19809,5448],{"class":5314},[5264,19811,5451],{"class":5270},[5264,19813,19814,19816,19818,19820,19822,19824],{"class":5266,"line":5281},[5264,19815,5285],{"class":5284},[5264,19817,5289],{"class":5288},[5264,19819,5460],{"class":5292},[5264,19821,5463],{"class":5270},[5264,19823,5364],{"class":5341},[5264,19825,5367],{"class":5270},[5087,19827,19829,19835,19839],{"icon":2821,"title":19828},"💾 DatabaseExceptionFilter",[5206,19830,19831,19832,19834],{},"Трансформує помилки TypeORM\u002FPrisma (",[5102,19833,5484],{},") у зрозумілі HTTP-відповіді. Мапить коди помилок PostgreSQL (23505 → 409 Conflict). Приховує SQL-деталі від клієнта.",[5206,19836,19837],{},[5144,19838,19794],{},[5254,19840,19842],{"className":5256,"code":19841,"language":5259,"meta":5260,"style":5260},"@Catch(QueryFailedError)\nexport class DatabaseExceptionFilter { \u002F* ... *\u002F }\n",[5102,19843,19844,19856],{"__ignoreMap":5260},[5264,19845,19846,19848,19850,19852,19854],{"class":5266,"line":5267},[5264,19847,5271],{"class":5270},[5264,19849,5275],{"class":5274},[5264,19851,5311],{"class":5270},[5264,19853,5484],{"class":5314},[5264,19855,5451],{"class":5270},[5264,19857,19858,19860,19862,19864,19866,19868],{"class":5266,"line":5281},[5264,19859,5285],{"class":5284},[5264,19861,5289],{"class":5288},[5264,19863,5495],{"class":5292},[5264,19865,5463],{"class":5270},[5264,19867,5364],{"class":5341},[5264,19869,5367],{"class":5270},[5087,19871,19873,19876,19880],{"icon":1348,"title":19872},"📡 Sentry Integration",[5206,19874,19875],{},"Автоматична відправка 5xx помилок у Sentry з контекстом запиту, користувача, тегами. Додавання Breadcrumbs через interceptor для трейсингу виконання. Збагачення помилок метаданими.",[5206,19877,19878],{},[5144,19879,19794],{},[5254,19881,19883],{"className":5256,"code":19882,"language":5259,"meta":5260,"style":5260},"Sentry.captureException(error, { extra: { userId, url } });\n",[5102,19884,19885],{"__ignoreMap":5260},[5264,19886,19887,19889,19891,19893,19895,19897,19899,19902,19904,19907,19909,19911],{"class":5266,"line":5267},[5264,19888,19754],{"class":5314},[5264,19890,5707],{"class":5270},[5264,19892,11473],{"class":5274},[5264,19894,5311],{"class":5270},[5264,19896,6106],{"class":5314},[5264,19898,6315],{"class":5270},[5264,19900,19901],{"class":5314},"extra:",[5264,19903,5463],{"class":5270},[5264,19905,19906],{"class":5314},"userId",[5264,19908,5324],{"class":5270},[5264,19910,5921],{"class":5314},[5264,19912,19913],{"class":5270}," } });\n",[5087,19915,19917,19927,19931],{"icon":4221,"title":19916},"⏱️ TimeoutExceptionFilter",[5206,19918,19783,19919,5129,19921,19923,19924,5707],{},[5102,19920,12207],{},[5102,19922,12248],{}," з RxJS. Повертає 408 Request Timeout з підказками для клієнта. Використовується з ",[5102,19925,19926],{},"TimeoutInterceptor",[5206,19928,19929],{},[5144,19930,19794],{},[5254,19932,19934],{"className":5256,"code":19933,"language":5259,"meta":5260,"style":5260},"@Catch(TimeoutError, RequestTimeoutException)\nexport class TimeoutExceptionFilter { \u002F* ... *\u002F }\n",[5102,19935,19936,19952],{"__ignoreMap":5260},[5264,19937,19938,19940,19942,19944,19946,19948,19950],{"class":5266,"line":5267},[5264,19939,5271],{"class":5270},[5264,19941,5275],{"class":5274},[5264,19943,5311],{"class":5270},[5264,19945,12248],{"class":5314},[5264,19947,5324],{"class":5270},[5264,19949,12207],{"class":5314},[5264,19951,5451],{"class":5270},[5264,19953,19954,19956,19958,19960,19962,19964],{"class":5266,"line":5281},[5264,19955,5285],{"class":5284},[5264,19957,5289],{"class":5288},[5264,19959,12285],{"class":5292},[5264,19961,5463],{"class":5270},[5264,19963,5364],{"class":5341},[5264,19965,5367],{"class":5270},[5087,19967,19969,19972,19976],{"icon":4068,"title":19968},"🔒 UnauthorizedExceptionFilter",[5206,19970,19971],{},"Спеціалізована обробка 401 помилок. Додає WWW-Authenticate заголовок. Логує спроби несанкціонованого доступу з IP та User-Agent. Надає action hints для логіну\u002Fреєстрації.",[5206,19973,19974],{},[5144,19975,19794],{},[5254,19977,19979],{"className":5256,"code":19978,"language":5259,"meta":5260,"style":5260},"response.setHeader('WWW-Authenticate', 'Bearer realm=\"api\"');\n",[5102,19980,19981],{"__ignoreMap":5260},[5264,19982,19983,19985,19987,19989,19991,19993,19995,19997],{"class":5266,"line":5267},[5264,19984,18955],{"class":5314},[5264,19986,5707],{"class":5270},[5264,19988,13182],{"class":5274},[5264,19990,5311],{"class":5270},[5264,19992,13187],{"class":5611},[5264,19994,5324],{"class":5270},[5264,19996,13192],{"class":5611},[5264,19998,6000],{"class":5270},[5087,20000,20002,20011,20015],{"icon":943,"title":20001},"🧩 Filter Composition",[5206,20003,20004,20005,20007,20008,20010],{},"Комбінування кількох filters через ",[5102,20006,10516],{}," токен. Порядок виконання: специфічний → загальний. Catch-all filter (",[5102,20009,14166],{},") реєструється останнім для обробки необроблених помилок.",[5206,20012,20013],{},[5144,20014,19794],{},[5254,20016,20018],{"className":5256,"code":20017,"language":5259,"meta":5260,"style":5260},"{ provide: APP_FILTER, useClass: ValidationExceptionFilter },\n{ provide: APP_FILTER, useClass: SentryExceptionFilter }, \u002F\u002F Останній\n",[5102,20019,20020,20044],{"__ignoreMap":5260},[5264,20021,20022,20025,20029,20031,20033,20035,20038,20040,20042],{"class":5266,"line":5267},[5264,20023,20024],{"class":5270},"{ ",[5264,20026,20028],{"class":20027},"s5IvJ","provide",[5264,20030,5318],{"class":5270},[5264,20032,10516],{"class":5698},[5264,20034,5324],{"class":5270},[5264,20036,20037],{"class":20027},"useClass",[5264,20039,5318],{"class":5270},[5264,20041,5104],{"class":5314},[5264,20043,12817],{"class":5270},[5264,20045,20046,20048,20050,20052,20054,20056,20058,20060,20062,20064],{"class":5266,"line":5281},[5264,20047,20024],{"class":5270},[5264,20049,20028],{"class":20027},[5264,20051,5318],{"class":5270},[5264,20053,10516],{"class":5698},[5264,20055,5324],{"class":5270},[5264,20057,20037],{"class":20027},[5264,20059,5318],{"class":5270},[5264,20061,10845],{"class":5314},[5264,20063,14077],{"class":5270},[5264,20065,20066],{"class":5341},"\u002F\u002F Останній\n",[5087,20068,20071,20080,20084],{"icon":20069,"title":20070},"i-lucide-bar-chart","📊 Datadog APM",[5206,20072,20073,20074,5324,20076,20079],{},"Інтеграція з Datadog для APM (Application Performance Monitoring). Додавання тегів до span: ",[5102,20075,15353],{},[5102,20077,20078],{},"http.status_code",". Логування з trace_id та span_id для кореляції.",[5206,20081,20082],{},[5144,20083,19794],{},[5254,20085,20087],{"className":5256,"code":20086,"language":5259,"meta":5260,"style":5260},"span.setTag('error', true);\nspan.setTag('http.status_code', 500);\n",[5102,20088,20089,20107],{"__ignoreMap":5260},[5264,20090,20091,20093,20095,20097,20099,20101,20103,20105],{"class":5266,"line":5267},[5264,20092,5264],{"class":5314},[5264,20094,5707],{"class":5270},[5264,20096,11343],{"class":5274},[5264,20098,5311],{"class":5270},[5264,20100,11431],{"class":5611},[5264,20102,5324],{"class":5270},[5264,20104,14925],{"class":5288},[5264,20106,6000],{"class":5270},[5264,20108,20109,20111,20113,20115,20117,20119,20121,20123],{"class":5266,"line":5281},[5264,20110,5264],{"class":5314},[5264,20112,5707],{"class":5270},[5264,20114,11343],{"class":5274},[5264,20116,5311],{"class":5270},[5264,20118,11348],{"class":5611},[5264,20120,5324],{"class":5270},[5264,20122,9130],{"class":6311},[5264,20124,6000],{"class":5270},[5087,20126,20129,20135,20139],{"icon":20127,"title":20128},"i-lucide-flask-conical","🧪 Testing Filters",[5206,20130,20131,20132,20134],{},"Unit-тести з мокуванням ",[5102,20133,5332],{},". E2E-тести для перевірки композиції filters. Тестування mapping помилок БД, форматування валідації, інтеграції з Sentry.",[5206,20136,20137],{},[5144,20138,19794],{},[5254,20140,20142],{"className":5256,"code":20141,"language":5259,"meta":5260,"style":5260},"expect(mockStatus).toHaveBeenCalledWith(409);\nexpect(mockJson).toHaveBeenCalledWith({ message: 'Duplicate' });\n",[5102,20143,20144,20162],{"__ignoreMap":5260},[5264,20145,20146,20148,20150,20152,20154,20156,20158,20160],{"class":5266,"line":5267},[5264,20147,17149],{"class":5274},[5264,20149,5311],{"class":5270},[5264,20151,15879],{"class":5314},[5264,20153,5989],{"class":5270},[5264,20155,15884],{"class":5274},[5264,20157,5311],{"class":5270},[5264,20159,9180],{"class":6311},[5264,20161,6000],{"class":5270},[5264,20163,20164,20166,20168,20170,20172,20174,20176,20178,20181],{"class":5266,"line":5281},[5264,20165,17149],{"class":5274},[5264,20167,5311],{"class":5270},[5264,20169,15899],{"class":5314},[5264,20171,5989],{"class":5270},[5264,20173,15884],{"class":5274},[5264,20175,15721],{"class":5270},[5264,20177,6071],{"class":5314},[5264,20179,20180],{"class":5611}," 'Duplicate'",[5264,20182,15729],{"class":5270},[5201,20184,20186],{"id":20185},"часті-запитання-faq","Часті запитання (FAQ)",[20188,20189,20190,20413,20514,20744,21143,21338,21662,22134],"accordion",{},[20191,20192,20194,20197,20335,20341],"accordion-item",{"title":20193},"Як витягнути назву поля з помилки unique constraint PostgreSQL?",[5206,20195,20196],{},"Використовуйте regex для парсингу назви constraint:",[5254,20198,20200],{"className":5256,"code":20199,"language":5259,"meta":5260,"style":5260},"private extractFieldName(constraint: string): string {\n  \u002F\u002F constraint format: \"table_field_key\"\n  const match = constraint?.match(\u002F^(.+?)_(.+?)_key$\u002F);\n  return match ? match[2] : 'field';\n}\n\n\u002F\u002F Використання\nconst field = this.extractFieldName('users_email_key'); \u002F\u002F \"email\"\n",[5102,20201,20202,20224,20229,20275,20296,20300,20304,20309],{"__ignoreMap":5260},[5264,20203,20204,20207,20210,20212,20214,20216,20218,20220,20222],{"class":5266,"line":5267},[5264,20205,20206],{"class":5314},"private",[5264,20208,20209],{"class":5274}," extractFieldName",[5264,20211,5311],{"class":5270},[5264,20213,7859],{"class":5314},[5264,20215,5318],{"class":5270},[5264,20217,6286],{"class":5314},[5264,20219,6031],{"class":5270},[5264,20221,6286],{"class":5314},[5264,20223,5302],{"class":5270},[5264,20225,20226],{"class":5266,"line":5281},[5264,20227,20228],{"class":5341},"  \u002F\u002F constraint format: \"table_field_key\"\n",[5264,20230,20231,20233,20235,20237,20239,20241,20243,20245,20247,20249,20251,20253,20255,20257,20259,20261,20263,20265,20267,20269,20271,20273],{"class":5266,"line":5305},[5264,20232,10790],{"class":5288},[5264,20234,8525],{"class":5698},[5264,20236,5702],{"class":5270},[5264,20238,7859],{"class":5314},[5264,20240,8532],{"class":5270},[5264,20242,8535],{"class":5274},[5264,20244,5311],{"class":5270},[5264,20246,6540],{"class":8540},[5264,20248,8544],{"class":8543},[5264,20250,5311],{"class":8547},[5264,20252,5707],{"class":8540},[5264,20254,8553],{"class":8552},[5264,20256,8556],{"class":8547},[5264,20258,8559],{"class":8540},[5264,20260,5311],{"class":8547},[5264,20262,5707],{"class":8540},[5264,20264,8553],{"class":8552},[5264,20266,8556],{"class":8547},[5264,20268,8570],{"class":8540},[5264,20270,8573],{"class":8543},[5264,20272,6540],{"class":8540},[5264,20274,6000],{"class":5270},[5264,20276,20277,20280,20282,20284,20286,20288,20290,20292,20294],{"class":5266,"line":5338},[5264,20278,20279],{"class":5284},"  return",[5264,20281,8525],{"class":5314},[5264,20283,8591],{"class":5270},[5264,20285,8535],{"class":5314},[5264,20287,7316],{"class":5270},[5264,20289,8598],{"class":6311},[5264,20291,8601],{"class":5270},[5264,20293,8604],{"class":5611},[5264,20295,5615],{"class":5270},[5264,20297,20298],{"class":5266,"line":5345},[5264,20299,5431],{"class":5270},[5264,20301,20302],{"class":5266,"line":5370},[5264,20303,5473],{"emptyLinePlaceholder":5472},[5264,20305,20306],{"class":5266,"line":5394},[5264,20307,20308],{"class":5341},"\u002F\u002F Використання\n",[5264,20310,20311,20313,20315,20317,20319,20321,20324,20326,20329,20332],{"class":5266,"line":5416},[5264,20312,18815],{"class":5288},[5264,20314,7263],{"class":5698},[5264,20316,5702],{"class":5270},[5264,20318,7001],{"class":5288},[5264,20320,5707],{"class":5270},[5264,20322,20323],{"class":5274},"extractFieldName",[5264,20325,5311],{"class":5270},[5264,20327,20328],{"class":5611},"'users_email_key'",[5264,20330,20331],{"class":5270},"); ",[5264,20333,20334],{"class":5341},"\u002F\u002F \"email\"\n",[5206,20336,20337,20338,5212],{},"Альтернативно, витягуйте з ",[5102,20339,20340],{},"exception.message",[5254,20342,20344],{"className":5256,"code":20343,"language":5259,"meta":5260,"style":5260},"const match = exception.message.match(\u002FKey \\((.+?)\\)=\u002F);\nconst field = match ? match[1] : 'unknown';\n",[5102,20345,20346,20388],{"__ignoreMap":5260},[5264,20347,20348,20350,20352,20354,20356,20358,20360,20362,20364,20366,20369,20372,20374,20376,20378,20380,20383,20386],{"class":5266,"line":5267},[5264,20349,18815],{"class":5288},[5264,20351,8525],{"class":5698},[5264,20353,5702],{"class":5270},[5264,20355,5315],{"class":5314},[5264,20357,5707],{"class":5270},[5264,20359,5830],{"class":5314},[5264,20361,5707],{"class":5270},[5264,20363,8535],{"class":5274},[5264,20365,5311],{"class":5270},[5264,20367,20368],{"class":8540},"\u002FKey ",[5264,20370,20371],{"class":9144},"\\(",[5264,20373,5311],{"class":8547},[5264,20375,5707],{"class":8540},[5264,20377,8553],{"class":8552},[5264,20379,8556],{"class":8547},[5264,20381,20382],{"class":9144},"\\)",[5264,20384,20385],{"class":8540},"=\u002F",[5264,20387,6000],{"class":5270},[5264,20389,20390,20392,20394,20396,20398,20400,20402,20404,20406,20408,20411],{"class":5266,"line":5281},[5264,20391,18815],{"class":5288},[5264,20393,7263],{"class":5698},[5264,20395,5702],{"class":5270},[5264,20397,8535],{"class":5314},[5264,20399,8591],{"class":5270},[5264,20401,8535],{"class":5314},[5264,20403,7316],{"class":5270},[5264,20405,8726],{"class":6311},[5264,20407,8601],{"class":5270},[5264,20409,20410],{"class":5611},"'unknown'",[5264,20412,5615],{"class":5270},[20191,20414,20416,20421,20440,20508],{"title":20415},"Чи потрібно логувати всі помилки в exception filter?",[5206,20417,20418],{},[5144,20419,20420],{},"Залежить від статус-коду:",[5092,20422,20423,20432],{},[5095,20424,20425,20428,20429,20431],{},[5144,20426,20427],{},"4xx (Client Errors)",": логувати на рівні ",[5102,20430,10212],{}," або не логувати взагалі (це очікувані помилки)",[5095,20433,20434,20428,20437,20439],{},[5144,20435,20436],{},"5xx (Server Errors)",[5102,20438,6106],{}," з повним стеком та контекстом",[5254,20441,20443],{"className":5256,"code":20442,"language":5259,"meta":5260,"style":5260},"const logLevel = status >= 500 ? 'error' : status >= 400 ? 'warn' : 'log';\nthis.logger[logLevel]('Exception occurred', { \u002F* ... *\u002F });\n",[5102,20444,20445,20484],{"__ignoreMap":5260},[5264,20446,20447,20449,20452,20454,20456,20458,20460,20462,20464,20466,20468,20470,20472,20474,20477,20479,20482],{"class":5266,"line":5267},[5264,20448,18815],{"class":5288},[5264,20450,20451],{"class":5698}," logLevel",[5264,20453,5702],{"class":5270},[5264,20455,5982],{"class":5314},[5264,20457,11093],{"class":5270},[5264,20459,9130],{"class":6311},[5264,20461,8591],{"class":5270},[5264,20463,11431],{"class":5611},[5264,20465,11434],{"class":5270},[5264,20467,5982],{"class":5314},[5264,20469,11093],{"class":5270},[5264,20471,6627],{"class":6311},[5264,20473,8591],{"class":5270},[5264,20475,20476],{"class":5611},"'warn'",[5264,20478,11434],{"class":5270},[5264,20480,20481],{"class":5611},"'log'",[5264,20483,5615],{"class":5270},[5264,20485,20486,20488,20490,20492,20494,20497,20500,20502,20504,20506],{"class":5266,"line":5281},[5264,20487,7001],{"class":5288},[5264,20489,5707],{"class":5270},[5264,20491,7726],{"class":5314},[5264,20493,7316],{"class":5270},[5264,20495,20496],{"class":5314},"logLevel",[5264,20498,20499],{"class":5270},"](",[5264,20501,15093],{"class":5611},[5264,20503,6315],{"class":5270},[5264,20505,5364],{"class":5341},[5264,20507,15729],{"class":5270},[5206,20509,20510,20513],{},[5144,20511,20512],{},"Рекомендація:"," логуйте 401\u002F403 для виявлення атак, але не логуйте 404 (зайвий шум).",[20191,20515,20517,20520],{"title":20516},"Як тестувати exception filter з інтеграцією Sentry?",[5206,20518,20519],{},"Мокуйте Sentry у тестах:",[5254,20521,20523],{"className":5256,"code":20522,"language":5259,"meta":5260,"style":5260},"jest.mock('@sentry\u002Fnode', () => ({\n  captureException: jest.fn(),\n  withScope: jest.fn(callback => callback({\n    setExtra: jest.fn(),\n    setUser: jest.fn(),\n    setTag: jest.fn(),\n  })),\n}));\n\nimport * as Sentry from '@sentry\u002Fnode';\n\nit('should send error to Sentry', () => {\n  const exception = new Error('Test error');\n  \n  filter.catch(exception, host);\n  \n  expect(Sentry.captureException).toHaveBeenCalledWith(exception);\n});\n",[5102,20524,20525,20545,20559,20582,20595,20608,20621,20626,20631,20635,20651,20655,20671,20690,20694,20713,20717,20740],{"__ignoreMap":5260},[5264,20526,20527,20529,20531,20534,20536,20539,20541,20543],{"class":5266,"line":5267},[5264,20528,15691],{"class":5314},[5264,20530,5707],{"class":5270},[5264,20532,20533],{"class":5274},"mock",[5264,20535,5311],{"class":5270},[5264,20537,20538],{"class":5611},"'@sentry\u002Fnode'",[5264,20540,15435],{"class":5270},[5264,20542,12060],{"class":5288},[5264,20544,6112],{"class":5270},[5264,20546,20547,20550,20553,20555,20557],{"class":5266,"line":5281},[5264,20548,20549],{"class":5314},"  captureException:",[5264,20551,20552],{"class":5314}," jest",[5264,20554,5707],{"class":5270},[5264,20556,15696],{"class":5274},[5264,20558,5908],{"class":5270},[5264,20560,20561,20564,20566,20568,20570,20572,20575,20577,20580],{"class":5266,"line":5305},[5264,20562,20563],{"class":5314},"  withScope:",[5264,20565,20552],{"class":5314},[5264,20567,5707],{"class":5270},[5264,20569,15696],{"class":5274},[5264,20571,5311],{"class":5270},[5264,20573,20574],{"class":5314},"callback",[5264,20576,6109],{"class":5288},[5264,20578,20579],{"class":5274}," callback",[5264,20581,7035],{"class":5270},[5264,20583,20584,20587,20589,20591,20593],{"class":5266,"line":5338},[5264,20585,20586],{"class":5314},"    setExtra:",[5264,20588,20552],{"class":5314},[5264,20590,5707],{"class":5270},[5264,20592,15696],{"class":5274},[5264,20594,5908],{"class":5270},[5264,20596,20597,20600,20602,20604,20606],{"class":5266,"line":5345},[5264,20598,20599],{"class":5314},"    setUser:",[5264,20601,20552],{"class":5314},[5264,20603,5707],{"class":5270},[5264,20605,15696],{"class":5274},[5264,20607,5908],{"class":5270},[5264,20609,20610,20613,20615,20617,20619],{"class":5266,"line":5370},[5264,20611,20612],{"class":5314},"    setTag:",[5264,20614,20552],{"class":5314},[5264,20616,5707],{"class":5270},[5264,20618,15696],{"class":5274},[5264,20620,5908],{"class":5270},[5264,20622,20623],{"class":5266,"line":5394},[5264,20624,20625],{"class":5270},"  })),\n",[5264,20627,20628],{"class":5266,"line":5416},[5264,20629,20630],{"class":5270},"}));\n",[5264,20632,20633],{"class":5266,"line":5422},[5264,20634,5473],{"emptyLinePlaceholder":5472},[5264,20636,20637,20639,20641,20643,20645,20647,20649],{"class":5266,"line":5428},[5264,20638,5585],{"class":5284},[5264,20640,10664],{"class":5288},[5264,20642,7825],{"class":5284},[5264,20644,10669],{"class":5314},[5264,20646,10672],{"class":5284},[5264,20648,10675],{"class":5611},[5264,20650,5615],{"class":5270},[5264,20652,20653],{"class":5266,"line":5781},[5264,20654,5473],{"emptyLinePlaceholder":5472},[5264,20656,20657,20660,20662,20665,20667,20669],{"class":5266,"line":5804},[5264,20658,20659],{"class":5274},"it",[5264,20661,5311],{"class":5270},[5264,20663,20664],{"class":5611},"'should send error to Sentry'",[5264,20666,15435],{"class":5270},[5264,20668,12060],{"class":5288},[5264,20670,5302],{"class":5270},[5264,20672,20673,20675,20677,20679,20681,20683,20685,20688],{"class":5266,"line":5809},[5264,20674,10790],{"class":5288},[5264,20676,7745],{"class":5698},[5264,20678,5702],{"class":5270},[5264,20680,7615],{"class":5288},[5264,20682,11461],{"class":5274},[5264,20684,5311],{"class":5270},[5264,20686,20687],{"class":5611},"'Test error'",[5264,20689,6000],{"class":5270},[5264,20691,20692],{"class":5266,"line":5815},[5264,20693,18592],{"class":5270},[5264,20695,20696,20699,20701,20703,20705,20707,20709,20711],{"class":5266,"line":5835},[5264,20697,20698],{"class":5314},"  filter",[5264,20700,5707],{"class":5270},[5264,20702,15855],{"class":5274},[5264,20704,5311],{"class":5270},[5264,20706,5315],{"class":5314},[5264,20708,5324],{"class":5270},[5264,20710,5327],{"class":5314},[5264,20712,6000],{"class":5270},[5264,20714,20715],{"class":5266,"line":5840},[5264,20716,18592],{"class":5270},[5264,20718,20719,20722,20724,20726,20728,20730,20732,20734,20736,20738],{"class":5266,"line":5846},[5264,20720,20721],{"class":5274},"  expect",[5264,20723,5311],{"class":5270},[5264,20725,19754],{"class":5314},[5264,20727,5707],{"class":5270},[5264,20729,11473],{"class":5314},[5264,20731,5989],{"class":5270},[5264,20733,15884],{"class":5274},[5264,20735,5311],{"class":5270},[5264,20737,5315],{"class":5314},[5264,20739,6000],{"class":5270},[5264,20741,20742],{"class":5266,"line":5857},[5264,20743,14485],{"class":5270},[20191,20745,20747,20750],{"title":20746},"Як обробити помилки зовнішніх API (fetch, axios)?",[5206,20748,20749],{},"Створіть спеціалізований filter:",[5254,20751,20753],{"className":5256,"code":20752,"language":5259,"meta":5260,"style":5260},"export class ExternalApiException extends HttpException {\n  constructor(\n    public readonly service: string,\n    public readonly statusCode: number,\n    message: string,\n  ) {\n    super({ service, statusCode, message }, HttpStatus.BAD_GATEWAY);\n  }\n}\n\n@Catch(ExternalApiException)\nexport class ExternalApiExceptionFilter implements ExceptionFilter {\n  catch(exception: ExternalApiException, host: ArgumentsHost) {\n    const response = host.switchToHttp().getResponse();\n    \n    response.status(502).json({\n      statusCode: 502,\n      error: 'External Service Error',\n      message: `${exception.service} service unavailable`,\n      originalStatus: exception.statusCode,\n      timestamp: new Date().toISOString(),\n    });\n  }\n}\n\n\u002F\u002F Використання у сервісі\ntry {\n  const data = await axios.get('https:\u002F\u002Fexternal-api.com\u002Fdata');\n  return data.data;\n} catch (error) {\n  throw new ExternalApiException('ExternalAPI', error.response?.status, error.message);\n}\n",[5102,20754,20755,20772,20778,20794,20809,20820,20825,20854,20858,20862,20866,20879,20894,20916,20936,20940,20959,20968,20977,20998,21011,21025,21029,21033,21037,21041,21046,21053,21078,21091,21103,21139],{"__ignoreMap":5260},[5264,20756,20757,20759,20761,20764,20767,20770],{"class":5266,"line":5267},[5264,20758,5285],{"class":5284},[5264,20760,5289],{"class":5288},[5264,20762,20763],{"class":5292}," ExternalApiException",[5264,20765,20766],{"class":5288}," extends",[5264,20768,20769],{"class":5292}," HttpException",[5264,20771,5302],{"class":5270},[5264,20773,20774,20776],{"class":5266,"line":5281},[5264,20775,8806],{"class":5288},[5264,20777,8001],{"class":5270},[5264,20779,20780,20783,20785,20788,20790,20792],{"class":5266,"line":5305},[5264,20781,20782],{"class":5288},"    public",[5264,20784,7607],{"class":5288},[5264,20786,20787],{"class":5314}," service",[5264,20789,5318],{"class":5270},[5264,20791,6286],{"class":5292},[5264,20793,5865],{"class":5270},[5264,20795,20796,20798,20800,20803,20805,20807],{"class":5266,"line":5338},[5264,20797,20782],{"class":5288},[5264,20799,7607],{"class":5288},[5264,20801,20802],{"class":5314}," statusCode",[5264,20804,5318],{"class":5270},[5264,20806,6395],{"class":5292},[5264,20808,5865],{"class":5270},[5264,20810,20811,20814,20816,20818],{"class":5266,"line":5345},[5264,20812,20813],{"class":5314},"    message",[5264,20815,5318],{"class":5270},[5264,20817,6286],{"class":5292},[5264,20819,5865],{"class":5270},[5264,20821,20822],{"class":5266,"line":5370},[5264,20823,20824],{"class":5270},"  ) {\n",[5264,20826,20827,20830,20832,20835,20837,20839,20841,20843,20845,20847,20849,20852],{"class":5266,"line":5394},[5264,20828,20829],{"class":5288},"    super",[5264,20831,15721],{"class":5270},[5264,20833,20834],{"class":5314},"service",[5264,20836,5324],{"class":5270},[5264,20838,7879],{"class":5314},[5264,20840,5324],{"class":5270},[5264,20842,5830],{"class":5314},[5264,20844,14077],{"class":5270},[5264,20846,7524],{"class":5314},[5264,20848,5707],{"class":5270},[5264,20850,20851],{"class":5698},"BAD_GATEWAY",[5264,20853,6000],{"class":5270},[5264,20855,20856],{"class":5266,"line":5416},[5264,20857,5425],{"class":5270},[5264,20859,20860],{"class":5266,"line":5422},[5264,20861,5431],{"class":5270},[5264,20863,20864],{"class":5266,"line":5428},[5264,20865,5473],{"emptyLinePlaceholder":5472},[5264,20867,20868,20870,20872,20874,20877],{"class":5266,"line":5781},[5264,20869,5271],{"class":5270},[5264,20871,5275],{"class":5274},[5264,20873,5311],{"class":5270},[5264,20875,20876],{"class":5314},"ExternalApiException",[5264,20878,5451],{"class":5270},[5264,20880,20881,20883,20885,20888,20890,20892],{"class":5266,"line":5804},[5264,20882,5285],{"class":5284},[5264,20884,5289],{"class":5288},[5264,20886,20887],{"class":5292}," ExternalApiExceptionFilter",[5264,20889,5296],{"class":5288},[5264,20891,5299],{"class":5292},[5264,20893,5302],{"class":5270},[5264,20895,20896,20898,20900,20902,20904,20906,20908,20910,20912,20914],{"class":5266,"line":5809},[5264,20897,5308],{"class":5274},[5264,20899,5311],{"class":5270},[5264,20901,5315],{"class":5314},[5264,20903,5318],{"class":5270},[5264,20905,20876],{"class":5292},[5264,20907,5324],{"class":5270},[5264,20909,5327],{"class":5314},[5264,20911,5318],{"class":5270},[5264,20913,5332],{"class":5292},[5264,20915,5335],{"class":5270},[5264,20917,20918,20920,20922,20924,20926,20928,20930,20932,20934],{"class":5266,"line":5815},[5264,20919,5695],{"class":5288},[5264,20921,5720],{"class":5698},[5264,20923,5702],{"class":5270},[5264,20925,5327],{"class":5314},[5264,20927,5707],{"class":5270},[5264,20929,5710],{"class":5274},[5264,20931,5902],{"class":5270},[5264,20933,5730],{"class":5274},[5264,20935,5713],{"class":5270},[5264,20937,20938],{"class":5266,"line":5835},[5264,20939,8909],{"class":5270},[5264,20941,20942,20944,20946,20948,20950,20953,20955,20957],{"class":5266,"line":5840},[5264,20943,5977],{"class":5314},[5264,20945,5707],{"class":5270},[5264,20947,5982],{"class":5274},[5264,20949,5311],{"class":5270},[5264,20951,20952],{"class":6311},"502",[5264,20954,5989],{"class":5270},[5264,20956,5992],{"class":5274},[5264,20958,7035],{"class":5270},[5264,20960,20961,20963,20966],{"class":5266,"line":5846},[5264,20962,5860],{"class":5314},[5264,20964,20965],{"class":6311}," 502",[5264,20967,5865],{"class":5270},[5264,20969,20970,20972,20975],{"class":5266,"line":5857},[5264,20971,5871],{"class":5314},[5264,20973,20974],{"class":5611}," 'External Service Error'",[5264,20976,5865],{"class":5270},[5264,20978,20979,20981,20983,20985,20987,20989,20991,20993,20996],{"class":5266,"line":5868},[5264,20980,5882],{"class":5314},[5264,20982,7059],{"class":5611},[5264,20984,7062],{"class":5288},[5264,20986,5315],{"class":5314},[5264,20988,5707],{"class":7068},[5264,20990,20834],{"class":5314},[5264,20992,7084],{"class":5288},[5264,20994,20995],{"class":5611}," service unavailable`",[5264,20997,5865],{"class":5270},[5264,20999,21000,21003,21005,21007,21009],{"class":5266,"line":5879},[5264,21001,21002],{"class":5314},"      originalStatus:",[5264,21004,7745],{"class":5314},[5264,21006,5707],{"class":5270},[5264,21008,7879],{"class":5314},[5264,21010,5865],{"class":5270},[5264,21012,21013,21015,21017,21019,21021,21023],{"class":5266,"line":5890},[5264,21014,5893],{"class":5314},[5264,21016,5896],{"class":5288},[5264,21018,5899],{"class":5274},[5264,21020,5902],{"class":5270},[5264,21022,5905],{"class":5274},[5264,21024,5908],{"class":5270},[5264,21026,21027],{"class":5266,"line":5911},[5264,21028,7129],{"class":5270},[5264,21030,21031],{"class":5266,"line":5926},[5264,21032,5425],{"class":5270},[5264,21034,21035],{"class":5266,"line":5941},[5264,21036,5431],{"class":5270},[5264,21038,21039],{"class":5266,"line":5963},[5264,21040,5473],{"emptyLinePlaceholder":5472},[5264,21042,21043],{"class":5266,"line":5969},[5264,21044,21045],{"class":5341},"\u002F\u002F Використання у сервісі\n",[5264,21047,21048,21051],{"class":5266,"line":5974},[5264,21049,21050],{"class":5284},"try",[5264,21052,5302],{"class":5270},[5264,21054,21055,21057,21060,21062,21064,21067,21069,21071,21073,21076],{"class":5266,"line":6003},[5264,21056,10790],{"class":5288},[5264,21058,21059],{"class":5698}," data",[5264,21061,5702],{"class":5270},[5264,21063,10798],{"class":5284},[5264,21065,21066],{"class":5314}," axios",[5264,21068,5707],{"class":5270},[5264,21070,10312],{"class":5274},[5264,21072,5311],{"class":5270},[5264,21074,21075],{"class":5611},"'https:\u002F\u002Fexternal-api.com\u002Fdata'",[5264,21077,6000],{"class":5270},[5264,21079,21080,21082,21084,21086,21089],{"class":5266,"line":6008},[5264,21081,20279],{"class":5284},[5264,21083,21059],{"class":5314},[5264,21085,5707],{"class":5270},[5264,21087,21088],{"class":5314},"data",[5264,21090,5615],{"class":5270},[5264,21092,21093,21095,21097,21099,21101],{"class":5266,"line":6013},[5264,21094,13925],{"class":5270},[5264,21096,15855],{"class":5284},[5264,21098,5146],{"class":5270},[5264,21100,6106],{"class":5314},[5264,21102,5335],{"class":5270},[5264,21104,21105,21108,21110,21112,21114,21117,21119,21121,21123,21125,21127,21129,21131,21133,21135,21137],{"class":5266,"line":6039},[5264,21106,21107],{"class":5284},"  throw",[5264,21109,5896],{"class":5288},[5264,21111,20763],{"class":5274},[5264,21113,5311],{"class":5270},[5264,21115,21116],{"class":5611},"'ExternalAPI'",[5264,21118,5324],{"class":5270},[5264,21120,6106],{"class":5314},[5264,21122,5707],{"class":5270},[5264,21124,18955],{"class":5314},[5264,21126,8532],{"class":5270},[5264,21128,5982],{"class":5314},[5264,21130,5324],{"class":5270},[5264,21132,6106],{"class":5314},[5264,21134,5707],{"class":5270},[5264,21136,5830],{"class":5314},[5264,21138,6000],{"class":5270},[5264,21140,21141],{"class":5266,"line":6062},[5264,21142,5431],{"class":5270},[20191,21144,21146,21155,21332],{"title":21145},"Чи можна змінити формат відповіді для ValidationPipe глобально?",[5206,21147,21148,21151,21152,5212],{},[5144,21149,21150],{},"Так",", налаштуйте ValidationPipe з кастомним ",[5102,21153,21154],{},"exceptionFactory",[5254,21156,21158],{"className":5256,"code":21157,"language":5259,"meta":5260,"style":5260},"\u002F\u002F main.ts\napp.useGlobalPipes(\n  new ValidationPipe({\n    exceptionFactory: (errors) => {\n      const formattedErrors = errors.map(error => ({\n        field: error.property,\n        value: error.value,\n        errors: Object.values(error.constraints || {}),\n      }));\n\n      return new BadRequestException({\n        statusCode: 400,\n        error: 'Validation Failed',\n        fields: formattedErrors,\n      });\n    },\n  }),\n);\n",[5102,21159,21160,21164,21175,21185,21203,21226,21239,21252,21272,21277,21281,21291,21299,21307,21316,21320,21324,21328],{"__ignoreMap":5260},[5264,21161,21162],{"class":5266,"line":5267},[5264,21163,10640],{"class":5341},[5264,21165,21166,21168,21170,21173],{"class":5266,"line":5281},[5264,21167,11686],{"class":5314},[5264,21169,5707],{"class":5270},[5264,21171,21172],{"class":5274},"useGlobalPipes",[5264,21174,8001],{"class":5270},[5264,21176,21177,21180,21183],{"class":5266,"line":5305},[5264,21178,21179],{"class":5288},"  new",[5264,21181,21182],{"class":5274}," ValidationPipe",[5264,21184,7035],{"class":5270},[5264,21186,21187,21190,21192,21194,21196,21199,21201],{"class":5266,"line":5338},[5264,21188,21189],{"class":5274},"    exceptionFactory",[5264,21191,5212],{"class":5314},[5264,21193,5146],{"class":5270},[5264,21195,6024],{"class":5314},[5264,21197,21198],{"class":5270},") ",[5264,21200,12060],{"class":5288},[5264,21202,5302],{"class":5270},[5264,21204,21205,21207,21210,21212,21214,21216,21218,21220,21222,21224],{"class":5266,"line":5345},[5264,21206,7260],{"class":5288},[5264,21208,21209],{"class":5698}," formattedErrors",[5264,21211,5702],{"class":5270},[5264,21213,6024],{"class":5314},[5264,21215,5707],{"class":5270},[5264,21217,6101],{"class":5274},[5264,21219,5311],{"class":5270},[5264,21221,6106],{"class":5314},[5264,21223,6109],{"class":5288},[5264,21225,6112],{"class":5270},[5264,21227,21228,21231,21233,21235,21237],{"class":5266,"line":5370},[5264,21229,21230],{"class":5314},"        field:",[5264,21232,6121],{"class":5314},[5264,21234,5707],{"class":5270},[5264,21236,6126],{"class":5314},[5264,21238,5865],{"class":5270},[5264,21240,21241,21244,21246,21248,21250],{"class":5266,"line":5394},[5264,21242,21243],{"class":5314},"        value:",[5264,21245,6121],{"class":5314},[5264,21247,5707],{"class":5270},[5264,21249,6141],{"class":5314},[5264,21251,5865],{"class":5270},[5264,21253,21254,21256,21258,21260,21262,21264,21266,21268,21270],{"class":5266,"line":5416},[5264,21255,15940],{"class":5314},[5264,21257,6152],{"class":5314},[5264,21259,5707],{"class":5270},[5264,21261,6157],{"class":5274},[5264,21263,5311],{"class":5270},[5264,21265,6106],{"class":5314},[5264,21267,5707],{"class":5270},[5264,21269,6166],{"class":5314},[5264,21271,6169],{"class":5270},[5264,21273,21274],{"class":5266,"line":5422},[5264,21275,21276],{"class":5270},"      }));\n",[5264,21278,21279],{"class":5266,"line":5428},[5264,21280,5473],{"emptyLinePlaceholder":5472},[5264,21282,21283,21285,21287,21289],{"class":5266,"line":5781},[5264,21284,6065],{"class":5284},[5264,21286,5896],{"class":5288},[5264,21288,15576],{"class":5274},[5264,21290,7035],{"class":5270},[5264,21292,21293,21295,21297],{"class":5266,"line":5804},[5264,21294,15922],{"class":5314},[5264,21296,7042],{"class":6311},[5264,21298,5865],{"class":5270},[5264,21300,21301,21303,21305],{"class":5266,"line":5809},[5264,21302,15931],{"class":5314},[5264,21304,5874],{"class":5611},[5264,21306,5865],{"class":5270},[5264,21308,21309,21312,21314],{"class":5266,"line":5815},[5264,21310,21311],{"class":5314},"        fields:",[5264,21313,21209],{"class":5314},[5264,21315,5865],{"class":5270},[5264,21317,21318],{"class":5266,"line":5835},[5264,21319,11533],{"class":5270},[5264,21321,21322],{"class":5266,"line":5840},[5264,21323,6744],{"class":5270},[5264,21325,21326],{"class":5266,"line":5846},[5264,21327,18937],{"class":5270},[5264,21329,21330],{"class":5266,"line":5857},[5264,21331,6000],{"class":5270},[5206,21333,21334,21335,21337],{},"Тоді ",[5102,21336,5104],{}," отримає вже структуровані помилки.",[20191,21339,21341,21344],{"title":21340},"Як додати requestId для трейсингу запитів?",[5206,21342,21343],{},"Використовуйте middleware для генерації requestId:",[5254,21345,21347],{"className":5256,"code":21346,"language":5259,"meta":5260,"style":5260},"\u002F\u002F request-id.middleware.ts\nimport { Injectable, NestMiddleware } from '@nestjs\u002Fcommon';\nimport { v4 as uuidv4 } from 'uuid';\n\n@Injectable()\nexport class RequestIdMiddleware implements NestMiddleware {\n  use(req: any, res: any, next: () => void) {\n    req.id = uuidv4();\n    res.setHeader('X-Request-Id', req.id);\n    next();\n  }\n}\n\n\u002F\u002F app.module.ts\nexport class AppModule implements NestModule {\n  configure(consumer: MiddlewareConsumer) {\n    consumer.apply(RequestIdMiddleware).forRoutes('*');\n  }\n}\n\n\u002F\u002F В exception filter\nconst errorResponse = {\n  statusCode: status,\n  message: exception.message,\n  requestId: request.id, \u002F\u002F UUID з middleware\n  timestamp: new Date().toISOString(),\n};\n",[5102,21348,21349,21354,21375,21398,21402,21410,21426,21462,21478,21502,21509,21513,21517,21521,21525,21540,21557,21584,21588,21592,21596,21601,21609,21617,21629,21644,21658],{"__ignoreMap":5260},[5264,21350,21351],{"class":5266,"line":5267},[5264,21352,21353],{"class":5341},"\u002F\u002F request-id.middleware.ts\n",[5264,21355,21356,21358,21360,21362,21364,21367,21369,21371,21373],{"class":5266,"line":5281},[5264,21357,5585],{"class":5284},[5264,21359,5463],{"class":5270},[5264,21361,8788],{"class":5314},[5264,21363,5324],{"class":5270},[5264,21365,21366],{"class":5314},"NestMiddleware",[5264,21368,5605],{"class":5270},[5264,21370,5608],{"class":5284},[5264,21372,5612],{"class":5611},[5264,21374,5615],{"class":5270},[5264,21376,21377,21379,21381,21384,21386,21389,21391,21393,21396],{"class":5266,"line":5305},[5264,21378,5585],{"class":5284},[5264,21380,5463],{"class":5270},[5264,21382,21383],{"class":5314},"v4",[5264,21385,7825],{"class":5284},[5264,21387,21388],{"class":5314}," uuidv4",[5264,21390,5605],{"class":5270},[5264,21392,5608],{"class":5284},[5264,21394,21395],{"class":5611}," 'uuid'",[5264,21397,5615],{"class":5270},[5264,21399,21400],{"class":5266,"line":5338},[5264,21401,5473],{"emptyLinePlaceholder":5472},[5264,21403,21404,21406,21408],{"class":5266,"line":5345},[5264,21405,5271],{"class":5270},[5264,21407,8788],{"class":5274},[5264,21409,5278],{"class":5270},[5264,21411,21412,21414,21416,21419,21421,21424],{"class":5266,"line":5370},[5264,21413,5285],{"class":5284},[5264,21415,5289],{"class":5288},[5264,21417,21418],{"class":5292}," RequestIdMiddleware",[5264,21420,5296],{"class":5288},[5264,21422,21423],{"class":5292}," NestMiddleware",[5264,21425,5302],{"class":5270},[5264,21427,21428,21431,21433,21436,21438,21440,21442,21444,21446,21448,21450,21452,21455,21457,21460],{"class":5266,"line":5394},[5264,21429,21430],{"class":5274},"  use",[5264,21432,5311],{"class":5270},[5264,21434,21435],{"class":5314},"req",[5264,21437,5318],{"class":5270},[5264,21439,5791],{"class":5292},[5264,21441,5324],{"class":5270},[5264,21443,17170],{"class":5314},[5264,21445,5318],{"class":5270},[5264,21447,5791],{"class":5292},[5264,21449,5324],{"class":5270},[5264,21451,11853],{"class":5274},[5264,21453,21454],{"class":5270},": () ",[5264,21456,12060],{"class":5288},[5264,21458,21459],{"class":5292}," void",[5264,21461,5335],{"class":5270},[5264,21463,21464,21467,21469,21471,21473,21476],{"class":5266,"line":5416},[5264,21465,21466],{"class":5314},"    req",[5264,21468,5707],{"class":5270},[5264,21470,10284],{"class":5314},[5264,21472,5702],{"class":5270},[5264,21474,21475],{"class":5274},"uuidv4",[5264,21477,5713],{"class":5270},[5264,21479,21480,21483,21485,21487,21489,21492,21494,21496,21498,21500],{"class":5266,"line":5422},[5264,21481,21482],{"class":5314},"    res",[5264,21484,5707],{"class":5270},[5264,21486,13182],{"class":5274},[5264,21488,5311],{"class":5270},[5264,21490,21491],{"class":5611},"'X-Request-Id'",[5264,21493,5324],{"class":5270},[5264,21495,21435],{"class":5314},[5264,21497,5707],{"class":5270},[5264,21499,10284],{"class":5314},[5264,21501,6000],{"class":5270},[5264,21503,21504,21507],{"class":5266,"line":5428},[5264,21505,21506],{"class":5274},"    next",[5264,21508,5713],{"class":5270},[5264,21510,21511],{"class":5266,"line":5781},[5264,21512,5425],{"class":5270},[5264,21514,21515],{"class":5266,"line":5804},[5264,21516,5431],{"class":5270},[5264,21518,21519],{"class":5266,"line":5809},[5264,21520,5473],{"emptyLinePlaceholder":5472},[5264,21522,21523],{"class":5266,"line":5815},[5264,21524,10490],{"class":5341},[5264,21526,21527,21529,21531,21533,21535,21538],{"class":5266,"line":5835},[5264,21528,5285],{"class":5284},[5264,21530,5289],{"class":5288},[5264,21532,10591],{"class":5292},[5264,21534,5296],{"class":5288},[5264,21536,21537],{"class":5292}," NestModule",[5264,21539,5302],{"class":5270},[5264,21541,21542,21545,21547,21550,21552,21555],{"class":5266,"line":5840},[5264,21543,21544],{"class":5274},"  configure",[5264,21546,5311],{"class":5270},[5264,21548,21549],{"class":5314},"consumer",[5264,21551,5318],{"class":5270},[5264,21553,21554],{"class":5292},"MiddlewareConsumer",[5264,21556,5335],{"class":5270},[5264,21558,21559,21562,21564,21567,21569,21572,21574,21577,21579,21582],{"class":5266,"line":5846},[5264,21560,21561],{"class":5314},"    consumer",[5264,21563,5707],{"class":5270},[5264,21565,21566],{"class":5274},"apply",[5264,21568,5311],{"class":5270},[5264,21570,21571],{"class":5314},"RequestIdMiddleware",[5264,21573,5989],{"class":5270},[5264,21575,21576],{"class":5274},"forRoutes",[5264,21578,5311],{"class":5270},[5264,21580,21581],{"class":5611},"'*'",[5264,21583,6000],{"class":5270},[5264,21585,21586],{"class":5266,"line":5857},[5264,21587,5425],{"class":5270},[5264,21589,21590],{"class":5266,"line":5868},[5264,21591,5431],{"class":5270},[5264,21593,21594],{"class":5266,"line":5879},[5264,21595,5473],{"emptyLinePlaceholder":5472},[5264,21597,21598],{"class":5266,"line":5890},[5264,21599,21600],{"class":5341},"\u002F\u002F В exception filter\n",[5264,21602,21603,21605,21607],{"class":5266,"line":5911},[5264,21604,18815],{"class":5288},[5264,21606,5851],{"class":5698},[5264,21608,5854],{"class":5270},[5264,21610,21611,21613,21615],{"class":5266,"line":5926},[5264,21612,18824],{"class":5314},[5264,21614,5767],{"class":5314},[5264,21616,5865],{"class":5270},[5264,21618,21619,21621,21623,21625,21627],{"class":5266,"line":5941},[5264,21620,18549],{"class":5314},[5264,21622,7745],{"class":5314},[5264,21624,5707],{"class":5270},[5264,21626,5830],{"class":5314},[5264,21628,5865],{"class":5270},[5264,21630,21631,21633,21635,21637,21639,21641],{"class":5266,"line":5963},[5264,21632,18769],{"class":5314},[5264,21634,5745],{"class":5314},[5264,21636,5707],{"class":5270},[5264,21638,10284],{"class":5314},[5264,21640,5324],{"class":5270},[5264,21642,21643],{"class":5341},"\u002F\u002F UUID з middleware\n",[5264,21645,21646,21648,21650,21652,21654,21656],{"class":5266,"line":5969},[5264,21647,18787],{"class":5314},[5264,21649,5896],{"class":5288},[5264,21651,5899],{"class":5274},[5264,21653,5902],{"class":5270},[5264,21655,5905],{"class":5274},[5264,21657,5908],{"class":5270},[5264,21659,21660],{"class":5266,"line":5974},[5264,21661,14334],{"class":5270},[20191,21663,21665,21668],{"title":21664},"Як обробити помилки асинхронних операцій (jobs, queues)?",[5206,21666,21667],{},"Для асинхронних jobs (Bull, BullMQ) створіть окремий error handler:",[5254,21669,21671],{"className":5256,"code":21670,"language":5259,"meta":5260,"style":5260},"\u002F\u002F job-error.handler.ts\nimport { Injectable, Logger } from '@nestjs\u002Fcommon';\nimport * as Sentry from '@sentry\u002Fnode';\n\n@Injectable()\nexport class JobErrorHandler {\n  private readonly logger = new Logger(JobErrorHandler.name);\n\n  handleJobError(job: any, error: Error) {\n    this.logger.error(`Job ${job.name} failed`, {\n      jobId: job.id,\n      data: job.data,\n      error: error.message,\n      stack: error.stack,\n    });\n\n    Sentry.captureException(error, {\n      tags: { job: job.name },\n      extra: { jobId: job.id, data: job.data },\n    });\n  }\n}\n\n\u002F\u002F email.processor.ts\n@Processor('email')\nexport class EmailProcessor {\n  constructor(private errorHandler: JobErrorHandler) {}\n\n  @Process('send')\n  async handleSend(job: Job) {\n    try {\n      await this.emailService.send(job.data);\n    } catch (error) {\n      this.errorHandler.handleJobError(job, error);\n      throw error; \u002F\u002F Bull помітить як failed job\n    }\n  }\n}\n",[5102,21672,21673,21678,21698,21714,21718,21726,21737,21762,21766,21790,21822,21836,21848,21860,21872,21876,21880,21894,21912,21941,21945,21949,21953,21957,21962,21975,21986,22004,22008,22022,22040,22047,22073,22085,22110,22122,22126,22130],{"__ignoreMap":5260},[5264,21674,21675],{"class":5266,"line":5267},[5264,21676,21677],{"class":5341},"\u002F\u002F job-error.handler.ts\n",[5264,21679,21680,21682,21684,21686,21688,21690,21692,21694,21696],{"class":5266,"line":5281},[5264,21681,5585],{"class":5284},[5264,21683,5463],{"class":5270},[5264,21685,8788],{"class":5314},[5264,21687,5324],{"class":5270},[5264,21689,7529],{"class":5314},[5264,21691,5605],{"class":5270},[5264,21693,5608],{"class":5284},[5264,21695,5612],{"class":5611},[5264,21697,5615],{"class":5270},[5264,21699,21700,21702,21704,21706,21708,21710,21712],{"class":5266,"line":5305},[5264,21701,5585],{"class":5284},[5264,21703,10664],{"class":5288},[5264,21705,7825],{"class":5284},[5264,21707,10669],{"class":5314},[5264,21709,10672],{"class":5284},[5264,21711,10675],{"class":5611},[5264,21713,5615],{"class":5270},[5264,21715,21716],{"class":5266,"line":5338},[5264,21717,5473],{"emptyLinePlaceholder":5472},[5264,21719,21720,21722,21724],{"class":5266,"line":5345},[5264,21721,5271],{"class":5270},[5264,21723,8788],{"class":5274},[5264,21725,5278],{"class":5270},[5264,21727,21728,21730,21732,21735],{"class":5266,"line":5370},[5264,21729,5285],{"class":5284},[5264,21731,5289],{"class":5288},[5264,21733,21734],{"class":5292}," JobErrorHandler",[5264,21736,5302],{"class":5270},[5264,21738,21739,21741,21743,21745,21747,21749,21751,21753,21756,21758,21760],{"class":5266,"line":5394},[5264,21740,6016],{"class":5288},[5264,21742,7607],{"class":5288},[5264,21744,7610],{"class":5314},[5264,21746,5702],{"class":5270},[5264,21748,7615],{"class":5288},[5264,21750,7618],{"class":5274},[5264,21752,5311],{"class":5270},[5264,21754,21755],{"class":5314},"JobErrorHandler",[5264,21757,5707],{"class":5270},[5264,21759,7627],{"class":5314},[5264,21761,6000],{"class":5270},[5264,21763,21764],{"class":5266,"line":5416},[5264,21765,5473],{"emptyLinePlaceholder":5472},[5264,21767,21768,21771,21773,21776,21778,21780,21782,21784,21786,21788],{"class":5266,"line":5422},[5264,21769,21770],{"class":5274},"  handleJobError",[5264,21772,5311],{"class":5270},[5264,21774,21775],{"class":5314},"job",[5264,21777,5318],{"class":5270},[5264,21779,5791],{"class":5292},[5264,21781,5324],{"class":5270},[5264,21783,6106],{"class":5314},[5264,21785,5318],{"class":5270},[5264,21787,18047],{"class":5292},[5264,21789,5335],{"class":5270},[5264,21791,21792,21794,21796,21798,21800,21802,21804,21807,21809,21811,21813,21815,21817,21820],{"class":5266,"line":5428},[5264,21793,7721],{"class":5288},[5264,21795,5707],{"class":5270},[5264,21797,7726],{"class":5314},[5264,21799,5707],{"class":5270},[5264,21801,6106],{"class":5274},[5264,21803,5311],{"class":5270},[5264,21805,21806],{"class":5611},"`Job ",[5264,21808,7062],{"class":5288},[5264,21810,21775],{"class":5314},[5264,21812,5707],{"class":7068},[5264,21814,7627],{"class":5314},[5264,21816,7084],{"class":5288},[5264,21818,21819],{"class":5611}," failed`",[5264,21821,7738],{"class":5270},[5264,21823,21824,21827,21830,21832,21834],{"class":5266,"line":5781},[5264,21825,21826],{"class":5314},"      jobId:",[5264,21828,21829],{"class":5314}," job",[5264,21831,5707],{"class":5270},[5264,21833,10284],{"class":5314},[5264,21835,5865],{"class":5270},[5264,21837,21838,21840,21842,21844,21846],{"class":5266,"line":5804},[5264,21839,11963],{"class":5314},[5264,21841,21829],{"class":5314},[5264,21843,5707],{"class":5270},[5264,21845,21088],{"class":5314},[5264,21847,5865],{"class":5270},[5264,21849,21850,21852,21854,21856,21858],{"class":5266,"line":5809},[5264,21851,5871],{"class":5314},[5264,21853,6121],{"class":5314},[5264,21855,5707],{"class":5270},[5264,21857,5830],{"class":5314},[5264,21859,5865],{"class":5270},[5264,21861,21862,21864,21866,21868,21870],{"class":5266,"line":5815},[5264,21863,15132],{"class":5314},[5264,21865,6121],{"class":5314},[5264,21867,5707],{"class":5270},[5264,21869,10430],{"class":5314},[5264,21871,5865],{"class":5270},[5264,21873,21874],{"class":5266,"line":5835},[5264,21875,7129],{"class":5270},[5264,21877,21878],{"class":5266,"line":5840},[5264,21879,5473],{"emptyLinePlaceholder":5472},[5264,21881,21882,21884,21886,21888,21890,21892],{"class":5266,"line":5846},[5264,21883,11901],{"class":5314},[5264,21885,5707],{"class":5270},[5264,21887,11473],{"class":5274},[5264,21889,5311],{"class":5270},[5264,21891,6106],{"class":5314},[5264,21893,7738],{"class":5270},[5264,21895,21896,21899,21901,21904,21906,21908,21910],{"class":5266,"line":5857},[5264,21897,21898],{"class":5314},"      tags:",[5264,21900,5463],{"class":5270},[5264,21902,21903],{"class":5314},"job:",[5264,21905,21829],{"class":5314},[5264,21907,5707],{"class":5270},[5264,21909,7627],{"class":5314},[5264,21911,12817],{"class":5270},[5264,21913,21914,21917,21919,21922,21924,21926,21928,21930,21933,21935,21937,21939],{"class":5266,"line":5868},[5264,21915,21916],{"class":5314},"      extra:",[5264,21918,5463],{"class":5270},[5264,21920,21921],{"class":5314},"jobId:",[5264,21923,21829],{"class":5314},[5264,21925,5707],{"class":5270},[5264,21927,10284],{"class":5314},[5264,21929,5324],{"class":5270},[5264,21931,21932],{"class":5314},"data:",[5264,21934,21829],{"class":5314},[5264,21936,5707],{"class":5270},[5264,21938,21088],{"class":5314},[5264,21940,12817],{"class":5270},[5264,21942,21943],{"class":5266,"line":5879},[5264,21944,7129],{"class":5270},[5264,21946,21947],{"class":5266,"line":5890},[5264,21948,5425],{"class":5270},[5264,21950,21951],{"class":5266,"line":5911},[5264,21952,5431],{"class":5270},[5264,21954,21955],{"class":5266,"line":5926},[5264,21956,5473],{"emptyLinePlaceholder":5472},[5264,21958,21959],{"class":5266,"line":5941},[5264,21960,21961],{"class":5341},"\u002F\u002F email.processor.ts\n",[5264,21963,21964,21966,21969,21971,21973],{"class":5266,"line":5963},[5264,21965,5271],{"class":5270},[5264,21967,21968],{"class":5274},"Processor",[5264,21970,5311],{"class":5270},[5264,21972,16499],{"class":5611},[5264,21974,5451],{"class":5270},[5264,21976,21977,21979,21981,21984],{"class":5266,"line":5969},[5264,21978,5285],{"class":5284},[5264,21980,5289],{"class":5288},[5264,21982,21983],{"class":5292}," EmailProcessor",[5264,21985,5302],{"class":5270},[5264,21987,21988,21990,21992,21994,21997,21999,22001],{"class":5266,"line":5974},[5264,21989,8806],{"class":5288},[5264,21991,5311],{"class":5270},[5264,21993,20206],{"class":5288},[5264,21995,21996],{"class":5314}," errorHandler",[5264,21998,5318],{"class":5270},[5264,22000,21755],{"class":5292},[5264,22002,22003],{"class":5270},") {}\n",[5264,22005,22006],{"class":5266,"line":6003},[5264,22007,5473],{"emptyLinePlaceholder":5472},[5264,22009,22010,22012,22015,22017,22020],{"class":5266,"line":6008},[5264,22011,6263],{"class":5270},[5264,22013,22014],{"class":5274},"Process",[5264,22016,5311],{"class":5270},[5264,22018,22019],{"class":5611},"'send'",[5264,22021,5451],{"class":5270},[5264,22023,22024,22026,22029,22031,22033,22035,22038],{"class":5266,"line":6013},[5264,22025,6462],{"class":5288},[5264,22027,22028],{"class":5274}," handleSend",[5264,22030,5311],{"class":5270},[5264,22032,21775],{"class":5314},[5264,22034,5318],{"class":5270},[5264,22036,22037],{"class":5292},"Job",[5264,22039,5335],{"class":5270},[5264,22041,22042,22045],{"class":5266,"line":6039},[5264,22043,22044],{"class":5284},"    try",[5264,22046,5302],{"class":5270},[5264,22048,22049,22052,22054,22056,22059,22061,22063,22065,22067,22069,22071],{"class":5266,"line":6062},[5264,22050,22051],{"class":5284},"      await",[5264,22053,5947],{"class":5288},[5264,22055,5707],{"class":5270},[5264,22057,22058],{"class":5314},"emailService",[5264,22060,5707],{"class":5270},[5264,22062,17126],{"class":5274},[5264,22064,5311],{"class":5270},[5264,22066,21775],{"class":5314},[5264,22068,5707],{"class":5270},[5264,22070,21088],{"class":5314},[5264,22072,6000],{"class":5270},[5264,22074,22075,22077,22079,22081,22083],{"class":5266,"line":6080},[5264,22076,10158],{"class":5270},[5264,22078,15855],{"class":5284},[5264,22080,5146],{"class":5270},[5264,22082,6106],{"class":5314},[5264,22084,5335],{"class":5270},[5264,22086,22087,22090,22092,22095,22097,22100,22102,22104,22106,22108],{"class":5266,"line":6086},[5264,22088,22089],{"class":5288},"      this",[5264,22091,5707],{"class":5270},[5264,22093,22094],{"class":5314},"errorHandler",[5264,22096,5707],{"class":5270},[5264,22098,22099],{"class":5274},"handleJobError",[5264,22101,5311],{"class":5270},[5264,22103,21775],{"class":5314},[5264,22105,5324],{"class":5270},[5264,22107,6106],{"class":5314},[5264,22109,6000],{"class":5270},[5264,22111,22112,22115,22117,22119],{"class":5266,"line":6091},[5264,22113,22114],{"class":5284},"      throw",[5264,22116,6121],{"class":5314},[5264,22118,8048],{"class":5270},[5264,22120,22121],{"class":5341},"\u002F\u002F Bull помітить як failed job\n",[5264,22123,22124],{"class":5266,"line":6115},[5264,22125,6083],{"class":5270},[5264,22127,22128],{"class":5266,"line":6131},[5264,22129,5425],{"class":5270},[5264,22131,22132],{"class":5266,"line":6146},[5264,22133,5431],{"class":5270},[20191,22135,22137,22140],{"title":22136},"Як уникнути дублювання логування в кількох filters?",[5206,22138,22139],{},"Створіть централізований logging service:",[5254,22141,22143],{"className":5256,"code":22142,"language":5259,"meta":5260,"style":5260},"\u002F\u002F error-logging.service.ts\n@Injectable()\nexport class ErrorLoggingService {\n  private readonly logger = new Logger(ErrorLoggingService.name);\n  private loggedErrors = new Set\u003Cstring>();\n\n  logError(exception: unknown, context: any) {\n    const errorKey = this.generateErrorKey(exception, context);\n\n    \u002F\u002F Уникнення дублювання\n    if (this.loggedErrors.has(errorKey)) {\n      return;\n    }\n\n    this.loggedErrors.add(errorKey);\n    setTimeout(() => this.loggedErrors.delete(errorKey), 5000);\n\n    this.logger.error('Exception occurred', {\n      message: exception instanceof Error ? exception.message : 'Unknown',\n      stack: exception instanceof Error ? exception.stack : undefined,\n      ...context,\n    });\n  }\n\n  private generateErrorKey(exception: unknown, context: any): string {\n    const message = exception instanceof Error ? exception.message : 'unknown';\n    return `${message}-${context.url}`;\n  }\n}\n\n\u002F\u002F Використання в filters\n@Catch()\nexport class LoggingExceptionFilter implements ExceptionFilter {\n  constructor(private errorLogging: ErrorLoggingService) {}\n\n  catch(exception: unknown, host: ArgumentsHost) {\n    const request = host.switchToHttp().getRequest();\n    this.errorLogging.logError(exception, { url: request.url });\n    \u002F\u002F ...\n  }\n}\n",[5102,22144,22145,22150,22158,22169,22194,22214,22218,22241,22267,22271,22276,22301,22307,22311,22315,22334,22364,22368,22386,22411,22435,22444,22448,22452,22456,22485,22513,22542,22546,22550,22554,22559,22567,22582,22599,22603,22625,22645,22675,22679,22683],{"__ignoreMap":5260},[5264,22146,22147],{"class":5266,"line":5267},[5264,22148,22149],{"class":5341},"\u002F\u002F error-logging.service.ts\n",[5264,22151,22152,22154,22156],{"class":5266,"line":5281},[5264,22153,5271],{"class":5270},[5264,22155,8788],{"class":5274},[5264,22157,5278],{"class":5270},[5264,22159,22160,22162,22164,22167],{"class":5266,"line":5305},[5264,22161,5285],{"class":5284},[5264,22163,5289],{"class":5288},[5264,22165,22166],{"class":5292}," ErrorLoggingService",[5264,22168,5302],{"class":5270},[5264,22170,22171,22173,22175,22177,22179,22181,22183,22185,22188,22190,22192],{"class":5266,"line":5338},[5264,22172,6016],{"class":5288},[5264,22174,7607],{"class":5288},[5264,22176,7610],{"class":5314},[5264,22178,5702],{"class":5270},[5264,22180,7615],{"class":5288},[5264,22182,7618],{"class":5274},[5264,22184,5311],{"class":5270},[5264,22186,22187],{"class":5314},"ErrorLoggingService",[5264,22189,5707],{"class":5270},[5264,22191,7627],{"class":5314},[5264,22193,6000],{"class":5270},[5264,22195,22196,22198,22201,22203,22205,22208,22210,22212],{"class":5266,"line":5345},[5264,22197,6016],{"class":5288},[5264,22199,22200],{"class":5314}," loggedErrors",[5264,22202,5702],{"class":5270},[5264,22204,7615],{"class":5288},[5264,22206,22207],{"class":5274}," Set",[5264,22209,5733],{"class":5270},[5264,22211,6286],{"class":5292},[5264,22213,5738],{"class":5270},[5264,22215,22216],{"class":5266,"line":5370},[5264,22217,5473],{"emptyLinePlaceholder":5472},[5264,22219,22220,22223,22225,22227,22229,22231,22233,22235,22237,22239],{"class":5266,"line":5394},[5264,22221,22222],{"class":5274},"  logError",[5264,22224,5311],{"class":5270},[5264,22226,5315],{"class":5314},[5264,22228,5318],{"class":5270},[5264,22230,5321],{"class":5292},[5264,22232,5324],{"class":5270},[5264,22234,11844],{"class":5314},[5264,22236,5318],{"class":5270},[5264,22238,5791],{"class":5292},[5264,22240,5335],{"class":5270},[5264,22242,22243,22245,22248,22250,22252,22254,22257,22259,22261,22263,22265],{"class":5266,"line":5416},[5264,22244,5695],{"class":5288},[5264,22246,22247],{"class":5698}," errorKey",[5264,22249,5702],{"class":5270},[5264,22251,7001],{"class":5288},[5264,22253,5707],{"class":5270},[5264,22255,22256],{"class":5274},"generateErrorKey",[5264,22258,5311],{"class":5270},[5264,22260,5315],{"class":5314},[5264,22262,5324],{"class":5270},[5264,22264,11844],{"class":5314},[5264,22266,6000],{"class":5270},[5264,22268,22269],{"class":5266,"line":5422},[5264,22270,5473],{"emptyLinePlaceholder":5472},[5264,22272,22273],{"class":5266,"line":5428},[5264,22274,22275],{"class":5341},"    \u002F\u002F Уникнення дублювання\n",[5264,22277,22278,22280,22282,22284,22286,22289,22291,22294,22296,22299],{"class":5266,"line":5781},[5264,22279,5348],{"class":5284},[5264,22281,5146],{"class":5270},[5264,22283,7001],{"class":5288},[5264,22285,5707],{"class":5270},[5264,22287,22288],{"class":5314},"loggedErrors",[5264,22290,5707],{"class":5270},[5264,22292,22293],{"class":5274},"has",[5264,22295,5311],{"class":5270},[5264,22297,22298],{"class":5314},"errorKey",[5264,22300,6059],{"class":5270},[5264,22302,22303,22305],{"class":5266,"line":5804},[5264,22304,6065],{"class":5284},[5264,22306,5615],{"class":5270},[5264,22308,22309],{"class":5266,"line":5809},[5264,22310,6083],{"class":5270},[5264,22312,22313],{"class":5266,"line":5815},[5264,22314,5473],{"emptyLinePlaceholder":5472},[5264,22316,22317,22319,22321,22323,22325,22328,22330,22332],{"class":5266,"line":5835},[5264,22318,7721],{"class":5288},[5264,22320,5707],{"class":5270},[5264,22322,22288],{"class":5314},[5264,22324,5707],{"class":5270},[5264,22326,22327],{"class":5274},"add",[5264,22329,5311],{"class":5270},[5264,22331,22298],{"class":5314},[5264,22333,6000],{"class":5270},[5264,22335,22336,22339,22341,22343,22345,22347,22349,22351,22354,22356,22358,22360,22362],{"class":5266,"line":5840},[5264,22337,22338],{"class":5274},"    setTimeout",[5264,22340,12057],{"class":5270},[5264,22342,12060],{"class":5288},[5264,22344,5947],{"class":5288},[5264,22346,5707],{"class":5270},[5264,22348,22288],{"class":5314},[5264,22350,5707],{"class":5270},[5264,22352,22353],{"class":5274},"delete",[5264,22355,5311],{"class":5270},[5264,22357,22298],{"class":5314},[5264,22359,12682],{"class":5270},[5264,22361,12679],{"class":6311},[5264,22363,6000],{"class":5270},[5264,22365,22366],{"class":5266,"line":5846},[5264,22367,5473],{"emptyLinePlaceholder":5472},[5264,22369,22370,22372,22374,22376,22378,22380,22382,22384],{"class":5266,"line":5857},[5264,22371,7721],{"class":5288},[5264,22373,5707],{"class":5270},[5264,22375,7726],{"class":5314},[5264,22377,5707],{"class":5270},[5264,22379,6106],{"class":5274},[5264,22381,5311],{"class":5270},[5264,22383,15093],{"class":5611},[5264,22385,7738],{"class":5270},[5264,22387,22388,22390,22392,22394,22396,22398,22400,22402,22404,22406,22409],{"class":5266,"line":5868},[5264,22389,5882],{"class":5314},[5264,22391,7745],{"class":5314},[5264,22393,5355],{"class":5288},[5264,22395,11461],{"class":5292},[5264,22397,8591],{"class":5270},[5264,22399,5315],{"class":5314},[5264,22401,5707],{"class":5270},[5264,22403,5830],{"class":5314},[5264,22405,11434],{"class":5270},[5264,22407,22408],{"class":5611},"'Unknown'",[5264,22410,5865],{"class":5270},[5264,22412,22413,22415,22417,22419,22421,22423,22425,22427,22429,22431,22433],{"class":5266,"line":5879},[5264,22414,15132],{"class":5314},[5264,22416,7745],{"class":5314},[5264,22418,5355],{"class":5288},[5264,22420,11461],{"class":5292},[5264,22422,8591],{"class":5270},[5264,22424,5315],{"class":5314},[5264,22426,5707],{"class":5270},[5264,22428,10430],{"class":5314},[5264,22430,11434],{"class":5270},[5264,22432,15151],{"class":5288},[5264,22434,5865],{"class":5270},[5264,22436,22437,22440,22442],{"class":5266,"line":5890},[5264,22438,22439],{"class":5270},"      ...",[5264,22441,11844],{"class":5314},[5264,22443,5865],{"class":5270},[5264,22445,22446],{"class":5266,"line":5911},[5264,22447,7129],{"class":5270},[5264,22449,22450],{"class":5266,"line":5926},[5264,22451,5425],{"class":5270},[5264,22453,22454],{"class":5266,"line":5941},[5264,22455,5473],{"emptyLinePlaceholder":5472},[5264,22457,22458,22460,22463,22465,22467,22469,22471,22473,22475,22477,22479,22481,22483],{"class":5266,"line":5963},[5264,22459,6016],{"class":5288},[5264,22461,22462],{"class":5274}," generateErrorKey",[5264,22464,5311],{"class":5270},[5264,22466,5315],{"class":5314},[5264,22468,5318],{"class":5270},[5264,22470,5321],{"class":5292},[5264,22472,5324],{"class":5270},[5264,22474,11844],{"class":5314},[5264,22476,5318],{"class":5270},[5264,22478,5791],{"class":5292},[5264,22480,6031],{"class":5270},[5264,22482,6286],{"class":5292},[5264,22484,5302],{"class":5270},[5264,22486,22487,22489,22491,22493,22495,22497,22499,22501,22503,22505,22507,22509,22511],{"class":5266,"line":5969},[5264,22488,5695],{"class":5288},[5264,22490,10112],{"class":5698},[5264,22492,5702],{"class":5270},[5264,22494,5315],{"class":5314},[5264,22496,5355],{"class":5288},[5264,22498,11461],{"class":5292},[5264,22500,8591],{"class":5270},[5264,22502,5315],{"class":5314},[5264,22504,5707],{"class":5270},[5264,22506,5830],{"class":5314},[5264,22508,11434],{"class":5270},[5264,22510,20410],{"class":5611},[5264,22512,5615],{"class":5270},[5264,22514,22515,22517,22519,22521,22523,22525,22528,22530,22532,22534,22536,22538,22540],{"class":5266,"line":5974},[5264,22516,6094],{"class":5284},[5264,22518,7059],{"class":5611},[5264,22520,7062],{"class":5288},[5264,22522,5830],{"class":5314},[5264,22524,7084],{"class":5288},[5264,22526,22527],{"class":5611},"-",[5264,22529,7062],{"class":5288},[5264,22531,11844],{"class":5314},[5264,22533,5707],{"class":7068},[5264,22535,5921],{"class":5314},[5264,22537,7084],{"class":5288},[5264,22539,8755],{"class":5611},[5264,22541,5615],{"class":5270},[5264,22543,22544],{"class":5266,"line":6003},[5264,22545,5425],{"class":5270},[5264,22547,22548],{"class":5266,"line":6008},[5264,22549,5431],{"class":5270},[5264,22551,22552],{"class":5266,"line":6013},[5264,22553,5473],{"emptyLinePlaceholder":5472},[5264,22555,22556],{"class":5266,"line":6039},[5264,22557,22558],{"class":5341},"\u002F\u002F Використання в filters\n",[5264,22560,22561,22563,22565],{"class":5266,"line":6062},[5264,22562,5271],{"class":5270},[5264,22564,5275],{"class":5274},[5264,22566,5278],{"class":5270},[5264,22568,22569,22571,22573,22576,22578,22580],{"class":5266,"line":6080},[5264,22570,5285],{"class":5284},[5264,22572,5289],{"class":5288},[5264,22574,22575],{"class":5292}," LoggingExceptionFilter",[5264,22577,5296],{"class":5288},[5264,22579,5299],{"class":5292},[5264,22581,5302],{"class":5270},[5264,22583,22584,22586,22588,22590,22593,22595,22597],{"class":5266,"line":6086},[5264,22585,8806],{"class":5288},[5264,22587,5311],{"class":5270},[5264,22589,20206],{"class":5288},[5264,22591,22592],{"class":5314}," errorLogging",[5264,22594,5318],{"class":5270},[5264,22596,22187],{"class":5292},[5264,22598,22003],{"class":5270},[5264,22600,22601],{"class":5266,"line":6091},[5264,22602,5473],{"emptyLinePlaceholder":5472},[5264,22604,22605,22607,22609,22611,22613,22615,22617,22619,22621,22623],{"class":5266,"line":6115},[5264,22606,5308],{"class":5274},[5264,22608,5311],{"class":5270},[5264,22610,5315],{"class":5314},[5264,22612,5318],{"class":5270},[5264,22614,5321],{"class":5292},[5264,22616,5324],{"class":5270},[5264,22618,5327],{"class":5314},[5264,22620,5318],{"class":5270},[5264,22622,5332],{"class":5292},[5264,22624,5335],{"class":5270},[5264,22626,22627,22629,22631,22633,22635,22637,22639,22641,22643],{"class":5266,"line":6131},[5264,22628,5695],{"class":5288},[5264,22630,5745],{"class":5698},[5264,22632,5702],{"class":5270},[5264,22634,5327],{"class":5314},[5264,22636,5707],{"class":5270},[5264,22638,5710],{"class":5274},[5264,22640,5902],{"class":5270},[5264,22642,5754],{"class":5274},[5264,22644,5713],{"class":5270},[5264,22646,22647,22649,22651,22654,22656,22659,22661,22663,22665,22667,22669,22671,22673],{"class":5266,"line":6146},[5264,22648,7721],{"class":5288},[5264,22650,5707],{"class":5270},[5264,22652,22653],{"class":5314},"errorLogging",[5264,22655,5707],{"class":5270},[5264,22657,22658],{"class":5274},"logError",[5264,22660,5311],{"class":5270},[5264,22662,5315],{"class":5314},[5264,22664,6315],{"class":5270},[5264,22666,15759],{"class":5314},[5264,22668,5745],{"class":5314},[5264,22670,5707],{"class":5270},[5264,22672,5921],{"class":5314},[5264,22674,15729],{"class":5270},[5264,22676,22677],{"class":5266,"line":6172},[5264,22678,19465],{"class":5341},[5264,22680,22681],{"class":5266,"line":6178},[5264,22682,5425],{"class":5270},[5264,22684,22685],{"class":5266,"line":6183},[5264,22686,5431],{"class":5270},[22688,22689],"hr",{},[5206,22691,22692,22693,22696,22697,22699,22700,22702,22703,22706],{},"У наступній лекції ",[5144,22694,22695],{},"16. Execution Context"," ми розглянемо API ",[5102,22698,11741],{},", методи ",[5102,22701,5332],{},", роботу з ",[5102,22704,22705],{},"Reflector"," для витягування метаданих та практичне застосування у Guards, Interceptors та Filters.",[22708,22709,22710],"style",{},"html pre.shiki code .sHH4Y, html code.shiki .sHH4Y{--shiki-light:#000000;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .s8Opu, html code.shiki .s8Opu{--shiki-light:#795E26;--shiki-default:#DCDCAA;--shiki-dark:#DCDCAA}html pre.shiki code .s8xlr, html code.shiki .s8xlr{--shiki-light:#AF00DB;--shiki-default:#C586C0;--shiki-dark:#C586C0}html pre.shiki code .su1O8, html code.shiki .su1O8{--shiki-light:#0000FF;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .sN1BT, html code.shiki .sN1BT{--shiki-light:#267F99;--shiki-default:#4EC9B0;--shiki-dark:#4EC9B0}html pre.shiki code .siwwj, html code.shiki .siwwj{--shiki-light:#001080;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .spJ8K, html code.shiki .spJ8K{--shiki-light:#008000;--shiki-default:#6A9955;--shiki-dark:#6A9955}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbdoH, html code.shiki .sbdoH{--shiki-light:#A31515;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .s-QsJ, html code.shiki .s-QsJ{--shiki-light:#0070C1;--shiki-default:#4FC1FF;--shiki-dark:#4FC1FF}html pre.shiki code .sJj4R, html code.shiki .sJj4R{--shiki-light:#098658;--shiki-default:#B5CEA8;--shiki-dark:#B5CEA8}html pre.shiki code .sKtos, html code.shiki .sKtos{--shiki-light:#800000;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .sLwNe, html code.shiki .sLwNe{--shiki-light:#0451A5;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sD7JJ, html code.shiki .sD7JJ{--shiki-light:#000000FF;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .shsrj, html code.shiki .shsrj{--shiki-light:#811F3F;--shiki-default:#D16969;--shiki-dark:#D16969}html pre.shiki code .siofk, html code.shiki .siofk{--shiki-light:#EE0000;--shiki-default:#DCDCAA;--shiki-dark:#DCDCAA}html pre.shiki code .sAV2Q, html code.shiki .sAV2Q{--shiki-light:#D16969;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .sYsli, html code.shiki .sYsli{--shiki-light:#000000;--shiki-default:#D7BA7D;--shiki-dark:#D7BA7D}html pre.shiki code .sjcCO, html code.shiki .sjcCO{--shiki-light:#EE0000;--shiki-default:#D7BA7D;--shiki-dark:#D7BA7D}html pre.shiki code .s5IvJ, html code.shiki .s5IvJ{--shiki-light:#000000;--shiki-default:#C8C8C8;--shiki-dark:#C8C8C8}",{"title":5260,"searchDepth":5281,"depth":5281,"links":22712},[22713,22714,22718,22722,22723,22729,22730,22731,22732,22736,22741,22746,22747,22756,22757],{"id":5203,"depth":5281,"text":5204},{"id":5557,"depth":5281,"text":5558,"children":22715},[22716,22717],{"id":5574,"depth":5305,"text":5575},{"id":6837,"depth":5305,"text":6838},{"id":7483,"depth":5281,"text":7484,"children":22719},[22720,22721],{"id":7497,"depth":5305,"text":7498},{"id":9231,"depth":5305,"text":9232},{"id":9861,"depth":5281,"text":9862},{"id":10597,"depth":5281,"text":10598,"children":22724},[22725,22726,22727,22728],{"id":10604,"depth":5305,"text":10605},{"id":10629,"depth":5305,"text":10630},{"id":10844,"depth":5305,"text":10845},{"id":11712,"depth":5305,"text":11713},{"id":12177,"depth":5281,"text":12178},{"id":12854,"depth":5281,"text":12855},{"id":13391,"depth":5281,"text":13392},{"id":13816,"depth":5281,"text":13817,"children":22733},[22734,22735],{"id":13823,"depth":5305,"text":13824},{"id":14183,"depth":5305,"text":14184},{"id":14378,"depth":5281,"text":14379,"children":22737},[22738,22739,22740],{"id":14385,"depth":5305,"text":14386},{"id":14403,"depth":5305,"text":14404},{"id":14617,"depth":5305,"text":14618},{"id":15357,"depth":5281,"text":15358,"children":22742},[22743,22744,22745],{"id":15361,"depth":5305,"text":15362},{"id":16010,"depth":5305,"text":16011},{"id":16819,"depth":5305,"text":16820},{"id":17734,"depth":5281,"text":17735},{"id":18053,"depth":5281,"text":18054,"children":22748},[22749,22750,22751,22752,22753,22754,22755],{"id":18057,"depth":5305,"text":18058},{"id":18288,"depth":5305,"text":18289},{"id":18515,"depth":5305,"text":18516},{"id":18804,"depth":5305,"text":18805},{"id":18944,"depth":5305,"text":18945},{"id":19111,"depth":5305,"text":19112},{"id":19476,"depth":5305,"text":19477},{"id":19773,"depth":5281,"text":19774},{"id":20185,"depth":5281,"text":20186},"ValidationExceptionFilter, DatabaseExceptionFilter, інтеграція з Sentry","md",null,{},{"title":4492,"description":22758},"JHrB5ltraCNqvfgKdlVe4E1Q8cr61ciDag6W13O84PQ",[22765,22767],{"title":4488,"path":4489,"stem":4490,"description":22766,"children":-1},"Концепція Exception Filters, HttpException, кастомні фільтри",{"title":4496,"path":4497,"stem":4498,"description":22768,"children":-1},"ExecutionContext API, ArgumentsHost, Reflector, метадані",1790366130405]