js390
v1.1.2
Published
Pure TypeScript DB2 for z/OS client library for Node v20+ and Bun
Maintainers
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 js390Quick 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 connectioncreatePool()for pooled accessconn.query()for result-returning SQLconn.execute()for INSERT, UPDATE, DELETE, and DDLconn.prepare()for repeated execution and streamingconn.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.
