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

@mochabug/adapt-builder

v2.0.0-beta.12

Published

Build adapt apps for versioned runtime profiles

Downloads

1,355

Readme

@mochabug/adapt-builder

Builds Mochabug Adapt apps for the selected runtime and browser. Owns the native runtime TypeScript declarations; Adaptkit scaffolds projects and the SDK provides application APIs and routers. Requires Node.js 22.12.0 or newer.

npm install -D @mochabug/adapt-builder
npx adapt-builder build            # production
npx adapt-builder build --staging
npx adapt-builder build --staging -o YOUR_ORGANIZATION_ID
npx adapt-builder build --emulate
npx adapt-builder dev              # Vite development server

The optional -o, --organization <id> override is only allowed with --staging. It sets the organization used in browser CDN URLs and upload.json in memory, leaving manifest.json unchanged. Adaptkit 2.0.0-beta.3 or newer reads the staging organization from upload.json and applies it to the uploaded manifest when you run adaptkit publish --staging.

Project and type boundaries

Adaptkit creates this layout; no build config is required:

manifest.json
runtime.json
README.md
tsconfig.json                # solution referencing the three projects below
tsconfig.runtime.json        # runtime entries and their imports
tsconfig.browser.json        # ui/ and ui_shared/, excluding SSG and tests
tsconfig.tools.json          # local configuration, SSG, tests, and scripts
src/<vertex>/
  vertex.json
  metadata.json
  executor.ts
  configurator.ts            # when enabled
  ui/<role>.html
  ui/<role>.main.ts
  ui/<role>.ssg.ts           # optional static rendering

| TypeScript project | lib | types | | --- | --- | --- | | Runtime | ES2024, DOM, DOM.Iterable | @mochabug/adapt-builder/runtime (includes Node 24) | | Browser | ES2024, DOM, DOM.Iterable | vite/client | | Host tools / SSG | ES2024, DOM, DOM.Iterable | node, vite/client |

Adaptkit scaffolds the project configuration. The root holds shared compiler options and references the browser, runtime, and local tools projects. Environment settings and source patterns belong to those project-owned configs. Tools also cover SSG, tests, and local scripts; DOM-dependent tests still need their test runner's DOM environment.

Install vite and @types/node directly when using the browser/tools configs; Adaptkit does this. Browser types come from TypeScript and Vite. Backend types are explicit imports from @mochabug/adapt-builder/runtime; the SDK adds no ambient types. Shared sources are checked in every environment that imports them. Runtime checking starts from src/**/executor.* and src/**/configurator.*; imported helpers are checked transitively. Keep backend imports out of browser code; exclude cannot hide an import.

Standard Fetch types, including HeadersInit, come from TypeScript's DOM library, as required by Connect RPC. Use the same runtime project for server rendering. DOM declarations also make browser globals visible to TypeScript; they do not provide window or document in the runtime. Keep browser API use in browser code. Native declarations add no standard global aliases and also support Node-only consumers that do not need DOM-dependent libraries.

Import HttpHeadersInit for native HTTP stream headers; it additionally accepts array-valued records for repeated headers. Node HTTP server requests expose optional request.mochabug with env: unknown and ctx.waitUntil(). Narrow the environment before accessing its bindings. Scaffolded projects use skipLibCheck: true: application code stays strict and uses dependency types, while declaration files are not checked themselves. They also check unused locals and parameters, indexed access, index-signature property access, return completeness, switch fallthrough, and side-effect imports.

The builder checks tsconfig.json and all referenced projects before replacing output. An absent config skips semantic checking. Errors fail the build with file/line diagnostics. Scaffolded environment configs set tsBuildInfoFile to keep native build caches in node_modules/.cache/typescript, with no root-level .tsbuildinfo files or additional Git ignore rule.

Runtime, browser, and SSG builds default Rolldown's checks.moduleLevelDirective to false. Adapt emits final application bundles and rendered HTML, without React Server Component directive boundaries, so these warnings are not useful here. This disables the whole module-directive warning category, including directives other than "use client", without changing output. Other warning categories and build errors remain visible through configured logging hooks. Projects can explicitly set the check to true in runtime.rolldown, browser.vite.build.rolldownOptions, or ssg.vite.build.rolldownOptions.

Runtime programs and exports

runtime.json groups vertices into programs. Every vertex belongs to one executor; a configurator-capable vertex also belongs to one configurator.

{
  "executors": [{
    "vertices": ["echo"],
    "runtime": { "runtime": "js_1.0", "jsCompatibility": "node24" },
    "maxMemoryMb": 64,
    "wallTimeSec": 30,
    "cpuTimeMs": 100
  }],
  "configurators": []
}

Each definition becomes a separate role-specific entry in one ESM graph. js_1.0 + node24 selects Rolldown's Node platform and Node 24 target. Unsupported profiles fail. Package dependencies are bundled; Node built-ins and mb:* imports remain native. Shared chunks and copied resources are flat modules.

Role sources export handlers matching their vertex's capabilities:

| Export | Handler | Role | | --- | --- | --- | | internal_http | http(stream, env, ctx) | Required lifecycle endpoint for both roles | | external_http | http(stream, env, ctx) | Executor HTTP, or configurator | | external_connect | connect(socket, env, ctx) | Executor TCP | | external_datagram | datagram(socket, env, ctx) | Executor QUIC datagrams |

In src/echo/executor.ts, these complete external handlers implement HTTP health checks and TCP/datagram echo. Export only those enabled by vertex.json:

