pact-gen-ts
Version:
Generating pact files from typescript definitions
143 lines (142 loc) • 5.89 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTypeRepresentation = getTypeRepresentation;
const ts = __importStar(require("typescript"));
const pact_annotations_1 = require("../consts/pact-annotations");
function getTypeRepresentation(entryType, source, isResponseFromFunction) {
if (entryType.isAny()) {
console.error('[ERROR]: "any" type is not allowed.');
process.exit(1);
}
if (entryType.isTuple()) {
console.error('[ERROR]: tuples in this tool are not allowed.');
process.exit(2);
}
if (entryType.isUnknown() || entryType.isUndefined() || entryType.isNull()) {
return {};
}
const stringRepresentationOfType = entryType.getText(source);
// Only for return type from function
if (isResponseFromFunction && (stringRepresentationOfType.includes('AxiosResponse<any>') || stringRepresentationOfType === 'void')) {
return {};
}
if (entryType.isArray()) {
const arrayElementType = entryType.getArrayElementTypeOrThrow();
return {
...getTypeRepresentation(arrayElementType, source),
isArray: true,
};
}
// For cases: field: "value";
if (entryType.isLiteral()) {
const literalValue = String(entryType.getLiteralValue());
return {
enumValues: [literalValue],
isEnum: true,
};
}
if ((entryType.isEnum() || entryType.isUnion()) && stringRepresentationOfType !== 'boolean') {
const enumMembers = entryType.getUnionTypes();
const enumValues = enumMembers.map((member) => member.getLiteralValue()).filter((member) => member);
if (enumValues.length) {
return {
enumValues: enumValues,
isEnum: true,
};
}
// For cases: field: "YES" | undefined;
return getTypeRepresentation(enumMembers[0], source);
}
switch (stringRepresentationOfType) {
case 'Blob':
return { type: 'string' };
case 'string':
case 'boolean':
case 'number':
return { type: stringRepresentationOfType };
default:
return { type: getObjectTypeRepresentation(entryType, source) };
}
}
const getObjectTypeRepresentation = (entryType, source) => {
const objectTypeRepresentation = {};
const objectProperties = entryType.getProperties();
for (const property of objectProperties) {
const propertyName = property.getEscapedName();
let typeMatcher;
let exampleRepresentation;
getJsDocTagsForObjectProperty(property).forEach((jsDocTag) => {
const annotation = jsDocTag.getFirstChildByKind(ts.SyntaxKind.Identifier)?.getText();
if (annotation === pact_annotations_1.PACT_ANNOTATIONS.PACT_MATCHER) {
typeMatcher = jsDocTag.getCommentText();
}
else if (annotation === pact_annotations_1.PACT_ANNOTATIONS.PACT_EXAMPLE) {
exampleRepresentation = jsDocTag?.getCommentText();
}
});
const propertyType = property.getTypeAtLocation(source);
const propertyTypeRepresentation = getTypeRepresentation(propertyType, source);
if (typeMatcher && exampleRepresentation) {
objectTypeRepresentation[propertyName] = {
...propertyTypeRepresentation,
type: typeMatcher,
exampleValue: exampleRepresentation,
};
}
else if (typeMatcher) {
objectTypeRepresentation[propertyName] = { ...propertyTypeRepresentation, type: typeMatcher };
}
else if (exampleRepresentation) {
objectTypeRepresentation[propertyName] = { ...propertyTypeRepresentation, exampleValue: exampleRepresentation };
}
else {
objectTypeRepresentation[propertyName] = propertyTypeRepresentation;
}
}
return objectTypeRepresentation;
};
/** Find all JS Doc tag children nodes for object property - handle only current property level without going lower in the tree **/
function getJsDocTagsForObjectProperty(property) {
const jsDocComments = property.getValueDeclaration()?.getChildrenOfKind(ts.SyntaxKind.JSDocComment);
if (!jsDocComments) {
return [];
}
const jsDocTags = [];
for (const jsDocComment of jsDocComments) {
jsDocTags.push(...jsDocComment.getChildrenOfKind(ts.SyntaxKind.JSDocTag));
}
return jsDocTags;
}