Skip to content

Commit 2f633d7

Browse files
committed
build: replace own cli schema bundler with @apidevtools/json-schema-ref-parser
This package provides better handling for schema bundling. See: https://github.com/APIDevTools/json-schema-ref-parser https://apitools.dev/json-schema-ref-parser/docs/
1 parent 404383b commit 2f633d7

File tree

5 files changed

+145
-100
lines changed

5 files changed

+145
-100
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
"@angular/platform-server": "14.0.3",
8080
"@angular/router": "14.0.3",
8181
"@angular/service-worker": "14.0.3",
82+
"@apidevtools/json-schema-ref-parser": "~9.0.9",
8283
"@babel/core": "7.18.6",
8384
"@babel/generator": "7.18.7",
8485
"@babel/helper-annotate-as-pure": "7.18.6",

packages/angular/cli/lib/config/workspace-schema.json

+102-32
Original file line numberDiff line numberDiff line change
@@ -183,46 +183,46 @@
183183
"type": "object",
184184
"properties": {
185185
"@schematics/angular:application": {
186-
"$ref": "../../../../schematics/angular/application/schema.json"
186+
"$ref": "#/definitions/schematicsAngularApplicationSchema"
187187
},
188188
"@schematics/angular:class": {
189-
"$ref": "../../../../schematics/angular/class/schema.json"
189+
"$ref": "#/definitions/schematicsAngularClassSchema"
190190
},
191191
"@schematics/angular:component": {
192-
"$ref": "../../../../schematics/angular/component/schema.json"
192+
"$ref": "#/definitions/schematicsAngularComponentSchema"
193193
},
194194
"@schematics/angular:directive": {
195-
"$ref": "../../../../schematics/angular/directive/schema.json"
195+
"$ref": "#/definitions/schematicsAngularDirectiveSchema"
196196
},
197197
"@schematics/angular:enum": {
198-
"$ref": "../../../../schematics/angular/enum/schema.json"
198+
"$ref": "#/definitions/schematicsAngular"
199199
},
200200
"@schematics/angular:guard": {
201-
"$ref": "../../../../schematics/angular/guard/schema.json"
201+
"$ref": "#/definitions/schematicsAngularGuardSchema"
202202
},
203203
"@schematics/angular:interceptor": {
204-
"$ref": "../../../../schematics/angular/interceptor/schema.json"
204+
"$ref": "#/definitions/schematicsAngularInterceptorSchema"
205205
},
206206
"@schematics/angular:interface": {
207-
"$ref": "../../../../schematics/angular/interface/schema.json"
207+
"$ref": "#/definitions/schematicsAngularInterfaceSchema"
208208
},
209209
"@schematics/angular:library": {
210-
"$ref": "../../../../schematics/angular/library/schema.json"
210+
"$ref": "#/definitions/schematicsAngularLibrarySchema"
211211
},
212212
"@schematics/angular:pipe": {
213-
"$ref": "../../../../schematics/angular/pipe/schema.json"
213+
"$ref": "#/definitions/schematicsAngularPipeSchema"
214214
},
215215
"@schematics/angular:ng-new": {
216-
"$ref": "../../../../schematics/angular/ng-new/schema.json"
216+
"$ref": "#/definitions/schematicsAngularNgNewSchema"
217217
},
218218
"@schematics/angular:resolver": {
219-
"$ref": "../../../../schematics/angular/resolver/schema.json"
219+
"$ref": "#/definitions/schematicsAngularResolverSchema"
220220
},
221221
"@schematics/angular:service": {
222-
"$ref": "../../../../schematics/angular/service/schema.json"
222+
"$ref": "#/definitions/schematicsAngularServiceSchema"
223223
},
224224
"@schematics/angular:web-worker": {
225-
"$ref": "../../../../schematics/angular/web-worker/schema.json"
225+
"$ref": "#/definitions/schematicsAngularWebWorkerSchema"
226226
}
227227
},
228228
"additionalProperties": {
@@ -450,12 +450,12 @@
450450
"description": "A default named configuration to use when a target configuration is not provided."
451451
},
452452
"options": {
453-
"$ref": "../../../../angular_devkit/build_angular/src/builders/app-shell/schema.json"
453+
"$ref": "#/definitions/angularBuildersAppShellSchema"
454454
},
455455
"configurations": {
456456
"type": "object",
457457
"additionalProperties": {
458-
"$ref": "../../../../angular_devkit/build_angular/src/builders/app-shell/schema.json"
458+
"$ref": "#/definitions/angularBuildersAppShellSchema"
459459
}
460460
}
461461
}
@@ -472,12 +472,12 @@
472472
"description": "A default named configuration to use when a target configuration is not provided."
473473
},
474474
"options": {
475-
"$ref": "../../../../angular_devkit/build_angular/src/builders/browser/schema.json"
475+
"$ref": "#/definitions/angularBuildersBrowserSchema"
476476
},
477477
"configurations": {
478478
"type": "object",
479479
"additionalProperties": {
480-
"$ref": "../../../../angular_devkit/build_angular/src/builders/browser/schema.json"
480+
"$ref": "#/definitions/angularBuildersBrowserSchema"
481481
}
482482
}
483483
}
@@ -494,12 +494,12 @@
494494
"description": "A default named configuration to use when a target configuration is not provided."
495495
},
496496
"options": {
497-
"$ref": "../../../../angular_devkit/build_angular/src/builders/browser-esbuild/schema.json"
497+
"$ref": "#/definitions/angularBuildersBrowserEsBuildSchema"
498498
},
499499
"configurations": {
500500
"type": "object",
501501
"additionalProperties": {
502-
"$ref": "../../../../angular_devkit/build_angular/src/builders/browser-esbuild/schema.json"
502+
"$ref": "#/definitions/angularBuildersBrowserEsBuildSchema"
503503
}
504504
}
505505
}
@@ -516,12 +516,12 @@
516516
"description": "A default named configuration to use when a target configuration is not provided."
517517
},
518518
"options": {
519-
"$ref": "../../../../angular_devkit/build_angular/src/builders/dev-server/schema.json"
519+
"$ref": "#/definitions/angularBuildersDevServerSchema"
520520
},
521521
"configurations": {
522522
"type": "object",
523523
"additionalProperties": {
524-
"$ref": "../../../../angular_devkit/build_angular/src/builders/dev-server/schema.json"
524+
"$ref": "#/definitions/angularBuildersDevServerSchema"
525525
}
526526
}
527527
}
@@ -538,12 +538,12 @@
538538
"description": "A default named configuration to use when a target configuration is not provided."
539539
},
540540
"options": {
541-
"$ref": "../../../../angular_devkit/build_angular/src/builders/extract-i18n/schema.json"
541+
"$ref": "#/definitions/angularBuildersExtractI18nSchema"
542542
},
543543
"configurations": {
544544
"type": "object",
545545
"additionalProperties": {
546-
"$ref": "../../../../angular_devkit/build_angular/src/builders/extract-i18n/schema.json"
546+
"$ref": "#/definitions/angularBuildersExtractI18nSchema"
547547
}
548548
}
549549
}
@@ -560,12 +560,12 @@
560560
"description": "A default named configuration to use when a target configuration is not provided."
561561
},
562562
"options": {
563-
"$ref": "../../../../angular_devkit/build_angular/src/builders/karma/schema.json"
563+
"$ref": "#/definitions/angularBuildersKarmaSchema"
564564
},
565565
"configurations": {
566566
"type": "object",
567567
"additionalProperties": {
568-
"$ref": "../../../../angular_devkit/build_angular/src/builders/karma/schema.json"
568+
"$ref": "#/definitions/angularBuildersKarmaSchema"
569569
}
570570
}
571571
}
@@ -582,12 +582,12 @@
582582
"description": "A default named configuration to use when a target configuration is not provided."
583583
},
584584
"options": {
585-
"$ref": "../../../../angular_devkit/build_angular/src/builders/protractor/schema.json"
585+
"$ref": "#/definitions/angularBuildersProtractorSchema"
586586
},
587587
"configurations": {
588588
"type": "object",
589589
"additionalProperties": {
590-
"$ref": "../../../../angular_devkit/build_angular/src/builders/protractor/schema.json"
590+
"$ref": "#/definitions/angularBuildersProtractorSchema"
591591
}
592592
}
593593
}
@@ -604,12 +604,12 @@
604604
"description": "A default named configuration to use when a target configuration is not provided."
605605
},
606606
"options": {
607-
"$ref": "../../../../angular_devkit/build_angular/src/builders/server/schema.json"
607+
"$ref": "#/definitions/angularBuildersServerSchema"
608608
},
609609
"configurations": {
610610
"type": "object",
611611
"additionalProperties": {
612-
"$ref": "../../../../angular_devkit/build_angular/src/builders/server/schema.json"
612+
"$ref": "#/definitions/angularBuildersServerSchema"
613613
}
614614
}
615615
}
@@ -626,12 +626,12 @@
626626
"description": "A default named configuration to use when a target configuration is not provided."
627627
},
628628
"options": {
629-
"$ref": "../../../../angular_devkit/build_angular/src/builders/ng-packagr/schema.json"
629+
"$ref": "#/definitions/angularBuildersNgPackagrSchema"
630630
},
631631
"configurations": {
632632
"type": "object",
633633
"additionalProperties": {
634-
"$ref": "../../../../angular_devkit/build_angular/src/builders/ng-packagr/schema.json"
634+
"$ref": "#/definitions/angularBuildersNgPackagrSchema"
635635
}
636636
}
637637
}
@@ -657,6 +657,76 @@
657657
}
658658
},
659659
"required": ["version"]
660+
},
661+
662+
"schematicsAngularApplicationSchema": {
663+
"$ref": "../../../../schematics/angular/application/schema.json"
664+
},
665+
"schematicsAngularClassSchema": {
666+
"$ref": "../../../../schematics/angular/class/schema.json"
667+
},
668+
"schematicsAngularComponentSchema": {
669+
"$ref": "../../../../schematics/angular/component/schema.json"
670+
},
671+
"schematicsAngularDirectiveSchema": {
672+
"$ref": "../../../../schematics/angular/directive/schema.json"
673+
},
674+
"schematicsAngular": {
675+
"$ref": "../../../../schematics/angular/enum/schema.json"
676+
},
677+
"schematicsAngularGuardSchema": {
678+
"$ref": "../../../../schematics/angular/guard/schema.json"
679+
},
680+
"schematicsAngularInterceptorSchema": {
681+
"$ref": "../../../../schematics/angular/interceptor/schema.json"
682+
},
683+
"schematicsAngularInterfaceSchema": {
684+
"$ref": "../../../../schematics/angular/interface/schema.json"
685+
},
686+
"schematicsAngularLibrarySchema": {
687+
"$ref": "../../../../schematics/angular/library/schema.json"
688+
},
689+
"schematicsAngularPipeSchema": {
690+
"$ref": "../../../../schematics/angular/pipe/schema.json"
691+
},
692+
"schematicsAngularNgNewSchema": {
693+
"$ref": "../../../../schematics/angular/ng-new/schema.json"
694+
},
695+
"schematicsAngularResolverSchema": {
696+
"$ref": "../../../../schematics/angular/resolver/schema.json"
697+
},
698+
"schematicsAngularServiceSchema": {
699+
"$ref": "../../../../schematics/angular/service/schema.json"
700+
},
701+
"schematicsAngularWebWorkerSchema": {
702+
"$ref": "../../../../schematics/angular/web-worker/schema.json"
703+
},
704+
"angularBuildersAppShellSchema": {
705+
"$ref": "../../../../schematics/angular/app-shell/schema.json"
706+
},
707+
"angularBuildersBrowserSchema": {
708+
"$ref": "../../../../angular_devkit/build_angular/src/builders/browser/schema.json"
709+
},
710+
"angularBuildersBrowserEsBuildSchema": {
711+
"$ref": "../../../../angular_devkit/build_angular/src/builders/browser-esbuild/schema.json"
712+
},
713+
"angularBuildersDevServerSchema": {
714+
"$ref": "../../../../angular_devkit/build_angular/src/builders/dev-server/schema.json"
715+
},
716+
"angularBuildersExtractI18nSchema": {
717+
"$ref": "../../../../angular_devkit/build_angular/src/builders/extract-i18n/schema.json"
718+
},
719+
"angularBuildersKarmaSchema": {
720+
"$ref": "../../../../angular_devkit/build_angular/src/builders/karma/schema.json"
721+
},
722+
"angularBuildersProtractorSchema": {
723+
"$ref": "../../../../angular_devkit/build_angular/src/builders/protractor/schema.json"
724+
},
725+
"angularBuildersServerSchema": {
726+
"$ref": "../../../../angular_devkit/build_angular/src/builders/server/schema.json"
727+
},
728+
"angularBuildersNgPackagrSchema": {
729+
"$ref": "../../../../angular_devkit/build_angular/src/builders/ng-packagr/schema.json"
660730
}
661731
}
662732
}

