npm.io
1.4.0 • Published 4d ago

zmodem2

Licence
MIT
Version
1.4.0
Deps
0
Size
490 kB
Vulns
0
Weekly
358

zmodem2-js

Notice:

This project is a JavaScript/TypeScript port of the zmodem2 Rust crate. Part of the code was generated by KiloCode's GLM5 model (z.ai).

All credit goes to the original author, Jarkko Sakkinen.

中文文档 | English

A modern ZMODEM file transfer protocol library for JavaScript/TypeScript. This library provides stream-like state machines for sending and receiving files with the ZMODEM protocol, suitable for both Node.js and browser environments.

Features

  • Cross-platform: Works in Node.js and browser environments
  • TypeScript native: Full TypeScript support with declaration files
  • Multiple module formats: ESM, CommonJS, and bundled versions
  • Tree-shakeable: ESM output supports tree shaking for optimal bundle sizes
  • Zero runtime dependencies: Lightweight and self-contained
  • Streaming API: Efficient handling of large files through streaming operations

Installation

npm install zmodem2

Module Formats

This package provides multiple output formats to suit different use cases:

Format Path Description
ESM dist/esm/ ES modules, tree-shakeable, no bundled dependencies
CommonJS dist/cjs/ CommonJS modules, no bundled dependencies
CommonJS Full dist/cjs-full/ CommonJS bundle with all code in a single file
Browser dist/browser/ IIFE format for direct browser usage

Usage

For use with modern bundlers (webpack, rollup, vite, etc.) that support tree shaking:

import { Sender, Receiver, ZmodemError } from 'zmodem2'

// Create a sender for file transfer
const sender = new Sender()

// Create a receiver for file reception
const receiver = new Receiver()
CommonJS - Node.js

For Node.js environments using require():

const { Sender, Receiver, ZmodemError } = require('zmodem2')

// Create a sender for file transfer
const sender = new Sender()

// Create a receiver for file reception
const receiver = new Receiver()
CommonJS Full Bundle - Node.js (All-in-one)

For environments where you want all code bundled in a single file:

const zmodem2 = require('zmodem2/cjs-full')

const { Sender, Receiver } = zmodem2

// Use Sender and Receiver
const sender = new Sender()
Browser (IIFE/UMD)

For direct browser usage without a bundler:

<script src="node_modules/zmodem2/dist/browser/zmodem2.min.js"></script>
<script>
  // Global variable: Zmodem2
  const sender = new Zmodem2.Sender()
  const receiver = new Zmodem2.Receiver()
</script>

Or via CDN:

<script src="https://unpkg.com/zmodem2/dist/browser/zmodem2.min.js"></script>

API Overview

Core Classes
Sender

Handles sending files via ZMODEM protocol.

const sender = new Sender()

// Get bytes to send over the wire
const outgoingBytes = sender.drainOutgoing()

// After writing bytes, advance the state
sender.advanceOutgoing()

// Feed incoming bytes from the remote
sender.feedIncoming(bytes)

// Send a file
const fileRequest = sender.pollFile()
if (fileRequest) {
  sender.feedFile(fileData)
}

// Check for events
const event = sender.pollEvent()
Receiver

Handles receiving files via ZMODEM protocol.

const receiver = new Receiver()

// Get bytes to send over the wire
const outgoingBytes = receiver.drainOutgoing()

// After writing bytes, advance the state
receiver.advanceOutgoing()

// Feed incoming bytes from the remote
receiver.feedIncoming(bytes)

// Receive file data
const fileBytes = receiver.drainFile()
if (fileBytes) {
  // Write to storage
  receiver.advanceFile()
}

// Check for events
const event = receiver.pollEvent()
Events

Both Sender and Receiver emit events through pollEvent():

enum SenderEvent {
  Ready = 'ready',
  FileRequest = 'fileRequest',
  Sent = 'sent',
  Error = 'error',
  Complete = 'complete'
}

