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

uhale

v1.1.0

Published

A TypeScript/JavaScript library for interacting with the Uhale API, providing functionality for file uploads, user authentication, and terminal management.

Readme

Uhale

A TypeScript/JavaScript library for interacting with the Uhale API, providing functionality for file uploads, user authentication, and terminal management.

Installation

npm install uhale

Quick Start

import { Uhale } from 'uhale';

const uhale = new Uhale();

// Login with email and password
await uhale.login('[email protected]', 'your-password');

// Upload a file
const fileId = await uhale.uploadFile({
    isImage: true,
    file: fileBuffer,
    fileSize: fileBuffer.length,
    terminalId: 'your-terminal-id',
    subject: 'Optional file description',
});

Configuration

Constructor Options

type UhaleOptions = {
    apiUrl?: string; // Default: 'https://whalephoto.zeasn.tv/photo/api/v1/web'
    userUrl?: string; // Default: 'https://saas.zeasn.tv'
    secretKey?: string; // Default: provided
    accessKey?: string; // Default: provided
};

Authentication

Login with Email/Password

await uhale.login('[email protected]', 'password');

Check Session State

const state = await uhale.getSessionIdState();
// Returns: 'loggedOut' | 'scanned' | 'loggedIn' | 'failed' | 'expired' | 'unknown'

Wait for Login Confirmation

await uhale.waitForLoggedIn();

File Operations

Upload Files

const fileId = await uhale.uploadFile({
    isImage: boolean, // true for images, false for videos
    file: Buffer | Blob, // File data
    fileSize: number, // Size in bytes
    terminalId: string, // Target terminal ID
    subject: string, // Optional description
});

Get Presigned Upload URL

const urlData = await uhale.getPresignedUrl({
    isImage: boolean,
    fileSize: number,
    terminalId: string,
    offlineStorage: boolean, // Default: false
});

// Returns:
// {
//     awsUploadUrl: string,
//     fileUrl: string,
//     fileId: string
// }

Save Uploaded File

await uhale.saveUploadedFile({
    fileUrl: string,
    fileId: string,
    subject: string,
    fileSize: number,
    terminalId: string,
});

Wait for Files to be Processed

await uhale.waitForFilesUploaded(fileIds);

File Management

Revoke Files

await uhale.revokeFiles(terminalId, fileIds);

Wait for Files to be Revoked

await uhale.waitForFilesRevoked(fileIds);

Terminal Management

Get Available Terminals

const terminals = await uhale.getTerminals();

// Returns array of UhaleTerminal objects with properties:
// - terminalId: string
// - name: string
// - state: string
// - location: string
// - availableSpace: string
// - offlineStorage: string
// - ... and more

Error Handling

The library throws errors for various conditions:

try {
    await uhale.login('email', 'password');
} catch (error) {
    // Handle authentication errors
    console.error('Login failed:', error.message);
}

try {
    await uhale.uploadFile({
        /* ... */
    });
} catch (error) {
    // Handle upload errors
    console.error('Upload failed:', error.message);
}

Common error scenarios:

  • No session ID available
  • Invalid credentials
  • API errors with error codes
  • Network timeouts
  • File upload failures

TypeScript Support

The library is written in TypeScript and includes full type definitions. Key types include:

  • UhaleOptions - Constructor configuration
  • UhaleTerminal - Terminal information
  • UhalePresignedUrl - Upload URL response
  • UhaleUser - User session data
  • UhaleResponse<T> - API response wrapper

Example: Complete File Upload Flow

import { Uhale } from 'uhale';
import { readFileSync } from 'fs';

async function uploadImage() {
    const uhale = new Uhale();

    try {
        // 1. Authenticate
        await uhale.login('[email protected]', 'password');
        await uhale.waitForLoggedIn();

        // 2. Get available terminals
        const terminals = await uhale.getTerminals();
        const terminalId = terminals[0].terminalId;

        // 3. Read file
        const fileBuffer = readFileSync('image.jpg');

        // 4. Upload file
        const fileId = await uhale.uploadFile({
            isImage: true,
            file: fileBuffer,
            fileSize: fileBuffer.length,
            terminalId: terminalId,
            subject: 'My uploaded image',
        });

        console.log('File uploaded successfully:', fileId);
    } catch (error) {
        console.error('Upload failed:', error.message);
    }
}