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

@omega-edit/client

v2.0.0

Published

OmegaEdit gRPC Client

Readme

npm Release Build Status FOSSA Status

TypeScript/Node.js client for Ωedit™ - a library for building editors that can handle massive files with multiple viewports, full undo/redo, and byte-level precision.

Batteries included - this package bundles the native gRPC server via its dependency on @omega-edit/server. No separate server install is needed.

Install

npm install @omega-edit/client
# or
yarn add @omega-edit/client

Quick Start

import {
  startServer,
  getClient,
  createSession,
  insert,
  saveSession,
  destroySession,
  stopServerGraceful,
  IOFlags,
} from '@omega-edit/client'

// 1. Start the bundled gRPC server
const pid = await startServer(9000)

// 2. Connect a client
const client = await getClient(9000)

// 3. Create a session (optionally backed by an existing file)
const sessionResp = await createSession()
const sessionId = sessionResp.getSessionId()

// 4. Make edits
await insert(sessionId, 0, new TextEncoder().encode('Hello, Ωedit™!'))

// 5. Save to disk
await saveSession(sessionId, '/tmp/hello.txt', IOFlags.OVERWRITE)

// 6. Clean up
await destroySession(sessionId)
await stopServerGraceful()

API Overview

Server Lifecycle

| Function | Description | | ------------------------------------------------- | ----------------------------------------- | | startServer(port?, host?, pidFile?, heartbeat?) | Start the bundled native gRPC server | | startServerUnixSocket(socketPath, ...) | Start using a Unix domain socket | | stopServerGraceful() | Graceful shutdown, returning status info | | stopServerImmediate() | Immediate shutdown, returning status info | | getServerInfo() | Runtime metadata for the native server | | getServerHeartbeat(sessions) | Heartbeat and process health | | startServerHeartbeatLoop(options) | Managed liveness heartbeat loop |

startServer(..., heartbeat) and startServerUnixSocket(..., heartbeat) accept the same HeartbeatOptions bag exported from @omega-edit/server, including native logging fields such as logFile, logLevel, and logConfigFile.

Shutdown migration note:

  • In the 2.x line, stopServerGraceful() and stopServerImmediate() return a structured result object with responseCode, serverProcessId, and status instead of returning only a numeric response code.
  • In the 2.x line, @omega-edit/client treats all int64-backed public values as JavaScript safe integers. Unsafe inputs are rejected before RPCs are sent, and unsafe outputs are rejected instead of being silently rounded.
  • In the 2.x line, autogenerated IDs are opaque. New sessions get sess_<uuidv7> IDs, autogenerated viewports get <sessionId>:vp_<uuidv7> IDs, and applications should treat both as server-issued handles rather than decoding semantics from the string value.
  • In the 2.x line, ChangeKind only exposes UNSPECIFIED, DELETE, INSERT, and OVERWRITE. The old CHANGE_* and CHANGE_KIND_* aliases were removed.
  • In the 2.x line, top-level enum exports use one short-name style only. Use names like IOFlags.OVERWRITE, CountKind.VIEWPORTS, ServerControlKind.GRACEFUL_SHUTDOWN, ServerControlStatus.COMPLETED, SessionEventKind.EDIT, and ViewportEventKind.EDIT; the older prefixed aliases were removed.

Server Health API Migration

getServerInfo() and getServerHeartbeat() now expose native-runtime metadata instead of JVM-shaped placeholders. The client-facing TypeScript API is renamed, while the protobuf layer keeps the legacy fields for wire compatibility.

Design rule:

  • Heartbeat is the only expected polling loop in a healthy OmegaEdit client.
  • Use SubscribeToSessionEvents and SubscribeToViewportEvents to keep UI state, computed file size, and viewport contents current.
  • If you are polling session or viewport state in steady-state operation, you are working around the design incorrectly and should fix the integration to consume subscriptions instead.

