in source/nodejs/ac-typed-schema/src/typed-schema.ts [151:357]
private transformType(type: SchemaType) {
try {
if (type instanceof SchemaEnum) {
var enumType = type as SchemaEnum;
var transformed: any = { ...type.original };
delete transformed.type;
delete transformed.values;
delete transformed.classType;
delete transformed.$schema;
delete transformed.extends;
var enums: string[] = [];
enumType.values.forEach(val => {
enums.push(val.value);
});
// If only allows strict enums but case-insensitive...
if (!this._enforceEnumCaseSensitivity && !this._allowCustomEnums) {
var enumRegexs: string[] = [];
enums.forEach(enumVal => {
enumRegexs.push("(" + this.toCaseInsensitiveRegex(enumVal) + ")");
});
var regex = "^" + enumRegexs.join("|") + "$";
transformed.anyOf = [
{
"enum": enums
},
{
"pattern": regex
}
];
} else if (!this._allowCustomEnums) {
// Else strict and sensitive
transformed.enum = enums;
} else {
// Else allows any enums, so no need for the regex
transformed.anyOf = [
{
"enum": enums
},
{
"type": "string"
}
];
}
return transformed;
} else if (!(type instanceof SchemaClass)) {
throw new Error("Unknown class type " + type);
}
var transformed: any = { ...type.original };
transformed.type = "object";
if (!this._allowAdditionalProperties) {
transformed.additionalProperties = false;
}
delete transformed.isAbstract;
delete transformed.classType;
delete transformed.$schema;
delete transformed.extends;
delete transformed.shorthand;
transformed.properties = {};
var overridesProperties = false;
var properties = new Map<string, SchemaProperty>();
if (type.extends.length > 0) {
type.properties.forEach(prop => {
if (prop.override) {
// If property exists in base classes
if (type.getAllExtendedProperties().indexOf(prop.name) !== -1) {
// Note that JSON schema doesn't support the concept of overriding properties, so instead
// we need to copy all the properties and NOT inherit.
overridesProperties = true;
} else {
console.warn(`${type.type}.${prop.name} has override set to true, but it doesn't override any base class properties.`);
}
} else {
// If property exists in base classes
if (type.getAllExtendedProperties().indexOf(prop.name) !== -1) {
console.warn(`Ignoring ${type.type}.${prop.name} as there's already this property specified in a base class. If you want to keep this property, add "override": "true".`);
}
}
});
}
if (overridesProperties) {
type.getAllProperties().forEach((propVal, key) => {
properties.set(key, propVal);
});
} else {
properties = type.properties;
}
if (properties.size > 0) {
properties.forEach((propVal, key) => {
var transformedPropVal: any;
try {
transformedPropVal = this.transformPropertyValue(propVal);
} catch (err) {
throw new Error("Failed transforming property " + key + "\n\n" + err.stack);
}
if (transformedPropVal.required) {
delete transformedPropVal.required;
if (!transformed.required) {
transformed.required = [];
}
transformed.required.push(key);
}
transformed.properties[key] = transformedPropVal;
});
}
if (!type.isAbstract) {
// If it's not abstract, we add the type property
// Note that we don't require it though, it's optional
var newProperties: any = {};
newProperties[this._typePropertyName] = {
"enum": [type.type],
"description": "Must be `" + type.type + "`"
};
transformed.properties = {
...newProperties,
...transformed.properties
};
}
if (type.extends.length > 0) {
if (!overridesProperties) {
// Have to add placeholders for all the properties
type.getAllExtendedProperties().forEach(extendedPropKey => {
// If there's an existing property defined, skip
var existingProp = type.properties.get(extendedPropKey);
if (existingProp !== undefined) {
if (!existingProp.override) {
console.warn(`Overriding extended property ${extendedPropKey} on type ${type.type}. If this was intentional, add "override": "true" to this property to prevent this warning from appearing.`);
}
return;
}
transformed.properties[extendedPropKey] = {};
});
transformed.allOf = [];
type.extends.forEach(extended => {
if (extended.getAllProperties().size > 0) {
transformed.allOf.push({
$ref: "#/definitions/Extendable." + extended.type
});
}
});
if (transformed.allOf.length == 0) {
delete transformed.allOf;
}
}
// Keep track of implementations
type.getAllExtended().forEach(extended => {
if (!this._implementationsOf[extended.type]) {
this._implementationsOf[extended.type] = [];
// If extending type isn't abstract, add that as an implementation
if (!extended.isAbstract) {
this._implementationsOf[extended.type].push(extended.type);
}
}
if (!type.isAbstract) {
this._implementationsOf[extended.type].push(type.type);
}
});
delete transformed.extends;
}
if (type.shorthand) {
transformed.anyOf = [
{
...transformed.properties[type.shorthand.name]
},
{
type: transformed.type,
properties: transformed.properties,
required: transformed.required,
additionalProperties: false
}
];
delete transformed.type;
delete transformed.properties;
delete transformed.required;
delete transformed.additionalProperties;
}
return transformed;
} catch (err) {
throw "Failed transforming type " + type.type + "\n\n" + err.stack;
}
}