getActiveScope, getActiveScopeId
Return the store branch (scope) the shopper picked, or null; the API client sends it, and scope-sensitive query keys include it.
import { getActiveScope, getActiveScopeId } from '@salla.sa/twilight-theme-engine/api/client';In plain words
Some stores sell from several branches or markets, and stock can differ between them. When a shopper picks one, that choice is the scope. getActiveScope() returns it as { id, type, allocation_type, allocation_id }, and getActiveScopeId() returns only the id. Both return null when nothing is picked.
The engine sends the scope with every API request and puts it in the cache keys of products and categories, so one branch never sees another branch's data.
Signature
function getActiveScope(): ActiveScope | null
function getActiveScopeId(): string | null // getActiveScope()?.id ?? null
// Not exported; use ReturnType<typeof getActiveScope>
interface ActiveScope {
id: string;
type?: string;
allocation_type?: string;
allocation_id?: string;
}Try it live
import { useQuery } from '@tanstack/react-query';
import { api, getActiveScope } from '@salla.sa/twilight-theme-engine/api/client';
/** A custom call whose answer depends on the branch: put the scope in the key. */
export function BranchOffers() {
const { data } = useQuery({
queryKey: ['custom-offers', { scope: getActiveScope() }],
queryFn: () => api.get('products?source=offers').json<{ data: unknown[] }>(),
});
return <span>{data?.data.length ?? 0} offers here</span>;
}
Example
import { useQuery } from '@tanstack/react-query';
import { api, getActiveScope } from '@salla.sa/twilight-theme-engine/api/client';
/** A custom request whose answer depends on the branch: the scope belongs in the key. */
export function useBranchStock(productId: string) {
return useQuery({
queryKey: ['branch-stock', productId, { scope: getActiveScope() }],
queryFn: () =>
api.get('products/' + productId + '/details').json<{ data: { quantity?: number } }>(),
});
}
How it behaves
Order:
Salla.storage.get('scope')from the Salla SDK; while that storage is not ready, thescopecookie; then the scopetwilightMiddlewareread from the same cookie on the server; thennull.A
nullfrom the SDK storage wins over an old cookie: it means the shopper cleared the choice. Only storage that is not ready yet falls through to the cookie.The root loader mirrors the SDK choice into the
scopecookie (syncScopeCookie), so the server renders the branch the browser picked.The client sends
s-scope-id, pluss-scope-type,s-scope-allocation-typeands-scope-allocation-idwhen present.store.settingsalso addsscope=<id>to its URL.Keys that include it:
product.queries.list,product.queries.detail, the product preview key,category.queries.list,wishlist.queries.listandstore.queries.settings.
Gotchas
It is read when you call it. A key built before the shopper switched branch still names the old one: build query options during render.
A custom query for scope-sensitive data (products, stock, categories) without the scope in its key serves one branch's cached answer to another.
getActiveScopeId()alone names the market, not the branch allocation, and the API answers stock per allocation. Put the wholegetActiveScope()object in keys.
Related
The HTTP client behind every engine API module: ky, pointed at the Salla Store API, adding store, language, version, token and branch headers.
product.listLists products from any source (latest, offers, a category, a brand, a search) with page size, sort, filters and cursor pagination.
categoryReads the store's category tree, or a single category, from the Salla API; the tree is cached per branch.
Source and docs
- Engine source:
packages/theme-engine/src/api/client.ts