@electron-releases/core
v0.1.0
Published
Core interfaces and types for Electron releases adapters and providers
Maintainers
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/coreQuick 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 channelChannel 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
