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-devThe 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.
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:
| Method | Default route | Request | Success response |
|---|---|---|---|
POST | /upload | multipart file and key fields | JSON { "storageUri": "s3://..." } |
POST | /get | JSON { "storageUri": "s3://..." } | Object bytes, or 404 when missing |
POST | /exists | JSON { "storageUri": "s3://..." } | JSON { "exists": true }, or 404 when missing |
DELETE | /delete | JSON { "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.