@iebh/vuex-tera-json
Version:
A Vuex plugin for syncing state with Tera (using JSON files)
231 lines (230 loc) • 8.09 kB
TypeScript
/**
* Configuration options for the TERA sync plugin.
*/
export interface TeraPluginConfig {
/**
* A unique prefix for storage keys and filenames to avoid conflicts.
* Often the name of the tool, e.g., 'my-awesome-tool'.
* @default ''
*/
keyPrefix?: string;
/**
* If true, a separate state file is maintained for each user.
* If false, the state is shared for the entire project.
* @default false
*/
isSeparateStateForEachUser?: boolean;
/**
* The interval in minutes for automatically saving the state.
* Set to 0 to disable auto-saving.
* @default 15
*/
autoSaveIntervalMinutes?: number;
/**
* If true, shows an initial alert to the user about manual saving (e.g., with Ctrl+S).
* @default false
*/
showInitialAlert?: boolean;
/**
* If true, enables the Ctrl+S (or Cmd+S) hotkey to trigger a manual save.
* @default true
*/
enableSaveHotkey?: boolean;
/**
* If true, the state will be loaded from the TERA file as soon as the plugin is ready.
* If false, the state will not be loaded automatically, and you must call `loadAndApplyStateFromFile()` manually.
* @default true
*/
loadImmediately?: boolean;
/**
* A function that is called before a save is attempted.
* If the function returns `true`, the save proceeds.
* If it returns a string, the save is aborted and the string is shown as a notification to the user.
* If it returns any other value (e.g., `false`), the save is aborted silently.
* @default () => true
*/
onBeforeSave?: () => boolean | string;
}
/**
* Represents the possible save statuses of the state.
*/
export declare enum SaveStatus {
SAVED = "Saved",
UNSAVED = "Unsaved changes",
SAVING = "Saving..."
}
/**
* A simplified representation of the TERA user object.
*/
export interface TeraUser {
id: string | number;
[key: string]: any;
}
/**
* Options for TERA's UI progress indicator.
*/
export interface TeraUiProgressOptions {
title: string;
backdrop: 'static' | boolean;
}
/**
* Options for TERA's project file selection dialog.
*/
export interface TeraSelectProjectFileOptions {
title: string;
showHiddenFiles: boolean;
}
/**
* A simplified representation of a TERA project file object.
*/
export interface TeraProjectFile {
path: string;
modified: string | number | Date;
getContents(options?: {
format: 'json' | 'text';
}): Promise<any>;
setContents(data: any): Promise<void>;
}
/**
* The `$tera` API object expected to be available on the Vue instance.
*/
export interface TeraApi {
project: {
id: string | number;
temp: Record<string, any>;
};
getUser(): Promise<TeraUser>;
getProjectFile(fileName: string, options?: {
cache: boolean;
}): Promise<TeraProjectFile | null>;
getProjectFileContents(encodedFileName: string, options?: {
format: 'json' | 'text';
}): Promise<any>;
setProjectFileContents(encodedFileName: string, data: any, options?: {
format: 'json';
}): Promise<void>;
createProjectFile(fileName: string): Promise<TeraProjectFile>;
setProjectState(key: string, value: any): Promise<void>;
selectProjectFile(options: TeraSelectProjectFileOptions): Promise<TeraProjectFile | null>;
uiProgress(options: TeraUiProgressOptions | false): Promise<void>;
}
/**
* A representation of the Vue instance required by the plugin.
*/
export interface VueInstance {
$tera: TeraApi;
/** Optional notification function, e.g., from Element UI. */
$notify?(options: any): void;
}
/**
* A generic interface for a Vuex-like store.
*/
export interface VuexStore {
state: any;
commit(mutationType: string, payload?: any): void;
subscribe(handler: (mutation: any, state: any) => any): () => void;
hasModule(path: string | string[]): boolean;
registerModule(path: string | string[], module: any, options?: any): void;
unregisterModule(path: string | string[]): void;
replaceState(state: any): void;
}
/**
* A generic interface for a Pinia-like store.
*/
export interface PiniaStore {
$id: string;
$patch(state: Partial<any>): void;
$subscribe(callback: (mutation: any, state: any) => void, options?: any): () => void;
$state: any;
saveStatus?: SaveStatus;
}
/**
* Interface for a custom store aggregator object.
* This allows managing state from multiple stores or sources.
*/
export interface PlainObjectStore {
/** Returns the complete state object to be serialized. */
getState(): any;
/** Replaces the state with the new state object from a file. */
replaceState(newState: any): void;
/** Updates the save status indicator. */
updateSaveStatus(status: SaveStatus): void;
/** Subscribes to state changes and returns an unsubscribe function. */
subscribe(callback: (mutation?: any) => void): () => void;
}
/**
* A union type representing any compatible store that can be passed to `createTeraSync`.
*/
export type SyncableStore = VuexStore | PiniaStore | PlainObjectStore;
/**
* Metadata for the storage file.
*/
export interface FileMetadata {
modified: Date;
}
/**
* The public API of the TERA File Sync plugin instance.
*/
export interface TeraFileSync {
/**
* The final, merged configuration object being used by the plugin.
*/
readonly config: TeraPluginConfig;
/**
* A flag indicating if the plugin has completed its initial setup.
*/
readonly initialized: boolean;
/**
* The current save status of the state.
*/
readonly saveStatus: SaveStatus;
/**
* Informs the plugin that the TERA environment is ready. This must be called
* after the Vue instance is mounted and `$tera` is available.
* It triggers the initial state load based on the `loadImmediately` config.
* @returns A promise that resolves when initialization is complete.
*/
setTeraReady(): Promise<void>;
/**
* Provides the Vue instance to the plugin. This is required for the plugin
* to interact with the TERA API.
* @param instance The Vue component instance.
*/
setVueInstance(instance: VueInstance): void;
/**
* Manually saves the current state to the configured TERA file.
* @returns A promise that resolves to `true` if the save was successful, `false` otherwise.
*/
saveState(): Promise<boolean>;
/**
* Prompts the user to select a JSON file via the TERA file picker,
* loads its content into the store, and sets it as the new target file for future saves.
* @returns A promise that resolves when the operation is complete.
*/
promptForNewJsonFile(): Promise<void>;
/**
* Manually triggers a load from the configured TERA file and replaces the store's state.
* Useful for re-syncing with the file system if `loadImmediately` was false.
* @returns A promise that resolves to `true` if the load was successful, `false` otherwise.
*/
loadAndApplyStateFromFile(): Promise<boolean>;
/**
* Retrieves metadata for the storage file.
* @returns A promise that resolves to an object with file metadata (e.g., last modified date) or null if the file doesn't exist.
*/
getFileMetadata(): Promise<FileMetadata | null>;
/**
* Cleans up all resources used by the plugin, including timers and event listeners.
* Should be called when the component using the plugin is destroyed.
*/
destroy(): void;
}
/**
* Creates and initializes a new TERA file sync manager.
* This is the main entry point for using the plugin.
*
* @param config - Plugin configuration options.
* @param store - The Vuex store, Pinia store, or a custom aggregator object that conforms to the `PlainObjectStore` interface.
* @returns The plugin instance, providing a public API to manage state synchronization.
*/
export declare function createTeraSync(config: TeraPluginConfig, store: SyncableStore): TeraFileSync;