AppDB.coffee 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # FILE: app/utils/AppDB.coffee
  2. class AppDB
  3. currentLanguage: 'ru'
  4. currentProject: 's5l.ru'
  5. designDocVersion: '1.1' # управление версией дизайна
  6. constructor: ->
  7. @localDB = new PouchDB('s5l_local')
  8. @remoteDB = new PouchDB('https://oleg:631074@couchdb.favt.ru.net/s5lru/')
  9. @syncHandler = null
  10. init: ->
  11. try
  12. await @remoteDB.info()
  13. debug.log "Remote DB connected"
  14. await @ensureDesignDocs()
  15. await @ensureDefaultContent()
  16. @startSync()
  17. AppDB.currentLanguage = globalThis._?.appState?.currentLanguage or 'ru'
  18. catch e
  19. debug.log "DB init failed:", e
  20. startSync: ->
  21. @syncHandler = @localDB.sync(@remoteDB, { live: true, retry: true })
  22. .on 'error', (err) -> debug.log "Sync error:", err
  23. ensureDesignDocs: ->
  24. adminDoc =
  25. _id: '_design/admin'
  26. version: @designDocVersion
  27. views:
  28. byPath:
  29. map: (doc) ->
  30. if doc.type == 'page'
  31. emit [doc.domain, doc.path], doc
  32. .toString()
  33. byType:
  34. map: (doc) ->
  35. emit doc.type, doc
  36. .toString()
  37. try
  38. existing = await @remoteDB.get('_design/admin')
  39. if existing.version != @designDocVersion
  40. adminDoc._rev = existing._rev
  41. await @remoteDB.put(adminDoc)
  42. debug.log "Design doc updated to v#{@designDocVersion}"
  43. catch
  44. await @remoteDB.put(adminDoc)
  45. debug.log "Design doc created v#{@designDocVersion}"
  46. ensureDefaultContent: ->
  47. defaultHome =
  48. _id: 'page::s5l.ru::/'
  49. type: 'page'
  50. domain: 's5l.ru'
  51. path: '/'
  52. translations:
  53. ru:
  54. title: "s5l.ru — мультиязычная offline-first платформа"
  55. subtitle: "Разрабатывайте быстро, работайте везде"
  56. content: '''
  57. # Добро пожаловать на s5l.ru
  58. **s5l.ru** — это платформа для быстрого запуска веб-проектов с поддержкой:
  59. - offline-first через PouchDB/CouchDB
  60. - автоматического переключения языка
  61. - динамической подгрузки контента
  62. - полной WCAG 2.2-совместимости
  63. Все тексты хранятся в базе и легко редактируются через админку.
  64. '''
  65. gallery: [
  66. { src: "/assets/hero-s5l.svg", alt: "Hero illustration" }
  67. ]
  68. en:
  69. title: "s5l.ru — multilingual offline-first platform"
  70. subtitle: "Build fast, work anywhere"
  71. content: '''
  72. # Welcome to s5l.ru
  73. **s5l.ru** is a platform for rapid web project launches with:
  74. - offline-first via PouchDB/CouchDB
  75. - automatic language switching
  76. - dynamic content loading
  77. - full WCAG 2.2 compliance
  78. All text is stored in the database and editable via admin panel.
  79. '''
  80. gallery: [
  81. { src: "/assets/hero-s5l.svg", alt: "Hero illustration" }
  82. ]
  83. tj:
  84. title: "s5l.ru — платформаи бисёрзабон ва аввал офлайн"
  85. subtitle: "Бисёр тез бунёд кунед, дар ҳама ҷо кор кунед"
  86. content: '''
  87. # Ба s5l.ru хуш омадед
  88. **s5l.ru** — ин платформа барои оғози тези лоиҳаҳои веб аст бо:
  89. - офлайн-аввал аз рӯи PouchDB/CouchDB
  90. - ивази худкори забон
  91. - боркунии динамикӣ
  92. - мутобиқати пурраи WCAG 2.2
  93. Ҳамаи матнҳо дар база нигоҳ дошта мешаванд ва аз ҷониби панели маъмури озодона таҳрир карда мешаванд.
  94. '''
  95. gallery: [
  96. { src: "/assets/hero-s5l.svg", alt: "Hero illustration" }
  97. ]
  98. try
  99. await @remoteDB.get('page::s5l.ru::/')
  100. catch
  101. await @remoteDB.put(defaultHome)
  102. debug.log "Default home page created"
  103. getDocumentByPath: (path, lang = @currentLanguage) ->
  104. path = path or '/'
  105. try
  106. result = await @localDB.query('admin/byPath', { key: [@currentProject, path], include_docs: true })
  107. if result.rows.length > 0
  108. doc = result.rows[0].doc
  109. return doc
  110. else
  111. throw new Error "Document not found"
  112. catch e
  113. debug.log "Fallback for path:", path, "lang:", lang
  114. # fallback to English if not found
  115. if lang != 'en'
  116. return await @getDocumentByPath(path, 'en')
  117. else
  118. throw new Error "Document not available even in English"
  119. module.exports = AppDB