Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# dependencies (bun install)
node_modules

# output
out
dist
*.tgz

# code coverage
coverage
*.lcov

# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# caches
.eslintcache
.cache
*.tsbuildinfo

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store
7 changes: 7 additions & 0 deletions .lefthook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pre-commit:
parallel: true
jobs:
- run: bun format {staged_files}
glob:
- "*.ts"
stage_fixed: true
18 changes: 15 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
FROM oven/bun as build

WORKDIR /build

ENV NODE_ENV=production
COPY . .
RUN bun install --frozen-lockfile && \
bun test --ci && \
bun compile

FROM debian:bookworm-slim

WORKDIR /app
Expand All @@ -23,11 +33,13 @@ RUN apt update && \
util-linux

ENV TZ=${TZ-"America/Edmonton"}
ENV vendor=${vendor-"fujitsu"}

RUN git clone https://github.com/rocketraman/sane-scan-pdf.git --depth 1

COPY scanbd.conf /etc/scanbd/scanbd.conf
COPY scan.sh /etc/scanbd/scripts/scan.sh
COPY discover.sh /app/discover.sh
COPY conf/scanbd.conf /etc/scanbd/scanbd.conf
COPY scripts/discover.sh /app/discover.sh
COPY --from=build /build/dist/scan /etc/scanbd/scripts/scan

RUN chmod +x /etc/scanbd/scripts/scan.sh && \
chmod +x /app/discover.sh
Expand Down
39 changes: 39 additions & 0 deletions biome.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"$schema": "node_modules/@biomejs/biome/configuration_schema.json",
"files": {
"includes": ["src/**/*.ts", "src/**/*.tsx", "*.json", "*.jsonc"]
},
"assist": {
"actions": {
"source": {
"organizeImports": {
"level": "on",
"options": {
"groups": [":URL:", ":BUN:"]
}
}
}
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"style": {
"useConst": "error",
"useImportType": "error"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "always"
}
}
}
78 changes: 78 additions & 0 deletions bun.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "scan-station",
"dependencies": {
"@topcli/spinner": "3.0.0",
},
"devDependencies": {
"@biomejs/biome": "2.1.4",
"@types/bun": "latest",
"lefthook": "1.12.3",
},
"peerDependencies": {
"typescript": "5",
},
},
},
"packages": {
"@biomejs/biome": ["@biomejs/[email protected]", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.1.4", "@biomejs/cli-darwin-x64": "2.1.4", "@biomejs/cli-linux-arm64": "2.1.4", "@biomejs/cli-linux-arm64-musl": "2.1.4", "@biomejs/cli-linux-x64": "2.1.4", "@biomejs/cli-linux-x64-musl": "2.1.4", "@biomejs/cli-win32-arm64": "2.1.4", "@biomejs/cli-win32-x64": "2.1.4" }, "bin": { "biome": "bin/biome" } }, "sha512-QWlrqyxsU0FCebuMnkvBIkxvPqH89afiJzjMl+z67ybutse590jgeaFdDurE9XYtzpjRGTI1tlUZPGWmbKsElA=="],

"@biomejs/cli-darwin-arm64": ["@biomejs/[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-sCrNENE74I9MV090Wq/9Dg7EhPudx3+5OiSoQOkIe3DLPzFARuL1dOwCWhKCpA3I5RHmbrsbNSRfZwCabwd8Qg=="],

"@biomejs/cli-darwin-x64": ["@biomejs/[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-gOEICJbTCy6iruBywBDcG4X5rHMbqCPs3clh3UQ+hRKlgvJTk4NHWQAyHOXvaLe+AxD1/TNX1jbZeffBJzcrOw=="],

"@biomejs/cli-linux-arm64": ["@biomejs/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-juhEkdkKR4nbUi5k/KRp1ocGPNWLgFRD4NrHZSveYrD6i98pyvuzmS9yFYgOZa5JhaVqo0HPnci0+YuzSwT2fw=="],

"@biomejs/cli-linux-arm64-musl": ["@biomejs/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-nYr7H0CyAJPaLupFE2cH16KZmRC5Z9PEftiA2vWxk+CsFkPZQ6dBRdcC6RuS+zJlPc/JOd8xw3uCCt9Pv41WvQ=="],

"@biomejs/cli-linux-x64": ["@biomejs/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-Eoy9ycbhpJVYuR+LskV9s3uyaIkp89+qqgqhGQsWnp/I02Uqg2fXFblHJOpGZR8AxdB9ADy87oFVxn9MpFKUrw=="],

"@biomejs/cli-linux-x64-musl": ["@biomejs/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-lvwvb2SQQHctHUKvBKptR6PLFCM7JfRjpCCrDaTmvB7EeZ5/dQJPhTYBf36BE/B4CRWR2ZiBLRYhK7hhXBCZAg=="],

"@biomejs/cli-win32-arm64": ["@biomejs/[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-3WRYte7orvyi6TRfIZkDN9Jzoogbv+gSvR+b9VOXUg1We1XrjBg6WljADeVEaKTvOcpVdH0a90TwyOQ6ue4fGw=="],

"@biomejs/cli-win32-x64": ["@biomejs/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-tBc+W7anBPSFXGAoQW+f/+svkpt8/uXfRwDzN1DvnatkRMt16KIYpEi/iw8u9GahJlFv98kgHcIrSsZHZTR0sw=="],

"@topcli/spinner": ["@topcli/[email protected]", "", { "dependencies": { "cli-spinners": "^3.1.0" } }, "sha512-wQHGvZSDiYt8OJyoS9SC2kVX2FjiH4fcpgAeL6xna1kQoiNlF8n6t7y1CbvickRfDUcGCHQKNf0Rp6DJqEmb4Q=="],

"@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.2.20" } }, "sha512-dX3RGzQ8+KgmMw7CsW4xT5ITBSCrSbfHc36SNT31EOUg/LA9JWq0VDdEXDRSe1InVWpd2yLUM1FUF/kEOyTzYA=="],

