HotupdaterHot Updater
Storage Adapters

Standalone Storage

Send CLI storage operations to your own authenticated HTTP storage service.

Before you start

standaloneStorage sends CLI storage operations to a remote HTTP service. Use it when you already operate, or will implement, the storage service described below. The adapter does not provision that service.

Complete the CLI and app installation, then install the adapter in the app or deploy workspace. This example also uses the Bare build adapter; keep your existing build adapter if it differs.

npm install @hot-updater/standalone @hot-updater/bare --save-dev

The server that serves mobile updates needs its own runtime storage adapter with get and getDownloadUrl, configured for the same stored objects. standaloneStorage has no getDownloadUrl, so it cannot serve a server's downloads: use it as the CLI's storage, where the CLI uploads.

Configuration

baseUrl selects the HTTP storage service root; protocol selects the persisted Storage URI scheme owned by that service. An HTTPS service can own s3://... URIs. Set the root without a trailing slash because route paths are appended directly.

Load credentials from your local ignored environment file or deployment secret store. The admin and storage tokens authenticate their respective services; neither belongs in the React Native app.

hot-updater.config.ts
import { existsSync } from "node:fs";
import { bare } from "@hot-updater/bare";
import {
  standaloneRepository,
  standaloneStorage, 
} from "@hot-updater/standalone";
import { defineConfig } from "hot-updater";

if (existsSync(".env.hotupdater")) {
  process.loadEnvFile(".env.hotupdater");
}

const adminToken = process.env.HOT_UPDATER_ADMIN_TOKEN;
const storageToken = process.env.HOT_UPDATER_STORAGE_TOKEN; 
if (!adminToken || !storageToken) {
  throw new Error("Admin and storage service credentials are required");
}

export default defineConfig({
  build: bare({ enableHermes: true }),
  database: standaloneRepository({
    baseUrl: "https://api.example.com/hot-updater/admin",
    commonHeaders: {
      Authorization: `Bearer ${adminToken}`,
    },
  }),
  storage: standaloneStorage({ 
    baseUrl: "https://storage.example.com/hot-updater", 
    protocol: "s3", 
    commonHeaders: { 
      Authorization: `Bearer ${storageToken}`, 
    }, 
  }), 
  updateStrategy: "appVersion",
});

The Standalone Repository configures the separate database/admin connection. The storage adapter can also be combined with another database adapter. List the server's plugins in plugins as well; see CLI Configuration.

commonHeaders applies to every storage request. Optional routes.put, routes.get, routes.exists and routes.delete callbacks can return { path, headers } to customize a route; route headers override common headers. Keep the method and body contract below. Let the adapter set the multipart content type for uploads.

Storage service contract

Authenticate these routes in your service before reading or changing objects. All paths are relative to baseUrl:

MethodDefault routeRequestSuccess response
POST/uploadmultipart file and key fieldsJSON { "storageUri": "s3://..." }
POST/getJSON { "storageUri": "s3://..." }Object bytes, or 404 when missing
POST/existsJSON { "storageUri": "s3://..." }JSON { "exists": true }, or 404 when missing
DELETE/deleteJSON { "storageUri": "s3://..." }Any 2xx, or 404 for an absent object

Return a validated storage URI using the configured protocol. A storage URI identifies the persisted object; the runtime storage adapter resolves its mobile download URL separately.

The built-in handlers from createHotUpdater do not implement these four storage-service routes. Its signed mobile-download route is a separate protocol. See custom server storage composition for configuring the runtime adapter.

Uploads buffer the input stream into a multipart file before sending it. Reads return a Web Response. The adapter supports put, get, exists and exact delete; it does not implement storage pruning operations.

On this page