pcsc-mini - v0.1.2
    Preparing search index...

    pcsc-mini • NPM Version

    › NodeJS PC/SC API bindings for smart card access on Linux / MacOS / Win32

    Docs ↗ | | Overview | | Prerequisites | | Installation | | Usage

    import * as pcsc from "pcsc-mini";
    const { CardDisposition, CardMode, ReaderStatus } = pcsc;

    const client = new pcsc.Client()
    .on("reader", onReader)
    .start();

    function onReader(reader: pcsc.Reader) {
    reader.on("change", async status => {
    if (!status.has(ReaderStatus.PRESENT)) return;
    if (status.hasAny(ReaderStatus.MUTE, ReaderStatus.IN_USE)) return;

    const card = await reader.connect(CardMode.SHARED);
    console.log(`${await card.state()}`);

    const resTx = await card.transmit(
    Uint8Array.of(0xca, 0xfe, 0xf0, 0x0d)
    );
    console.log(resTx);

    const codeFeatures = pcsc.controlCode(3400);
    const features = await card.control(codeFeatures);
    console.log(features);

    await card.disconnect(CardDisposition.RESET);
    client.stop();
    process.exit(0);
    });
    }

    pcsc-mini provides NodeJS bindings to native PC/SC (Personal Computer/Smart Card) APIs:

    * MacOS has a separate implementation built on the CryptoTokenKit API.

    Pre-built binary packages are available for the following targets.

    These are installed as optional dependencies of the main pcsc-mini package (e.g. @pcsc-mini/linux-x86_64-gnu).

    OS arm64 x86 x86_64
    Linux ( gnu ) ☑️
    Linux ( musl )* ☑️
    MacOS N/A ☑️
    Windows ☑️ ⬜️

    ✅ Tested & verified  •  ☑️ Not tested  •  ⬜️ Not available

    * During testing on Alpine, the PCSC server daemon needed to be started after a reader was connected for detection/monitoring to work and required a restart whenever a reader was disconnected and reconnected.

    Runtime Supported Versions
    NodeJS v16.x.x, v18.x.x, v20.x.x, v22.x.x v24.x.x
    OTHERS:
    Bun Tested with v1.2.12 (may work with earlier)
    Deno Tested with v2.3.1 (may work with earlier)
    Electron v15.0.0+ (Tested up to v36.2.0)

    Required packages:

    • ccid
    • pcsc-lite
    • pcsc-lite-libs
    doas apk add ccid pcsc-lite pcsc-lite-libs
    

    To run the server daemon:

    doas rc-service pcscd start
    

    Required packages:

    • libpcsclite1
    • pcscd
    sudo apt install libpcsclite1 pcscd
    

    To run the server daemon:

    sudo systemctl start pcscd
    

    N/A :: MacOS and Windows come pre-installed with smart card support. No additional installation needed.


    Bun

    bun add pcsc-mini
    

    Deno

    deno add npm:pcsc-mini
    

    npm

    npm i pcsc-mini
    

    pnpm

    pnpm add pcsc-mini
    
    import * as pcsc from "pcsc-mini";
    const { CardDisposition, CardMode, ReaderStatus } = pcsc;

    // The `Client` emits a "reader" event for each detected device.
    const client = new pcsc.Client()
    .on("reader", onReader)
    .on("error", onError)
    .start();

    function onError(err: pcsc.Err) {
    console.error("Unexpected PCSC error:", err);
    client.stop();

    // [ Log and exit / attempt `start()` retries with backoff / etc... ]
    };

    function onReader(reader: pcsc.Reader) {
    let card: pcsc.Card | undefined;

    console.log(`Reader detected: ${reader}`);

    // Each reader emits a "change" event on every reader state change.
    reader.on("change", async status => {
    if (status.hasAny(ReaderStatus.MUTE, ReaderStatus.IN_USE)) return;

    if (!status.has(ReaderStatus.PRESENT)) {
    void card?.disconnect(CardDisposition.RESET);
    card = undefined;
    return;
    }

    try {
    if (!card) card = await reader.connect(CardMode.SHARED);

    // Transmit Uint8Array (or NodeJS Buffer) data:
    const res = await card.transmit(
    Uint8Array.of(0xca, 0xfe, 0xf0, 0x0d)
    );

    // Use Uint8Array response directly, or via DataView/Buffer:
    const vw = new DataView(res.buffer, res.byteOffset, res.length);
    const tag = vw.getUint8(0);
    const len = vw.getUint16(2);
    const val = new Uint8Array(res.buffer, 4, len);

    // ...
    } catch (err) {
    console.error("Card error:", err);
    }
    });

    // "disconnect" is emitted when a reader is no longer detected.
    //
    // All event listeners will be removed from the now-invalid reader.
    // Any reader/card-related state should be disposed of here.
    reader.on("disconnect", async () => {
    void card?.disconnect(CardDisposition.RESET);
    card = undefined;
    });
    }
    Tip

    See the E2E test application for more involved usage and error handling.

    Minimum Version Recommended Version
    Zig v0.14.1 See .zigversion
    NodeJS v24.0.0 See .nvmrc
    pnpm v10.0.0 See package.json
    OPTIONAL:
    Bun v1.2.12
    Deno v2.3.1

    See Prerequisites section above for a list of runtime prerequisites.

    Other relevant development libraries (e.g. libpcsclite-dev on Debian-based distros) are included in the pcsc dependency. No additional installation needed.

    N/A :: Required MacOS Framework .tbds are included in the pcsc dependency. No additional installation needed.

    N/A :: Required DLLs are shipped with the Zig compiler. No additional installation needed.

    This will output an lib/addon.node file to enable unit testing. Runs automatically when running the unit tests.

    zig build
    
    zig build test
    
    zig build test:node -- --watch
    
    zig build test:zig --watch
    

    This enables testing basic operations against real devices (supporting up to 4 simultaneously connected readers) to verify functionality not testable via unit tests.

    zig build e2e
    

    This will output the final NPM package directories to ./zig-out/npm_packages.

    zig build packages
    

    MIT