"@types/node": ["@types/[email protected]", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="],

"@types/react": ["@types/[email protected]", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA=="],

"bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-pxTnQYOrKvdOwyiyd/7sMt9yFOenN004Y6O4lCcCUoKVej48FS5cvTw9geRaEcB9TsDZaJKAxPTVvi8tFsVuXA=="],

"cli-spinners": ["[email protected]", "", {}, "sha512-pXftdQloMZzjCr3pCTIRniDcys6dDzgpgVhAHHk6TKBDbRuP1MkuetTF5KSv4YUutbOPa7+7ZrAJ2kVtbMqyXA=="],

"csstype": ["[email protected]", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],

"lefthook": ["[email protected]", "", { "optionalDependencies": { "lefthook-darwin-arm64": "1.12.3", "lefthook-darwin-x64": "1.12.3", "lefthook-freebsd-arm64": "1.12.3", "lefthook-freebsd-x64": "1.12.3", "lefthook-linux-arm64": "1.12.3", "lefthook-linux-x64": "1.12.3", "lefthook-openbsd-arm64": "1.12.3", "lefthook-openbsd-x64": "1.12.3", "lefthook-windows-arm64": "1.12.3", "lefthook-windows-x64": "1.12.3" }, "bin": { "lefthook": "bin/index.js" } }, "sha512-huMg+mGp6wHPjkaLdchuOvxVRMzvz6OVdhivatiH2Qn47O5Zm46jwzbVPYIanX6N/8ZTjGLBxv8tZ0KYmKt/Jg=="],

"lefthook-darwin-arm64": ["[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-j1lwaosWRy3vhz8oQgCS1M6EUFN95aIYeNuqkczsBoAA6BDNAmVP1ctYEIYUK4bYaIgENbqbA9prYMAhyzh6Og=="],

"lefthook-darwin-x64": ["[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-x6aWFfLQX4m5zQ4X9zh5+hHOE5XTvNjz2zB9DI+xbIBLs2RRg0xJNT3OfgSrBU1QtEBneJ5dRQP5nl47td9GDQ=="],

"lefthook-freebsd-arm64": ["[email protected]", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-41OmulLqVZ0EOHmmHouJrpL59SwDD7FLoso4RsQVIBPaf8fHacdLo07Ye28VWQ5XolZQvnWcr1YXKo4JhqQMyw=="],

"lefthook-freebsd-x64": ["[email protected]", "", { "os": "freebsd", "cpu": "x64" }, "sha512-741/JRCJIS++hgYEH2uefN4FsH872V7gy2zDhcfQofiZnWP7+qhl4Wmwi8IpjIu4X7hLOC4cT18LOVU5L8KV9Q=="],

"lefthook-linux-arm64": ["[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-BXIy1aDFZmFgmebJliNrEqZfX1lSOD4b/USvANv1UirFrNgTq5SRssd1CKfflT2PwKX6LsJTD4WabLLWZOxp9A=="],

"lefthook-linux-x64": ["[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-FRdwdj5jsQAP2eVrtkVUqMqYNCbQ2Ix84izy29/BvLlu/hVypAGbDfUkgFnsmAd6ZsCBeYCEtPuqyg3E3SO0Rg=="],

"lefthook-openbsd-arm64": ["[email protected]", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-tch5wXY4GOjKAYohH7OFoxNdVHuUSYt2Pulo2VTkMYEG8IrvJnRO5MkvgHtKDHzU5mfABQYv5+ccJykDx5hQWA=="],

"lefthook-openbsd-x64": ["[email protected]", "", { "os": "openbsd", "cpu": "x64" }, "sha512-IHbHg/rUFXrAN7LnjcQEtutCHBaD49CZge96Hpk0GZ2eEG5GTCNRnUyEf+Kf3+RTqHFgwtADdpeDa/ZaGZTM4g=="],

"lefthook-windows-arm64": ["[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-wghcE5TSpb+mbtemUV6uAo9hEK09kxRzhf2nPdeDX+fw42cL2TGZsbaCnDyzaY144C+L2/wEWrLIHJMnZYkuqA=="],

"lefthook-windows-x64": ["[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-7Co/L8e2x2hGC1L33jDJ4ZlTkO3PJm25GOGpLfN1kqwhGB/uzMLeTI/PBczjlIN8isUv26ouNd9rVR7Bibrwyg=="],

"typescript": ["[email protected]", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],

"undici-types": ["[email protected]", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
}
}
2 changes: 2 additions & 0 deletions bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[install]
exact = true
2 changes: 1 addition & 1 deletion scanbd.conf → conf/scanbd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ global {
to-value = 0
}
desc = "Scan to file"
script = "scan.sh"
script = "scan"
}
}
21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "scan-station",
"module": "src/index.ts",
"type": "module",
"private": true,
"scripts": {
"compile": "bun build --compile --outfile dist/scan --minify src/scan.ts",
"format": "biome lint --write && biome format --write"
},
"devDependencies": {
"@biomejs/biome": "2.1.4",
"@types/bun": "latest",
"lefthook": "1.12.3"
},
"peerDependencies": {
"typescript": "5"
},
"dependencies": {
"@topcli/spinner": "3.0.0"
}
}
34 changes: 0 additions & 34 deletions scan.sh

