@aituber-onair/kizuna
Version:
A sophisticated bond system (絆 - Kizuna) for managing relationships between users and AI characters in AITuber OnAir.
139 lines • 4.26 kB
JavaScript
/**
* StorageProvider - Abstract class for storage providers
*
* Provides a unified interface for different storage systems
* (LocalStorage, IndexedDB, external APIs, etc.)
*/
/**
* Abstract base class for storage providers
*/
export class StorageProvider {
// ============================================================================
// Common utility methods
// ============================================================================
/**
* Serialize data
*/
serialize(data) {
try {
return JSON.stringify(data, this.replacer);
}
catch (error) {
throw new Error(`Failed to serialize data: ${error}`);
}
}
/**
* Deserialize data
*/
deserialize(data) {
try {
return JSON.parse(data, this.reviver);
}
catch (error) {
throw new Error(`Failed to deserialize data: ${error}`);
}
}
/**
* Validate data
*/
validateKey(key) {
if (!key || typeof key !== "string" || key.trim().length === 0) {
throw new Error("Invalid key: key must be a non-empty string");
}
if (key.length > 256) {
throw new Error("Invalid key: key must be less than 256 characters");
}
}
/**
* Get data size (in bytes)
*/
getDataSize(data) {
return new Blob([data]).size;
}
/**
* Generate safe key name
*/
sanitizeKey(key) {
return key.replace(/[^a-zA-Z0-9_\-:.]/g, "_");
}
// ============================================================================
// JSON serialization helpers
// ============================================================================
/**
* Replacer function for JSON.stringify
* Properly serializes special objects like Date and Map
*/
replacer(key, value) {
// Process Date objects
if (value instanceof Date) {
return {
__type: "Date",
value: value.toISOString(),
};
}
// Process Map objects
if (value instanceof Map) {
return {
__type: "Map",
value: Array.from(value.entries()),
};
}
// Process Set objects
if (value instanceof Set) {
return {
__type: "Set",
value: Array.from(value),
};
}
return value;
}
/**
* Reviver function for JSON.parse
* Restores serialized special objects
*/
reviver(key, value) {
if (typeof value === "object" && value !== null && "__type" in value) {
const typedValue = value;
switch (typedValue.__type) {
case "Date":
return new Date(typedValue.value);
case "Map":
return new Map(typedValue.value);
case "Set":
return new Set(typedValue.value);
}
}
return value;
}
}
/**
* Storage error class
*/
export class StorageError extends Error {
constructor(message, code, originalError) {
super(message);
this.code = code;
this.originalError = originalError;
this.name = "StorageError";
}
}
/**
* Storage error codes
*/
export var StorageErrorCode;
(function (StorageErrorCode) {
StorageErrorCode["NOT_AVAILABLE"] = "NOT_AVAILABLE";
StorageErrorCode["QUOTA_EXCEEDED"] = "QUOTA_EXCEEDED";
StorageErrorCode["PERMISSION_DENIED"] = "PERMISSION_DENIED";
StorageErrorCode["NETWORK_ERROR"] = "NETWORK_ERROR";
StorageErrorCode["INVALID_KEY"] = "INVALID_KEY";
StorageErrorCode["INVALID_DATA"] = "INVALID_DATA";
StorageErrorCode["SERIALIZATION_ERROR"] = "SERIALIZATION_ERROR";
StorageErrorCode["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
StorageErrorCode["SAVE_ERROR"] = "SAVE_ERROR";
StorageErrorCode["LOAD_ERROR"] = "LOAD_ERROR";
StorageErrorCode["REMOVE_ERROR"] = "REMOVE_ERROR";
StorageErrorCode["CLEAR_ERROR"] = "CLEAR_ERROR";
StorageErrorCode["INFO_ERROR"] = "INFO_ERROR";
})(StorageErrorCode || (StorageErrorCode = {}));
//# sourceMappingURL=StorageProvider.js.map