UNPKG

@lobehub/chat-plugin-sdk

Version:

Lobe Chat Plugin SDK, help you to build an amazing chat plugin for Lobe Chat

332 lines (325 loc) 13.5 kB
import _typeof from "@babel/runtime/helpers/esm/typeof"; import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime"; import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"; import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator"; import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; import _createClass from "@babel/runtime/helpers/esm/createClass"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import SwaggerParser from '@apidevtools/swagger-parser'; import { convertParametersToJSONSchema } from 'openapi-jsonschema-parameters'; import { pluginApiSchema } from "../schema/manifest"; export var OPENAPI_REQUEST_BODY_KEY = '_requestBody'; export var OpenAPIConvertor = /*#__PURE__*/function () { function OpenAPIConvertor(openapi) { var _this = this; _classCallCheck(this, OpenAPIConvertor); _defineProperty(this, "openapi", void 0); _defineProperty(this, "convertOpenAPIToPluginSchema", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() { var api, paths, methods, plugins, _i, _Object$entries, _Object$entries$_i, path, operations, _iterator, _step, method, operation, parametersSchema, requestBodySchema, parameters, _parameters$required, name, description, plugin, res; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: _context.next = 2; return SwaggerParser.dereference(_this.openapi); case 2: api = _context.sent; paths = api.paths; methods = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace']; plugins = []; _i = 0, _Object$entries = Object.entries(paths); case 7: if (!(_i < _Object$entries.length)) { _context.next = 42; break; } _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), path = _Object$entries$_i[0], operations = _Object$entries$_i[1]; _iterator = _createForOfIteratorHelper(methods); _context.prev = 10; _iterator.s(); case 12: if ((_step = _iterator.n()).done) { _context.next = 31; break; } method = _step.value; operation = operations[method]; if (!operation) { _context.next = 29; break; } parametersSchema = convertParametersToJSONSchema(operation.parameters || []); requestBodySchema = _this.convertRequestBodyToSchema(operation.requestBody); parameters = _this.mergeSchemas.apply(_this, _toConsumableArray(Object.values(parametersSchema))); if (requestBodySchema && requestBodySchema.properties && Object.keys(requestBodySchema.properties).length > 0) { parameters.properties[OPENAPI_REQUEST_BODY_KEY] = requestBodySchema; (_parameters$required = parameters.required) === null || _parameters$required === void 0 || _parameters$required.push('_requestBody'); } // 保留原始逻辑作为备选 name = operation.operationId || "".concat(method.toUpperCase(), " ").concat(path); description = operation.summary || operation.description || name; plugin = { description: description, name: name, parameters: parameters }; res = pluginApiSchema.safeParse(plugin); if (!res.success) { _context.next = 28; break; } plugins.push(plugin); _context.next = 29; break; case 28: throw res.error; case 29: _context.next = 12; break; case 31: _context.next = 36; break; case 33: _context.prev = 33; _context.t0 = _context["catch"](10); _iterator.e(_context.t0); case 36: _context.prev = 36; _iterator.f(); return _context.finish(36); case 39: _i++; _context.next = 7; break; case 42: return _context.abrupt("return", plugins); case 43: case "end": return _context.stop(); } }, _callee, null, [[10, 33, 36, 39]]); }))); _defineProperty(this, "convertAuthToSettingsSchema", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() { var rawSettingsSchema, settingsSchema, _yield$import, SwaggerClient, openAPI, api, _i2, _Object$entries2, _api$components, entry, authSchema, _ref3, _ref4, key, value, _args2 = arguments; return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: rawSettingsSchema = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : { properties: {}, type: 'object' }; settingsSchema = rawSettingsSchema; // @ts-ignore _context2.next = 4; return import('swagger-client'); case 4: _yield$import = _context2.sent; SwaggerClient = _yield$import.default; _context2.next = 8; return SwaggerClient.resolve({ spec: _this.openapi }); case 8: openAPI = _context2.sent; api = openAPI.spec; _i2 = 0, _Object$entries2 = Object.entries(((_api$components = api.components) === null || _api$components === void 0 ? void 0 : _api$components.securitySchemes) || {}); case 11: if (!(_i2 < _Object$entries2.length)) { _context2.next = 29; break; } entry = _Object$entries2[_i2]; authSchema = {}; _ref3 = entry, _ref4 = _slicedToArray(_ref3, 2), key = _ref4[0], value = _ref4[1]; _context2.t0 = value.type; _context2.next = _context2.t0 === 'apiKey' ? 18 : _context2.t0 === 'http' ? 20 : _context2.t0 === 'oauth2' ? 22 : 24; break; case 18: authSchema = { properties: _defineProperty({}, key, { description: value.description || "".concat(key, " API Key"), format: 'password', title: value.name, type: 'string' }), required: [key], type: 'object' }; return _context2.abrupt("break", 24); case 20: if (value.scheme === 'basic') { authSchema = { properties: _defineProperty({}, key, { description: 'Basic authentication credentials', format: 'password', type: 'string' }), required: [key], type: 'object' }; } else if (value.scheme === 'bearer') { authSchema = { properties: _defineProperty({}, key, { description: value.description || "".concat(key, " Bearer token"), format: 'password', title: key, type: 'string' }), required: [key], type: 'object' }; } return _context2.abrupt("break", 24); case 22: authSchema = { properties: _defineProperty(_defineProperty(_defineProperty({}, "".concat(key, "_clientId"), { description: 'Client ID for OAuth2', type: 'string' }), "".concat(key, "_clientSecret"), { description: 'Client Secret for OAuth2', format: 'password', type: 'string' }), "".concat(key, "_accessToken"), { description: 'Access token for OAuth2', format: 'password', type: 'string' }), required: ["".concat(key, "_clientId"), "".concat(key, "_clientSecret"), "".concat(key, "_accessToken")], type: 'object' }; return _context2.abrupt("break", 24); case 24: // 合并当前鉴权机制的 schema 到 settingsSchema Object.assign(settingsSchema.properties, authSchema.properties); if (authSchema.required) { settingsSchema.required = _toConsumableArray(new Set([].concat(_toConsumableArray(settingsSchema.required || []), _toConsumableArray(authSchema.required)))); } case 26: _i2++; _context2.next = 11; break; case 29: return _context2.abrupt("return", settingsSchema); case 30: case "end": return _context2.stop(); } }, _callee2); }))); this.openapi = openapi; } _createClass(OpenAPIConvertor, [{ key: "convertRequestBodyToSchema", value: function convertRequestBodyToSchema(requestBody) { if (!requestBody || !requestBody.content) { return null; } var requestBodySchema = {}; // 遍历所有的 content-type for (var _i3 = 0, _Object$entries3 = Object.entries(requestBody.content); _i3 < _Object$entries3.length; _i3++) { var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i3], 2), contentType = _Object$entries3$_i[0], mediaType = _Object$entries3$_i[1]; if (mediaType.schema) { // 直接使用已解析的 Schema var resolvedSchema = this.removeRequiredFields(mediaType.schema); // 根据不同的 content-type,可以在这里添加特定的处理逻辑 switch (contentType) { case 'application/json': { // 直接使用解析后的 Schema 作为 JSON 的请求体定义 requestBodySchema = resolvedSchema; break; } case 'application/x-www-form-urlencoded': case 'multipart/form-data': { // 这些类型通常用于文件上传和表单数据,可能需要特别处理 requestBodySchema = resolvedSchema; break; } // 其他 MIME 类型... default: { // 如果遇到未知的 content-type,可以选择忽略或抛出错误 console.warn("Unsupported content-type: ".concat(contentType)); break; } } } } return requestBodySchema; } }, { key: "removeRequiredFields", value: function removeRequiredFields(schema) { if (schema && _typeof(schema) === 'object') { // 如果是对象类型,遍历它的每个属性 for (var key in schema) { // eslint-disable-next-line no-prototype-builtins if (schema.hasOwnProperty(key)) { var value = schema[key]; // 如果属性是 required 并且值为 true,则删除该属性 if (key === 'required' && value === true) { delete schema[key]; } else { // 否则,如果属性是对象或数组,则递归处理 schema[key] = this.removeRequiredFields(value); } } } } else if (Array.isArray(schema)) { // 如果是数组类型,遍历每个元素 return schema.map(this.removeRequiredFields.bind(this)); } return schema; } }, { key: "mergeSchemas", value: function mergeSchemas() { var _mergedSchema$require; // 初始化合并后的 Schema var mergedSchema = { properties: {}, required: [], type: 'object' }; // 遍历每个参数的 Schema for (var _len = arguments.length, schemas = new Array(_len), _key = 0; _key < _len; _key++) { schemas[_key] = arguments[_key]; } for (var _i4 = 0, _schemas = schemas; _i4 < _schemas.length; _i4++) { var schema = _schemas[_i4]; if (schema && schema.properties) { // 合并属性 Object.assign(mergedSchema.properties, schema.properties); // 合并必需字段 if (Array.isArray(schema.required)) { mergedSchema.required = _toConsumableArray(new Set([].concat(_toConsumableArray(mergedSchema.required || []), _toConsumableArray(schema.required)))); } } } // 如果没有任何必需字段,则删除 required 属性 if (((_mergedSchema$require = mergedSchema.required) === null || _mergedSchema$require === void 0 ? void 0 : _mergedSchema$require.length) === 0) { delete mergedSchema.required; } return mergedSchema; } }]); return OpenAPIConvertor; }();