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

e-imzo-server-client

v1.1.0

Published

Unofficial high-performance TypeScript & Node.js client SDK for Uzbekistan E-IMZO and E-IMZO-SERVER REST API with first-class NestJS support.

Readme

E-IMZO Client SDK (Node.js & TypeScript)

NPM Version Build & Test License: MIT Compatible Server

[!IMPORTANT] Disclaimer: This is an unofficial, community-maintained open-source client SDK. It is neither affiliated with, endorsed by, nor maintained by the State Tax Committee of Uzbekistan (DSQ), SIC "Yangi Texnologiyalar", or official E-IMZO service operators.

High-performance, strongly-typed, modern unofficial TypeScript and Node.js Client SDK for Uzbekistan's E-IMZO and E-IMZO-SERVER REST API and Mobile ID-CARD system, featuring first-class NestJS compatibility.

Documentation reference: qo0p/e-imzo-doc.
Compatible Server Docker: 0605AbMu/e-imzo-server (ghcr.io/0605abmu/e-imzo-server:2.2.1).


🌟 Features

  • ⚡ Zero runtime dependencies: Built using standard global fetch (Node.js 18+) and native IEEE 802.3 CRC32 calculation.
  • 🎯 Full API Coverage:
    • Health & Diagnostics: /ping, /info
    • Web Auth & PKCS#7: /frontend/challenge, /backend/auth, /frontend/timestamp/pkcs7, /backend/pkcs7/verify/attached, /backend/pkcs7/verify/detached, /frontend/pkcs7/make-attached, /frontend/pkcs7/join
    • Mobile ID-CARD (E-IMZO Mobile): /frontend/mobile/auth, /frontend/mobile/sign, /frontend/mobile/status, /frontend/mobile/upload, /backend/mobile/authenticate/{DocumentID}, /backend/mobile/verify
  • 🏢 First-Class NestJS Module: Full dynamic module support (EImzoModule.register(...), EImzoModule.registerAsync(...)), inject via EImzoService or @InjectEImzoClient().
  • 🇺🇿 Uzbek OID Helpers: Auto-parsing of PINFL (JSHSHIR - 1.2.860.3.16.1.2), Legal Entity TIN (STIR - 1.2.860.3.16.1.1), Physical Person TIN (UID), organization name, and legal entity detection.
  • 🔑 Key Type Detection: Auto-detects key/token type via paramSetOID (Pfx, IdCard, Baik, Uzguard).
  • 📱 Mobile QR & Deeplink Generator: Built-in IEEE 802.3 CRC32 checksum calculation, QR code generator, and eimzo://sign?qc=... deeplink generator and validator.
  • 📦 Dual ESM & CommonJS: Full compatibility with both import and require(), complete with TypeScript declarations (.d.ts / .d.mts) and sourcemaps.

📦 Installation

# npm
npm install e-imzo-server-client

# pnpm
pnpm add e-imzo-server-client

# yarn
yarn add e-imzo-server-client

🚀 Quick Start (Node.js / TypeScript)

1. Initialize Client

import { EImzoClient } from 'e-imzo-server-client';

const eimzo = new EImzoClient({
  baseUrl: 'http://127.0.0.1:8080/', // E-IMZO-SERVER URL
  defaultHost: 'myportal.gov.uz',    // Required domain registered on E-IMZO
  defaultRealIp: '1.2.3.4',          // Client IP (X-Real-IP)
  timeout: 30000,                    // Timeout in ms (default: 30000)
  throwOnError: true,                // Auto throw EImzoApiException on status != 1
});

// Check server status
const ping = await eimzo.ping();
console.log('Server time:', ping.serverDateTime, 'VPN Key:', ping.vpnKeyInfo?.serialNumber);

2. Web Authentication Flow

// Step 1: Frontend requests a random challenge
const { challenge, ttl } = await eimzo.getChallenge();
console.log(`Sign this challenge: ${challenge} (Valid for ${ttl}s)`);

// Step 2: User signs the challenge via browser E-IMZO plugin, returning pkcs7Base64
const pkcs7Base64 = 'MIAGCSqGSIb3DQEHAqCAMIACAQEx...';

// Step 3: Backend verifies the signature and authenticates user
const auth = await eimzo.authenticate(pkcs7Base64);
const cert = auth.subjectCertificateInfo;

console.log('Full Name:', cert?.commonName);
console.log('PINFL / JSHSHIR:', cert?.pinfl);
console.log('TIN / STIR:', cert?.tin);
console.log('Is Legal Entity:', cert?.isLegalEntity);

3. PKCS#7 Document Verification

// Attached verification (document is embedded inside PKCS#7)
const result = await eimzo.verifyAttached(pkcs7AttachedBase64);
if (result.pkcs7Info?.isAllSignersValid) {
  console.log('Document content Base64:', result.pkcs7Info.documentBase64);
  console.log('Primary signer PINFL:', result.pkcs7Info.primarySigner?.certificate?.pinfl);
}

