UNPKG

@grafana/runtime

Version:
1 lines 8.75 kB
{"version":3,"file":"userStorage.mjs","sources":["../../../src/utils/userStorage.tsx"],"sourcesContent":["import { get } from 'lodash';\nimport { lastValueFrom } from 'rxjs';\n\nimport { usePluginContext, type UserStorage as UserStorageType } from '@grafana/data';\n\nimport { config } from '../config';\nimport { BackendSrvRequest, getBackendSrv } from '../services';\n\nconst baseURL = `/apis/userstorage.grafana.app/v0alpha1/namespaces/${config.namespace}/user-storage`;\n\ninterface RequestOptions extends BackendSrvRequest {\n manageError?: (err: unknown) => { error: unknown };\n showErrorAlert?: boolean;\n\n // rtk codegen sets this\n body?: BackendSrvRequest['data'];\n}\n\nexport type UserStorageSpec = {\n data: { [key: string]: string };\n};\n\nasync function apiRequest<T>(requestOptions: RequestOptions) {\n try {\n const { data: responseData, ...meta } = await lastValueFrom(\n getBackendSrv().fetch<T>({\n ...requestOptions,\n url: baseURL + requestOptions.url,\n data: requestOptions.body,\n showErrorAlert: false,\n })\n );\n return { data: responseData, meta };\n } catch (error) {\n return requestOptions.manageError ? requestOptions.manageError(error) : { error };\n }\n}\n\n/**\n * A class for interacting with the backend user storage.\n * Exposed internally only to avoid misuse (wrong service name)..\n */\nexport class UserStorage implements UserStorageType {\n private service: string;\n private resourceName: string;\n private userUID: string;\n private canUseUserStorage: boolean;\n private storageSpec: UserStorageSpec | null | undefined;\n\n constructor(service: string) {\n this.service = service;\n this.userUID = config.bootData.user.uid === '' ? config.bootData.user.id.toString() : config.bootData.user.uid;\n this.resourceName = `${service}:${this.userUID}`;\n this.canUseUserStorage = config.bootData.user.isSignedIn;\n }\n\n private async init() {\n if (this.storageSpec !== undefined) {\n return;\n }\n const userStorage = await apiRequest<{ spec: UserStorageSpec }>({\n url: `/${this.resourceName}`,\n method: 'GET',\n manageError: (error) => {\n if (get(error, 'status') === 404) {\n this.storageSpec = null;\n return { error: null };\n }\n return { error };\n },\n });\n if ('error' in userStorage) {\n return userStorage.error;\n }\n this.storageSpec = userStorage.data.spec;\n return;\n }\n\n async getItem(key: string): Promise<string | null> {\n if (!this.canUseUserStorage) {\n // Fallback to localStorage\n return localStorage.getItem(`${this.resourceName}:${key}`);\n }\n // Ensure this.storageSpec is initialized\n await this.init();\n if (!this.storageSpec) {\n // Also, fallback to localStorage for backward compatibility\n return localStorage.getItem(`${this.resourceName}:${key}`);\n }\n return this.storageSpec.data[key];\n }\n\n async setItem(key: string, value: string): Promise<void> {\n if (!this.canUseUserStorage) {\n // Fallback to localStorage\n localStorage.setItem(`${this.resourceName}:${key}`, value);\n return;\n }\n\n const newData = { data: { [key]: value } };\n // Ensure this.storageSpec is initialized\n const error = await this.init();\n if (error) {\n // Fallback to localStorage\n localStorage.setItem(`${this.resourceName}:${key}`, value);\n return;\n }\n\n if (!this.storageSpec) {\n // No user storage found, create a new one\n await apiRequest<UserStorageSpec>({\n url: `/`,\n method: 'POST',\n body: {\n metadata: { name: this.resourceName, labels: { user: this.userUID, service: this.service } },\n spec: newData,\n },\n manageError: (error) => {\n // Fallback to localStorage\n localStorage.setItem(`${this.resourceName}:${key}`, value);\n return { error };\n },\n });\n this.storageSpec = newData;\n return;\n }\n\n // Update existing user storage\n this.storageSpec.data[key] = value;\n await apiRequest<UserStorageSpec>({\n headers: { 'Content-Type': 'application/merge-patch+json' },\n url: `/${this.resourceName}`,\n method: 'PATCH',\n body: { spec: newData },\n manageError: (error) => {\n // Fallback to localStorage\n localStorage.setItem(`${this.resourceName}:${key}`, value);\n return { error };\n },\n });\n }\n}\n\n// This is a type alias to avoid breaking changes\nexport interface PluginUserStorage extends UserStorageType {}\n\n/**\n * A hook for interacting with the backend user storage (or local storage if not enabled).\n * @returns An scoped object for a plugin and a user with getItem and setItem functions.\n * @alpha Experimental\n */\nexport function usePluginUserStorage(): PluginUserStorage {\n const context = usePluginContext();\n if (!context) {\n throw new Error(`No PluginContext found. The usePluginUserStorage() hook can only be used from a plugin.`);\n }\n return new UserStorage(context?.meta.id);\n}\n"],"names":["error"],"mappings":"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"}