mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-15 10:11:50 +08:00
With this change we automate the generation of `@angular/cli/lib/config/schema.json`. While on paper we could use quicktype for this. Quicktype doesn't handle `patternProperties` and `oneOf` that well. How does this works? Relative `$ref` will be resolved and inlined as part of the root schema definitions. Example ```json "@schematics/angular:enum": { "$ref": "../../../../schematics/angular/enum/schema.json" }, ``` Will be parsed and transformed to ```json "@schematics/angular:enum": { "$ref": "#/definitions/SchematicsAngularEnumSchema" }, "definitions: { "SchematicsAngularEnumSchema": { "title": "Angular Enum Options Schema", "type": "object", "description": "Generates a new, generic enum definition for the given or default project.", "properties": {...} } } ```
92 lines
2.6 KiB
JavaScript
92 lines
2.6 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
const { readFileSync, writeFileSync, mkdirSync } = require('fs');
|
|
const { resolve, dirname } = require('path');
|
|
|
|
/**
|
|
* Generator the Angular CLI workspace schema file.
|
|
*/
|
|
function generate(inPath, outPath) {
|
|
// While on paper we could use quicktype for this.
|
|
// Quicktype doesn't handle `patternProperties` and `oneOf` that well.
|
|
|
|
const jsonSchema = readFileSync(inPath, 'utf8');
|
|
const nestedDefinitions = {};
|
|
const schemaParsed = JSON.parse(jsonSchema, (key, value) => {
|
|
if (key === '$ref' && typeof value === 'string' && !value.startsWith('#')) {
|
|
// Resolve $ref and camelize key
|
|
const definitionKey = value
|
|
.replace(/(\.json|src)/g, '')
|
|
.split(/\\|\/|_|-|\./)
|
|
.filter(p => !!p)
|
|
.map(s => s.charAt(0).toUpperCase() + s.slice(1))
|
|
.join('');
|
|
|
|
const nestedSchemaPath = resolve(dirname(inPath), value);
|
|
const nestedSchema = readFileSync(nestedSchemaPath, 'utf8');
|
|
const nestedSchemaJson = JSON.parse(nestedSchema, (key, value) => {
|
|
switch (key) {
|
|
case '$ref':
|
|
if (value.startsWith('#/definitions/')) {
|
|
return value.replace('#/definitions/', `#/definitions/${definitionKey}/definitions/`);
|
|
} else {
|
|
throw new Error(`Error while resolving $ref ${value} in ${nestedSchemaPath}.`);
|
|
}
|
|
case '$id':
|
|
case '$id':
|
|
case '$schema':
|
|
case 'id':
|
|
case 'required':
|
|
return undefined;
|
|
default:
|
|
return value;
|
|
}
|
|
});
|
|
|
|
nestedDefinitions[definitionKey] = nestedSchemaJson;
|
|
|
|
return `#/definitions/${definitionKey}`;
|
|
}
|
|
|
|
return key === ''
|
|
? {
|
|
...value,
|
|
definitions: {
|
|
...value.definitions,
|
|
...nestedDefinitions,
|
|
}
|
|
}
|
|
: value;
|
|
});
|
|
|
|
const buildWorkspaceDirectory = process.env['BUILD_WORKSPACE_DIRECTORY'] || '.';
|
|
outPath = resolve(buildWorkspaceDirectory, outPath);
|
|
|
|
mkdirSync(dirname(outPath), { recursive: true });
|
|
writeFileSync(outPath, JSON.stringify(schemaParsed, undefined, 2));
|
|
}
|
|
|
|
if (require.main === module) {
|
|
const argv = process.argv.slice(2);
|
|
if (argv.length !== 2) {
|
|
console.error('Must include 2 arguments.');
|
|
process.exit(1);
|
|
}
|
|
|
|
const [inPath, outPath] = argv;
|
|
|
|
try {
|
|
generate(inPath, outPath);
|
|
} catch (error) {
|
|
console.error('An error happened:');
|
|
console.error(err);
|
|
process.exit(127);
|
|
}
|
|
}
|
|
|
|
exports.generate = generate; |