scripts/build-schema.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ export default async function (argv: {}, logger: logging.Logger) {
5555
const cliJsonSchema = require('../tools/ng_cli_schema_generator');
5656
const inputPath = 'packages/angular/cli/lib/config/workspace-schema.json';
5757
const outputPath = path.join(dist, inputPath.replace('workspace-schema.json', 'schema.json'));
58-
cliJsonSchema.generate(inputPath, outputPath);
58+
await cliJsonSchema.generate(inputPath, outputPath);
5959
}

tools/ng_cli_schema_generator.js

+20-64
Original file line numberDiff line numberDiff line change
@@ -8,86 +8,42 @@
88

99
const { readFileSync, writeFileSync, mkdirSync } = require('fs');
1010
const { resolve, dirname } = require('path');
11+
const schemaRefParser = require('@apidevtools/json-schema-ref-parser');
1112

1213
/**
1314
* Generator the Angular CLI workspace schema file.
1415
*/
15-
function generate(inPath, outPath) {
16+
17+
async function generate(inPath, outPath) {
1618
// While on paper we could use quicktype for this.
1719
// Quicktype doesn't handle `patternProperties` and `oneOf` that well.
18-
1920
const jsonSchema = readFileSync(inPath, 'utf8');
20-
const nestedDefinitions = {};
21-
const schemaParsed = JSON.parse(jsonSchema, (key, value) => {
22-
if (key === '$ref' && typeof value === 'string' && !value.startsWith('#')) {
23-
// Resolve $ref and camelize key
24-
const definitionKey = value
25-
.replace(/(\.json|src)/g, '')
26-
.split(/\\|\/|_|-|\./)
27-
.filter((p) => !!p)
28-
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
29-
.join('');
30-
31-
const nestedSchemaPath = resolve(dirname(inPath), value);
32-
const nestedSchema = readFileSync(nestedSchemaPath, 'utf8');
33-
const nestedSchemaJson = JSON.parse(nestedSchema, (key, value) => {
34-
switch (key) {
35-
case '$ref':
36-
if (value.startsWith('#/definitions/')) {
37-
return value.replace('#/definitions/', `#/definitions/${definitionKey}/definitions/`);
38-
} else {
39-
throw new Error(`Error while resolving $ref ${value} in ${nestedSchemaPath}.`);
40-
}
41-
case '$id':
42-
case '$id':
43-
case '$schema':
44-
case 'id':
45-
case 'required':
46-
return undefined;
47-
default:
48-
return value;
49-
}
50-
});
51-
52-
nestedDefinitions[definitionKey] = nestedSchemaJson;
53-
54-
return `#/definitions/${definitionKey}`;
55-
}
56-
57-
return key === ''
58-
? {
59-
...value,
60-
definitions: {
61-
...value.definitions,
62-
...nestedDefinitions,
63-
},
64-
}
65-
: value;
66-
});
67-
6821
const buildWorkspaceDirectory = process.env['BUILD_WORKSPACE_DIRECTORY'] || '.';
6922
outPath = resolve(buildWorkspaceDirectory, outPath);
23+
const schema = await schemaRefParser.bundle(inPath, JSON.parse(jsonSchema));
7024

7125
mkdirSync(dirname(outPath), { recursive: true });
72-
writeFileSync(outPath, JSON.stringify(schemaParsed, undefined, 2));
26+
writeFileSync(outPath, JSON.stringify(schema, undefined, 2));
7327
}
7428

7529
if (require.main === module) {
76-
const argv = process.argv.slice(2);
77-
if (argv.length !== 2) {
78-
console.error('Must include 2 arguments.');
79-
process.exit(1);
80-
}
30+
(async () => {
31+
const argv = process.argv.slice(2);
32+
if (argv.length !== 2) {
33+
console.error('Must include 2 arguments.');
34+
process.exit(1);
35+
}
8136

82-
const [inPath, outPath] = argv;
37+
const [inPath, outPath] = argv;
8338

84-
try {
85-
generate(inPath, outPath);
86-
} catch (error) {
87-
console.error('An error happened:');
88-
console.error(error);
89-
process.exit(127);
90-
}
39+
try {
40+
await generate(inPath, outPath);
41+
} catch (error) {
42+
console.error('An error happened:');
43+
console.error(error);
44+
process.exit(127);
45+
}
46+
})();
9147
}
9248

9349
exports.generate = generate;

0 commit comments

Comments
 (0)