/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import type { SqlExpression } from 'druid-query-toolkit'; import type { Host } from './host'; import type { UpdateEvent } from './host-store'; import type { Parameter, ParameterDefinitions, ParameterTypes } from './parameter'; type ExtractParameters = P[Name] extends Parameter ? Name : never; // If the parameter has a default value, use that, otherwise include undefined type ParameterValueType

= P extends { default: infer V } ? V : ParameterTypes[P['type']] | undefined; export type ParametersToParams = { [Name in keyof D as ExtractParameters]: ParameterValueType; }; export interface VisualModuleContext { /** * Container element for the visual module. * * This is where the visual module should render its content. */ container: HTMLElement; /** * Host for the visual module. */ host: Host; /** * Gets the last update event that was sent to the visual module, if any. */ getLastUpdateEvent(): UpdateEvent | undefined; /** * Updates a single parameter to the given value. * * @param name - Parameter name. * @param value - New value. */ updateParam(name: Name, value: Params[Name]): void; /** * Updates multiple parameters at once. * * @param params - Map of parameter names to their new values. */ updateParams(params: Partial): void; /** * Updates the table that the visual module will query against. * * This may be different from the common table set on the Host. * * @param table - New table name or 'undefined' to use the common table. */ updateTable(table: SqlExpression): void; /** * Updates the WHERE clause for this visual module. * * If defined, this will be combined with the common WHERE clause set * on the Host. * * @param where */ updateWhere(where: string | SqlExpression | undefined): void; /** * Updates the HAVING clause for this visual module. * * If defined, this will be combined with the common HAVING clause set * on the Host. * * @param having */ updateHaving(having: string | SqlExpression | undefined): void; } export interface VisualModuleInstance { /** * Main update function for the visual module. * * This is invoked by the host when either the query or the parameters change. * * @param updateEvent - Event containing the new query and parameters. */ update(updateEvent: UpdateEvent): Promise | void; /** * Optional cleanup function for the visual module. */ destroy?(): Promise | void; } export interface VisualModule

{ /** * Parameters that this module accepts. */ parameters: P | undefined; /** * Order of parameters for display purposes. * * Omitting a parameter from this list _may_ cause it to be hidden from the UI, * depending on the host implementation. */ parameterOrder: (keyof P)[] | undefined; /** * Creates a new instance of this module. */ (context: VisualModuleContext>): VisualModuleInstance< ParametersToParams

>; } type ParameterizedModuleFactory

= ( context: VisualModuleContext>, ) => VisualModuleInstance>; export interface TypedVisualModuleOptions

{ /** * The visual module instance factory. */ module: ParameterizedModuleFactory

; /** * Parameters that this module accepts. */ parameters?: P & ParameterDefinitions; /** * Order of parameters for display purposes. * * Omitting a parameter from this list _may_ cause it to be hidden from the UI, * depending on the host implementation. */ parameterOrder?: (keyof P)[]; } /** * Defines a new visual module. * * This is a convenience function for defining a module with strongly typed parameters * inferred from the parameter definitions. */ export function typedVisualModule

({ module: factory, parameters, parameterOrder, }: TypedVisualModuleOptions

): VisualModule

{ if (typeof factory !== 'function') { throw new Error('Expected "module" to be a function'); } if (parameterOrder) { const seenParams = new Set(); for (const paramName of parameterOrder) { if (seenParams.has(paramName)) { throw new Error( `Duplicate parameter name defined in parameterOrder array: ${String(paramName)}`, ); } seenParams.add(paramName); } } else { parameterOrder = Object.getOwnPropertyNames(parameters) as (keyof P)[]; } const result: VisualModule

= context => { return factory(context); }; result.parameters = parameters; result.parameterOrder = parameterOrder; return result; }