[{"data":1,"prerenderedAt":8002},["ShallowReactive",2],{"navigation_docs":3,"-java-pr2-jar-packaging-distribution":3135,"-java-pr2-jar-packaging-distribution-surround":7997},[4,1669,1826,2280,2461,2668,2790,2840,2897,2931,3057,3094,3131],{"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,1346,1636,1665],{"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],{"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},"Desktop UI","i-lucide-app-window","\u002Fcsharp\u002Fdesktop-ui","01.csharp\u002F12.desktop-ui",[1352,1356,1360,1364,1368,1372,1376,1380,1384,1388,1392,1396,1400,1404,1408,1412,1416,1420,1424,1428,1432,1436,1440,1444,1448,1452,1456,1460,1464,1468,1472,1476,1480,1484,1488,1492,1496,1500,1504,1508,1512,1516,1520,1524,1528,1532,1536,1540,1544,1548,1552,1556,1560,1564,1568,1572,1576,1580,1584,1588,1592,1596,1600,1604,1608,1612,1616,1620,1624,1628,1632],{"title":1353,"path":1354,"stem":1355},"Що таке десктопна розробка?","\u002Fcsharp\u002Fdesktop-ui\u002Fwhat-is-desktop-dev","01.csharp\u002F12.desktop-ui\u002F01.what-is-desktop-dev",{"title":1357,"path":1358,"stem":1359},"Архітектура WPF — як влаштований графічний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-architecture","01.csharp\u002F12.desktop-ui\u002F02.wpf-architecture",{"title":1361,"path":1362,"stem":1363},"Перший WPF-проєкт — від нуля до вікна","\u002Fcsharp\u002Fdesktop-ui\u002Ffirst-wpf-app","01.csharp\u002F12.desktop-ui\u002F03.first-wpf-app",{"title":1365,"path":1366,"stem":1367},"Перший Avalonia-проєкт: WPF для всіх платформ","\u002Fcsharp\u002Fdesktop-ui\u002F03a.first-avalonia-app","01.csharp\u002F12.desktop-ui\u002F03a.first-avalonia-app",{"title":1369,"path":1370,"stem":1371},"XAML: декларативний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-basics","01.csharp\u002F12.desktop-ui\u002F04.xaml-basics",{"title":1373,"path":1374,"stem":1375},"Fluent UI у WPF — сучасний дизайн Windows 11","\u002Fcsharp\u002Fdesktop-ui\u002F04a.wpf-fluent-ui","01.csharp\u002F12.desktop-ui\u002F04a.wpf-fluent-ui",{"title":1377,"path":1378,"stem":1379},"WPF UI — сучасна бібліотека Fluent контролів","\u002Fcsharp\u002Fdesktop-ui\u002F04b.wpf-ui-library","01.csharp\u002F12.desktop-ui\u002F04b.wpf-ui-library",{"title":1381,"path":1382,"stem":1383},"HandyControl — велика бібліотека UI контролів для WPF","\u002Fcsharp\u002Fdesktop-ui\u002F04c.handycontrol-library","01.csharp\u002F12.desktop-ui\u002F04c.handycontrol-library",{"title":1385,"path":1386,"stem":1387},"Простори імен та ресурси XAML","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-namespaces-resources","01.csharp\u002F12.desktop-ui\u002F05.xaml-namespaces-resources",{"title":1389,"path":1390,"stem":1391},"XAML в Avalonia: ключові відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F05a.avalonia-xaml-differences","01.csharp\u002F12.desktop-ui\u002F05a.avalonia-xaml-differences",{"title":1393,"path":1394,"stem":1395},"Розширення розмітки XAML (Markup Extensions)","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-markup-extensions","01.csharp\u002F12.desktop-ui\u002F06.xaml-markup-extensions",{"title":1397,"path":1398,"stem":1399},"Панелі Layout: StackPanel, WrapPanel, DockPanel","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part1","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part1",{"title":1401,"path":1402,"stem":1403},"Grid, Canvas, UniformGrid","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part2","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part2",{"title":1405,"path":1406,"stem":1407},"Просунуті техніки Layout","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-advanced","01.csharp\u002F12.desktop-ui\u002F08.layout-advanced",{"title":1409,"path":1410,"stem":1411},"Адаптивний Layout та найкращі практики","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-responsive","01.csharp\u002F12.desktop-ui\u002F09.layout-responsive",{"title":1413,"path":1414,"stem":1415},"Layout в Avalonia: відмінності та нові можливості","\u002Fcsharp\u002Fdesktop-ui\u002F09a.layout-avalonia","01.csharp\u002F12.desktop-ui\u002F09a.layout-avalonia",{"title":1417,"path":1418,"stem":1419},"Button, Image, ProgressBar та інші базові контроли","\u002Fcsharp\u002Fdesktop-ui\u002Fbasic-controls","01.csharp\u002F12.desktop-ui\u002F10.basic-controls",{"title":1421,"path":1422,"stem":1423},"Контроли в Avalonia: відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F10a.controls-avalonia","01.csharp\u002F12.desktop-ui\u002F10a.controls-avalonia",{"title":1425,"path":1426,"stem":1427},"Текстові контроли — TextBlock, TextBox, RichTextBox","\u002Fcsharp\u002Fdesktop-ui\u002Ftext-controls","01.csharp\u002F12.desktop-ui\u002F11.text-controls",{"title":1429,"path":1430,"stem":1431},"Контроли вибору — CheckBox, RadioButton, ComboBox, ListBox, DatePicker","\u002Fcsharp\u002Fdesktop-ui\u002Fselection-controls","01.csharp\u002F12.desktop-ui\u002F12.selection-controls",{"title":1433,"path":1434,"stem":1435},"Content Model — GroupBox, Expander, TabControl, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fcontent-controls","01.csharp\u002F12.desktop-ui\u002F13.content-controls",{"title":1437,"path":1438,"stem":1439},"UI\u002FUX принципи десктопних застосунків","\u002Fcsharp\u002Fdesktop-ui\u002F13a.ui-ux-principles","01.csharp\u002F12.desktop-ui\u002F13a.ui-ux-principles",{"title":1441,"path":1442,"stem":1443},"Dependency Properties — Концепція та Value Resolution","\u002Fcsharp\u002Fdesktop-ui\u002Fdependency-properties-part1","01.csharp\u002F12.desktop-ui\u002F14.dependency-properties-part1",{"title":1445,"path":1446,"stem":1447},"Avalonia Property System — StyledProperty та DirectProperty","\u002Fcsharp\u002Fdesktop-ui\u002F14a.avalonia-property-system","01.csharp\u002F12.desktop-ui\u002F14a.avalonia-property-system",{"title":1449,"path":1450,"stem":1451},"Attached Properties — Властивості без меж","\u002Fcsharp\u002Fdesktop-ui\u002Fattached-properties","01.csharp\u002F12.desktop-ui\u002F15.attached-properties",{"title":1453,"path":1454,"stem":1455},"Routed Events — Маршрутизація подій у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Frouted-events","01.csharp\u002F12.desktop-ui\u002F16.routed-events",{"title":1457,"path":1458,"stem":1459},"Data Binding — Від Code-Behind до Декларативності","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part1","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part1",{"title":1461,"path":1462,"stem":1463},"INotifyPropertyChanged — Живе оновлення UI","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part2","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part2",{"title":1465,"path":1466,"stem":1467},"Compiled Bindings в Avalonia — Безпека на етапі компіляції","\u002Fcsharp\u002Fdesktop-ui\u002F17a.avalonia-compiled-bindings","01.csharp\u002F12.desktop-ui\u002F17a.avalonia-compiled-bindings",{"title":1469,"path":1470,"stem":1471},"Просунутий Data Binding — ElementName, RelativeSource, MultiBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-advanced","01.csharp\u002F12.desktop-ui\u002F18.data-binding-advanced",{"title":1473,"path":1474,"stem":1475},"Value Converters — Перетворення типів даних у Data Binding","\u002Fcsharp\u002Fdesktop-ui\u002Fvalue-converters","01.csharp\u002F12.desktop-ui\u002F19.value-converters",{"title":1477,"path":1478,"stem":1479},"Data Templates — Візуалізація об'єктів у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-templates","01.csharp\u002F12.desktop-ui\u002F20.data-templates",{"title":1481,"path":1482,"stem":1483},"Collections Binding Part 1 — ObservableCollection та ItemsControl","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part1","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part1",{"title":1485,"path":1486,"stem":1487},"Collections Binding Part 2 — ICollectionView, Filtering, Sorting та Virtualization","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part2","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part2",{"title":1489,"path":1490,"stem":1491},"MVVM Pattern — Від Spaghetti Code до архітектури","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-pattern","01.csharp\u002F12.desktop-ui\u002F22.mvvm-pattern",{"title":1493,"path":1494,"stem":1495},"ViewModel Implementation — Від BaseViewModel до валідації","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-implementation","01.csharp\u002F12.desktop-ui\u002F23.viewmodel-implementation",{"title":1497,"path":1498,"stem":1499},"Commands — Від event handlers до декларативних команд","\u002Fcsharp\u002Fdesktop-ui\u002Fcommands","01.csharp\u002F12.desktop-ui\u002F24.commands",{"title":1501,"path":1502,"stem":1503},"MVVM Toolkit — MVVM без boilerplate через Source Generators","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-toolkit","01.csharp\u002F12.desktop-ui\u002F25.mvvm-toolkit",{"title":1505,"path":1506,"stem":1507},"Messenger Pattern — Комунікація між ViewModel без прямих посилань","\u002Fcsharp\u002Fdesktop-ui\u002Fmessenger-pattern","01.csharp\u002F12.desktop-ui\u002F26.messenger-pattern",{"title":1509,"path":1510,"stem":1511},"Стилі WPF — CSS для десктопу","\u002Fcsharp\u002Fdesktop-ui\u002Fstyles-basics","01.csharp\u002F12.desktop-ui\u002F27.styles-basics",{"title":1513,"path":1514,"stem":1515},"CSS-like стилі Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F27a.avalonia-css-styling","01.csharp\u002F12.desktop-ui\u002F27a.avalonia-css-styling",{"title":1517,"path":1518,"stem":1519},"Control Templates — Частина 1. Концепція та TemplateBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part1","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part1",{"title":1521,"path":1522,"stem":1523},"Control Templates — Частина 2. Named Parts та ContentPresenter","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part2","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part2",{"title":1525,"path":1526,"stem":1527},"Control Themes в Avalonia — нова ера стилізації","\u002Fcsharp\u002Fdesktop-ui\u002F28a.avalonia-control-themes","01.csharp\u002F12.desktop-ui\u002F28a.avalonia-control-themes",{"title":1529,"path":1530,"stem":1531},"Triggers та Visual State Manager у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Ftriggers-visual-states","01.csharp\u002F12.desktop-ui\u002F29.triggers-visual-states",{"title":1533,"path":1534,"stem":1535},"Pseudo-classes в Avalonia — замість WPF Triggers","\u002Fcsharp\u002Fdesktop-ui\u002F29a.avalonia-pseudo-classes","01.csharp\u002F12.desktop-ui\u002F29a.avalonia-pseudo-classes",{"title":1537,"path":1538,"stem":1539},"Теми та ресурсні словники у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fresources-themes","01.csharp\u002F12.desktop-ui\u002F30.resources-themes",{"title":1541,"path":1542,"stem":1543},"Avalonia Themes — Fluent Design та система тематизації","\u002Fcsharp\u002Fdesktop-ui\u002F30a.avalonia-themes-fluent","01.csharp\u002F12.desktop-ui\u002F30a.avalonia-themes-fluent",{"title":1545,"path":1546,"stem":1547},"Контроли колекцій — глибоке занурення","\u002Fcsharp\u002Fdesktop-ui\u002Fcollection-controls","01.csharp\u002F12.desktop-ui\u002F31.collection-controls",{"title":1549,"path":1550,"stem":1551},"DataGrid — колонки та базове відображення","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part1","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part1",{"title":1553,"path":1554,"stem":1555},"DataGrid — сортування, фільтрація, редагування","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part2","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part2",{"title":1557,"path":1558,"stem":1559},"TreeView та GridView","\u002Fcsharp\u002Fdesktop-ui\u002Ftreeview-listview","01.csharp\u002F12.desktop-ui\u002F33.treeview-listview",{"title":1561,"path":1562,"stem":1563},"Меню, Toolbar, ContextMenu, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fmenus-toolbars","01.csharp\u002F12.desktop-ui\u002F34.menus-toolbars",{"title":1565,"path":1566,"stem":1567},"Навігація та керування вікнами. Частина 1: вікна та сторінки","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part1","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part1",{"title":1569,"path":1570,"stem":1571},"Навігація та керування вікнами. Частина 2: MVVM-навігація","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part2","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part2",{"title":1573,"path":1574,"stem":1575},"Avalonia — Навігація та діалоги","\u002Fcsharp\u002Fdesktop-ui\u002F35a.avalonia-navigation-dialogs","01.csharp\u002F12.desktop-ui\u002F35a.avalonia-navigation-dialogs",{"title":1577,"path":1578,"stem":1579},"Діалоги та File Pickers у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdialogs-file-pickers","01.csharp\u002F12.desktop-ui\u002F36.dialogs-file-pickers",{"title":1581,"path":1582,"stem":1583},"UserControl: компонентний підхід у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fuser-controls","01.csharp\u002F12.desktop-ui\u002F37.user-controls",{"title":1585,"path":1586,"stem":1587},"Custom Controls: Lookless Controls у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fcustom-controls","01.csharp\u002F12.desktop-ui\u002F38.custom-controls",{"title":1589,"path":1590,"stem":1591},"Avalonia TemplatedControl — Lookless Controls","\u002Fcsharp\u002Fdesktop-ui\u002F38a.avalonia-templated-controls","01.csharp\u002F12.desktop-ui\u002F38a.avalonia-templated-controls",{"title":1593,"path":1594,"stem":1595},"Анімації у WPF: Storyboard та Easing Functions","\u002Fcsharp\u002Fdesktop-ui\u002Fanimations-transitions","01.csharp\u002F12.desktop-ui\u002F39.animations-transitions",{"title":1597,"path":1598,"stem":1599},"Анімації в Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F39a.avalonia-animations","01.csharp\u002F12.desktop-ui\u002F39a.avalonia-animations",{"title":1601,"path":1602,"stem":1603},"2D Графіка та Мультимедіа у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fmedia-graphics","01.csharp\u002F12.desktop-ui\u002F40.media-graphics",{"title":1605,"path":1606,"stem":1607},"Dependency Injection у WPF та Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Fdi-integration","01.csharp\u002F12.desktop-ui\u002F41.di-integration",{"title":1609,"path":1610,"stem":1611},"SQLite та EF Core у десктопних додатках","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part1","01.csharp\u002F12.desktop-ui\u002F42.data-persistence-part1",{"title":1613,"path":1614,"stem":1615},"Repository Pattern та Unit of Work","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part2","01.csharp\u002F12.desktop-ui\u002F43.data-persistence-part2",{"title":1617,"path":1618,"stem":1619},"Тестування ViewModels","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-testing","01.csharp\u002F12.desktop-ui\u002F44.viewmodel-testing",{"title":1621,"path":1622,"stem":1623},"Avalonia Headless Testing — тестування UI без вікон","\u002Fcsharp\u002Fdesktop-ui\u002F44a.avalonia-headless-testing","01.csharp\u002F12.desktop-ui\u002F44a.avalonia-headless-testing",{"title":1625,"path":1626,"stem":1627},"Кросплатформна розробка з Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-cross-platform","01.csharp\u002F12.desktop-ui\u002F45.avalonia-cross-platform",{"title":1629,"path":1630,"stem":1631},"Пакування та розгортання Avalonia додатків","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F46.avalonia-packaging-deployment",{"title":1633,"path":1634,"stem":1635},"Розгортання WPF застосунків","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F47.wpf-packaging-deployment",{"title":1637,"icon":658,"path":1638,"stem":1639,"children":1640,"page":59},"Network Programming","\u002Fcsharp\u002Fnetwork-programming","01.csharp\u002F13.network-programming",[1641,1645,1649,1653,1657,1661],{"title":1642,"path":1643,"stem":1644},"Основи комп'ютерних мереж","\u002Fcsharp\u002Fnetwork-programming\u002Ffoundations","01.csharp\u002F13.network-programming\u002F01.foundations",{"title":1646,"path":1647,"stem":1648},"Модель OSI та стек TCP\u002FIP","\u002Fcsharp\u002Fnetwork-programming\u002Fosi-model","01.csharp\u002F13.network-programming\u002F02.osi-model",{"title":1650,"path":1651,"stem":1652},"IP-протокол та адресація","\u002Fcsharp\u002Fnetwork-programming\u002Fip-addressing","01.csharp\u002F13.network-programming\u002F03.ip-addressing",{"title":1654,"path":1655,"stem":1656},"UDP — протокол без з'єднання","\u002Fcsharp\u002Fnetwork-programming\u002Fudp","01.csharp\u002F13.network-programming\u002F05.udp",{"title":1658,"path":1659,"stem":1660},"UDP Broadcast та Multicast","\u002Fcsharp\u002Fnetwork-programming\u002Fudp-broadcast-multicast","01.csharp\u002F13.network-programming\u002F06.udp-broadcast-multicast",{"title":1662,"path":1663,"stem":1664},"HTTP — протокол вебу","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-fundamentals","01.csharp\u002F13.network-programming\u002F07.http-fundamentals",{"title":1666,"path":1667,"stem":1668},"C# & .NET: The Ultimate Roadmap","\u002Fcsharp\u002Froadmap","01.csharp\u002Froadmap",{"title":1670,"icon":1671,"path":1672,"stem":1673,"children":1674,"page":59},"C++","i-devicon-cplusplus","\u002Fcpp","02.cpp",[1675,1679,1683,1687,1691,1695,1699,1703,1707,1710,1714,1718,1722,1726,1730,1734,1738,1742,1746,1750,1754,1758,1762,1766,1770,1774,1778,1782,1786,1790,1794,1798,1802,1806,1810,1814,1818,1822],{"title":1676,"path":1677,"stem":1678},"Вступ у програмування та алгоритми","\u002Fcpp\u002Fintro-algorithms","02.cpp\u002F01.intro-algorithms",{"title":1680,"path":1681,"stem":1682},"Code Style: угоди про оформлення коду","\u002Fcpp\u002Fcode-style","02.cpp\u002F02.code-style",{"title":1684,"path":1685,"stem":1686},"Середовище розробки та перший проєкт","\u002Fcpp\u002Fide-setup","02.cpp\u002F03.ide-setup",{"title":1688,"path":1689,"stem":1690},"Вивід даних на екран","\u002Fcpp\u002Fdata-output","02.cpp\u002F04.data-output",{"title":1692,"path":1693,"stem":1694},"Типи даних, змінні та константи","\u002Fcpp\u002Fdata-types-variables","02.cpp\u002F05.data-types-variables",{"title":1696,"path":1697,"stem":1698},"Ввід даних з клавіатури","\u002Fcpp\u002Fdata-input","02.cpp\u002F06.data-input",{"title":1700,"path":1701,"stem":1702},"Оператори, перетворення типів та логічні операції","\u002Fcpp\u002Foperators-type-conversion","02.cpp\u002F07.operators-type-conversion",{"title":1704,"path":1705,"stem":1706},"Цикли","\u002Fcpp\u002Floops","02.cpp\u002F08.loops",{"title":32,"path":1708,"stem":1709},"\u002Fcpp\u002Farrays","02.cpp\u002F09.arrays",{"title":1711,"path":1712,"stem":1713},"Алгоритми сортування та аналіз складності","\u002Fcpp\u002Fsorting","02.cpp\u002F10.sorting",{"title":1715,"path":1716,"stem":1717},"Алгоритми пошуку","\u002Fcpp\u002Fsearching","02.cpp\u002F11.searching",{"title":1719,"path":1720,"stem":1721},"Функції: основи","\u002Fcpp\u002Ffunctions-basics","02.cpp\u002F12.functions-basics",{"title":1723,"path":1724,"stem":1725},"Функції: прототипи, область видимості та додаткові можливості","\u002Fcpp\u002Ffunctions-scope","02.cpp\u002F13.functions-scope",{"title":1727,"path":1728,"stem":1729},"Функції: перевантаження та шаблони","\u002Fcpp\u002Ffunctions-overloading-templates","02.cpp\u002F14.functions-overloading-templates",{"title":1731,"path":1732,"stem":1733},"Вказівники: основи","\u002Fcpp\u002Fpointers-basics","02.cpp\u002F15.pointers-basics",{"title":1735,"path":1736,"stem":1737},"Посилання (References)","\u002Fcpp\u002Freferences","02.cpp\u002F16.references",{"title":1739,"path":1740,"stem":1741},"Вказівники, const і масиви","\u002Fcpp\u002Fpointers-const-arrays","02.cpp\u002F17.pointers-const-arrays",{"title":1743,"path":1744,"stem":1745},"Адресна арифметика","\u002Fcpp\u002Fpointer-arithmetic","02.cpp\u002F18.pointer-arithmetic",{"title":1747,"path":1748,"stem":1749},"Динамічна пам'ять","\u002Fcpp\u002Fdynamic-memory","02.cpp\u002F19.dynamic-memory",{"title":1751,"path":1752,"stem":1753},"Вказівники типу void","\u002Fcpp\u002Fvoid-pointers","02.cpp\u002F20.void-pointers",{"title":1755,"path":1756,"stem":1757},"Вказівники на вказівники","\u002Fcpp\u002Fpointers-to-pointers","02.cpp\u002F21.pointers-to-pointers",{"title":1759,"path":1760,"stem":1761},"Оператор доступу до членів через вказівник (->)","\u002Fcpp\u002Fmember-access-operator","02.cpp\u002F22.member-access-operator",{"title":1763,"path":1764,"stem":1765},"Цикл for-each (Range-based for)","\u002Fcpp\u002Fforeach-loop","02.cpp\u002F23.foreach-loop",{"title":1767,"path":1768,"stem":1769},"Вказівники на функції","\u002Fcpp\u002Ffunction-pointers","02.cpp\u002F24.function-pointers",{"title":1771,"path":1772,"stem":1773},"Лямбда-вирази","\u002Fcpp\u002Flambdas","02.cpp\u002F25.lambdas",{"title":1775,"path":1776,"stem":1777},"Лямбда-захоплення","\u002Fcpp\u002Flambda-captures","02.cpp\u002F26.lambda-captures",{"title":1779,"path":1780,"stem":1781},"Еліпсис","\u002Fcpp\u002Fellipsis","02.cpp\u002F27.ellipsis",{"title":1783,"path":1784,"stem":1785},"Безпечні альтернативи еліпсису","\u002Fcpp\u002F27a.ellipsis","02.cpp\u002F27a.ellipsis",{"title":1787,"path":1788,"stem":1789},"Аргументи командного рядка","\u002Fcpp\u002Fcommand-line-arguments","02.cpp\u002F28.command-line-arguments",{"title":1791,"path":1792,"stem":1793},"Перерахування (enum)","\u002Fcpp\u002Fenum","02.cpp\u002F29.enum",{"title":1795,"path":1796,"stem":1797},"Класи-перерахування (enum class)","\u002Fcpp\u002Fenum-class","02.cpp\u002F30.enum-class",{"title":1799,"path":1800,"stem":1801},"Псевдоніми типів (typedef і using)","\u002Fcpp\u002Ftype-aliases","02.cpp\u002F31.type-aliases",{"title":1803,"path":1804,"stem":1805},"Системи числення та двійкова арифметика","\u002Fcpp\u002Fnumber-systems","02.cpp\u002F32.number-systems",{"title":1807,"path":1808,"stem":1809},"Структури (struct): агрегування даних","\u002Fcpp\u002Fstruct","02.cpp\u002F33.struct",{"title":1811,"path":1812,"stem":1813},"Структури у функціях","\u002Fcpp\u002Fstruct-functions","02.cpp\u002F34.struct-functions",{"title":1815,"path":1816,"stem":1817},"Масиви структур і вкладені структури","\u002Fcpp\u002Fstruct-arrays","02.cpp\u002F35.struct-arrays",{"title":1819,"path":1820,"stem":1821},"Патерни struct та межі застосування","\u002Fcpp\u002Fstruct-patterns","02.cpp\u002F36.struct-patterns",{"title":1823,"path":1824,"stem":1825},"План навчання: Курс C++ — Продовження (Статті 29–60+)","\u002Fcpp\u002Fcurriculum-plan","02.cpp\u002Fcurriculum-plan",{"title":1827,"icon":1828,"path":1829,"stem":1830,"children":1831,"page":59},"JavaScript","i-devicon-javascript","\u002Fjavascript","03.javascript",[1832,1858,1912,1934,2238,2276],{"title":1833,"icon":1834,"path":1835,"stem":1836,"children":1837,"page":59},"Events","i-lucide-mouse-pointer-click","\u002Fjavascript\u002Fevents","03.javascript\u002F01.events",[1838,1842,1846,1850,1854],{"title":1839,"path":1840,"stem":1841},"Вступ до подій браузера","\u002Fjavascript\u002Fevents\u002Fintro","03.javascript\u002F01.events\u002F01.intro",{"title":1843,"path":1844,"stem":1845},"Бульбашковий механізм (Bubbling) та занурення (Capturing)","\u002Fjavascript\u002Fevents\u002Fbubbling-capturing","03.javascript\u002F01.events\u002F02.bubbling-capturing",{"title":1847,"path":1848,"stem":1849},"Делегування подій (Event Delegation)","\u002Fjavascript\u002Fevents\u002Fdelegate-events","03.javascript\u002F01.events\u002F03.delegate-events",{"title":1851,"path":1852,"stem":1853},"Типові дії браузера та preventDefault()","\u002Fjavascript\u002Fevents\u002Fprevent-default","03.javascript\u002F01.events\u002F04.prevent-default",{"title":1855,"path":1856,"stem":1857},"Запуск користувацьких подій (Custom Events)","\u002Fjavascript\u002Fevents\u002Fcustom-events","03.javascript\u002F01.events\u002F05.custom-events",{"title":1859,"icon":1860,"path":1861,"stem":1862,"children":1863,"page":59},"Network","i-lucide-globe","\u002Fjavascript\u002Fnetwork","03.javascript\u002F02.network",[1864,1868,1872,1876,1880,1884,1888,1892,1896,1900,1904,1908],{"title":1865,"path":1866,"stem":1867},"Fetch API - Сучасний підхід до HTTP-запитів","\u002Fjavascript\u002Fnetwork\u002F01-fetch-api","03.javascript\u002F02.network\u002F01-fetch-api",{"title":1869,"path":1870,"stem":1871},"FormData - Робота з формами та файлами","\u002Fjavascript\u002Fnetwork\u002F02-formdata","03.javascript\u002F02.network\u002F02-formdata",{"title":1873,"path":1874,"stem":1875},"Відстеження прогресу завантаження","\u002Fjavascript\u002Fnetwork\u002F03-download-progress","03.javascript\u002F02.network\u002F03-download-progress",{"title":1877,"path":1878,"stem":1879},"Переривання fetch-запитів","\u002Fjavascript\u002Fnetwork\u002F04-abort-requests","03.javascript\u002F02.network\u002F04-abort-requests",{"title":1881,"path":1882,"stem":1883},"CORS - Запити між різними джерелами","\u002Fjavascript\u002Fnetwork\u002F05-cors","03.javascript\u002F02.network\u002F05-cors",{"title":1885,"path":1886,"stem":1887},"Fetch API - Повний довідник опцій","\u002Fjavascript\u002Fnetwork\u002F06-fetch-options","03.javascript\u002F02.network\u002F06-fetch-options",{"title":1889,"path":1890,"stem":1891},"URL Objects - Робота з посиланнями","\u002Fjavascript\u002Fnetwork\u002F07-url-objects","03.javascript\u002F02.network\u002F07-url-objects",{"title":1893,"path":1894,"stem":1895},"XMLHttpRequest - AJAX та низькорівневі запити","\u002Fjavascript\u002Fnetwork\u002F08-xmlhttprequest","03.javascript\u002F02.network\u002F08-xmlhttprequest",{"title":1897,"path":1898,"stem":1899},"Відновлюване завантаження файлів","\u002Fjavascript\u002Fnetwork\u002F09-resumable-upload","03.javascript\u002F02.network\u002F09-resumable-upload",{"title":1901,"path":1902,"stem":1903},"Cookies, document.cookie та світ після \"Cookiepocalypse\"","\u002Fjavascript\u002Fnetwork\u002F10-cookies","03.javascript\u002F02.network\u002F10-cookies",{"title":1905,"path":1906,"stem":1907},"js-cookie: Керування Cookies без Болю","\u002Fjavascript\u002Fnetwork\u002F11-js-cookie","03.javascript\u002F02.network\u002F11-js-cookie",{"title":1909,"path":1910,"stem":1911},"Axios: Потужний HTTP-клієнт для JavaScript","\u002Fjavascript\u002Fnetwork\u002F12-axios","03.javascript\u002F02.network\u002F12-axios",{"title":1913,"icon":1914,"path":1915,"stem":1916,"children":1917,"page":59},"Bom","i-lucide-monitor","\u002Fjavascript\u002Fbom","03.javascript\u002F03.bom",[1918,1922,1926,1930],{"title":1919,"path":1920,"stem":1921},"LocalStorage, SessionStorage та patterns збереження даних","\u002Fjavascript\u002Fbom\u002F01-localstorage","03.javascript\u002F03.bom\u002F01-localstorage",{"title":1923,"path":1924,"stem":1925},"Location Object - Керування адресою сторінки","\u002Fjavascript\u002Fbom\u002F02-location-object","03.javascript\u002F03.bom\u002F02-location-object",{"title":1927,"path":1928,"stem":1929},"History API - Керування історією браузера","\u002Fjavascript\u002Fbom\u002F03-history-api","03.javascript\u002F03.bom\u002F03-history-api",{"title":1931,"path":1932,"stem":1933},"Navigator Object - Ідентифікація та Можливості Пристрою","\u002Fjavascript\u002Fbom\u002F04-navigator-object","03.javascript\u002F03.bom\u002F04-navigator-object",{"title":1935,"icon":1936,"path":1937,"stem":1938,"children":1939},"React","i-devicon-react","\u002Fjavascript\u002Freact","03.javascript\u002F04.react\u002Findex",[1940,1941,1945,1949,1953,1957,2020,2055,2207],{"title":1935,"path":1937,"stem":1938},{"title":1942,"path":1943,"stem":1944},"Робота з Формами в React","\u002Fjavascript\u002Freact\u002Freact-forms","03.javascript\u002F04.react\u002F01.react-forms",{"title":1946,"path":1947,"stem":1948},"React Hook Form: Професійна Робота з Формами","\u002Fjavascript\u002Freact\u002Freact-hook-form","03.javascript\u002F04.react\u002F02.react-hook-form",{"title":1950,"path":1951,"stem":1952},"React Hook Form: Глибоке Розуміння Архітектури та Оптимізації","\u002Fjavascript\u002Freact\u002Freact-hook-form-new","03.javascript\u002F04.react\u002F02.react-hook-form-new",{"title":1954,"path":1955,"stem":1956},"Axios та React: Професійна Архітектура Запитів","\u002Fjavascript\u002Freact\u002Fdata-fetching-axios","03.javascript\u002F04.react\u002F03.data-fetching-axios",{"title":1958,"icon":132,"path":1959,"stem":1960,"children":1961},"Tanstack Query","\u002Fjavascript\u002Freact\u002Ftanstack-query","03.javascript\u002F04.react\u002F04.tanstack-query\u002Findex",[1962,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004,2008,2012,2016],{"title":1963,"path":1959,"stem":1960},"TanStack Query: Майстерність Керування Станом Сервера",{"title":1965,"path":1966,"stem":1967},"Парадигма Server State: Чому useEffect недостатньо","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-state-paradigm","03.javascript\u002F04.react\u002F04.tanstack-query\u002F01.server-state-paradigm",{"title":1969,"path":1970,"stem":1971},"Встановлення та Налаштування: Фундамент","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Finstallation-and-devtools","03.javascript\u002F04.react\u002F04.tanstack-query\u002F02.installation-and-devtools",{"title":1973,"path":1974,"stem":1975},"Основи Запитів та Магія Ключів","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fquery-basics-and-keys","03.javascript\u002F04.react\u002F04.tanstack-query\u002F03.query-basics-and-keys",{"title":1977,"path":1978,"stem":1979},"Синхронізація Даних: Життєвий Цикл Запиту","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fdata-synchronization","03.javascript\u002F04.react\u002F04.tanstack-query\u002F04.data-synchronization",{"title":1981,"path":1982,"stem":1983},"Мутації та Інвалідація: Зміна Даних","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fmutations-and-invalidation","03.javascript\u002F04.react\u002F04.tanstack-query\u002F05.mutations-and-invalidation",{"title":1985,"path":1986,"stem":1987},"Оптимістичні Оновлення: Швидше за Світло","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Foptimistic-updates","03.javascript\u002F04.react\u002F04.tanstack-query\u002F06.optimistic-updates",{"title":1989,"path":1990,"stem":1991},"Пагінація та Infinite Scroll","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fpagination-and-load-more","03.javascript\u002F04.react\u002F04.tanstack-query\u002F07.pagination-and-load-more",{"title":1993,"path":1994,"stem":1995},"Просунуті Патерни та Оптимізація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F04.tanstack-query\u002F08.advanced-patterns",{"title":1997,"path":1998,"stem":1999},"Архітектура та Best Practices","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Farchitecture-and-best-practices","03.javascript\u002F04.react\u002F04.tanstack-query\u002F09.architecture-and-best-practices",{"title":2001,"path":2002,"stem":2003},"Server-Side Rendering (SSR) та Гідратація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-side-rendering","03.javascript\u002F04.react\u002F04.tanstack-query\u002F10.server-side-rendering",{"title":2005,"path":2006,"stem":2007},"Стратегії Тестування","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Ftesting-strategies","03.javascript\u002F04.react\u002F04.tanstack-query\u002F11.testing-strategies",{"title":2009,"path":2010,"stem":2011},"Аутентифікація та Обробка Помилок","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fauthentication-and-errors","03.javascript\u002F04.react\u002F04.tanstack-query\u002F12.authentication-and-errors",{"title":2013,"path":2014,"stem":2015},"React Suspense та Майбутнє","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Freact-suspense","03.javascript\u002F04.react\u002F04.tanstack-query\u002F13.react-suspense",{"title":2017,"path":2018,"stem":2019},"Глибоке Занурення в Продуктивність","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fperformance-deep-dive","03.javascript\u002F04.react\u002F04.tanstack-query\u002F14.performance-deep-dive",{"title":2021,"icon":1936,"path":2022,"stem":2023,"children":2024},"React Router","\u002Fjavascript\u002Freact\u002Freact-router","03.javascript\u002F04.react\u002F05.react-router\u002Findex",[2025,2027,2031,2035,2039,2043,2047,2051],{"title":2026,"path":2022,"stem":2023},"React Router: Навігаційна система сучасного вебу",{"title":2028,"path":2029,"stem":2030},"Налаштування та Базовий Роутинг","\u002Fjavascript\u002Freact\u002Freact-router\u002Fsetup-and-basic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F01.setup-and-basic-routing",{"title":2032,"path":2033,"stem":2034},"Динамічна Навігація","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnavigation-and-links","03.javascript\u002F04.react\u002F05.react-router\u002F02.navigation-and-links",{"title":2036,"path":2037,"stem":2038},"Вкладені Маршрути та Макети","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnested-routes-and-layouts","03.javascript\u002F04.react\u002F05.react-router\u002F03.nested-routes-and-layouts",{"title":2040,"path":2041,"stem":2042},"Динамічні Маршрути та Параметри","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdynamic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F04.dynamic-routing",{"title":2044,"path":2045,"stem":2046},"Data APIs: Loaders та Actions","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdata-loading","03.javascript\u002F04.react\u002F05.react-router\u002F05.data-loading",{"title":2048,"path":2049,"stem":2050},"Просунуті Патерни","\u002Fjavascript\u002Freact\u002Freact-router\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F05.react-router\u002F06.advanced-patterns",{"title":2052,"path":2053,"stem":2054},"Legacy Routing: Компонентний підхід","\u002Fjavascript\u002Freact\u002Freact-router\u002Flegacy-routing","03.javascript\u002F04.react\u002F05.react-router\u002F07.legacy-routing",{"title":2056,"icon":132,"path":2057,"stem":2058,"children":2059},"Redux","\u002Fjavascript\u002Freact\u002Fredux","03.javascript\u002F04.react\u002F06.redux\u002Findex",[2060,2062,2078,2107,2116,2137,2153,2182],{"title":2061,"path":2057,"stem":2058},"Redux: Еволюція управління станом",{"title":14,"icon":15,"path":2063,"stem":2064,"children":2065,"page":59},"\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals",[2066,2070,2074],{"title":2067,"path":2068,"stem":2069},"Вступ до State Management","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fintro-state-management","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F01.intro-state-management",{"title":2071,"path":2072,"stem":2073},"Філософія Redux та Три Принципи","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fredux-philosophy","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F02.redux-philosophy",{"title":2075,"path":2076,"stem":2077},"Чисті функції та Іммутабельність","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fpure-functions-immutability","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F03.pure-functions-immutability",{"title":2079,"icon":132,"path":2080,"stem":2081,"children":2082,"page":59},"Classic Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux",[2083,2087,2091,2095,2099,2103],{"title":2084,"path":2085,"stem":2086},"Створення Store (Classic Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fstore-setup","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F01.store-setup",{"title":2088,"path":2089,"stem":2090},"Actions, Constants та Action Creators","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Factions-constants","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F02.actions-constants",{"title":2092,"path":2093,"stem":2094},"Логіка Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freducers","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F03.reducers",{"title":2096,"path":2097,"stem":2098},"Комбінування Reducers (Root Reducer)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fdata-flow","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F04.data-flow",{"title":2100,"path":2101,"stem":2102},"Підключення до 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":2104,"path":2105,"stem":2106},"Middleware та Асинхронність (Redux Thunk)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fmiddleware-thunk","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F06.middleware-thunk",{"title":2108,"icon":132,"path":2109,"stem":2110,"children":2111,"page":59},"Transition To Rtk","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk",[2112],{"title":2113,"path":2114,"stem":2115},"Проблеми класичного 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":2117,"icon":132,"path":2118,"stem":2119,"children":2120,"page":59},"Redux Toolkit","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit",[2121,2125,2129,2133],{"title":2122,"path":2123,"stem":2124},"Налаштування Store з configureStore","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fconfigure-store","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F01.configure-store",{"title":2126,"path":2127,"stem":2128},"createSlice: Революція в Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fcreate-slice","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F02.create-slice",{"title":2130,"path":2131,"stem":2132},"Асинхронність з createAsyncThunk","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fasync-thunks","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F03.async-thunks",{"title":2134,"path":2135,"stem":2136},"04. Entity Adapter: Керування нормалізованим станом","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fentity-adapter","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F04.entity-adapter",{"title":2138,"icon":92,"path":2139,"stem":2140,"children":2141,"page":59},"Advanced","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced",[2142,2146,2150],{"title":2143,"path":2144,"stem":2145},"Мемоізація та Селектори: Повний Гайд по Reselect","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Fselectors-reselect","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F01.selectors-reselect",{"title":2147,"path":2148,"stem":2149},"RTK Query: Архітектура Серверного Кешу","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Frtk-query-intro","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F02.rtk-query-intro",{"title":1997,"path":2151,"stem":2152},"\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Farchitecture-best-practices","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F03.architecture-best-practices",{"title":2154,"icon":132,"path":2155,"stem":2156,"children":2157,"page":59},"Project Kanban","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban",[2158,2162,2166,2170,2174,2178],{"title":2159,"path":2160,"stem":2161},"Проєкт: Kanban Board (Trello Clone)","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fproject-overview","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F01.project-overview",{"title":2163,"path":2164,"stem":2165},"Налаштування та Типізація","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fsetup-and-types","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F02.setup-and-types",{"title":2167,"path":2168,"stem":2169},"Board Slice: Серце Дошки","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fboard-slice","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F03.board-slice",{"title":2171,"path":2172,"stem":2173},"Логіка 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":2175,"path":2176,"stem":2177},"Інтеграція з RTK Query","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Frtk-query-integration","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F05.rtk-query-integration",{"title":2179,"path":2180,"stem":2181},"Optimistic Updates","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Foptimistic-updates","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F06.optimistic-updates",{"title":2183,"icon":132,"path":2184,"stem":2185,"children":2186,"page":59},"Testing","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting","03.javascript\u002F04.react\u002F06.redux\u002F07.testing",[2187,2191,2195,2199,2203],{"title":2188,"path":2189,"stem":2190},"Тестування Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Fintro-testing","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F01.intro-testing",{"title":2192,"path":2193,"stem":2194},"Тестування Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-reducers","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F02.testing-reducers",{"title":2196,"path":2197,"stem":2198},"Тестування Селекторів","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-selectors","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F03.testing-selectors",{"title":2200,"path":2201,"stem":2202},"Тестування Компонентів (Integration)","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-components","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F04.testing-components",{"title":2204,"path":2205,"stem":2206},"Тестування Async Thunks","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-thunks","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F05.testing-thunks",{"title":2208,"icon":132,"path":2209,"stem":2210,"children":2211},"Ui Libraries","\u002Fjavascript\u002Freact\u002Fui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002Findex",[2212,2214,2218,2222,2226,2230,2234],{"title":2213,"path":2209,"stem":2210},"UI Бібліотеки в React",{"title":2215,"path":2216,"stem":2217},"Вступ до UI Бібліотек: Навіщо Винаходити Велосипед Двічі?","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fintroduction-to-ui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002F01.introduction-to-ui-libraries",{"title":2219,"path":2220,"stem":2221},"Філософія shadcn\u002Fui: \"Not a Component Library\"","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-philosophy","03.javascript\u002F04.react\u002F07.ui-libraries\u002F02.shadcn-philosophy",{"title":2223,"path":2224,"stem":2225},"Установка та Налаштування shadcn\u002Fui","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-installation","03.javascript\u002F04.react\u002F07.ui-libraries\u002F03.shadcn-installation",{"title":2227,"path":2228,"stem":2229},"Базові Компоненти shadcn\u002Fui: Фундамент Інтерфейсу","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-basics","03.javascript\u002F04.react\u002F07.ui-libraries\u002F04.shadcn-components-basics",{"title":2231,"path":2232,"stem":2233},"Компоненти Форм: Побудова Інтерактивних Form","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-forms","03.javascript\u002F04.react\u002F07.ui-libraries\u002F05.shadcn-components-forms",{"title":2235,"path":2236,"stem":2237},"Складні Компоненти: Dialog, Dropdown, Table та Command","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-advanced","03.javascript\u002F04.react\u002F07.ui-libraries\u002F06.shadcn-components-advanced",{"title":2239,"icon":2240,"path":2241,"stem":2242,"children":2243,"page":59},"TypeScript","i-devicon-typescript","\u002Fjavascript\u002Ftypescript","03.javascript\u002F05.typescript",[2244,2248,2252,2256,2260,2264,2268,2272],{"title":2245,"path":2246,"stem":2247},"TypeScript: Броня для вашого коду","\u002Fjavascript\u002Ftypescript\u002Fintro-and-basic-types","03.javascript\u002F05.typescript\u002F01.intro-and-basic-types",{"title":2249,"path":2250,"stem":2251},"Майстерність Моделювання Даних: Інтерфейси та Просунуті Типи","\u002Fjavascript\u002Ftypescript\u002Finterfaces-and-advanced-types","03.javascript\u002F05.typescript\u002F02.interfaces-and-advanced-types",{"title":2253,"path":2254,"stem":2255},"Алхімія Типів: Generics та Utility Types","\u002Fjavascript\u002Ftypescript\u002Fgenerics-and-utilities","03.javascript\u002F05.typescript\u002F03.generics-and-utilities",{"title":2257,"path":2258,"stem":2259},"Архітектура та Шаблони: Класи в TypeScript","\u002Fjavascript\u002Ftypescript\u002Fclasses-and-oop","03.javascript\u002F05.typescript\u002F04.classes-and-oop",{"title":2261,"path":2262,"stem":2263},"Продакшн та Екосистема: Advanced Config & Workflow","\u002Fjavascript\u002Ftypescript\u002Fadvanced-patterns-and-config","03.javascript\u002F05.typescript\u002F05.advanced-patterns-and-config",{"title":2265,"path":2266,"stem":2267},"TypeScript у світі React","\u002Fjavascript\u002Ftypescript\u002Freact-basics","03.javascript\u002F05.typescript\u002F06.react-basics",{"title":2269,"path":2270,"stem":2271},"React + TypeScript: Продвинуті патерни","\u002Fjavascript\u002Ftypescript\u002Freact-advanced","03.javascript\u002F05.typescript\u002F07.react-advanced",{"title":2273,"path":2274,"stem":2275},"React + TypeScript: Екосистема та бібліотеки","\u002Fjavascript\u002Ftypescript\u002Freact-ecosystem","03.javascript\u002F05.typescript\u002F08.react-ecosystem",{"title":2277,"path":2278,"stem":2279},"Atomic Design","\u002Fjavascript\u002Fatomic-design","03.javascript\u002F2.atomic-design",{"title":2281,"icon":2282,"path":2283,"stem":2284,"children":2285,"page":59},"Java","i-devicon-java","\u002Fjava","04.java",[2286,2289,2292,2296,2300,2304,2308],{"title":162,"path":2287,"stem":2288},"\u002Fjava\u002Fdata-mapper-part1","04.java\u002F01.data-mapper-part1",{"title":166,"path":2290,"stem":2291},"\u002Fjava\u002Fdata-mapper-part2","04.java\u002F02.data-mapper-part2",{"title":2293,"path":2294,"stem":2295},"Service Layer: Організація бізнес-логіки","\u002Fjava\u002Fservice-layer","04.java\u002F03.service-layer",{"title":2297,"path":2298,"stem":2299},"Rich Domain Model та State Pattern","\u002Fjava\u002Frich-domain-model","04.java\u002F04.rich-domain-model",{"title":2301,"path":2302,"stem":2303},"Патерни для складної бізнес-логіки","\u002Fjava\u002Fbusiness-logic-patterns","04.java\u002F05.business-logic-patterns",{"title":2305,"path":2306,"stem":2307},"Обробка помилок та валідація","\u002Fjava\u002Ferror-handling-validation","04.java\u002F06.error-handling-validation",{"title":2309,"path":2310,"stem":2311,"children":2312,"page":59},"Проектування баз даних","\u002Fjava\u002Fpr2","04.java\u002Fpr2",[2313,2317,2321,2325,2329,2333,2337,2341,2345,2349,2353,2357,2361,2365,2369,2373,2377,2381,2385,2389,2393,2397,2401,2405,2409,2413,2417,2421,2425,2429,2433,2437,2441,2445,2449,2453,2457],{"title":2314,"path":2315,"stem":2316},"Концептуальне моделювання: Мистецтво розуміння предметної області","\u002Fjava\u002Fpr2\u002Fconceptual-modeling","04.java\u002Fpr2\u002F01.conceptual-modeling",{"title":2318,"path":2319,"stem":2320},"Логічне моделювання: Від бізнес-ідей до структур даних","\u002Fjava\u002Fpr2\u002Flogical-modeling","04.java\u002Fpr2\u002F02.logical-modeling",{"title":2322,"path":2323,"stem":2324},"Нормалізація: Гігієна даних та боротьба з аномаліями","\u002Fjava\u002Fpr2\u002Fnormalization","04.java\u002Fpr2\u002F03.normalization",{"title":2326,"path":2327,"stem":2328},"Фізична схема: Від абстракції до DDL","\u002Fjava\u002Fpr2\u002Fphysical-schema","04.java\u002Fpr2\u002F04.physical-schema",{"title":2330,"path":2331,"stem":2332},"Архітектурна класифікація таблиць","\u002Fjava\u002Fpr2\u002Ftable-classification","04.java\u002Fpr2\u002F05.table-classification",{"title":2334,"path":2335,"stem":2336},"Database Migrations: Версіонування схеми з Flyway","\u002Fjava\u002Fpr2\u002Fdatabase-migrations","04.java\u002Fpr2\u002F06.database-migrations",{"title":2338,"path":2339,"stem":2340},"А що, якби це була не реляційна БД?","\u002Fjava\u002Fpr2\u002Fbeyond-relational","04.java\u002Fpr2\u002F07.beyond-relational",{"title":2342,"path":2343,"stem":2344},"Object-Relational Impedance Mismatch: Два світи, що не хочуть дружити","\u002Fjava\u002Fpr2\u002Fimpedance-mismatch","04.java\u002Fpr2\u002F09.impedance-mismatch",{"title":2346,"path":2347,"stem":2348},"JDBC: Перший контакт із базою даних","\u002Fjava\u002Fpr2\u002Fjdbc-fundamentals","04.java\u002Fpr2\u002F10.jdbc-fundamentals",{"title":2350,"path":2351,"stem":2352},"Якість коду: Spotless, SpotBugs та SonarQube","\u002Fjava\u002Fpr2\u002F10a.code-quality","04.java\u002Fpr2\u002F10a.code-quality",{"title":2354,"path":2355,"stem":2356},"Connection Pool: Патерн Object Pool для JDBC-з'єднань","\u002Fjava\u002Fpr2\u002Fconnection-pool","04.java\u002Fpr2\u002F11.connection-pool",{"title":2358,"path":2359,"stem":2360},"Row Data Gateway: Об'єкт як обгортка рядка таблиці","\u002Fjava\u002Fpr2\u002Frow-data-gateway","04.java\u002Fpr2\u002F12.row-data-gateway",{"title":2362,"path":2363,"stem":2364},"Table Data Gateway: Фасад таблиці як архітектурний відступ","\u002Fjava\u002Fpr2\u002Ftable-data-gateway","04.java\u002Fpr2\u002F13.table-data-gateway",{"title":2366,"path":2367,"stem":2368},"Repository + Data Mapper: Правильна шарова архітектура з JDBC","\u002Fjava\u002Fpr2\u002Frepository-data-mapper","04.java\u002Fpr2\u002F14.repository-data-mapper",{"title":2370,"path":2371,"stem":2372},"Identity Map: Кешування сутностей у рамках сесії","\u002Fjava\u002Fpr2\u002Fidentity-map","04.java\u002Fpr2\u002F15.identity-map",{"title":2374,"path":2375,"stem":2376},"Unit of Work: Відстеження змін і координація JDBC-транзакцій","\u002Fjava\u002Fpr2\u002Funit-of-work","04.java\u002Fpr2\u002F16.unit-of-work",{"title":2378,"path":2379,"stem":2380},"Strategy: Замінювані SQL-стратегії для підтримки різних СУБД","\u002Fjava\u002Fpr2\u002Fstrategy-sql","04.java\u002Fpr2\u002F17.strategy-sql",{"title":2382,"path":2383,"stem":2384},"Proxy: Lazy Loading для One-To-Many колекцій","\u002Fjava\u002Fpr2\u002Fproxy-lazy-loading","04.java\u002Fpr2\u002F18.proxy-lazy-loading",{"title":2386,"path":2387,"stem":2388},"Generic Repository через Java Reflection: анотації та динамічний SQL","\u002Fjava\u002Fpr2\u002Fgeneric-repository-reflection","04.java\u002Fpr2\u002F19.generic-repository-reflection",{"title":2390,"path":2391,"stem":2392},"Specification Pattern: Композиція бізнес-правил для складних запитів","\u002Fjava\u002Fpr2\u002Fspecification-pattern","04.java\u002Fpr2\u002F20.specification-pattern",{"title":2394,"path":2395,"stem":2396},"Розширені можливості Specification Pattern: підзапити, агрегації та гібридний підхід","\u002Fjava\u002Fpr2\u002F20a.advanced-specifications","04.java\u002Fpr2\u002F20a.advanced-specifications",{"title":2398,"path":2399,"stem":2400},"Асинхронність у JDBC: Від блокуючих викликів до CompletableFuture","\u002Fjava\u002Fpr2\u002Fasynchronous-jdbc","04.java\u002Fpr2\u002F21.asynchronous-jdbc",{"title":2402,"path":2403,"stem":2404},"Інтеграційне тестування JDBC-репозиторіїв: Embedded H2 та патерн AAA","\u002Fjava\u002Fpr2\u002Fintegration-testing-h2","04.java\u002Fpr2\u002F22.integration-testing-h2",{"title":2406,"path":2407,"stem":2408},"Testcontainers: Тестування з реальною PostgreSQL у Docker-контейнерах","\u002Fjava\u002Fpr2\u002Fintegration-testing-testcontainers","04.java\u002Fpr2\u002F23.integration-testing-testcontainers",{"title":2410,"path":2411,"stem":2412},"Google Guice: Впровадження залежностей у JavaFX-проєкті","\u002Fjava\u002Fpr2\u002Fdependency-injection-guice","04.java\u002Fpr2\u002F24.dependency-injection-guice",{"title":2414,"path":2415,"stem":2416},"JavaFX: Основи побудови графічних інтерфейсів","\u002Fjava\u002Fpr2\u002Fjavafx-fundamentals","04.java\u002Fpr2\u002F25.javafx-fundamentals",{"title":2418,"path":2419,"stem":2420},"Properties та Bindings: Реактивність у JavaFX","\u002Fjava\u002Fpr2\u002Fjavafx-properties-bindings","04.java\u002Fpr2\u002F26.javafx-properties-bindings",{"title":2422,"path":2423,"stem":2424},"MVC vs MVP vs MVVM: Еволюція архітектурних патернів UI","\u002Fjava\u002Fpr2\u002Fui-architecture-patterns","04.java\u002Fpr2\u002F27.ui-architecture-patterns",{"title":2426,"path":2427,"stem":2428},"MVVM на практиці: Побудова ViewModel","\u002Fjava\u002Fpr2\u002Fmvvm-viewmodel-implementation","04.java\u002Fpr2\u002F28.mvvm-viewmodel-implementation",{"title":2430,"path":2431,"stem":2432},"View та Controller: Зв'язування з ViewModel через FXML","\u002Fjava\u002Fpr2\u002Fmvvm-view-controller","04.java\u002Fpr2\u002F29.mvvm-view-controller",{"title":2434,"path":2435,"stem":2436},"Інтеграція MVVM з Guice: Автоматична ін'єкція залежностей","\u002Fjava\u002Fpr2\u002Fmvvm-guice-integration","04.java\u002Fpr2\u002F30.mvvm-guice-integration",{"title":2438,"path":2439,"stem":2440},"Валідація та обробка помилок у MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-validation-error-handling","04.java\u002Fpr2\u002F31.mvvm-validation-error-handling",{"title":2442,"path":2443,"stem":2444},"Навігація та управління екранами у JavaFX MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-navigation-screen-management","04.java\u002Fpr2\u002F32.mvvm-navigation-screen-management",{"title":2446,"path":2447,"stem":2448},"Тестування JavaFX MVVM-додатків","\u002Fjava\u002Fpr2\u002Fmvvm-testing","04.java\u002Fpr2\u002F33.mvvm-testing",{"title":2450,"path":2451,"stem":2452},"Стилізація та теми у JavaFX: CSS та User Experience","\u002Fjava\u002Fpr2\u002Fjavafx-styling-themes","04.java\u002Fpr2\u002F34.javafx-styling-themes",{"title":2454,"path":2455,"stem":2456},"AtlantaFX: Сучасні теми для JavaFX додатків","\u002Fjava\u002Fpr2\u002Fatlantafx-modern-themes","04.java\u002Fpr2\u002F35.atlantafx-modern-themes",{"title":2458,"path":2459,"stem":2460},"Пакування та розповсюдження JavaFX-додатків","\u002Fjava\u002Fpr2\u002Fjar-packaging-distribution","04.java\u002Fpr2\u002F36.jar-packaging-distribution",{"title":2462,"icon":2463,"path":2464,"stem":2465,"children":2466,"page":59},"Бази даних","i-lucide-database","\u002Fdatabases","06.databases",[2467,2497,2520,2557,2586,2604,2638,2650,2659],{"title":2468,"icon":2469,"path":2470,"stem":2471,"children":2472,"page":59},"Intro","i-lucide-play","\u002Fdatabases\u002Fintro","06.databases\u002F01.intro",[2473,2477,2481,2485,2489,2493],{"title":2474,"path":2475,"stem":2476},"Введення в теорію баз даних","\u002Fdatabases\u002Fintro\u002Fintroduction-to-databases","06.databases\u002F01.intro\u002F01.introduction-to-databases",{"title":2478,"path":2479,"stem":2480},"Реляційна модель даних","\u002Fdatabases\u002Fintro\u002Frelational-model-theory","06.databases\u002F01.intro\u002F02.relational-model-theory",{"title":2482,"path":2483,"stem":2484},"ER-моделювання","\u002Fdatabases\u002Fintro\u002Fer-modeling","06.databases\u002F01.intro\u002F03.er-modeling",{"title":2486,"path":2487,"stem":2488},"Логічне проектування БД","\u002Fdatabases\u002Fintro\u002Flogical-schema","06.databases\u002F01.intro\u002F04.logical-schema",{"title":2490,"path":2491,"stem":2492},"Класифікація таблиць","\u002Fdatabases\u002Fintro\u002Ftable-classification","06.databases\u002F01.intro\u002F05.table-classification",{"title":2494,"path":2495,"stem":2496},"PlantUML для баз даних","\u002Fdatabases\u002Fintro\u002Fplantuml-diagrams","06.databases\u002F01.intro\u002F06.plantuml-diagrams",{"title":2498,"icon":2463,"path":2499,"stem":2500,"children":2501,"page":59},"MS SQL Server Start","\u002Fdatabases\u002Fms-sql-server-start","06.databases\u002F02.ms-sql-server-start",[2502,2506,2512,2516],{"title":2503,"path":2504,"stem":2505},"Типи даних у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fdata-types","06.databases\u002F02.ms-sql-server-start\u002F01.data-types",{"title":2507,"path":2508,"stem":2509,"children":2510},"Індекси у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-indexes","06.databases\u002F02.ms-sql-server-start\u002F02.sql-indexes",[2511],{"title":2507,"path":2508,"stem":2509},{"title":2513,"path":2514,"stem":2515},"Системні бази даних MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsystem-databases","06.databases\u002F02.ms-sql-server-start\u002F03.system-databases",{"title":2517,"path":2518,"stem":2519},"Огляд мови SQL та запитів","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-queries-overview","06.databases\u002F02.ms-sql-server-start\u002F04.sql-queries-overview",{"title":2521,"icon":2463,"path":2522,"stem":2523,"children":2524,"page":59},"SQL","\u002Fdatabases\u002Fsql","06.databases\u002F03.sql",[2525,2529,2533,2537,2541,2545,2549,2553],{"title":2526,"path":2527,"stem":2528},"Налаштування демонстраційної бази даних","\u002Fdatabases\u002Fsql\u002Fsample-database-setup","06.databases\u002F03.sql\u002F00.sample-database-setup",{"title":2530,"path":2531,"stem":2532},"DDL - Створення таблиць (CREATE TABLE)","\u002Fdatabases\u002Fsql\u002Fddl-create-table","06.databases\u002F03.sql\u002F01.ddl-create-table",{"title":2534,"path":2535,"stem":2536},"DDL - Зміна та видалення таблиць (ALTER, DROP)","\u002Fdatabases\u002Fsql\u002Fddl-alter-drop-table","06.databases\u002F03.sql\u002F02.ddl-alter-drop-table",{"title":2538,"path":2539,"stem":2540},"SELECT запити - Основи","\u002Fdatabases\u002Fsql\u002Fselect-queries-fundamentals","06.databases\u002F03.sql\u002F03.select-queries-fundamentals",{"title":2542,"path":2543,"stem":2544},"SELECT запити - Розширені можливості","\u002Fdatabases\u002Fsql\u002Fselect-queries-advanced","06.databases\u002F03.sql\u002F04.select-queries-advanced",{"title":2546,"path":2547,"stem":2548},"INSERT запити - Додавання даних","\u002Fdatabases\u002Fsql\u002Finsert-queries","06.databases\u002F03.sql\u002F05.insert-queries",{"title":2550,"path":2551,"stem":2552},"UPDATE та DELETE запити","\u002Fdatabases\u002Fsql\u002Fupdate-delete-queries","06.databases\u002F03.sql\u002F06.update-delete-queries",{"title":2554,"path":2555,"stem":2556},"Транзакції в SQL","\u002Fdatabases\u002Fsql\u002Ftransactions","06.databases\u002F03.sql\u002F07.transactions",{"title":2558,"icon":2463,"path":2559,"stem":2560,"children":2561,"page":59},"Multi Table Databases","\u002Fdatabases\u002Fmulti-table-databases","06.databases\u002F04.multi-table-databases",[2562,2566,2570,2574,2578,2582],{"title":2563,"path":2564,"stem":2565},"Зв'язки та нормалізація БД","\u002Fdatabases\u002Fmulti-table-databases\u002Frelationships-and-normalization","06.databases\u002F04.multi-table-databases\u002F00.relationships-and-normalization",{"title":2567,"path":2568,"stem":2569},"INNER JOIN - З'єднання таблиць","\u002Fdatabases\u002Fmulti-table-databases\u002Finner-join","06.databases\u002F04.multi-table-databases\u002F01.inner-join",{"title":2571,"path":2572,"stem":2573},"OUTER JOINs - LEFT, RIGHT, FULL","\u002Fdatabases\u002Fmulti-table-databases\u002Fouter-joins","06.databases\u002F04.multi-table-databases\u002F02.outer-joins",{"title":2575,"path":2576,"stem":2577},"CROSS та SELF JOINs","\u002Fdatabases\u002Fmulti-table-databases\u002Fcross-self-joins","06.databases\u002F04.multi-table-databases\u002F03.cross-self-joins",{"title":2579,"path":2580,"stem":2581},"Підзапити (Subqueries)","\u002Fdatabases\u002Fmulti-table-databases\u002Fsubqueries","06.databases\u002F04.multi-table-databases\u002F04.subqueries",{"title":2583,"path":2584,"stem":2585},"Агрегації з JOIN","\u002Fdatabases\u002Fmulti-table-databases\u002Faggregations-with-joins","06.databases\u002F04.multi-table-databases\u002F05.aggregations-with-joins",{"title":2587,"icon":2588,"path":2589,"stem":2590,"children":2591,"page":59},"Aggregate Functions","i-lucide-calculator","\u002Fdatabases\u002Faggregate-functions","06.databases\u002F05.aggregate-functions",[2592,2596,2600],{"title":2593,"path":2594,"stem":2595},"Функції агрегування в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fintroduction-aggregate-functions","06.databases\u002F05.aggregate-functions\u002F01.introduction-aggregate-functions",{"title":2597,"path":2598,"stem":2599},"Групування даних в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fgrouping-data","06.databases\u002F05.aggregate-functions\u002F02.grouping-data",{"title":2601,"path":2602,"stem":2603},"Підзапити з агрегатними функціями","\u002Fdatabases\u002Faggregate-functions\u002Fsubqueries-aggregates","06.databases\u002F05.aggregate-functions\u002F03.subqueries-aggregates",{"title":2605,"icon":2606,"path":2607,"stem":2608,"children":2609,"page":59},"Тригери та зберігаємі процедури","i-lucide-database-zap","\u002Fdatabases\u002Ftriggers-stored-procedures","06.databases\u002F07.triggers-stored-procedures",[2610,2614,2618,2622,2626,2630,2634],{"title":2611,"path":2612,"stem":2613},"DML-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fdml-triggers","06.databases\u002F07.triggers-stored-procedures\u002F01.dml-triggers",{"title":2615,"path":2616,"stem":2617},"DDL-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fddl-triggers","06.databases\u002F07.triggers-stored-procedures\u002F02.ddl-triggers",{"title":2619,"path":2620,"stem":2621},"Transact-SQL розширення","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransact-sql-extensions","06.databases\u002F07.triggers-stored-procedures\u002F03.transact-sql-extensions",{"title":2623,"path":2624,"stem":2625},"Транзакції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransactions","06.databases\u002F07.triggers-stored-procedures\u002F04.transactions",{"title":2627,"path":2628,"stem":2629},"Зберігаємі процедури","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fstored-procedures","06.databases\u002F07.triggers-stored-procedures\u002F05.stored-procedures",{"title":2631,"path":2632,"stem":2633},"Користувацькі функції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fuser-defined-functions","06.databases\u002F07.triggers-stored-procedures\u002F06.user-defined-functions",{"title":2635,"path":2636,"stem":2637},"Безпека баз даних","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fsecurity","06.databases\u002F07.triggers-stored-procedures\u002F08.security",{"title":2635,"icon":793,"path":2639,"stem":2640,"children":2641,"page":59},"\u002Fdatabases\u002Fsecurity","06.databases\u002F08.security",[2642,2646],{"title":2643,"path":2644,"stem":2645},"Вступ до безпеки баз даних","\u002Fdatabases\u002Fsecurity\u002Fintroduction","06.databases\u002F08.security\u002F01.introduction",{"title":2647,"path":2648,"stem":2649},"Системні представлення та метадані","\u002Fdatabases\u002Fsecurity\u002Fsystem-views","06.databases\u002F08.security\u002F02.system-views",{"title":2651,"icon":2652,"path":2653,"stem":2654,"children":2655,"page":59},"Резервне копіювання та відновлення","i-lucide-database-backup","\u002Fdatabases\u002Fbackup-recovery","06.databases\u002F09.backup-recovery",[2656],{"title":2651,"path":2657,"stem":2658},"\u002Fdatabases\u002Fbackup-recovery\u002Fbackup-restore","06.databases\u002F09.backup-recovery\u002F01.backup-restore",{"title":2660,"icon":2661,"path":2662,"stem":2663,"children":2664,"page":59},"Повнотекстовий пошук","i-lucide-search","\u002Fdatabases\u002Ffull-text-search","06.databases\u002F10.full-text-search",[2665],{"title":2660,"path":2666,"stem":2667},"\u002Fdatabases\u002Ffull-text-search\u002Ffull-text-search","06.databases\u002F10.full-text-search\u002F01.full-text-search",{"title":2669,"icon":2670,"path":2671,"stem":2672,"children":2673,"page":59},"Tools","i-lucide-wrench","\u002Ftools","07.tools",[2674,2750],{"title":2675,"icon":2676,"path":2677,"stem":2678,"children":2679},"Docker","i-simple-icons-docker","\u002Ftools\u002Fdocker","07.tools\u002F01.docker\u002Findex",[2680,2682,2686,2690,2694,2698,2702,2706,2710,2714,2718,2722,2726,2730,2734,2738,2742,2746],{"title":2681,"path":2677,"stem":2678},"Docker: від нуля до production",{"title":2683,"path":2684,"stem":2685},"Контейнеризація — від проблеми до рішення","\u002Ftools\u002Fdocker\u002Fcontainerization-concept","07.tools\u002F01.docker\u002F01.containerization-concept",{"title":2687,"path":2688,"stem":2689},"Docker — що це і навіщо?","\u002Ftools\u002Fdocker\u002Fdocker-what-and-why","07.tools\u002F01.docker\u002F02.docker-what-and-why",{"title":2691,"path":2692,"stem":2693},"Архітектура Docker Engine","\u002Ftools\u002Fdocker\u002Fdocker-architecture","07.tools\u002F01.docker\u002F03.docker-architecture",{"title":2695,"path":2696,"stem":2697},"Встановлення Docker","\u002Ftools\u002Fdocker\u002Finstallation","07.tools\u002F01.docker\u002F04.installation",{"title":2699,"path":2700,"stem":2701},"Перший контейнер — docker run","\u002Ftools\u002Fdocker\u002Ffirst-container","07.tools\u002F01.docker\u002F05.first-container",{"title":2703,"path":2704,"stem":2705},"Життєвий цикл контейнера","\u002Ftools\u002Fdocker\u002Fcontainer-lifecycle","07.tools\u002F01.docker\u002F06.container-lifecycle",{"title":2707,"path":2708,"stem":2709},"Docker Images — фундаментальні концепції","\u002Ftools\u002Fdocker\u002Fdocker-images-fundamentals","07.tools\u002F01.docker\u002F07.docker-images-fundamentals",{"title":2711,"path":2712,"stem":2713},"Dockerfile — основи","\u002Ftools\u002Fdocker\u002Fdockerfile-basics","07.tools\u002F01.docker\u002F08.dockerfile-basics",{"title":2715,"path":2716,"stem":2717},"Dockerfile — просунуті техніки","\u002Ftools\u002Fdocker\u002Fdockerfile-advanced","07.tools\u002F01.docker\u002F09.dockerfile-advanced",{"title":2719,"path":2720,"stem":2721},"Build Context та кешування шарів","\u002Ftools\u002Fdocker\u002Fbuild-context-and-cache","07.tools\u002F01.docker\u002F10.build-context-and-cache",{"title":2723,"path":2724,"stem":2725},"Реєстри Docker-образів","\u002Ftools\u002Fdocker\u002Fimage-registries","07.tools\u002F01.docker\u002F11.image-registries",{"title":2727,"path":2728,"stem":2729},"Контейнеризація .NET додатків","\u002Ftools\u002Fdocker\u002Fdotnet-containerization","07.tools\u002F01.docker\u002F12.dotnet-containerization",{"title":2731,"path":2732,"stem":2733},"Томи та збереження даних","\u002Ftools\u002Fdocker\u002Fvolumes-and-data","07.tools\u002F01.docker\u002F13.volumes-and-data",{"title":2735,"path":2736,"stem":2737},"Основи мережі в Docker","\u002Ftools\u002Fdocker\u002Fnetworking-basics","07.tools\u002F01.docker\u002F14.networking-basics",{"title":2739,"path":2740,"stem":2741},"Змінні оточення та конфігурація","\u002Ftools\u002Fdocker\u002Fenvironment-and-configuration","07.tools\u002F01.docker\u002F15.environment-and-configuration",{"title":2743,"path":2744,"stem":2745},"Docker Compose — оркестрація контейнерів","\u002Ftools\u002Fdocker\u002Fdocker-compose-basics","07.tools\u002F01.docker\u002F16.docker-compose-basics",{"title":2747,"path":2748,"stem":2749},"Docker Compose — Multi-Service застосунки","\u002Ftools\u002Fdocker\u002Fcompose-multi-service","07.tools\u002F01.docker\u002F17.compose-multi-service",{"title":2751,"icon":2752,"path":2753,"stem":2754,"children":2755},"Kubernetes","simple-icons:kubernetes","\u002Ftools\u002Fkubernetes","07.tools\u002F02.kubernetes\u002Findex",[2756,2758,2762,2766,2770,2774,2778,2782,2786],{"title":2757,"path":2753,"stem":2754},"Kubernetes: від розробки до production",{"title":2759,"path":2760,"stem":2761},"Kubernetes — коли Docker Compose більше не вистачає","\u002Ftools\u002Fkubernetes\u002Fwhy-kubernetes","07.tools\u002F02.kubernetes\u002F01.why-kubernetes",{"title":2763,"path":2764,"stem":2765},"Архітектура Kubernetes — анатомія кластера","\u002Ftools\u002Fkubernetes\u002Fkubernetes-architecture","07.tools\u002F02.kubernetes\u002F02.kubernetes-architecture",{"title":2767,"path":2768,"stem":2769},"Локальне середовище — minikube, kind та k3s","\u002Ftools\u002Fkubernetes\u002Flocal-environment","07.tools\u002F02.kubernetes\u002F03.local-environment",{"title":2771,"path":2772,"stem":2773},"Pod — атомарна одиниця Kubernetes","\u002Ftools\u002Fkubernetes\u002Fpods-and-containers","07.tools\u002F02.kubernetes\u002F04.pods-and-containers",{"title":2775,"path":2776,"stem":2777},"Патерни використання Pod","\u002Ftools\u002Fkubernetes\u002Fpod-patterns","07.tools\u002F02.kubernetes\u002F05.pod-patterns",{"title":2779,"path":2780,"stem":2781},"Deployment — декларативне управління Pod","\u002Ftools\u002Fkubernetes\u002Fdeployment-basics","07.tools\u002F02.kubernetes\u002F06.deployment-basics",{"title":2783,"path":2784,"stem":2785},"Rolling Updates та управління життєвим циклом Deployment","\u002Ftools\u002Fkubernetes\u002Fdeployment-rolling-updates","07.tools\u002F02.kubernetes\u002F07.deployment-rolling-updates",{"title":2787,"path":2788,"stem":2789},"Service — мережева абстракція для Pod","\u002Ftools\u002Fkubernetes\u002Fservices-networking","07.tools\u002F02.kubernetes\u002F08.services-networking",{"title":2791,"icon":2792,"path":2793,"stem":2794,"children":2795,"page":59},"Software Engineering","i-lucide-code-2","\u002Fsoftware-engineering","09.software-engineering",[2796,2800,2804,2808,2812,2816,2820,2824,2828,2832,2836],{"title":2797,"path":2798,"stem":2799},"1. Аналіз предметної області. Експертні знання та складність","\u002Fsoftware-engineering\u002Fintro-subdomains","09.software-engineering\u002F01.intro-subdomains",{"title":2801,"path":2802,"stem":2803},"2. Обмежені контексти. Інтеграція обмежених контекстів","\u002Fsoftware-engineering\u002Fintegrating-limited-contexts","09.software-engineering\u002F02.integrating-limited-contexts",{"title":2805,"path":2806,"stem":2807},"3. Реалізація простої бізнес-логіки","\u002Fsoftware-engineering\u002Fsimple","09.software-engineering\u002F03.simple",{"title":2809,"path":2810,"stem":2811},"4. Опрацювання складної бізнес-логіки","\u002Fsoftware-engineering\u002Fcomplex-business-logic","09.software-engineering\u002F04.complex-business-logic",{"title":2813,"path":2814,"stem":2815},"5. Моделювання фактора часу. Подієво-орієнтована архітектура.","\u002Fsoftware-engineering\u002Fmodelling-the-time-factor","09.software-engineering\u002F05.modelling-the-time-factor",{"title":2817,"path":2818,"stem":2819},"6. Архітектурні патерни","\u002Fsoftware-engineering\u002Farchitectural-patterns","09.software-engineering\u002F06.architectural-patterns",{"title":2821,"path":2822,"stem":2823},"Паттерни взаємодії","\u002Fsoftware-engineering\u002Fpatterns-of-interaction","09.software-engineering\u002F07.patterns-of-interaction",{"title":2825,"path":2826,"stem":2827},"Евристика проєктування","\u002Fsoftware-engineering\u002Fdesign-heuristics","09.software-engineering\u002F08.design-heuristics",{"title":2829,"path":2830,"stem":2831},"Еволюція проєктних рішень","\u002Fsoftware-engineering\u002Fevolution-of-design-solutions","09.software-engineering\u002F09.evolution-of-design-solutions",{"title":2833,"path":2834,"stem":2835},"EventStorming","\u002Fsoftware-engineering\u002Feventstorming","09.software-engineering\u002F10.eventstorming",{"title":2837,"path":2838,"stem":2839},"DDD на практиці","\u002Fsoftware-engineering\u002Fddd-in-practice","09.software-engineering\u002F11.ddd-in-practice",{"title":2841,"icon":943,"path":2842,"stem":2843,"children":2844,"page":59},"DDD","\u002Fddd","10.ddd",[2845,2849,2853,2857,2861,2865,2869,2873,2877,2881,2885,2889,2893],{"title":2846,"path":2847,"stem":2848},"Аналіз предметної області","\u002Fddd\u002Fdomain-analysis","10.ddd\u002F01.domain-analysis",{"title":2850,"path":2851,"stem":2852},"Експертні знання про предметну область","\u002Fddd\u002Fdomain-expert-knowledge","10.ddd\u002F02.domain-expert-knowledge",{"title":2854,"path":2855,"stem":2856},"Як осмислити складність предметної області","\u002Fddd\u002Fmanaging-domain-complexity","10.ddd\u002F03.managing-domain-complexity",{"title":2858,"path":2859,"stem":2860},"Інтеграція обмежених контекстів","\u002Fddd\u002Fbounded-context-integration","10.ddd\u002F04.bounded-context-integration",{"title":2862,"path":2863,"stem":2864},"Реалізація простої бізнес-логіки","\u002Fddd\u002Fsimple-business-logic","10.ddd\u002F05.simple-business-logic",{"title":2866,"path":2867,"stem":2868},"Обробка складної бізнес-логіки","\u002Fddd\u002Fcomplex-business-logic","10.ddd\u002F06.complex-business-logic",{"title":2870,"path":2871,"stem":2872},"Моделювання фактора часу","\u002Fddd\u002Ftime-modeling","10.ddd\u002F07.time-modeling",{"title":2874,"path":2875,"stem":2876},"Глава 8. Архітектурні Патерни","\u002Fddd\u002Farchitectural-patterns","10.ddd\u002F08.architectural-patterns",{"title":2878,"path":2879,"stem":2880},"Глава 9. Патерни Взаємодії","\u002Fddd\u002Finteraction-patterns","10.ddd\u002F09.interaction-patterns",{"title":2882,"path":2883,"stem":2884},"Глава 10. Проектні Евристики","\u002Fddd\u002Fdesign-heuristics","10.ddd\u002F10.design-heuristics",{"title":2886,"path":2887,"stem":2888},"Глава 11. Еволюція Проектних Рішень","\u002Fddd\u002Fevolution-of-design-decisions","10.ddd\u002F11.evolution-of-design-decisions",{"title":2890,"path":2891,"stem":2892},"Глава 12. EventStorming","\u002Fddd\u002Fevent-storming","10.ddd\u002F12.event-storming",{"title":2894,"path":2895,"stem":2896},"Глава 13. DDD на Практиці","\u002Fddd\u002Fddd-in-practice","10.ddd\u002F13.ddd-in-practice",{"title":2898,"icon":2899,"path":2900,"stem":2901,"children":2902,"page":59},"Media Streaming","i-lucide-video","\u002Fmedia-streaming","11.media-streaming",[2903,2907,2911,2915,2919,2923,2927],{"title":2904,"path":2905,"stem":2906},"01. Магія Стрімінгу: Що відбувається, коли ви натискаєте \"Play\"","\u002Fmedia-streaming\u002Fintroduction","11.media-streaming\u002F01.introduction",{"title":2908,"path":2909,"stem":2910},"02. Анатомія Медіа: Кодеки, Контейнери та Стиснення","\u002Fmedia-streaming\u002Faudio-video-anatomy","11.media-streaming\u002F02.audio-video-anatomy",{"title":2912,"path":2913,"stem":2914},"03. The Gym: FFmpeg Deep Dive","\u002Fmedia-streaming\u002Fffmpeg-gym","11.media-streaming\u002F03.ffmpeg-gym",{"title":2916,"path":2917,"stem":2918},"04. HLS Protocol: HTTP Live Streaming у Деталях","\u002Fmedia-streaming\u002Fhls-protocol","11.media-streaming\u002F04.hls-protocol",{"title":2920,"path":2921,"stem":2922},"05. DASH Protocol: Відкритий Стандарт","\u002Fmedia-streaming\u002Fdash-protocol","11.media-streaming\u002F05.dash-protocol",{"title":2924,"path":2925,"stem":2926},"06. Масштабування: CDN та Adaptive Bitrate","\u002Fmedia-streaming\u002Fcdn-and-adaptive-bitrate","11.media-streaming\u002F06.cdn-and-adaptive-bitrate",{"title":2928,"path":2929,"stem":2930},"07. Війна із Затримкою (Latency)","\u002Fmedia-streaming\u002Frealtime-latency","11.media-streaming\u002F07.realtime-latency",{"title":2932,"icon":2933,"path":2934,"stem":2935,"children":2936,"page":59},"HTML & CSS","i-devicon-html5","\u002Fhtml-css","12.html-css",[2937,2941,2945,2949,2953,2957,2961,2965,2969,2973,2977,2981,2985,2989,2993,2997,3001,3005,3009,3013,3017,3021,3025,3029,3033,3037,3041,3045,3049,3053],{"title":2938,"path":2939,"stem":2940},"Вступ до HTML. Структура документа","\u002Fhtml-css\u002Fintro-html-structure","12.html-css\u002F01.intro-html-structure",{"title":2942,"path":2943,"stem":2944},"Форматування тексту в HTML","\u002Fhtml-css\u002Fhtml-text-formatting","12.html-css\u002F02.html-text-formatting",{"title":2946,"path":2947,"stem":2948},"Посилання та зображення в HTML","\u002Fhtml-css\u002Fhtml-links-images","12.html-css\u002F03.html-links-images",{"title":2950,"path":2951,"stem":2952},"Списки та таблиці в HTML","\u002Fhtml-css\u002Fhtml-lists-tables","12.html-css\u002F04.html-lists-tables",{"title":2954,"path":2955,"stem":2956},"Форми в HTML","\u002Fhtml-css\u002Fhtml-forms","12.html-css\u002F05.html-forms",{"title":2958,"path":2959,"stem":2960},"Семантичні елементи HTML5","\u002Fhtml-css\u002Fhtml-semantic-elements","12.html-css\u002F06.html-semantic-elements",{"title":2962,"path":2963,"stem":2964},"Мультимедіа та розширені елементи HTML","\u002Fhtml-css\u002Fhtml-multimedia-advanced","12.html-css\u002F07.html-multimedia-advanced",{"title":2966,"path":2967,"stem":2968},"Мікророзмітка та SEO в HTML","\u002Fhtml-css\u002Fhtml-microdata-seo","12.html-css\u002F08.html-microdata-seo",{"title":2970,"path":2971,"stem":2972},"Вступ до CSS. Селектори та специфічність","\u002Fhtml-css\u002Fcss-intro-selectors","12.html-css\u002F09.css-intro-selectors",{"title":2974,"path":2975,"stem":2976},"Блокова модель CSS. Відступи. Box Sizing","\u002Fhtml-css\u002Fcss-box-model","12.html-css\u002F10.css-box-model",{"title":2978,"path":2979,"stem":2980},"Розміри у CSS: повний довідник одиниць і ключових слів","\u002Fhtml-css\u002F10a.css-sizing","12.html-css\u002F10a.css-sizing",{"title":2982,"path":2983,"stem":2984},"Типографіка в CSS. Шрифти та текст","\u002Fhtml-css\u002Fcss-typography","12.html-css\u002F11.css-typography",{"title":2986,"path":2987,"stem":2988},"Кольори та фони в CSS","\u002Fhtml-css\u002Fcss-colors-backgrounds","12.html-css\u002F12.css-colors-backgrounds",{"title":2990,"path":2991,"stem":2992},"Тіні та фільтри в CSS","\u002Fhtml-css\u002F12b.css-shadows-filters","12.html-css\u002F12b.css-shadows-filters",{"title":2994,"path":2995,"stem":2996},"CSS Flexbox: Фундамент гнучких макетів","\u002Fhtml-css\u002Fcss-flexbox-fundamentals","12.html-css\u002F13.css-flexbox-fundamentals",{"title":2998,"path":2999,"stem":3000},"CSS Flexbox: Вирівнювання та Позиціонування","\u002Fhtml-css\u002Fcss-flexbox-alignment-sizing-and-patterns","12.html-css\u002F14.css-flexbox-alignment-sizing-and-patterns",{"title":3002,"path":3003,"stem":3004},"CSS Grid. Двовимірний макет. Частина 1","\u002Fhtml-css\u002Fcss-layout-grid","12.html-css\u002F15.css-layout-grid",{"title":3006,"path":3007,"stem":3008},"CSS Grid. Двовимірний макет. Частина 2","\u002Fhtml-css\u002Fcss-layout-grid-advanced","12.html-css\u002F16.css-layout-grid-advanced",{"title":3010,"path":3011,"stem":3012},"Позиціонування в CSS. Z-index. Stacking Context","\u002Fhtml-css\u002Fcss-positioning","12.html-css\u002F17.css-positioning",{"title":3014,"path":3015,"stem":3016},"CSS Анімації та Переходи","\u002Fhtml-css\u002Fcss-animations-transitions","12.html-css\u002F18.css-animations-transitions",{"title":3018,"path":3019,"stem":3020},"Адаптивний дизайн. Media Queries. Частина 1","\u002Fhtml-css\u002Fcss-responsive-media-queries","12.html-css\u002F19.css-responsive-media-queries",{"title":3022,"path":3023,"stem":3024},"Адаптивний дизайн. Частина 2: clamp(), Container Queries, @layer","\u002Fhtml-css\u002Fcss-responsive-advanced","12.html-css\u002F20.css-responsive-advanced",{"title":3026,"path":3027,"stem":3028},"CSS Custom Properties. Методології. Сучасний CSS","\u002Fhtml-css\u002Fcss-variables-methodologies","12.html-css\u002F21.css-variables-methodologies",{"title":3030,"path":3031,"stem":3032},"Сучасний CSS 2023–2025: Нові можливості","\u002Fhtml-css\u002Fcss-modern-features","12.html-css\u002F22.css-modern-features",{"title":3034,"path":3035,"stem":3036},"CSS Nesting, @layer, @scope та @property: нативний препроцесор","\u002Fhtml-css\u002F22a.css-nesting-modern-syntax","12.html-css\u002F22a.css-nesting-modern-syntax",{"title":3038,"path":3039,"stem":3040},"CSS для форм та інтерактивних станів","\u002Fhtml-css\u002Fcss-forms-interactive-states","12.html-css\u002F23.css-forms-interactive-states",{"title":3042,"path":3043,"stem":3044},"Доступність у CSS (CSS Accessibility)","\u002Fhtml-css\u002Fcss-accessibility","12.html-css\u002F24.css-accessibility",{"title":3046,"path":3047,"stem":3048},"CSS-функції та сучасні sizing primitives","\u002Fhtml-css\u002Fcss-functions-sizing","12.html-css\u002F25.css-functions-sizing",{"title":3050,"path":3051,"stem":3052},"Rendering Pipeline і CSS Performance","\u002Fhtml-css\u002Fcss-rendering-performance","12.html-css\u002F26.css-rendering-performance",{"title":3054,"path":3055,"stem":3056},"CSS Best Practices: типові ситуації та правильні рішення","\u002Fhtml-css\u002Fcss-best-practices","12.html-css\u002F27.css-best-practices",{"title":3058,"path":3059,"stem":3060,"children":3061,"page":59},"AWS","\u002Faws","13.aws",[3062,3066,3070,3074,3078,3082,3086,3090],{"title":3063,"path":3064,"stem":3065},"Реєстрація AWS акаунту та студентські програми","\u002Faws\u002Faccount-registration","13.aws\u002F00.account-registration",{"title":3067,"path":3068,"stem":3069},"Вступ до хмарних обчислень та AWS","\u002Faws\u002Fintroduction-to-cloud","13.aws\u002F01.introduction-to-cloud",{"title":3071,"path":3072,"stem":3073},"AWS IAM — Identity and Access Management","\u002Faws\u002Fiam","13.aws\u002F02.iam",{"title":3075,"path":3076,"stem":3077},"Docker та контейнеризація в AWS — ECR, ECS та Fargate","\u002Faws\u002Fdocker-ecs","13.aws\u002F03.docker-ecs",{"title":3079,"path":3080,"stem":3081},"Amazon EC2 — Elastic Compute Cloud","\u002Faws\u002Fec2","13.aws\u002F04.ec2",{"title":3083,"path":3084,"stem":3085},"Elastic Load Balancing та Auto Scaling","\u002Faws\u002Falb-asg","13.aws\u002F05.alb-asg",{"title":3087,"path":3088,"stem":3089},"Amazon S3 — Simple Storage Service","\u002Faws\u002Fs3","13.aws\u002F06.s3",{"title":3091,"path":3092,"stem":3093},"Amazon CloudFront — Content Delivery Network","\u002Faws\u002Fcloudfront","13.aws\u002F07.cloudfront",{"title":3095,"path":3096,"stem":3097,"children":3098,"page":59},"Tailwind","\u002Ftailwind","21.tailwind",[3099,3103,3107,3111,3115,3119,3123,3127],{"title":3100,"path":3101,"stem":3102},"Що таке Tailwind CSS і навіщо він потрібен","\u002Ftailwind\u002Ftailwind-intro-philosophy","21.tailwind\u002F01.tailwind-intro-philosophy",{"title":3104,"path":3105,"stem":3106},"Встановлення та налаштування Tailwind CSS v4","\u002Ftailwind\u002Ftailwind-installation-setup","21.tailwind\u002F02.tailwind-installation-setup",{"title":3108,"path":3109,"stem":3110},"Utility-класи: основи та система Tailwind","\u002Ftailwind\u002Ftailwind-utility-classes-core","21.tailwind\u002F03.tailwind-utility-classes-core",{"title":3112,"path":3113,"stem":3114},"Layout: Flexbox та Grid через Tailwind","\u002Ftailwind\u002Ftailwind-flexbox-grid","21.tailwind\u002F04.tailwind-flexbox-grid",{"title":3116,"path":3117,"stem":3118},"Кастомізація теми через @theme у Tailwind v4","\u002Ftailwind\u002Ftailwind-theme-customization","21.tailwind\u002F05.tailwind-theme-customization",{"title":3120,"path":3121,"stem":3122},"Варіанти: hover, focus, responsive, dark mode та нові v4","\u002Ftailwind\u002Ftailwind-variants-states","21.tailwind\u002F06.tailwind-variants-states",{"title":3124,"path":3125,"stem":3126},"Типографіка та система кольорів у Tailwind v4","\u002Ftailwind\u002Ftailwind-typography-colors","21.tailwind\u002F07.tailwind-typography-colors",{"title":3128,"path":3129,"stem":3130},"Компоненти та повторюваність: @apply, @utility та патерни","\u002Ftailwind\u002Ftailwind-components-patterns","21.tailwind\u002F08.tailwind-components-patterns",{"title":3132,"path":3133,"stem":3134},"Тестування компонентів діаграм","\u002Ftest-components","98.test-components",{"id":3136,"title":2458,"body":3137,"description":7991,"extension":7992,"links":7993,"meta":7994,"navigation":3451,"path":2459,"seo":7995,"stem":2460,"__hash__":7996},"docs\u002F04.java\u002Fpr2\u002F36.jar-packaging-distribution.md",{"type":3138,"value":3139,"toc":7957},"minimark",[3140,3144,3149,3157,3164,3179,3185,3204,3207,3210,3214,3219,3237,3251,3255,3262,3942,3977,4094,4097,4311,4313,4317,4321,4332,4346,4436,4450,4454,4457,4572,4588,4604,4607,4625,4646,4662,4666,4671,4700,4702,4706,4712,4720,4724,4731,4778,4882,4944,5010,5017,5021,5027,5148,5165,5169,5175,5284,5286,5290,5294,5313,5863,5866,5899,5903,5906,5913,7125,7127,7131,7135,7145,7148,7174,7178,7181,7189,7239,7245,7316,7341,7347,7389,7446,7459,7615,7621,7677,7681,7691,7754,7756,7760,7763,7891,7944,7953],[3141,3142,2458],"h1",{"id":3143},"пакування-та-розповсюдження-javafx-додатків",[3145,3146,3148],"h2",{"id":3147},"вступ-від-середовища-розробника-до-рук-користувача","Вступ: Від середовища розробника до рук користувача",[3150,3151,3152,3153],"p",{},"Уявіть ситуацію, з якою стикається кожен розробник після завершення основного етапу розробки. Додаток запускається бездоганно з командного рядка, усі тести проходять успішно, інтерфейс виглядає саме так, як задумано. Настає момент, коли потрібно передати результат роботи замовнику або кінцевому користувачеві. І тут виникає закономірне питання: ",[3154,3155,3156],"strong",{},"як запустити цей додаток на комп'ютері, де не встановлено ні JDK, ні IntelliJ IDEA, ні Maven?",[3150,3158,3159,3160,3163],{},"Це питання є ключовим у промисловій розробці програмного забезпечення. Процес перетворення вихідного коду на готовий до розповсюдження продукт називається ",[3154,3161,3162],{},"релізною інженерією"," (release engineering). Для Java-екосистеми цей процес має свою специфіку, зумовлену особливостями платформи JVM.",[3150,3165,3166,3169,3170,3174,3175,3178],{},[3154,3167,3168],{},"Проблема класичного JAR."," Стандартний JAR-файл (Java ARchive), який генерують Maven або Gradle, містить лише скомпільований байт-код вашого проєкту. Він не включає ні сторонні бібліотеки (AtlantaFX, Google Guice, HikariCP), ні модулі JavaFX, ні саму JVM. Спроба запустити такий файл командою ",[3171,3172,3173],"code",{},"java -jar audiobook.jar"," на чистій машині завершиться помилкою ",[3171,3176,3177],{},"ClassNotFoundException"," при першому ж зверненні до будь-якої зовнішньої залежності.",[3150,3180,3181,3184],{},[3154,3182,3183],{},"Еволюція підходів до розповсюдження."," Протягом двох десятиліть розвитку Java-екосистеми сформувалося кілька підходів до вирішення цієї проблеми:",[3186,3187,3188,3194,3199],"card-group",{},[3189,3190,3193],"card",{"icon":3191,"title":3192},"i-heroicons-archive-box-arrow-down","Fat JAR \u002F Uber JAR","Усі залежності упаковуються в один великий JAR-файл. Простий підхід, але вимагає встановленої JVM на цільовій машині.",[3189,3195,3198],{"icon":3196,"title":3197},"i-heroicons-cpu-chip","jlink: Custom Runtime Image","Створення мінімального образу JVM, що містить лише необхідні модулі. Зменшує розмір дистрибутиву, але вимагає модульності проєкту.",[3189,3200,3203],{"icon":3201,"title":3202},"i-heroicons-archive-box","jpackage: Нативний інсталятор","Генерація платформо-специфічного інсталятора (.exe, .msi, .dmg, .deb, .rpm), що включає всі залежності та вбудовану JVM. Найкращий досвід для кінцевого користувача.",[3150,3205,3206],{},"У цій статті ми послідовно пройдемо всі три рівні пакування — від простого Fat JAR до повноцінного нативного інсталятора — та навчимося публікувати релізи у GitHub Releases для зручного розповсюдження серед користувачів.",[3208,3209],"hr",{},[3145,3211,3213],{"id":3212},"частина-i-fat-jar-перший-крок-до-самодостатнього-артефакту","Частина I. Fat JAR: Перший крок до самодостатнього артефакту",[3215,3216,3218],"h3",{"id":3217},"що-таке-fat-jar-і-чому-він-так-називається","Що таке Fat JAR і чому він так називається",[3150,3220,3221,3224,3225,3228,3229,3232,3233,3236],{},[3154,3222,3223],{},"Fat JAR"," (також відомий як ",[3154,3226,3227],{},"Uber JAR"," або ",[3154,3230,3231],{},"Shaded JAR",") — це JAR-архів, що містить не лише байт-код власного проєкту, а й байт-код усіх його транзитивних залежностей. Назва \"fat\" (жирний) є красномовною: якщо звичайний JAR платформи аудіокниг може важити 50–100 КБ, то Fat JAR з усіма бібліотеками (AtlantaFX, Guice, HikariCP, H2) зважитиме 30–50 МБ. Це, безумовно, збільшує розмір артефакту, проте забезпечує головне: ",[3154,3234,3235],{},"єдину точку входу"," у вигляді одного файлу.",[3238,3239,3240,3243,3244,3247,3248,3250],"note",{},[3154,3241,3242],{},"Fat JAR не вирішує проблему JVM."," Щоб запустити Fat JAR, на цільовій машині все одно має бути встановлена сумісна Java Runtime Environment (JRE). Цю проблему повністю вирішує лише ",[3171,3245,3246],{},"jpackage",", розглянутий у наступному розділі. Fat JAR є зручним проміжним рішенням — для передачі між розробниками, розгортання на серверах, де JRE вже наявна, або як будівельний блок для ",[3171,3249,3246],{},".",[3215,3252,3254],{"id":3253},"налаштування-maven-плагін-maven-shade-plugin","Налаштування Maven: плагін maven-shade-plugin",[3150,3256,3257,3258,3261],{},"Maven не надає вбудованої підтримки Fat JAR. Для цього використовується ",[3154,3259,3260],{},"maven-shade-plugin"," — один із найпопулярніших плагінів Maven-екосистеми, що дозволяє \"затінити\" (shade) всі залежності в єдиний архів.",[3263,3264,3270],"pre",{"className":3265,"code":3266,"filename":3267,"language":3268,"meta":3269,"style":3269},"language-xml shiki shiki-themes light-plus dark-plus dark-plus","\u003Cbuild>\n    \u003Cplugins>\n        \u003C!-- Компілятор: вказуємо версію Java -->\n        \u003Cplugin>\n            \u003CgroupId>org.apache.maven.plugins\u003C\u002FgroupId>\n            \u003CartifactId>maven-compiler-plugin\u003C\u002FartifactId>\n            \u003Cversion>3.13.0\u003C\u002Fversion>\n            \u003Cconfiguration>\n                \u003Csource>21\u003C\u002Fsource>\n                \u003Ctarget>21\u003C\u002Ftarget>\n            \u003C\u002Fconfiguration>\n        \u003C\u002Fplugin>\n\n        \u003C!-- Fat JAR: упаковуємо всі залежності в один архів -->\n        \u003Cplugin>\n            \u003CgroupId>org.apache.maven.plugins\u003C\u002FgroupId>\n            \u003CartifactId>maven-shade-plugin\u003C\u002FartifactId>\n            \u003Cversion>3.5.3\u003C\u002Fversion>\n            \u003Cexecutions>\n                \u003Cexecution>\n                    \u003Cphase>package\u003C\u002Fphase>\n                    \u003Cgoals>\n                        \u003Cgoal>shade\u003C\u002Fgoal>\n                    \u003C\u002Fgoals>\n                    \u003Cconfiguration>\n                        \u003C!-- Головний клас: точка входу додатку -->\n                        \u003Ctransformers>\n                            \u003Ctransformer implementation=\n                                \"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer\">\n                                \u003CmainClass>dev.kostyl.audiobook.Launcher\u003C\u002FmainClass>\n                            \u003C\u002Ftransformer>\n                            \u003C!-- Об'єднання META-INF\u002Fservices (важливо для Guice) -->\n                            \u003Ctransformer implementation=\n                                \"org.apache.maven.plugins.shade.resource.ServicesResourceTransformer\"\u002F>\n                        \u003C\u002Ftransformers>\n                        \u003C!-- Виключення підписів з JAR-файлів залежностей -->\n                        \u003Cfilters>\n                            \u003Cfilter>\n                                \u003Cartifact>*:*\u003C\u002Fartifact>\n                                \u003Cexcludes>\n                                    \u003Cexclude>META-INF\u002F*.SF\u003C\u002Fexclude>\n                                    \u003Cexclude>META-INF\u002F*.DSA\u003C\u002Fexclude>\n                                    \u003Cexclude>META-INF\u002F*.RSA\u003C\u002Fexclude>\n                                \u003C\u002Fexcludes>\n                            \u003C\u002Ffilter>\n                        \u003C\u002Ffilters>\n                        \u003C!-- Назва вихідного файлу -->\n                        \u003CoutputFile>\n                            ${project.build.directory}\u002F${project.artifactId}-fat.jar\n                        \u003C\u002FoutputFile>\n                    \u003C\u002Fconfiguration>\n                \u003C\u002Fexecution>\n            \u003C\u002Fexecutions>\n        \u003C\u002Fplugin>\n    \u003C\u002Fplugins>\n\u003C\u002Fbuild>\n","pom.xml","xml","",[3171,3271,3272,3288,3299,3306,3317,3340,3359,3378,3388,3408,3426,3436,3446,3453,3459,3468,3485,3502,3520,3530,3540,3560,3570,3590,3600,3609,3615,3625,3641,3650,3670,3680,3686,3697,3706,3716,3722,3732,3742,3761,3771,3791,3809,3827,3837,3846,3855,3861,3871,3877,3886,3895,3905,3914,3923,3933],{"__ignoreMap":3269},[3273,3274,3277,3281,3285],"span",{"class":3275,"line":3276},"line",1,[3273,3278,3280],{"class":3279},"s0P7L","\u003C",[3273,3282,3284],{"class":3283},"sKtos","build",[3273,3286,3287],{"class":3279},">\n",[3273,3289,3291,3294,3297],{"class":3275,"line":3290},2,[3273,3292,3293],{"class":3279},"    \u003C",[3273,3295,3296],{"class":3283},"plugins",[3273,3298,3287],{"class":3279},[3273,3300,3302],{"class":3275,"line":3301},3,[3273,3303,3305],{"class":3304},"spJ8K","        \u003C!-- Компілятор: вказуємо версію Java -->\n",[3273,3307,3309,3312,3315],{"class":3275,"line":3308},4,[3273,3310,3311],{"class":3279},"        \u003C",[3273,3313,3314],{"class":3283},"plugin",[3273,3316,3287],{"class":3279},[3273,3318,3320,3323,3326,3329,3333,3336,3338],{"class":3275,"line":3319},5,[3273,3321,3322],{"class":3279},"            \u003C",[3273,3324,3325],{"class":3283},"groupId",[3273,3327,3328],{"class":3279},">",[3273,3330,3332],{"class":3331},"sHH4Y","org.apache.maven.plugins",[3273,3334,3335],{"class":3279},"\u003C\u002F",[3273,3337,3325],{"class":3283},[3273,3339,3287],{"class":3279},[3273,3341,3343,3345,3348,3350,3353,3355,3357],{"class":3275,"line":3342},6,[3273,3344,3322],{"class":3279},[3273,3346,3347],{"class":3283},"artifactId",[3273,3349,3328],{"class":3279},[3273,3351,3352],{"class":3331},"maven-compiler-plugin",[3273,3354,3335],{"class":3279},[3273,3356,3347],{"class":3283},[3273,3358,3287],{"class":3279},[3273,3360,3362,3364,3367,3369,3372,3374,3376],{"class":3275,"line":3361},7,[3273,3363,3322],{"class":3279},[3273,3365,3366],{"class":3283},"version",[3273,3368,3328],{"class":3279},[3273,3370,3371],{"class":3331},"3.13.0",[3273,3373,3335],{"class":3279},[3273,3375,3366],{"class":3283},[3273,3377,3287],{"class":3279},[3273,3379,3381,3383,3386],{"class":3275,"line":3380},8,[3273,3382,3322],{"class":3279},[3273,3384,3385],{"class":3283},"configuration",[3273,3387,3287],{"class":3279},[3273,3389,3391,3394,3397,3399,3402,3404,3406],{"class":3275,"line":3390},9,[3273,3392,3393],{"class":3279},"                \u003C",[3273,3395,3396],{"class":3283},"source",[3273,3398,3328],{"class":3279},[3273,3400,3401],{"class":3331},"21",[3273,3403,3335],{"class":3279},[3273,3405,3396],{"class":3283},[3273,3407,3287],{"class":3279},[3273,3409,3411,3413,3416,3418,3420,3422,3424],{"class":3275,"line":3410},10,[3273,3412,3393],{"class":3279},[3273,3414,3415],{"class":3283},"target",[3273,3417,3328],{"class":3279},[3273,3419,3401],{"class":3331},[3273,3421,3335],{"class":3279},[3273,3423,3415],{"class":3283},[3273,3425,3287],{"class":3279},[3273,3427,3429,3432,3434],{"class":3275,"line":3428},11,[3273,3430,3431],{"class":3279},"            \u003C\u002F",[3273,3433,3385],{"class":3283},[3273,3435,3287],{"class":3279},[3273,3437,3439,3442,3444],{"class":3275,"line":3438},12,[3273,3440,3441],{"class":3279},"        \u003C\u002F",[3273,3443,3314],{"class":3283},[3273,3445,3287],{"class":3279},[3273,3447,3449],{"class":3275,"line":3448},13,[3273,3450,3452],{"emptyLinePlaceholder":3451},true,"\n",[3273,3454,3456],{"class":3275,"line":3455},14,[3273,3457,3458],{"class":3304},"        \u003C!-- Fat JAR: упаковуємо всі залежності в один архів -->\n",[3273,3460,3462,3464,3466],{"class":3275,"line":3461},15,[3273,3463,3311],{"class":3279},[3273,3465,3314],{"class":3283},[3273,3467,3287],{"class":3279},[3273,3469,3471,3473,3475,3477,3479,3481,3483],{"class":3275,"line":3470},16,[3273,3472,3322],{"class":3279},[3273,3474,3325],{"class":3283},[3273,3476,3328],{"class":3279},[3273,3478,3332],{"class":3331},[3273,3480,3335],{"class":3279},[3273,3482,3325],{"class":3283},[3273,3484,3287],{"class":3279},[3273,3486,3488,3490,3492,3494,3496,3498,3500],{"class":3275,"line":3487},17,[3273,3489,3322],{"class":3279},[3273,3491,3347],{"class":3283},[3273,3493,3328],{"class":3279},[3273,3495,3260],{"class":3331},[3273,3497,3335],{"class":3279},[3273,3499,3347],{"class":3283},[3273,3501,3287],{"class":3279},[3273,3503,3505,3507,3509,3511,3514,3516,3518],{"class":3275,"line":3504},18,[3273,3506,3322],{"class":3279},[3273,3508,3366],{"class":3283},[3273,3510,3328],{"class":3279},[3273,3512,3513],{"class":3331},"3.5.3",[3273,3515,3335],{"class":3279},[3273,3517,3366],{"class":3283},[3273,3519,3287],{"class":3279},[3273,3521,3523,3525,3528],{"class":3275,"line":3522},19,[3273,3524,3322],{"class":3279},[3273,3526,3527],{"class":3283},"executions",[3273,3529,3287],{"class":3279},[3273,3531,3533,3535,3538],{"class":3275,"line":3532},20,[3273,3534,3393],{"class":3279},[3273,3536,3537],{"class":3283},"execution",[3273,3539,3287],{"class":3279},[3273,3541,3543,3546,3549,3551,3554,3556,3558],{"class":3275,"line":3542},21,[3273,3544,3545],{"class":3279},"                    \u003C",[3273,3547,3548],{"class":3283},"phase",[3273,3550,3328],{"class":3279},[3273,3552,3553],{"class":3331},"package",[3273,3555,3335],{"class":3279},[3273,3557,3548],{"class":3283},[3273,3559,3287],{"class":3279},[3273,3561,3563,3565,3568],{"class":3275,"line":3562},22,[3273,3564,3545],{"class":3279},[3273,3566,3567],{"class":3283},"goals",[3273,3569,3287],{"class":3279},[3273,3571,3573,3576,3579,3581,3584,3586,3588],{"class":3275,"line":3572},23,[3273,3574,3575],{"class":3279},"                        \u003C",[3273,3577,3578],{"class":3283},"goal",[3273,3580,3328],{"class":3279},[3273,3582,3583],{"class":3331},"shade",[3273,3585,3335],{"class":3279},[3273,3587,3578],{"class":3283},[3273,3589,3287],{"class":3279},[3273,3591,3593,3596,3598],{"class":3275,"line":3592},24,[3273,3594,3595],{"class":3279},"                    \u003C\u002F",[3273,3597,3567],{"class":3283},[3273,3599,3287],{"class":3279},[3273,3601,3603,3605,3607],{"class":3275,"line":3602},25,[3273,3604,3545],{"class":3279},[3273,3606,3385],{"class":3283},[3273,3608,3287],{"class":3279},[3273,3610,3612],{"class":3275,"line":3611},26,[3273,3613,3614],{"class":3304},"                        \u003C!-- Головний клас: точка входу додатку -->\n",[3273,3616,3618,3620,3623],{"class":3275,"line":3617},27,[3273,3619,3575],{"class":3279},[3273,3621,3622],{"class":3283},"transformers",[3273,3624,3287],{"class":3279},[3273,3626,3628,3631,3634,3638],{"class":3275,"line":3627},28,[3273,3629,3630],{"class":3279},"                            \u003C",[3273,3632,3633],{"class":3283},"transformer",[3273,3635,3637],{"class":3636},"sa4r_"," implementation",[3273,3639,3640],{"class":3331},"=\n",[3273,3642,3644,3648],{"class":3275,"line":3643},29,[3273,3645,3647],{"class":3646},"su9tN","                                \"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer\"",[3273,3649,3287],{"class":3279},[3273,3651,3653,3656,3659,3661,3664,3666,3668],{"class":3275,"line":3652},30,[3273,3654,3655],{"class":3279},"                                \u003C",[3273,3657,3658],{"class":3283},"mainClass",[3273,3660,3328],{"class":3279},[3273,3662,3663],{"class":3331},"dev.kostyl.audiobook.Launcher",[3273,3665,3335],{"class":3279},[3273,3667,3658],{"class":3283},[3273,3669,3287],{"class":3279},[3273,3671,3673,3676,3678],{"class":3275,"line":3672},31,[3273,3674,3675],{"class":3279},"                            \u003C\u002F",[3273,3677,3633],{"class":3283},[3273,3679,3287],{"class":3279},[3273,3681,3683],{"class":3275,"line":3682},32,[3273,3684,3685],{"class":3304},"                            \u003C!-- Об'єднання META-INF\u002Fservices (важливо для Guice) -->\n",[3273,3687,3689,3691,3693,3695],{"class":3275,"line":3688},33,[3273,3690,3630],{"class":3279},[3273,3692,3633],{"class":3283},[3273,3694,3637],{"class":3636},[3273,3696,3640],{"class":3331},[3273,3698,3700,3703],{"class":3275,"line":3699},34,[3273,3701,3702],{"class":3646},"                                \"org.apache.maven.plugins.shade.resource.ServicesResourceTransformer\"",[3273,3704,3705],{"class":3279},"\u002F>\n",[3273,3707,3709,3712,3714],{"class":3275,"line":3708},35,[3273,3710,3711],{"class":3279},"                        \u003C\u002F",[3273,3713,3622],{"class":3283},[3273,3715,3287],{"class":3279},[3273,3717,3719],{"class":3275,"line":3718},36,[3273,3720,3721],{"class":3304},"                        \u003C!-- Виключення підписів з JAR-файлів залежностей -->\n",[3273,3723,3725,3727,3730],{"class":3275,"line":3724},37,[3273,3726,3575],{"class":3279},[3273,3728,3729],{"class":3283},"filters",[3273,3731,3287],{"class":3279},[3273,3733,3735,3737,3740],{"class":3275,"line":3734},38,[3273,3736,3630],{"class":3279},[3273,3738,3739],{"class":3283},"filter",[3273,3741,3287],{"class":3279},[3273,3743,3745,3747,3750,3752,3755,3757,3759],{"class":3275,"line":3744},39,[3273,3746,3655],{"class":3279},[3273,3748,3749],{"class":3283},"artifact",[3273,3751,3328],{"class":3279},[3273,3753,3754],{"class":3331},"*:*",[3273,3756,3335],{"class":3279},[3273,3758,3749],{"class":3283},[3273,3760,3287],{"class":3279},[3273,3762,3764,3766,3769],{"class":3275,"line":3763},40,[3273,3765,3655],{"class":3279},[3273,3767,3768],{"class":3283},"excludes",[3273,3770,3287],{"class":3279},[3273,3772,3774,3777,3780,3782,3785,3787,3789],{"class":3275,"line":3773},41,[3273,3775,3776],{"class":3279},"                                    \u003C",[3273,3778,3779],{"class":3283},"exclude",[3273,3781,3328],{"class":3279},[3273,3783,3784],{"class":3331},"META-INF\u002F*.SF",[3273,3786,3335],{"class":3279},[3273,3788,3779],{"class":3283},[3273,3790,3287],{"class":3279},[3273,3792,3794,3796,3798,3800,3803,3805,3807],{"class":3275,"line":3793},42,[3273,3795,3776],{"class":3279},[3273,3797,3779],{"class":3283},[3273,3799,3328],{"class":3279},[3273,3801,3802],{"class":3331},"META-INF\u002F*.DSA",[3273,3804,3335],{"class":3279},[3273,3806,3779],{"class":3283},[3273,3808,3287],{"class":3279},[3273,3810,3812,3814,3816,3818,3821,3823,3825],{"class":3275,"line":3811},43,[3273,3813,3776],{"class":3279},[3273,3815,3779],{"class":3283},[3273,3817,3328],{"class":3279},[3273,3819,3820],{"class":3331},"META-INF\u002F*.RSA",[3273,3822,3335],{"class":3279},[3273,3824,3779],{"class":3283},[3273,3826,3287],{"class":3279},[3273,3828,3830,3833,3835],{"class":3275,"line":3829},44,[3273,3831,3832],{"class":3279},"                                \u003C\u002F",[3273,3834,3768],{"class":3283},[3273,3836,3287],{"class":3279},[3273,3838,3840,3842,3844],{"class":3275,"line":3839},45,[3273,3841,3675],{"class":3279},[3273,3843,3739],{"class":3283},[3273,3845,3287],{"class":3279},[3273,3847,3849,3851,3853],{"class":3275,"line":3848},46,[3273,3850,3711],{"class":3279},[3273,3852,3729],{"class":3283},[3273,3854,3287],{"class":3279},[3273,3856,3858],{"class":3275,"line":3857},47,[3273,3859,3860],{"class":3304},"                        \u003C!-- Назва вихідного файлу -->\n",[3273,3862,3864,3866,3869],{"class":3275,"line":3863},48,[3273,3865,3575],{"class":3279},[3273,3867,3868],{"class":3283},"outputFile",[3273,3870,3287],{"class":3279},[3273,3872,3874],{"class":3275,"line":3873},49,[3273,3875,3876],{"class":3331},"                            ${project.build.directory}\u002F${project.artifactId}-fat.jar\n",[3273,3878,3880,3882,3884],{"class":3275,"line":3879},50,[3273,3881,3711],{"class":3279},[3273,3883,3868],{"class":3283},[3273,3885,3287],{"class":3279},[3273,3887,3889,3891,3893],{"class":3275,"line":3888},51,[3273,3890,3595],{"class":3279},[3273,3892,3385],{"class":3283},[3273,3894,3287],{"class":3279},[3273,3896,3898,3901,3903],{"class":3275,"line":3897},52,[3273,3899,3900],{"class":3279},"                \u003C\u002F",[3273,3902,3537],{"class":3283},[3273,3904,3287],{"class":3279},[3273,3906,3908,3910,3912],{"class":3275,"line":3907},53,[3273,3909,3431],{"class":3279},[3273,3911,3527],{"class":3283},[3273,3913,3287],{"class":3279},[3273,3915,3917,3919,3921],{"class":3275,"line":3916},54,[3273,3918,3441],{"class":3279},[3273,3920,3314],{"class":3283},[3273,3922,3287],{"class":3279},[3273,3924,3926,3929,3931],{"class":3275,"line":3925},55,[3273,3927,3928],{"class":3279},"    \u003C\u002F",[3273,3930,3296],{"class":3283},[3273,3932,3287],{"class":3279},[3273,3934,3936,3938,3940],{"class":3275,"line":3935},56,[3273,3937,3335],{"class":3279},[3273,3939,3284],{"class":3283},[3273,3941,3287],{"class":3279},[3943,3944,3945,3955,3956,3959,3960,3963,3964,3967,3968,3970,3971,3974,3975,3250],"warning",{},[3154,3946,3947,3948,3951,3952,3250],{},"Клас ",[3171,3949,3950],{},"Launcher"," замість ",[3171,3953,3954],{},"App"," JavaFX-додатки мають специфіку: якщо головний клас безпосередньо успадковується від ",[3171,3957,3958],{},"javafx.application.Application",", запуск через ",[3171,3961,3962],{},"java -jar"," завершується помилкою ",[3171,3965,3966],{},"java.lang.reflect.InvocationTargetException",". Це пов'язано з тим, що JavaFX-модулі не завантажуються автоматично через classpath. Рішення — створити клас-обгортку ",[3171,3969,3950],{},", що не успадковується від ",[3171,3972,3973],{},"Application",", і саме його вказувати як ",[3171,3976,3658],{},[3263,3978,3983],{"className":3979,"code":3980,"filename":3981,"language":3982,"meta":3269,"style":3269},"language-java shiki shiki-themes light-plus dark-plus dark-plus","package dev.kostyl.audiobook;\n\n\u002F**\n * Клас-обгортка для запуску JavaFX-додатку через Fat JAR.\n * Не успадковується від Application — це критично для коректного\n * завантаження класів через classpath (не module-path).\n *\u002F\npublic class Launcher {\n    public static void main(String[] args) {\n        AudiobookApp.main(args); \u002F\u002F Делегуємо до реального Application\n    }\n}\n","Launcher.java","java",[3171,3984,3985,3993,3997,4002,4007,4012,4017,4022,4037,4068,4084,4089],{"__ignoreMap":3269},[3273,3986,3987,3990],{"class":3275,"line":3276},[3273,3988,3553],{"class":3989},"su1O8",[3273,3991,3992],{"class":3331}," dev.kostyl.audiobook;\n",[3273,3994,3995],{"class":3275,"line":3290},[3273,3996,3452],{"emptyLinePlaceholder":3451},[3273,3998,3999],{"class":3275,"line":3301},[3273,4000,4001],{"class":3304},"\u002F**\n",[3273,4003,4004],{"class":3275,"line":3308},[3273,4005,4006],{"class":3304}," * Клас-обгортка для запуску JavaFX-додатку через Fat JAR.\n",[3273,4008,4009],{"class":3275,"line":3319},[3273,4010,4011],{"class":3304}," * Не успадковується від Application — це критично для коректного\n",[3273,4013,4014],{"class":3275,"line":3342},[3273,4015,4016],{"class":3304}," * завантаження класів через classpath (не module-path).\n",[3273,4018,4019],{"class":3275,"line":3361},[3273,4020,4021],{"class":3304}," *\u002F\n",[3273,4023,4024,4027,4030,4034],{"class":3275,"line":3380},[3273,4025,4026],{"class":3989},"public",[3273,4028,4029],{"class":3989}," class",[3273,4031,4033],{"class":4032},"sN1BT"," Launcher",[3273,4035,4036],{"class":3331}," {\n",[3273,4038,4039,4042,4045,4048,4052,4055,4058,4061,4065],{"class":3275,"line":3390},[3273,4040,4041],{"class":3989},"    public",[3273,4043,4044],{"class":3989}," static",[3273,4046,4047],{"class":4032}," void",[3273,4049,4051],{"class":4050},"s8Opu"," main",[3273,4053,4054],{"class":3331},"(",[3273,4056,4057],{"class":4032},"String",[3273,4059,4060],{"class":3331},"[] ",[3273,4062,4064],{"class":4063},"siwwj","args",[3273,4066,4067],{"class":3331},") {\n",[3273,4069,4070,4073,4075,4078,4081],{"class":3275,"line":3410},[3273,4071,4072],{"class":4063},"        AudiobookApp",[3273,4074,3250],{"class":3331},[3273,4076,4077],{"class":4050},"main",[3273,4079,4080],{"class":3331},"(args); ",[3273,4082,4083],{"class":3304},"\u002F\u002F Делегуємо до реального Application\n",[3273,4085,4086],{"class":3275,"line":3428},[3273,4087,4088],{"class":3331},"    }\n",[3273,4090,4091],{"class":3275,"line":3438},[3273,4092,4093],{"class":3331},"}\n",[3150,4095,4096],{},"Тепер зберіть проєкт та перевірте результат:",[4098,4099,4100,4172],"tabs",{},[4101,4102,4105],"tabs-item",{"icon":4103,"label":4104},"i-simple-icons-apachemaven","Maven",[3263,4106,4110],{"className":4107,"code":4108,"language":4109,"meta":3269,"style":3269},"language-bash shiki shiki-themes light-plus dark-plus dark-plus","# Збірка Fat JAR\nmvn clean package\n\n# Результат у директорії target\u002F\nls -lh target\u002Faudiobook-app-fat.jar\n# → -rw-r--r-- 1 user staff 42M audiobook-app-fat.jar\n\n# Запуск Fat JAR\njava -jar target\u002Faudiobook-app-fat.jar\n","bash",[3171,4111,4112,4117,4129,4133,4138,4149,4154,4158,4163],{"__ignoreMap":3269},[3273,4113,4114],{"class":3275,"line":3276},[3273,4115,4116],{"class":3304},"# Збірка Fat JAR\n",[3273,4118,4119,4122,4126],{"class":3275,"line":3290},[3273,4120,4121],{"class":4050},"mvn",[3273,4123,4125],{"class":4124},"sbdoH"," clean",[3273,4127,4128],{"class":4124}," package\n",[3273,4130,4131],{"class":3275,"line":3301},[3273,4132,3452],{"emptyLinePlaceholder":3451},[3273,4134,4135],{"class":3275,"line":3308},[3273,4136,4137],{"class":3304},"# Результат у директорії target\u002F\n",[3273,4139,4140,4143,4146],{"class":3275,"line":3319},[3273,4141,4142],{"class":4050},"ls",[3273,4144,4145],{"class":3989}," -lh",[3273,4147,4148],{"class":4124}," target\u002Faudiobook-app-fat.jar\n",[3273,4150,4151],{"class":3275,"line":3342},[3273,4152,4153],{"class":3304},"# → -rw-r--r-- 1 user staff 42M audiobook-app-fat.jar\n",[3273,4155,4156],{"class":3275,"line":3361},[3273,4157,3452],{"emptyLinePlaceholder":3451},[3273,4159,4160],{"class":3275,"line":3380},[3273,4161,4162],{"class":3304},"# Запуск Fat JAR\n",[3273,4164,4165,4167,4170],{"class":3275,"line":3390},[3273,4166,3982],{"class":4050},[3273,4168,4169],{"class":3989}," -jar",[3273,4171,4148],{"class":4124},[4101,4173,4176,4187,4260],{"icon":4174,"label":4175},"i-simple-icons-gradle","Gradle",[3150,4177,4178,4179,4182,4183,4186],{},"Для Gradle аналогічна функціональність надається через завдання ",[3171,4180,4181],{},"shadowJar"," із плагіна ",[3154,4184,4185],{},"com.github.johnrengelman.shadow",":",[3263,4188,4193],{"className":4189,"code":4190,"filename":4191,"language":4192,"meta":3269,"style":3269},"language-groovy shiki shiki-themes light-plus dark-plus dark-plus","plugins {\n    id 'application'\n    id 'org.openjfx.javafxplugin' version '0.1.0'\n    id 'com.github.johnrengelman.shadow' version '8.1.1'\n}\n\napplication {\n    mainClass = 'dev.kostyl.audiobook.Launcher'\n}\n\nshadowJar {\n    archiveClassifier.set('fat')\n    mergeServiceFiles() \u002F\u002F Аналог ServicesResourceTransformer для Guice\n}\n","build.gradle","groovy",[3171,4194,4195,4200,4205,4210,4215,4219,4223,4228,4233,4237,4241,4246,4251,4256],{"__ignoreMap":3269},[3273,4196,4197],{"class":3275,"line":3276},[3273,4198,4199],{},"plugins {\n",[3273,4201,4202],{"class":3275,"line":3290},[3273,4203,4204],{},"    id 'application'\n",[3273,4206,4207],{"class":3275,"line":3301},[3273,4208,4209],{},"    id 'org.openjfx.javafxplugin' version '0.1.0'\n",[3273,4211,4212],{"class":3275,"line":3308},[3273,4213,4214],{},"    id 'com.github.johnrengelman.shadow' version '8.1.1'\n",[3273,4216,4217],{"class":3275,"line":3319},[3273,4218,4093],{},[3273,4220,4221],{"class":3275,"line":3342},[3273,4222,3452],{"emptyLinePlaceholder":3451},[3273,4224,4225],{"class":3275,"line":3361},[3273,4226,4227],{},"application {\n",[3273,4229,4230],{"class":3275,"line":3380},[3273,4231,4232],{},"    mainClass = 'dev.kostyl.audiobook.Launcher'\n",[3273,4234,4235],{"class":3275,"line":3390},[3273,4236,4093],{},[3273,4238,4239],{"class":3275,"line":3410},[3273,4240,3452],{"emptyLinePlaceholder":3451},[3273,4242,4243],{"class":3275,"line":3428},[3273,4244,4245],{},"shadowJar {\n",[3273,4247,4248],{"class":3275,"line":3438},[3273,4249,4250],{},"    archiveClassifier.set('fat')\n",[3273,4252,4253],{"class":3275,"line":3448},[3273,4254,4255],{},"    mergeServiceFiles() \u002F\u002F Аналог ServicesResourceTransformer для Guice\n",[3273,4257,4258],{"class":3275,"line":3455},[3273,4259,4093],{},[3263,4261,4263],{"className":4107,"code":4262,"language":4109,"meta":3269,"style":3269},"# Збірка Fat JAR\n.\u002Fgradlew shadowJar\n\n# Результат у директорії build\u002Flibs\u002F\nls -lh build\u002Flibs\u002Faudiobook-app-fat.jar\n\n# Запуск Fat JAR\njava -jar build\u002Flibs\u002Faudiobook-app-fat.jar\n",[3171,4264,4265,4269,4277,4281,4286,4295,4299,4303],{"__ignoreMap":3269},[3273,4266,4267],{"class":3275,"line":3276},[3273,4268,4116],{"class":3304},[3273,4270,4271,4274],{"class":3275,"line":3290},[3273,4272,4273],{"class":4050},".\u002Fgradlew",[3273,4275,4276],{"class":4124}," shadowJar\n",[3273,4278,4279],{"class":3275,"line":3301},[3273,4280,3452],{"emptyLinePlaceholder":3451},[3273,4282,4283],{"class":3275,"line":3308},[3273,4284,4285],{"class":3304},"# Результат у директорії build\u002Flibs\u002F\n",[3273,4287,4288,4290,4292],{"class":3275,"line":3319},[3273,4289,4142],{"class":4050},[3273,4291,4145],{"class":3989},[3273,4293,4294],{"class":4124}," build\u002Flibs\u002Faudiobook-app-fat.jar\n",[3273,4296,4297],{"class":3275,"line":3342},[3273,4298,3452],{"emptyLinePlaceholder":3451},[3273,4300,4301],{"class":3275,"line":3361},[3273,4302,4162],{"class":3304},[3273,4304,4305,4307,4309],{"class":3275,"line":3380},[3273,4306,3982],{"class":4050},[3273,4308,4169],{"class":3989},[3273,4310,4294],{"class":4124},[3208,4312],{},[3145,4314,4316],{"id":4315},"частина-ii-jpackage-нативний-інсталятор-із-вбудованою-jvm","Частина II. jpackage: Нативний інсталятор із вбудованою JVM",[3215,4318,4320],{"id":4319},"концептуальна-основа-що-таке-jpackage","Концептуальна основа: що таке jpackage",[3150,4322,4323,4327,4328,4331],{},[3154,4324,4325],{},[3171,4326,3246],{}," — це інструмент командного рядка, що з'явився у складі JDK 16 як стабільна функція (до цього він існував у вигляді інкубаційного модуля з JDK 14). Його призначення — генерація ",[3154,4329,4330],{},"нативних інсталяторів"," для desktop-додатків на Java, що не вимагають попередньої установки JVM на цільовій машині.",[3150,4333,4334,4335,4337,4338,4341,4342,4345],{},"Принцип роботи ",[3171,4336,3246],{}," полягає у наступному: інструмент бере ваш Fat JAR (або директорію з класами), додає до нього ",[3154,4339,4340],{},"урізаний образ JRE"," (створений за допомогою ",[3171,4343,4344],{},"jlink","), іконку програми, метадані (назва, версія, виробник) та упаковує все це у формат, звичний для кожної операційної системи:",[4347,4348,4349,4365],"table",{},[4350,4351,4352],"thead",{},[4353,4354,4355,4359,4362],"tr",{},[4356,4357,4358],"th",{},"Операційна система",[4356,4360,4361],{},"Формат інсталятора",[4356,4363,4364],{},"Результат",[4366,4367,4368,4388,4406,4421],"tbody",{},[4353,4369,4370,4376,4385],{},[4371,4372,4373],"td",{},[3154,4374,4375],{},"Windows",[4371,4377,4378,3228,4381,4384],{},[3171,4379,4380],{},".msi",[3171,4382,4383],{},".exe"," (NSIS)",[4371,4386,4387],{},"Стандартний Windows Installer",[4353,4389,4390,4395,4403],{},[4371,4391,4392],{},[3154,4393,4394],{},"macOS",[4371,4396,4397,3228,4400],{},[3171,4398,4399],{},".dmg",[3171,4401,4402],{},".pkg",[4371,4404,4405],{},"Образ диска або пакет macOS",[4353,4407,4408,4413,4418],{},[4371,4409,4410],{},[3154,4411,4412],{},"Linux (Debian\u002FUbuntu)",[4371,4414,4415],{},[3171,4416,4417],{},".deb",[4371,4419,4420],{},"Пакет Debian",[4353,4422,4423,4428,4433],{},[4371,4424,4425],{},[3154,4426,4427],{},"Linux (RHEL\u002FFedora)",[4371,4429,4430],{},[3171,4431,4432],{},".rpm",[4371,4434,4435],{},"Пакет RPM",[4437,4438,4439,4442,4443,4445,4446,4449],"tip",{},[3154,4440,4441],{},"Крос-компіляція неможлива."," ",[3171,4444,3246],{}," генерує інсталятор ",[3154,4447,4448],{},"лише для тієї операційної системи, на якій він запускається",". Щоб створити інсталятори для Windows, macOS та Linux одночасно, необхідно використовувати CI\u002FCD-систему (наприклад, GitHub Actions) з окремими runner-агентами для кожної платформи. Саме цей підхід ми розглянемо у розділі про GitHub Actions.",[3215,4451,4453],{"id":4452},"передумови-що-потрібно-перед-запуском-jpackage","Передумови: що потрібно перед запуском jpackage",[3150,4455,4456],{},"Перш ніж розпочати генерацію інсталятора, переконайтеся, що виконані такі умови:",[4458,4459,4460,4464,4469,4486,4500,4504,4514,4529,4532],"steps",{},[3215,4461,4463],{"id":4462},"крок-1-jdk-17-із-підтримкою-jpackage","Крок 1: JDK 17+ із підтримкою jpackage",[3150,4465,4466,4468],{},[3171,4467,3246],{}," є частиною JDK 14+. Перевірте наявність інструменту:",[3263,4470,4472],{"className":4107,"code":4471,"language":4109,"meta":3269,"style":3269},"jpackage --version\n# → 21.0.3\n",[3171,4473,4474,4481],{"__ignoreMap":3269},[3273,4475,4476,4478],{"class":3275,"line":3276},[3273,4477,3246],{"class":4050},[3273,4479,4480],{"class":3989}," --version\n",[3273,4482,4483],{"class":3275,"line":3290},[3273,4484,4485],{"class":3304},"# → 21.0.3\n",[3150,4487,4488,4489,4492,4493,4496,4497,3250],{},"Якщо команда не знайдена — переконайтеся, що ",[3171,4490,4491],{},"JAVA_HOME"," вказує на повний JDK (не JRE), та що директорія ",[3171,4494,4495],{},"$JAVA_HOME\u002Fbin"," присутня у ",[3171,4498,4499],{},"PATH",[3215,4501,4503],{"id":4502},"крок-2-інструменти-платформи-лише-для-windows","Крок 2: Інструменти платформи (лише для Windows)",[3150,4505,4506,4507,4509,4510,4513],{},"Для генерації ",[3171,4508,4380],{},"-інсталятора на Windows необхідно встановити ",[3154,4511,4512],{},"WiX Toolset"," — набір інструментів для компіляції MSI-пакетів.",[4515,4516,4517],"blockquote",{},[3150,4518,4519,4522,4524,4525,4528],{},[3273,4520,4521],{},"!IMPORTANT",[3171,4523,3246],{}," вимагає ",[3154,4526,4527],{},"виключно WiX Toolset версії 3.x"," (версії 4.x та 5.x не підтримуються утилітою автоматично). Тому необхідно встановлювати саме версію 3.",[3150,4530,4531],{},"Для встановлення WiX Toolset v3 скористайтеся одним із пакетних менеджерів для Windows:",[4098,4533,4534],{},[4101,4535,4538,4541],{"icon":4536,"label":4537},"i-simple-icons-scoop","Scoop",[3150,4539,4540],{},"Для Scoop спочатку потрібно підключити репозиторій версій, оскільки WiX 3 є застарілою гілкою:",[3263,4542,4546],{"className":4543,"code":4544,"language":4545,"meta":3269,"style":3269},"language-powershell shiki shiki-themes light-plus dark-plus dark-plus","# Додавання бакету версій\nscoop bucket add versions\n\n# Встановлення версії 3 WiX Toolset\nscoop install versions\u002Fwixtoolset3\n","powershell",[3171,4547,4548,4553,4558,4562,4567],{"__ignoreMap":3269},[3273,4549,4550],{"class":3275,"line":3276},[3273,4551,4552],{"class":3304},"# Додавання бакету версій\n",[3273,4554,4555],{"class":3275,"line":3290},[3273,4556,4557],{"class":3331},"scoop bucket add versions\n",[3273,4559,4560],{"class":3275,"line":3301},[3273,4561,3452],{"emptyLinePlaceholder":3451},[3273,4563,4564],{"class":3275,"line":3308},[3273,4565,4566],{"class":3304},"# Встановлення версії 3 WiX Toolset\n",[3273,4568,4569],{"class":3275,"line":3319},[3273,4570,4571],{"class":3331},"scoop install versions\u002Fwixtoolset3\n",[4101,4573,4576,4579],{"icon":4574,"label":4575},"i-simple-icons-chocolatey","Chocolatey",[3150,4577,4578],{},"Chocolatey за замовчуванням встановлює стабільну гілку WiX Toolset v3:",[3263,4580,4582],{"className":4543,"code":4581,"language":4545,"meta":3269,"style":3269},"choco install wixtoolset --yes\n",[3171,4583,4584],{"__ignoreMap":3269},[3273,4585,4586],{"class":3275,"line":3276},[3273,4587,4581],{"class":3331},[4101,4589,4592,4595],{"icon":4590,"label":4591},"i-simple-icons-windows","Winget",[3150,4593,4594],{},"Утиліта Winget (Windows Package Manager) дозволяє встановити пакет за його унікальним ідентифікатором:",[3263,4596,4598],{"className":4543,"code":4597,"language":4545,"meta":3269,"style":3269},"winget install -e --id WiXToolset.WiXToolset\n",[3171,4599,4600],{"__ignoreMap":3269},[3273,4601,4602],{"class":3275,"line":3276},[3273,4603,4597],{"class":3331},[3150,4605,4606],{},"::",[3150,4608,4609,4610,4613,4614,4617,4618,4621,4622,4624],{},"Після встановлення переконайтеся, що шлях до утиліт WiX (зокрема до папки ",[3171,4611,4612],{},"bin",", де знаходяться ",[3171,4615,4616],{},"candle.exe"," та ",[3171,4619,4620],{},"light.exe",") додано до системної змінної ",[3171,4623,4499],{},". Перезапустіть термінал та перевірте наявність інструменту:",[3263,4626,4628],{"className":4543,"code":4627,"language":4545,"meta":3269,"style":3269},"# Перевірка наявності WiX\ncandle.exe --version\n# → Windows Installer XML Toolset Compiler version 3.14.0.8606\n",[3171,4629,4630,4635,4641],{"__ignoreMap":3269},[3273,4631,4632],{"class":3275,"line":3276},[3273,4633,4634],{"class":3304},"# Перевірка наявності WiX\n",[3273,4636,4637,4639],{"class":3275,"line":3290},[3273,4638,4616],{"class":4050},[3273,4640,4480],{"class":3331},[3273,4642,4643],{"class":3275,"line":3301},[3273,4644,4645],{"class":3304},"# → Windows Installer XML Toolset Compiler version 3.14.0.8606\n",[3150,4647,4506,4648,4650,4651,4654,4655,3250],{},[3171,4649,4383],{}," (NSIS-інсталятора) встановіть ",[3154,4652,4653],{},"NSIS"," з ",[4656,4657,4661],"a",{"href":4658,"rel":4659},"https:\u002F\u002Fnsis.sourceforge.io\u002F",[4660],"nofollow","nsis.sourceforge.io",[3215,4663,4665],{"id":4664},"крок-3-зібраний-fat-jar","Крок 3: Зібраний Fat JAR",[3150,4667,4668,4670],{},[3171,4669,3246],{}," вимагає вхідний JAR-файл. Використовуйте Fat JAR, створений у попередньому розділі:",[3263,4672,4674],{"className":4107,"code":4673,"language":4109,"meta":3269,"style":3269},"# Maven\nmvn clean package\n# Gradle\n.\u002Fgradlew shadowJar\n",[3171,4675,4676,4681,4689,4694],{"__ignoreMap":3269},[3273,4677,4678],{"class":3275,"line":3276},[3273,4679,4680],{"class":3304},"# Maven\n",[3273,4682,4683,4685,4687],{"class":3275,"line":3290},[3273,4684,4121],{"class":4050},[3273,4686,4125],{"class":4124},[3273,4688,4128],{"class":4124},[3273,4690,4691],{"class":3275,"line":3301},[3273,4692,4693],{"class":3304},"# Gradle\n",[3273,4695,4696,4698],{"class":3275,"line":3308},[3273,4697,4273],{"class":4050},[3273,4699,4276],{"class":4124},[3150,4701,4606],{},[3215,4703,4705],{"id":4704},"структура-проєкту-перед-пакуванням","Структура проєкту перед пакуванням",[3150,4707,4708,4709,4186],{},"Для зручності рекомендується розмістити всі ресурси для пакування в окремій директорії ",[3171,4710,4711],{},"packaging\u002F",[3263,4713,4718],{"className":4714,"code":4716,"language":4717},[4715],"language-text","audiobook-app\u002F\n├── src\u002F\n├── target\u002F\n│   └── audiobook-app-fat.jar       ← зібраний Fat JAR\n├── packaging\u002F\n│   ├── windows\u002F\n│   │   ├── audiobook.ico           ← іконка для Windows (.ico)\n│   │   └── license.rtf             ← ліцензія для MSI-діалогу\n│   ├── macos\u002F\n│   │   └── audiobook.icns          ← іконка для macOS (.icns)\n│   └── linux\u002F\n│       └── audiobook.png           ← іконка для Linux (.png, 128×128)\n└── pom.xml\n","text",[3171,4719,4716],{"__ignoreMap":3269},[3215,4721,4723],{"id":4722},"генерація-інсталятора-для-windows-msi","Генерація інсталятора для Windows (.msi)",[3150,4725,4726,4727,4730],{},"Наведена команда виконується на ",[3154,4728,4729],{},"Windows-машині"," (або у Windows runner у GitHub Actions):",[4515,4732,4733,4761],{},[3150,4734,4735,4738,4741,4742,4745,4746,4749,4750,4753,4754,4757,4758],{},[3273,4736,4737],{},"!WARNING",[3154,4739,4740],{},"Проблема з кирилицею у метаданих на Windows","\nWiX Toolset v3 за замовчуванням використовує західноєвропейську кодову сторінку (наприклад, ",[3171,4743,4744],{},"1252","). Якщо значення параметрів ",[3171,4747,4748],{},"--description",", ",[3171,4751,4752],{},"--vendor"," чи ",[3171,4755,4756],{},"--name"," містять кириличні символи, WiX не зможе скомпілювати інсталятор і поверне помилку виду:\n",[3171,4759,4760],{},"light.exe : error LGHT0311 : A string was provided with characters that are not available in the specified database code page '1252'.",[3150,4762,4763,4766,4767,4769,4770,4773,4774,4777],{},[3154,4764,4765],{},"Рекомендація:"," Завжди вказуйте опис програми (",[3171,4768,4748],{},") та інші метадані ",[3154,4771,4772],{},"виключно англійською мовою",". Якщо використання кирилиці є критичним, вам доведеться примусово задавати кодову сторінку за допомогою параметра ",[3171,4775,4776],{},"--win-codepage 1251",", проте англомовний варіант є найбільш надійним та сумісним.",[3263,4779,4781],{"className":4543,"code":4780,"language":4545,"meta":3269,"style":3269},"jpackage ^\n  --type msi ^\n  --name \"Audiobook Platform\" ^\n  --app-version \"1.0.0\" ^\n  --vendor \"Kostyl Dev\" ^\n  --description \"Audiobook Management Platform\" ^\n  --input target\u002F ^\n  --main-jar audiobook-app-fat.jar ^\n  --main-class dev.kostyl.audiobook.Launcher ^\n  --icon packaging\u002Fwindows\u002Faudiobook.ico ^\n  --dest dist\u002F ^\n  --win-dir-chooser ^\n  --win-menu ^\n  --win-shortcut ^\n  --win-menu-group \"Kostyl Dev\"\n",[3171,4782,4783,4788,4793,4804,4814,4824,4834,4839,4844,4849,4854,4859,4864,4869,4874],{"__ignoreMap":3269},[3273,4784,4785],{"class":3275,"line":3276},[3273,4786,4787],{"class":3331},"jpackage ^\n",[3273,4789,4790],{"class":3275,"line":3290},[3273,4791,4792],{"class":3331},"  --type msi ^\n",[3273,4794,4795,4798,4801],{"class":3275,"line":3301},[3273,4796,4797],{"class":3331},"  --name ",[3273,4799,4800],{"class":4124},"\"Audiobook Platform\"",[3273,4802,4803],{"class":3331}," ^\n",[3273,4805,4806,4809,4812],{"class":3275,"line":3308},[3273,4807,4808],{"class":3331},"  --app-version ",[3273,4810,4811],{"class":4124},"\"1.0.0\"",[3273,4813,4803],{"class":3331},[3273,4815,4816,4819,4822],{"class":3275,"line":3319},[3273,4817,4818],{"class":3331},"  --vendor ",[3273,4820,4821],{"class":4124},"\"Kostyl Dev\"",[3273,4823,4803],{"class":3331},[3273,4825,4826,4829,4832],{"class":3275,"line":3342},[3273,4827,4828],{"class":3331},"  --description ",[3273,4830,4831],{"class":4124},"\"Audiobook Management Platform\"",[3273,4833,4803],{"class":3331},[3273,4835,4836],{"class":3275,"line":3361},[3273,4837,4838],{"class":3331},"  --input target\u002F ^\n",[3273,4840,4841],{"class":3275,"line":3380},[3273,4842,4843],{"class":3331},"  --main-jar audiobook-app-fat.jar ^\n",[3273,4845,4846],{"class":3275,"line":3390},[3273,4847,4848],{"class":3331},"  --main-class dev.kostyl.audiobook.Launcher ^\n",[3273,4850,4851],{"class":3275,"line":3410},[3273,4852,4853],{"class":3331},"  --icon packaging\u002Fwindows\u002Faudiobook.ico ^\n",[3273,4855,4856],{"class":3275,"line":3428},[3273,4857,4858],{"class":3331},"  --dest dist\u002F ^\n",[3273,4860,4861],{"class":3275,"line":3438},[3273,4862,4863],{"class":3331},"  --win-dir-chooser ^\n",[3273,4865,4866],{"class":3275,"line":3448},[3273,4867,4868],{"class":3331},"  --win-menu ^\n",[3273,4870,4871],{"class":3275,"line":3455},[3273,4872,4873],{"class":3331},"  --win-shortcut ^\n",[3273,4875,4876,4879],{"class":3275,"line":3461},[3273,4877,4878],{"class":3331},"  --win-menu-group ",[3273,4880,4881],{"class":4124},"\"Kostyl Dev\"\n",[4883,4884,4885,4912,4915,4923,4931,4936,4940],"field-group",{},[4886,4887,4890,4891,4749,4894,4749,4897,4749,4900,4749,4903,4749,4906,4749,4909,3250],"field",{"name":4888,"type":4889},"--type","string","Тип вихідного пакету: ",[3171,4892,4893],{},"msi",[3171,4895,4896],{},"exe",[3171,4898,4899],{},"dmg",[3171,4901,4902],{},"pkg",[3171,4904,4905],{},"deb",[3171,4907,4908],{},"rpm",[3171,4910,4911],{},"app-image",[4886,4913,4914],{"name":4756,"type":4889},"Назва програми, що відображається у меню «Пуск» та панелі керування.",[4886,4916,4918,4919,4922],{"name":4917,"type":4889},"--app-version","Версія програми у форматі ",[3171,4920,4921],{},"major.minor.patch",". Відображається у «Установка та видалення програм».",[4886,4924,4926,4927,4930],{"name":4925,"type":4889},"--input","Директорія, що містить ",[3171,4928,4929],{},"--main-jar",". Усі файли з неї потраплять у дистрибутив.",[4886,4932,4935],{"name":4933,"type":4934},"--win-dir-chooser","boolean","Додає у діалог інсталятора крок вибору директорії встановлення.",[4886,4937,4939],{"name":4938,"type":4934},"--win-menu","Створює ярлик у меню «Пуск».",[4886,4941,4943],{"name":4942,"type":4934},"--win-shortcut","Створює ярлик на робочому столі.",[4945,4946,4948,4962,4971,4979,4988,4995,5002],"terminal-preview",{"title":4947},"jpackage — Windows MSI",[4949,4950,4952,4442,4957],"div",{"className":4951},[3275],[3273,4953,4956],{"className":4954},[4955],"opacity-40","PS C:\\audiobook-app>",[3154,4958,4961],{"className":4959},[4960],"font-bold","jpackage --type msi --name \"Audiobook Platform\" ...",[4949,4963,4965,4970],{"className":4964},[3275],[3273,4966,4969],{"className":4967},[4968,4960],"text-blue-400","WARNING:"," Using incubator modules: jdk.incubator.jpackage",[4949,4972,4974],{"className":4973},[3275],[3273,4975,4978],{"className":4976},[4977],"text-gray-400","Checking WiX toolset installation...",[4949,4980,4982,4987],{"className":4981},[3275],[3273,4983,4986],{"className":4984},[4985,4960],"text-green-400","OK:"," WiX 3.14.0.8606 found at C:\\Program Files\\WiX Toolset v3.14\\bin",[4949,4989,4991],{"className":4990},[3275],[3273,4992,4994],{"className":4993},[4977],"Building application image...",[4949,4996,4998],{"className":4997},[3275],[3273,4999,5001],{"className":5000},[4977],"Generating MSI installer...",[4949,5003,5005,5009],{"className":5004},[3275],[3273,5006,5008],{"className":5007},[4985,4960],"SUCCESS:"," Installer created: dist\\Audiobook Platform-1.0.0.msi (87 MB)",[3150,5011,5012,5013,5016],{},"Результатом є файл ",[3171,5014,5015],{},"dist\u002FAudiobook Platform-1.0.0.msi",", що є повноцінним Windows-інсталятором з майстром встановлення.",[3215,5018,5020],{"id":5019},"генерація-інсталятора-для-macos-dmg","Генерація інсталятора для macOS (.dmg)",[3150,5022,5023,5024,4186],{},"На ",[3154,5025,5026],{},"macOS-машині",[3263,5028,5030],{"className":4107,"code":5029,"language":4109,"meta":3269,"style":3269},"jpackage \\\n  --type dmg \\\n  --name \"Audiobook Platform\" \\\n  --app-version \"1.0.0\" \\\n  --vendor \"Kostyl Dev\" \\\n  --input target\u002F \\\n  --main-jar audiobook-app-fat.jar \\\n  --main-class dev.kostyl.audiobook.Launcher \\\n  --icon packaging\u002Fmacos\u002Faudiobook.icns \\\n  --dest dist\u002F \\\n  --mac-package-name \"audiobook-platform\" \\\n  --mac-package-identifier \"dev.kostyl.audiobook\"\n",[3171,5031,5032,5040,5050,5060,5070,5080,5090,5100,5110,5120,5130,5140],{"__ignoreMap":3269},[3273,5033,5034,5036],{"class":3275,"line":3276},[3273,5035,3246],{"class":4050},[3273,5037,5039],{"class":5038},"sjcCO"," \\\n",[3273,5041,5042,5045,5048],{"class":3275,"line":3290},[3273,5043,5044],{"class":3989},"  --type",[3273,5046,5047],{"class":4124}," dmg",[3273,5049,5039],{"class":5038},[3273,5051,5052,5055,5058],{"class":3275,"line":3301},[3273,5053,5054],{"class":3989},"  --name",[3273,5056,5057],{"class":4124}," \"Audiobook Platform\"",[3273,5059,5039],{"class":5038},[3273,5061,5062,5065,5068],{"class":3275,"line":3308},[3273,5063,5064],{"class":3989},"  --app-version",[3273,5066,5067],{"class":4124}," \"1.0.0\"",[3273,5069,5039],{"class":5038},[3273,5071,5072,5075,5078],{"class":3275,"line":3319},[3273,5073,5074],{"class":3989},"  --vendor",[3273,5076,5077],{"class":4124}," \"Kostyl Dev\"",[3273,5079,5039],{"class":5038},[3273,5081,5082,5085,5088],{"class":3275,"line":3342},[3273,5083,5084],{"class":3989},"  --input",[3273,5086,5087],{"class":4124}," target\u002F",[3273,5089,5039],{"class":5038},[3273,5091,5092,5095,5098],{"class":3275,"line":3361},[3273,5093,5094],{"class":3989},"  --main-jar",[3273,5096,5097],{"class":4124}," audiobook-app-fat.jar",[3273,5099,5039],{"class":5038},[3273,5101,5102,5105,5108],{"class":3275,"line":3380},[3273,5103,5104],{"class":3989},"  --main-class",[3273,5106,5107],{"class":4124}," dev.kostyl.audiobook.Launcher",[3273,5109,5039],{"class":5038},[3273,5111,5112,5115,5118],{"class":3275,"line":3390},[3273,5113,5114],{"class":3989},"  --icon",[3273,5116,5117],{"class":4124}," packaging\u002Fmacos\u002Faudiobook.icns",[3273,5119,5039],{"class":5038},[3273,5121,5122,5125,5128],{"class":3275,"line":3410},[3273,5123,5124],{"class":3989},"  --dest",[3273,5126,5127],{"class":4124}," dist\u002F",[3273,5129,5039],{"class":5038},[3273,5131,5132,5135,5138],{"class":3275,"line":3428},[3273,5133,5134],{"class":3989},"  --mac-package-name",[3273,5136,5137],{"class":4124}," \"audiobook-platform\"",[3273,5139,5039],{"class":5038},[3273,5141,5142,5145],{"class":3275,"line":3438},[3273,5143,5144],{"class":3989},"  --mac-package-identifier",[3273,5146,5147],{"class":4124}," \"dev.kostyl.audiobook\"\n",[3238,5149,5150,5153,5154,5157,5158,5161,5162,3250],{},[3154,5151,5152],{},"Підпис коду (Code Signing) для macOS."," Якщо ви плануєте розповсюджувати програму через App Store або не хочете, щоб macOS Gatekeeper блокував запуск, необхідно підписати інсталятор сертифікатом Apple Developer Certificate. Для цього додайте параметр ",[3171,5155,5156],{},"--mac-sign"," та вкажіть ",[3171,5159,5160],{},"--mac-signing-key-user-name \"Developer Name (TEAMID)\"",". Процес потребує Apple Developer Program ($99\u002Fрік). Для навчальних проєктів підпис не є обов'язковим — користувачі можуть запустити програму через ",[3171,5163,5164],{},"Ctrl+Click → Відкрити",[3215,5166,5168],{"id":5167},"генерація-пакету-для-linux-deb","Генерація пакету для Linux (.deb)",[3150,5170,5023,5171,5174],{},[3154,5172,5173],{},"Linux-машині"," (Debian\u002FUbuntu):",[3263,5176,5178],{"className":4107,"code":5177,"language":4109,"meta":3269,"style":3269},"jpackage \\\n  --type deb \\\n  --name \"audiobook-platform\" \\\n  --app-version \"1.0.0\" \\\n  --vendor \"Kostyl Dev\" \\\n  --input target\u002F \\\n  --main-jar audiobook-app-fat.jar \\\n  --main-class dev.kostyl.audiobook.Launcher \\\n  --icon packaging\u002Flinux\u002Faudiobook.png \\\n  --dest dist\u002F \\\n  --linux-package-name \"audiobook-platform\" \\\n  --linux-app-category \"Education\" \\\n  --linux-shortcut\n",[3171,5179,5180,5186,5195,5203,5211,5219,5227,5235,5243,5252,5260,5269,5279],{"__ignoreMap":3269},[3273,5181,5182,5184],{"class":3275,"line":3276},[3273,5183,3246],{"class":4050},[3273,5185,5039],{"class":5038},[3273,5187,5188,5190,5193],{"class":3275,"line":3290},[3273,5189,5044],{"class":3989},[3273,5191,5192],{"class":4124}," deb",[3273,5194,5039],{"class":5038},[3273,5196,5197,5199,5201],{"class":3275,"line":3301},[3273,5198,5054],{"class":3989},[3273,5200,5137],{"class":4124},[3273,5202,5039],{"class":5038},[3273,5204,5205,5207,5209],{"class":3275,"line":3308},[3273,5206,5064],{"class":3989},[3273,5208,5067],{"class":4124},[3273,5210,5039],{"class":5038},[3273,5212,5213,5215,5217],{"class":3275,"line":3319},[3273,5214,5074],{"class":3989},[3273,5216,5077],{"class":4124},[3273,5218,5039],{"class":5038},[3273,5220,5221,5223,5225],{"class":3275,"line":3342},[3273,5222,5084],{"class":3989},[3273,5224,5087],{"class":4124},[3273,5226,5039],{"class":5038},[3273,5228,5229,5231,5233],{"class":3275,"line":3361},[3273,5230,5094],{"class":3989},[3273,5232,5097],{"class":4124},[3273,5234,5039],{"class":5038},[3273,5236,5237,5239,5241],{"class":3275,"line":3380},[3273,5238,5104],{"class":3989},[3273,5240,5107],{"class":4124},[3273,5242,5039],{"class":5038},[3273,5244,5245,5247,5250],{"class":3275,"line":3390},[3273,5246,5114],{"class":3989},[3273,5248,5249],{"class":4124}," packaging\u002Flinux\u002Faudiobook.png",[3273,5251,5039],{"class":5038},[3273,5253,5254,5256,5258],{"class":3275,"line":3410},[3273,5255,5124],{"class":3989},[3273,5257,5127],{"class":4124},[3273,5259,5039],{"class":5038},[3273,5261,5262,5265,5267],{"class":3275,"line":3428},[3273,5263,5264],{"class":3989},"  --linux-package-name",[3273,5266,5137],{"class":4124},[3273,5268,5039],{"class":5038},[3273,5270,5271,5274,5277],{"class":3275,"line":3438},[3273,5272,5273],{"class":3989},"  --linux-app-category",[3273,5275,5276],{"class":4124}," \"Education\"",[3273,5278,5039],{"class":5038},[3273,5280,5281],{"class":3275,"line":3448},[3273,5282,5283],{"class":3989},"  --linux-shortcut\n",[3208,5285],{},[3145,5287,5289],{"id":5288},"частина-iii-автоматизація-jpackage-maven-plugin-та-github-actions","Частина III. Автоматизація: jpackage-maven-plugin та GitHub Actions",[3215,5291,5293],{"id":5292},"інтеграція-jpackage-у-збірку-maven","Інтеграція jpackage у збірку Maven",[3150,5295,5296,5297,5299,5300,5305,5306,5309,5310,5312],{},"Виконання ",[3171,5298,3246],{}," вручну з командного рядка є зручним для налагодження, але незручним для регулярних релізів. Плагін ",[3154,5301,5302],{},[3171,5303,5304],{},"jpackage-maven-plugin"," від проєкту ",[3171,5307,5308],{},"io.github.fvarrui"," дозволяє описати всі параметри пакування безпосередньо у ",[3171,5311,3267],{}," та запускати пакування однією командою.",[3263,5314,5316],{"className":3265,"code":5315,"filename":3267,"language":3268,"meta":3269,"style":3269},"\u003Cplugin>\n    \u003CgroupId>io.github.fvarrui\u003C\u002FgroupId>\n    \u003CartifactId>javapackager\u003C\u002FartifactId>\n    \u003Cversion>1.7.6\u003C\u002Fversion>\n    \u003Cexecutions>\n        \u003Cexecution>\n            \u003Cphase>package\u003C\u002Fphase>\n            \u003Cgoals>\n                \u003Cgoal>package\u003C\u002Fgoal>\n            \u003C\u002Fgoals>\n            \u003Cconfiguration>\n                \u003CmainClass>dev.kostyl.audiobook.Launcher\u003C\u002FmainClass>\n                \u003CbundleJre>true\u003C\u002FbundleJre>\n                \u003CgenerateInstaller>true\u003C\u002FgenerateInstaller>\n                \u003CadministratorRequired>false\u003C\u002FadministratorRequired>\n                \u003Cplatform>auto\u003C\u002Fplatform>\n                \u003Cname>Audiobook Platform\u003C\u002Fname>\n                \u003Cversion>1.0.0\u003C\u002Fversion>\n                \u003CorganizationName>Kostyl Dev\u003C\u002ForganizationName>\n                \u003CorganizationUrl>https:\u002F\u002Fkostyl.dev\u003C\u002ForganizationUrl>\n                \u003CiconFile>packaging\u002Fapp-icon\u003C\u002FiconFile>\u003C!-- без розширення: плагін підбирає .ico\u002F.icns\u002F.png -->\n                \u003CoutputDirectory>dist\u003C\u002FoutputDirectory>\n                \u003CwinConfig>\n                    \u003CcreateDesktopIconLink>true\u003C\u002FcreateDesktopIconLink>\n                    \u003CcreateStartMenuIconLink>true\u003C\u002FcreateStartMenuIconLink>\n                    \u003CmenuGroupName>Kostyl Dev\u003C\u002FmenuGroupName>\n                    \u003CgenerateInstaller>true\u003C\u002FgenerateInstaller>\n                    \u003CinstallerType>msi\u003C\u002FinstallerType>\n                \u003C\u002FwinConfig>\n                \u003CmacConfig>\n                    \u003CgenerateDmg>true\u003C\u002FgenerateDmg>\n                \u003C\u002FmacConfig>\n                \u003ClinuxConfig>\n                    \u003CgenerateDeb>true\u003C\u002FgenerateDeb>\n                    \u003CgenerateRpm>false\u003C\u002FgenerateRpm>\n                \u003C\u002FlinuxConfig>\n            \u003C\u002Fconfiguration>\n        \u003C\u002Fexecution>\n    \u003C\u002Fexecutions>\n\u003C\u002Fplugin>\n",[3171,5317,5318,5326,5342,5359,5376,5384,5392,5408,5416,5432,5440,5448,5464,5482,5499,5517,5535,5553,5570,5588,5606,5627,5645,5654,5671,5688,5705,5721,5738,5746,5755,5772,5780,5789,5806,5823,5831,5839,5847,5855],{"__ignoreMap":3269},[3273,5319,5320,5322,5324],{"class":3275,"line":3276},[3273,5321,3280],{"class":3279},[3273,5323,3314],{"class":3283},[3273,5325,3287],{"class":3279},[3273,5327,5328,5330,5332,5334,5336,5338,5340],{"class":3275,"line":3290},[3273,5329,3293],{"class":3279},[3273,5331,3325],{"class":3283},[3273,5333,3328],{"class":3279},[3273,5335,5308],{"class":3331},[3273,5337,3335],{"class":3279},[3273,5339,3325],{"class":3283},[3273,5341,3287],{"class":3279},[3273,5343,5344,5346,5348,5350,5353,5355,5357],{"class":3275,"line":3301},[3273,5345,3293],{"class":3279},[3273,5347,3347],{"class":3283},[3273,5349,3328],{"class":3279},[3273,5351,5352],{"class":3331},"javapackager",[3273,5354,3335],{"class":3279},[3273,5356,3347],{"class":3283},[3273,5358,3287],{"class":3279},[3273,5360,5361,5363,5365,5367,5370,5372,5374],{"class":3275,"line":3308},[3273,5362,3293],{"class":3279},[3273,5364,3366],{"class":3283},[3273,5366,3328],{"class":3279},[3273,5368,5369],{"class":3331},"1.7.6",[3273,5371,3335],{"class":3279},[3273,5373,3366],{"class":3283},[3273,5375,3287],{"class":3279},[3273,5377,5378,5380,5382],{"class":3275,"line":3319},[3273,5379,3293],{"class":3279},[3273,5381,3527],{"class":3283},[3273,5383,3287],{"class":3279},[3273,5385,5386,5388,5390],{"class":3275,"line":3342},[3273,5387,3311],{"class":3279},[3273,5389,3537],{"class":3283},[3273,5391,3287],{"class":3279},[3273,5393,5394,5396,5398,5400,5402,5404,5406],{"class":3275,"line":3361},[3273,5395,3322],{"class":3279},[3273,5397,3548],{"class":3283},[3273,5399,3328],{"class":3279},[3273,5401,3553],{"class":3331},[3273,5403,3335],{"class":3279},[3273,5405,3548],{"class":3283},[3273,5407,3287],{"class":3279},[3273,5409,5410,5412,5414],{"class":3275,"line":3380},[3273,5411,3322],{"class":3279},[3273,5413,3567],{"class":3283},[3273,5415,3287],{"class":3279},[3273,5417,5418,5420,5422,5424,5426,5428,5430],{"class":3275,"line":3390},[3273,5419,3393],{"class":3279},[3273,5421,3578],{"class":3283},[3273,5423,3328],{"class":3279},[3273,5425,3553],{"class":3331},[3273,5427,3335],{"class":3279},[3273,5429,3578],{"class":3283},[3273,5431,3287],{"class":3279},[3273,5433,5434,5436,5438],{"class":3275,"line":3410},[3273,5435,3431],{"class":3279},[3273,5437,3567],{"class":3283},[3273,5439,3287],{"class":3279},[3273,5441,5442,5444,5446],{"class":3275,"line":3428},[3273,5443,3322],{"class":3279},[3273,5445,3385],{"class":3283},[3273,5447,3287],{"class":3279},[3273,5449,5450,5452,5454,5456,5458,5460,5462],{"class":3275,"line":3438},[3273,5451,3393],{"class":3279},[3273,5453,3658],{"class":3283},[3273,5455,3328],{"class":3279},[3273,5457,3663],{"class":3331},[3273,5459,3335],{"class":3279},[3273,5461,3658],{"class":3283},[3273,5463,3287],{"class":3279},[3273,5465,5466,5468,5471,5473,5476,5478,5480],{"class":3275,"line":3448},[3273,5467,3393],{"class":3279},[3273,5469,5470],{"class":3283},"bundleJre",[3273,5472,3328],{"class":3279},[3273,5474,5475],{"class":3331},"true",[3273,5477,3335],{"class":3279},[3273,5479,5470],{"class":3283},[3273,5481,3287],{"class":3279},[3273,5483,5484,5486,5489,5491,5493,5495,5497],{"class":3275,"line":3455},[3273,5485,3393],{"class":3279},[3273,5487,5488],{"class":3283},"generateInstaller",[3273,5490,3328],{"class":3279},[3273,5492,5475],{"class":3331},[3273,5494,3335],{"class":3279},[3273,5496,5488],{"class":3283},[3273,5498,3287],{"class":3279},[3273,5500,5501,5503,5506,5508,5511,5513,5515],{"class":3275,"line":3461},[3273,5502,3393],{"class":3279},[3273,5504,5505],{"class":3283},"administratorRequired",[3273,5507,3328],{"class":3279},[3273,5509,5510],{"class":3331},"false",[3273,5512,3335],{"class":3279},[3273,5514,5505],{"class":3283},[3273,5516,3287],{"class":3279},[3273,5518,5519,5521,5524,5526,5529,5531,5533],{"class":3275,"line":3470},[3273,5520,3393],{"class":3279},[3273,5522,5523],{"class":3283},"platform",[3273,5525,3328],{"class":3279},[3273,5527,5528],{"class":3331},"auto",[3273,5530,3335],{"class":3279},[3273,5532,5523],{"class":3283},[3273,5534,3287],{"class":3279},[3273,5536,5537,5539,5542,5544,5547,5549,5551],{"class":3275,"line":3487},[3273,5538,3393],{"class":3279},[3273,5540,5541],{"class":3283},"name",[3273,5543,3328],{"class":3279},[3273,5545,5546],{"class":3331},"Audiobook Platform",[3273,5548,3335],{"class":3279},[3273,5550,5541],{"class":3283},[3273,5552,3287],{"class":3279},[3273,5554,5555,5557,5559,5561,5564,5566,5568],{"class":3275,"line":3504},[3273,5556,3393],{"class":3279},[3273,5558,3366],{"class":3283},[3273,5560,3328],{"class":3279},[3273,5562,5563],{"class":3331},"1.0.0",[3273,5565,3335],{"class":3279},[3273,5567,3366],{"class":3283},[3273,5569,3287],{"class":3279},[3273,5571,5572,5574,5577,5579,5582,5584,5586],{"class":3275,"line":3522},[3273,5573,3393],{"class":3279},[3273,5575,5576],{"class":3283},"organizationName",[3273,5578,3328],{"class":3279},[3273,5580,5581],{"class":3331},"Kostyl Dev",[3273,5583,3335],{"class":3279},[3273,5585,5576],{"class":3283},[3273,5587,3287],{"class":3279},[3273,5589,5590,5592,5595,5597,5600,5602,5604],{"class":3275,"line":3532},[3273,5591,3393],{"class":3279},[3273,5593,5594],{"class":3283},"organizationUrl",[3273,5596,3328],{"class":3279},[3273,5598,5599],{"class":3331},"https:\u002F\u002Fkostyl.dev",[3273,5601,3335],{"class":3279},[3273,5603,5594],{"class":3283},[3273,5605,3287],{"class":3279},[3273,5607,5608,5610,5613,5615,5618,5620,5622,5624],{"class":3275,"line":3542},[3273,5609,3393],{"class":3279},[3273,5611,5612],{"class":3283},"iconFile",[3273,5614,3328],{"class":3279},[3273,5616,5617],{"class":3331},"packaging\u002Fapp-icon",[3273,5619,3335],{"class":3279},[3273,5621,5612],{"class":3283},[3273,5623,3328],{"class":3279},[3273,5625,5626],{"class":3304},"\u003C!-- без розширення: плагін підбирає .ico\u002F.icns\u002F.png -->\n",[3273,5628,5629,5631,5634,5636,5639,5641,5643],{"class":3275,"line":3562},[3273,5630,3393],{"class":3279},[3273,5632,5633],{"class":3283},"outputDirectory",[3273,5635,3328],{"class":3279},[3273,5637,5638],{"class":3331},"dist",[3273,5640,3335],{"class":3279},[3273,5642,5633],{"class":3283},[3273,5644,3287],{"class":3279},[3273,5646,5647,5649,5652],{"class":3275,"line":3572},[3273,5648,3393],{"class":3279},[3273,5650,5651],{"class":3283},"winConfig",[3273,5653,3287],{"class":3279},[3273,5655,5656,5658,5661,5663,5665,5667,5669],{"class":3275,"line":3592},[3273,5657,3545],{"class":3279},[3273,5659,5660],{"class":3283},"createDesktopIconLink",[3273,5662,3328],{"class":3279},[3273,5664,5475],{"class":3331},[3273,5666,3335],{"class":3279},[3273,5668,5660],{"class":3283},[3273,5670,3287],{"class":3279},[3273,5672,5673,5675,5678,5680,5682,5684,5686],{"class":3275,"line":3602},[3273,5674,3545],{"class":3279},[3273,5676,5677],{"class":3283},"createStartMenuIconLink",[3273,5679,3328],{"class":3279},[3273,5681,5475],{"class":3331},[3273,5683,3335],{"class":3279},[3273,5685,5677],{"class":3283},[3273,5687,3287],{"class":3279},[3273,5689,5690,5692,5695,5697,5699,5701,5703],{"class":3275,"line":3611},[3273,5691,3545],{"class":3279},[3273,5693,5694],{"class":3283},"menuGroupName",[3273,5696,3328],{"class":3279},[3273,5698,5581],{"class":3331},[3273,5700,3335],{"class":3279},[3273,5702,5694],{"class":3283},[3273,5704,3287],{"class":3279},[3273,5706,5707,5709,5711,5713,5715,5717,5719],{"class":3275,"line":3617},[3273,5708,3545],{"class":3279},[3273,5710,5488],{"class":3283},[3273,5712,3328],{"class":3279},[3273,5714,5475],{"class":3331},[3273,5716,3335],{"class":3279},[3273,5718,5488],{"class":3283},[3273,5720,3287],{"class":3279},[3273,5722,5723,5725,5728,5730,5732,5734,5736],{"class":3275,"line":3627},[3273,5724,3545],{"class":3279},[3273,5726,5727],{"class":3283},"installerType",[3273,5729,3328],{"class":3279},[3273,5731,4893],{"class":3331},[3273,5733,3335],{"class":3279},[3273,5735,5727],{"class":3283},[3273,5737,3287],{"class":3279},[3273,5739,5740,5742,5744],{"class":3275,"line":3643},[3273,5741,3900],{"class":3279},[3273,5743,5651],{"class":3283},[3273,5745,3287],{"class":3279},[3273,5747,5748,5750,5753],{"class":3275,"line":3652},[3273,5749,3393],{"class":3279},[3273,5751,5752],{"class":3283},"macConfig",[3273,5754,3287],{"class":3279},[3273,5756,5757,5759,5762,5764,5766,5768,5770],{"class":3275,"line":3672},[3273,5758,3545],{"class":3279},[3273,5760,5761],{"class":3283},"generateDmg",[3273,5763,3328],{"class":3279},[3273,5765,5475],{"class":3331},[3273,5767,3335],{"class":3279},[3273,5769,5761],{"class":3283},[3273,5771,3287],{"class":3279},[3273,5773,5774,5776,5778],{"class":3275,"line":3682},[3273,5775,3900],{"class":3279},[3273,5777,5752],{"class":3283},[3273,5779,3287],{"class":3279},[3273,5781,5782,5784,5787],{"class":3275,"line":3688},[3273,5783,3393],{"class":3279},[3273,5785,5786],{"class":3283},"linuxConfig",[3273,5788,3287],{"class":3279},[3273,5790,5791,5793,5796,5798,5800,5802,5804],{"class":3275,"line":3699},[3273,5792,3545],{"class":3279},[3273,5794,5795],{"class":3283},"generateDeb",[3273,5797,3328],{"class":3279},[3273,5799,5475],{"class":3331},[3273,5801,3335],{"class":3279},[3273,5803,5795],{"class":3283},[3273,5805,3287],{"class":3279},[3273,5807,5808,5810,5813,5815,5817,5819,5821],{"class":3275,"line":3708},[3273,5809,3545],{"class":3279},[3273,5811,5812],{"class":3283},"generateRpm",[3273,5814,3328],{"class":3279},[3273,5816,5510],{"class":3331},[3273,5818,3335],{"class":3279},[3273,5820,5812],{"class":3283},[3273,5822,3287],{"class":3279},[3273,5824,5825,5827,5829],{"class":3275,"line":3718},[3273,5826,3900],{"class":3279},[3273,5828,5786],{"class":3283},[3273,5830,3287],{"class":3279},[3273,5832,5833,5835,5837],{"class":3275,"line":3724},[3273,5834,3431],{"class":3279},[3273,5836,3385],{"class":3283},[3273,5838,3287],{"class":3279},[3273,5840,5841,5843,5845],{"class":3275,"line":3734},[3273,5842,3441],{"class":3279},[3273,5844,3537],{"class":3283},[3273,5846,3287],{"class":3279},[3273,5848,5849,5851,5853],{"class":3275,"line":3744},[3273,5850,3928],{"class":3279},[3273,5852,3527],{"class":3283},[3273,5854,3287],{"class":3279},[3273,5856,5857,5859,5861],{"class":3275,"line":3763},[3273,5858,3335],{"class":3279},[3273,5860,3314],{"class":3283},[3273,5862,3287],{"class":3279},[3150,5864,5865],{},"Тепер запустити повний цикл збірки та пакування можна однією командою:",[3263,5867,5869],{"className":4107,"code":5868,"language":4109,"meta":3269,"style":3269},"mvn clean package\n# → target\u002Faudiobook-app-fat.jar     (Fat JAR)\n# → dist\u002FAudiobook Platform-1.0.0.msi  (Windows)  або\n# → dist\u002FAudiobook Platform-1.0.0.dmg  (macOS)    або\n# → dist\u002Faudiobook-platform_1.0.0.deb  (Linux)\n",[3171,5870,5871,5879,5884,5889,5894],{"__ignoreMap":3269},[3273,5872,5873,5875,5877],{"class":3275,"line":3276},[3273,5874,4121],{"class":4050},[3273,5876,4125],{"class":4124},[3273,5878,4128],{"class":4124},[3273,5880,5881],{"class":3275,"line":3290},[3273,5882,5883],{"class":3304},"# → target\u002Faudiobook-app-fat.jar     (Fat JAR)\n",[3273,5885,5886],{"class":3275,"line":3301},[3273,5887,5888],{"class":3304},"# → dist\u002FAudiobook Platform-1.0.0.msi  (Windows)  або\n",[3273,5890,5891],{"class":3275,"line":3308},[3273,5892,5893],{"class":3304},"# → dist\u002FAudiobook Platform-1.0.0.dmg  (macOS)    або\n",[3273,5895,5896],{"class":3275,"line":3319},[3273,5897,5898],{"class":3304},"# → dist\u002Faudiobook-platform_1.0.0.deb  (Linux)\n",[3215,5900,5902],{"id":5901},"github-actions-збірка-інсталяторів-для-всіх-платформ","GitHub Actions: Збірка інсталяторів для всіх платформ",[3150,5904,5905],{},"Найпрофесійніший підхід — автоматична збірка інсталяторів для всіх трьох платформ при кожному новому тегу релізу. GitHub Actions надає безкоштовні runner-агенти для Windows, macOS та Ubuntu.",[3150,5907,5908,5909,5912],{},"Створіть файл ",[3171,5910,5911],{},".github\u002Fworkflows\u002Frelease.yml"," у репозиторії:",[3263,5914,5918],{"className":5915,"code":5916,"filename":5911,"language":5917,"meta":3269,"style":3269},"language-yaml shiki shiki-themes light-plus dark-plus dark-plus","name: Release — Build Installers\n\n# Запускається при пуші тегу виду v1.0.0, v2.3.1 тощо\non:\n  push:\n    tags:\n      - 'v*.*.*'\n\njobs:\n  build-installers:\n    # Матриця: три паралельних завдання для трьох ОС\n    strategy:\n      matrix:\n        os: [windows-latest, macos-latest, ubuntu-latest]\n    \n    runs-on: ${{ matrix.os }}\n    \n    steps:\n      # 1. Клонування репозиторію\n      - name: Checkout repository\n        uses: actions\u002Fcheckout@v4\n\n      # 2. Встановлення JDK 25 (включає jpackage)\n      - name: Set up JDK 25\n        uses: actions\u002Fsetup-java@v4\n        with:\n          java-version: '25'\n          distribution: 'temurin'\n          cache: maven\n\n      # 3. Встановлення WiX Toolset (лише для Windows)\n      - name: Install WiX Toolset (Windows only)\n        if: matrix.os == 'windows-latest'\n        run: |\n          choco install wixtoolset --yes\n\n      # 4. Встановлення інструментів збірки RPM (лише для Linux)\n      - name: Install RPM packaging tools (Linux only)\n        if: matrix.os == 'ubuntu-latest'\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y rpm\n\n      # 5. Збірка Fat JAR\n      - name: Build Fat JAR\n        run: mvn clean package -DskipTests\n\n      # 6. Підготовка директорії вхідних файлів для jpackage\n      - name: Prepare jpackage input\n        run: |\n          mkdir -p jpackage-input\n          cp target\u002Faudiobook-app-fat.jar jpackage-input\u002F\n\n      # 7. Визначення версії з тегу (v1.0.0 → 1.0.0)\n      - name: Extract version from tag\n        id: version\n        shell: bash\n        run: echo \"VERSION=${GITHUB_REF_NAME#v}\" >> $GITHUB_OUTPUT\n\n      # 8. Генерація нативного інсталятора через jpackage\n      - name: Package installer (Windows)\n        if: matrix.os == 'windows-latest'\n        shell: pwsh\n        run: |\n          jpackage `\n            --type msi `\n            --name \"Audiobook Platform\" `\n            --app-version \"${{ steps.version.outputs.VERSION }}\" `\n            --vendor \"Kostyl Dev\" `\n            --input jpackage-input\u002F `\n            --main-jar audiobook-app-fat.jar `\n            --main-class dev.kostyl.audiobook.Launcher `\n            --icon packaging\u002Fwindows\u002Faudiobook.ico `\n            --dest dist\u002F `\n            --win-dir-chooser `\n            --win-menu `\n            --win-shortcut\n\n      - name: Package installer (macOS)\n        if: matrix.os == 'macos-latest'\n        run: |\n          jpackage \\\n            --type dmg \\\n            --name \"Audiobook Platform\" \\\n            --app-version \"${{ steps.version.outputs.VERSION }}\" \\\n            --vendor \"Kostyl Dev\" \\\n            --input jpackage-input\u002F \\\n            --main-jar audiobook-app-fat.jar \\\n            --main-class dev.kostyl.audiobook.Launcher \\\n            --icon packaging\u002Fmacos\u002Faudiobook.icns \\\n            --dest dist\u002F\n\n      - name: Package installer (Linux DEB & RPM)\n        if: matrix.os == 'ubuntu-latest'\n        run: |\n          # Створення DEB-пакета для Debian\u002FUbuntu\n          jpackage \\\n            --type deb \\\n            --name \"audiobook-platform\" \\\n            --app-version \"${{ steps.version.outputs.VERSION }}\" \\\n            --vendor \"Kostyl Dev\" \\\n            --input jpackage-input\u002F \\\n            --main-jar audiobook-app-fat.jar \\\n            --main-class dev.kostyl.audiobook.Launcher \\\n            --icon packaging\u002Flinux\u002Faudiobook.png \\\n            --dest dist\u002F \\\n            --linux-shortcut\n\n          # Створення RPM-пакета для RedHat\u002FFedora\u002FCentOS\n          jpackage \\\n            --type rpm \\\n            --name \"audiobook-platform\" \\\n            --app-version \"${{ steps.version.outputs.VERSION }}\" \\\n            --vendor \"Kostyl Dev\" \\\n            --input jpackage-input\u002F \\\n            --main-jar audiobook-app-fat.jar \\\n            --main-class dev.kostyl.audiobook.Launcher \\\n            --icon packaging\u002Flinux\u002Faudiobook.png \\\n            --dest dist\u002F \\\n            --linux-shortcut\n\n          # Копіювання Fat JAR у директорію dist, щоб він також потрапив у реліз\n          cp target\u002Faudiobook-app-fat.jar dist\u002F\n\n      # 9. Збереження артефактів для наступного завдання\n      - name: Upload installer artifact\n        uses: actions\u002Fupload-artifact@v4\n        with:\n          name: installer-${{ matrix.os }}\n          path: dist\u002F\n          retention-days: 1\n\n  # Окреме завдання: публікація GitHub Release\n  publish-release:\n    needs: build-installers\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n\n    steps:\n      - name: Download all installer artifacts\n        uses: actions\u002Fdownload-artifact@v4\n        with:\n          path: installers\u002F\n          merge-multiple: true\n\n      - name: Create GitHub Release\n        uses: softprops\u002Faction-gh-release@v2\n        with:\n          name: \"Audiobook Platform ${{ github.ref_name }}\"\n          body: |\n            ## Що нового у ${{ github.ref_name }}\n\n            Опис змін цього релізу.\n\n            ## Завантаження\n\n            | Операційна система \u002F Платформа | Файл |\n            |---|---|\n            | Windows 10\u002F11 | `*.msi` |\n            | macOS 12+ | `*.dmg` |\n            | Ubuntu\u002FDebian | `*.deb` |\n            | RedHat\u002FFedora | `*.rpm` |\n            | Будь-яка (з встановленою JRE) | `*.jar` |\n          files: installers\u002F**\n          draft: false\n          prerelease: false\n","yaml",[3171,5919,5920,5930,5934,5939,5947,5954,5961,5969,5973,5980,5987,5992,5999,6006,6030,6035,6045,6049,6056,6061,6072,6082,6086,6091,6102,6111,6118,6128,6138,6148,6152,6157,6168,6178,6189,6194,6198,6203,6214,6223,6231,6236,6241,6245,6250,6261,6270,6274,6279,6290,6298,6303,6308,6312,6317,6328,6338,6349,6359,6364,6370,6382,6391,6401,6410,6416,6422,6428,6434,6440,6446,6452,6458,6464,6470,6476,6482,6488,6493,6505,6515,6524,6530,6536,6542,6548,6554,6560,6566,6572,6578,6584,6589,6601,6610,6619,6625,6630,6636,6642,6647,6652,6657,6662,6667,6673,6679,6685,6690,6696,6701,6707,6712,6717,6722,6727,6732,6737,6742,6747,6752,6757,6763,6769,6774,6780,6792,6802,6809,6820,6831,6843,6848,6854,6862,6873,6883,6891,6902,6907,6914,6926,6936,6943,6953,6964,6969,6981,6991,6998,7008,7018,7024,7029,7035,7040,7046,7051,7057,7063,7069,7075,7081,7087,7093,7104,7115],{"__ignoreMap":3269},[3273,5921,5922,5924,5927],{"class":3275,"line":3276},[3273,5923,5541],{"class":3283},[3273,5925,5926],{"class":3331},": ",[3273,5928,5929],{"class":3646},"Release — Build Installers\n",[3273,5931,5932],{"class":3275,"line":3290},[3273,5933,3452],{"emptyLinePlaceholder":3451},[3273,5935,5936],{"class":3275,"line":3301},[3273,5937,5938],{"class":3304},"# Запускається при пуші тегу виду v1.0.0, v2.3.1 тощо\n",[3273,5940,5941,5944],{"class":3275,"line":3308},[3273,5942,5943],{"class":3989},"on",[3273,5945,5946],{"class":3331},":\n",[3273,5948,5949,5952],{"class":3275,"line":3319},[3273,5950,5951],{"class":3283},"  push",[3273,5953,5946],{"class":3331},[3273,5955,5956,5959],{"class":3275,"line":3342},[3273,5957,5958],{"class":3283},"    tags",[3273,5960,5946],{"class":3331},[3273,5962,5963,5966],{"class":3275,"line":3361},[3273,5964,5965],{"class":3331},"      - ",[3273,5967,5968],{"class":3646},"'v*.*.*'\n",[3273,5970,5971],{"class":3275,"line":3380},[3273,5972,3452],{"emptyLinePlaceholder":3451},[3273,5974,5975,5978],{"class":3275,"line":3390},[3273,5976,5977],{"class":3283},"jobs",[3273,5979,5946],{"class":3331},[3273,5981,5982,5985],{"class":3275,"line":3410},[3273,5983,5984],{"class":3283},"  build-installers",[3273,5986,5946],{"class":3331},[3273,5988,5989],{"class":3275,"line":3428},[3273,5990,5991],{"class":3304},"    # Матриця: три паралельних завдання для трьох ОС\n",[3273,5993,5994,5997],{"class":3275,"line":3438},[3273,5995,5996],{"class":3283},"    strategy",[3273,5998,5946],{"class":3331},[3273,6000,6001,6004],{"class":3275,"line":3448},[3273,6002,6003],{"class":3283},"      matrix",[3273,6005,5946],{"class":3331},[3273,6007,6008,6011,6014,6017,6019,6022,6024,6027],{"class":3275,"line":3455},[3273,6009,6010],{"class":3283},"        os",[3273,6012,6013],{"class":3331},": [",[3273,6015,6016],{"class":3646},"windows-latest",[3273,6018,4749],{"class":3331},[3273,6020,6021],{"class":3646},"macos-latest",[3273,6023,4749],{"class":3331},[3273,6025,6026],{"class":3646},"ubuntu-latest",[3273,6028,6029],{"class":3331},"]\n",[3273,6031,6032],{"class":3275,"line":3461},[3273,6033,6034],{"class":3331},"    \n",[3273,6036,6037,6040,6042],{"class":3275,"line":3470},[3273,6038,6039],{"class":3283},"    runs-on",[3273,6041,5926],{"class":3331},[3273,6043,6044],{"class":3646},"${{ matrix.os }}\n",[3273,6046,6047],{"class":3275,"line":3487},[3273,6048,6034],{"class":3331},[3273,6050,6051,6054],{"class":3275,"line":3504},[3273,6052,6053],{"class":3283},"    steps",[3273,6055,5946],{"class":3331},[3273,6057,6058],{"class":3275,"line":3522},[3273,6059,6060],{"class":3304},"      # 1. Клонування репозиторію\n",[3273,6062,6063,6065,6067,6069],{"class":3275,"line":3532},[3273,6064,5965],{"class":3331},[3273,6066,5541],{"class":3283},[3273,6068,5926],{"class":3331},[3273,6070,6071],{"class":3646},"Checkout repository\n",[3273,6073,6074,6077,6079],{"class":3275,"line":3542},[3273,6075,6076],{"class":3283},"        uses",[3273,6078,5926],{"class":3331},[3273,6080,6081],{"class":3646},"actions\u002Fcheckout@v4\n",[3273,6083,6084],{"class":3275,"line":3562},[3273,6085,3452],{"emptyLinePlaceholder":3451},[3273,6087,6088],{"class":3275,"line":3572},[3273,6089,6090],{"class":3304},"      # 2. Встановлення JDK 25 (включає jpackage)\n",[3273,6092,6093,6095,6097,6099],{"class":3275,"line":3592},[3273,6094,5965],{"class":3331},[3273,6096,5541],{"class":3283},[3273,6098,5926],{"class":3331},[3273,6100,6101],{"class":3646},"Set up JDK 25\n",[3273,6103,6104,6106,6108],{"class":3275,"line":3602},[3273,6105,6076],{"class":3283},[3273,6107,5926],{"class":3331},[3273,6109,6110],{"class":3646},"actions\u002Fsetup-java@v4\n",[3273,6112,6113,6116],{"class":3275,"line":3611},[3273,6114,6115],{"class":3283},"        with",[3273,6117,5946],{"class":3331},[3273,6119,6120,6123,6125],{"class":3275,"line":3617},[3273,6121,6122],{"class":3283},"          java-version",[3273,6124,5926],{"class":3331},[3273,6126,6127],{"class":3646},"'25'\n",[3273,6129,6130,6133,6135],{"class":3275,"line":3627},[3273,6131,6132],{"class":3283},"          distribution",[3273,6134,5926],{"class":3331},[3273,6136,6137],{"class":3646},"'temurin'\n",[3273,6139,6140,6143,6145],{"class":3275,"line":3643},[3273,6141,6142],{"class":3283},"          cache",[3273,6144,5926],{"class":3331},[3273,6146,6147],{"class":3646},"maven\n",[3273,6149,6150],{"class":3275,"line":3652},[3273,6151,3452],{"emptyLinePlaceholder":3451},[3273,6153,6154],{"class":3275,"line":3672},[3273,6155,6156],{"class":3304},"      # 3. Встановлення WiX Toolset (лише для Windows)\n",[3273,6158,6159,6161,6163,6165],{"class":3275,"line":3682},[3273,6160,5965],{"class":3331},[3273,6162,5541],{"class":3283},[3273,6164,5926],{"class":3331},[3273,6166,6167],{"class":3646},"Install WiX Toolset (Windows only)\n",[3273,6169,6170,6173,6175],{"class":3275,"line":3688},[3273,6171,6172],{"class":3283},"        if",[3273,6174,5926],{"class":3331},[3273,6176,6177],{"class":3646},"matrix.os == 'windows-latest'\n",[3273,6179,6180,6183,6185],{"class":3275,"line":3699},[3273,6181,6182],{"class":3283},"        run",[3273,6184,5926],{"class":3331},[3273,6186,6188],{"class":6187},"s8xlr","|\n",[3273,6190,6191],{"class":3275,"line":3708},[3273,6192,6193],{"class":3646},"          choco install wixtoolset --yes\n",[3273,6195,6196],{"class":3275,"line":3718},[3273,6197,3452],{"emptyLinePlaceholder":3451},[3273,6199,6200],{"class":3275,"line":3724},[3273,6201,6202],{"class":3304},"      # 4. Встановлення інструментів збірки RPM (лише для Linux)\n",[3273,6204,6205,6207,6209,6211],{"class":3275,"line":3734},[3273,6206,5965],{"class":3331},[3273,6208,5541],{"class":3283},[3273,6210,5926],{"class":3331},[3273,6212,6213],{"class":3646},"Install RPM packaging tools (Linux only)\n",[3273,6215,6216,6218,6220],{"class":3275,"line":3744},[3273,6217,6172],{"class":3283},[3273,6219,5926],{"class":3331},[3273,6221,6222],{"class":3646},"matrix.os == 'ubuntu-latest'\n",[3273,6224,6225,6227,6229],{"class":3275,"line":3763},[3273,6226,6182],{"class":3283},[3273,6228,5926],{"class":3331},[3273,6230,6188],{"class":6187},[3273,6232,6233],{"class":3275,"line":3773},[3273,6234,6235],{"class":3646},"          sudo apt-get update\n",[3273,6237,6238],{"class":3275,"line":3793},[3273,6239,6240],{"class":3646},"          sudo apt-get install -y rpm\n",[3273,6242,6243],{"class":3275,"line":3811},[3273,6244,3452],{"emptyLinePlaceholder":3451},[3273,6246,6247],{"class":3275,"line":3829},[3273,6248,6249],{"class":3304},"      # 5. Збірка Fat JAR\n",[3273,6251,6252,6254,6256,6258],{"class":3275,"line":3839},[3273,6253,5965],{"class":3331},[3273,6255,5541],{"class":3283},[3273,6257,5926],{"class":3331},[3273,6259,6260],{"class":3646},"Build Fat JAR\n",[3273,6262,6263,6265,6267],{"class":3275,"line":3848},[3273,6264,6182],{"class":3283},[3273,6266,5926],{"class":3331},[3273,6268,6269],{"class":3646},"mvn clean package -DskipTests\n",[3273,6271,6272],{"class":3275,"line":3857},[3273,6273,3452],{"emptyLinePlaceholder":3451},[3273,6275,6276],{"class":3275,"line":3863},[3273,6277,6278],{"class":3304},"      # 6. Підготовка директорії вхідних файлів для jpackage\n",[3273,6280,6281,6283,6285,6287],{"class":3275,"line":3873},[3273,6282,5965],{"class":3331},[3273,6284,5541],{"class":3283},[3273,6286,5926],{"class":3331},[3273,6288,6289],{"class":3646},"Prepare jpackage input\n",[3273,6291,6292,6294,6296],{"class":3275,"line":3879},[3273,6293,6182],{"class":3283},[3273,6295,5926],{"class":3331},[3273,6297,6188],{"class":6187},[3273,6299,6300],{"class":3275,"line":3888},[3273,6301,6302],{"class":3646},"          mkdir -p jpackage-input\n",[3273,6304,6305],{"class":3275,"line":3897},[3273,6306,6307],{"class":3646},"          cp target\u002Faudiobook-app-fat.jar jpackage-input\u002F\n",[3273,6309,6310],{"class":3275,"line":3907},[3273,6311,3452],{"emptyLinePlaceholder":3451},[3273,6313,6314],{"class":3275,"line":3916},[3273,6315,6316],{"class":3304},"      # 7. Визначення версії з тегу (v1.0.0 → 1.0.0)\n",[3273,6318,6319,6321,6323,6325],{"class":3275,"line":3925},[3273,6320,5965],{"class":3331},[3273,6322,5541],{"class":3283},[3273,6324,5926],{"class":3331},[3273,6326,6327],{"class":3646},"Extract version from tag\n",[3273,6329,6330,6333,6335],{"class":3275,"line":3935},[3273,6331,6332],{"class":3283},"        id",[3273,6334,5926],{"class":3331},[3273,6336,6337],{"class":3646},"version\n",[3273,6339,6341,6344,6346],{"class":3275,"line":6340},57,[3273,6342,6343],{"class":3283},"        shell",[3273,6345,5926],{"class":3331},[3273,6347,6348],{"class":3646},"bash\n",[3273,6350,6352,6354,6356],{"class":3275,"line":6351},58,[3273,6353,6182],{"class":3283},[3273,6355,5926],{"class":3331},[3273,6357,6358],{"class":3646},"echo \"VERSION=${GITHUB_REF_NAME#v}\" >> $GITHUB_OUTPUT\n",[3273,6360,6362],{"class":3275,"line":6361},59,[3273,6363,3452],{"emptyLinePlaceholder":3451},[3273,6365,6367],{"class":3275,"line":6366},60,[3273,6368,6369],{"class":3304},"      # 8. Генерація нативного інсталятора через jpackage\n",[3273,6371,6373,6375,6377,6379],{"class":3275,"line":6372},61,[3273,6374,5965],{"class":3331},[3273,6376,5541],{"class":3283},[3273,6378,5926],{"class":3331},[3273,6380,6381],{"class":3646},"Package installer (Windows)\n",[3273,6383,6385,6387,6389],{"class":3275,"line":6384},62,[3273,6386,6172],{"class":3283},[3273,6388,5926],{"class":3331},[3273,6390,6177],{"class":3646},[3273,6392,6394,6396,6398],{"class":3275,"line":6393},63,[3273,6395,6343],{"class":3283},[3273,6397,5926],{"class":3331},[3273,6399,6400],{"class":3646},"pwsh\n",[3273,6402,6404,6406,6408],{"class":3275,"line":6403},64,[3273,6405,6182],{"class":3283},[3273,6407,5926],{"class":3331},[3273,6409,6188],{"class":6187},[3273,6411,6413],{"class":3275,"line":6412},65,[3273,6414,6415],{"class":3646},"          jpackage `\n",[3273,6417,6419],{"class":3275,"line":6418},66,[3273,6420,6421],{"class":3646},"            --type msi `\n",[3273,6423,6425],{"class":3275,"line":6424},67,[3273,6426,6427],{"class":3646},"            --name \"Audiobook Platform\" `\n",[3273,6429,6431],{"class":3275,"line":6430},68,[3273,6432,6433],{"class":3646},"            --app-version \"${{ steps.version.outputs.VERSION }}\" `\n",[3273,6435,6437],{"class":3275,"line":6436},69,[3273,6438,6439],{"class":3646},"            --vendor \"Kostyl Dev\" `\n",[3273,6441,6443],{"class":3275,"line":6442},70,[3273,6444,6445],{"class":3646},"            --input jpackage-input\u002F `\n",[3273,6447,6449],{"class":3275,"line":6448},71,[3273,6450,6451],{"class":3646},"            --main-jar audiobook-app-fat.jar `\n",[3273,6453,6455],{"class":3275,"line":6454},72,[3273,6456,6457],{"class":3646},"            --main-class dev.kostyl.audiobook.Launcher `\n",[3273,6459,6461],{"class":3275,"line":6460},73,[3273,6462,6463],{"class":3646},"            --icon packaging\u002Fwindows\u002Faudiobook.ico `\n",[3273,6465,6467],{"class":3275,"line":6466},74,[3273,6468,6469],{"class":3646},"            --dest dist\u002F `\n",[3273,6471,6473],{"class":3275,"line":6472},75,[3273,6474,6475],{"class":3646},"            --win-dir-chooser `\n",[3273,6477,6479],{"class":3275,"line":6478},76,[3273,6480,6481],{"class":3646},"            --win-menu `\n",[3273,6483,6485],{"class":3275,"line":6484},77,[3273,6486,6487],{"class":3646},"            --win-shortcut\n",[3273,6489,6491],{"class":3275,"line":6490},78,[3273,6492,3452],{"emptyLinePlaceholder":3451},[3273,6494,6496,6498,6500,6502],{"class":3275,"line":6495},79,[3273,6497,5965],{"class":3331},[3273,6499,5541],{"class":3283},[3273,6501,5926],{"class":3331},[3273,6503,6504],{"class":3646},"Package installer (macOS)\n",[3273,6506,6508,6510,6512],{"class":3275,"line":6507},80,[3273,6509,6172],{"class":3283},[3273,6511,5926],{"class":3331},[3273,6513,6514],{"class":3646},"matrix.os == 'macos-latest'\n",[3273,6516,6518,6520,6522],{"class":3275,"line":6517},81,[3273,6519,6182],{"class":3283},[3273,6521,5926],{"class":3331},[3273,6523,6188],{"class":6187},[3273,6525,6527],{"class":3275,"line":6526},82,[3273,6528,6529],{"class":3646},"          jpackage \\\n",[3273,6531,6533],{"class":3275,"line":6532},83,[3273,6534,6535],{"class":3646},"            --type dmg \\\n",[3273,6537,6539],{"class":3275,"line":6538},84,[3273,6540,6541],{"class":3646},"            --name \"Audiobook Platform\" \\\n",[3273,6543,6545],{"class":3275,"line":6544},85,[3273,6546,6547],{"class":3646},"            --app-version \"${{ steps.version.outputs.VERSION }}\" \\\n",[3273,6549,6551],{"class":3275,"line":6550},86,[3273,6552,6553],{"class":3646},"            --vendor \"Kostyl Dev\" \\\n",[3273,6555,6557],{"class":3275,"line":6556},87,[3273,6558,6559],{"class":3646},"            --input jpackage-input\u002F \\\n",[3273,6561,6563],{"class":3275,"line":6562},88,[3273,6564,6565],{"class":3646},"            --main-jar audiobook-app-fat.jar \\\n",[3273,6567,6569],{"class":3275,"line":6568},89,[3273,6570,6571],{"class":3646},"            --main-class dev.kostyl.audiobook.Launcher \\\n",[3273,6573,6575],{"class":3275,"line":6574},90,[3273,6576,6577],{"class":3646},"            --icon packaging\u002Fmacos\u002Faudiobook.icns \\\n",[3273,6579,6581],{"class":3275,"line":6580},91,[3273,6582,6583],{"class":3646},"            --dest dist\u002F\n",[3273,6585,6587],{"class":3275,"line":6586},92,[3273,6588,3452],{"emptyLinePlaceholder":3451},[3273,6590,6592,6594,6596,6598],{"class":3275,"line":6591},93,[3273,6593,5965],{"class":3331},[3273,6595,5541],{"class":3283},[3273,6597,5926],{"class":3331},[3273,6599,6600],{"class":3646},"Package installer (Linux DEB & RPM)\n",[3273,6602,6604,6606,6608],{"class":3275,"line":6603},94,[3273,6605,6172],{"class":3283},[3273,6607,5926],{"class":3331},[3273,6609,6222],{"class":3646},[3273,6611,6613,6615,6617],{"class":3275,"line":6612},95,[3273,6614,6182],{"class":3283},[3273,6616,5926],{"class":3331},[3273,6618,6188],{"class":6187},[3273,6620,6622],{"class":3275,"line":6621},96,[3273,6623,6624],{"class":3646},"          # Створення DEB-пакета для Debian\u002FUbuntu\n",[3273,6626,6628],{"class":3275,"line":6627},97,[3273,6629,6529],{"class":3646},[3273,6631,6633],{"class":3275,"line":6632},98,[3273,6634,6635],{"class":3646},"            --type deb \\\n",[3273,6637,6639],{"class":3275,"line":6638},99,[3273,6640,6641],{"class":3646},"            --name \"audiobook-platform\" \\\n",[3273,6643,6645],{"class":3275,"line":6644},100,[3273,6646,6547],{"class":3646},[3273,6648,6650],{"class":3275,"line":6649},101,[3273,6651,6553],{"class":3646},[3273,6653,6655],{"class":3275,"line":6654},102,[3273,6656,6559],{"class":3646},[3273,6658,6660],{"class":3275,"line":6659},103,[3273,6661,6565],{"class":3646},[3273,6663,6665],{"class":3275,"line":6664},104,[3273,6666,6571],{"class":3646},[3273,6668,6670],{"class":3275,"line":6669},105,[3273,6671,6672],{"class":3646},"            --icon packaging\u002Flinux\u002Faudiobook.png \\\n",[3273,6674,6676],{"class":3275,"line":6675},106,[3273,6677,6678],{"class":3646},"            --dest dist\u002F \\\n",[3273,6680,6682],{"class":3275,"line":6681},107,[3273,6683,6684],{"class":3646},"            --linux-shortcut\n",[3273,6686,6688],{"class":3275,"line":6687},108,[3273,6689,3452],{"emptyLinePlaceholder":3451},[3273,6691,6693],{"class":3275,"line":6692},109,[3273,6694,6695],{"class":3646},"          # Створення RPM-пакета для RedHat\u002FFedora\u002FCentOS\n",[3273,6697,6699],{"class":3275,"line":6698},110,[3273,6700,6529],{"class":3646},[3273,6702,6704],{"class":3275,"line":6703},111,[3273,6705,6706],{"class":3646},"            --type rpm \\\n",[3273,6708,6710],{"class":3275,"line":6709},112,[3273,6711,6641],{"class":3646},[3273,6713,6715],{"class":3275,"line":6714},113,[3273,6716,6547],{"class":3646},[3273,6718,6720],{"class":3275,"line":6719},114,[3273,6721,6553],{"class":3646},[3273,6723,6725],{"class":3275,"line":6724},115,[3273,6726,6559],{"class":3646},[3273,6728,6730],{"class":3275,"line":6729},116,[3273,6731,6565],{"class":3646},[3273,6733,6735],{"class":3275,"line":6734},117,[3273,6736,6571],{"class":3646},[3273,6738,6740],{"class":3275,"line":6739},118,[3273,6741,6672],{"class":3646},[3273,6743,6745],{"class":3275,"line":6744},119,[3273,6746,6678],{"class":3646},[3273,6748,6750],{"class":3275,"line":6749},120,[3273,6751,6684],{"class":3646},[3273,6753,6755],{"class":3275,"line":6754},121,[3273,6756,3452],{"emptyLinePlaceholder":3451},[3273,6758,6760],{"class":3275,"line":6759},122,[3273,6761,6762],{"class":3646},"          # Копіювання Fat JAR у директорію dist, щоб він також потрапив у реліз\n",[3273,6764,6766],{"class":3275,"line":6765},123,[3273,6767,6768],{"class":3646},"          cp target\u002Faudiobook-app-fat.jar dist\u002F\n",[3273,6770,6772],{"class":3275,"line":6771},124,[3273,6773,3452],{"emptyLinePlaceholder":3451},[3273,6775,6777],{"class":3275,"line":6776},125,[3273,6778,6779],{"class":3304},"      # 9. Збереження артефактів для наступного завдання\n",[3273,6781,6783,6785,6787,6789],{"class":3275,"line":6782},126,[3273,6784,5965],{"class":3331},[3273,6786,5541],{"class":3283},[3273,6788,5926],{"class":3331},[3273,6790,6791],{"class":3646},"Upload installer artifact\n",[3273,6793,6795,6797,6799],{"class":3275,"line":6794},127,[3273,6796,6076],{"class":3283},[3273,6798,5926],{"class":3331},[3273,6800,6801],{"class":3646},"actions\u002Fupload-artifact@v4\n",[3273,6803,6805,6807],{"class":3275,"line":6804},128,[3273,6806,6115],{"class":3283},[3273,6808,5946],{"class":3331},[3273,6810,6812,6815,6817],{"class":3275,"line":6811},129,[3273,6813,6814],{"class":3283},"          name",[3273,6816,5926],{"class":3331},[3273,6818,6819],{"class":3646},"installer-${{ matrix.os }}\n",[3273,6821,6823,6826,6828],{"class":3275,"line":6822},130,[3273,6824,6825],{"class":3283},"          path",[3273,6827,5926],{"class":3331},[3273,6829,6830],{"class":3646},"dist\u002F\n",[3273,6832,6834,6837,6839],{"class":3275,"line":6833},131,[3273,6835,6836],{"class":3283},"          retention-days",[3273,6838,5926],{"class":3331},[3273,6840,6842],{"class":6841},"sJj4R","1\n",[3273,6844,6846],{"class":3275,"line":6845},132,[3273,6847,3452],{"emptyLinePlaceholder":3451},[3273,6849,6851],{"class":3275,"line":6850},133,[3273,6852,6853],{"class":3304},"  # Окреме завдання: публікація GitHub Release\n",[3273,6855,6857,6860],{"class":3275,"line":6856},134,[3273,6858,6859],{"class":3283},"  publish-release",[3273,6861,5946],{"class":3331},[3273,6863,6865,6868,6870],{"class":3275,"line":6864},135,[3273,6866,6867],{"class":3283},"    needs",[3273,6869,5926],{"class":3331},[3273,6871,6872],{"class":3646},"build-installers\n",[3273,6874,6876,6878,6880],{"class":3275,"line":6875},136,[3273,6877,6039],{"class":3283},[3273,6879,5926],{"class":3331},[3273,6881,6882],{"class":3646},"ubuntu-latest\n",[3273,6884,6886,6889],{"class":3275,"line":6885},137,[3273,6887,6888],{"class":3283},"    permissions",[3273,6890,5946],{"class":3331},[3273,6892,6894,6897,6899],{"class":3275,"line":6893},138,[3273,6895,6896],{"class":3283},"      contents",[3273,6898,5926],{"class":3331},[3273,6900,6901],{"class":3646},"write\n",[3273,6903,6905],{"class":3275,"line":6904},139,[3273,6906,3452],{"emptyLinePlaceholder":3451},[3273,6908,6910,6912],{"class":3275,"line":6909},140,[3273,6911,6053],{"class":3283},[3273,6913,5946],{"class":3331},[3273,6915,6917,6919,6921,6923],{"class":3275,"line":6916},141,[3273,6918,5965],{"class":3331},[3273,6920,5541],{"class":3283},[3273,6922,5926],{"class":3331},[3273,6924,6925],{"class":3646},"Download all installer artifacts\n",[3273,6927,6929,6931,6933],{"class":3275,"line":6928},142,[3273,6930,6076],{"class":3283},[3273,6932,5926],{"class":3331},[3273,6934,6935],{"class":3646},"actions\u002Fdownload-artifact@v4\n",[3273,6937,6939,6941],{"class":3275,"line":6938},143,[3273,6940,6115],{"class":3283},[3273,6942,5946],{"class":3331},[3273,6944,6946,6948,6950],{"class":3275,"line":6945},144,[3273,6947,6825],{"class":3283},[3273,6949,5926],{"class":3331},[3273,6951,6952],{"class":3646},"installers\u002F\n",[3273,6954,6956,6959,6961],{"class":3275,"line":6955},145,[3273,6957,6958],{"class":3283},"          merge-multiple",[3273,6960,5926],{"class":3331},[3273,6962,6963],{"class":3989},"true\n",[3273,6965,6967],{"class":3275,"line":6966},146,[3273,6968,3452],{"emptyLinePlaceholder":3451},[3273,6970,6972,6974,6976,6978],{"class":3275,"line":6971},147,[3273,6973,5965],{"class":3331},[3273,6975,5541],{"class":3283},[3273,6977,5926],{"class":3331},[3273,6979,6980],{"class":3646},"Create GitHub Release\n",[3273,6982,6984,6986,6988],{"class":3275,"line":6983},148,[3273,6985,6076],{"class":3283},[3273,6987,5926],{"class":3331},[3273,6989,6990],{"class":3646},"softprops\u002Faction-gh-release@v2\n",[3273,6992,6994,6996],{"class":3275,"line":6993},149,[3273,6995,6115],{"class":3283},[3273,6997,5946],{"class":3331},[3273,6999,7001,7003,7005],{"class":3275,"line":7000},150,[3273,7002,6814],{"class":3283},[3273,7004,5926],{"class":3331},[3273,7006,7007],{"class":4124},"\"Audiobook Platform ${{ github.ref_name }}\"\n",[3273,7009,7011,7014,7016],{"class":3275,"line":7010},151,[3273,7012,7013],{"class":3283},"          body",[3273,7015,5926],{"class":3331},[3273,7017,6188],{"class":6187},[3273,7019,7021],{"class":3275,"line":7020},152,[3273,7022,7023],{"class":3646},"            ## Що нового у ${{ github.ref_name }}\n",[3273,7025,7027],{"class":3275,"line":7026},153,[3273,7028,3452],{"emptyLinePlaceholder":3451},[3273,7030,7032],{"class":3275,"line":7031},154,[3273,7033,7034],{"class":3646},"            Опис змін цього релізу.\n",[3273,7036,7038],{"class":3275,"line":7037},155,[3273,7039,3452],{"emptyLinePlaceholder":3451},[3273,7041,7043],{"class":3275,"line":7042},156,[3273,7044,7045],{"class":3646},"            ## Завантаження\n",[3273,7047,7049],{"class":3275,"line":7048},157,[3273,7050,3452],{"emptyLinePlaceholder":3451},[3273,7052,7054],{"class":3275,"line":7053},158,[3273,7055,7056],{"class":3646},"            | Операційна система \u002F Платформа | Файл |\n",[3273,7058,7060],{"class":3275,"line":7059},159,[3273,7061,7062],{"class":3646},"            |---|---|\n",[3273,7064,7066],{"class":3275,"line":7065},160,[3273,7067,7068],{"class":3646},"            | Windows 10\u002F11 | `*.msi` |\n",[3273,7070,7072],{"class":3275,"line":7071},161,[3273,7073,7074],{"class":3646},"            | macOS 12+ | `*.dmg` |\n",[3273,7076,7078],{"class":3275,"line":7077},162,[3273,7079,7080],{"class":3646},"            | Ubuntu\u002FDebian | `*.deb` |\n",[3273,7082,7084],{"class":3275,"line":7083},163,[3273,7085,7086],{"class":3646},"            | RedHat\u002FFedora | `*.rpm` |\n",[3273,7088,7090],{"class":3275,"line":7089},164,[3273,7091,7092],{"class":3646},"            | Будь-яка (з встановленою JRE) | `*.jar` |\n",[3273,7094,7096,7099,7101],{"class":3275,"line":7095},165,[3273,7097,7098],{"class":3283},"          files",[3273,7100,5926],{"class":3331},[3273,7102,7103],{"class":3646},"installers\u002F**\n",[3273,7105,7107,7110,7112],{"class":3275,"line":7106},166,[3273,7108,7109],{"class":3283},"          draft",[3273,7111,5926],{"class":3331},[3273,7113,7114],{"class":3989},"false\n",[3273,7116,7118,7121,7123],{"class":3275,"line":7117},167,[3273,7119,7120],{"class":3283},"          prerelease",[3273,7122,5926],{"class":3331},[3273,7124,7114],{"class":3989},[3208,7126],{},[3145,7128,7130],{"id":7129},"частина-iv-публікація-у-github-releases","Частина IV. Публікація у GitHub Releases",[3215,7132,7134],{"id":7133},"принцип-github-releases","Принцип GitHub Releases",[3150,7136,7137,7140,7141,7144],{},[3154,7138,7139],{},"GitHub Releases"," — це механізм GitHub для публікації версіонованих випусків програмного забезпечення. Кожен реліз прив'язується до конкретного ",[3154,7142,7143],{},"git-тегу"," та може містити довільну кількість файлів-артефактів: інсталяторів, архівів із вихідним кодом, документації.",[3150,7146,7147],{},"На відміну від звичайного коміту, реліз має:",[7149,7150,7151,7162,7168],"ul",{},[7152,7153,7154,7157,7158,7161],"li",{},[3154,7155,7156],{},"Версійний тег"," (наприклад, ",[3171,7159,7160],{},"v1.0.0",") — незмінний покажчик у git-історії.",[7152,7163,7164,7167],{},[3154,7165,7166],{},"Назву та опис"," — що змінилося, які нові можливості з'явилися, які помилки виправлено.",[7152,7169,7170,7173],{},[3154,7171,7172],{},"Бінарні файли"," — безпосередньо файли для завантаження кінцевими користувачами.",[3215,7175,7177],{"id":7176},"публікація-релізу-вручну-через-git-і-github-cli","Публікація релізу вручну через git і GitHub CLI",[3150,7179,7180],{},"Якщо ви не використовуєте GitHub Actions, реліз можна опублікувати в кілька кроків.",[3150,7182,7183,7186,7187,4186],{},[3154,7184,7185],{},"Крок 1."," Переконайтеся, що всі зміни закоміченні та ви знаходитесь на гілці ",[3171,7188,4077],{},[3263,7190,7192],{"className":4107,"code":7191,"language":4109,"meta":3269,"style":3269},"git status\n# → On branch main, nothing to commit, working tree clean\n\ngit log --oneline -3\n# → a1b2c3d Фінальна версія платформи аудіокниг\n# → 9f8e7d6 Виправлення валідації форм\n# → 5c4b3a2 Інтеграція AtlantaFX\n",[3171,7193,7194,7202,7207,7211,7224,7229,7234],{"__ignoreMap":3269},[3273,7195,7196,7199],{"class":3275,"line":3276},[3273,7197,7198],{"class":4050},"git",[3273,7200,7201],{"class":4124}," status\n",[3273,7203,7204],{"class":3275,"line":3290},[3273,7205,7206],{"class":3304},"# → On branch main, nothing to commit, working tree clean\n",[3273,7208,7209],{"class":3275,"line":3301},[3273,7210,3452],{"emptyLinePlaceholder":3451},[3273,7212,7213,7215,7218,7221],{"class":3275,"line":3308},[3273,7214,7198],{"class":4050},[3273,7216,7217],{"class":4124}," log",[3273,7219,7220],{"class":3989}," --oneline",[3273,7222,7223],{"class":3989}," -3\n",[3273,7225,7226],{"class":3275,"line":3319},[3273,7227,7228],{"class":3304},"# → a1b2c3d Фінальна версія платформи аудіокниг\n",[3273,7230,7231],{"class":3275,"line":3342},[3273,7232,7233],{"class":3304},"# → 9f8e7d6 Виправлення валідації форм\n",[3273,7235,7236],{"class":3275,"line":3361},[3273,7237,7238],{"class":3304},"# → 5c4b3a2 Інтеграція AtlantaFX\n",[3150,7240,7241,7244],{},[3154,7242,7243],{},"Крок 2."," Створіть анотований тег для нового релізу:",[3263,7246,7248],{"className":4107,"code":7247,"language":4109,"meta":3269,"style":3269},"# Синтаксис: git tag -a \u003Cтег> -m \"\u003Cповідомлення>\"\ngit tag -a v1.0.0 -m \"Перший стабільний реліз Audiobook Platform\"\n\n# Перевірка: переглянути всі теги\ngit tag -l\n# → v1.0.0\n\n# Переглянути деталі тегу\ngit show v1.0.0\n",[3171,7249,7250,7255,7274,7278,7283,7292,7297,7301,7306],{"__ignoreMap":3269},[3273,7251,7252],{"class":3275,"line":3276},[3273,7253,7254],{"class":3304},"# Синтаксис: git tag -a \u003Cтег> -m \"\u003Cповідомлення>\"\n",[3273,7256,7257,7259,7262,7265,7268,7271],{"class":3275,"line":3290},[3273,7258,7198],{"class":4050},[3273,7260,7261],{"class":4124}," tag",[3273,7263,7264],{"class":3989}," -a",[3273,7266,7267],{"class":4124}," v1.0.0",[3273,7269,7270],{"class":3989}," -m",[3273,7272,7273],{"class":4124}," \"Перший стабільний реліз Audiobook Platform\"\n",[3273,7275,7276],{"class":3275,"line":3301},[3273,7277,3452],{"emptyLinePlaceholder":3451},[3273,7279,7280],{"class":3275,"line":3308},[3273,7281,7282],{"class":3304},"# Перевірка: переглянути всі теги\n",[3273,7284,7285,7287,7289],{"class":3275,"line":3319},[3273,7286,7198],{"class":4050},[3273,7288,7261],{"class":4124},[3273,7290,7291],{"class":3989}," -l\n",[3273,7293,7294],{"class":3275,"line":3342},[3273,7295,7296],{"class":3304},"# → v1.0.0\n",[3273,7298,7299],{"class":3275,"line":3361},[3273,7300,3452],{"emptyLinePlaceholder":3451},[3273,7302,7303],{"class":3275,"line":3380},[3273,7304,7305],{"class":3304},"# Переглянути деталі тегу\n",[3273,7307,7308,7310,7313],{"class":3275,"line":3390},[3273,7309,7198],{"class":4050},[3273,7311,7312],{"class":4124}," show",[3273,7314,7315],{"class":4124}," v1.0.0\n",[3238,7317,7318,4442,7321,7324,7325,7328,7329,7332,7333,7336,7337,7340],{},[3154,7319,7320],{},"Різниця між легким та анотованим тегом.",[3171,7322,7323],{},"git tag v1.0.0"," (без ",[3171,7326,7327],{},"-a",") створює ",[3154,7330,7331],{},"легкий тег"," — простий покажчик на коміт. ",[3171,7334,7335],{},"git tag -a v1.0.0 -m \"...\""," створює ",[3154,7338,7339],{},"анотований тег"," — окремий git-об'єкт із автором, датою та повідомленням. Для релізів завжди слід використовувати анотовані теги: вони несуть більше семантики та краще відображаються в інтерфейсі GitHub.",[3150,7342,7343,7346],{},[3154,7344,7345],{},"Крок 3."," Запушіть тег до віддаленого репозиторію:",[3263,7348,7350],{"className":4107,"code":7349,"language":4109,"meta":3269,"style":3269},"# Пуш конкретного тегу\ngit push origin v1.0.0\n\n# АБО пуш усіх локальних тегів одночасно\ngit push origin --tags\n",[3171,7351,7352,7357,7369,7373,7378],{"__ignoreMap":3269},[3273,7353,7354],{"class":3275,"line":3276},[3273,7355,7356],{"class":3304},"# Пуш конкретного тегу\n",[3273,7358,7359,7361,7364,7367],{"class":3275,"line":3290},[3273,7360,7198],{"class":4050},[3273,7362,7363],{"class":4124}," push",[3273,7365,7366],{"class":4124}," origin",[3273,7368,7315],{"class":4124},[3273,7370,7371],{"class":3275,"line":3301},[3273,7372,3452],{"emptyLinePlaceholder":3451},[3273,7374,7375],{"class":3275,"line":3308},[3273,7376,7377],{"class":3304},"# АБО пуш усіх локальних тегів одночасно\n",[3273,7379,7380,7382,7384,7386],{"class":3275,"line":3319},[3273,7381,7198],{"class":4050},[3273,7383,7363],{"class":4124},[3273,7385,7366],{"class":4124},[3273,7387,7388],{"class":3989}," --tags\n",[4945,7390,7392,7403,7410,7417,7424,7431,7438],{"title":7391},"git push — tag",[4949,7393,7395,4442,7399],{"className":7394},[3275],[3273,7396,7398],{"className":7397},[4955],"$",[3154,7400,7402],{"className":7401},[4960],"git push origin v1.0.0",[4949,7404,7406],{"className":7405},[3275],[3273,7407,7409],{"className":7408},[4977],"Enumerating objects: 1, done.",[4949,7411,7413],{"className":7412},[3275],[3273,7414,7416],{"className":7415},[4977],"Counting objects: 100% (1\u002F1), done.",[4949,7418,7420],{"className":7419},[3275],[3273,7421,7423],{"className":7422},[4977],"Writing objects: 100% (1\u002F1), 190 bytes | 190.00 KiB\u002Fs, done.",[4949,7425,7427],{"className":7426},[3275],[3273,7428,7430],{"className":7429},[4977],"Total 1 (delta 0), reused 0 (delta 0), pack-reused 0",[4949,7432,7434],{"className":7433},[3275],[3273,7435,7437],{"className":7436},[4968],"To https:\u002F\u002Fgithub.com\u002Farakviel\u002Faudiobook-platform.git",[4949,7439,7441,7442],{"className":7440},[3275]," * [new tag]         ",[3273,7443,7445],{"className":7444},[4985,4960],"v1.0.0 → v1.0.0",[3150,7447,7448,7451,7452,7455,7456,4186],{},[3154,7449,7450],{},"Крок 4."," Після пуші тегу, якщо ви налаштували GitHub Actions із файлом ",[3171,7453,7454],{},"release.yml",", workflow запуститься автоматично. Якщо ж публікуєте вручну — використайте ",[3154,7457,7458],{},"GitHub CLI",[3263,7460,7462],{"className":4107,"code":7461,"language":4109,"meta":3269,"style":3269},"# Встановлення GitHub CLI (якщо ще не встановлено)\n# macOS: brew install gh\n# Windows: choco install gh\n# Linux: sudo apt install gh\n\n# Автентифікація\ngh auth login\n\n# Публікація релізу з файлами\ngh release create v1.0.0 \\\n  dist\u002F*.msi \\\n  dist\u002F*.dmg \\\n  dist\u002F*.deb \\\n  --title \"Audiobook Platform v1.0.0\" \\\n  --notes \"## Перший реліз\n\nПлатформа для управління та прослуховування аудіокниг.\n\n### Що включено\n- Повний CRUD для аудіокниг\n- MVVM-архітектура з Guice\n- Сучасний інтерфейс на AtlantaFX\n- Інтеграція з H2 базою даних\"\n",[3171,7463,7464,7469,7474,7479,7484,7488,7493,7504,7508,7513,7527,7539,7549,7559,7569,7577,7581,7586,7590,7595,7600,7605,7610],{"__ignoreMap":3269},[3273,7465,7466],{"class":3275,"line":3276},[3273,7467,7468],{"class":3304},"# Встановлення GitHub CLI (якщо ще не встановлено)\n",[3273,7470,7471],{"class":3275,"line":3290},[3273,7472,7473],{"class":3304},"# macOS: brew install gh\n",[3273,7475,7476],{"class":3275,"line":3301},[3273,7477,7478],{"class":3304},"# Windows: choco install gh\n",[3273,7480,7481],{"class":3275,"line":3308},[3273,7482,7483],{"class":3304},"# Linux: sudo apt install gh\n",[3273,7485,7486],{"class":3275,"line":3319},[3273,7487,3452],{"emptyLinePlaceholder":3451},[3273,7489,7490],{"class":3275,"line":3342},[3273,7491,7492],{"class":3304},"# Автентифікація\n",[3273,7494,7495,7498,7501],{"class":3275,"line":3361},[3273,7496,7497],{"class":4050},"gh",[3273,7499,7500],{"class":4124}," auth",[3273,7502,7503],{"class":4124}," login\n",[3273,7505,7506],{"class":3275,"line":3380},[3273,7507,3452],{"emptyLinePlaceholder":3451},[3273,7509,7510],{"class":3275,"line":3390},[3273,7511,7512],{"class":3304},"# Публікація релізу з файлами\n",[3273,7514,7515,7517,7520,7523,7525],{"class":3275,"line":3410},[3273,7516,7497],{"class":4050},[3273,7518,7519],{"class":4124}," release",[3273,7521,7522],{"class":4124}," create",[3273,7524,7267],{"class":4124},[3273,7526,5039],{"class":5038},[3273,7528,7529,7532,7535,7537],{"class":3275,"line":3428},[3273,7530,7531],{"class":4124},"  dist\u002F",[3273,7533,7534],{"class":3989},"*",[3273,7536,4380],{"class":4124},[3273,7538,5039],{"class":5038},[3273,7540,7541,7543,7545,7547],{"class":3275,"line":3438},[3273,7542,7531],{"class":4124},[3273,7544,7534],{"class":3989},[3273,7546,4399],{"class":4124},[3273,7548,5039],{"class":5038},[3273,7550,7551,7553,7555,7557],{"class":3275,"line":3448},[3273,7552,7531],{"class":4124},[3273,7554,7534],{"class":3989},[3273,7556,4417],{"class":4124},[3273,7558,5039],{"class":5038},[3273,7560,7561,7564,7567],{"class":3275,"line":3455},[3273,7562,7563],{"class":3989},"  --title",[3273,7565,7566],{"class":4124}," \"Audiobook Platform v1.0.0\"",[3273,7568,5039],{"class":5038},[3273,7570,7571,7574],{"class":3275,"line":3461},[3273,7572,7573],{"class":3989},"  --notes",[3273,7575,7576],{"class":4124}," \"## Перший реліз\n",[3273,7578,7579],{"class":3275,"line":3470},[3273,7580,3452],{"emptyLinePlaceholder":3451},[3273,7582,7583],{"class":3275,"line":3487},[3273,7584,7585],{"class":4124},"Платформа для управління та прослуховування аудіокниг.\n",[3273,7587,7588],{"class":3275,"line":3504},[3273,7589,3452],{"emptyLinePlaceholder":3451},[3273,7591,7592],{"class":3275,"line":3522},[3273,7593,7594],{"class":4124},"### Що включено\n",[3273,7596,7597],{"class":3275,"line":3532},[3273,7598,7599],{"class":4124},"- Повний CRUD для аудіокниг\n",[3273,7601,7602],{"class":3275,"line":3542},[3273,7603,7604],{"class":4124},"- MVVM-архітектура з Guice\n",[3273,7606,7607],{"class":3275,"line":3562},[3273,7608,7609],{"class":4124},"- Сучасний інтерфейс на AtlantaFX\n",[3273,7611,7612],{"class":3275,"line":3572},[3273,7613,7614],{"class":4124},"- Інтеграція з H2 базою даних\"\n",[3150,7616,7617,7620],{},[3154,7618,7619],{},"Крок 5."," Переконайтеся, що реліз опублікований:",[3263,7622,7624],{"className":4107,"code":7623,"language":4109,"meta":3269,"style":3269},"# Перегляд усіх релізів у репозиторії\ngh release list\n\n# → TITLE                           TAG       PUBLISHED\n# → Audiobook Platform v1.0.0       v1.0.0    about 1 minute ago\n\n# Відкрити реліз у браузері\ngh release view v1.0.0 --web\n",[3171,7625,7626,7631,7640,7644,7649,7654,7658,7663],{"__ignoreMap":3269},[3273,7627,7628],{"class":3275,"line":3276},[3273,7629,7630],{"class":3304},"# Перегляд усіх релізів у репозиторії\n",[3273,7632,7633,7635,7637],{"class":3275,"line":3290},[3273,7634,7497],{"class":4050},[3273,7636,7519],{"class":4124},[3273,7638,7639],{"class":4124}," list\n",[3273,7641,7642],{"class":3275,"line":3301},[3273,7643,3452],{"emptyLinePlaceholder":3451},[3273,7645,7646],{"class":3275,"line":3308},[3273,7647,7648],{"class":3304},"# → TITLE                           TAG       PUBLISHED\n",[3273,7650,7651],{"class":3275,"line":3319},[3273,7652,7653],{"class":3304},"# → Audiobook Platform v1.0.0       v1.0.0    about 1 minute ago\n",[3273,7655,7656],{"class":3275,"line":3342},[3273,7657,3452],{"emptyLinePlaceholder":3451},[3273,7659,7660],{"class":3275,"line":3361},[3273,7661,7662],{"class":3304},"# Відкрити реліз у браузері\n",[3273,7664,7665,7667,7669,7672,7674],{"class":3275,"line":3380},[3273,7666,7497],{"class":4050},[3273,7668,7519],{"class":4124},[3273,7670,7671],{"class":4124}," view",[3273,7673,7267],{"class":4124},[3273,7675,7676],{"class":3989}," --web\n",[3215,7678,7680],{"id":7679},"semantic-versioning-угода-щодо-нумерації-версій","Semantic Versioning: угода щодо нумерації версій",[3150,7682,7683,7684,7687,7688,4186],{},"Щоб версії релізів несли змістовну інформацію для користувачів та інших розробників, дотримуйтеся стандарту ",[3154,7685,7686],{},"Semantic Versioning (SemVer)"," у форматі ",[3171,7689,7690],{},"MAJOR.MINOR.PATCH",[7692,7693,7694,7718,7736],"accordion",{},[7695,7696,7699,7706],"accordion-item",{"icon":7697,"label":7698},"i-lucide-circle-help","MAJOR — Ламаючі зміни",[3150,7700,7701,7702,7705],{},"Збільшується, коли вносяться ",[3154,7703,7704],{},"несумісні зміни API або поведінки"," програми. Наприклад: зміна формату бази даних, видалення функції, кардинальна зміна UI.",[3150,7707,7708,4442,7711,7714,7715,3250],{},[3154,7709,7710],{},"Приклад:",[3171,7712,7713],{},"v1.0.0 → v2.0.0"," — нова версія не читає базу даних від ",[3171,7716,7717],{},"v1.x.x",[7695,7719,7721,7728],{"icon":7697,"label":7720},"MINOR — Нові функції (зворотно сумісні)",[3150,7722,7723,7724,7727],{},"Збільшується при додаванні ",[3154,7725,7726],{},"нових можливостей",", які не порушують сумісність із попередніми версіями.",[3150,7729,7730,4442,7732,7735],{},[3154,7731,7710],{},[3171,7733,7734],{},"v1.0.0 → v1.1.0"," — додано нову вкладку «Статистика» без зміни наявної функціональності.",[7695,7737,7739,7746],{"icon":7697,"label":7738},"PATCH — Виправлення помилок",[3150,7740,7741,7742,7745],{},"Збільшується при ",[3154,7743,7744],{},"виправленні помилок"," без додавання нових функцій.",[3150,7747,7748,4442,7750,7753],{},[3154,7749,7710],{},[3171,7751,7752],{},"v1.1.0 → v1.1.1"," — виправлено падіння додатку при спробі відкрити порожній список.",[3208,7755],{},[3145,7757,7759],{"id":7758},"підсумок-повний-релізний-цикл","Підсумок: Повний релізний цикл",[3150,7761,7762],{},"Нижче наведено зведений огляд повного шляху від вихідного коду до рук користувача:",[4458,7764,7765,7769,7778,7782,7797,7801,7819,7823,7852,7856],{},[3215,7766,7768],{"id":7767},"розробка-та-коміти","Розробка та коміти",[3150,7770,7771,7772,7777],{},"Розробіть функціональність, покрийте тестами, закомітьте зміни. Дотримуйтесь конвенції ",[4656,7773,7776],{"href":7774,"rel":7775},"https:\u002F\u002Fwww.conventionalcommits.org\u002F",[4660],"Conventional Commits"," для структурованих повідомлень комітів.",[3215,7779,7781],{"id":7780},"оновлення-версії-у-pomxml","Оновлення версії у pom.xml",[3263,7783,7785],{"className":4107,"code":7784,"language":4109,"meta":3269,"style":3269},"mvn versions:set -DnewVersion=1.0.0\n",[3171,7786,7787],{"__ignoreMap":3269},[3273,7788,7789,7791,7794],{"class":3275,"line":3276},[3273,7790,4121],{"class":4050},[3273,7792,7793],{"class":4124}," versions:set",[3273,7795,7796],{"class":3989}," -DnewVersion=1.0.0\n",[3215,7798,7800],{"id":7799},"збірка-fat-jar","Збірка Fat JAR",[3263,7802,7804],{"className":4107,"code":7803,"language":4109,"meta":3269,"style":3269},"mvn clean package\n# → target\u002Faudiobook-app-fat.jar\n",[3171,7805,7806,7814],{"__ignoreMap":3269},[3273,7807,7808,7810,7812],{"class":3275,"line":3276},[3273,7809,4121],{"class":4050},[3273,7811,4125],{"class":4124},[3273,7813,4128],{"class":4124},[3273,7815,7816],{"class":3275,"line":3290},[3273,7817,7818],{"class":3304},"# → target\u002Faudiobook-app-fat.jar\n",[3215,7820,7822],{"id":7821},"генерація-нативного-інсталятора","Генерація нативного інсталятора",[3263,7824,7826],{"className":4107,"code":7825,"language":4109,"meta":3269,"style":3269},"# Запускається на відповідній платформі або через GitHub Actions\njpackage --type msi ... --dest dist\u002F\n",[3171,7827,7828,7833],{"__ignoreMap":3269},[3273,7829,7830],{"class":3275,"line":3276},[3273,7831,7832],{"class":3304},"# Запускається на відповідній платформі або через GitHub Actions\n",[3273,7834,7835,7837,7840,7843,7846,7849],{"class":3275,"line":3290},[3273,7836,3246],{"class":4050},[3273,7838,7839],{"class":3989}," --type",[3273,7841,7842],{"class":4124}," msi",[3273,7844,7845],{"class":4124}," ...",[3273,7847,7848],{"class":3989}," --dest",[3273,7850,7851],{"class":4124}," dist\u002F\n",[3215,7853,7855],{"id":7854},"тегування-та-публікація","Тегування та публікація",[3263,7857,7859],{"className":4107,"code":7858,"language":4109,"meta":3269,"style":3269},"git tag -a v1.0.0 -m \"Реліз v1.0.0\"\ngit push origin v1.0.0\n# GitHub Actions автоматично збирає інсталятори та публікує реліз\n",[3171,7860,7861,7876,7886],{"__ignoreMap":3269},[3273,7862,7863,7865,7867,7869,7871,7873],{"class":3275,"line":3276},[3273,7864,7198],{"class":4050},[3273,7866,7261],{"class":4124},[3273,7868,7264],{"class":3989},[3273,7870,7267],{"class":4124},[3273,7872,7270],{"class":3989},[3273,7874,7875],{"class":4124}," \"Реліз v1.0.0\"\n",[3273,7877,7878,7880,7882,7884],{"class":3275,"line":3290},[3273,7879,7198],{"class":4050},[3273,7881,7363],{"class":4124},[3273,7883,7366],{"class":4124},[3273,7885,7315],{"class":4124},[3273,7887,7888],{"class":3275,"line":3301},[3273,7889,7890],{"class":3304},"# GitHub Actions автоматично збирає інсталятори та публікує реліз\n",[3186,7892,7893,7914,7929],{},[3189,7894,7895,7903],{"icon":3191,"title":3223},[3150,7896,7897,7900,7901,3250],{},[3154,7898,7899],{},"Коли використовувати:"," Розгортання на серверах, передача між розробниками, як вхідний артефакт для ",[3171,7902,3246],{},[3150,7904,7905,4442,7908,3228,7911],{},[3154,7906,7907],{},"Команда:",[3171,7909,7910],{},"mvn clean package",[3171,7912,7913],{},".\u002Fgradlew shadowJar",[3189,7915,7917,7922],{"icon":7916,"title":3246},"i-heroicons-computer-desktop",[3150,7918,7919,7921],{},[3154,7920,7899],{}," Розповсюдження кінцевим користувачам, створення інсталяторів для всіх ОС.",[3150,7923,7924,4442,7926],{},[3154,7925,7907],{},[3171,7927,7928],{},"jpackage --type msi|dmg|deb ...",[3189,7930,7932,7937],{"icon":7931,"title":7139},"i-heroicons-cloud-arrow-up",[3150,7933,7934,7936],{},[3154,7935,7899],{}," Публічне розповсюдження, версіонування, централізоване сховище артефактів.",[3150,7938,7939,4442,7941],{},[3154,7940,7907],{},[3171,7942,7943],{},"git tag -a v1.0.0 && git push origin v1.0.0",[4437,7945,7946,7949,7950,7952],{},[3154,7947,7948],{},"Найпростіший старт."," Якщо ви лише починаєте знайомство з релізною інженерією, реалізуйте кроки послідовно: спочатку налаштуйте Fat JAR та переконайтеся, що він запускається на іншому комп'ютері. Потім додайте ",[3171,7951,3246],{}," для своєї поточної ОС. Нарешті, налаштуйте GitHub Actions для автоматизації збірки на всіх трьох платформах. Кожен крок є самодостатнім і надає цінність незалежно від наступних.",[7954,7955,7956],"style",{},"html pre.shiki code .s0P7L, html code.shiki .s0P7L{--shiki-light:#800000;--shiki-default:#808080;--shiki-dark:#808080}html pre.shiki code .sKtos, html code.shiki .sKtos{--shiki-light:#800000;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .spJ8K, html code.shiki .spJ8K{--shiki-light:#008000;--shiki-default:#6A9955;--shiki-dark:#6A9955}html pre.shiki code .sHH4Y, html code.shiki .sHH4Y{--shiki-light:#000000;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .sa4r_, html code.shiki .sa4r_{--shiki-light:#E50000;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .su9tN, html code.shiki .su9tN{--shiki-light:#0000FF;--shiki-default:#CE9178;--shiki-dark:#CE9178}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 .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 .s8Opu, html code.shiki .s8Opu{--shiki-light:#795E26;--shiki-default:#DCDCAA;--shiki-dark:#DCDCAA}html pre.shiki code .siwwj, html code.shiki .siwwj{--shiki-light:#001080;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sbdoH, html code.shiki .sbdoH{--shiki-light:#A31515;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .sjcCO, html code.shiki .sjcCO{--shiki-light:#EE0000;--shiki-default:#D7BA7D;--shiki-dark:#D7BA7D}html pre.shiki code .s8xlr, html code.shiki .s8xlr{--shiki-light:#AF00DB;--shiki-default:#C586C0;--shiki-dark:#C586C0}html pre.shiki code .sJj4R, html code.shiki .sJj4R{--shiki-light:#098658;--shiki-default:#B5CEA8;--shiki-dark:#B5CEA8}",{"title":3269,"searchDepth":3290,"depth":3290,"links":7958},[7959,7960,7964,7975,7979,7984],{"id":3147,"depth":3290,"text":3148},{"id":3212,"depth":3290,"text":3213,"children":7961},[7962,7963],{"id":3217,"depth":3301,"text":3218},{"id":3253,"depth":3301,"text":3254},{"id":4315,"depth":3290,"text":4316,"children":7965},[7966,7967,7968,7969,7970,7971,7972,7973,7974],{"id":4319,"depth":3301,"text":4320},{"id":4452,"depth":3301,"text":4453},{"id":4462,"depth":3301,"text":4463},{"id":4502,"depth":3301,"text":4503},{"id":4664,"depth":3301,"text":4665},{"id":4704,"depth":3301,"text":4705},{"id":4722,"depth":3301,"text":4723},{"id":5019,"depth":3301,"text":5020},{"id":5167,"depth":3301,"text":5168},{"id":5288,"depth":3290,"text":5289,"children":7976},[7977,7978],{"id":5292,"depth":3301,"text":5293},{"id":5901,"depth":3301,"text":5902},{"id":7129,"depth":3290,"text":7130,"children":7980},[7981,7982,7983],{"id":7133,"depth":3301,"text":7134},{"id":7176,"depth":3301,"text":7177},{"id":7679,"depth":3301,"text":7680},{"id":7758,"depth":3290,"text":7759,"children":7985},[7986,7987,7988,7989,7990],{"id":7767,"depth":3301,"text":7768},{"id":7780,"depth":3301,"text":7781},{"id":7799,"depth":3301,"text":7800},{"id":7821,"depth":3301,"text":7822},{"id":7854,"depth":3301,"text":7855},"Від вихідного коду до готового інсталятора: створення Fat JAR, використання jpackage для генерації нативних інсталяторів під Windows, macOS та Linux, публікація релізів у GitHub Releases.","md",null,{},{"title":2458,"description":7991},"WIiRIlanft3duc5YjKA6lYB4rIgHF5yTMCHuueaWz8g",[7998,8000],{"title":2454,"path":2455,"stem":2456,"description":7999,"children":-1},"Від стандартного Modena до сучасного дизайну: AtlantaFX як колекція готових тем (Primer, Nord, Cupertino, Dracula), додаткові контроли, CSS Variables, utility classes, інтеграція з MVVM-додатками.",{"title":2474,"path":2475,"stem":2476,"description":8001,"children":-1},"Історія розвитку баз даних, порівняння моделей зберігання даних та встановлення MS SQL Server",1778998323510]