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

js390

v1.1.2

Published

Pure TypeScript DB2 for z/OS client library for Node v20+ and Bun

Readme

js390

js390 is a pure TypeScript DB2 for z/OS client library for Node.js and Bun. It talks to DB2 directly over the wire protocol and is designed as a small, dependable application driver with no native bindings and no external runtime dependencies.

Install

npm install js390
# or
bun add js390

Quick start

import { connect } from 'js390'

const conn = await connect({
  host: 'mainframe.example.com',
  user: 'MYUSER',
  password: 'mypassword',
  database: 'DSNLOC'
})

const rows = await conn.query(
  'SELECT ID, NAME, EMAIL FROM APP.CUSTOMERS WHERE STATUS = ?',
  ['ACTIVE']
)

console.log(rows)

await conn.close()

What js390 provides

  • direct DB2 for z/OS connectivity from Node.js 20+ and Bun
  • simple queries and parameterized SQL
  • prepared statements
  • batch execution
  • async streaming for large result sets
  • transactions and savepoints
  • connection pooling
  • schema and catalog metadata helpers
  • TLS support
  • zero runtime dependencies

How it works with DB2

js390 opens a TCP or TLS connection to a DB2 for z/OS server, signs in with a user profile, and then runs SQL statements directly against the target database. For read workloads it can fetch rows in blocks or stream them incrementally. For write workloads it supports parameter binding, prepared execution, and batch submission for higher-throughput inserts and updates.

At the application level, the main pieces are:

  • connect() for a single connection
  • createPool() for pooled access
  • conn.query() for result-returning SQL
  • conn.execute() for INSERT, UPDATE, DELETE, and DDL
  • conn.prepare() for repeated execution and streaming
  • conn.getMetaData() for catalog discovery

Main docs

Current scope

js390 is focused on application-facing DB2 access for z/OS:

  • core SELECT, INSERT, UPDATE, DELETE, and DDL flows
  • prepared statements and repeated execution
  • connection pools and transaction control
  • metadata reads from system catalog tables

Areas that are intentionally small or still evolving are documented in docs/feature-matrix.md.

Example: connection pool

import { createPool } from 'js390'

const pool = createPool({
  host: 'mainframe.example.com',
  user: 'MYUSER',
  password: 'mypassword',
  database: 'DSNLOC',
  max: 10,
})

const rows = await pool.query(
  'SELECT DEPTNO, COUNT(*) AS TOTAL FROM APP.EMP GROUP BY DEPTNO'
)

console.log(rows)

await pool.close()

Example: prepared statement and batch execution

const stmt = await conn.prepare(
  'INSERT INTO APP.EVENT_LOG (EVENT_ID, EVENT_TYPE, CREATED_AT) VALUES (?, ?, ?)'
)

const result = await stmt.executeBatch([
  ['evt-1', 'LOGIN', '2026-05-28-10.15.00'],
  ['evt-2', 'LOGOUT', '2026-05-28-10.16.00'],
])

console.log(result.totalAffected)

await stmt.close()

Example: streaming rows

const stmt = await conn.prepare(
  'SELECT ID, NAME, EMAIL FROM APP.CUSTOMERS WHERE STATUS = ?'
)

for await (const row of stmt.stream(['ACTIVE'])) {
  console.log(row)
}

await stmt.close()

Known limitations

The following features are not yet implemented. They are listed roughly by priority — items near the top are more likely to affect typical workloads.

| Area | What's missing | Notes | |------|---------------|-------| | Stored procedures | call() sends IN parameters but does not return OUT/INOUT values or multiple result sets | Most production stored procedures return values — this is the largest functional gap | | LOB locators | LOBs are always fully materialized in memory; no server-side locator handles | Large LOBs can cause out-of-memory; no progressive streaming | | Scrollable cursors | Cursors are forward-only; no absolute(), relative(), or backward navigation | Pagination and data-grid patterns require application-level workarounds | | Client reroute | Single host:port only; no automatic failover to alternate servers | HA / Sysplex environments need manual reconnect logic | | XA / distributed transactions | No two-phase commit, no XA resource interface | Limits js390 to single-database transaction scope | | Positioned UPDATE/DELETE | No cursor names; cannot use WHERE CURRENT OF | Legacy cursor-update patterns are unsupported | | Kerberos authentication | Only cleartext password (SECMEC 3); no SECMEC 11 / GSS-API | Blocks deployment in Kerberos-only environments | | UDT / ARRAY types | DISTINCT type metadata is discarded; no ARRAY, ROW, or CURSOR type support | DISTINCT types still work (same wire format as base type) | | Token authentication | No SECMEC 15 (plugin) or SECMEC 19 (OAuth/JWT token) | Relevant for cloud/hybrid access patterns | | LZ4 compression | All data transferred uncompressed | Affects throughput on high-latency or bandwidth-limited links | | Auto package binding | Requires external DB2Binder tool to bind CLI packages before first use | One-time setup step; documented in the project wiki |

Trademark notice

IBM, DB2, z/OS, and related marks are trademarks or registered trademarks of International Business Machines Corporation in the United States and/or other countries.