All files / src/controllers DataConnectorController.ts

100% Statements 31/31
50% Branches 2/4
100% Functions 15/15
100% Lines 28/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112                    5x                             5x       8x 8x           8x 8x                     8x       2x 2x 2x   2x   2x 2x 1x   3x         2x                   8x 1x 1x   1x                   8x 1x 1x   1x                 8x 1x 1x   1x      
import { EditorAPI, EditorResponse } from '../types/CommonTypes';
import { ConnectorConfigOptions, MetaData } from '../types/ConnectorTypes';
import {
    DataConnectorCapabilities,
    DataModel,
    DataPage,
    EditorDataPage,
    PageConfig,
} from '../types/DataConnectorTypes';
import { DataItemMappingTools, EngineDataItem } from '../utils/DataItemMappingTools';
import { getEditorResponseData } from '../utils/EditorResponseData';
 
/**
 * The DataConnectorController is responsible for all communication regarding Data connectors.
 * Methods inside this controller can be called by `window.SDK.dataConnector.{method-name}`
 *
 * The way GraFx Studio handles different sources of Data is called 'DataConnector'.
 * A DataConnector is an implementation of a set of capabilities we need
 * to interact with a certain Data Management system.
 * In essence, a connector is the combination of a JavaScript snippet and some metadata.
 * The JavaScript snippet is loaded in the studio engine using a sandboxed JavaScript execution engine (QuickJs).
 * This allows us to execute the Data connector
 * both on web using webassembly and on the server side during e.g., animation output generation.
 * This controller is an interface to the running connector instance inside the studio engine.
 */
export class DataConnectorController {
    /**
     * @ignore
     */
    #editorAPI: EditorAPI;
    #dataItemMappingTools: DataItemMappingTools;
 
    /**
     * @ignore
     */
    constructor(editorAPI: EditorAPI, dataItemMappingTools: DataItemMappingTools) {
        this.#editorAPI = editorAPI;
        this.#dataItemMappingTools = dataItemMappingTools;
    }
 
    /**
     * Query a specific DataConnector for data using both specific PageConfig and the dynamic
     * context as parameters.
     * @param connectorId unique id of the Data connector
     * @param config page configuration
     * @param context context that will be available in the connector script.
     * @returns a DataPage with an array of data objects
     */
    getPage = async (
        connectorId: string,
        config: PageConfig,
        context: MetaData = {},
    ): Promise<EditorResponse<DataPage>> => {
        const res = await this.#editorAPI;
        return res
            .dataConnectorGetPage(connectorId, JSON.stringify(config), JSON.stringify(context))
            .then((result) => getEditorResponseData<EditorDataPage<EngineDataItem>>(result))
            .then((resp) => {
                const update: EditorResponse<DataPage> = { ...resp, parsedData: null };
                if (resp.parsedData) {
                    update.parsedData = {
                        data: resp.parsedData.data.map((e: EngineDataItem) =>
                            this.#dataItemMappingTools.mapEngineToDataItem(e),
                        ),
                        continuationToken: resp.parsedData.continuationToken,
                    };
                }
                return update;
            });
    };
 
    /**
     * Query a specific DataConnector for a data model using the dynamic context as parameter.
     * @param connectorId unique id of the data connector
     * @param context context that will be available in the connector script.
     * @returns DataModel
     */
    getModel = async (connectorId: string, context: MetaData = {}) => {
        const res = await this.#editorAPI;
        return res
            .dataConnectorGetModel(connectorId, JSON.stringify(context))
            .then((result) => getEditorResponseData<DataModel>(result));
    };
 
    /**
     * All connectors have a certain set of mappings they allow to be passed into the connector methods their context. This
     * method allows you to discover which mappings are available for a given connector. If you want to use any of these
     * mappings, they will be available in the `context` parameter of any connector method.
     * @param connectorId unique id of the data connector
     * @returns connector mappings
     */
    getConfigurationOptions = async (connectorId: string) => {
        const res = await this.#editorAPI;
        return res
            .dataConnectorGetConfigurationOptions(connectorId)
            .then((result) => getEditorResponseData<ConnectorConfigOptions>(result));
    };
 
    /**
     * This method returns what capabilities the selected connector has. It gives an indication what methods can
     * be used successfully for a certain connector.
     * @param connectorId unique id of the Data connector
     * @returns DataConnectorCapabilities
     */
    getCapabilities = async (connectorId: string) => {
        const res = await this.#editorAPI;
        return res
            .dataConnectorGetCapabilities(connectorId)
            .then((result) => getEditorResponseData<DataConnectorCapabilities>(result));
    };
}