scanservjs: init at 2.27.1; nixos/scanservjs: init (#249806)

This commit is contained in:
Arne Keller
2024-12-12 17:01:22 +01:00
committed by GitHub
5 changed files with 315 additions and 0 deletions
@@ -16,6 +16,8 @@
- [Bazecor](https://github.com/Dygmalab/Bazecor), the graphical configurator for Dygma Products.
- [scanservjs](https://github.com/sbs20/scanservjs/), a web UI for SANE scanners. Available at [services.scanservjs](#opt-services.scanservjs.enable).
- [Kimai](https://www.kimai.org/), a web-based multi-user time-tracking application. Available as [services.kimai](options.html#opt-services.kimai).
- [Omnom](https://github.com/asciimoo/omnom), a webpage bookmarking and snapshotting service. Available as [services.omnom](options.html#opt-services.omnom.enable).
+1
View File
@@ -624,6 +624,7 @@
./services/hardware/sane_extra_backends/brscan4.nix
./services/hardware/sane_extra_backends/brscan5.nix
./services/hardware/sane_extra_backends/dsseries.nix
./services/hardware/scanservjs.nix
./services/hardware/spacenavd.nix
./services/hardware/supergfxd.nix
./services/hardware/tcsd.nix
@@ -0,0 +1,155 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.scanservjs;
settings = {
scanimage = lib.getExe' config.hardware.sane.backends-package "scanimage";
convert = lib.getExe' pkgs.imagemagick "convert";
tesseract = lib.getExe pkgs.tesseract;
# it defaults to config/devices.json, but "config" dir doesn't exist by default and scanservjs doesn't create it
devicesPath = "devices.json";
} // cfg.settings;
settingsFormat = pkgs.formats.json { };
leafs =
attrs:
builtins.concatLists (
lib.mapAttrsToList (k: v: if builtins.isAttrs v then leafs v else [ v ]) attrs
);
package = pkgs.scanservjs;
configFile = pkgs.writeText "config.local.js" ''
/* eslint-disable no-unused-vars */
module.exports = {
afterConfig(config) {
${
builtins.concatStringsSep "" (
leafs (
lib.mapAttrsRecursive (path: val: ''
${builtins.concatStringsSep "." path} = ${builtins.toJSON val};
'') { config = settings; }
)
)
}
${cfg.extraConfig}
},
afterDevices(devices) {
${cfg.extraDevicesConfig}
},
async afterScan(fileInfo) {
${cfg.runAfterScan}
},
actions: [
${builtins.concatStringsSep ",\n" cfg.extraActions}
],
};
'';
in
{
options.services.scanservjs = {
enable = lib.mkEnableOption "scanservjs";
stateDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/scanservjs";
description = ''
State directory for scanservjs.
'';
};
settings = lib.mkOption {
default = { };
description = ''
Config to set in config.local.js's `afterConfig`.
'';
type = lib.types.submodule {
freeformType = settingsFormat.type;
options.host = lib.mkOption {
type = lib.types.str;
description = "The IP to listen on.";
default = "127.0.0.1";
};
options.port = lib.mkOption {
type = lib.types.port;
description = "The port to listen on.";
default = 8080;
};
};
};
extraConfig = lib.mkOption {
default = "";
type = lib.types.lines;
description = ''
Extra code to add to config.local.js's `afterConfig`.
'';
};
extraDevicesConfig = lib.mkOption {
default = "";
type = lib.types.lines;
description = ''
Extra code to add to config.local.js's `afterDevices`.
'';
};
runAfterScan = lib.mkOption {
default = "";
type = lib.types.lines;
description = ''
Extra code to add to config.local.js's `afterScan`.
'';
};
extraActions = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.lines;
description = "Actions to add to config.local.js's `actions`.";
};
};
config = lib.mkIf cfg.enable {
hardware.sane.enable = true;
users.users.scanservjs = {
group = "scanservjs";
extraGroups = [
"scanner"
"lp"
];
home = cfg.stateDir;
isSystemUser = true;
createHome = true;
};
users.groups.scanservjs = { };
systemd.services.scanservjs = {
description = "scanservjs";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
# yes, those paths are configurable, but the config option isn't always used...
# a lot of the time scanservjs just takes those from PATH
path = with pkgs; [
coreutils
config.hardware.sane.backends-package
imagemagick
tesseract
];
environment = {
NIX_SCANSERVJS_CONFIG_PATH = configFile;
SANE_CONFIG_DIR = "/etc/sane-config";
LD_LIBRARY_PATH = "/etc/sane-libs";
};
serviceConfig = {
ExecStart = lib.getExe package;
Restart = "always";
User = "scanservjs";
Group = "scanservjs";
WorkingDirectory = cfg.stateDir;
};
};
};
}
@@ -0,0 +1,64 @@
diff --git a/packages/server/src/api.js b/packages/server/src/api.js
index bd43842..71ce7c9 100644
--- a/packages/server/src/api.js
+++ b/packages/server/src/api.js
@@ -105,7 +105,7 @@ module.exports = new class Api {
}
// If not then it's possible the default image is not quite the correct aspect ratio
- const buffer = FileInfo.create(`${config.previewDirectory}/default.jpg`).toBuffer();
+ const buffer = FileInfo.create('NIX_OUT_PLACEHOLDER/lib/node_modules/scanservjs-api/data/preview/default.jpg').toBuffer();
try {
// We need to know the correct aspect ratio from the device
diff --git a/packages/server/src/application.js b/packages/server/src/application.js
index 2771036..0c2a4c0 100644
--- a/packages/server/src/application.js
+++ b/packages/server/src/application.js
@@ -26,7 +26,7 @@ module.exports = new class Application {
userOptions() {
if (this._userOptions === null) {
- this._userOptions = new UserOptions('../../config/config.local.js');
+ this._userOptions = new UserOptions(process.env.NIX_SCANSERVJS_CONFIG_PATH);
}
return this._userOptions;
}
diff --git a/packages/server/src/classes/user-options.js b/packages/server/src/classes/user-options.js
index f129e3c..c71e754 100644
--- a/packages/server/src/classes/user-options.js
+++ b/packages/server/src/classes/user-options.js
@@ -4,7 +4,7 @@ const path = require('path');
module.exports = class UserOptions {
constructor(localConfigPath) {
if (localConfigPath) {
- const localPath = path.join(__dirname, localConfigPath);
+ const localPath = localConfigPath;
if (fs.existsSync(localPath)) {
this.local = require(localPath);
}
diff --git a/packages/server/src/configure.js b/packages/server/src/configure.js
index c9e5ed8..484949c 100644
--- a/packages/server/src/configure.js
+++ b/packages/server/src/configure.js
@@ -71,6 +71,7 @@ function initialize(rootPath) {
try {
fs.mkdirSync(config.outputDirectory, { recursive: true });
+ fs.mkdirSync(config.previewDirectory, { recursive: true });
fs.mkdirSync(config.tempDirectory, { recursive: true });
} catch (exception) {
log.warn(`Error ensuring output and temp directories exist: ${exception}`);
diff --git a/packages/server/src/server.js b/packages/server/src/server.js
index e1a9fb0..3d58d37 100644
--- a/packages/server/src/server.js
+++ b/packages/server/src/server.js
@@ -5,7 +5,7 @@ const configure = require('./configure');
const config = application.config();
const app = express();
-app.use(express.static('client'));
+app.use(express.static('@client@'));
configure(app);
+93
View File
@@ -0,0 +1,93 @@
{
lib,
fetchFromGitHub,
buildNpmPackage,
fetchNpmDeps,
nodejs,
substituteAll,
}:
let
version = "2.27.1";
src = fetchFromGitHub {
owner = "sbs20";
repo = "scanservjs";
# rev = "v${version}";
# 2.27.1 doesn't have a tag
rev = "b15adc6f97fb152fd9819371bb1a9b8118baf55b";
hash = "sha256-ne9fEF/eurWPXzmJQzBn5jiy+JgxMWiCXsOdmu2fj6E=";
};
depsHashes = {
server = "sha256-M8t+TrE+ntZaI9X7hEel94bz34DPtW32n0KKMSoCfIs=";
client = "sha256-C31WBYE8ba0t4mfKFAuYWrCZtSdN7tQIYmCflDRKuBM=";
};
serverDepsForClient = fetchNpmDeps {
inherit src nodejs;
sourceRoot = "${src.name}/packages/server";
name = "scanservjs";
hash = depsHashes.server or lib.fakeHash;
};
# static client files
client = buildNpmPackage {
pname = "scanservjs-client";
inherit version src nodejs;
sourceRoot = "${src.name}/packages/client";
npmDepsHash = depsHashes.client or lib.fakeHash;
preBuild = ''
cd ../server
chmod +w package-lock.json . /build/source/
npmDeps=${serverDepsForClient} npmConfigHook
cd ../client
'';
env.NODE_OPTIONS = "--openssl-legacy-provider";
dontNpmInstall = true;
installPhase = ''
mv /build/source/dist/client $out
'';
};
in
buildNpmPackage {
pname = "scanservjs";
inherit version src nodejs;
sourceRoot = "${src.name}/packages/server";
npmDepsHash = depsHashes.server or lib.fakeHash;
# can't use "patches" since they change the server deps' hash for building the client
# (I don't want to maintain one more hash)
preBuild = ''
chmod +w /build/source
patch -p3 <${
substituteAll {
src = ./decouple-from-source-tree.patch;
inherit client;
}
}
substituteInPlace src/api.js --replace 'NIX_OUT_PLACEHOLDER' "$out"
'';
postInstall = ''
mkdir -p $out/bin
makeWrapper ${lib.getExe nodejs} $out/bin/scanservjs \
--set NODE_ENV production \
--add-flags "'$out/lib/node_modules/scanservjs-api/src/server.js'"
'';
meta = {
description = "SANE scanner nodejs web ui";
longDescription = "scanservjs is a simple web-based UI for SANE which allows you to share a scanner on a network without the need for drivers or complicated installation.";
homepage = "https://github.com/sbs20/scanservjs";
license = lib.licenses.gpl2Only;
mainProgram = "scanservjs";
maintainers = with lib.maintainers; [ chayleaf ];
platforms = lib.platforms.linux;
};
}