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

electron-releases-core

v0.1.0

Published

Core interfaces and types for Electron releases adapters and providers

Downloads

64

Readme

electron-releases-core

Core interfaces, types, and routing logic for Electron auto-update servers. This package provides the foundation that adapters and providers build upon.

Installation

npm install electron-releases-core
# or
yarn add electron-releases-core
# or
bun add electron-releases-core

Quick Start

Most users won't use this package directly—instead, use an adapter like electron-releases-adapter-nextjs with a provider like electron-releases-provider-github.

However, if you're building a custom adapter or provider, this package gives you the core building blocks.

import {
  routeRequest,
  normalizeConfig,
  type AdapterConfig,
  type ReleasesProvider,
  type AssetsProvider,
} from "electron-releases-core";

// Create your providers (or use existing ones)
const releases: ReleasesProvider = { /* ... */ };
const assets: AssetsProvider = { /* ... */ };

// Normalize configuration
const config = normalizeConfig({
  channels: ["alpha", "beta", "stable"],
  releases,
  assets,
});

// Route incoming requests
const response = await routeRequest(request, pathSegments, config);

API Endpoints

The router handles the following endpoints (relative to your mount point):

| Endpoint | Description | |----------|-------------| | GET / | List releases. Add ?channel=beta to filter by channel, or ?all=true for all channels. | | GET /download | Auto-detect platform from User-Agent and redirect to download. | | GET /download/:platform | Download for a specific platform (e.g., mac, win32, darwin_arm64). | | GET /update/:platform/:version | Check for updates (Squirrel-compatible). Returns update info or 204. | | GET /update/win32/:version/RELEASES | Squirrel.Windows RELEASES file. |

Core Types

ReleasesProvider

Interface for fetching release metadata from your source (GitHub, GitLab, S3, etc.):

interface ReleasesProvider {
  // Get a single release
  getRelease(options?: GetReleaseOptions): Promise<ReleaseInfo | null>;

  // Get releases for multiple channels
  getReleases(options?: GetReleasesOptions): Promise<Record<string, ReleaseInfo | null>>;

  // Infer channel from version string (e.g., "1.0.0-beta.1" → "beta")
  getChannelFromVersion(version: string): string;
}

AssetsProvider

Interface for generating authenticated download URLs:

interface AssetsProvider {
  // Get a signed/authenticated download URL for an asset
  getSignedDownloadUrl(asset: PlatformAsset): Promise<string | null>;
}

ReleaseInfo

Release metadata structure:

interface ReleaseInfo {
  version: string;           // e.g., "1.0.0", "1.0.0-beta.1"
  notes: string;             // Release notes/changelog
  pub_date: string;          // ISO date string
  channel: string;           // e.g., "stable", "beta", "alpha"
  platforms: Record<string, PlatformAsset>;
  files: Record<string, string>;  // Additional files (e.g., RELEASES)
}

PlatformAsset

Individual asset metadata:

interface PlatformAsset {
  name: string;         // Filename
  api_url: string;      // API URL for authenticated downloads
  url: string;          // Public download URL
  content_type: string; // MIME type
  size: number;         // Size in MB
}

AdapterConfig

Configuration passed to adapters:

interface AdapterConfig {
  channels?: string[];       // Default: ["alpha", "beta", "stable"]
  releases: ReleasesProvider;
  assets: AssetsProvider;
}

Platform Identifiers

The router recognizes these platform identifiers and their aliases:

| Canonical | Aliases | |-----------|---------| | darwin | mac, macos, osx | | exe | win32, windows, win | | dmg | dmg | | deb | debian | | rpm | fedora | | AppImage | appimage |

All platforms support an _arm64 suffix (e.g., darwin_arm64, exe_arm64).

Utilities

checkAlias

Resolve platform aliases to canonical names:

import { checkAlias } from "electron-releases-core";

checkAlias("macos");      // → "darwin"
checkAlias("win32");      // → "exe"
checkAlias("mac_arm64");  // → "darwin_arm64"
checkAlias("invalid");    // → ""

detectPlatformFromUserAgent

Auto-detect platform from HTTP User-Agent:

import { detectPlatformFromUserAgent } from "electron-releases-core";

detectPlatformFromUserAgent("Mozilla/5.0 (Macintosh; ...)");  // → "dmg"
detectPlatformFromUserAgent("Mozilla/5.0 (Windows NT ...)");  // → "exe"

parseRoute

Parse path segments into route information:

import { parseRoute } from "electron-releases-core";

parseRoute([]);                              // { type: "releases", params: {} }
parseRoute(["download"]);                    // { type: "download", params: {} }
parseRoute(["download", "mac"]);             // { type: "download-platform", params: { platform: "mac" } }
parseRoute(["update", "darwin", "1.0.0"]);   // { type: "update", params: { platform: "darwin", version: "1.0.0" } }

Channels

Channels are ordered by stability, with the last channel being the default/stable channel:

const channels = ["alpha", "beta", "stable"];
// "stable" is the default channel

Channel matching rules:

  • Stable channel: Non-prerelease versions without any channel suffix
  • Other channels: Prerelease versions with matching suffix (e.g., 1.0.0-beta.1)

Building a Custom Provider

To create a provider for a new source:

import type { ReleasesProvider, AssetsProvider, ReleaseInfo } from "electron-releases-core";

export function configureCustomProvider(config: CustomProviderConfig): {
  releases: ReleasesProvider;
  assets: AssetsProvider;
} {
  return {
    releases: {
      async getRelease(options) {
        // Fetch and return release info from your source
        return {
          version: "1.0.0",
          notes: "Release notes",
          pub_date: new Date().toISOString(),
          channel: options?.channel ?? "stable",
          platforms: {
            darwin: {
              name: "MyApp-1.0.0-mac.zip",
              api_url: "https://...",
              url: "https://...",
              content_type: "application/zip",
              size: 85.2,
            },
          },
          files: {},
        };
      },

      async getReleases(options) {
        // Return releases for each channel
        return {
          stable: await this.getRelease({ channel: "stable" }),
          beta: await this.getRelease({ channel: "beta" }),
        };
      },

      getChannelFromVersion(version) {
        if (version.includes("-beta")) return "beta";
        if (version.includes("-alpha")) return "alpha";
        return "stable";
      },
    },

    assets: {
      async getSignedDownloadUrl(asset) {
        // Return authenticated URL or null
        return asset.url;
      },
    },
  };
}

Building a Custom Adapter

To create an adapter for a new framework:

import { routeRequest, normalizeConfig, type AdapterConfig } from "electron-releases-core";

export function configureCustomAdapter(config: AdapterConfig) {
  const normalizedConfig = normalizeConfig(config);

  return async function handler(req: MyFrameworkRequest): Promise<MyFrameworkResponse> {
    // Extract path segments from your framework's request
    const pathSegments = extractPathSegments(req);
    
    // Create a standard Request object
    const request = new Request(req.url, { headers: req.headers });
    
    // Route and get response
    const response = await routeRequest(request, pathSegments, normalizedConfig);
    
    // Convert to your framework's response format
    return convertResponse(response);
  };
}

License

MIT