HotupdaterHot Updater
Self Hosting (Custom)Database Adapters

Kysely

Since v0.22.0+

Build a self-hosted Hot Updater server with Kysely query builder.

Installation

Install Kysely and SQLite driver.

npm install kysely better-sqlite3 @types/better-sqlite3 --save-dev

For other databases, see Kysely's dialect documentation.

Setup

Create a database connection file:

src/kysely.ts
import { Kysely, SqliteDialect } from "kysely";
import Database from "better-sqlite3";

export const db = new Kysely({
  dialect: new SqliteDialect({
    database: new Database("./data/database.db"),
  }),
});

Hot Updater Configuration

Create the Hot Updater instance:

src/hotUpdater.ts
import { createHotUpdater } from "@hot-updater/server";
import { kyselyAdapter } from "@hot-updater/server/adapters/kysely";
import { s3Storage } from "@hot-updater/aws";
import { db } from "./kysely";

export const hotUpdater = createHotUpdater({
  database: kyselyAdapter({ db, provider: "sqlite" }),
  storages: [
    s3Storage({
      region: "auto",
      endpoint: process.env.R2_ENDPOINT,
      credentials: {
        accessKeyId: process.env.R2_ACCESS_KEY_ID!,
        secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
      },
      bucketName: process.env.R2_BUCKET_NAME!,
    }),
  ],
  basePath: "/hot-updater",
});

Schema Management

Generate SQL migration files for Hot Updater tables:

npx hot-updater db generate src/hotUpdater.ts --yes

Apply migrations to the database:

npx hot-updater db migrate src/hotUpdater.ts

Generate vs Migrate

  • generate - Creates SQL migration files for manual review before applying to database
  • migrate - Runs Kysely migrator to directly apply migrations to the database

Need to generate SQL without config? See SQL Export for standalone SQL generation with the --sql flag.

CLI Configuration

Configure your CLI to use this self-hosted server.

hot-updater.config.ts
import { defineConfig } from "@hot-updater/core";
import { bare } from "@hot-updater/bare";
import { s3Storage } from "@hot-updater/aws";
import { standaloneRepository } from "@hot-updater/standalone";

export default defineConfig({
  build: bare(),
  storage: s3Storage({
    region: "auto",
    endpoint: process.env.R2_ENDPOINT,
    credentials: {
      accessKeyId: process.env.R2_ACCESS_KEY_ID!,
      secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
    },
    bucketName: process.env.R2_BUCKET_NAME!,
  }),
  database: standaloneRepository({
    baseUrl: "http://localhost:3000/hot-updater",
  }),
});

The storage plugin must match the storages in your server's createHotUpdater. Both use s3Storage in this example.

API Endpoints

The server automatically creates these endpoints:

MethodEndpointDescription
GET/hot-updater/versionGet server version
GET/hot-updater/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleIdCheck for updates by fingerprint
GET/hot-updater/app-version/:platform/:version/:channel/:minBundleId/:bundleIdCheck for updates by app version
GET/hot-updater/api/bundlesList bundles (query: channel, platform, limit, offset)
GET/hot-updater/api/bundles/:idGet bundle by ID
POST/hot-updater/api/bundlesCreate or update bundles
DELETE/hot-updater/api/bundles/:idDelete bundle
GET/hot-updater/api/bundles/channelsList all channels