UNPKG

rapini

Version:

Generate React Query hooks, SWR hooks, Axios requests and Typescript types from OpenAPI files

345 lines (344 loc) 14.6 kB
"use strict"; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.combineUniqueParams = exports.createParams = exports.refToTypeName = exports.sanitizeTypeName = exports.isRequestBodyObject = exports.normalizeOperationId = exports.lowercaseFirstLetter = exports.capitalizeFirstLetter = exports.appendNullToUnion = exports.nonArraySchemaObjectTypeToTs = exports.createDictionaryType = exports.createTypeAliasDeclarationType = exports.createTypeRefOrSchemaObjectIfPathRef = exports.schemaObjectTypeNode = exports.schemaObjectOrRefType = exports.nodeId = exports.isOneOfOrAnyOfObject = exports.isAllOfObject = exports.isArraySchemaObject = exports.isReferenceObject = exports.isParameterObject = exports.isOpenApiV3Document = void 0; var typescript_1 = __importDefault(require("typescript")); var types_1 = require("./types"); function isOpenApiV3Document(doc) { return "openapi" in doc; } exports.isOpenApiV3Document = isOpenApiV3Document; function isParameterObject(param) { return "name" in param; } exports.isParameterObject = isParameterObject; function isReferenceObject(item) { return item !== undefined && "$ref" in item; } exports.isReferenceObject = isReferenceObject; function isArraySchemaObject(param) { return "items" in param; } exports.isArraySchemaObject = isArraySchemaObject; function isAllOfObject(param) { return "allOf" in param; } exports.isAllOfObject = isAllOfObject; function isOneOfOrAnyOfObject(param) { return "oneOf" in param || "anyOf" in param; } exports.isOneOfOrAnyOfObject = isOneOfOrAnyOfObject; var unknownTypeNode = typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.UnknownKeyword); function nodeId(node) { if (typescript_1.default.isArrayTypeNode(node)) { return "Array<".concat(nodeId(node.elementType), ">"); } if (typescript_1.default.isParenthesizedTypeNode(node)) { return "(".concat(nodeId(node.type), ")"); } if (typescript_1.default.isUnionTypeNode(node)) { return node.types.map(nodeId).join("|"); } if (typescript_1.default.isTypeLiteralNode(node)) { return ("type-literal-" + node.members .map(function (elementType) { return elementType.name && typescript_1.default.isIdentifier(elementType.name) ? elementType.name.text : elementType.kind; }) .join("&")); } if (typescript_1.default.isIdentifier(node)) { return node.text; } if (typescript_1.default.isTypeReferenceNode(node)) { if (typescript_1.default.isIdentifier(node.typeName)) { return node.typeName.text; } } return node.kind.toString(); } exports.nodeId = nodeId; function schemaObjectOrRefType($refs, schema) { if (!schema || (isReferenceObject(schema) && !schema.$ref)) { return { node: unknownTypeNode, id: "unknown" }; } if (isReferenceObject(schema)) { if (schema.$ref.startsWith("#/paths/")) { var pathObj = $refs.get(schema.$ref); var node_1 = schemaObjectTypeNode($refs, pathObj); return { node: node_1, id: nodeId(node_1) }; } var refType = referenceType($refs, schema); return refType; } var node = schemaObjectTypeNode($refs, schema); return { node: node, id: nodeId(node) }; } exports.schemaObjectOrRefType = schemaObjectOrRefType; function createTypeNode($refs, item) { return isReferenceObject(item) ? createTypeRefOrSchemaObjectIfPathRef($refs, item) : schemaObjectTypeNode($refs, item); } function schemaObjectTypeNode($refs, item) { if (isAllOfObject(item) && item.allOf) { return typescript_1.default.factory.createIntersectionTypeNode(item.allOf.map(function (allOfItem) { return createTypeNode($refs, allOfItem); })); } if (isOneOfOrAnyOfObject(item)) { var items = item.oneOf || item.anyOf; if (items) { return typescript_1.default.factory.createUnionTypeNode(items.map(function (oneOrAnyItem) { return createTypeNode($refs, oneOrAnyItem); })); } } if (isArraySchemaObject(item)) { return typescript_1.default.factory.createArrayTypeNode(createTypeNode($refs, item.items)); } if (item.additionalProperties) { return createDictionaryType($refs, item); } if (item.properties) { return (0, types_1.createLiteralNodeFromProperties)($refs, item); } return nonArraySchemaObjectTypeToTs($refs, item); } exports.schemaObjectTypeNode = schemaObjectTypeNode; /** * Create a Ref Type Alias if local reference. * If it's a remote reference, starting with #/path/ then * resolve inline and do an inline object type */ function createTypeRefOrSchemaObjectIfPathRef($refs, item) { if (item.$ref.startsWith("#/paths/")) { // TODO: Instead of resolving inline, create a Type Alias instead and reference that var pathObj = $refs.get(item.$ref); return schemaObjectTypeNode($refs, pathObj); } return createTypeRefFromRef(item); } exports.createTypeRefOrSchemaObjectIfPathRef = createTypeRefOrSchemaObjectIfPathRef; function createTypeRefFromRef(item) { return typescript_1.default.factory.createTypeReferenceNode(refToTypeName(item.$ref)); } function createTypeAliasDeclarationType($refs, item) { return isReferenceObject(item) ? createTypeRefOrSchemaObjectIfPathRef($refs, item) : schemaObjectTypeNode($refs, item); } exports.createTypeAliasDeclarationType = createTypeAliasDeclarationType; function resolveAdditionalPropertiesType($refs, additionalProperties) { if (!additionalProperties) { return unknownTypeNode; } if (typeof additionalProperties === "boolean") { if (additionalProperties === true) { return typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.AnyKeyword); } return unknownTypeNode; } return createTypeAliasDeclarationType($refs, additionalProperties); } // Dictionaries look like: { [key: string]: any } function createDictionaryType($refs, item) { return typescript_1.default.factory.createTypeLiteralNode([ typescript_1.default.factory.createIndexSignature( /*modifiers*/ undefined, /*params*/ [ typescript_1.default.factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ typescript_1.default.factory.createIdentifier("key"), /*questionToken*/ undefined, /*type*/ typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.StringKeyword), /*initializer*/ undefined), ], /*type*/ resolveAdditionalPropertiesType($refs, item.additionalProperties)), ]); } exports.createDictionaryType = createDictionaryType; function nonArraySchemaObjectTypeToTs($refs, item) { if (!item.type) { return typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.AnyKeyword); } switch (item.type) { case "string": { if (item.enum) { return schemaObjectTypeToEnumType(item.enum, item.nullable); } return appendNullToUnion(typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.StringKeyword), item.nullable); } case "integer": case "number": return appendNullToUnion(typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.NumberKeyword), item.nullable); case "boolean": return appendNullToUnion(typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.BooleanKeyword), item.nullable); case "object": { if (item.additionalProperties) { return createDictionaryType($refs, item); } return appendNullToUnion((0, types_1.createLiteralNodeFromProperties)($refs, item), item.nullable); } default: return unknownTypeNode; } } exports.nonArraySchemaObjectTypeToTs = nonArraySchemaObjectTypeToTs; function schemaObjectTypeToEnumType(enumValues, nullable) { var enums = enumValues.map(function (value) { return typescript_1.default.factory.createLiteralTypeNode(typescript_1.default.factory.createStringLiteral(value)); }); return appendNullToUnion(typescript_1.default.factory.createUnionTypeNode(/*types*/ enums), nullable); } function appendNullToUnion(type, nullable) { return nullable ? typescript_1.default.factory.createUnionTypeNode( /*types*/ [ type, typescript_1.default.factory.createLiteralTypeNode(typescript_1.default.factory.createNull()), ]) : type; } exports.appendNullToUnion = appendNullToUnion; function referenceType($refs, item) { var name = refToTypeName(item.$ref); return { node: createTypeRefOrSchemaObjectIfPathRef($refs, item), id: name, }; } function capitalizeFirstLetter(str) { return str.charAt(0).toUpperCase() + str.slice(1); } exports.capitalizeFirstLetter = capitalizeFirstLetter; function lowercaseFirstLetter(str) { return str.charAt(0).toLowerCase() + str.slice(1); } exports.lowercaseFirstLetter = lowercaseFirstLetter; /** * Normalizes operation id's so there is consistency * @param operationId Raw value from openapi file * @returns normalized value with underscores and dashes removed, and in camelCase * @example normalizeOperationId("helloGoodbye") // helloGoodbye * @example normalizeOperationId("test1-test8-test1_test2") // test1Test8Test1Test2 * @example normalizeOperationId("Test1_test8-test1_test2") // test1Test8Test1Test2 */ function normalizeOperationId(operationId) { var split = operationId .split("-") .flatMap(function (x) { return x.split("_"); }) .map(function (x, i) { return i === 0 ? lowercaseFirstLetter(x) : capitalizeFirstLetter(x); }); return split.join(""); } exports.normalizeOperationId = normalizeOperationId; function isRequestBodyObject(obj) { return "content" in obj; } exports.isRequestBodyObject = isRequestBodyObject; // Replaces dots/hyphens/underscores with nothing // and capitalizes every items first letter function sanitizeTypeName(name) { return name .split(".") .flatMap(function (x) { return x.split("-"); }) .flatMap(function (x) { return x.split("_"); }) .map(capitalizeFirstLetter) .join(""); } exports.sanitizeTypeName = sanitizeTypeName; /** * Removes the path in the ref and just returns the last part, which is used as the Type name * @param ref The ref in the OpenAPI file * @returns The type name */ function refToTypeName(ref) { var parts = ref.split("/"); var lastPart = parts[parts.length - 1]; return sanitizeTypeName(lastPart); } exports.refToTypeName = refToTypeName; function createParams($refs, item, pathParams) { if (!item.parameters && !pathParams) { return []; } var paramObjects = combineUniqueParams($refs, pathParams, item.parameters); return paramObjects .sort(function (x, y) { return (x.required === y.required ? 0 : x.required ? -1 : 1); }) // put all optional values at the end .map(function (param) { var _a; return ({ required: (_a = param.required) !== null && _a !== void 0 ? _a : false, name: typescript_1.default.factory.createIdentifier(param.name), arrowFuncParam: typescript_1.default.factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ typescript_1.default.factory.createIdentifier(param.name), /*questionToken*/ param.required ? undefined : typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.QuestionToken), /*type*/ schemaObjectOrRefType($refs, param.schema).node, /*initializer*/ undefined), }); }); } exports.createParams = createParams; function resolveParams($refs, params) { return params.flatMap(function (p) { if (isParameterObject(p)) { return [p]; } var ref = $refs.get(p.$ref); if (isParameterObject(ref)) { return [ref]; } return []; }); } // Combines path and item parameters into a single unique array. // A unique parameter is defined by a combination of a name and location. // Item parameters override path parameters with the same name and location. function combineUniqueParams($refs, pathParams, itemParams) { if (pathParams === void 0) { pathParams = []; } if (itemParams === void 0) { itemParams = []; } var pathParamsResolved = resolveParams($refs, pathParams); var itemParamsResolved = resolveParams($refs, itemParams); if (!pathParamsResolved.length) { return itemParamsResolved; } else if (!itemParamsResolved.length) { return pathParamsResolved; } var paramKey = function (p) { return "".concat(p.name, "-").concat(p.in); }; var itemParamIds = new Set(itemParamsResolved.map(paramKey)); return __spreadArray(__spreadArray([], __read(itemParamsResolved), false), __read(pathParamsResolved.filter(function (p) { return !itemParamIds.has(paramKey(p)); })), false); } exports.combineUniqueParams = combineUniqueParams;