@iebh/vuex-tera-json
Version:
A Vuex plugin for syncing state with Tera (using JSON files)
332 lines (331 loc) • 12.3 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;
/**
* An optional function that resets the store to its initial, default state.
* This is called before loading data from a file to ensure new state properties
* are initialized correctly.
* For Pinia, this would typically be `() => store.$reset()`.
* For Vuex, `() => store.commit('RESET_STATE')`.
*/
resetState?: () => void | Promise<void>;
}
/**
* Represents the possible save statuses of the state.
*/
export declare enum SaveStatus {
/** Indicates that all current changes are safely stored */
SAVED = "Saved",
/** Indicates that there are modifications pending to be saved */
UNSAVED = "Unsaved changes",
/** Indicates that a save operation is currently in progress */
SAVING = "Saving..."
}
/**
* A simplified representation of the TERA user object.
*/
export interface TeraUser {
/** The unique identifier of the user */
id: string | number;
/** Additional custom properties */
[key: string]: any;
}
/**
* Options for TERA's UI progress indicator.
*/
export interface TeraUiProgressOptions {
/** The text title to display in the progress indicator */
title: string;
/**
* Defines the backdrop behaviour.
* 'static' prevents closing the progress UI when clicking outside.
*/
backdrop: 'static' | boolean;
}
/**
* Options for TERA's project file selection dialog.
*/
export interface TeraSelectProjectFileOptions {
/** The title of the file selection dialog */
title: string;
/** Whether to show hidden files in the selection dialog */
showHiddenFiles: boolean;
/** File filters to restrict what can be selected */
filters?: {
/** The file extension to filter by (e.g., 'json') */
ext: string;
};
}
/**
* A simplified representation of a TERA project file object.
*/
export interface TeraProjectFile {
/** The absolute or relative path to the file */
path: string;
/** The last modification date/time of the file */
modified: string | number | Date;
/**
* Retrieves the contents of the file.
* @param options Format options for reading the file.
* @returns A promise resolving to the file contents.
*/
getContents(options?: {
format: 'json' | 'text';
}): Promise<any>;
/**
* Sets the contents of the file.
* @param data The data to write to the file.
* @returns A promise resolving when the write is complete.
*/
setContents(data: any): Promise<void>;
}
/**
* The `$tera` API object expected to be available on the Vue instance.
*/
export interface TeraApi {
/** Information relating to the current active project */
project: {
/** The unique ID of the project */
id: string | number;
/** Temporary storage associated with the project */
temp: Record<string, any>;
};
/** Fetches the active TERA user */
getUser(): Promise<TeraUser>;
/** Retrieves standard TERA application credentials */
getCredentials(): object;
/** Retrieves the Kinde authentication token */
getKindeToken(): string;
/**
* Retrieves a specific project file without its content.
* @param fileName The name of the file to retrieve.
* @param options Caching options.
* @returns A promise resolving to the file object, or null if not found.
*/
getProjectFile(fileName: string, options?: {
cache: boolean;
}): Promise<TeraProjectFile | null>;
/**
* Retrieves the contents of a specific project file.
* @param encodedFileName The URI-encoded name of the file to read.
* @param options Format parsing options.
* @returns A promise resolving to the content.
*/
getProjectFileContents(encodedFileName: string, options?: {
format: 'json' | 'text';
}): Promise<any>;
/**
* Writes data to a specific project file.
* @param encodedFileName The URI-encoded name of the file.
* @param data The content payload to write.
* @param options Setting options.
*/
setProjectFileContents(encodedFileName: string, data: any, options?: {
format: 'json';
}): Promise<void>;
/**
* Creates a new project file securely.
* @param fileName The name of the new file.
* @returns A promise resolving to the new file object.
*/
createProjectFile(fileName: string): Promise<TeraProjectFile>;
/**
* Updates state data bound to the current project context.
* @param key The state key to update.
* @param value The value to associate with the key.
*/
setProjectState(key: string, value: any): Promise<void>;
/**
* Prompts the user with a UI dialog to select a project file.
* @param options Configuration for the file picker.
* @returns A promise resolving to the selected file, or null if cancelled.
*/
selectProjectFile(options: TeraSelectProjectFileOptions): Promise<TeraProjectFile | null>;
/**
* Toggles or configures the TERA-level UI progress overlay.
* @param options Progress config, or `false` to hide.
*/
uiProgress(options: TeraUiProgressOptions | false): Promise<void>;
}
/**
* A representation of the Vue instance required by the plugin.
*/
export interface VueInstance {
/** The TERA API object natively injected into the application */
$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 {
/** The root state object */
state: any;
/** Commits a mutation */
commit(mutationType: string, payload?: any): void;
/** Subscribes to store mutations */
subscribe(handler: (mutation: any, state: any) => any): () => void;
/** Checks if a module is registered at the given path */
hasModule(path: string | string[]): boolean;
/** Registers a dynamic module */
registerModule(path: string | string[], module: any, options?: any): void;
/** Unregisters a dynamic module */
unregisterModule(path: string | string[]): void;
/** Replaces the root state */
replaceState(state: any): void;
}
/**
* A generic interface for a Pinia-like store.
*/
export interface PiniaStore {
/** The unique identifier of the store */
$id: string;
/** Applies a state patch */
$patch(state: Partial<any>): void;
/** Subscribes to state/mutation changes */
$subscribe(callback: (mutation: any, state: any) => void, options?: any): () => void;
/** The actual state object */
$state: any;
/** Optional tracking property for the save status */
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 | Promise<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 {
/** The date the file was last modified */
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 a backup copy of the current data file.
* @returns A promise that resolves to `true` if the backup was successful, `false` otherwise.
*/
createDataFileBackup(): Promise<boolean>;
}
/**
* 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;