{"id":30770445,"url":"https://github.com/dakirchik/simplepwa","last_synced_at":"2026-05-18T06:05:02.349Z","repository":{"id":294179791,"uuid":"981941158","full_name":"Dakirchik/simplePWA","owner":"Dakirchik","description":"Modern framework for creating adaptive, reactive Progressive Web Applications (PWA) with offline support. Built on Web Components with easy IndexedDB integration, responsive routing, and a reactive store for offline-first applications.","archived":false,"fork":false,"pushed_at":"2025-09-03T10:06:50.000Z","size":232,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-10T01:28:05.050Z","etag":null,"topics":["adaptive","cli","indexeddb","manifest","offline","offline-first","progressive-web-app","pwa","reactive","routing","store","web-components"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dakirchik.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-12T06:20:00.000Z","updated_at":"2025-09-04T12:29:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"4c2d0c0f-5770-4b70-9311-fcebda9868fe","html_url":"https://github.com/Dakirchik/simplePWA","commit_stats":null,"previous_names":["fominalexey/simplepwa","dakirchik/simplepwa"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Dakirchik/simplePWA","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dakirchik%2FsimplePWA","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dakirchik%2FsimplePWA/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dakirchik%2FsimplePWA/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dakirchik%2FsimplePWA/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dakirchik","download_url":"https://codeload.github.com/Dakirchik/simplePWA/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dakirchik%2FsimplePWA/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33167430,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T05:43:36.989Z","status":"ssl_error","status_checked_at":"2026-05-18T05:43:19.133Z","response_time":71,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adaptive","cli","indexeddb","manifest","offline","offline-first","progressive-web-app","pwa","reactive","routing","store","web-components"],"created_at":"2025-09-04T23:05:21.861Z","updated_at":"2026-05-18T06:05:02.313Z","avatar_url":"https://github.com/Dakirchik.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🚀 SimplePWA Framework\n\n# Description in English\n\n**SimplePWA** — It is a modern framework for creating adaptive, reactive web applications with offline mode support и PWA (Progressive Web Applications).\nThe framework is built on [Web Components](https://developer.mozilla.org/ru/docs/Web/Web_Components) and provides easy integration [IndexedDB](https://developer.mozilla.org/ru/docs/Web/API/IndexedDB_API) for `offline-first` applications.\n\n---\n\n## ✨ Main features\n\n| Feature | Description |\n|--------|----------|\n| 📱 Responsive Routing | Automatic detection of device type and loading of appropriate components |\n| 💾 Offline Support | Data synchronization and operation without internet connection |\n| 🔄 Reactive Store | Global state with subscriptions for changes |\n| 📦 Web Components | Encapsulation of styles and logic in custom elements |\n| 🚀 PWA out of the box | Service Worker, manifest, and tools for creating PWA applications |\n| 🛠️ CLI Tools | Rapid creation of new PWA projects |\n\n---\n\n## 📦 Installation\n\n```bash\nnpm install @dakir/simple-pwa\n# or\nyarn add @dakir/simple-pwa\n```\n\n---\n\n## 🧪 Quick Start\n\n```js\nimport { App } from '@dakir/simple-pwa';\n\n// Create an instance of the application\nconst app = App.create({\n  rootElement: '#app',\n  pwa: {\n    enabled: true,\n    serviceWorkerPath: '/service-worker.js'\n  }\n});\n\n// Launch the application\napp.start();\n```\n\n---\n\n## 🧭 Routing\n\nThe framework automatically detects the device type (mobile / desktop) and loads the corresponding components:\n\n```js\nconst routes = [\n  {\n    path: '/',\n    desktopComponent: DesktopHome,\n    mobileComponent: MobileHome\n  },\n  {\n    path: '/about',\n    desktopComponent: DesktopAbout,\n    mobileComponent: MobileAbout\n  }\n];\n\nconst app = new App({ routes });\n```\n\n---\n\n## 🧩 Components\n\nCreate responsive components by inheriting from the base class:\n\n```js\nimport { Component } from '@dakir/simple-pwa';\n\nclass CustomComponent extends Component {\n  render() {\n    if (this.shadowRoot) {\n      this.shadowRoot.innerHTML = `\n        \u003cstyle\u003e\n          :host { display: block; padding: 20px; }\n          h2 { color: #2c3e50; }\n        \u003c/style\u003e\n        \u003ch2\u003eMy component\u003c/h2\u003e\n        \u003cp\u003eCounter: ${this.state.count || 0}\u003c/p\u003e\n        \u003cbutton id=\"increment\"\u003e+\u003c/button\u003e\n      `;\n\n      this.shadowRoot.getElementById('increment')?.addEventListener('click', () =\u003e {\n        this.setState({ count: (this.state.count || 0) + 1 });\n      });\n    }\n  }\n}\n\ncustomElements.define('custom-component', CustomComponent);\n```\n\n---\n\n## 🗄️ Working with Store\n\nGlobal state with reactive updates:\n\n```js\nimport { Store } from '@dakir/simple-pwa';\n\n// Creating a global store\nconst appStore = new Store({\n  user: null,\n  theme: 'light',\n  counter: 0\n});\n\n// Updating state\nappStore.setState({ theme: 'dark' });\n\n// Subscribing to changes\nconst unsubscribe = appStore.subscribe(state =\u003e {\n  console.log('State updated:', state);\n});\n\n// Unsubscribe from updates\nunsubscribe();\n```\n\n---\n\n## 🔌 Offline-First with IndexedDB\n\nSimplePWA includes a powerful sync manager for working with data in offline mode:\n\n```js\nimport { App } from '@dakir/simple-pwa';\n\nconst app = App.create({\n  syncDataManagerOptions: {\n    dbName: 'my-app-db'\n  }\n});\n\n// Retrieving data from IndexedDB\nconst items = await app.getDBList();\n\n// Adding an item\nawait app.addDBItem({\n  id: '123',\n  type: 'task',\n  data: JSON.stringify({ title: 'Task', completed: false }),\n  lastModified: new Date().toISOString(),\n  lastSynced: new Date().toISOString()\n});\n\n// Synchronizing with the server when the connection is restored\napp.setupAutoSync({\n  tasks: () =\u003e fetch('/api/tasks').then(res =\u003e res.json()),\n  users: () =\u003e fetch('/api/users').then(res =\u003e res.json())\n}, {\n  onNetworkRestore: true,\n  interval: 5 * 60 * 1000  // Every 5 minutes\n});\n```\n\n---\n\n## 🛠️ Creating PWA via CLI\n\n```bash\nnpx create-pwa my-project\n```\n\nCLI will ask questions about the name, description, icons, and other parameters. Upon completion, you'll get a ready-to-use PWA project that you can launch immediately.\n\n### 🧑‍🔧 Generating a Service Worker\n\n```bash\nnpx create-sw\n```\n\nCLI will help set up caching strategies and handle offline states.\n\n---\n\n## 📘 API Reference\n\n### `App`\n\nThe `App` class encapsulates routing, global state, synchronization, and PWA operations.\n\n#### 🏁 Creating an Application\n\n```js\nimport { App } from '@dakir/simple-pwa';\n\nconst app = App.create({\n  rootElement: '#app', // or HTMLElement\n  routes: [ /* ... */ ],\n  pwa: { enabled: true },\n  syncDataManagerOptions: { dbName: 'my-db' }\n});\n```\n\n#### 🔧 Main Methods\n\n| Method | Description |\n|------|----------|\n| `start()` | Start the application |\n| `navigate(path)` | Navigate to a route |\n| `getDeviceType()` | Get current device type (`mobile` / `desktop`) |\n| `getState()` | Get store state object |\n| `setState(patch)` | Update store state |\n| `addEventListener()` | Add a global event handler |\n\n---\n\n### 🧲 Working with IndexedDB (SyncDataManager)\n\n| Method | Description |\n|------|----------|\n| `getDBList(...)` | Retrieve a list of objects from IndexedDB |\n| `getDBListByIndex(...)` | Retrieve a list by index |\n| `getDBItem(id)` | Retrieve an object by ID |\n| `getDBItemByIndex(...)` | Retrieve an object by a specific index |\n| `addDBItem(obj)` | Add an object |\n| `updateDBItem(obj)` | Update an object |\n| `deleteDBItem(id)` | Delete an object by ID |\n| `syncDBList(fetchMethod)` | Synchronize a list with the server |\n| `syncDBItem(fetchMethod)` | Synchronize a single object with the server |\n| `isSyncNeeded(lastSynced, [timeDelay])` | Check if re-synchronization is needed |\n| `deleteDB([nameDB])` | Delete a database |\n| `isOfflineMode()` | Check if the app is in offline mode |\n| `isSyncing()` | Check if synchronization is currently in progress |\n| `syncAllData(methods)` | Run synchronization of all collections (e.g., tasks and users simultaneously) |\n| `setupAutoSync(methods, options)` | Configure auto-sync on network restoration, by timer, or at startup |\n| `checkAndSync(id, method, [timeDelay])` | Check and synchronize data as needed |\n\n#### Example usage of synchronization methods\n\n```js\n// Retrieve all tasks\nconst tasks = await app.getDBList();\n\n// Add a new task\nawait app.addDBItem({ id: '1', type: 'task', ... });\n\n// Synchronize tasks with the server\nawait app.syncDBList(() =\u003e fetch('/api/tasks').then(r =\u003e r.json()));\n\n// Auto-sync when the network is restored\napp.setupAutoSync({\n  tasks: () =\u003e fetch('/api/tasks').then(r =\u003e r.json())\n});\n```\n\n---\n\n### 🧠 Store\n\nReactive global store for storing application state.\n\n```js\nimport { Store } from '@dakir/simple-pwa';\n\n// Create a store\nconst store = new Store({ theme: 'light', counter: 0 });\n\n// Subscribe to changes\nconst unsubscribe = store.subscribe(state =\u003e {\n  console.log('New state:', state);\n});\n\n// Update state\nstore.setState({ theme: 'dark' });\n\n// Unsubscribe\nunsubscribe();\n```\n\n---\n\n### 🧱 Components (Web Components)\n\nBase class `Component` and derived classes `DesktopComponent`, `MobileComponent`.\n\n```js\nimport { Component } from '@dakir/simple-pwa';\n\nclass MyCounter extends Component {\n  render() {\n    if (this.shadowRoot) {\n      this.shadowRoot.innerHTML = `\n        \u003cspan\u003eCount: ${this.state.count || 0}\u003c/span\u003e\n        \u003cbutton id=\"inc\"\u003e+\u003c/button\u003e\n      `;\n      this.shadowRoot.getElementById('inc')?.addEventListener('click', () =\u003e {\n        this.setState({ count: (this.state.count || 0) + 1 });\n      });\n    }\n  }\n}\n\ncustomElements.define('my-counter', MyCounter);\n```\n\n---\n\n### 🧭 Adaptive Routing\n\nUse mobile and desktop components for different devices:\n\n```js\nconst routes = [\n  {\n    path: '/',\n    desktopComponent: DesktopHome,\n    mobileComponent: MobileHome\n  }\n];\nconst app = new App({ routes });\n```\n\n---\n\n## 📜 License\n\nMIT\n\n---\n\n## 📬 Feedback and Support\n\nFound a bug or want to suggest an improvement?\nOpen an [issue](https://github.com/Dakirchik/simplePWA/issues) or [PR](https://github.com/Dakirchik/simplePWA/pulls)!\n\n\n---\n\n🚀 **SimplePWA — your fast path to production-ready PWA!**\n\n# Описание на русском\n\n**SimplePWA** — это современный фреймворк для создания адаптивных, реактивных веб-приложений с поддержкой оффлайн-режима и PWA (Progressive Web Applications).\nФреймворк построен на [Web Components](https://developer.mozilla.org/ru/docs/Web/Web_Components) и обеспечивает простую интеграцию [IndexedDB](https://developer.mozilla.org/ru/docs/Web/API/IndexedDB_API) для `offline-first` приложений.\n\n---\n\n## ✨ Основные возможности\n\n| Функция | Описание |\n|--------|----------|\n| 📱 Адаптивная маршрутизация | Автоматическое определение типа устройства и загрузка соответствующих компонентов |\n| 💾 Поддержка оффлайн-режима | Синхронизация данных и работа без подключения к интернету |\n| 🔄 Реактивный стор | Глобальное состояние с подписками на изменения |\n| 📦 Web Components | Инкапсуляция стилей и логики в пользовательские элементы |\n| 🚀 PWA из коробки | Service Worker, манифест и инструменты для создания PWA |\n| 🛠️ CLI-инструменты | Быстрое создание новых PWA проектов |\n\n---\n\n## 📦 Установка\n\n```bash\nnpm install @dakir/simple-pwa\n# или\nyarn add @dakir/simple-pwa\n```\n\n---\n\n## 🧪 Быстрый старт\n\n```js\nimport { App } from '@dakir/simple-pwa';\n\n// Создайте экземпляр приложения\nconst app = App.create({\n  rootElement: '#app',\n  pwa: {\n    enabled: true,\n    serviceWorkerPath: '/service-worker.js'\n  }\n});\n\n// Запустите приложение\napp.start();\n```\n\n---\n\n## 🧭 Маршрутизация\n\nФреймворк автоматически определяет тип устройства (мобильное / десктопное) и загружает соответствующие компоненты:\n\n```js\nconst routes = [\n  {\n    path: '/',\n    desktopComponent: DesktopHome,\n    mobileComponent: MobileHome\n  },\n  {\n    path: '/about',\n    desktopComponent: DesktopAbout,\n    mobileComponent: MobileAbout\n  }\n];\n\nconst app = new App({ routes });\n```\n\n---\n\n## 🧩 Компоненты\n\nСоздавайте адаптивные компоненты, наследуясь от базового класса:\n\n```js\nimport { Component } from '@dakir/simple-pwa';\n\nclass CustomComponent extends Component {\n  render() {\n    if (this.shadowRoot) {\n      this.shadowRoot.innerHTML = `\n        \u003cstyle\u003e\n          :host { display: block; padding: 20px; }\n          h2 { color: #2c3e50; }\n        \u003c/style\u003e\n        \u003ch2\u003eМой компонент\u003c/h2\u003e\n        \u003cp\u003eСчётчик: ${this.state.count || 0}\u003c/p\u003e\n        \u003cbutton id=\"increment\"\u003e+\u003c/button\u003e\n      `;\n\n      this.shadowRoot.getElementById('increment')?.addEventListener('click', () =\u003e {\n        this.setState({ count: (this.state.count || 0) + 1 });\n      });\n    }\n  }\n}\n\ncustomElements.define('custom-component', CustomComponent);\n```\n\n---\n\n## 🗄️ Работа с хранилищем (Store)\n\nГлобальное состояние с реактивными обновлениями:\n\n```js\nimport { Store } from '@dakir/simple-pwa';\n\n// Создание глобального хранилища\nconst appStore = new Store({\n  user: null,\n  theme: 'light',\n  counter: 0\n});\n\n// Обновление состояния\nappStore.setState({ theme: 'dark' });\n\n// Подписка на изменения\nconst unsubscribe = appStore.subscribe(state =\u003e {\n  console.log('Состояние обновлено:', state);\n});\n\n// Отписаться от обновлений\nunsubscribe();\n```\n\n---\n\n## 🔌 Offline-First с IndexedDB\n\nSimplePWA включает мощный менеджер синхронизации для работы с данными в оффлайн-режиме:\n\n```js\nimport { App } from '@dakir/simple-pwa';\n\nconst app = App.create({\n  syncDataManagerOptions: {\n    dbName: 'my-app-db'\n  }\n});\n\n// Получение данных из IndexedDB\nconst items = await app.getDBList();\n\n// Добавление элемента\nawait app.addDBItem({\n  id: '123',\n  type: 'task',\n  data: JSON.stringify({ title: 'Задача', completed: false }),\n  lastModified: new Date().toISOString(),\n  lastSynced: new Date().toISOString()\n});\n\n// Синхронизация с сервером при восстановлении соединения\napp.setupAutoSync({\n  tasks: () =\u003e fetch('/api/tasks').then(res =\u003e res.json()),\n  users: () =\u003e fetch('/api/users').then(res =\u003e res.json())\n}, {\n  onNetworkRestore: true,\n  interval: 5 * 60 * 1000  // Каждые 5 минут\n});\n```\n\n---\n\n## 🛠️ Создание PWA через CLI\n\n```bash\nnpx create-pwa my-project\n```\n\nCLI задаст вопросы о названии, описании, иконках и других параметрах. После завершения вы получите готовый PWA проект, который можно сразу запустить.\n\n### 🧑‍🔧 Генерация Service Worker\n\n```bash\nnpx create-sw\n```\n\nCLI поможет настроить стратегии кеширования и обработку оффлайн-состояния.\n\n---\n\n## 📘 API Reference\n\n### `App`\n\nКласс `App` инкапсулирует маршрутизацию, глобальное состояние, синхронизацию и работу с PWA.\n\n#### 🏁 Создание приложения\n\n```js\nimport { App } from '@dakir/simple-pwa';\n\nconst app = App.create({\n  rootElement: '#app', // или HTMLElement\n  routes: [ /* ... */ ],\n  pwa: { enabled: true },\n  syncDataManagerOptions: { dbName: 'my-db' }\n});\n```\n\n#### 🔧 Основные методы\n\n| Метод | Описание |\n|------|----------|\n| `start()` | Запустить приложение |\n| `navigate(path)` | Перейти по маршруту |\n| `getDeviceType()` | Получить текущий тип устройства (`mobile` / `desktop`) |\n| `getState()` | Получить объект состояния store |\n| `setState(patch)` | Обновить состояние store |\n| `addEventListener()` | Добавить глобальный обработчик событий |\n\n---\n\n### 🧲 Работа с IndexedDB (SyncDataManager)\n\n| Метод | Описание |\n|------|----------|\n| `getDBList(...)` | Получить список объектов из IndexedDB |\n| `getDBListByIndex(...)` | Получить список по индексу |\n| `getDBItem(id)` | Получить объект по ID |\n| `getDBItemByIndex(...)` | Получить объект по определённому индексу |\n| `addDBItem(obj)` | Добавить объект |\n| `updateDBItem(obj)` | Обновить объект |\n| `deleteDBItem(id)` | Удалить объект по ID |\n| `syncDBList(fetchMethod)` | Синхронизировать список с сервером |\n| `syncDBItem(fetchMethod)` | Синхронизировать один объект с сервером |\n| `isSyncNeeded(lastSynced, [timeDelay])` | Проверить, требуется ли повторная синхронизация |\n| `deleteDB([nameDB])` | Удалить базу данных |\n| `isOfflineMode()` | Проверить, в оффлайн-режиме ли работает приложение |\n| `isSyncing()` | Проверить, идёт ли сейчас синхронизация |\n| `syncAllData(methods)` | Запустить синхронизацию всех коллекций (например, задач и пользователей одновременно) |\n| `setupAutoSync(methods, options)` | Настроить автосинхронизацию при восстановлении сети, по таймеру, при старте |\n| `checkAndSync(id, method, [timeDelay])` | Проверить и синхронизировать данные по необходимости |\n\n#### Пример использования методов синхронизации\n\n```js\n// Получить все задачи\nconst tasks = await app.getDBList();\n\n// Добавить новую задачу\nawait app.addDBItem({ id: '1', type: 'task', ... });\n\n// Синхронизировать задачи с сервером\nawait app.syncDBList(() =\u003e fetch('/api/tasks').then(r =\u003e r.json()));\n\n// Автоматическая синхронизация при восстановлении сети\napp.setupAutoSync({\n  tasks: () =\u003e fetch('/api/tasks').then(r =\u003e r.json())\n});\n```\n\n---\n\n### 🧠 Store\n\nРеактивный глобальный стор для хранения состояния приложения.\n\n```js\nimport { Store } from '@dakir/simple-pwa';\n\n// Создать стор\nconst store = new Store({ theme: 'light', counter: 0 });\n\n// Подписка на изменения\nconst unsubscribe = store.subscribe(state =\u003e {\n  console.log('Новое состояние:', state);\n});\n\n// Обновить состояние\nstore.setState({ theme: 'dark' });\n\n// Отписка\nunsubscribe();\n```\n\n---\n\n### 🧱 Компоненты (Web Components)\n\nБазовый класс `Component` и производные `DesktopComponent`, `MobileComponent`.\n\n```js\nimport { Component } from '@dakir/simple-pwa';\n\nclass MyCounter extends Component {\n  render() {\n    if (this.shadowRoot) {\n      this.shadowRoot.innerHTML = `\n        \u003cspan\u003eCount: ${this.state.count || 0}\u003c/span\u003e\n        \u003cbutton id=\"inc\"\u003e+\u003c/button\u003e\n      `;\n      this.shadowRoot.getElementById('inc')?.addEventListener('click', () =\u003e {\n        this.setState({ count: (this.state.count || 0) + 1 });\n      });\n    }\n  }\n}\n\ncustomElements.define('my-counter', MyCounter);\n```\n\n---\n\n### 🧭 Адаптивная маршрутизация\n\nИспользуйте мобильные и десктопные компоненты для разных устройств:\n\n```js\nconst routes = [\n  {\n    path: '/',\n    desktopComponent: DesktopHome,\n    mobileComponent: MobileHome\n  }\n];\nconst app = new App({ routes });\n```\n\n---\n\n## 📜 Лицензия\n\nMIT\n\n---\n\n## 📬 Обратная связь и поддержка\n\nНашли баг или хотите предложить улучшение?\nОткрывайте [issue](https://github.com/Dakirchik/simplePWA/issues) или [PR](https://github.com/Dakirchik/simplePWA/pulls)!\n\n---\n\n🚀 **SimplePWA — ваш быстрый путь к production-ready PWA!**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdakirchik%2Fsimplepwa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdakirchik%2Fsimplepwa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdakirchik%2Fsimplepwa/lists"}