@mkptraveltech/id-scanner-securescan
v0.1.19
Published
Passport scanner library for Plustek SecureScan x50 scanner
Downloads
117
Readme
README.md
MKP Passport Scanner – WebFxScan Client
Client ringan berbasis TypeScript untuk mengontrol scanner via WebFxScan (melalui scan.js) di aplikasi web/renderer (Electron/React/Next.js, dsb). Library ini menangani:
- Koneksi ke perangkat scanner (IP/Port)
- Pemilihan device & konfigurasi scan dengan dialog HTML (browser only)
- Penyimpanan konfigurasi ringan di
localStorage - Callback auto scan / progress
- (Opsional) Validasi
partnerCodeke server aplikasi
Catatan — Library ini membungkus class
WebFxScandariscan.js. Pastikan filescan.jsmengeksporWebFxScan(ESM) dan dapat dibundel pada environment Anda.
🔎 Daftar Isi
- Fitur
- Instalasi
- Pemakaian Singkat
- Contoh React
- Alur Kerja
- Penyimpanan Lokal
- Mode dev vs prod
- Keamanan & Privasi
- Troubleshooting Cepat
- Lisensi
- Kontribusi
- Tautan Terkait
✨ Fitur
- ✅ API minimal & ergonomis (
createWebFxScan,WebFxScanClient) - ✅ Dialog HTML bawaan untuk input IP/Port, pilih device, dan set config (browser only)
- ✅ TypeScript-first (tipe kuat untuk parameter & hasil scan)
- ✅ Mode prod/dev untuk memisahkan alur validasi & pengiriman hasil
- ✅ Kompatibel dengan UI modern (React/Next/Electron renderer)
📦 Instalasi
# via Git URL
npm install https://gitlab.com/labib.mkp/mkp-id-scanner-securescan.git
# atau
pnpm add https://gitlab.com/labib.mkp/mkp-id-scanner-securescan.gitJika publish ke registry privat:
npm i @mkp/mkp-passport-scanner-securescan.
Persyaratan
| Komponen | Versi/Info |
| -------- | ----------------------------------------- |
| Node | 18+ (dev/build) |
| Runtime | Browser / Electron Renderer |
| scan.js | Harus meng-export WebFxScan (ES module) |
🚀 Pemakaian Singkat
import { createWebFxScan } from "@mkp/mkp-passport-scanner-securescan";
const scanClient = createWebFxScan({ mode: "dev" }); // "prod" | "dev"
// 1) Hubungkan ke scanner
await scanClient.connect({
// Opsi 1: isi IP/Port langsung
scannerServerIp: "10.243.191.245",
scannerIp: "10.243.191.245",
scannerPort: "17778",
isUpdateConfig: false,
// Opsi 2: tanpa IP/Port + isUpdateConfig:true (muncul dialog)
// isUpdateConfig: true,
});
// 2) (Opsional) pasang callback autoscan
scanClient.setAutoScanCallback((data) => {
console.log("AutoScan =>", data.fileName, data.ocrText);
});
// 3) Mulai scan (manual)
const res = await scanClient.scan();
if (res.code === 0) {
console.log(
"Scan OK:",
res.data.map((p) => p.fileName),
);
} else {
console.error("Scan gagal:", res.message);
}
// 4) Utilitas
await scanClient.getPaperStatus();
await scanClient.close();⚛️ Contoh React
import { useEffect, useState } from "react";
import { createWebFxScan } from "@mkp/mkp-passport-scanner-securescan";
export default function Scan() {
const [connected, setConnected] = useState(false);
const [img, setImg] = useState<string | null>(null);
const scan = createWebFxScan({ mode: "dev" });
useEffect(() => {
(async () => {
const r = await scan.connect({
scannerServerIp: "10.243.191.245",
scannerIp: "10.243.191.245",
scannerPort: "17778",
isUpdateConfig: false,
});
setConnected(r.code === 0);
scan.setAutoScanCallback((d) => setImg(d.base64));
})();
}, []);
const doScan = async () => {
const r = await scan.scan();
if (r.code === 0 && r.data[0]) setImg(r.data[0].base64);
};
return (
<div>
<button disabled={!connected} onClick={doScan}>
Scan
</button>
{img && <img src={img} alt="passport" />}
</div>
);
}🧭 Alur Kerja (Ringkas)
connect()
- Kumpulkan IP/Port (argumen →
localStorage→ dialog). getDeviceList()→ pilih device (dialog jika perlu).- Simpan device & config dasar (resolution/mode/brightness/quality/autoScan).
setScanner()dengan config.- (Mode prod) Validasi
partnerCodeviaPOST {scannerServerIp}/scanner/init.
- Kumpulkan IP/Port (argumen →
scan() →
serverInstance.scan(); returnScanData[].getPaperStatus() / close()` → utilitas.
💾 Penyimpanan Lokal
Key yang digunakan di localStorage:
scannerServerIp,scannerIp,scannerPort,scannerAuthTokenscannerDevice,scannerScanConfig
close()akan menghapus key-key tersebut. Pada error validasipartnerCodedata juga dibersihkan.
🧪 Mode dev vs prod
| Mode | Perilaku |
| -------- | ------------------------------------------------------------------------------------- |
| dev | Tidak validasi partnerCode. Dapat menyetel token dummy agar alur UI lancar. |
| prod | Menjalankan validasi partnerCode (jika partnerCode & scannerServerIp tersedia). |
🔐 Keamanan & Privasi
- Jangan commit
scannerAuthTokenke repo. - Pastikan CORS & TLS server Anda benar jika dipanggil dari browser.
- Hindari menampilkan base64 hasil scan ke publik tanpa proteksi.
🩺 Troubleshooting Cepat
- Dialog input/selector tidak muncul di Electron Main → Jalankan dari renderer process.
scan.jstidak ditemukan /WebFxScanundefined → Pastikan bundler meloloskanscan.js(ESM) dan path import benar.- Koneksi OK,
scan()kosong → CekdeviceName&sourcesaatsetScanner(). CobaisUpdateConfig: true. - Tidak bisa mengetik di dialog
<input>→ Cek global key listener yang mungkinpreventDefault().
Lihat
docs/API.mduntuk detail tipe/method & catatan issue.
📄 Lisensi
ISC — © Labib MKP
🤝 Kontribusi
PR/issue dipersilakan. Sertakan deskripsi masalah, langkah reproduksi, environment, serta log relevan.
🔗 Tautan Terkait
scan.js(penyediaWebFxScan) — wajib tersedia di project Andadocs/API.md— dokumentasi tipe & method detail
docs/API.md
API Reference
Import
import defaultExport, { createWebFxScan, WebFxScanClient, PaperSize, ImageFmt, RecognizeType, RecognizeLang, type ConnectOptions, type ClientOptions, type DeviceInfo, type DeviceOptions, type ScanParams, type ScanData, type ScanProgress, type FxResult, } from "@mkp/mkp-passport-scanner-securescan";
defaultExportberisi{ create, Client }.
Konstanta & Tipe
PaperSize
"A4" | "Letter" | "Legal" | "A3" | "B5" | "A5" | "A6" | "LongPaper" | (string & {})ImageFmt
"jpg" | "png" | "tif" | "pdf" | "ofd" | (string & {})RecognizeType
"none" | "fulltext" | "barcode" | (string & {})Catatan:
DEFAULT_SCAN_CONFIGmemakai nilai"passport" as any. Jika memang diperlukan, pertimbangkan menambah literal"passport"ke unionRecognizeType.
RecognizeLang
"en" | "zh-cn" | "zh-tw" | "jp" | "kr" | "de" | "de+en" | "fr" | "id" | (string & {})FxResult<T>
// OK
{
code: number;
message: string;
data: T;
}
// Error
{
code: number;
message: string | unknown;
}code === 0 → sukses, selain itu dianggap error.
Interfaces
ClientOptions
interface ClientOptions {
mode?: "prod" | "dev";
authApiUrl?: string; // reserved untuk masa depan
authToken?: string;
}ConnectOptions
interface ConnectOptions {
scannerServerIp?: string;
scannerIp?: string;
scannerPort?: string;
partnerCode?: string; // untuk validasi di mode "prod"
authToken?: string; // Basic/Bearer token, jika diperlukan server
isUpdateConfig?: boolean; // true => tampilkan dialog untuk set/ubah config
autoScan?: boolean; // override config autoscan
errorCallback?: (ev: Event | unknown) => void;
closeCallback?: (ev: CloseEvent | unknown) => void;
}DeviceOptions
interface DeviceOptions {
deviceName: string;
displayName?: string;
source?: { value: string; type: string };
paperSize?: string[];
paperSizeDetail?: Array<{
width: number;
height: number;
unit: "mm" | "inch";
}>;
resolution?: number[] | { min: number; max: number };
mode?: string[];
}ScanParams
interface ScanParams {
deviceName: string;
source?: string;
paperSize?: PaperSize;
resolution?: number;
mode?: "lineart" | "gray" | "color" | string;
imageFmt?: ImageFmt;
filenameFormat?: string;
filenameBeginindex?: number;
savePath?: string;
brightness?: number;
contrast?: number;
quality?: number;
autoRotate?: boolean;
rotate?: 0 | 90 | 180 | 270;
removeBlankPage?: boolean;
swdeskew?: boolean;
swcrop?: boolean;
duplexBackFlip?: boolean;
duplexMergeType?: 0 | 1 | 2 | 3;
scanCount?: number;
autoScan?: boolean;
apAutoScan?: boolean;
recognizeType?: RecognizeType; // lihat catatan "passport" di atas
recognizeLang?: RecognizeLang;
fullTextType?: "txt" | "pdf" | "odf" | string;
}ScanData
interface ScanData {
fileName: string;
base64: string;
ocrText?: string;
[k: string]: unknown;
}ScanProgress
interface ScanProgress {
page: number;
status: "scanning" | "mergeFile" | string;
fileName?: string;
[k: string]: unknown;
}Kelas & Fungsi
createWebFxScan(options?: ClientOptions): WebFxScanClient
Factory untuk membuat instance client.
class WebFxScanClient
constructor(opts?: ClientOptions)
Membungkus pembuatan _WebFxScan dari scan.js. Menyimpan mode, authToken, serta state IP/Port.
connect(options?: ConnectOptions): Promise<FxResult<void>>
Langkah:
- Kumpulkan IP/Port (argumen →
localStorage→ dialog). getDeviceList()→ pilih device (dialog jika perlu).setScanner()sesuai config.- (prod) Validasi
partnerCodeviaPOST {scannerServerIp}/scanner/init.
Hasil: { code: 0, message: "Connected successfully" } pada sukses, atau error code != 0.
setAutoScanCallback(callback: (progress: ScanData) => void): any
Meneruskan callback ke WebFxScan.setAutoScanCallback.
scan(options?: { callback?: (p: ScanProgress) => void; eventCallback?: (c: number | string) => void; timeout?: number; hideBase64?: boolean; }): Promise<FxResult<ScanData[]>>
Memanggil serverInstance.scan(). Mengembalikan ScanData[].
Catatan mode prod: Terdapat blok pengiriman ke endpoint yang tampak membalik kondisi
resp.ok. Periksa logika ini sebelum produksi.
getPaperStatus(): Promise<FxResult<{ message: string }>>
Proxy ke serverInstance.getPaperStatus().
close(): Promise<FxResult<void>>
Membersihkan localStorage terkait dan menutup koneksi di _fx.
Catatan Implementasi & Known Issues
- Enum
RecognizeTypevs default"passport"— Pertimbangkan menambahkan'passport'ke unionRecognizeTypeagar konsisten denganDEFAULT_SCAN_CONFIG. - Blok sukses/error di
scan()(mode prod) — Saat iniresp.ok === truediperlakukan seolah error. Balikkan kondisinya agar sesuai harapan. - Dialog
<dialog>& focus — Pada beberapa SPA/Electron, globalkeydownlistener dapat mengganggu input. HindaripreventDefault()saat dialog terbuka.
Roadmap Singkat
- Mengaktifkan kembali method yang dikomentari (
getFileList,convert,mergePdf,imageProcess,deleteFile,calibrate, dll.) - Menstandardisasi
RecognizeTypetermasuk"passport" - Memperbaiki blok sukses/error di
scan()(prod) - Opsi i18n untuk dialog bawaan