enum ReceiverEvent {
  Ready = 'ready',
  FileStart = 'fileStart',
  FileData = 'fileData',
  FileEnd = 'fileEnd',
  Error = 'error',
  Complete = 'complete'
}
Error Handling
import { ZmodemError, NotConnectedError, ReadError, WriteError } from 'zmodem2'

try {
  // ZMODEM operations
} catch (error) {
  if (error instanceof ZmodemError) {
    console.error('ZMODEM error:', error.message)
  }
}
Constants and Utilities
import {
  // Constants
  ZPAD, ZDLE, XON,
  SUBPACKET_MAX_SIZE, SUBPACKET_PER_ACK,
  
  // CRC utilities
  crc16Xmodem, crc32IsoHdlc,
  Crc16, Crc32,
  
  // ZDLE encoding
  ZDLE_TABLE, UNZDLE_TABLE,
  escapeByte, unescapeByte,
  
  // Header types
  Encoding, Frame,
  Zrinit, Header,
  decodeHeader, createZrinit
} from 'zmodem2'

TypeScript Support

This package includes TypeScript declaration files. No additional @types/ package is needed.

import {
  Sender,
  Receiver,
  SenderEvent,
  ReceiverEvent,
  FileRequest,
  ZmodemError
} from 'zmodem2'

const sender: Sender = new Sender()
const event: SenderEvent | null = sender.pollEvent()

Building from Source

# Clone the repository
git clone https://github.com/zxdong262/zmodem2-js.git
cd zmodem2-js

# Install dependencies
npm install

# Build all formats
npm run build

# Build specific format
npm run build:esm    # ESM only
npm run build:cjs    # CommonJS only
npm run build:types  # Declaration files only
Build Output Structure
dist/
  esm/           # ES modules (tree-shakeable)
    index.js
    index.d.ts
    ...
  cjs/           # CommonJS modules
    index.cjs
    index.d.ts
    ...
  cjs-full/      # Bundled CommonJS
    index.cjs
    index.d.ts
  browser/       # Browser bundle
    zmodem2.js
    zmodem2.min.js
    index.d.ts

Testing

# Run unit tests
npm test

# Run integration tests
npm run test:upload
npm run test:download

# Watch mode
npm run test:watch

License

MIT License - see LICENSE for details.

Demo

This project includes a demo application to showcase ZMODEM file transfer functionality. The demo consists of:

  • Demo Server: A Node.js server in src/server/index.mjs that provides WebSocket connections for terminal emulation and ZMODEM file transfers
  • Demo Client: A React-based web client in src/client/ that provides a terminal interface with ZMODEM support
Running the Demo
  1. Install dependencies (if not already installed):

    npm install
  2. Configure SSH connection: Create a .env file in the project root with your SSH connection details:

    TEST_HOST=localhost
    TEST_PORT=22
    TEST_USER=your-username
    TEST_PASS=your-password
    # Or use SSH key
    # TEST_KEY_PATH=/path/to/your/ssh/key
  3. Start the demo:

    npm start

    This will start both the demo server and the development server for the client.

  4. Access the demo: Open your browser and navigate to http://localhost:5173 to access the demo client.

Demo Features
  • Terminal Emulation: Full terminal emulation through SSH connection
  • ZMODEM File Transfer: Support for both sending and receiving files using ZMODEM protocol
  • WebSocket Communication: Real-time communication between client and server
  • WASM Support: Uses WebAssembly for high-performance CRC calculations
Demo Server Code

The demo server code is located in src/server/index.mjs and provides:

  • WebSocket endpoint for terminal connections
  • SSH connection management
  • Logging functionality
  • CORS support for cross-origin requests
Demo Client Code

The demo client code is located in src/client/ and includes:

  • React-based terminal interface using xterm.js
  • ZMODEM addon for file transfer functionality
  • WebSocket client for communication with the server
  • File selection dialog for sending files
  • zmodem2-wasm - WebAssembly implementation for high-performance CRC calculations
  • electerm - Terminal app with ZMODEM support which uses this library for ZMODEM file transfers

Keywords