@grafana/runtime
Version:
Grafana Runtime Library
1 lines • 8.84 kB
Source Map (JSON)
{"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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"}