rapini
Version:
Generate React Query hooks, SWR hooks, Axios requests and Typescript types from OpenAPI files
345 lines (344 loc) • 14.6 kB
JavaScript
"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;