This file was deleted.

1 change: 0 additions & 1 deletion discover.sh → scripts/discover.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/bin/sh

vendor=${vendor:-"fujitsu"}
device=$(lsusb | grep -i $vendor | awk '{print $6}')

if [ -z "$device" ]; then
Expand Down
39 changes: 39 additions & 0 deletions src/scan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Spinner } from '@topcli/spinner';
import { $ } from 'bun';
import uploader from './uploader/uploader';

const dateFormat = process.env.date_format ?? '%Y-%m-%d-%H%M%S-%3N-%Z';
const filePrefix = process.env.file_prefix ?? 'scan';
const vendor = process.env.vendor ?? 'fujitsu';
const dpi = process.env.dpi ?? '300';
const mode = process.env.mode ?? 'Color';
const outputDir = process.env.output_dir ?? './scans';
const scanProgram = process.env.scan_program ?? '/app/sane-scan-pdf/scan';
const spinner = new Spinner();

// Run the scan command
try {
const now = await $`date +${dateFormat}`.text();
const fileOutputPath = `${outputDir}/${filePrefix}-${now}.pdf`;
const flags = {
'-v': '',
'-d': '',
'-x': vendor,
'-r': dpi,
'--mode': mode,
'--skip-empty-pages': '',
'--crop': '',
'-o': fileOutputPath,
};

spinner.start(`Scanning document to ${fileOutputPath}`);
await $`${scanProgram} ${Object.entries(flags).flat().filter(Boolean).join(' ')}`;
spinner.succeed(`Scan completed: ${fileOutputPath}`);

// upload the scanned document
await uploader(fileOutputPath);
process.exit(0);
} catch (error) {
spinner.failed(`Scan failed: ${JSON.stringify(error)}`);
process.exit(1);
}
Loading