Current getServerInfo() fields:

  • serverHostname
  • serverProcessId
  • serverVersion
  • runtimeKind
  • runtimeName
  • platform
  • availableProcessors
  • compiler
  • buildType
  • cppStandard

Current getServerHeartbeat() fields:

  • latency
  • sessionCount
  • serverTimestamp
  • serverUptime
  • serverCpuCount
  • serverCpuLoadAverage?
  • serverResidentMemoryBytes?
  • serverVirtualMemoryBytes?
  • serverPeakResidentMemoryBytes?

startServerHeartbeatLoop() builds the sanctioned recurring heartbeat pattern on top of getServerHeartbeat(sessionIds): it starts immediately by default, skips overlapping heartbeats, and routes results and errors through callbacks so integrations do not need to hand-roll their own timer logic.

Migration notes:

  • getServerHeartbeat() is now strictly getServerHeartbeat(sessionIds). The old extra hostname / PID / interval-style arguments are removed in 2.x.
  • jvmVersion, jvmVendor, and jvmPath were removed from the client-facing TypeScript API. Use runtimeKind, runtimeName, platform, and compiler instead.
  • serverMaxMemory, serverCommittedMemory, and serverUsedMemory were removed from the client-facing TypeScript API. They were JVM-heap concepts and are now replaced with process-memory metrics.
  • Optional heartbeat fields may be undefined when the host platform cannot report them. Treat missing values as "unavailable", not zero.
  • serverVirtualMemoryBytes is intentionally best-effort and may be omitted on platforms where the available process metric is not semantically comparable.

Client Connection

| Function | Description | | --------------------------------- | ----------------------------------------------- | | getClient(port?, host?) | Get or create a gRPC client connection | | waitForReady(client, deadline?) | Block until the server is accepting connections | | resetClient() | Tear down the current client connection |

Sessions

| Function | Description | | ------------------------------------------------------------------------- | ------------------------------ | | createSession(filePath?, sessionId?, checkpointDir?) | Open an editing session | | createSessionFromBytes(data, sessionId?, checkpointDir?) | Open a session from bytes | | destroySession(sessionId) | Close and discard a session | | saveSession(sessionId, path, flags?, offset?, length?) | Save session content to a file | | getComputedFileSize(sessionId) | Logical file size after edits | | getSegment(sessionId, offset, length) | Read a byte range | | getSessionBytes(sessionId, offset?, length?) | Read session bytes in memory | | getSessionCount() | Number of active sessions | | pauseSessionChanges(sessionId) / resumeSessionChanges(sessionId) | Pause/resume change tracking | | runSessionTransaction(sessionId, work) | Run scoped atomic edit work | | beginSessionTransaction(sessionId) / endSessionTransaction(sessionId) | Group edits atomically |

Subscription-first guidance:

  • getComputedFileSize(sessionId) is a direct snapshot RPC, not a steady-state synchronization mechanism.
  • Long-lived clients should treat subscribeSessionEvents(...) as the authoritative source for computed file size and other session-derived state.
  • Long-lived viewport consumers should treat subscribeViewportEvents(...) as the authoritative source for viewport invalidation and refresh timing.
  • Prefer runSessionTransaction(...) over hand-managed beginSessionTransaction(...) / endSessionTransaction(...) pairs so transaction scope is enforced in one function.
  • Outside of heartbeat, polling is a design smell. If a consumer needs repeated polling to stay correct, the right fix is to expose or consume the relevant event stream.

Subscriptions

| Function | Description | | ----------------------------------------------------------------------- | ----------------------------- | | subscribeSessionEvents({ sessionId, interest?, onEvent, onError? }) | Managed session event stream | | subscribeViewportEvents({ viewportId, interest?, onEvent, onError? }) | Managed viewport event stream |

These helpers wrap the raw server-stream subscriptions and own the repetitive parts of integration:

  • building the subscription request
  • attaching data and error handlers
  • ignoring expected cancel/reset shutdown noise
  • routing callback failures through onError
  • exposing a simple cancel() handle for teardown

