# Use the Node.js / TypeScript SDK

**Applies to:** current development source bundles. Obtain a matched client/server release through [early-access support](mailto:info@simplemagic.com); registry publication is not available yet. Paths below are relative to the supplied source checkout.

Promise-based TCP client for Node.js 22+, with TypeScript declarations and no
runtime dependencies. This first release has not been published to npm.

## Install and use

From an application next to this checkout: `npm install ../smkv/node-smkv`.
The package is ESM; use `import` or dynamic `import()` from CommonJS.

```javascript
import {Client} from '@simplemagic/smkv';

const client = new Client('127.0.0.1:7379', {poolSize: 4, timeoutMs: 5000});
try {
  await client.put(Buffer.from('greeting'), Buffer.from('hello'),
                   {sync: true, ttlMs: 60000});
  console.log(await client.get(Buffer.from('greeting')));
  const users = client.table('users');
  await users.put(Buffer.from('42'), {name: 'Ada', visits: 1n});
  await users.update(Buffer.from('42'), {visits: 2n});
  console.log(await users.get(Buffer.from('42'), ['name']));
} finally {
  client.close();
}
```

Run `node node-smkv/examples/basic.mjs 127.0.0.1:7379` against a disposable node.
Keys/values are `Uint8Array` or Buffer; reads return Buffer. Column values are
bytes, string, boolean, **bigint for int64**, or **number for float64**. Decoded
columns have a null prototype; use `Object.hasOwn` to test membership.

## Cluster and security

```javascript
import {ClusterClient} from '@simplemagic/smkv';
const cluster = await ClusterClient.connect(['127.0.0.1:7381']);
try {
  console.log(await cluster.get(Buffer.from('greeting')));
  // Explicitly permits stale reads:
  console.log(await cluster.getReplica(Buffer.from('greeting')));
} finally { cluster.close(); }
```

Seeds are **management** endpoints. `refresh()` updates discovery and `topology`
returns a copy. Epochs above JavaScript's safe integer range are rejected.

Data `security` and `managementSecurity` are configured independently. Plaintext
and no authentication are defaults. For TLS, pass `security: {tls: {ca: pem},
credential: {name, token}}`; load PEM and credentials from files/your secret provider.
TLS always verifies the certificate and endpoint hostname/IP. Optional `servername`
overrides the verification name. Verification cannot be disabled; no downgrade.

## Deadlines and error handling

Defaults: four connections per node, five-second operation and idle timeouts,
1 KiB keys and 1 MiB values. Set `poolSize`, `timeoutMs`, `idleTimeoutMs`,
`maxKeyBytes`, or `maxValueBytes` to match your server. Per-operation `timeoutMs`
can shorten the total deadline; `signal` accepts AbortSignal. Pool wait is included.
`close()` aborts active requests and closes all connections.

Writes accept `sync`, `replicaAck`, and `durableReplicaAck`. Defaults do not
request per-write disk synchronization. `ttlMs` accepts a safe integer or bigint;
omitted means no expiry for put and preserves expiry for update, zero expires
immediately. Delete does not accept TTL. Table `update(key, setColumns, remove)`
is atomic; `get(key, columns)` supports projection.

`SmkvError.code` identifies errors (`not_found` differs from an empty value).
`status` contains the server status when present. `outcomeUnknown` means a mutation
may have completed, including after cancellation. Do not blindly replay it.
Cluster retries are limited to explicit `wrong_owner` responses, within the original
deadline. Other failures return to the caller.

Scans, batch operations, and browser connections are not included in this release.
See [shared contract](sdk-clients.html) and [tests](sdk-clients.html#initial-release-limits).

## Logical databases

Select the database when constructing the client (or cluster client):

```javascript
new Client("127.0.0.1:7379", {database: "orders"})
```

Omitting the option uses `default` and preserves existing wire keys. Named
databases require database-aware development servers (cluster protocol 5, or 6
with experimental group sync). Names use 1–64 ASCII letters, digits, `_` or `-`.
The selection scopes raw keys and all table operations, including replica reads.
The complete database-prefixed key is hashed for routing and counts against the
key-size limit. Databases share cluster capacity and durability settings.
