UNPKG

@prismatic-io/spectral

Version:

Utility library for building Prismatic connectors and code-native integrations

175 lines (174 loc) 10.5 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertComponent = exports.convertConnection = exports.convertTrigger = exports.convertTemplateInput = exports._isValidTemplateValue = exports.convertInput = void 0; const types_1 = require("../types"); const perform_1 = require("./perform"); const omit_1 = __importDefault(require("lodash/omit")); const PollingTriggerDefinition_1 = require("../types/PollingTriggerDefinition"); const convertInput = (key, _a) => { var { default: defaultValue, type, label, collection } = _a, rest = __rest(_a, ["default", "type", "label", "collection"]); const keyLabel = collection === "keyvaluelist" && typeof label === "object" ? label.key : undefined; return Object.assign(Object.assign({}, (0, omit_1.default)(rest, [ "onPremControlled", "permissionAndVisibilityType", "visibleToOrgDeployer", "writeOnly", ])), { key, type, default: defaultValue !== null && defaultValue !== void 0 ? defaultValue : types_1.InputFieldDefaultMap[type], collection, label: typeof label === "string" ? label : label.value, keyLabel, onPremiseControlled: ("onPremControlled" in rest && rest.onPremControlled) || undefined }); }; exports.convertInput = convertInput; const TEMPLATE_VALUE_REGEX = /{{#(\w+)}}/g; const TEMPLATE_VALUE_ERRORS = { NO_SLOTS: "No template slots were found. Declare a template slot with this notation: {{#someInputKey}}", INVALID_KEYS: "Invalid keys were found in the template string. All referenced keys must be non-template inputs declared in the first argument:", }; const _isValidTemplateValue = (template, inputs) => { const matches = [...template.matchAll(TEMPLATE_VALUE_REGEX)]; if (matches.length === 0) { return { isValid: false, error: TEMPLATE_VALUE_ERRORS.NO_SLOTS, }; } const invalidKeys = []; for (const [_substr, key] of matches) { if (!inputs[key] || inputs[key].type === "template") { invalidKeys.push(key); } } if (invalidKeys.length > 0) { return { isValid: false, error: `${TEMPLATE_VALUE_ERRORS.INVALID_KEYS} ${invalidKeys}`, }; } return { isValid: true, }; }; exports._isValidTemplateValue = _isValidTemplateValue; const convertTemplateInput = (key, _a, inputs) => { var { templateValue, label } = _a, rest = __rest(_a, ["templateValue", "label"]); const validation = (0, exports._isValidTemplateValue)(templateValue, inputs); if (!validation.isValid) { throw `Template input "${key}": ${validation.error}`; } return Object.assign(Object.assign({}, (0, omit_1.default)(rest, ["permissionAndVisibilityType", "visibleToOrgDeployer", "writeOnly"])), { key, type: "template", default: templateValue !== null && templateValue !== void 0 ? templateValue : "", label: typeof label === "string" ? label : label.value, shown: false }); }; exports.convertTemplateInput = convertTemplateInput; const convertAction = (actionKey, _a, hooks) => { var { inputs = {}, perform } = _a, action = __rest(_a, ["inputs", "perform"]); const convertedInputs = Object.entries(inputs).map(([key, value]) => (0, exports.convertInput)(key, value)); const inputCleaners = Object.entries(inputs).reduce((result, [key, { clean }]) => (Object.assign(Object.assign({}, result), { [key]: clean })), {}); return Object.assign(Object.assign({}, action), { key: actionKey, inputs: convertedInputs, perform: (0, perform_1.createPerform)(perform, { inputCleaners, errorHandler: hooks === null || hooks === void 0 ? void 0 : hooks.error, }) }); }; const convertTrigger = (triggerKey, trigger, hooks) => { var _a; const { onInstanceDeploy, onInstanceDelete } = trigger; const inputs = (_a = trigger.inputs) !== null && _a !== void 0 ? _a : {}; const isPollingTrigger = (0, PollingTriggerDefinition_1.isPollingTriggerDefinition)(trigger); const triggerInputKeys = Object.keys(inputs); const convertedTriggerInputs = Object.entries(inputs).map(([key, value]) => { return (0, exports.convertInput)(key, value); }); const triggerInputCleaners = Object.entries(inputs).reduce((result, [key, { clean }]) => (Object.assign(Object.assign({}, result), { [key]: clean })), {}); let scheduleSupport = "scheduleSupport" in trigger ? trigger.scheduleSupport : "invalid"; let convertedActionInputs = []; let performToUse; if (isPollingTrigger) { // Pull inputs up from the action and make them available on the trigger const { pollAction: action } = trigger; let actionInputCleaners = {}; scheduleSupport = "required"; if (action) { convertedActionInputs = Object.entries(action.inputs).reduce((accum, [key, value]) => { if (triggerInputKeys.includes(key)) { throw new Error(`The pollingTrigger "${trigger.display.label}" was defined with an input with the key: ${key}. This key duplicates an input on the associated "${action.display.label}" action. Please assign the trigger input a different key.`); } accum.push((0, exports.convertInput)(key, value)); return accum; }, []); actionInputCleaners = Object.entries(action.inputs).reduce((result, [key, { clean }]) => (Object.assign(Object.assign({}, result), { [key]: clean })), {}); } const combinedCleaners = Object.assign({}, actionInputCleaners, triggerInputCleaners); performToUse = (0, perform_1.createPollingPerform)(trigger, { inputCleaners: combinedCleaners, errorHandler: hooks === null || hooks === void 0 ? void 0 : hooks.error, }); } else { performToUse = (0, perform_1.createPerform)(trigger.perform, { inputCleaners: triggerInputCleaners, errorHandler: hooks === null || hooks === void 0 ? void 0 : hooks.error, }); } const result = Object.assign(Object.assign({}, trigger), { key: triggerKey, inputs: convertedTriggerInputs.concat(convertedActionInputs), perform: performToUse, scheduleSupport, synchronousResponseSupport: "synchronousResponseSupport" in trigger ? trigger.synchronousResponseSupport : scheduleSupport === "invalid" ? "valid" : "invalid" }); if (onInstanceDeploy) { result.onInstanceDeploy = (0, perform_1.createPerform)(onInstanceDeploy, { inputCleaners: triggerInputCleaners, errorHandler: hooks === null || hooks === void 0 ? void 0 : hooks.error, }); result.hasOnInstanceDeploy = true; } if (onInstanceDelete) { result.onInstanceDelete = (0, perform_1.createPerform)(onInstanceDelete, { inputCleaners: triggerInputCleaners, errorHandler: hooks === null || hooks === void 0 ? void 0 : hooks.error, }); result.hasOnInstanceDelete = true; } const { pollAction, triggerType } = result, resultTrigger = __rest(result, ["pollAction", "triggerType"]); return resultTrigger; }; exports.convertTrigger = convertTrigger; const convertDataSource = (dataSourceKey, _a, hooks) => { var { inputs = {}, perform } = _a, dataSource = __rest(_a, ["inputs", "perform"]); const convertedInputs = Object.entries(inputs).map(([key, value]) => (0, exports.convertInput)(key, value)); const inputCleaners = Object.entries(inputs).reduce((result, [key, { clean }]) => (Object.assign(Object.assign({}, result), { [key]: clean })), {}); return Object.assign(Object.assign({}, dataSource), { key: dataSourceKey, inputs: convertedInputs, perform: (0, perform_1.createPerform)(perform, { inputCleaners, errorHandler: hooks === null || hooks === void 0 ? void 0 : hooks.error, }) }); }; const convertConnection = (_a) => { var { inputs = {} } = _a, connection = __rest(_a, ["inputs"]); const { display: { label, icons, description: comments } } = connection, remaining = __rest(connection, ["display"]); const convertedInputs = Object.entries(inputs).map(([key, value]) => { if ("templateValue" in value) { return (0, exports.convertTemplateInput)(key, value, inputs); } return (0, exports.convertInput)(key, value); }); return Object.assign(Object.assign({}, remaining), { label, comments, iconPath: icons === null || icons === void 0 ? void 0 : icons.oauth2ConnectionIconPath, avatarIconPath: icons === null || icons === void 0 ? void 0 : icons.avatarPath, inputs: convertedInputs }); }; exports.convertConnection = convertConnection; const convertComponent = (_a) => { var { connections = [], actions = {}, triggers = {}, dataSources = {}, hooks } = _a, definition = __rest(_a, ["connections", "actions", "triggers", "dataSources", "hooks"]); const convertedActions = Object.entries(actions).reduce((result, [actionKey, action]) => (Object.assign(Object.assign({}, result), { [actionKey]: convertAction(actionKey, action, hooks) })), {}); const convertedTriggers = Object.entries(triggers).reduce((result, [triggerKey, trigger]) => (Object.assign(Object.assign({}, result), { [triggerKey]: (0, exports.convertTrigger)(triggerKey, trigger, hooks) })), {}); const convertedDataSources = Object.entries(dataSources).reduce((result, [dataSourceKey, dataSource]) => (Object.assign(Object.assign({}, result), { [dataSourceKey]: convertDataSource(dataSourceKey, dataSource, hooks) })), {}); return Object.assign(Object.assign({}, definition), { connections: connections.map(exports.convertConnection), actions: convertedActions, triggers: convertedTriggers, dataSources: convertedDataSources }); }; exports.convertComponent = convertComponent;