Ver código fonte

Merge branch 'release/1.0.3'

Book Pauk 2 anos atrás
pai
commit
894349618c
7 arquivos alterados com 309 adições e 9 exclusões
  1. 264 2
      README.md
  2. 31 0
      build/release.js
  3. 1 1
      client/components/Search/Search.vue
  4. 2 2
      package-lock.json
  5. 2 1
      package.json
  6. 7 1
      server/core/WebWorker.js
  7. 2 2
      server/index.js

+ 264 - 2
README.md

@@ -1,3 +1,265 @@
-# inpx-web
+inpx-web
+========
 
-Веб-сервер для поиска по inpx-коллекции.
+Веб-сервер для поиска по .inpx-коллекции.
+Выглядит это так: https://lib.omnireader.ru
+
+.inpx - индексный файл для импорта\экспорта информации из базы данных сетевых библиотек
+в базу каталогизатора [MyHomeLib](https://alex80.github.io/mhl/)
+или [freeLib](http://sourceforge.net/projects/freelibdesign)
+или [LightLib](https://lightlib.azurewebsites.net)
+
+Просто поместите приложение `inpx-web` в папку с .inpx-файлом и файлами библиотеки (zip-архивами) и запустите.
+Сервер будет доступен по адресу http://127.0.0.1:12380
+
+После открытия веб-приложения в бразуере, для быстрого понимания того, как работает поиск, воспользуйтесь памяткой (кнопка со знаком вопроса).
+
+##
+* [Возможности программы](#capabilities)
+* [Использование](#usage)
+    * [Параметры командной строки](#cli)
+    * [Конфигурация](#config)
+    * [Удаленная библиотека](#remotelib)
+    * [Фильтр по аторам и книгам](#filter)
+    * [Настройка https с помощью nginx](#https)
+* [Сборка проекта](#build)
+* [Разработка](#development)
+
+<a id="capabilities" />
+
+## Возможности программы
+- поиск по автору, серии, названию и пр.
+- скачивание книги, копирование ссылки или открытие в читалке
+- возможность указать рабочий каталог при запуске, а также расположение .inpx и файлов библиотеки
+- ограничение доступа по паролю
+- работа в режиме "удаленная библиотека"
+- фильтр авторов и книг при создании поисковой БД для создания своей коллекции "на лету"
+- подхват изменений .inpx-файла (периодическая проверка), автоматическое пересоздание поисковой БД
+- мощная оптимизация, хорошая скорость поиска
+- релизы под Linux и Windows
+
+<a id="usage" />
+
+## Использование
+Поместите приложение `inpx-web` в папку с .inpx-файлом и файлами библиотеки и запустите.
+По умолчанию сервер будет доступен по адресу http://127.0.0.1:12380
+
+<a id="cli" />
+
+### Параметры командной строки
+Запустите `inpx-web --help`, чтобы увидеть список опций:
+```console
+Usage: inpx-web [options]
+
+Options:
+  --help              Показать опции командной строки
+  --host=<ip>         Задать имя хоста для веб сервера, по умолчанию: 0.0.0.0
+  --port=<port>       Задать порт для веб сервера, по умолчанию: 12380
+  --app-dir=<dirpath> Задать рабочую директорию, по умолчанию: <execDir>/.inpx-web
+  --lib-dir=<dirpath> Задать директорию библиотеки (с zip-архивами), по умолчанию: там же, где лежит файл приложения
+  --inpx=<filepath>   Задать путь к файлу .inpx, по умолчанию: тот, что найдется в директории библиотеки
+  --recreate          Принудительно пересоздать поисковую БД при запуске приложения
+```
+
+<a id="config" />
+
+### Конфигурация
+При первом запуске в рабочей директории будет создан конфигурационный файл `config.json`:
+```js
+{
+    // пароль для ограничения доступа к веб-интерфейсу сервера
+    "accessPassword": "",
+
+    // содержимое кнопки-ссылки (читать), если не задано - кнопка (читать) не показывается
+    // пример: "https://omnireader.ru/#/reader?url=${DOWNLOAD_LINK}"
+    // на место ${DOWNLOAD_LINK} будет подставлена ссылка на скачивание файла книги
+    "bookReadLink": "",
+
+    // включить(true)/выключить(false) журналирование
+    "loggingEnabled": true,
+
+    // максимальный размер в байтах директории закешированных файлов в <раб.дир>/public/files
+    // чистка каждый час
+    "maxFilesDirSize": 1073741824,
+    
+    // включить(true)/выключить(false) кеширование запросов на сервере
+    "queryCacheEnabled": true,
+
+    // периодичность чистки кеша запросов на сервере, в минутах
+    "cacheCleanInterval": 60,
+
+    // периодичность проверки изменений .inpx-файла
+    // если файл изменился, поисковая БД будет автоматически пересоздана
+    "inpxCheckInterval": 60,
+
+    // включить(true)/выключить(false) режим работы с малым количеством физической памяти на машине
+    // при включении этого режима, количество требуемой для создания БД памяти снижается примерно в 1.5-2 раза
+    // во столько же раз увеличивается время создания
+    "lowMemoryMode": false,
+
+    // включить(true)/выключить(false) режим "Удаленная библиотека" (сервер)
+    "allowRemoteLib": false,
+
+    // включить(Object)/выключить(false) режим "Удаленная библиотека" (клиент)
+    // подробнее см. раздел "Удаленная библиотека" ниже
+    "remoteLib": false,
+
+    // настройки веб-сервера
+    "server": {
+        "host": "0.0.0.0",
+        "port": "12380"
+    }
+}
+```
+
+При необходимости, можно настроить нужный параметр в этом файле вручную. Параметры командной
+строки имеют больший приоритет, чем настройки из `config.json`.
+
+<a id="remotelib" />
+
+### Удаленная библиотека
+
+В случае, когда необходимо физически разнести веб-интерфейс и библиотеку файлов на разные машины,
+приложение может работать в режиме клиент-сервер: веб-интерфейс, поисковый движок и поисковая БД на одной машине (клиент),
+а библиотека книг и .inpx-файл на другой (сервер).
+
+Для этого необходимо развернуть два приложения, первое из которых будет клиентом для второго.
+
+На сервере правим `config.json`:
+```
+    "accessPassword": "123456",
+    "allowRemoteLib": true,
+```
+
+На клиенте:
+```
+    "remoteLib": {
+    	"accessPassword": "123456",
+        "url": "ws://server.host:12380"
+    },
+```
+
+Если сервер работает по протоколу `http://`, то указываем протокол `ws://`, а для `https://` соответственно `wss://`.
+Пароль не обязателен, но необходим в случае, если сервер тоже "смотрит" в интернет, для ограничения доступа к его веб-интерфесу.
+При указании `"remoteLib": {...}` настройки командной строки --inpx и --lib-dir игнорируются,
+т.к. файлы .inpx-индекса и библиотеки используются удаленно.
+
+<a id="filter" />
+
+### Фильтр по аторам и книгам
+
+При создании поисковой БД во время загрузки и парсинга .inpx-файла, имеется возможность
+отфильтровать авторов и книги, задав определенные критерии. Для этого небходимо создать
+в рабочей директории (там же, где `config.json`) файл `filter.json` следующего вида:
+```json
+{
+  "info": {
+    "collection": "Новое название коллекции",
+    "structure": "",
+    "version": "1.0.0"
+  },
+  "filter": "(r) => r.del == 0",
+  "includeAuthors": ["Имя автора 1", "Имя автора 2"],
+  "excludeAuthors": ["Имя автора"]
+}
+```
+При создании поисковой БД, авторы и книги из `includeAuthors` будут добавлены, а из `excludeAuthors` исключены.
+Использование совместно `includeAuthors` и `excludeAuthors` имеет мало смысла, поэтому для включения
+определенных авторов можно использовать только `includeAuthors`:
+```json
+{
+  "info": {
+    "collection": "Новое название коллекции"
+  },
+  "includeAuthors": ["Имя автора 1", "Имя автора 2"]
+}
+```
+Для исключения:
+```json
+{
+  "info": {
+    "collection": "Новое название коллекции"
+  },
+  "excludeAuthors": ["Имя автора 1", "Имя автора 2"]
+}
+```
+
+Параметр `filter` используется для более гибкой фильтрации по атрибутам записей из .inpx.
+Уберем все записи, помеченные как удаленные и исключим "Имя автора 1":
+```json
+{
+  "info": {
+    "collection": "Новое название коллекции"
+  },
+  "filter": "(inpxRec) => inpxRec.del == 0",
+  "excludeAuthors": ["Имя автора 1"]
+}
+```
+Использование `filter` небезопасно, т.к. позволяет выполнить произвольный js-код внутри программы,
+поэтому запуск приложения в этом случае должен сопровождаться дополнительным параметром командной строки `--unsafe-filter`.
+Названия атрибутов inpxRec соответствуют названиям в нижнем регистре из структуры structure.info в .inpx-файле.
+<a id="https" />
+
+### Настройка https с помощью nginx
+Проще всего настроить https с помощью certbot и проксирования в nginx (пример для debian-based linux):
+
+```sh
+#ставим nginx
+sudo apt install nginx
+```
+```
+#правим конфиг nginx
+server {
+  listen 80;
+  server_name <имя сервера>;
+  set $inpx_web http://127.0.0.1:12380;
+
+  client_max_body_size 512m;
+  proxy_read_timeout 1h;
+
+  location / {
+    proxy_pass $inpx_web;
+    proxy_http_version 1.1;
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+  }
+}
+```
+```sh
+#загружаем новый конфиг
+sudo service nginx reload
+```
+Далее следовать инструкции установки https://certbot.eff.org/instructions?ws=nginx&os=debianbuster
+
+<a id="build" />
+
+### Сборка проекта
+Сборка только в среде Linux.
+Необходима версия node.js не ниже 16.
+
+```sh
+git clone https://github.com/bookpauk/inpx-web
+cd inpx-web
+npm i
+```
+
+#### Для платформы Windows
+```sh
+npm run build:win
+```
+
+#### Для платформы Linux
+```sh
+npm run build:linux
+```
+
+Результат сборки будет доступен в каталоге `dist/linux|win` в виде исполнимого (standalone) файла.
+
+<a id="development" />
+
+### Разработка
+```sh
+npm run dev
+```
+
+Связаться с автором проекта: [bookpauk@gmail.com](mailto:bookpauk@gmail.com)

+ 31 - 0
build/release.js

@@ -0,0 +1,31 @@
+const fs = require('fs-extra');
+const path = require('path');
+const { execSync } = require('child_process');
+
+const pckg = require('../package.json');
+
+const distDir = path.resolve(__dirname, '../dist');
+const outDir = `${distDir}/release`;
+
+async function makeRelease(target) {
+    const srcDir = `${distDir}/${target}`;
+
+    if (await fs.pathExists(srcDir)) {
+        const zipFile = `${outDir}/${pckg.name}-${pckg.version}-${target}.zip`;
+
+        execSync(`zip -r ${zipFile} .`, {cwd: srcDir, stdio: 'inherit'});
+    }
+}
+
+async function main() {
+    try {
+        await fs.emptyDir(outDir);
+        await makeRelease('win');
+        await makeRelease('linux');
+    } catch(e) {
+        console.error(e);
+        process.exit(1);
+    }
+}
+
+main();

+ 1 - 1
client/components/Search/Search.vue

@@ -533,7 +533,7 @@ class Search {
     }
 
     openReleasePage() {
-        window.open('https://github.com/bookpauk/inpx-web', '_blank');
+        window.open('https://github.com/bookpauk/inpx-web/releases', '_blank');
     }
 
     makeProjectName() {

+ 2 - 2
package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "inpx-web",
-  "version": "1.0.2",
+  "version": "1.0.3",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "inpx-web",
-      "version": "1.0.2",
+      "version": "1.0.3",
       "hasInstallScript": true,
       "license": "CC0-1.0",
       "dependencies": {

+ 2 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "inpx-web",
-  "version": "1.0.2",
+  "version": "1.0.3",
   "author": "Book Pauk <bookpauk@gmail.com>",
   "license": "CC0-1.0",
   "repository": "bookpauk/inpx-web",
@@ -13,6 +13,7 @@
     "build:linux": "npm run build:client && node build/prepkg.js linux && pkg -t node16-linux-x64 -C GZip --options max-old-space-size=4096,expose-gc -o dist/linux/inpx-web .",
     "build:win": "npm run build:client && node build/prepkg.js win && pkg -t node16-win-x64 -C GZip --options max-old-space-size=4096,expose-gc -o dist/win/inpx-web .",
     "build:client-dev": "webpack --config build/webpack.dev.config.js",
+    "release": "npm run build:linux && npm run build:client && node build/release.js",
     "postinstall": "npm run build:client-dev"
   },
   "bin": "server/index.js",

+ 7 - 1
server/core/WebWorker.js

@@ -146,7 +146,13 @@ class WebWorker {
                 await fs.remove(dbPath);
 
             if (!await fs.pathExists(dbPath)) {
-                await this.createDb(dbPath);
+                try {
+                    await this.createDb(dbPath);
+                } catch (e) {
+                    //при ошибке создания БД удалим ее, чтобы не работать с поломанной базой при следующем запуске
+                    await fs.remove(dbPath);
+                    throw e;
+                }
                 utils.freeMemory();
             }
 

+ 2 - 2
server/index.js

@@ -205,13 +205,13 @@ function initStatic(app, config) {
     });
 
     //заголовки при отдаче
-    const filesDir = `${config.publicDir}/files`;
+    const filesDir = utils.toUnixPath(`${config.publicDir}/files`);
     app.use(express.static(config.publicDir, {
         setHeaders: (res, filePath) => {
             //res.set('Cache-Control', 'no-cache');
             //res.set('Expires', '-1');
 
-            if (utils.toUnixPath(path.dirname(filePath)) == utils.toUnixPath(filesDir)) {
+            if (utils.toUnixPath(path.dirname(filePath)) == filesDir) {
                 res.set('Content-Encoding', 'gzip');
 
                 if (res.downFileName)