Skip to content

Commit 8ce7778

Browse files
committed
feat(pos): add keys property to Storage type for subscribable access
Adds Subscribable, StorageKeys types and optional keys property to the POS Storage interface. Each key is exposed as Subscribable<T | undefined> for reactive updates across targets of the same extension. Part of: shop/issues-retail#26020
1 parent 06eeda4 commit 8ce7778

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

  • packages/ui-extensions/src/surfaces/point-of-sale/types

packages/ui-extensions/src/surfaces/point-of-sale/types/storage.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,25 @@ export class StorageError extends Error {
1313
export interface Storage<
1414
BaseStorageTypes extends Record<string, any> = Record<string, unknown>,
1515
> {
16+
/**
17+
* Reactive access to storage values as Subscribables.
18+
*
19+
* Each key is exposed as a `Subscribable<T | undefined>`, enabling reactive
20+
* updates across targets of the same extension. One target can subscribe to
21+
* a key and react when another target updates it via `set()` or `delete()`.
22+
*
23+
* Only available on API version `2026-04` and later.
24+
*
25+
* @example
26+
* ```typescript
27+
* // Subscribe to changes from another target:
28+
* const unsubscribe = shopify.storage.keys.syncStatus.subscribe((value) => {
29+
* console.log('syncStatus changed:', value);
30+
* });
31+
* ```
32+
*/
33+
keys?: StorageKeys<BaseStorageTypes>;
34+
1635
/**
1736
* Stores a value under the specified key, overwriting any existing value. Values must be JSON-serializable and return `StorageError` when storage limits are exceeded. Commonly used for storing user preferences, caching API responses, or passing contextual data from tiles to modals.
1837
*
@@ -73,3 +92,31 @@ export interface Storage<
7392
Keys extends keyof StorageTypes = keyof StorageTypes,
7493
>(): Promise<[Keys, StorageTypes[Keys]][]>;
7594
}
95+
96+
/**
97+
* Represents a readonly value managed by the host that an extension can
98+
* subscribe to for reactive updates.
99+
*/
100+
export interface Subscribable<Value = unknown> {
101+
/** Synchronous access to the current value. */
102+
readonly value: Value;
103+
/** Registers a callback that fires when the value changes. Returns an unsubscribe function. */
104+
subscribe: (callback: (value: Value) => void) => () => void;
105+
}
106+
107+
/**
108+
* Provides reactive, subscribable access to individual storage keys.
109+
*
110+
* Each property is a `Subscribable` that reflects the current value of the
111+
* corresponding storage key. Values are `undefined` when the key does not exist.
112+
*
113+
* Mutations are performed through the existing `Storage` methods (`set`, `delete`,
114+
* `clear`, etc.) — `StorageKeys` is read-only and reactive.
115+
*/
116+
export type StorageKeys<
117+
BaseStorageTypes extends Record<string, any> = Record<string, unknown>,
118+
> = {
119+
readonly [K in keyof BaseStorageTypes]: Subscribable<
120+
BaseStorageTypes[K] | undefined
121+
>;
122+
};

0 commit comments

Comments
 (0)