// executor.ts
import type { ExecutorEnvironment, ExportedHandler } from '@mochabug/adapt-builder/runtime';

export const external_http = {
  async http(stream) {
    if (stream.method !== 'GET' || stream.path !== '/health') {
      await stream.respond({ status: 404 }).end();
      return;
    }
    await stream.respond({ headers: { 'content-type': 'application/json' } }).json({ ok: true });
  },
} satisfies ExportedHandler<ExecutorEnvironment>;

export const external_connect = {
  async connect(socket) {
    await socket.readable.pipeTo(socket.writable);
  },
} satisfies ExportedHandler<ExecutorEnvironment>;

export const external_datagram = {
  async datagram(socket) {
    for (;;) {
      const packet = await socket.receive();
      if (packet === null) return;
      await socket.send(packet);
    }
  },
} satisfies ExportedHandler<ExecutorEnvironment>;

The runtime injects the role-specific env and ctx. Use ExportedHandler<ConfiguratorEnvironment> for configurators. env.assets exposes .fetch(); env.httpproxy, env.plugin, env.fileforge, and the role's env.executor or env.configurator expose .http(). ctx.waitUntil() registers background work. Await the full session inside TCP/datagram handlers: returning ends the incoming session.

internal_http must implement the platform lifecycle protocol. The SDK supplies createIERouter() for executors and createICRouter() for configurators; Adaptkit scaffolds them. See the SDK router examples. Configurator sources have exactly internal_http and external_http. The builder prefixes exports with the vertex name, for example echo_external_connect and echo_external_datagram.

Outbound connections

mb:http exports http, mb:connect exports raw TCP connect, and mb:datagram exports QUIC datagram. Each module has one named export. Call them from an active handler and await the work; connections belong to that request.

HTTP calls take a URL and optional method, headers, signal, and protocol preferences. The returned exchange owns the upload: use end(body), write(), or writable. Both env.service.http(url, options) and http(url, options) snapshot request metadata synchronously and start I/O only when the exchange is used. Supplied signals retain their identity and cancel the entire exchange, including response streaming. Upload and response progress independently, so read response while an upload is pending when handling an early server response. Direct http(url, options) calls derive the destination and TLS from HTTP/HTTPS URLs. Use options.endpoint only to dial a different address while retaining the URL's HTTP authority and TLS hostname. insecure overrides TLS without changing the port. Environment bindings retain their configured destination and transport; proxy bindings use the target URL's scheme for target TLS independently of the proxy connection. Custom logical URL schemes require explicit routing and default to TLS.

Credit to Cloudflare for the TCP Socket interface design, familiar from Workers' connect() API. This attribution applies specifically to the interface design.

// outbound.ts
import { http } from 'mb:http';
import { connect } from 'mb:connect';
import { datagram } from 'mb:datagram';
import type { HttpBinding } from '@mochabug/adapt-builder/runtime';

// A configured environment binding supplies the physical destination and transport.
export async function createItem(service: HttpBinding, signal: AbortSignal) {
  const exchange = service.http('https://api.example.com/items', {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    signal,
  });
  try {
    await exchange.end(JSON.stringify({ name: 'Example' }));
    const response = await exchange.response;
    return await response.json();
  } finally {
    await exchange.close();
  }
}

// Call from an active handler; connections belong to that request.
export async function callServices() {
  const exchange = http('https://api.example.com/health');
  try {
    await exchange.end();
    const response = await exchange.response;
    console.log(await response.json());
  } finally {
    await exchange.close();
  }

  const tcp = connect('tcp.example.com:443', { secureTransport: 'on' });
  try {
    await tcp.opened;
    const writer = tcp.writable.getWriter();
    try {
      await writer.write(new TextEncoder().encode('hello\n'));
    } finally {
      writer.releaseLock();
    }
  } finally {
    await tcp.close();
  }

  const packets = datagram('quic.example.com:443');
  try {
    await packets.opened;
    await packets.send(new TextEncoder().encode('hello'));
    console.log(await packets.receive());
  } finally {
    await packets.close();
  }
}

Datagrams are RFC 9221 QUIC DATAGRAM. Await opened before reading maxDatagramSize; keep packets within that limit. A send may transfer its buffer, so do not reuse sent buffers. TCP connect and Connect RPC are different APIs: Connect RPC runs over HTTP and is handled by the SDK router.

Browser builds and output

Vite 8 builds ui/<role>.html with its matching .main source. A matching .ssg module optionally renders HTML on the build host. dev uses Vite's development mode; every artifact build uses production mode and real APIs.

| Output | Contents | | --- | --- | | dist/modules/ | Runtime entries, shared chunks, copied resources | | dist/assets/browser/<vertex>/<role>/index.html | Private browser HTML | | dist/cdn/browser/ | Public JS, CSS, images, workers, and public/ files | | dist/upload.json | Environment, program descriptors, module paths, asset prefixes |

Production uses https://cdn.mochabug.com/adapt/plugins, staging uses https://cdn-dev.mochabug.com/adapt/plugins, and emulation uses https://localhost:51002. Adaptkit validates that the artifact matches the upload environment, then reads source-owned manifest, vertices, README, logos, and metadata. The builder emits only build-owned output.

See build configuration for Rolldown/Vite options, public pages, SSG, assets, and output paths. Integrations can use BuildOptions.onStatus and BuildOptions.onDiagnostic for build progress and diagnostics.