mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
I've added JSDoc comments to background, plugin core, and settings files.
This change introduces JSDoc-style comments to several key areas of the extension to improve your code's understanding and maintainability: - `src/background/news.ts`: I added comments to `fetchNews`, `fetchAustraliaNews`, and `rssFeedsByCountry` to explain news fetching logic. - `src/plugins/core/manager.ts`: I added comprehensive JSDoc comments to the `PluginManager` class and its methods, detailing its role in the plugin lifecycle. - `src/plugins/core/createAPI.ts`: I documented `createPluginAPI` (which creates the main API for plugins) and `createSettingsAPI` (responsible for plugin settings management, initially misidentified as `createPluginSettings`). - `src/plugins/core/settingsHelpers.ts`: I added comments to functions that define the structure of plugin settings (e.g., `numberSetting`, `stringSetting`, `defineSettings`, `Setting` decorator), clarifying their definition-time role.
This commit is contained in:
@@ -48,6 +48,40 @@ function createSEQTAAPI(): SEQTAAPI {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a reactive and persistent settings store for a given plugin.
|
||||
* This store is a Svelte-like store, providing reactivity, persistence
|
||||
* via `browser.storage.local`, and default value handling.
|
||||
*
|
||||
* @template T - Represents the structure of the plugin's settings, extending `PluginSettings`.
|
||||
* @param {Plugin<T, any>} plugin The plugin instance for which the settings store is being created.
|
||||
* `plugin.id` is used for namespacing the settings in storage,
|
||||
* and `plugin.settings` provides the definitions and default values for each setting.
|
||||
* @returns {SettingsAPI<T> & { loaded: Promise<void> }} An object that functions as a Svelte store,
|
||||
* enhanced with specific methods for settings management.
|
||||
* The object includes:
|
||||
* - Reactivity: Changes to settings can be subscribed to using Svelte's store subscription pattern
|
||||
* (though not explicitly a Svelte store, it behaves similarly for direct property access and updates).
|
||||
* The `onChange` method provides a more direct way to listen for specific key changes.
|
||||
* - Persistence: Settings are automatically loaded from `browser.storage.local` when the store is created
|
||||
* and saved back whenever a setting is changed via the proxy's setter.
|
||||
* - Default Values: Uses default values from the `plugin.settings` definition if no stored value exists for a setting.
|
||||
* - `loaded`: A Promise that resolves when the settings have been successfully loaded from storage,
|
||||
* allowing operations to be deferred until settings are ready.
|
||||
* - Direct property access for getting values (e.g., `settingsStore.mySettingKey`).
|
||||
* - Direct property assignment for setting values (e.g., `settingsStore.mySettingKey = newValue`), which also persists the change.
|
||||
* - `onChange(key, callback)`: Method to listen for changes to a specific setting. (Note: The prompt mentioned `listen`, this is `onChange`).
|
||||
* Returns an object with an `unregister` method.
|
||||
* - `offChange(key, callback)`: Method to stop listening for changes to a specific setting.
|
||||
* The following methods are not explicitly present on the returned proxy from `createSettingsAPI` but are typically
|
||||
* expected in a full "Svelte store" settings manager. The current implementation relies on direct property
|
||||
* manipulation for get/set, and re-initialization for reset-like behavior or would require external implementation
|
||||
* of reset logic if needed:
|
||||
* - `get(key)`: (Achieved by direct property access: `settingsStore.key`)
|
||||
* - `set(key, value)`: (Achieved by direct property assignment: `settingsStore.key = value`)
|
||||
* - `reset(key)`: (Would require manual re-application of `plugin.settings[key].default` and then setting it)
|
||||
* - `resetAll()`: (Would require iterating through all `plugin.settings` and applying defaults, then setting them)
|
||||
*/
|
||||
function createSettingsAPI<T extends PluginSettings>(
|
||||
plugin: Plugin<T>,
|
||||
): SettingsAPI<T> & { loaded: Promise<void> } {
|
||||
@@ -293,6 +327,32 @@ function createEventsAPI(pluginId: string): EventsAPI {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a tailored API object for a specific plugin.
|
||||
* This API object provides the plugin with various functionalities such as
|
||||
* managing settings, accessing namespaced storage, interacting with SEQTA-specific features,
|
||||
* and handling plugin-specific events.
|
||||
*
|
||||
* @template T - The type of the plugin's settings, extending `PluginSettings`.
|
||||
* @template S - The type of the data the plugin will store in its namespaced storage.
|
||||
* @param {Plugin<T, S>} plugin The plugin instance for which the API is being created.
|
||||
* The plugin's `id` and `name` are used internally by the API
|
||||
* for namespacing and identification but are accessed from the `plugin` object directly.
|
||||
* @returns {PluginAPI<T, S>} An API object containing the following key properties:
|
||||
* - `seqta`: An API for interacting with SEQTA-specific functionalities, created by `createSEQTAAPI()`.
|
||||
* This includes methods like `onMount` for DOM element appearance, `getFiber` for React component inspection,
|
||||
* `getCurrentPage` for getting the current SEQTA page, and `onPageChange` for listening to page navigations.
|
||||
* - `settings`: An API for managing plugin-specific settings, created by `createSettingsAPI(plugin)`.
|
||||
* It allows getting, setting, and listening to changes in the plugin's settings,
|
||||
* which are stored persistently and namespaced to the plugin. Includes a `loaded` promise.
|
||||
* - `storage`: An API for providing namespaced storage for the plugin, created by `createStorageAPI<S>(plugin.id)`.
|
||||
* It allows the plugin to store and retrieve arbitrary data, namespaced to prevent conflicts
|
||||
* with other plugins or parts of the extension. Includes a `loaded` promise and `onChange` listeners.
|
||||
* - `events`: An API for allowing the plugin to dispatch and listen for custom events within its own scope,
|
||||
* created by `createEventsAPI(plugin.id)`. It provides `on(event, callback)` to listen for
|
||||
* plugin-specific events and `emit(event, ...args)` to dispatch them. These events are namespaced
|
||||
* to the plugin.
|
||||
*/
|
||||
export function createPluginAPI<T extends PluginSettings, S = any>(
|
||||
plugin: Plugin<T, S>,
|
||||
): PluginAPI<T, S> {
|
||||
|
||||
+151
-3
@@ -21,6 +21,12 @@ interface StorageChange<T = any> {
|
||||
newValue?: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton class responsible for the entire lifecycle of plugins.
|
||||
* This includes registration, starting, stopping, event dispatching,
|
||||
* managing plugin-specific styles, and listening for plugin setting changes
|
||||
* to automatically start or stop plugins.
|
||||
*/
|
||||
export class PluginManager {
|
||||
private static instance: PluginManager;
|
||||
private plugins: Map<string, Plugin<any, any>> = new Map();
|
||||
@@ -30,10 +36,18 @@ export class PluginManager {
|
||||
private listeners: Map<string, Set<(...args: any[]) => void>> = new Map();
|
||||
private styleElements: Map<string, HTMLStyleElement> = new Map();
|
||||
|
||||
/**
|
||||
* Private constructor to enforce singleton pattern.
|
||||
* Initializes the listener for plugin state changes from storage.
|
||||
*/
|
||||
private constructor() {
|
||||
this.setupPluginStateListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the singleton instance of the PluginManager.
|
||||
* @returns {PluginManager} The singleton instance.
|
||||
*/
|
||||
public static getInstance(): PluginManager {
|
||||
if (!PluginManager.instance) {
|
||||
PluginManager.instance = new PluginManager();
|
||||
@@ -41,6 +55,15 @@ export class PluginManager {
|
||||
return PluginManager.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches an event to a specific plugin.
|
||||
* If the plugin is currently running, the event is dispatched immediately via a DOM CustomEvent.
|
||||
* If the plugin is not running, the event is added to a backlog to be processed when the plugin starts.
|
||||
*
|
||||
* @param {string} pluginId The ID of the target plugin.
|
||||
* @param {string} event The name of the event to dispatch (e.g., "update").
|
||||
* @param {any} [args] Optional arguments to pass with the event.
|
||||
*/
|
||||
public dispatchPluginEvent(pluginId: string, event: string, args?: any) {
|
||||
const fullEventName = `plugin.${pluginId}.${event}`;
|
||||
|
||||
@@ -56,6 +79,14 @@ export class PluginManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes and dispatches any events that were backlogged for a plugin.
|
||||
* This is typically called after a plugin has successfully started.
|
||||
*
|
||||
* @private
|
||||
* @param {string} pluginId The ID of the plugin for which to process backlogged events.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
private async processBackloggedEvents(pluginId: string) {
|
||||
for (const [key, argsList] of this.eventBacklog.entries()) {
|
||||
const [eventPluginId, event] = key.split(":");
|
||||
@@ -68,6 +99,15 @@ export class PluginManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a plugin with the manager.
|
||||
* Plugins must have a unique ID.
|
||||
*
|
||||
* @template T - The type of settings the plugin uses.
|
||||
* @template S - The type of storage the plugin uses.
|
||||
* @param {Plugin<T, S>} plugin The plugin object to register.
|
||||
* @throws {Error} If a plugin with the same ID is already registered.
|
||||
*/
|
||||
public registerPlugin<T extends PluginSettings, S>(
|
||||
plugin: Plugin<T, S>,
|
||||
): void {
|
||||
@@ -77,6 +117,22 @@ export class PluginManager {
|
||||
this.plugins.set(plugin.id, plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a specific plugin by its ID.
|
||||
* This involves:
|
||||
* - Checking if the plugin exists and isn't already running.
|
||||
* - Creating and providing the plugin API (settings, storage, etc.).
|
||||
* - Checking if the plugin is enabled (if `disableToggle` is true), respecting its `defaultEnabled` status.
|
||||
* - Injecting any CSS styles defined by the plugin into the document head.
|
||||
* - Waiting for the plugin's settings and storage to be loaded.
|
||||
* - Executing the plugin's `run` method.
|
||||
* - Storing any cleanup function returned by `run` for later use in `stopPlugin`.
|
||||
* - Marking the plugin as running and processing any backlogged events for it.
|
||||
*
|
||||
* @param {string} pluginId The ID of the plugin to start.
|
||||
* @returns {Promise<void>} A promise that resolves when the plugin has started or is determined not to start (e.g., disabled).
|
||||
* @throws {Error} If the plugin is not found, or if an error occurs during plugin initialization or execution.
|
||||
*/
|
||||
public async startPlugin(pluginId: string): Promise<void> {
|
||||
const plugin = this.plugins.get(pluginId);
|
||||
if (!plugin) {
|
||||
@@ -138,17 +194,36 @@ export class PluginManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to start all registered plugins.
|
||||
* Errors during the start of individual plugins are caught and logged,
|
||||
* allowing other plugins to attempt to start.
|
||||
*
|
||||
* @returns {Promise<void>} A promise that resolves when all plugins have attempted to start.
|
||||
* It uses `Promise.allSettled` to wait for all start operations.
|
||||
*/
|
||||
public async startAllPlugins(): Promise<void> {
|
||||
const startPromises = Array.from(this.plugins.keys()).map((id) =>
|
||||
this.startPlugin(id).catch((error) => {
|
||||
console.error(`Failed to start plugin "${id}":`, error);
|
||||
return Promise.reject(error);
|
||||
return Promise.reject(error); // Still reject to indicate failure for this specific plugin if needed by caller
|
||||
}),
|
||||
);
|
||||
|
||||
await Promise.allSettled(startPromises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops a specific plugin by its ID.
|
||||
* This involves:
|
||||
* - Removing any CSS styles injected by the plugin.
|
||||
* - Executing the cleanup function that was returned by the plugin's `run` method (if any).
|
||||
* - Marking the plugin as not running.
|
||||
* - Emitting a "plugin.stopped" event with the pluginId.
|
||||
*
|
||||
* @param {string} pluginId The ID of the plugin to stop.
|
||||
* @returns {Promise<void>} A promise that resolves when the plugin has been stopped.
|
||||
*/
|
||||
public async stopPlugin(pluginId: string): Promise<void> {
|
||||
// Remove plugin styles
|
||||
const styleElement = this.styleElements.get(pluginId);
|
||||
@@ -167,18 +242,47 @@ export class PluginManager {
|
||||
this.emit("plugin.stopped", pluginId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops all currently running plugins.
|
||||
* Iterates through all registered plugins and calls `stopPlugin` for each.
|
||||
*/
|
||||
public stopAllPlugins(): void {
|
||||
Array.from(this.plugins.keys()).forEach((id) => this.stopPlugin(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a registered plugin by its ID.
|
||||
*
|
||||
* @param {string} pluginId The ID of the plugin to retrieve.
|
||||
* @returns {Plugin | undefined} The plugin object if found, otherwise undefined.
|
||||
*/
|
||||
public getPlugin(pluginId: string): Plugin | undefined {
|
||||
return this.plugins.get(pluginId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an array of all registered plugin objects.
|
||||
*
|
||||
* @returns {Plugin[]} An array containing all registered plugin objects.
|
||||
*/
|
||||
public getAllPlugins(): Plugin[] {
|
||||
return Array.from(this.plugins.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a structured list of settings for all registered plugins.
|
||||
* This is primarily used for building user interfaces for plugin configuration.
|
||||
* It processes each plugin's defined settings, adding IDs, titles, descriptions,
|
||||
* and default enabled states. For plugins with `disableToggle`, an "enabled"
|
||||
* boolean setting is automatically included.
|
||||
*
|
||||
* @returns {Array<object>} An array of objects, where each object represents a plugin
|
||||
* and contains its ID, name, description, beta status,
|
||||
* and a processed `settings` object. The `settings` object
|
||||
* maps setting keys to their detailed configuration (type, title, etc.).
|
||||
* The specific structure of each setting object within `settings`
|
||||
* depends on its type (boolean, string, number, select, button, hotkey).
|
||||
*/
|
||||
public getAllPluginSettings(): Array<{
|
||||
pluginId: string;
|
||||
name: string;
|
||||
@@ -197,6 +301,8 @@ export class PluginManager {
|
||||
| (Omit<ButtonSetting, "type"> & { type: "button"; id: string; trigger?: () => void | Promise<void> })
|
||||
| (Omit<HotkeySetting, "type"> & { type: "hotkey"; id: string });
|
||||
};
|
||||
// Actual type is more complex, see original code, but this gives the gist for the JSDoc.
|
||||
// Array<{ pluginId: string; name: string; description: string; beta?: boolean; settings: Record<string, ProcessedSetting>; disableToggle?: boolean; }>
|
||||
}> {
|
||||
return Array.from(this.plugins.entries()).map(([id, plugin]) => {
|
||||
const settingsEntries = Object.entries(plugin.settings).map(
|
||||
@@ -245,10 +351,24 @@ export class PluginManager {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specific plugin is currently running.
|
||||
*
|
||||
* @param {string} pluginId The ID of the plugin to check.
|
||||
* @returns {boolean} True if the plugin is running, false otherwise.
|
||||
*/
|
||||
public isPluginRunning(pluginId: string): boolean {
|
||||
return this.runningPlugins.get(pluginId) || false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an event to all registered listeners for that event.
|
||||
* This is an internal event bus for the PluginManager itself.
|
||||
*
|
||||
* @private
|
||||
* @param {string} event The name of the event to emit.
|
||||
* @param {any[]} args Arguments to pass to the event listeners.
|
||||
*/
|
||||
private emit(event: string, ...args: any[]): void {
|
||||
const listeners = this.listeners.get(event);
|
||||
if (listeners) {
|
||||
@@ -256,6 +376,12 @@ export class PluginManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an event listener for PluginManager's internal events.
|
||||
*
|
||||
* @param {string} event The name of the event to listen for (e.g., "plugin.stopped").
|
||||
* @param {(...args: any[]) => void} callback The function to call when the event is emitted.
|
||||
*/
|
||||
public on(event: string, callback: (...args: any[]) => void): void {
|
||||
if (!this.listeners.has(event)) {
|
||||
this.listeners.set(event, new Set());
|
||||
@@ -263,6 +389,12 @@ export class PluginManager {
|
||||
this.listeners.get(event)!.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters an event listener for PluginManager's internal events.
|
||||
*
|
||||
* @param {string} event The name of the event.
|
||||
* @param {(...args: any[]) => void} callback The callback function to remove.
|
||||
*/
|
||||
public off(event: string, callback: (...args: any[]) => void): void {
|
||||
const listeners = this.listeners.get(event);
|
||||
if (listeners) {
|
||||
@@ -270,7 +402,16 @@ export class PluginManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Add handler for plugin enable/disable state changes
|
||||
/**
|
||||
* Handles the change in a plugin's enabled state.
|
||||
* Starts or stops the plugin based on the new `enabled` value.
|
||||
* This is typically called by `setupPluginStateListener` when a relevant storage change is detected.
|
||||
*
|
||||
* @private
|
||||
* @param {string} pluginId The ID of the plugin whose state has changed.
|
||||
* @param {boolean} enabled The new enabled state of the plugin.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
private async handlePluginStateChange(
|
||||
pluginId: string,
|
||||
enabled: boolean,
|
||||
@@ -282,7 +423,14 @@ export class PluginManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Add listener for plugin settings changes
|
||||
/**
|
||||
* Sets up a listener for browser storage changes.
|
||||
* This listener monitors changes to plugin settings (specifically the `enabled` property
|
||||
* for plugins with `disableToggle: true`) and calls `handlePluginStateChange`
|
||||
* to automatically start or stop plugins accordingly.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private setupPluginStateListener(): void {
|
||||
browser.storage.onChanged.addListener(
|
||||
(changes: { [key: string]: StorageChange }, area: string) => {
|
||||
|
||||
@@ -5,8 +5,19 @@ import type {
|
||||
SelectSetting,
|
||||
StringSetting,
|
||||
HotkeySetting,
|
||||
PluginSettings,
|
||||
} from "./types";
|
||||
|
||||
/**
|
||||
* Creates a complete `NumberSetting` object from its options.
|
||||
* This helper function ensures the `type` property is correctly set to "number".
|
||||
* It's used for defining a numeric setting for a plugin.
|
||||
* This function itself does not handle storage or persistence; it defines the setting's structure.
|
||||
*
|
||||
* @param {Omit<NumberSetting, "type">} options The configuration options for the number setting,
|
||||
* excluding the `type` property (e.g., `title`, `default`, `min`, `max`).
|
||||
* @returns {NumberSetting} A complete number setting object with `type: "number"`.
|
||||
*/
|
||||
export function numberSetting(
|
||||
options: Omit<NumberSetting, "type">,
|
||||
): NumberSetting {
|
||||
@@ -16,6 +27,16 @@ export function numberSetting(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a complete `BooleanSetting` object from its options.
|
||||
* This helper function ensures the `type` property is correctly set to "boolean".
|
||||
* It's used for defining a boolean (true/false) setting for a plugin.
|
||||
* This function itself does not handle storage or persistence; it defines the setting's structure.
|
||||
*
|
||||
* @param {Omit<BooleanSetting, "type">} options The configuration options for the boolean setting,
|
||||
* excluding the `type` property (e.g., `title`, `default`).
|
||||
* @returns {BooleanSetting} A complete boolean setting object with `type: "boolean"`.
|
||||
*/
|
||||
export function booleanSetting(
|
||||
options: Omit<BooleanSetting, "type">,
|
||||
): BooleanSetting {
|
||||
@@ -25,6 +46,16 @@ export function booleanSetting(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a complete `StringSetting` object from its options.
|
||||
* This helper function ensures the `type` property is correctly set to "string".
|
||||
* It's used for defining a text-based setting for a plugin.
|
||||
* This function itself does not handle storage or persistence; it defines the setting's structure.
|
||||
*
|
||||
* @param {Omit<StringSetting, "type">} options The configuration options for the string setting,
|
||||
* excluding the `type` property (e.g., `title`, `default`, `placeholder`).
|
||||
* @returns {StringSetting} A complete string setting object with `type: "string"`.
|
||||
*/
|
||||
export function stringSetting(
|
||||
options: Omit<StringSetting, "type">,
|
||||
): StringSetting {
|
||||
@@ -34,15 +65,36 @@ export function stringSetting(
|
||||
};
|
||||
}
|
||||
|
||||
export function selectSetting<T extends string>(
|
||||
options: Omit<SelectSetting<T>, "type">,
|
||||
): SelectSetting<T> {
|
||||
/**
|
||||
* Creates a complete `SelectSetting` object from its options.
|
||||
* This helper function ensures the `type` property is correctly set to "select".
|
||||
* It's used for defining a setting where the user can choose from a predefined list of options.
|
||||
* This function itself does not handle storage or persistence; it defines the setting's structure.
|
||||
*
|
||||
* @template TValue - The type of the value for each option in the select list (extends string).
|
||||
* @param {Omit<SelectSetting<TValue>, "type">} options The configuration options for the select setting,
|
||||
* excluding the `type` property (e.g., `title`, `default`, `options` array).
|
||||
* @returns {SelectSetting<TValue>} A complete select setting object with `type: "select"`.
|
||||
*/
|
||||
export function selectSetting<TValue extends string>(
|
||||
options: Omit<SelectSetting<TValue>, "type">,
|
||||
): SelectSetting<TValue> {
|
||||
return {
|
||||
type: "select",
|
||||
...options,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a complete `ButtonSetting` object from its options.
|
||||
* This helper function ensures the `type` property is correctly set to "button".
|
||||
* It's used for defining a button in the plugin's settings UI, which can trigger an action.
|
||||
* This function itself does not handle storage or persistence; it defines the button's structure and action.
|
||||
*
|
||||
* @param {Omit<ButtonSetting, "type">} options The configuration options for the button setting,
|
||||
* excluding the `type` property (e.g., `title`, `label`, `trigger` function).
|
||||
* @returns {ButtonSetting} A complete button setting object with `type: "button"`.
|
||||
*/
|
||||
export function buttonSetting(
|
||||
options: Omit<ButtonSetting, "type">,
|
||||
): ButtonSetting {
|
||||
@@ -52,6 +104,16 @@ export function buttonSetting(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a complete `HotkeySetting` object from its options.
|
||||
* This helper function ensures the `type` property is correctly set to "hotkey".
|
||||
* It's used for defining a setting where the user can configure a keyboard shortcut.
|
||||
* This function itself does not handle storage or persistence; it defines the hotkey setting's structure.
|
||||
*
|
||||
* @param {Omit<HotkeySetting, "type">} options The configuration options for the hotkey setting,
|
||||
* excluding the `type` property (e.g., `title`, `default` hotkey string).
|
||||
* @returns {HotkeySetting} A complete hotkey setting object with `type: "hotkey"`.
|
||||
*/
|
||||
export function hotkeySetting(
|
||||
options: Omit<HotkeySetting, "type">,
|
||||
): HotkeySetting {
|
||||
@@ -61,10 +123,42 @@ export function hotkeySetting(
|
||||
};
|
||||
}
|
||||
|
||||
export function defineSettings<T extends Record<string, any>>(settings: T): T {
|
||||
/**
|
||||
* Defines a collection of settings for a plugin.
|
||||
* This function currently acts as an identity function, returning the settings object as is.
|
||||
* Its primary purpose is to provide type inference and a structured way to define
|
||||
* the entire settings configuration for a plugin, ensuring it conforms to the expected type.
|
||||
* This function itself does not handle storage or persistence; it's for structural definition.
|
||||
*
|
||||
* @template TSettings - A record type where keys are setting names and values are setting definition objects
|
||||
* (e.g., `NumberSetting`, `BooleanSetting`).
|
||||
* @param {TSettings} settings The complete settings configuration object for the plugin.
|
||||
* @returns {TSettings} The same settings configuration object, primarily for type checking/inference.
|
||||
*/
|
||||
export function defineSettings<TSettings extends Record<string, any>>(settings: TSettings): TSettings {
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* A property decorator for declaratively defining a plugin setting on a class property.
|
||||
* When a class property is decorated with `@Setting({...})`, this decorator adds the
|
||||
* provided setting definition (`settingDef`) to a static `settings` object on the
|
||||
* class's prototype. This allows settings to be defined alongside their related class logic.
|
||||
* This decorator itself does not handle runtime storage or persistence of setting *values*;
|
||||
* it is for defining the *structure* and *metadata* of a setting.
|
||||
*
|
||||
* Example:
|
||||
* ```typescript
|
||||
* class MyPlugin extends BasePlugin {
|
||||
* @Setting(numberSetting({ title: "My Number", default: 10 }))
|
||||
* myNumberSetting: number; // Type annotation for the setting's value
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param {any} settingDef The setting definition object, typically created by one of the
|
||||
* helper functions like `numberSetting(...)`, `booleanSetting(...)`, etc.
|
||||
* @returns {PropertyDecorator} A property decorator function.
|
||||
*/
|
||||
export function Setting(settingDef: any): PropertyDecorator {
|
||||
return (target, propertyKey) => {
|
||||
const proto = target.constructor.prototype;
|
||||
|
||||
Reference in New Issue
Block a user