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

@pjson/node

v0.5.2

Published

Priority JSON Streaming Protocol (PJS) client library for JavaScript/TypeScript

Readme

PJS JavaScript/TypeScript Client

npm version License: MIT OR Apache-2.0 TypeScript

Progressive JSON Loading for JavaScript & TypeScript Applications

The official JavaScript/TypeScript client library for the Priority JSON Streaming Protocol (PJS). Deliver JSON data progressively with intelligent prioritization for optimal user experience and performance.

✨ Features

  • 🚀 Progressive Loading: Render critical data first, details later
  • Priority-Based Streaming: Critical fields arrive in milliseconds
  • 🎯 Smart Reconstruction: Automatic JSON patching and assembly
  • 🌐 Multiple Transports: HTTP, WebSocket, Server-Sent Events
  • 🛡️ Type Safety: Full TypeScript support with comprehensive types
  • 📊 Performance Metrics: Built-in monitoring and statistics
  • 🎨 React Integration: (Coming soon) Hooks and components
  • 📱 Framework Agnostic: Works with any JavaScript framework

🏃‍♂️ Quick Start

Installation

npm install @pjs/client
# or
yarn add @pjs/client
# or
pnpm add @pjs/client

Basic Usage

import { PJSClient, Priority } from '@pjs/client';

// Create client
const client = new PJSClient({
  baseUrl: 'http://localhost:3000'
});

// Stream JSON with progressive rendering
const data = await client.stream('/api/users', {
  onRender: (partialData, metadata) => {
    // Render immediately for high-priority data
    if (metadata.priority >= Priority.High) {
      updateUI(partialData);
    }
  },
  onProgress: (progress) => {
    console.log(`Loading: ${progress.completionPercentage}%`);
  }
});

console.log('Complete data:', data);

Quick Start Helper

import { quickStart } from '@pjs/client';

// Minimal setup with smart defaults
const client = quickStart('http://localhost:3000');
const userData = await client.stream('/api/user/profile');

📚 API Reference

PJSClient

Main client class for streaming JSON data.

class PJSClient {
  constructor(config: PJSClientConfig)
  
  async connect(): Promise<string>
  async disconnect(): Promise<void>
  async stream<T>(endpoint: string, options?: StreamOptions): Promise<T>
  
  getSessionId(): string | undefined
  getStreamStats(): StreamStats[]
  isClientConnected(): boolean
  
  // Event listeners
  on(event: PJSEvent, listener: EventListener): this
}

Configuration

interface PJSClientConfig {
  baseUrl: string                    // PJS server URL
  transport?: TransportType          // 'http' | 'websocket' | 'sse'
  sessionId?: string                 // Existing session ID
  headers?: Record<string, string>   // Custom headers
  timeout?: number                   // Request timeout (default: 30000)
  debug?: boolean                    // Enable debug logging
  bufferSize?: number                // Buffer size (default: 1MB)
  priorityThreshold?: Priority       // Minimum priority to process
  maxConcurrentStreams?: number      // Max concurrent streams
}

Stream Options

interface StreamOptions {
  priorityStrategy?: PriorityStrategy  // Custom prioritization
  onRender?: RenderCallback           // Progressive rendering
  onProgress?: ProgressCallback       // Progress updates
  timeout?: number                    // Stream timeout
  queryParams?: Record<string, string>
  headers?: Record<string, string>
}

Priority System

enum Priority {
  Critical = 100,    // User identity, errors, status
  High = 75,         // Names, titles, key information
  Medium = 50,       // Descriptions, content
  Low = 25,          // Metadata, timestamps
  Background = 10    // Analytics, large datasets
}

Event System

// Listen for events
client.on('skeleton_ready', ({ data, processingTime }) => {
  console.log('Initial structure ready:', data);
});

client.on('patch_applied', ({ patch, priority, path }) => {
  console.log(`Applied ${patch.operation} to ${path}`);
});

client.on('stream_complete', ({ data, stats, totalTime }) => {
  console.log(`Stream completed in ${totalTime}ms`);
  console.log('Final data:', data);
  console.log('Statistics:', stats);
});

client.on('progress_update', (progress) => {
  console.log(`Progress: ${progress.completionPercentage}%`);
});

🌐 Transport Options

HTTP Transport (Default)

Best for: Simple integration, maximum compatibility

const client = new PJSClient({
  baseUrl: 'http://localhost:3000',
  transport: 'http'
});

WebSocket Transport

Best for: Real-time applications, bi-directional communication

