UNPKG

@prismatic-io/spectral

Version:

Utility library for building Prismatic connectors and code-native integrations

689 lines (688 loc) 33.5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertConfigVar = exports.convertInputValue = exports.convertFlow = exports.convertConfigPages = exports.convertIntegration = void 0; const yaml_1 = __importDefault(require("yaml")); const uuid_1 = require("uuid"); const assign_1 = __importDefault(require("lodash/assign")); const camelCase_1 = __importDefault(require("lodash/camelCase")); const pick_1 = __importDefault(require("lodash/pick")); const types_1 = require("../types"); const convertComponent_1 = require("./convertComponent"); const integration_1 = require("./integration"); const merge_1 = __importDefault(require("lodash/merge")); const context_1 = require("./context"); const path_1 = __importDefault(require("path")); const fs_1 = require("fs"); const convertIntegration = (definition) => { var _a, _b, _c; // Generate a unique reference key that will be used to reference the // actions, triggers, data sources, and connections that are created // inline as part of the integration definition. const referenceKey = (0, uuid_1.v4)(); const scopedConfigVars = (_a = definition.scopedConfigVars) !== null && _a !== void 0 ? _a : {}; const configVars = Object.values({ configPages: (_b = definition.configPages) !== null && _b !== void 0 ? _b : {}, userLevelConfigPages: (_c = definition.userLevelConfigPages) !== null && _c !== void 0 ? _c : {}, }).reduce((acc, configPages) => (Object.assign(Object.assign({}, acc), Object.values(configPages).reduce((acc, configPage) => Object.entries(configPage.elements).reduce((acc, [key, element]) => { // "string" elements are HTML elements and should be ignored. if (typeof element === "string") { return acc; } if (key in acc || key in scopedConfigVars) { throw new Error(`Duplicate config var key: "${key}"`); } return Object.assign(Object.assign({}, acc), { [key]: element }); }, acc), {}))), {}); let metadata = {}; try { const metaDataPath = path_1.default.join("..", ".spectral", "metadata.json"); const file = (0, fs_1.readFileSync)(metaDataPath, { encoding: "utf-8" }); metadata = JSON.parse(file); } catch (e) { // No-op. If there's no metadata file then we move on. } const cniComponent = codeNativeIntegrationComponent(definition, referenceKey, configVars); const cniYaml = codeNativeIntegrationYaml(definition, referenceKey, configVars, metadata); return Object.assign(Object.assign({}, cniComponent), { codeNativeIntegrationYAML: cniYaml }); }; exports.convertIntegration = convertIntegration; const convertConfigPages = (pages, userLevelConfigured) => { if (!pages || !Object.keys(pages).length) { return []; } return Object.entries(pages).map(([name, { tagline, elements }]) => (Object.assign(Object.assign({ name, tagline }, (userLevelConfigured ? { userLevelConfigured } : {})), { elements: Object.entries(elements) .filter(([key, value]) => !(0, types_1.isConnectionScopedConfigVar)(value)) .map(([key, value]) => { if (typeof value === "string") { return { type: "htmlElement", value, }; } else if (value && typeof value === "object" && "dataType" in value && value.dataType === "htmlElement") { return { type: "htmlElement", value: key, }; } return { type: "configVar", value: key, }; }) }))); }; exports.convertConfigPages = convertConfigPages; const codeNativeIntegrationYaml = ({ name, description, category, documentation, version, labels, endpointType, triggerPreprocessFlowConfig, flows, configPages, userLevelConfigPages, scopedConfigVars, instanceProfile = "Default Instance Profile", componentRegistry = {}, }, referenceKey, configVars, metadata) => { // Find the preprocess flow config on the flow, if one exists. const preprocessFlows = flows.filter((flow) => flow.preprocessFlowConfig); // Do some validation of preprocess flow configs. if (preprocessFlows.length > 1) { throw new Error("Only one flow may define a Preprocess Flow Config."); } if (preprocessFlows.length && triggerPreprocessFlowConfig) { throw new Error("Integration must not define both a Trigger Preprocess Flow Config and a Preprocess Flow."); } const hasPreprocessFlow = preprocessFlows.length > 0; const preprocessFlowConfig = hasPreprocessFlow ? preprocessFlows[0].preprocessFlowConfig : triggerPreprocessFlowConfig; const nonPreprocessFlowTypes = ["instance_specific", "shared_instance"]; if (nonPreprocessFlowTypes.includes(endpointType || "flow_specific") && !preprocessFlowConfig) { throw new Error("Integration with specified EndpointType must define either a Trigger Preprocess Flow Config or a Preprocess Flow."); } const configVarMap = Object.entries(scopedConfigVars !== null && scopedConfigVars !== void 0 ? scopedConfigVars : {}).reduce((acc, [key, value]) => { if (typeof value === "string") { return acc; } return Object.assign(Object.assign({}, acc), { [key]: value }); }, Object.assign({}, (configVars !== null && configVars !== void 0 ? configVars : {}))); const requiredConfigVars = []; Object.entries(configVarMap).forEach(([key, configVar]) => { if (!(0, types_1.isHtmlElementConfigVar)(configVar)) { requiredConfigVars.push((0, exports.convertConfigVar)(key, configVar, referenceKey, componentRegistry)); } }); // Transform the IntegrationDefinition into the structure that is appropriate // for generating YAML, which will then be used by the Prismatic API to import // the integration as a Code Native Integration. const result = { definitionVersion: integration_1.DefinitionVersion, isCodeNative: true, name, description, category, documentation, version, labels, requiredConfigVars, endpointType, preprocessFlowName: hasPreprocessFlow ? preprocessFlows[0].name : undefined, externalCustomerIdField: fieldNameToReferenceInput(hasPreprocessFlow ? "onExecution" : "payload", preprocessFlowConfig === null || preprocessFlowConfig === void 0 ? void 0 : preprocessFlowConfig.externalCustomerIdField), externalCustomerUserIdField: fieldNameToReferenceInput(hasPreprocessFlow ? "onExecution" : "payload", preprocessFlowConfig === null || preprocessFlowConfig === void 0 ? void 0 : preprocessFlowConfig.externalCustomerUserIdField), flowNameField: fieldNameToReferenceInput(hasPreprocessFlow ? "onExecution" : "payload", preprocessFlowConfig === null || preprocessFlowConfig === void 0 ? void 0 : preprocessFlowConfig.flowNameField), flows: flows.map((flow) => (0, exports.convertFlow)(flow, componentRegistry, referenceKey)), defaultInstanceProfile: instanceProfile, configPages: [ ...(0, exports.convertConfigPages)(configPages, false), ...(0, exports.convertConfigPages)(userLevelConfigPages, true), ], importMetadata: metadata, }; return yaml_1.default.stringify(result); }; const permissionAndVisibilityTypeValueMap = { customer: { orgOnly: false, visibleToOrgDeployer: true, visibleToCustomerDeployer: true, }, embedded: { orgOnly: false, visibleToOrgDeployer: true, visibleToCustomerDeployer: false, }, organization: { orgOnly: true, visibleToOrgDeployer: true, visibleToCustomerDeployer: false, }, }; const getPermissionAndVisibilityValues = ({ permissionAndVisibilityType = "customer", visibleToOrgDeployer = true, }) => { return Object.assign(Object.assign({}, permissionAndVisibilityTypeValueMap[permissionAndVisibilityType]), (visibleToOrgDeployer !== undefined ? { visibleToOrgDeployer } : {})); }; /** Converts permission and visibility properties into `meta` properties for inputs. */ const convertInputPermissionAndVisibility = ({ permissionAndVisibilityType, visibleToOrgDeployer, }) => { const meta = getPermissionAndVisibilityValues({ permissionAndVisibilityType, visibleToOrgDeployer, }); return meta; }; /** Converts permission and visibility properties into `meta` properties for config vars. */ const convertConfigVarPermissionAndVisibility = ({ permissionAndVisibilityType, visibleToOrgDeployer: visibleToOrgDeployerBase, }) => { const { orgOnly, visibleToCustomerDeployer, visibleToOrgDeployer } = getPermissionAndVisibilityValues({ permissionAndVisibilityType, visibleToOrgDeployer: visibleToOrgDeployerBase, }); return { orgOnly, meta: { visibleToCustomerDeployer, visibleToOrgDeployer, }, }; }; const convertComponentReference = (componentReference, componentRegistry, referenceType) => { var _a, _b; const manifest = componentRegistry[componentReference.component]; if (!manifest) { throw new Error(`Component with key "${componentReference.component}" not found in component registry.`); } const manifestEntry = manifest[referenceType][componentReference.key]; if (!manifestEntry) { throw new Error(`Component with key "${componentReference.component}" does not have an entry with key "${componentReference.key}" in the component registry.`); } const ref = { component: { key: manifest.key, signature: (_a = manifest.signature) !== null && _a !== void 0 ? _a : "", isPublic: manifest.public, }, // older versions of the manifest did not contain a key so we fall back to the componentReference key key: (_b = manifestEntry.key) !== null && _b !== void 0 ? _b : componentReference.key, }; const inputs = Object.entries(manifestEntry.inputs).reduce((result, [key, manifestEntryInput]) => { var _a, _b, _c; // Retrieve the input value or default to the manifest's default value const value = (_b = (_a = componentReference.values) === null || _a === void 0 ? void 0 : _a[key]) !== null && _b !== void 0 ? _b : { value: (_c = manifestEntryInput.default) !== null && _c !== void 0 ? _c : "", }; const type = manifestEntryInput.collection ? "complex" : "value" in value ? "value" : "configVar"; if ("value" in value) { const valueExpr = manifestEntryInput.collection === "keyvaluelist" && value.value instanceof Object ? Object.entries(value.value).map(([k, v]) => ({ name: { type: "value", value: k }, type: "value", value: JSON.stringify(v), })) : manifestEntryInput.collection === "valuelist" && Array.isArray(value.value) ? value.value.map((v) => ({ type: "value", value: v })) : value.value; const formattedValue = type === "complex" || typeof valueExpr === "string" ? valueExpr : JSON.stringify(valueExpr); const meta = convertInputPermissionAndVisibility((0, pick_1.default)(value, ["permissionAndVisibilityType", "visibleToOrgDeployer"])); const { writeOnly } = (0, pick_1.default)(value, ["writeOnly"]); if (writeOnly) { meta.writeOnly = writeOnly; } return Object.assign(Object.assign({}, result), { [key]: { type: type, value: formattedValue, meta } }); } if ("configVar" in value) { return Object.assign(Object.assign({}, result), { [key]: { type: "configVar", value: value.configVar } }); } if ("template" in value) { return Object.assign(Object.assign({}, result), { [key]: { type: "template", value: value.template } }); } return result; }, {}); return { ref, inputs, }; }; const convertComponentRegistry = (componentRegistry, publicSupplementalComponent) => { const convertedRegistry = Object.values(componentRegistry).map(({ key, public: isPublic, signature }) => ({ key, signature: signature !== null && signature !== void 0 ? signature : "", isPublic, })); if (publicSupplementalComponent) { convertedRegistry.push({ key: `${publicSupplementalComponent}-triggers`, isPublic: true, version: "LATEST", }); } return convertedRegistry; }; /** * Create a reference to the private component built as part of this CNI. * * References to this component always use `version: "LATEST", isPublic: false` * because they automatically publish alongside the corresponding CNI yml. * */ const codeNativeIntegrationComponentReference = (referenceKey) => ({ key: referenceKey, version: "LATEST", isPublic: false, }); /* A flow's trigger gets wrapped in a custom component if there's a defined * onTrigger function, or if any custom onInstance behavior is defined. * */ const flowUsesWrapperTrigger = (flow) => { return typeof flow.onTrigger === "function" || flow.onInstanceDelete || flow.onInstanceDeploy; }; const convertFlowSchemas = (flowKey, schemas) => { return Object.entries(schemas).reduce((acc, [key, value]) => { acc[key] = { title: value.title || `${flowKey}-${key}`, type: "object", $comment: value.$comment, properties: value.properties, $schema: value.$schema || types_1.DEFAULT_JSON_SCHEMA_VERSION, }; return acc; }, {}); }; /** Converts a Flow into the structure necessary for YAML generation. */ const convertFlow = (flow, componentRegistry, referenceKey) => { var _a; const result = Object.assign({}, flow); result.onTrigger = undefined; result.trigger = undefined; result.onInstanceDeploy = undefined; result.onInstanceDelete = undefined; result.onExecution = undefined; result.preprocessFlowConfig = undefined; result.errorConfig = undefined; let publicSupplementalComponent; const triggerStep = { name: "On Trigger", stableKey: `${flow.stableKey}-onTrigger`, description: "The function that will be executed by the flow to return an HTTP response.", isTrigger: true, errorConfig: "errorConfig" in flow ? Object.assign({}, flow.errorConfig) : undefined, }; const useWrapperTrigger = flowUsesWrapperTrigger(flow); if ((0, types_1.isComponentReference)(flow.onTrigger) && !useWrapperTrigger) { const { ref, inputs } = convertComponentReference(flow.onTrigger, componentRegistry, "triggers"); triggerStep.action = ref; triggerStep.inputs = inputs; } else if (useWrapperTrigger) { if (!flow.onTrigger) { publicSupplementalComponent = flow.schedule ? "schedule" : "webhook"; } triggerStep.action = { key: flowFunctionKey(flow.name, "onTrigger"), component: codeNativeIntegrationComponentReference(referenceKey), }; } else { const hasSchedule = "schedule" in flow && typeof flow.schedule === "object"; const key = hasSchedule ? "schedule" : "webhook"; triggerStep.action = { key, component: { key: `${key}-triggers`, /** * TODO: Add support for specific versions of platform triggers */ version: "LATEST", isPublic: true, }, }; } if ("schedule" in flow && typeof flow.schedule === "object") { const { schedule } = flow; triggerStep.schedule = { type: "configVar" in schedule ? "configVar" : "value", value: "configVar" in schedule ? schedule.configVar : schedule.value, meta: { scheduleType: "custom", timeZone: (_a = schedule.timezone) !== null && _a !== void 0 ? _a : "", }, }; result.schedule = undefined; } const actionStep = { action: { key: flowFunctionKey(flow.name, "onExecution"), component: codeNativeIntegrationComponentReference(referenceKey), }, name: "On Execution", stableKey: `${flow.stableKey}-onExecution`, description: "The function that will be executed by the flow.", errorConfig: "errorConfig" in flow ? Object.assign({}, flow.errorConfig) : undefined, }; result.steps = [triggerStep, actionStep]; result.supplementalComponents = convertComponentRegistry(componentRegistry, publicSupplementalComponent); result.schemas = flow.schemas ? convertFlowSchemas(flow.stableKey, flow.schemas) : undefined; return result; }; exports.convertFlow = convertFlow; /** Converts an input value to the expected server type by its collection type. */ const convertInputValue = (value, collectionType) => { if (collectionType !== "keyvaluelist") { return value; } if (Array.isArray(value)) { return value; } return Object.entries(value).map(([key, value]) => ({ key, value: typeof value === "string" ? value : JSON.stringify(value), })); }; exports.convertInputValue = convertInputValue; /** Converts a Config Var into the structure necessary for YAML generation. */ const convertConfigVar = (key, configVar, referenceKey, componentRegistry) => { var _a, _b, _c; if ((0, types_1.isConnectionScopedConfigVar)(configVar)) { const { stableKey } = (0, pick_1.default)(configVar, ["stableKey"]); return { key, stableKey, dataType: "connection", useScopedConfigVar: stableKey, }; } const { orgOnly, meta } = convertConfigVarPermissionAndVisibility((0, pick_1.default)(configVar, ["permissionAndVisibilityType", "visibleToOrgDeployer"])); if ((0, types_1.isConnectionDefinitionConfigVar)(configVar)) { const { stableKey, description } = (0, pick_1.default)(configVar, ["stableKey", "description"]); return { stableKey, description, key, dataType: "connection", connection: { key: (0, camelCase_1.default)(key), component: codeNativeIntegrationComponentReference(referenceKey), }, inputs: Object.entries(configVar.inputs).reduce((result, [key, input]) => { // Connection template inputs are never shown in the resulting YAML. if (input.shown === false || "templateValue" in input) { return result; } const meta = convertInputPermissionAndVisibility((0, pick_1.default)(input, ["permissionAndVisibilityType", "visibleToOrgDeployer"])); if (input.writeOnly) { meta.writeOnly = input.writeOnly; } const defaultValue = input.collection ? (input.default || []).map((defaultValue) => { if (typeof defaultValue === "string") { return { type: "value", value: defaultValue, }; } return { name: defaultValue.key, type: "value", value: defaultValue.value, }; }) : input.default || ""; return Object.assign(Object.assign({}, result), { [key]: { type: input.collection ? "complex" : "value", value: defaultValue, meta, } }); }, {}), orgOnly, meta: Object.assign(Object.assign({}, meta), ("oauth2Config" in configVar ? (_a = configVar.oauth2Config) !== null && _a !== void 0 ? _a : {} : {})), }; } if ((0, types_1.isConnectionReferenceConfigVar)(configVar)) { const { ref, inputs } = convertComponentReference(configVar.connection, componentRegistry, "connections"); const { stableKey = "", description, connection: { template, onPremiseConnectionConfig }, } = (0, pick_1.default)(configVar, ["stableKey", "description", "connection"]); return { stableKey, description, key, dataType: "connection", onPremiseConnectionConfig, connection: Object.assign(Object.assign({}, ref), { template }), inputs, orgOnly, meta: Object.assign(Object.assign({}, meta), ("oauth2Config" in configVar ? (_b = configVar.oauth2Config) !== null && _b !== void 0 ? _b : {} : {})), }; } const rawDefaultValue = "defaultValue" in configVar ? (0, exports.convertInputValue)(configVar.defaultValue, configVar.collectionType) : undefined; const defaultValue = typeof rawDefaultValue !== "undefined" ? typeof rawDefaultValue === "string" ? rawDefaultValue : JSON.stringify(rawDefaultValue) : undefined; const result = (0, assign_1.default)({ orgOnly, meta, key, defaultValue }, (0, pick_1.default)(configVar, [ "stableKey", "description", "dataType", "pickList", "timeZone", "codeLanguage", "collectionType", ])); if ((0, types_1.isScheduleConfigVar)(configVar)) { result.scheduleType = "custom"; } if ((0, types_1.isJsonFormConfigVar)(configVar) || (0, types_1.isJsonFormDataSourceConfigVar)(configVar)) { result.meta = Object.assign(Object.assign({}, result.meta), { validationMode: (_c = configVar === null || configVar === void 0 ? void 0 : configVar.validationMode) !== null && _c !== void 0 ? _c : "ValidateAndShow" }); } if ((0, types_1.isDataSourceDefinitionConfigVar)(configVar)) { result.dataType = configVar.dataSourceType; result.dataSource = { key: (0, camelCase_1.default)(key), component: codeNativeIntegrationComponentReference(referenceKey), }; } if ((0, types_1.isDataSourceReferenceConfigVar)(configVar)) { const { ref, inputs } = convertComponentReference(configVar.dataSource, componentRegistry, "dataSources"); result.dataType = componentRegistry[configVar.dataSource.component].dataSources[ref.key].dataSourceType; result.dataSource = ref; result.inputs = inputs; if (configVar.validationMode) { result.meta = Object.assign(Object.assign({}, result.meta), { validationMode: configVar.validationMode }); } } return result; }; exports.convertConfigVar = convertConfigVar; /** Maps the step name field to a fully qualified input. */ const fieldNameToReferenceInput = (stepName, fieldName) => fieldName ? { type: "reference", value: `${stepName}.results.${fieldName}` } : undefined; /** Actions and Triggers will be scoped to their flow by combining the flow * name and the function name. This is to ensure that the keys are unique * on the resulting object, which will be turned into a Component. */ const flowFunctionKey = (flowName, functionName) => { const flowKey = flowName .replace(/[^0-9a-zA-Z]+/g, " ") .trim() .split(" ") .map((w, i) => i === 0 ? w.toLowerCase() : w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()) .join(""); return `${flowKey}_${functionName}`; }; /* Generates component argument for invokeTrigger calls. */ const invokeTriggerComponentInput = (componentRef, onTrigger, eventName) => { const { component } = componentRef; const inputComponent = "signature" in componentRef.component ? { key: component.key, signature: "signature" in component && component.signature !== null && component.signature !== void 0 ? component.signature : "", isPublic: component.isPublic, } : component; return { component: inputComponent, key: onTrigger ? onTrigger.key : componentRef.key, triggerEventFunctionName: eventName, }; }; /* Generates a wrapper function that calls an existing component trigger's perform. */ const generateTriggerPerformFn = (componentRef, onTrigger, componentRegistry) => { const performFn = componentRef && typeof onTrigger !== "function" ? (context, payload, params) => __awaiter(void 0, void 0, void 0, function* () { // @ts-expect-error: _components isn't part of the public API const { _components } = context; const invokeTrigger = _components.invokeTrigger; const cniContext = (0, context_1.createCNIContext)(context, componentRegistry); return yield invokeTrigger(invokeTriggerComponentInput(componentRef, onTrigger, "perform"), cniContext, payload, params); }) : (context, payload, params) => __awaiter(void 0, void 0, void 0, function* () { const cniContext = (0, context_1.createCNIContext)(context, componentRegistry); return yield onTrigger(cniContext, payload, params); }); return performFn; }; /** Generates a wrapper function that calls an existing component's onInstanceDeploy * or onInstanceDelete, then calls the flow-defined version if it exists. * Returns the deep-merged results of the two, prioritizing the custom response * if there's a conflict. */ const generateOnInstanceWrapperFn = (componentRef, onTrigger, eventName, componentRegistry, customFn) => { const onInstanceFn = componentRef && typeof onTrigger !== "function" ? (context, params) => __awaiter(void 0, void 0, void 0, function* () { // @ts-expect-error: _components isn't part of the public API const { _components } = context; const invokeTrigger = _components.invokeTrigger; const cniContext = (0, context_1.createCNIContext)(context, componentRegistry); const invokeResponse = (yield invokeTrigger(invokeTriggerComponentInput(componentRef, onTrigger, eventName), cniContext, null, params)) || {}; let customResponse = {}; if (customFn) { customResponse = (yield customFn(cniContext, params)) || {}; } return (0, merge_1.default)(invokeResponse, customResponse); }) : (context, params) => __awaiter(void 0, void 0, void 0, function* () { if (customFn) { const cniContext = (0, context_1.createCNIContext)(context, componentRegistry); return yield customFn(cniContext, params); } }); return onInstanceFn; }; const convertOnExecution = (onExecution, componentRegistry) => (context, params) => __awaiter(void 0, void 0, void 0, function* () { const actionContext = (0, context_1.createCNIContext)(context, componentRegistry); const result = yield onExecution(actionContext, params); (0, context_1.logDebugResults)(actionContext); return result; }); /** Creates the structure necessary to import a Component as part of a * Code Native integration. */ const codeNativeIntegrationComponent = ({ name, iconPath, description, flows = [], componentRegistry = {} }, referenceKey, configVars) => { const convertedActions = flows.reduce((result, { name, onExecution }) => { const key = flowFunctionKey(name, "onExecution"); return Object.assign(Object.assign({}, result), { [key]: { key, display: { label: `${name} - onExecution`, description: "The function that will be executed by the flow.", }, perform: convertOnExecution(onExecution, componentRegistry), inputs: [], } }); }, {}); const convertedTriggers = flows.reduce((result, { name, onTrigger, onInstanceDeploy, onInstanceDelete, schedule }) => { if (!flowUsesWrapperTrigger({ onTrigger, onInstanceDelete, onInstanceDeploy, })) { // In this scenario, the user has defined an existing component trigger // without any custom behavior, so we don't need to wrap anything. return result; } const key = flowFunctionKey(name, "onTrigger"); const defaultComponentKey = schedule && typeof schedule === "object" ? "schedule" : "webhook"; const defaultComponentRef = { component: { key: `${defaultComponentKey}-triggers`, version: "LATEST", isPublic: true, }, key: defaultComponentKey, }; // The component ref here is undefined if onTrigger is a function. const { ref } = (0, types_1.isComponentReference)(onTrigger) ? convertComponentReference(onTrigger, componentRegistry, "triggers") : { ref: onTrigger ? undefined : defaultComponentRef }; const performFn = generateTriggerPerformFn(ref, onTrigger, componentRegistry); const deleteFn = generateOnInstanceWrapperFn(ref, onTrigger, "onInstanceDelete", componentRegistry, onInstanceDelete); const deployFn = generateOnInstanceWrapperFn(ref, onTrigger, "onInstanceDeploy", componentRegistry, onInstanceDeploy); return Object.assign(Object.assign({}, result), { [key]: { key, display: { label: `${name} - onTrigger`, description: "The function that will be executed by the flow to return an HTTP response.", }, perform: performFn, onInstanceDeploy: deployFn, hasOnInstanceDeploy: !!deployFn, onInstanceDelete: deleteFn, hasOnInstanceDelete: !!deleteFn, inputs: [], scheduleSupport: "valid", synchronousResponseSupport: "valid", } }); }, {}); const convertedDataSources = Object.entries(configVars).reduce((result, [key, configVar]) => { if (!(0, types_1.isDataSourceDefinitionConfigVar)(configVar)) { return result; } const camelKey = (0, camelCase_1.default)(key); const dataSource = (0, pick_1.default)(configVar, ["perform", "dataSourceType"]); return Object.assign(Object.assign({}, result), { [camelKey]: Object.assign(Object.assign({}, dataSource), { key: camelKey, display: { label: key, description: key, }, inputs: [] }) }); }, {}); const convertedConnections = Object.entries(configVars).reduce((result, [key, configVar]) => { var _a; if (!(0, types_1.isConnectionDefinitionConfigVar)(configVar)) { return result; } const convertedInputs = Object.entries(configVar.inputs).map(([key, value]) => { if ("templateValue" in value) { return (0, convertComponent_1.convertTemplateInput)(key, value, configVar.inputs); } return (0, convertComponent_1.convertInput)(key, value); }); const connection = (0, pick_1.default)(configVar, ["oauth2Type", "oauth2PkceMethod"]); const { avatarPath: avatarIconPath, oauth2ConnectionIconPath: iconPath } = (_a = configVar.icons) !== null && _a !== void 0 ? _a : {}; return [ ...result, Object.assign(Object.assign({}, connection), { iconPath, avatarIconPath, inputs: convertedInputs, key: (0, camelCase_1.default)(key), label: key }), ]; }, []); return { key: referenceKey, display: { label: referenceKey, iconPath, description: description || name, }, connections: convertedConnections, actions: convertedActions, triggers: convertedTriggers, dataSources: convertedDataSources, }; };