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

@jetstart/core

v2.3.4

Published

Build server and orchestration for JetStart

Readme

@jetstart/core

Central build server and real-time orchestration layer for JetStart.

Overview

@jetstart/core is the engine that powers jetstart. It runs three networked services and orchestrates the complete hot reload pipeline — from detecting a file change to having new code running on a physical Android device in instantly.

src/
├── build/
│   ├── kotlin-compiler.ts    # Invokes kotlinc, builds classpath from SDK + Gradle caches
│   ├── dex-generator.ts      # Runs d8 to convert .class files to classes.dex
│   ├── override-generator.ts # Generates $Override companion classes (InstantRun-style)
│   ├── hot-reload-service.ts # Orchestrates compile → override → dex pipeline
│   ├── gradle.ts             # GradleExecutor + AdbHelper for full builds
│   ├── gradle-injector.ts    # Injects JetStart plugin config into build.gradle
│   ├── watcher.ts            # chokidar-based file watcher with debounce
│   ├── builder.ts            # High-level build manager
│   ├── cache.ts              # Incremental build cache
│   ├── parser.ts             # Gradle output parser
│   ├── dsl-parser.ts         # Compose DSL parser
│   └── js-compiler-service.ts # kotlinc-js → ES module for web emulator
├── server/
│   ├── http.ts               # Express HTTP server setup
│   ├── routes.ts             # REST API routes
│   └── middleware.ts         # Request middleware
├── websocket/
│   ├── manager.ts            # Connection registry, session routing
│   ├── handler.ts            # Message dispatch + session/token validation
│   └── index.ts
├── utils/
│   ├── logger.ts             # Colored terminal logger
│   ├── qr.ts                 # QR code generation
│   └── session.ts            # Session creation and lifecycle
└── types/
    └── index.ts              # ServerSession, QRCodeOptions

Architecture

File change detected  (chokidar — watches *.kt, *.xml, *.gradle, 300ms debounce)
  │
  ├─► KotlinCompiler
  │     kotlinc + Compose compiler plugin (bundled in Kotlin 2.0+, or Gradle cache fallback)
  │     Classpath: android.jar + Gradle module cache + transforms-3 cache + project build outputs
  │     Uses @argfile to avoid Windows command-line length limits
  │     → .class files in a temp directory
  │
  ├─► OverrideGenerator
  │     Generates $Override companion classes for each modified class (InstantRun pattern)
  │     Compiles override source files back through KotlinCompiler
  │     Falls back to direct class reload if override generation fails
  │
  ├─► DexGenerator
  │     Runs d8 from $ANDROID_HOME/build-tools/<latest>
  │     --min-api 24  (Android 7.0+)
  │     → classes.dex
  │
  └─► WebSocketHandler.sendDexReload()
        Broadcasts base64-encoded DEX + class name list to all authenticated Android clients
        Android runtime loads classes via custom ClassLoader — no reinstall needed

For the web emulator, a parallel path compiles via kotlinc-js to an ES module and broadcasts it as core:js-update.


Usage

import { JetStartServer } from '@jetstart/core';

const server = new JetStartServer({
  httpPort: 8765,
  wsPort: 8766,
  host: '0.0.0.0',           // Bind to all interfaces
  displayHost: '192.168.1.5', // LAN IP used in QR code and terminal output
  projectPath: '/path/to/my-app',
  projectName: 'my-app',
  // For Android emulators — host is reachable at 10.0.2.2 inside the AVD
  emulatorHost: '10.0.2.2',
});

const session = await server.start();
// session.id and session.token are embedded in the QR code

server.on('build:complete', (result) => {
  console.log('APK ready:', result.apkPath);
});

await server.stop();

HTTP API

All endpoints are served on the HTTP port (default 8765).

GET /

Redirects to https://web.jetstart.site with the active session's connection parameters (host, port, wsPort, sessionId, token, version, projectName) as query parameters, so the web emulator connects automatically. Returns a plain status page if no session is active.

