UNPKG

@prismatic-io/spectral

Version:

Utility library for building Prismatic connectors and code-native integrations

136 lines (135 loc) 7.38 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.createInvokeFlow = void 0; exports.createCNIContext = createCNIContext; exports.createDebugContext = createDebugContext; exports.logDebugResults = logDebugResults; const node_perf_hooks_1 = require("node:perf_hooks"); const node_process_1 = require("node:process"); const axios_1 = __importDefault(require("axios")); const convertIntegration_1 = require("./convertIntegration"); const MEMORY_USAGE_CONVERSION = 1024 * 1024; function createCNIContext(context, componentRegistry) { // Component, debug, and invokeFlow methods are not provided as part of the server context. // They are added to the context via spectral, here. var _a; // @ts-expect-error _components isn't part of the public API const _components = (_a = context._components) !== null && _a !== void 0 ? _a : { invoke: () => { } }; const invoke = _components.invoke; // Construct the component methods from the component registry const componentMethods = Object.entries(componentRegistry).reduce((accumulator, [registryComponentKey, { key: componentKey, actions, public: isPublic, signature }]) => { const componentActions = Object.entries(actions).reduce((actionsAccumulator, [registryActionKey, action]) => { const manifestActions = componentRegistry[registryComponentKey].actions[registryActionKey]; // Define the method to be called for the action const invokeAction = (values) => __awaiter(this, void 0, void 0, function* () { var _a; // Apply defaults directly within the transformation process const transformedValues = Object.entries(manifestActions.inputs).reduce((transformedAccumulator, [inputKey, inputValueBase]) => { var _a; const inputValue = (_a = values[inputKey]) !== null && _a !== void 0 ? _a : inputValueBase.default; const { collection } = inputValueBase; return Object.assign(Object.assign({}, transformedAccumulator), { [inputKey]: (0, convertIntegration_1.convertInputValue)(inputValue, collection) }); }, {}); // Invoke the action with the transformed values return invoke({ component: { key: componentKey, signature: signature !== null && signature !== void 0 ? signature : "", isPublic, }, // older versions of manifests did not contain action.key so we fall back to the registry key key: (_a = action.key) !== null && _a !== void 0 ? _a : registryActionKey, }, Object.assign(Object.assign({}, context), { debug: createDebugContext(context) }), transformedValues); }); return Object.assign(Object.assign({}, actionsAccumulator), { [registryActionKey]: invokeAction }); }, {}); return Object.assign(Object.assign({}, accumulator), { [registryComponentKey]: componentActions }); }, {}); return Object.assign(Object.assign({}, context), { debug: createDebugContext(context), components: componentMethods, invokeFlow: (0, exports.createInvokeFlow)(context, { isCNI: true }) }); } function createDebugContext(context) { const globalDebug = Boolean(context.globalDebug); return { enabled: globalDebug, timeElapsed: { mark: (actionContext, label) => { if (globalDebug) { actionContext.debug.results.timeElapsed.marks[label] = node_perf_hooks_1.performance.now(); } }, measure: (actionContext, label, marks) => { if (globalDebug) { actionContext.debug.results.timeElapsed.measurements[label] = { marks, duration: actionContext.debug.results.timeElapsed.marks[marks.end] - actionContext.debug.results.timeElapsed.marks[marks.start], }; } }, }, memoryUsage: (actionContext, label, showDetail) => { if (globalDebug) { const usage = showDetail ? memoryUsageInMB() : node_process_1.memoryUsage.rss() / MEMORY_USAGE_CONVERSION; actionContext.debug.results.memoryUsage.push({ mark: label, rss: typeof usage === "number" ? usage : usage.rss, detail: typeof usage === "number" ? undefined : usage, }); } }, results: { timeElapsed: { marks: {}, measurements: {} }, memoryUsage: [], allowedMemory: Number(context.runnerAllocatedMemoryMb), }, }; } function logDebugResults(context) { if (context.debug.enabled) { context.logger.metric(context.debug.results); } } function memoryUsageInMB() { const usage = (0, node_process_1.memoryUsage)(); return Object.keys(usage).reduce((accum, key) => { accum[key] = usage[key] / MEMORY_USAGE_CONVERSION; return accum; }, { rss: -1, heapTotal: -1, heapUsed: -1, external: -1, arrayBuffers: -1, }); } function formatExecutionFrameHeaders(frame, source) { let frameToUse = frame; if (source) { frameToUse = Object.assign(Object.assign({}, frame), { customSource: source }); } return JSON.stringify(frameToUse); } const createInvokeFlow = (context, options = {}) => { return (flowName, data, config, source) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; const sourceToUse = options.isCNI ? source : undefined; return yield axios_1.default.post(context.webhookUrls[flowName], data, Object.assign(Object.assign({}, config), { headers: Object.assign(Object.assign(Object.assign({}, ((_a = config === null || config === void 0 ? void 0 : config.headers) !== null && _a !== void 0 ? _a : {})), (((_b = context.webhookApiKeys[flowName]) === null || _b === void 0 ? void 0 : _b.length) > 0 ? { "Api-Key": context.webhookApiKeys[flowName][0], } : {})), { "prismatic-invoked-by": formatExecutionFrameHeaders(context.executionFrame, sourceToUse), "prismatic-invoke-type": "Cross Flow", "prismatic-executionid": context.executionId }) })); }); }; exports.createInvokeFlow = createInvokeFlow;