Use them instead of wiring raw gRPC streams by hand in application code.

Editor Integration Helpers

These higher-level helpers sit on top of the session, viewport, and subscription primitives for editor-style applications:

| Helper | Description | | --------------------------- | ---------------------------------------------------------------------------- | | EditorHistoryController | Tracks local vs checkpoint-backed undo/redo and save-state semantics | | EditorSearchController | Owns bounded-vs-large search mode and routes replace-all strategies | | EditorSessionModel | Tracks computed file size, change count, viewport identity, and sync waiters | | ScopedEditorSessionHandle | Opens a session, owns viewport lifecycle and subscriptions, and cleans up |

These are especially useful for front-ends such as VS Code extensions that want to stay subscription-first without rebuilding the same session/search/history bookkeeping in each integration.

Editing

| Function | Description | | ------------------------------------------------------- | --------------------------------- | | insert(sessionId, offset, data) | Insert bytes at an offset | | del(sessionId, offset, length) | Delete a byte range | | overwrite(sessionId, offset, data) | Overwrite bytes at an offset | | replace(sessionId, offset, removeLen, replacement) | Remove + insert in one operation | | undo(sessionId) / redo(sessionId) | Unlimited undo/redo | | clear(sessionId) | Undo all changes | | getLastChange(sessionId) | Details of the most recent change | | getChangeCount(sessionId) / getUndoCount(sessionId) | Change and undo stack depth |

Viewports

| Function | Description | | ----------------------------------------------------------------------- | -------------------------------------------- | | createViewport(viewportId?, sessionId, offset, capacity, isFloating?) | Create a window into the data | | modifyViewport(viewportId, offset, capacity, isFloating?) | Move or resize a viewport | | destroyViewport(viewportId) | Remove a viewport | | getViewportData(viewportId) | Read the current viewport content | | viewportHasChanges(viewportId) | Check if content has changed since last read | | getViewportCount(sessionId) | Number of active viewports |

Search & Profile

  • searchSession(...) - forward and reverse byte-pattern search
  • replaceSession(...) - search-and-replace across the session
  • profileSession(...) - byte-frequency profiling and line-ending detection

Logging

import { createSimpleFileLogger, setLogger } from '@omega-edit/client'

setLogger(createSimpleFileLogger('/tmp/omega-edit.log', 'debug'))

Package Format

Distributed as both ESM and CommonJS with full TypeScript source maps and declaration files. Internally, the package now uses protobuf-ts for native ESM-friendly generated bindings instead of the old jspb runtime bridge.

| Output | Path | Format | | ----------- | ----------------- | --------------------------------- | | ESM | dist/esm/ | ES2020 module syntax (ES6 target) | | CJS | dist/cjs/ | CommonJS | | Types | dist/esm/*.d.ts | TypeScript declarations | | Source Maps | dist/**/*.map | Embedded TypeScript sources |

Environment Variables

| Variable | Default | Description | | ----------------------------- | ----------- | --------------------- | | OMEGA_EDIT_SERVER_HOST | 127.0.0.1 | Server bind address | | OMEGA_EDIT_SERVER_PORT | 9000 | Server port | | OMEGA_EDIT_SERVER_LOG_CONFIG | - | Native server logback-style XML config | | OMEGA_EDIT_SERVER_LOG_FILE | - | Native server log file | | OMEGA_EDIT_SERVER_LOG_LEVEL | - | Native server log level | | OMEGA_EDIT_CLIENT_LOG_LEVEL | - | Client-side log level |

Examples

See the examples/typescript/ directory for runnable TypeScript examples covering editing, search/replace, viewports, data profiling, and record/replay.

Development

See DEVELOPMENT.md for build, test, and contribution instructions.

Documentation

Full documentation is published at https://ctc-oss.github.io/omega-edit/.

Versioning

Ωedit™ follows Semantic Versioning.

License

Apache 2.0 - see LICENSE.txt.

FOSSA Status