From 27648a17797fa8f8e7423331b6a4380798c30b28 Mon Sep 17 00:00:00 2001 From: peternandersson Date: Fri, 20 Sep 2024 15:00:45 -0700 Subject: [PATCH] Add validation and some cleanup --- README.md | 46 +++++++++---------- src/client/initialize.ts | 95 ++++++++++++++++++++++++++-------------- src/react/hooks.ts | 75 ++++++++++++++++--------------- src/types.ts | 50 ++++++++++----------- 4 files changed, 148 insertions(+), 118 deletions(-) diff --git a/README.md b/README.md index e069073..a2269f6 100644 --- a/README.md +++ b/README.md @@ -434,23 +434,23 @@ interface PluginInstance { /** * Gets a static image of a workbook variable */ - getVariable(id: string): WorkbookVariable; + getVariable(configId: string): WorkbookVariable; /** * Setter for workbook variable passed in */ - setVariable(id: string, ...values: unknown[]): void; + setVariable(configId: string, ...values: unknown[]): void; /** * Getter for interaction selection state */ - getInteraction(id: string): WorkbookSelection[]; + getInteraction(configId: string): WorkbookSelection[]; /** * Setter for interaction selection state */ setInteraction( - id: string, + configId: string, elementId: string, selection: WorkbookSelection[], ): void; @@ -458,12 +458,12 @@ interface PluginInstance { /** * Triggers an action based on the provided action trigger ID */ - triggerAction(id: string): void; + triggerAction(configId: string): void; /** * Registers an effect with the provided action effect ID */ - registerEffect(id: string, effect: Function): void; + registerEffect(configId: string, effect: Function): void; /** * Overrider function for Config Ready state @@ -474,7 +474,7 @@ interface PluginInstance { * Allows users to subscribe to changes in the passed in variable */ subscribeToWorkbookVariable( - id: string, + configId: string, callback: (input: WorkbookVariable) => void, ): Unsubscriber; @@ -483,7 +483,7 @@ interface PluginInstance { * Allows users to subscribe to changes in the passed in interaction ID */ subscribeToWorkbookInteraction( - id: string, + configId: string, callback: (input: WorkbookSelection[]) => void, ): Unsubscriber; }; @@ -492,13 +492,13 @@ interface PluginInstance { /** * Getter for Column Data by parent sheet ID */ - getElementColumns(id: string): Promise; + getElementColumns(configId: string): Promise; /** * Subscriber to changes in column data by ID */ subscribeToElementColumns( - id: string, + configId: string, callback: (cols: WbElementColumns) => void, ): Unsubscriber; @@ -506,7 +506,7 @@ interface PluginInstance { * Subscriber for the data within a given sheet */ subscribeToElementData( - id: string, + configId: string, callback: (data: WbElementData) => void, ): Unsubscriber; }; @@ -647,12 +647,12 @@ interface WorkbookElementColumns { Provides the latest data values from corresponding sheet, up to 25000 values. ```ts -function useElementData(elementId: string): WorkbookElementData; +function useElementData(configId: string): WorkbookElementData; ``` Arguments -- `elementId : string` - A workbook element’s unique identifier. +- `configId : string` - A workbook element’s unique identifier from the plugin config. Returns the row data from the specified element. @@ -668,12 +668,12 @@ Provides the latest data values from the corresponding sheet (initially 25000), callback for fetching more data in chunks of 25000 values. ```ts -function useElementData(elementId: string): [WorkbookElementData, () => void]; +function useElementData(configId: string): [WorkbookElementData, () => void]; ``` Arguments -- `elementId : string` - A workbook element’s unique identifier. +- `configId : string` - A workbook element’s unique identifier from the plugin config. Returns the row data from the specified element, and a callback for fetching more data. @@ -690,13 +690,13 @@ Returns a given variable's value and a setter to update that variable ```ts function useVariable( - variableId: string, + configId: string, ): [WorkbookVariable | undefined, (...values: unknown[]) => void]; ``` Arguments -- `variableId : string` - The ID of the variable +- `configId : string` - The config ID corresponding to the workbook control variable The returned setter function accepts 1 or more variable values expressed as an array or multiple parameters @@ -711,14 +711,14 @@ Returns a given interaction's selection state and a setter to update that intera ```ts function useInteraction( - interactionId: string, + configId: string, elementId: string, ): [WorkbookSelection | undefined, (value: WorkbookSelection[]) => void]; ``` Arguments -- `interactionId : string` - The ID of the interaction +- `configId : string` - The config ID corresponding to the workbook interaction - `elementId : string` - The ID of the element that this interaction is associated with @@ -730,7 +730,7 @@ function setVariableCallback(value: WorkbookSelection[]): void; #### useActionTrigger() -- `configId : string` - The ID of the action trigger from the Plugin Config +- `configId : string` - The config ID corresponding to the action trigger Returns a callback function to trigger one or more action effects for a given action trigger @@ -742,7 +742,7 @@ function useActionTrigger(configId: string): () => void; Arguments -- `configId : string` - The ID of the action trigger from the Plugin Config +- `configId : string` - The config ID corresponding to the action trigger The function that can be called to asynchronously trigger the action @@ -755,12 +755,12 @@ function triggerActionCallback(configId: string): void; Registers and unregisters an action effect within the plugin ```ts -function useActionEffect(effectId: string, effect: () => void); +function useActionEffect(configId: string, effect: () => void); ``` Arguments -- `effectId : string` - The ID of the action effect +- `configId : string` - The config ID corresponding to the action effect - `effect : Function` - The function to be called when the effect is triggered #### useConfig() diff --git a/src/client/initialize.ts b/src/client/initialize.ts index c44c8fd..2914a47 100644 --- a/src/client/initialize.ts +++ b/src/client/initialize.ts @@ -4,7 +4,6 @@ import { PluginMessageResponse, WorkbookSelection, WorkbookVariable, - Unsubscriber, } from '../types'; export function initialize(): PluginInstance { @@ -126,28 +125,48 @@ export function initialize(): PluginInstance { on('config', listener); return () => off('config', listener); }, - getVariable(id: string): WorkbookVariable { - return subscribedWorkbookVars[id]; + getVariable(configId: string) { + if (configId === undefined) { + console.warn(`Invalid config variable: ${configId}`); + } + return subscribedWorkbookVars[configId]; }, - setVariable(id: string, ...values: unknown[]) { - void execPromise('wb:plugin:variable:set', id, ...values); + setVariable(configId: string, ...values: unknown[]) { + if (configId === undefined) { + console.warn(`Invalid config variable: ${configId}`); + } + void execPromise('wb:plugin:variable:set', configId, ...values); }, - getInteraction(id: string) { - return subscribedInteractions[id]; + getInteraction(configId: string) { + if (configId === undefined) { + console.warn(`Invalid config interaction: ${configId}`); + } + return subscribedInteractions[configId]; }, setInteraction( - id: string, + configId: string, elementId: string, selection: | string[] | Array>, ) { - void execPromise('wb:plugin:selection:set', id, elementId, selection); + void execPromise( + 'wb:plugin:selection:set', + configId, + elementId, + selection, + ); }, triggerAction(configId: string) { + if (configId === undefined) { + console.warn(`Invalid config action trigger: ${configId}`); + } void execPromise('wb:plugin:action-trigger:invoke', configId); }, registerEffect(configId: string, effect: () => void) { + if (configId === undefined) { + console.warn(`Invalid config action effect: ${configId}`); + } registeredEffects[configId] = effect; return () => { delete registeredEffects[configId]; @@ -159,24 +178,24 @@ export function initialize(): PluginInstance { setLoadingState(loadingState) { void execPromise('wb:plugin:config:loading-state', loadingState); }, - subscribeToWorkbookVariable( - id: string, - callback: (input: WorkbookVariable) => void, - ): Unsubscriber { + subscribeToWorkbookVariable(configId, callback) { + if (configId === undefined) { + console.warn(`Invalid config variable: ${configId}`); + } const setValues = (values: Record) => { - callback(values[id]); + callback(values[configId]); }; on('wb:plugin:variable:update', setValues); return () => { off('wb:plugin:variable:update', setValues); }; }, - subscribeToWorkbookInteraction( - id: string, - callback: (input: WorkbookSelection[]) => void, - ): Unsubscriber { + subscribeToWorkbookInteraction(configId, callback) { + if (configId === undefined) { + console.warn(`Invalid config interaction: ${configId}`); + } const setValues = (values: Record) => { - callback(values[id]); + callback(values[configId]); }; on('wb:plugin:selection:update', setValues); return () => { @@ -185,31 +204,43 @@ export function initialize(): PluginInstance { }, }, elements: { - getElementColumns(id) { - return execPromise('wb:plugin:element:columns:get', id); - }, - subscribeToElementColumns(id, callback) { - const eventName = `wb:plugin:element:${id}:columns`; + getElementColumns(configId) { + if (configId === undefined) { + console.warn(`Invalid config element: ${configId}`); + } + return execPromise('wb:plugin:element:columns:get', configId); + }, + subscribeToElementColumns(configId, callback) { + if (configId === undefined) { + console.warn(`Invalid config element: ${configId}`); + } + const eventName = `wb:plugin:element:${configId}:columns`; on(eventName, callback); - void execPromise('wb:plugin:element:subscribe:columns', id); + void execPromise('wb:plugin:element:subscribe:columns', configId); return () => { off(eventName, callback); - void execPromise('wb:plugin:element:unsubscribe:columns', id); + void execPromise('wb:plugin:element:unsubscribe:columns', configId); }; }, - subscribeToElementData(id, callback) { - const eventName = `wb:plugin:element:${id}:data`; + subscribeToElementData(configId, callback) { + if (configId === undefined) { + console.warn(`Invalid config element: ${configId}`); + } + const eventName = `wb:plugin:element:${configId}:data`; on(eventName, callback); - void execPromise('wb:plugin:element:subscribe:data', id); + void execPromise('wb:plugin:element:subscribe:data', configId); return () => { off(eventName, callback); - void execPromise('wb:plugin:element:unsubscribe:data', id); + void execPromise('wb:plugin:element:unsubscribe:data', configId); }; }, - fetchMoreElementData(id) { - void execPromise('wb:plugin:element:fetch-more', id); + fetchMoreElementData(configId) { + if (configId === undefined) { + console.warn(`Invalid config element: ${configId}`); + } + void execPromise('wb:plugin:element:fetch-more', configId); }, }, destroy() { diff --git a/src/react/hooks.ts b/src/react/hooks.ts index c8f3e65..7e6ab14 100644 --- a/src/react/hooks.ts +++ b/src/react/hooks.ts @@ -1,11 +1,4 @@ -import { - useContext, - useEffect, - useCallback, - useRef, - useMemo, - useState, -} from 'react'; +import { useContext, useEffect, useCallback, useRef, useState } from 'react'; import { PluginContext } from './Context'; import { @@ -70,64 +63,69 @@ export function useLoadingState( } /** - * Provides the latest column values from corresponding sheet - * @param {string} id Sheet ID to retrieve from workbook - * @returns {WorkbookElementColumns} Values of corresponding columns contained within the sheet + * Provides the latest column values from corresponding config element + * @param {string} configId ID from the config for fetching element columns, with type: 'element' + * @returns {WorkbookElementColumns} Values of corresponding columns contained + * within the config element */ -export function useElementColumns(id: string): WorkbookElementColumns { +export function useElementColumns(configId: string): WorkbookElementColumns { + if (configId === undefined) { + throw new Error('[Plugin - useElementColumns] Config element not defined'); + } const client = usePlugin(); const [columns, setColumns] = useState({}); useEffect(() => { - if (id) { - return client.elements.subscribeToElementColumns(id, setColumns); + if (configId) { + return client.elements.subscribeToElementColumns(configId, setColumns); } - }, [client, id]); + }, [client, configId]); return columns; } /** - * Provides the latest data values from corresponding sheet (max 25_000) - * @param {string} id Sheet ID to get element data from - * @returns {WorkbookElementData} Element Data for corresponding sheet, if any + * Provides the latest data values from config element (max 25_000) + * @param {string} configId ID from the config for fetching element data, with type: 'element' + * @returns {WorkbookElementData} Element Data for config element, if any */ -export function useElementData(id: string): WorkbookElementData { +export function useElementData(configId: string): WorkbookElementData { const client = usePlugin(); const [data, setData] = useState({}); useEffect(() => { - if (id) { - return client.elements.subscribeToElementData(id, setData); + if (configId) { + return client.elements.subscribeToElementData(configId, setData); } - }, [client, id]); + }, [client, configId]); return data; } /** - * Provides the latest data values from corresponding sheet with a callback to + * Provides the latest data values from corresponding config element with a callback to * fetch more in chunks of 25_000 data points - * @param {string} id Sheet ID to get element data from - * @returns {WorkbookElementData} Element Data for corresponding sheet, if any + * @param {string} configId ID from the config for fetching paginated + * element data, with type: 'element' + * @returns {WorkbookElementData} Element Data for configured config element, if any */ export function usePaginatedElementData( - id: string, + configId: string, ): [WorkbookElementData, () => void] { const client = usePlugin(); const [data, setData] = useState({}); const loadMore = useCallback(() => { - if (id) { - client.elements.fetchMoreElementData(id); + if (configId) { + client.elements.fetchMoreElementData(configId); } - }, [id]); + }, [configId]); useEffect(() => { - if (id) { - return client.elements.subscribeToElementData(id, setData); + if (configId) { + return client.elements.subscribeToElementData(configId, setData); } - }, [client, id]); + }, [client, configId]); return [data, loadMore]; } @@ -159,9 +157,10 @@ export function useConfig(key?: string): any { } /** - * React hook for accessing a workbook variable - * @param {string} id ID of variable within Plugin Config to use - * @returns {[(WorkbookVariable | undefined), Function]} Constantly updating value of the variable and setter for the variable + * React hook for accessing a workbook control variable + * @param {string} id ID from the config of type: 'variable' + * @returns {[(WorkbookVariable | undefined), Function]} Constantly updating + * value of the control variable and setter for the variable */ export function useVariable( id: string, @@ -184,7 +183,7 @@ export function useVariable( /** * @deprecated Use Action API instead * React hook for accessing a workbook interaction selections state - * @param {string} id ID of variable within Plugin Config to use + * @param {string} id ID from the config of type: 'interaction' * @returns {[(WorkbookSelection | undefined), Function]} Constantly updating selection state and setter thereof */ export function useInteraction( @@ -215,7 +214,7 @@ export function useInteraction( /** * React hook for returning a triggering callback function for the registered * action trigger - * @param {string} configId ID of action trigger from the plugin config + * @param {string} configId ID from the config of type: 'action-trigger' * @returns {Function} A callback function to trigger the action */ export function useActionTrigger(configId: string): () => void { @@ -228,7 +227,7 @@ export function useActionTrigger(configId: string): () => void { /** * React hook for registering and unregistering an action effect - * @param {string} configId ID of action effect from plugin config + * @param {string} configId ID from the config of type: 'action-effect' * @param {Function} effect The function to be called when the action is triggered */ export function useActionEffect(configId: string, effect: () => void) { diff --git a/src/types.ts b/src/types.ts index 176b5bf..a05c74c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,8 +25,8 @@ export interface PluginConfig { /** * @typedef {object} WorkbookVariable - * @property {string} name Name of Control Variable within Workbook - * @property {{string}} defaultValue Current Value containing at least type as string + * @property {string} name Name of control variable within workbook + * @property {{string}} defaultValue Current value containing at least type as string */ export interface WorkbookVariable { name: string; @@ -235,48 +235,48 @@ export interface PluginInstance { /** * Gets a static image of a workbook variable - * @param {string} id ID of the workbook variable in config + * @param {string} configId ID from config of type: 'variable' * @returns {WorkbookVariable} Current value of the workbook variable */ - getVariable(id: string): WorkbookVariable; + getVariable(configId: string): WorkbookVariable; /** * Setter for workbook variable passed in - * @param {string} id ID of the workbook variable in config + * @param {string} configId ID from config of type: 'variable' * @param {unknown[]} values Values to assign to the workbook variable */ - setVariable(id: string, ...values: unknown[]): void; + setVariable(configId: string, ...values: unknown[]): void; /** * @deprecated Use Action API instead * Getter for interaction selection state - * @param {string} id ID from interaction type in Plugin Config + * @param {string} configId ID from config of type: 'interaction' */ - getInteraction(id: string): WorkbookSelection[]; + getInteraction(configId: string): WorkbookSelection[]; /** * @deprecated Use Action API instead * Setter for interaction selection state - * @param {string} id ID from interaction type in Plugin Config + * @param {string} configId ID from config of type: 'interaction' * @param {string} elementId Source element ID from element type in Plugin Config * @param {Object} selection List of column IDs or Columns and values and key-value pairs to select */ setInteraction( - id: string, + configId: string, elementId: string, selection: WorkbookSelection[], ): void; /** * Triggers an action based on the provided action trigger ID - * @param {string} configId ID from action-trigger type in Plugin Config + * @param {string} configId ID from config of type: 'action-trigger' */ triggerAction(configId: string): void; /** * Registers an effect with the provided action effect ID - * @param {string} configId ID from action-effect type in Plugin Config - * @param effect The effect function to register + * @param {string} configId ID from config of type: 'action-effect' + * @param {Function} effect The effect function to register * @returns {Unsubscriber} A callable unsubscriber */ registerEffect(configId: string, effect: () => void): () => void; @@ -289,24 +289,24 @@ export interface PluginInstance { /** * Allows users to subscribe to changes in the passed in variable - * @param {string} id ID of the workbook variable in config + * @param {string} configId ID from config of type: 'variable' * @callback callback Function to be called upon receiving an updated workbook variable * @returns {Unsubscriber} A callable unsubscriber */ subscribeToWorkbookVariable( - id: string, + configId: string, callback: (input: WorkbookVariable) => void, ): Unsubscriber; /** * @deprecated Use Action API instead * Allows users to subscribe to changes in the passed in interaction ID - * @param {string} id ID of the interaction variable within Plugin Config + * @param {string} configId ID from the config of type: 'interaction' * @callback callback Function to be called upon receiving an updated interaction selection state * @returns {Unsubscriber} A callable unsubscriber */ subscribeToWorkbookInteraction( - id: string, + configId: string, callback: (input: WorkbookSelection[]) => void, ): Unsubscriber; }; @@ -314,38 +314,38 @@ export interface PluginInstance { elements: { /** * Getter for Column Data by parent sheet ID - * @param {string} id Sheet ID to retrieve columns from + * @param {string} configId ID from config of type: 'element' * @returns {WorkbookElementColumns} Column values contained within corresponding sheet */ - getElementColumns(id: string): Promise; + getElementColumns(configId: string): Promise; /** * Subscriber to changes in column data by ID - * @param {string} id Column ID to subscribe to + * @param {string} configId ID from config of type: 'element' * @callback callback Callback function to be called upon changes to column data * @returns {Unsubscriber} Callable unsubscriber to column data changes */ subscribeToElementColumns( - id: string, + configId: string, callback: (cols: WorkbookElementColumns) => void, ): Unsubscriber; /** * Subscriber for the data within a given sheet - * @param {string} id Sheet ID to get element data from + * @param {string} configId ID from config of type: 'element' * @callback callback Function to call on data passed in * @returns {Unsubscriber} A callable unsubscriber to changes in the data */ subscribeToElementData( - id: string, + configId: string, callback: (data: WorkbookElementData) => void, ): Unsubscriber; /** * Ask sigma to load more data - * @param {string} id Sheet ID to load more data + * @param {string} configId ID from config of type: 'element' */ - fetchMoreElementData(id: string): void; + fetchMoreElementData(configId: string): void; }; /**