Skip to content

Add Storage API for Admin #3095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {I18n} from '../../../../api';
import {ApiVersion} from '../../../../shared';
import type {Storage} from '../storage/storage';
import type {ExtensionTarget as AnyExtensionTarget} from '../../extension-targets';

export interface Intents {
Expand Down Expand Up @@ -54,6 +55,11 @@ export interface StandardApi<ExtensionTarget extends AnyExtensionTarget> {
*/
intents: Intents;

/**
* Provides methods for setting, getting, and clearing browser data from the extension
*/
storage: Storage;

/**
* Used to query the Admin GraphQL API
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs';

const data: ReferenceEntityTemplateSchema = {
name: 'Storage',
description:
"This API is used to store data in the extension. It allows you to set, get, and manage key-value pairs within the app's allocated storage space. This is useful for persisting state or configuration data across user sessions.",
isVisualComponent: false,
type: 'API',
definitions: [
{
title: 'Storage',
description: '',
type: 'Storage',
},
],
category: 'API',
subCategory: 'Target APIs',
related: [],
};

export default data;
110 changes: 110 additions & 0 deletions packages/ui-extensions/src/surfaces/admin/api/storage/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
export interface Storage<
BaseStorageTypes extends Record<string, any> = Record<string, unknown>,
> {
/**
* Sets the value of a key in the storage.
*
* @param key - The key to set the value for.
* @param value - The value to set for the key.
* Can be any primitive type supported by `JSON.stringify`.
*
* Rejects with a `StorageExceededError` if the extension exceeds its allotted storage limit.
*/
set<
StorageTypes extends BaseStorageTypes = BaseStorageTypes,
Keys extends keyof StorageTypes = keyof StorageTypes,
>(
key: Keys,
value: StorageTypes[Keys],
): Promise<void>;

/**
* Sets multiple key-value pairs in the storage at once.
*
* If the operation fails, no changes are made to storage.
*
* @param entries - An object containing key-value pairs to store.
* Values can be any primitive type supported by `JSON.stringify`.
*
* Rejects with a `StorageExceededError` if the extension exceeds its allotted storage limit.
*/
setMany<StorageTypes extends BaseStorageTypes = BaseStorageTypes>(
entries: Partial<StorageTypes>,
): Promise<void>;

/**
* Gets the value of a key in the storage.
*
* @param key - The key to get the value for.
* @returns The value of the key.
*
* If no value for the key exists, the resolved value is undefined.
*/
get<
StorageTypes extends BaseStorageTypes = BaseStorageTypes,
Keys extends keyof StorageTypes = keyof StorageTypes,
>(
key: Keys,
): Promise<StorageTypes[Keys] | undefined>;

/**
* Gets the values of multiple keys in the storage at once.
*
* @param keys - An array of keys to get the values for.
* @returns An object containing key-value pairs for the requested keys.
*
* The returned array is in the same order as `keys`, with `undefined` values for keys that do not exist.
*/
getMany<
StorageTypes extends BaseStorageTypes = BaseStorageTypes,
Keys extends keyof StorageTypes = keyof StorageTypes,
>(
keys: Keys[],
): Promise<(StorageTypes[Keys] | undefined)[]>;

/**
* Clears the storage.
*/
clear(): Promise<void>;

/**
* Deletes a key from the storage.
*
* @param key - The key to delete.
* @returns A promise that resolves to `true` if the key was deleted, or `false` if the key did not exist.
*/
delete<
StorageTypes extends BaseStorageTypes = BaseStorageTypes,
Keys extends keyof StorageTypes = keyof StorageTypes,
>(
key: Keys,
): Promise<boolean>;

/**
* Deletes multiple keys from the storage at once.
*
* @param keys - An array of keys to delete.
* @returns A promise that resolves to an object with `keys` keys, and boolean values,
* which are `true` if the key was deleted, or `false` if the key did not exist.
*/
deleteMany<
StorageTypes extends BaseStorageTypes = BaseStorageTypes,
Keys extends keyof StorageTypes = keyof StorageTypes,
>(
keys: Keys[],
): Promise<Record<Keys, boolean>>;

/**
* Gets all the keys and values in the storage.
*
* @returns An iterator containing all the keys and values in the storage.
*/
entries<
StorageTypes extends BaseStorageTypes = BaseStorageTypes,
Keys extends keyof StorageTypes = keyof StorageTypes,
>(): Promise<IterableIterator<[Keys, StorageTypes[Keys]]>>;
}

export interface StorageExceededError extends Error {
name: 'StorageExceededError';
}