Local-storage-backed persistence for GraphDB Workbench, built on the Persistence interface and LocalStorageService.
Persistence API: the generic storage interface.Persistence interface and its methods.LocalStorageService, namespaces, and key prefixing.Persistence APIThe Persistence API provides a generic interface for interacting with a storage system. It supports storing,
retrieving, and removing data via a Storage-compatible implementation (e.g., localStorage or sessionStorage).
The code is in packages/api/src/services/storage/.
Persistence Interface
The Persistence interface defines the structure for storage-related services:
getStorage(): Storage - Returns the underlying storage implementation.get(key: string): StorageData - Retrieves the value associated with the provided key.set(key: string, value: string): void - Stores the given value under the provided key.remove(key: string): void - Deletes the value associated with the provided key.The LocalStorageService abstract class implements the Persistence interface using localStorage. It is the base
class for specialized storage services.
1. Namespace Support:
NAMESPACE to scope its keys.<global>.<NAMESPACE>.<key>, where the global prefix is StorageKey.GLOBAL_NAMESPACE
(ontotext.gdb).2. Storage Methods:
get(key: string, usePrefixedKey = true): StorageData - Reads a value. Pass false to read a raw, unprefixed key.getAsJson<T>(key: string): T | null - Reads a raw key and parses it as JSON; null if missing or invalid.storeValue(key: string, value: string): void - Saves a value under the prefixed key.remove(key: string, usePrefixedKey = true): void - Removes a value.Subclasses implement set(key, value), usually by calling storeValue.
3. Key Management:
getPrefixedKey(key) adds whatever part of the prefix is missing: a bare key gets both prefixes, a key
that already starts with <NAMESPACE>. gets only the global one, and a fully prefixed key is left as is.export class LanguageStorageService extends LocalStorageService {
readonly NAMESPACE = 'i18n';
set(key: string, value: string) {
this.storeValue(key, value);
}
}
LanguageStorageService stores language-related properties under the ontotext.gdb.i18n. prefix.
LocalStorageSubscriptionHandlerService keeps the context in sync when localStorage changes in another tab.
onto-layout listens for the window’s storage event and passes it to handleStorageChange.
StorageEvent, the service strips the global prefix and splits the rest into the namespace and the property
name.ServiceProvider.getAllBySuperType(ContextService)):
the first whose canHandle(propertyName) is true. The namespace is only required to be present.deserializeProperty() turns the raw string into a value (see
Context API), and updateContextProperty() sets it. A removed key
sets undefined.handleStorageChange(event: StorageEvent): void {
const withoutGlobalPrefix = event.key?.substring(StorageKey.GLOBAL_NAMESPACE.length + 1);
let namespace = '';
let contextPropertyKey = '';
if (withoutGlobalPrefix) {
namespace = withoutGlobalPrefix.substring(0, withoutGlobalPrefix.indexOf('.'));
contextPropertyKey = withoutGlobalPrefix.substring(namespace.length + 1);
}
const handler = this.resolveHandler(namespace, contextPropertyKey);
if (handler) {
let newValue;
if (event.newValue !== null) {
newValue = handler.deserializeProperty(contextPropertyKey, event.newValue);
}
handler.updateContextProperty(contextPropertyKey, newValue);
}
}
LocalStorageService subclass so keys are prefixed and isolated.LocalStorageService per domain, specifying the NAMESPACE.selectedRepository), so canHandle finds the service.See also: Developers Guide