Skip to main content

Hooks & API

UI Extensions provide hooks to access store context, settings, session tokens, storage, and the current resource.

Extension API

Every extension receives an ExtensionApi object that provides access to all platform capabilities:

interface ExtensionApi {
target: ExtensionTarget; // The current extension target
settings: Record<string, unknown>; // Extension settings
store: StoreContext; // Store information
resource?: ResourceContext; // Current resource (product, order, etc.)
setHeight(height: number): void; // Update container height
sessionToken: SessionToken; // Session token for API calls
storage: ExtensionStorage; // Key-value storage
i18n: I18n; // Internationalization
}

StoreContext

interface StoreContext {
domain: string; // Store domain (e.g. "mystore.qumra.store")
locale: string; // Current locale
currency: string; // Store currency code
}

ResourceContext

interface ResourceContext {
id: string; // Resource ID
type: string; // Resource type (product, order, customer)
data?: Record<string, unknown>; // Additional resource data
}

useApi()

Access the full Extension API from any component within an extension:

import { useApi } from "@qumra/riwaq";

function MyExtension() {
const api = useApi();

return (
<div>
<p>Store: {api.store.domain}</p>
<p>Locale: {api.store.locale}</p>
<p>Currency: {api.store.currency}</p>
{api.resource && (
<p>Resource: {api.resource.type} #{api.resource.id}</p>
)}
</div>
);
}

useSettings()

Access the extension's configured settings:

import { useSettings } from "@qumra/riwaq";

function MyExtension() {
const settings = useSettings();

return (
<div>
<h3>{settings.title as string}</h3>
<p>Show badge: {settings.showBadge ? "Yes" : "No"}</p>
<p>Max items: {settings.maxItems as number}</p>
</div>
);
}

Settings are defined in the extension configuration. See Settings for details on defining settings fields.

useSessionToken()

Get a session token for making authenticated API calls from the extension:

import { useSessionToken } from "@qumra/riwaq";

function MyExtension() {
const sessionToken = useSessionToken();

async function fetchData() {
const token = await sessionToken.get();

const response = await fetch("https://your-app.com/api/data", {
headers: {
Authorization: `Bearer ${token}`,
},
});

return response.json();
}

return <button onClick={fetchData}>Load Data</button>;
}

SessionToken Interface

MethodReturn TypeDescription
get()Promise<string>Get a valid session token. Refreshes automatically if expired.

useExtensionLanguage()

Get the current language/locale of the extension context:

import { useExtensionLanguage } from "@qumra/riwaq";

function MyExtension() {
const language = useExtensionLanguage();

return <p>Current language: {language}</p>; // "ar", "en", etc.
}

useStorage()

Persist key-value data within the extension's scope:

import { useStorage } from "@qumra/riwaq";
import { useState, useEffect } from "react";

function MyExtension() {
const storage = useStorage();
const [count, setCount] = useState(0);

useEffect(() => {
// Load saved value
storage.get("viewCount").then((value) => {
if (value) setCount(Number(value));
});
}, []);

async function incrementCount() {
const newCount = count + 1;
setCount(newCount);
await storage.set("viewCount", String(newCount));
}

return (
<div>
<p>Views: {count}</p>
<button onClick={incrementCount}>Increment</button>
</div>
);
}

ExtensionStorage Interface

MethodReturn TypeDescription
get(key)Promise<string | null>Get a stored value by key.
set(key, value)Promise<void>Store a value.
delete(key)Promise<void>Delete a stored value.

useResource()

Access the current resource (product, order, customer) when the extension is rendered in a resource context:

import { useResource } from "@qumra/riwaq";

function ProductExtension() {
const resource = useResource();

if (!resource) return <p>No resource context</p>;

return (
<div>
<p>Type: {resource.type}</p>
<p>ID: {resource.id}</p>
{resource.data && (
<pre>{JSON.stringify(resource.data, null, 2)}</pre>
)}
</div>
);
}

setHeight()

Dynamically adjust the extension container height:

import { useApi } from "@qumra/riwaq";
import { useEffect, useRef } from "react";

function MyExtension() {
const api = useApi();
const ref = useRef<HTMLDivElement>(null);

useEffect(() => {
if (ref.current) {
api.setHeight(ref.current.scrollHeight);
}
});

return <div ref={ref}>{/* Content */}</div>;
}

i18n

Translate strings with replacements:

import { useApi } from "@qumra/riwaq";

function MyExtension() {
const { i18n } = useApi();

return (
<p>{i18n.translate("greeting", { name: "Ahmed" })}</p>
// Output: "Hello, Ahmed!" (based on translation files)
);
}