GET /health

{ "status": "ok", "version": "0.1.0", "uptime": 42.3 }

GET /version

{ "version": "0.1.0" }

POST /session/create

Creates a new dev session and returns a base64 QR code PNG.

Request body:

{ "projectName": "my-app", "projectPath": "/abs/path/to/my-app" }

Response:

{
  "session": { "id": "abc123", "token": "xyz789", "projectName": "my-app", "createdAt": 1711900000000 },
  "qrCode": "data:image/png;base64,..."
}

GET /session/:sessionId

Returns the session object (404 if not found).

GET /download/:filename

Streams the most recently built APK as a file download.


WebSocket Protocol

The WebSocket server runs on port 8766. Every client must send client:connect with the matching sessionId and token (both embedded in the QR code). Mismatched connections are closed immediately:

  • Close code 4001 — session mismatch (device built against a different session, rescan QR)
  • Close code 4002 — token mismatch

Messages: device/browser → core

| Type | Key fields | Description | |---|---|---| | client:connect | sessionId, token, deviceInfo | Authenticate with session credentials | | client:status | status | Send a SessionStatus update | | client:log | log: LogEntry | Forward a device log entry to the server | | client:heartbeat | — | Keep-alive ping | | client:disconnect | reason? | Graceful disconnect | | client:click | action, elementType, elementText? | UI interaction from web emulator |

Messages: core → device/browser

| Type | Key fields | Description | |---|---|---| | core:connected | projectName | Authentication accepted | | core:build-start | — | Gradle build has begun | | core:build-status | status: BuildStatus | Mid-build progress update | | core:build-complete | apkInfo, downloadUrl | APK ready for download/install | | core:build-error | error, details? | Build failed | | core:dex-reload | dexBase64, classNames[] | Hot reload DEX patch for Android devices | | core:js-update | jsBase64, sourceFile, byteSize | ES module update for the web emulator | | core:log | log: LogEntry | Device log broadcast to dashboard clients | | core:disconnect | reason | Server shutting down |


File Watcher

import { FileWatcher } from '@jetstart/core';

const watcher = new FileWatcher({
  projectPath: '/path/to/project',
  callback: (changedFiles) => { /* handle changes */ },
  debounceMs: 300,
});

watcher.watch('/path/to/project');
// Watches **/*.kt, **/*.xml, **/*.gradle, **/*.gradle.kts
// Ignores: node_modules, build, .gradle, .git, dist

watcher.stop();

Hot Reload Service

import { HotReloadService } from '@jetstart/core';

const service = new HotReloadService('/path/to/project');

// Check that kotlinc and d8 are available
const env = await service.checkEnvironment();
if (!env.ready) console.log(env.issues);

// Compile a changed file and get the DEX payload
const result = await service.hotReload('/path/to/project/app/src/main/java/com/example/MainActivity.kt');
if (result.success) {
  console.log(`Done in ${result.compileTime + result.dexTime}ms`);
  // result.dexBase64 — send this to the device
  // result.classNames — fully-qualified class names patched
}

Gradle & ADB

GradleExecutor runs full Gradle builds (debug or release). It prefers system Gradle over the project gradlew wrapper for speed, auto-creates local.properties if the Android SDK is found but not configured, and supports Gradle build flags --parallel --build-cache --configure-on-demand --daemon.

AdbHelper handles wireless ADB connections with retry logic (up to 5 attempts, escalating delays) to account for user-approval timing on the device, and polls for device readiness after adb connect since the device may transition through connectingofflinedevice states.


Environment Variables

| Variable | Description | |---|---| | ANDROID_HOME / ANDROID_SDK_ROOT | Android SDK path — required for hot reload and Gradle builds | | KOTLIN_HOME | Kotlin installation path — used to find kotlinc | | JAVA_HOME | JDK path | | DEBUG | Enable verbose logging |


License

MIT