Quick start
Save a counter that survives a reload, then see what a missing capability looks like.
A counter in four steps
-
Install.
@moku-labs/coreand@moku-labs/commonare required peers, so your app and every Moku framework share one copy.install bun add @moku-labs/system @moku-labs/core @moku-labs/common -
Compose the capabilities you use. Plugins come from subpaths. A store-only app carries no code of the other capabilities.
-
Start the app.
start()picks each capability's provider. A method called before it answersunavailable. -
Read the result. Every method returns
SystemResult<T>. Checkokbefore you readvalue.
The code
import { createApp } from "@moku-labs/system";
import { storePlugin } from "@moku-labs/system/store";
const system = createApp({
plugins: [storePlugin],
pluginConfigs: { store: { name: "my-app" } }
});
await system.start();
const saved = await system.store.get<number>("count");
const count = saved.ok ? (saved.value ?? 0) : 0;
const written = await system.store.set("count", count + 1);
if (!written.ok) console.warn(written.reason, written.message);
await system.stop();- The IndexedDB database on the web, the store file
my-app.jsonin Tauri. - An absent key is
okwithundefined, not a failure.
The same file runs in a browser and in the native shell. Nothing in it names a runtime.
When a capability is missing
A tray icon does not exist on the web. The call still answers, with data you can act on:
import { createApp } from "@moku-labs/system";
import { trayPlugin } from "@moku-labs/system/tray";
const system = createApp({ plugins: [trayPlugin] });
await system.start();
const result = await system.tray.setTooltip("Syncing");
if (!result.ok && result.reason === "unsupported") {
console.log(`no tray on ${result.provider}`);
}- In a browser:
no tray on web. Hide the feature.
Add the native shell
The Tauri packages are optional peers. Install only the ones your capabilities load:
bun add @tauri-apps/api @tauri-apps/plugin-storeThen package the app with @moku-labs/native. It generates the Tauri
permissions from the capabilities you list.
Related
- How it works: the provider seam and the result contract.
- One app, web and native: the bundler setup and the shared list.