npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ahopez/zk-workers-lib

v1.0.4

Published

A powerful, runtime-agnostic ZKTeco Biometric Device SDK for Node.js and Cloudflare Workers (raw TCP sockets).

Readme

@ahopez/zk-workers-lib

npm version License: MIT Node.js Version Downloads

A modern, runtime-agnostic ZKTeco Biometric Device SDK written in TypeScript. Decoupled from native platform modules, this SDK enables communication with physical biometric fingerprint scanners from both Node.js and edge-computing runtimes like Cloudflare Workers.


✨ Why This Package? (How It Differs)

Traditional ZKTeco node packages (like node-zklib or zklib-js) are hardcoded to Node.js's native net and dgram socket modules. This tightly couples them to a standard server environment and prevents them from executing on edge networks.

  • 🌐 Cloudflare Workers & Edge Support: The first ZK SDK capable of running inside Cloudflare Workers using the native cloudflare:sockets TCP API.
  • 📦 ESM & CommonJS Dual Bundling: Full TypeScript support, pre-packaged with type declarations (.d.ts) and ESM/CJS exports.
  • 🔒 Stateless Request Mutexing: Solves socket dropouts (STREAM_CLOSED_PREMATURELY) and interleaving packet collisions by enforcing a thread-safe connection-per-request mutex lock pattern.
  • Zero External Dependencies: Pure JS/TS implementation using native ArrayBuffer and DataView binary parsing for maximum performance.

📦 Installation

npm install @ahopez/zk-workers-lib
yarn add @ahopez/zk-workers-lib
pnpm add @ahopez/zk-workers-lib

🚀 Quick Start

1. Node.js Integration

import { ZKClient, getUsers, getAttendances } from '@ahopez/zk-workers-lib';
import { NodeTransport } from '@ahopez/zk-workers-lib/transports/node';

const transport = new NodeTransport({ ip: '192.168.1.201', port: 4370, timeout: 10000 });
const client = new ZKClient(transport);

async function main() {
  try {
    await client.createSocket();
    console.log('Connected to device!');

    const users = await getUsers(client);
    const logs = await getAttendances(client);

    console.log(`Enrolled Users: ${users.length}`);
    console.log(`Check-in Logs: ${logs.length}`);

    await client.disconnect();
  } catch (error) {
    console.error('Connection failed:', error);
  }
}

main();

2. Cloudflare Workers Integration

import { ZKClient, getUsers } from '@ahopez/zk-workers-lib';
import { CloudflareTransport } from '@ahopez/zk-workers-lib/transports/cloudflare';

export default {
  async fetch(request, env, ctx) {
    const transport = new CloudflareTransport({ ip: '122.252.225.190', port: 4370, timeout: 10000 });
    const client = new ZKClient(transport);

    await client.createSocket();
    const users = await getUsers(client);
    await client.disconnect();

    return new Response(JSON.stringify(users), {
      headers: { 'Content-Type': 'application/json' }
    });
  }
};

📖 API Reference

Core Client Methods

| Method | Parameters | Description | |--------|------------|-------------| | new ZKClient(transport) | transport: ITransport | Initializes the client with a transport adapter | | createSocket() | - | Connects to the device and establishes a session | | disconnect() | - | Closes the connection to the device | | executeCmd() | command: number, data: Uint8Array \| string | Executes a raw ZK command code |

User Management

| Method / Function | Parameters | Description | |--------|------------|-------------| | getUsers(client) | client: ZKClient | Retrieves all users from the device database | | getUser(client, userId) | client: ZKClient, userId: string | Finds a user by their User String ID | | setUser(client, ...) | client, uid, userid, name, password?, role?, cardno? | Creates or updates a user on the device | | deleteUser(client, uid) | client: ZKClient, uid: number | Deletes a user profile from the device |

Biometric Management

| Function / Method | Parameters | Description | |--------|------------|-------------| | getUserTemplate(client, ...) | client, uid, fingerIndex | Reads a specific fingerprint template of a user | | getAllTemplates(client) | client: ZKClient | Downloads all fingerprint templates inside device memory | | client.enrollFingerprint(...) | userId: string, fingerIndex: number | Wakes up the scanner to enroll a specific finger (0-9) |

Attendance Records

| Function | Parameters | Description | |--------|------------|-------------| | getAttendances(client, cb?) | client, cb? | Reads all attendance records from device memory | | clearAttendanceLog(client) | client | Wipes attendance log records from the storage chip |

Device Maintenance & Option Controls

| Function | Parameters | Description | |--------|------------|-------------| | getInfo(client) | client | Retrieves storage capacity details and count metrics | | getTime(client) | client | Reads the current local time of the device clock | | setTime(client, date) | client, date: Date | Sets the device's clock to the specified date-time | | getOption(client, keyword) | client, keyword: string | Reads a hardware option parameter (e.g., IPAddress, NetMask) | | voiceTest(client) | client | Plays the device's hardware test sound | | clearData(client) | client | Clears user and template databases | | refreshData(client) | client | Commits changes and flushes device memory | | freeData(client) | client | Frees device transmission buffers |


💡 Examples

User Registration & Role Configuration

import { ZKClient, setUser } from '@ahopez/zk-workers-lib';
import { NodeTransport } from '@ahopez/zk-workers-lib/transports/node';

const client = new ZKClient(new NodeTransport({ ip: '192.168.1.201' }));
await client.createSocket();

// Set user 'John Doe' as an Administrator (role code 14)
await setUser(
  client,
  2,           // Unique numeric UID
  'EMP102',    // String User ID
  'John Doe',  // Name
  '',          // Password
  14,          // Role code (0: User, 14: Admin)
  123456       // RFID Card Number
);

await client.disconnect();

Remote Fingerprint Enrollment Flow

Enrolls a user's right index finger (index 1) remotely from the dashboard:

import { ZKClient } from '@ahopez/zk-workers-lib';
import { NodeTransport } from '@ahopez/zk-workers-lib/transports/node';

const client = new ZKClient(new NodeTransport({ ip: '192.168.1.201' }));
await client.createSocket();

// Put device in enroll mode: stops capturing, sets target parameters, prompts verify scan
await client.enrollFingerprint('EMP102', 1);

// Device speaker will speak "Please press your finger". User scans 3 times.
await client.disconnect();

🔧 Configuration

Pluggable Transport Construction

Choose the transport layer matching your runtime environment:

// For Node.js (CommonJS or ESM)
new NodeTransport({ ip, port, timeout })

// For Cloudflare Workers (ESM)
new CloudflareTransport({ ip, port, timeout })

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | ip | string | - | Biometric device IP address (required) | | port | number | 4370 | Connection port | | timeout | number | 10000 | Connection socket timeout in milliseconds |


🤝 Contributing

This repository is closed to external contributions. Pull requests and contributions are not accepted.


📄 License

This project is licensed under the MIT License.


Author: ArunKumar
Email: [email protected]