@dvsa/mes-test-schema
Version:
Domain model for data associated with tests administered by the Driving Examiner Services project
129 lines (110 loc) • 4.9 kB
text/typescript
declare var require: any;
declare var process: any;
const merge = require('deepmerge');
const common = require('./category-definitions/common/index.json');
const fs = require('fs');
const prettyJs = require('pretty-js');
const json2ts = require('json-schema-to-typescript');
const derefSchema = require('json-schema-deref-sync');
const categories = [
'ADI2',
'B',
'BE',
'C', 'CE', 'C1', 'C1E', 'CM', 'C1M', 'CEM', 'C1EM',
'D', 'DE', 'D1', 'D1E', 'DM', 'D1M', 'DEM', 'D1EM',
'F', 'G', 'H', 'K',
];
// standalone categories are categories that don't merge with the common schema
const standaloneCategories = ['AM1', 'AM2', 'CPC', 'ADI3'];
// Json styling config
const options = {
indent: "\t",
newline: "\r\n",
quoteProperties: "true"
};
const cliArgument = process.argv[2];
// Clears and cleans the generated schemas/typescripts
if (cliArgument === 'clean') {
deleteFileIfExists(`./categories/common/index.d.ts`);
for (let category of categories) {
deleteFileIfExists(`./categories/${category}/index.json`);
deleteFileIfExists(`./categories/${category}/partial.d.ts`);
// DO NOT DELETE THIS FILE IT HAS BEEN MODIFIED BY HAND
// AND WILL NOT BE REGENERATED
// deleteFileIfExists(`./categories/${category}/index.d.ts`);
}
console.log('All categories have been cleaned');
}
if (cliArgument === 'generate') {
// Generate common typescript file
generateTypescriptInterfaces(`./category-definitions/common/index.json`, `./categories/common/index.d.ts`);
for (let category of categories) {
const partialSchema = `./category-definitions/${category}/partial.json`;
const combinedSchema = `./categories/${category}/index.json`;
// Generate combined schemas
generateCombinedSchema(partialSchema, combinedSchema);
// Generate typescript files
generateTypescriptInterfaces(partialSchema, `./categories/${category}/partial.d.ts`);
// DO NOT REGENERATE THIS FILE. IT HAS BEEN MODIFIED BY HAND
// generateTypescriptInterfaces(combinedSchema);
}
for (let category of standaloneCategories) {
// dereference and copy across Cat partial.json files
deReferenceJsonSchema(`./category-definitions/${category}/index.json`, `./categories/${category}/index.json`);
// generate Cat typescript files (standalone)
generateTypescriptInterfaces(`./category-definitions/${category}/index.json`, `./categories/${category}/index.d.ts`);
}
// copy common partial.json file across for consistency
copyFile(`./category-definitions/common/index.json`, `./categories/common/index.json`);
console.log('All categories have been generated');
}
function copyFile(source: string, destination: string) {
fs.copyFile(source, destination, (err: NodeJS.ErrnoException | null) => {
if (err) throw err;
});
}
function generateCombinedSchema(partialSchemaLocation: string, combinedSchemaLocation: string) {
const currentCategoryJson = require(partialSchemaLocation);
currentCategoryJson['title'] = currentCategoryJson['title'].replace('Partial ', '');
const combinedJsonObject = removeRefs(merge(common, currentCategoryJson));
let combinedJsonString = JSON.stringify(combinedJsonObject);
combinedJsonString = combinedJsonString.replace(/..\/common\/index.json/g, '');
fs.writeFileSync(combinedSchemaLocation, prettyJs(combinedJsonString, options));
}
function generateTypescriptInterfaces(schemaLocation: string, saveToLocation: string) {
json2ts.compileFromFile(schemaLocation, {
unreachableDefinitions: true
}).then((ts: string) => fs.writeFileSync(saveToLocation, ts))
}
function deleteFileIfExists(fileLocation: string) {
try {
fs.unlinkSync(fileLocation);
} catch (e) {
console.error(e);
}
}
// Remove all $ref if they have siblings
function removeRefs(obj: any): any {
const removeRefsFields = (obj: any) => {
Object.keys(obj).forEach((key) => {
const value = obj[key];
if (key === '$ref' && Object.keys(obj).length > 1) delete obj[key];
if (typeof value === 'object') removeRefsFields(value);
});
return obj;
};
return removeRefsFields(obj);
}
function deReferenceJsonSchema(sourcePath: string, targetPath: string): void {
const originalSchema = require(sourcePath);
const baseFolder = sourcePath.substring(0, sourcePath.lastIndexOf("/"));
let deReferencedJsonSchema = derefSchema(originalSchema, {
baseFolder: baseFolder,
});
let deReferencedSchema = prettyJs(JSON.stringify(deReferencedJsonSchema), options);
fs.writeFile(targetPath, deReferencedSchema, 'utf8', (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`unable to write to file ${targetPath}`);
}
})
}