// Detached verification (signature separated from document)
const detachedResult = await eimzo.verifyDetached(documentBase64, pkcs7DetachedBase64);
console.log('Verified:', detachedResult.pkcs7Info?.isAllSignersValid);

4. Mobile ID-CARD (E-IMZO Mobile)

import { EImzoClient, buildDeepLink, buildQrCode } from 'e-imzo-server-client';

// 1. Initialize mobile auth or sign session
const { siteId, documentId, challenge } = await eimzo.mobileAuth();

// 2. Generate QR code & Deeplink for mobile app
const qrCode = buildQrCode(siteId!, documentId!, challenge!);
const deepLink = buildDeepLink(qrCode); // eimzo://sign?qc=...

console.log('Scan QR Code:', qrCode);
console.log('Open App Deeplink:', deepLink);

// 3. Poll status until user approves on smartphone
let status = await eimzo.getMobileStatus(documentId!);
while (status.isPending) {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  status = await eimzo.getMobileStatus(documentId!);
}

if (status.isCompleted) {
  // 4. Verify authentication on backend
  const verified = await eimzo.mobileAuthenticate(documentId!);
  console.log('Authenticated User PINFL:', verified.subjectCertificateInfo?.pinfl);
}

🦅 NestJS Integration

e-imzo-server-client provides native subpath export e-imzo-server-client/nestjs with first-class dynamic module support.

1. Register Module Synchronously

// app.module.ts
import { Module } from '@nestjs/common';
import { EImzoModule } from 'e-imzo-server-client/nestjs';

@Module({
  imports: [
    EImzoModule.register({
      isGlobal: true, // makes EImzoService available everywhere
      baseUrl: 'http://127.0.0.1:8080',
      defaultHost: 'myportal.gov.uz',
    }),
  ],
})
export class AppModule {}

2. Register Module Asynchronously (with ConfigService)

// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { EImzoModule } from 'e-imzo-server-client/nestjs';

@Module({
  imports: [
    ConfigModule.forRoot(),
    EImzoModule.registerAsync({
      isGlobal: true,
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        baseUrl: config.getOrThrow<string>('EIMZO_SERVER_URL'),
        defaultHost: config.get<string>('EIMZO_DEFAULT_HOST'),
        defaultRealIp: config.get<string>('EIMZO_DEFAULT_REAL_IP'),
        timeout: config.get<number>('EIMZO_TIMEOUT', 30000),
      }),
    }),
  ],
})
export class AppModule {}

3. Inject in Services or Controllers

You can inject EImzoService directly, or use the @InjectEImzoClient() decorator:

// auth.service.ts
import { Injectable } from '@nestjs/common';
import { EImzoService, InjectEImzoClient } from 'e-imzo-server-client/nestjs';
import { EImzoClient } from 'e-imzo-server-client';

@Injectable()
export class AuthService {
  constructor(
    // Option A: Inject EImzoService (inherits all EImzoClient methods)
    private readonly eimzoService: EImzoService,

    // Option B: Inject interface with decorator
    @InjectEImzoClient() private readonly client: EImzoClient,
  ) {}

  async authenticateUser(pkcs7Base64: string) {
    const auth = await this.eimzoService.authenticate(pkcs7Base64);
    const cert = auth.subjectCertificateInfo;

    return {
      pinfl: cert?.pinfl,
      stir: cert?.tin,
      fullName: cert?.commonName,
      isLegalEntity: cert?.isLegalEntity,
    };
  }
}

🇺🇿 Uzbek Certificate OID Reference

SubjectCertificateInfo automatically parses standard Uzbek X.509 OIDs:

| Property | OID / Key | Description | Example | | :--- | :--- | :--- | :--- | | pinfl | 1.2.860.3.16.1.2 | 14-digit JSHSHIR / PINFL | 30101900000001 | | legalEntityTin | 1.2.860.3.16.1.1 | 9-digit Legal Entity STIR / INN | 123456789 | | physicalPersonTin | UID | 9-digit Physical Person STIR / INN | 400000000 | | tin | Fallback | Legal entity STIR if present, else physical person TIN | 123456789 | | commonName | CN | Full Name of Certificate Holder | ALIEV VALI KARIMOVICH | | organization | O | Company / Enterprise Name | OOO "ENTERPRISE" | | isLegalEntity | Computed | true if legalEntityTin is present | true / false | | isPhysicalPerson | Computed | true if individual certificate | true / false |


⚠️ Error Handling & Status Codes

When throwOnError: true (default), any response where status !== 1 throws EImzoApiException.

import { EImzoClient, EImzoApiException, EImzoStatusCode } from 'e-imzo-server-client';

try {
  await eimzo.authenticate(pkcs7);
} catch (error) {
  if (error instanceof EImzoApiException) {
    console.error('Error status code:', error.status);
    console.error('API Endpoint:', error.endpoint);
    console.error('Message:', error.message);

    if (error.status === EImzoStatusCode.ChallengeNotFoundOrExpired) {
      // Challenge has expired
    } else if (error.status === EImzoStatusCode.SignatureInvalid) {
      // Signature is invalid
    }
  }
}

📄 License

This project is licensed under the MIT License.