const client = new PJSClient({
  baseUrl: 'ws://localhost:3000',
  transport: 'websocket'
});

Server-Sent Events

Best for: One-way streaming, automatic reconnection

const client = new PJSClient({
  baseUrl: 'http://localhost:3000',
  transport: 'sse'
});

🎨 Advanced Examples

React Integration

import React, { useState, useEffect } from 'react';
import { PJSClient, Priority } from '@pjs/client';

function UserProfile({ userId }: { userId: string }) {
  const [userData, setUserData] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    const client = new PJSClient({
      baseUrl: process.env.REACT_APP_API_URL
    });
    
    client.stream(`/api/users/${userId}`, {
      onRender: (partialData, metadata) => {
        // Update UI progressively
        setUserData(partialData);
        
        // Stop loading spinner when critical data arrives
        if (metadata.priority >= Priority.High) {
          setLoading(false);
        }
      }
    });
  }, [userId]);
  
  if (loading) return <div>Loading...</div>;
  
  return (
    <div>
      <h1>{userData?.name || 'Loading name...'}</h1>
      <p>{userData?.email || 'Loading email...'}</p>
      {/* More fields will populate progressively */}
    </div>
  );
}

Custom Priority Strategy

const customStrategy: PriorityStrategy = {
  name: 'ecommerce',
  calculatePriority: (path, value, context) => {
    if (path.includes('price')) return Priority.Critical;
    if (path.includes('product.name')) return Priority.High;
    if (path.includes('reviews')) return Priority.Background;
    return Priority.Medium;
  }
};

const data = await client.stream('/api/products', {
  priorityStrategy: customStrategy
});

Performance Monitoring

client.on('stream_complete', ({ stats }) => {
  console.log('Performance Metrics:');
  console.log(`Time to first frame: ${stats.performance.timeToFirstFrame}ms`);
  console.log(`Time to skeleton: ${stats.performance.timeToSkeleton}ms`);
  console.log(`Total time: ${stats.performance.timeToCompletion}ms`);
  console.log(`Throughput: ${stats.performance.throughputMbps} MB/s`);
  console.log(`Memory efficiency: ${stats.performance.memoryStats.efficiency}%`);
});

Error Handling

try {
  const data = await client.stream('/api/data');
} catch (error) {
  if (error instanceof PJSError) {
    switch (error.type) {
      case PJSErrorType.ConnectionError:
        console.error('Connection failed:', error.message);
        break;
      case PJSErrorType.TimeoutError:
        console.error('Stream timed out:', error.message);
        break;
      case PJSErrorType.ParseError:
        console.error('Invalid data received:', error.message);
        break;
    }
  }
}

🔧 Utilities

Frame Validation

import { validateFrame } from '@pjs/client';

const isValidFrame = validateFrame(receivedData);

JSON Path Parsing

import { parseJsonPath } from '@pjs/client';

const result = parseJsonPath('$.user.profile[0].name');
console.log(result.segments); // ['user', 'profile[0]', 'name']
console.log(result.isValid);  // true

Memory Estimation

import { estimateObjectSize, formatBytes } from '@pjs/client';

const size = estimateObjectSize(largeObject);
console.log(`Object size: ${formatBytes(size)}`);

🚀 Performance Benefits

Traditional JSON Loading

Time →  |-------- 2000ms --------| 
Data →  [                    ████] ← All data at once
UI   →  [          loading...    ] ← User waits

PJS Progressive Loading

Time →  |-------- 2000ms --------| 
Data →  [██]    [██]    [██]   [█] ← Progressive chunks
UI   →  [█]     [██]    [███] [██] ← Immediate rendering
        ↑        ↑       ↑     ↑
      50ms     200ms    500ms  2000ms
   Critical    High    Medium   Low

Results:

  • 70% faster perceived loading time
  • 🎯 Critical data in 50ms vs 2000ms
  • 📱 Better UX on slow connections
  • 💾 Lower memory usage during loading

🛠️ Development

Building

npm install
npm run build

Testing

npm test
npm run test:watch
npm run test:coverage

Linting

npm run lint
npm run lint:fix

Documentation

npm run docs

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

git clone https://github.com/pjs-rs/pjs
cd pjs/crates/pjs-js-client
npm install
npm run dev

📋 Requirements

  • Node.js: 18.0.0 or higher
  • TypeScript: 5.0+ (for TypeScript projects)
  • Modern Browser: ES2020 support required

📄 License

Licensed under either of:

at your option.

🔗 Related Projects


DocumentationExamplesBenchmarksGitHub

Made with ❤️ for the JavaScript community