| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- class PouchDBService
- constructor: (options = {}) ->
- {
- @localDbName = 'braer_color_cache'
- @remoteDbUrl = 'http://localhost:5984/braer_color_shop'
- @userFilter = { userId: null }
- @appVersion = '1.0.0'
- } = options
-
- @localDb = null
- @remoteDb = null
- @initialized = false
- @syncHandler = null
- # Основная инициализация
- init: ->
- return Promise.resolve() if @initialized
-
- try
- debug.log '🚀 Инициализация PouchDB сервиса...'
-
- # Создание локальной базы
- @localDb = new PouchDB(@localDbName)
- debug.log '📁 Локальная база создана:', @localDbName
-
- # Создание/подключение удаленной базы
- await @ensureRemoteDatabase()
-
- # Загрузка design документов
- await @ensureDesignDocs()
-
- # Настройка синхронизации
- await @setupSync()
-
- @initialized = true
- debug.log '✅ PouchDB сервис инициализирован'
- return Promise.resolve()
-
- catch error
- console.error '❌ Ошибка инициализации PouchDB:', error
- return Promise.reject(error)
- # Создание удаленной базы если не существует
- ensureRemoteDatabase: ->
- try
- @remoteDb = new PouchDB(@remoteDbUrl)
-
- # Проверка существования базы
- info = await @remoteDb.info()
- debug.log '🌐 Удаленная база подключена:', info.db_name
-
- catch error
- if error.status == 404
- debug.log '📦 Создание новой удаленной базы...'
- # В браузере создание БД происходит автоматически при первом обращении
- @remoteDb = new PouchDB(@remoteDbUrl)
- info = await @remoteDb.info()
- debug.log '✅ Удаленная база создана:', info.db_name
- else
- throw error
- # Создание design документов
- ensureDesignDocs: ->
- try
- # Загрузка design документов
- adminDesign = require 'app/design/admin.coffee'
- siteDesign = require 'app/design/site.coffee'
-
- # Сохранение design документов
- await @saveDesignDoc(adminDesign)
- await @saveDesignDoc(siteDesign)
-
- debug.log '📝 Design документы загружены'
-
- catch error
- console.error 'Ошибка загрузки design документов:', error
- throw error
- # Сохранение design документа с проверкой версий
- saveDesignDoc: (designDoc) ->
- try
- existingDoc = await @remoteDb.get(designDoc._id)
-
- # Проверка необходимости обновления
- if existingDoc.hash != designDoc.hash || existingDoc.version != designDoc.version
- designDoc._rev = existingDoc._rev
- await @remoteDb.put(designDoc)
- debug.log "🔄 Design документ обновлен: #{designDoc._id}"
- else
- debug.log "✅ Design документ актуален: #{designDoc._id}"
-
- catch error
- if error.status == 404
- # Документ не существует, создаем новый
- await @remoteDb.put(designDoc)
- debug.log "✅ Design документ создан: #{designDoc._id}"
- else
- throw error
- # Настройка синхронизации
- setupSync: ->
- @syncHandler = PouchDB.sync(@remoteDb, @localDb, {
- live: true,
- retry: true,
- filter: (doc) => @shouldSyncDocument(doc)
- })
-
- @syncHandler
- .on('change', (info) =>
- debug.log '🔄 Синхронизация:', info)
- .on('paused', (err) =>
- debug.log '⏸️ Синхронизация приостановлена')
- .on('active', =>
- debug.log '🔄 Синхронизация активна')
- .on('error', (err) =>
- console.error '❌ Ошибка синхронизации:', err)
-
- debug.log '🔁 Синхронизация настроена'
- # Проверка необходимости синхронизации документа
- shouldSyncDocument: (doc) ->
- return false if doc._id?.startsWith('_design/')
-
- # Всегда синхронизируем общие данные
- if doc.type in ['product', 'category', 'settings', 'hero_slide', 'blog_article', 'route', 'domain_settings']
- return true
-
- # Для пользовательских данных проверяем принадлежность
- if doc.type in ['order', 'user_data', 'cart']
- return doc.userId == @userFilter?.userId
-
- # Для мультидоменности проверяем принадлежность к домену
- if doc.domains
- return @userFilter?.currentDomain in doc.domains
-
- return false
- # Умное получение документа
- getDocument: (docId) ->
- @ensureInit()
-
- try
- # Сначала пробуем локально
- doc = await @localDb.get(docId)
- debug.log '📄 Документ получен из локального кэша:', docId
- return doc
-
- catch localError
- if localError.status == 404
- try
- # Затем пробуем удаленно
- doc = await @remoteDb.get(docId)
- # Сохраняем в кэш для будущих запросов
- await @localDb.put(doc)
- debug.log '📄 Документ получен из удаленной БД и закэширован:', docId
- return doc
- catch remoteError
- console.error '❌ Документ не найден:', docId
- throw remoteError
- else
- throw localError
- # Сохранение документа (только в удаленную БД)
- saveToRemote: (doc) ->
- @ensureInit()
-
- try
- # Проверяем существование документа
- existingDoc = await @remoteDb.get(doc._id)
- doc._rev = existingDoc._rev
- result = await @remoteDb.put(doc)
- debug.log '💾 Документ обновлен в удаленной БД:', doc._id
- return result
-
- catch error
- if error.status == 404
- # Документ не существует, создаем новый
- result = await @remoteDb.put(doc)
- debug.log '💾 Документ создан в удаленной БД:', doc._id
- return result
- else
- console.error '❌ Ошибка сохранения документа:', error
- throw error
- # Пакетное сохранение
- bulkDocs: (docs) ->
- @ensureInit()
- await @remoteDb.bulkDocs(docs)
- # Выполнение view запроса
- queryView: (designDoc, viewName, options = {}) ->
- @ensureInit()
- await @remoteDb.query("#{designDoc}/#{viewName}", options)
- # Получение вложений
- getAttachment: (docId, attachmentName) ->
- @ensureInit()
- await @remoteDb.getAttachment(docId, attachmentName)
- # Сохранение вложения
- putAttachment: (docId, attachmentName, attachment, type) ->
- @ensureInit()
-
- try
- doc = await @remoteDb.get(docId)
- await @remoteDb.putAttachment(docId, attachmentName, doc._rev, attachment, type)
- debug.log '📎 Вложение сохранено:', "#{docId}/#{attachmentName}"
- catch error
- if error.status == 404
- # Документ не существует, создаем сначала базовый документ
- await @remoteDb.put({ _id: docId, type: 'with_attachments' })
- await @remoteDb.putAttachment(docId, attachmentName, attachment, type)
- else
- throw error
- # Вспомогательные методы
- ensureInit: ->
- if !@initialized
- throw new Error 'PouchDBService не инициализирован. Вызовите init() сначала.'
- destroy: ->
- if @syncHandler
- @syncHandler.cancel()
- @initialized = false
- debug.log '🧹 PouchDBService уничтожен'
- # Создание и экспорт синглтона
- module.exports = new PouchDBService({
- localDbName: 'braer_color_cache'
- remoteDbUrl: 'https://oleg:631074@couchdb.favt.ru.net/braer_color_shop'
- userFilter: { userId: 'current_user_id' }
- appVersion: '1.0.0'
- })
|