Hikotest on the Web
Install @hikotest/sdk, connect it to your project with two copy-paste values — no GitHub token — and call over-the-air business logic from Node or the browser.
What you'll need
| Runtime | Node.js 18+ (has built-in fetch + WebAssembly) or any modern browser |
| Language | TypeScript or JavaScript — type definitions ship with the package |
| Module system | ESM (the package is ESM-only) |
| To connect | Your panel address + Project ID — copy them from Settings → SDK Integration. No GitHub token needed. |
1Install the package
npm install @hikotest/sdk
2Get your panel address and Project ID
In the panel, open your project and go to Settings → SDK Integration. You'll see two values with copy buttons:
| Panel address | The address of your Hikotest panel, e.g. https://your-panel.hikotest.app — this is panelBaseUrl |
| Project ID | A long unique id for your project (a UUID) — this is projectId |
That's everything the SDK needs to find your project's bundle. Neither value is a secret — the Project ID is a public, device-facing identifier — so you can keep them in normal config.
3Connect and start the SDK
Point the SDK at your panel with the two values, then initialize. It downloads your project's release.wasm and manifest.json from the panel, then starts a background update loop (a check every 60 seconds by default).
import { Hikotest } from '@hikotest/sdk';
Hikotest.configure({
panelBaseUrl: 'https://your-panel.hikotest.app', // copy from Settings → SDK Integration
projectId: 'your-project-id', // copy from Settings → SDK Integration
});
await Hikotest.initialize();4Call your functions
The simplest path is Hikotest.call — the function signature is resolved from the live manifest, so you don't supply any type information at the call site:
const total = await Hikotest.call('calculateTax', 100, 18); // 118
const ok = await Hikotest.call('checkCoupon', 'HIKO20', 250); // true
const price = await Hikotest.call('applyCampaign', 1000, 'VIP30'); // 700For compile-time safety, use the generated TypeScript wrapper. Every deploy writes sdk/typescript/hikotest-functions.tsinto your project's release — parameter names, types and TSDoc included. Copy it into your app:
import { applyCampaign } from './hikotest-functions';
const price = await applyCampaign(1000, 'VIP30'); // typed at compile timeTo pin the signature at the call site (mirroring the mobile SDKs), use execute:
await Hikotest.execute('applyCampaign', '(float,string)->float', 1000, 'VIP30');API overview
| configure(options) | panelBaseUrl?, projectId?, updateIntervalMs?, wasmAssetName?, manifestAssetName?, localBundle?, lockedFunctions? (legacy: repoOwner?, repoName?, githubToken?) |
| initialize() / shutdown() | Start (download + update loop) and stop the SDK |
| call(name, ...args) | Invoke a function; signature resolved from the live manifest |
| execute(name, token, ...args) | Invoke with an explicit signature token, e.g. "(int,string)->boolean" |
| functions() / bundleVersion | List deployed functions; inspect the loaded bundle version |
| loadBundle(bytes, manifest?) | Load a bundle directly — tests, caches or backend proxies |
| isLocallyPinned(name) | True when calls to the function are served from the embedded local bundle |
| isReady / initState / onStateChange | Readiness flag, current state and a state-change subscription |
Hybrid mode — OTA lock (device-side guarantee)
Some functions (payments, pricing, authorization) should never change over-the-air. Download a release you trust from the panel (release.wasm + manifest.json), ship it as a static asset and pass it at configure time:
Hikotest.configure({
panelBaseUrl: 'https://your-panel.hikotest.app',
projectId: 'your-project-id',
localBundle: { wasmBytes, manifest }, // the pinned release you embedded
lockedFunctions: ['applyPayment'], // device-side lock list (optional)
});
await Hikotest.initialize();- A function runs from the embedded local bundle when the live manifest marks it ota:false (locked in the panel) or it is in your lockedFunctions list. Everything else keeps hot-reloading from the live OTA bundle.
- The device wins. The union is one-way: even if the panel unlocks a function remotely, anything in your lockedFunctions list keeps running from the embedded bundle until you ship an app update.
- A locked function missing from the embedded bundle raises a clear error — there is no silent OTA fallback.
- Fully offline mode is the degenerate case: pass only localBundle (no panel connection) and the SDK never touches the network.
How OTA updates behave
- Every deploy (and rollback) from the panel publishes an immutable release with a bumped bundle version (e.g. v1.0.7).
- The update loop asks the panel for the latest version (every 60 seconds by default); when a new one appears, the bundle is hot-swapped — in-flight calls finish on the old module.
- Because call reads the live manifest, functions added in a new deploy become callable without any client code change.
- Wrapper code only changes when a function signature changes; internal logic updates arrive without touching your codebase.
Connect via GitHub token (legacy)
Older setup — read releases straight from GitHub— only if you were already using it
Before the panel path existed, the SDK read releases directly from your project's build repository on GitHub. It still works, but the panel path above is preferred: it needs no token, avoids GitHub's per-device rate limit, and keeps credentials out of your app. Use either the panel values or the GitHub values, never both.
Hikotest.configure({
repoOwner: 'your-github-username',
repoName: 'your-project-build-repo',
// githubToken: only for private repos — keep it server-side, never in a browser bundle
});
await Hikotest.initialize();