@mha/scanner-bridge-sdk
v1.1.1
Published
React WebSocket bridge client linking frontend UI applications to local hardware scanners
Downloads
405
Maintainers
Readme
Scanner Bridge SDK
React WebSocket bridge client for local TWAIN hardware scanners. Replace clunky JavaScript TWAIN libraries with a clean, modern React API.
🔥 Drop-in Replacement for TW-TWAIN-JS
Migrating from TW-TWAIN-JS? Zero code changes required!
// Just change this line:
// import TWTwainJS from "../../lib/TWTwainJS";
import TWTwainJS from "@mha/scanner-bridge-sdk/compat";
// Everything else works exactly the same! 🎉📖 Complete TW-TWAIN-JS Replacement Guide →
Features
- ✅ TW-TWAIN-JS Compatible - Drop-in replacement, no code changes
- ✅ WebSocket-based - Backend handles all TWAIN complexity
- ✅ React Hooks - Modern, idiomatic React patterns
- ✅ TypeScript - Full type safety
- ✅ Live Previews - Real-time JPEG Base64 streams during scanning
- ✅ Multi-page Documents - Compile selected pages to PDF or TIFF
- ✅ Automatic Reconnection - Resilient connection management
- ✅ Chakra UI v3 - Matches scan-edit-lib dependencies
- ✅ getFile() Support - Full compatibility with existing TIFF/PDF workflows
Installation
npm install @mha/scanner-bridge-sdkPrerequisites
The Scanner Bridge backend must be running at ws://127.0.0.1:8080 (configurable).
Quick Start
1. Wrap your app with the provider
import { ScannerBridgeProvider } from "@mha/scanner-bridge-sdk";
function App() {
return (
<ScannerBridgeProvider>
<YourScannerComponent />
</ScannerBridgeProvider>
);
}2. Use the hooks
import {
useScanner,
useScanSession,
DocumentFormat,
} from "@mha/scanner-bridge-sdk";
function ScannerComponent() {
const { scanners, listScanners, startScan, isLoading } = useScanner();
const [sessionId, setSessionId] = useState<string | null>(null);
const { session, isScanning, compileDocument } = useScanSession(sessionId);
const handleScan = async () => {
const id = await startScan({
resolution: 300,
colorMode: ColorMode.RGB,
});
setSessionId(id);
};
const handleCompile = async () => {
const doc = await compileDocument({
format: DocumentFormat.PDF,
pages: [1, 2, 3], // or "1-3,5,7-9"
});
// Upload doc.blob to your backend
const formData = new FormData();
formData.append("file", doc.blob, "scanned-document.pdf");
await fetch("/api/upload", { method: "POST", body: formData });
};
return (
<div>
<button onClick={listScanners}>Refresh Scanners</button>
{scanners.map((scanner) => (
<div key={scanner.id}>{scanner.name}</div>
))}
<button onClick={handleScan} disabled={isLoading}>
Start Scan
</button>
{session?.pages.map((page) => (
<img
key={page.pageNumber}
src={`data:image/jpeg;base64,${page.preview}`}
alt={`Page ${page.pageNumber}`}
/>
))}
{session && !isScanning && (
<button onClick={handleCompile}>Compile to PDF</button>
)}
</div>
);
}API Reference
<ScannerBridgeProvider>
Provider component that manages the WebSocket connection.
Props:
config?: BridgeConfig- Configuration optionsurl?: string- WebSocket URL (default:ws://127.0.0.1:8080)reconnectInterval?: number- Reconnection delay in ms (default:3000)reconnectAttempts?: number- Max reconnection attempts (default:10)debug?: boolean- Enable debug logging (default:false)
useScannerBridge()
Low-level hook for connection management.
Returns:
{
isConnected: boolean;
isConnecting: boolean;
connectionError: string | null;
lastError: string | null;
client: ScannerBridgeClient;
connect: () => Promise<void>;
disconnect: () => void;
}useScanner()
Scanner enumeration and scan initiation.
Returns:
{
scanners: ScannerInfo[];
isLoading: boolean;
error: string | null;
listScanners: () => Promise<void>;
startScan: (options?: ScanOptions) => Promise<string>; // Returns sessionId
cancelScan: (sessionId: string) => Promise<void>;
}ScanOptions:
{
scannerId?: number; // Scanner index (omit for default)
colorMode?: ColorMode; // RGB, Gray, BW
resolution?: number; // DPI (e.g., 300)
paperSize?: PaperSize; // A4, Letter, Legal
duplexEnabled?: boolean; // Front/back scanning
useFeeder?: boolean; // Auto-feed multiple pages
}useScanSession(sessionId)
Manage an active scan session and compile documents.
Returns:
{
session: ScanSession | null; // Current session state
isScanning: boolean; // Is scan in progress?
compileDocument: (options) => Promise<CompiledDocument>;
getSessionInfo: () => Promise<void>;
}CompileOptions:
{
format: DocumentFormat; // PDF or TIFF
pages?: number[] | string; // [1,3,5] or "1-3,5,7-9" (omit for all)
}CompiledDocument:
{
sessionId: string;
format: DocumentFormat;
pageCount: number;
selectedPages: number[];
sizeBytes: number;
blob: Blob; // Ready for upload!
timestamp: string;
}Page Selection Syntax
The pages parameter supports flexible formats:
| Format | Example | Result |
| --------- | ------------- | ------------------------- |
| Array | [1, 3, 5] | Pages 1, 3, 5 |
| Range | "1-5" | Pages 1, 2, 3, 4, 5 |
| Mixed | "1-3,5,7-9" | Pages 1, 2, 3, 5, 7, 8, 9 |
| Omit | undefined | All pages |
Types
import type {
ScannerInfo,
ScanOptions,
ScanSession,
ScannedPage,
CompileOptions,
CompiledDocument,
BridgeConfig,
} from "@mha/scanner-bridge-sdk";
import {
ColorMode,
PaperSize,
ScanStatus,
DocumentFormat,
} from "@mha/scanner-bridge-sdk";Comparison with TW-TWAIN-JS
| Feature | TW-TWAIN-JS | Scanner Bridge SDK | | --------------------- | -------------------- | --------------------------- | | TWAIN Handling | Browser (complex) | Backend (simple) | | Multi-page TIFF | JavaScript libraries | Native Windows GDI+ | | PDF Generation | Client-side (heavy) | Server-side (fast) | | Live Previews | ❌ | ✅ Real-time Base64 streams | | React Integration | Manual | Native hooks | | TypeScript | Partial | Full type safety | | Reconnection | Manual | Automatic |
License
MIT
