mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-17 02:54:21 +08:00
fix(@angular/cli): error out when command json is invalid
This commit is contained in:
parent
7ca3bb5263
commit
eef66f0f65
@ -36,7 +36,6 @@ export class GenerateCommand extends SchematicCommand<GenerateCommandSchema> {
|
|||||||
schematic.description.path,
|
schematic.description.path,
|
||||||
this._workflow.registry,
|
this._workflow.registry,
|
||||||
schematic.description.schemaJson,
|
schematic.description.schemaJson,
|
||||||
this.logger,
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -92,7 +92,7 @@ export async function runCommand(
|
|||||||
}
|
}
|
||||||
|
|
||||||
commandMap[name] =
|
commandMap[name] =
|
||||||
await parseJsonSchemaToCommandDescription(name, schemaPath, registry, schema, logger);
|
await parseJsonSchemaToCommandDescription(name, schemaPath, registry, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
let commandName: string | undefined = undefined;
|
let commandName: string | undefined = undefined;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import { json, logging } from '@angular-devkit/core';
|
import { BaseException, json } from '@angular-devkit/core';
|
||||||
import { ExportStringRef } from '@angular-devkit/schematics/tools';
|
import { ExportStringRef } from '@angular-devkit/schematics/tools';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { dirname, resolve } from 'path';
|
import { dirname, resolve } from 'path';
|
||||||
@ -19,6 +19,13 @@ import {
|
|||||||
Value,
|
Value,
|
||||||
} from '../models/interface';
|
} from '../models/interface';
|
||||||
|
|
||||||
|
|
||||||
|
export class CommandJsonPathException extends BaseException {
|
||||||
|
constructor(public readonly path: string, public readonly name: string) {
|
||||||
|
super(`File ${path} was not found while constructing the subcommand ${name}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _getEnumFromValue<E, T extends E[keyof E]>(
|
function _getEnumFromValue<E, T extends E[keyof E]>(
|
||||||
value: json.JsonValue,
|
value: json.JsonValue,
|
||||||
enumeration: E,
|
enumeration: E,
|
||||||
@ -40,7 +47,6 @@ export async function parseJsonSchemaToSubCommandDescription(
|
|||||||
jsonPath: string,
|
jsonPath: string,
|
||||||
registry: json.schema.SchemaRegistry,
|
registry: json.schema.SchemaRegistry,
|
||||||
schema: json.JsonObject,
|
schema: json.JsonObject,
|
||||||
logger: logging.Logger,
|
|
||||||
): Promise<SubCommandDescription> {
|
): Promise<SubCommandDescription> {
|
||||||
const options = await parseJsonSchemaToOptions(registry, schema);
|
const options = await parseJsonSchemaToOptions(registry, schema);
|
||||||
|
|
||||||
@ -69,7 +75,7 @@ export async function parseJsonSchemaToSubCommandDescription(
|
|||||||
try {
|
try {
|
||||||
longDescription = readFileSync(ldPath, 'utf-8');
|
longDescription = readFileSync(ldPath, 'utf-8');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.warn(`File ${ldPath} was not found while constructing the subcommand ${name}.`);
|
throw new CommandJsonPathException(ldPath, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let usageNotes = '';
|
let usageNotes = '';
|
||||||
@ -78,7 +84,7 @@ export async function parseJsonSchemaToSubCommandDescription(
|
|||||||
try {
|
try {
|
||||||
usageNotes = readFileSync(unPath, 'utf-8');
|
usageNotes = readFileSync(unPath, 'utf-8');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.warn(`File ${unPath} was not found while constructing the subcommand ${name}.`);
|
throw new CommandJsonPathException(unPath, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,10 +105,9 @@ export async function parseJsonSchemaToCommandDescription(
|
|||||||
jsonPath: string,
|
jsonPath: string,
|
||||||
registry: json.schema.SchemaRegistry,
|
registry: json.schema.SchemaRegistry,
|
||||||
schema: json.JsonObject,
|
schema: json.JsonObject,
|
||||||
logger: logging.Logger,
|
|
||||||
): Promise<CommandDescription> {
|
): Promise<CommandDescription> {
|
||||||
const subcommand =
|
const subcommand =
|
||||||
await parseJsonSchemaToSubCommandDescription(name, jsonPath, registry, schema, logger);
|
await parseJsonSchemaToSubCommandDescription(name, jsonPath, registry, schema);
|
||||||
|
|
||||||
// Before doing any work, let's validate the implementation.
|
// Before doing any work, let's validate the implementation.
|
||||||
if (typeof schema.$impl != 'string') {
|
if (typeof schema.$impl != 'string') {
|
||||||
|
76
packages/angular/cli/utilities/json-schema_spec.ts
Normal file
76
packages/angular/cli/utilities/json-schema_spec.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
import { schema } from '@angular-devkit/core';
|
||||||
|
import { readFileSync } from 'fs';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { CommandJsonPathException, parseJsonSchemaToCommandDescription } from './json-schema';
|
||||||
|
|
||||||
|
describe('parseJsonSchemaToCommandDescription', () => {
|
||||||
|
let registry: schema.CoreSchemaRegistry;
|
||||||
|
const baseSchemaJson = {
|
||||||
|
'$schema': 'http://json-schema.org/schema',
|
||||||
|
'$id': 'ng-cli://commands/version.json',
|
||||||
|
'description': 'Outputs Angular CLI version.',
|
||||||
|
'$longDescription': 'not a file ref',
|
||||||
|
|
||||||
|
'$aliases': ['v'],
|
||||||
|
'$scope': 'all',
|
||||||
|
'$impl': './version-impl#VersionCommand',
|
||||||
|
|
||||||
|
'type': 'object',
|
||||||
|
'allOf': [
|
||||||
|
{ '$ref': './definitions.json#/definitions/base' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
registry = new schema.CoreSchemaRegistry([]);
|
||||||
|
registry.registerUriHandler((uri: string) => {
|
||||||
|
if (uri.startsWith('ng-cli://')) {
|
||||||
|
const content = readFileSync(
|
||||||
|
join(__dirname, '..', uri.substr('ng-cli://'.length)), 'utf-8');
|
||||||
|
|
||||||
|
return of(JSON.parse(content));
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should throw on invalid $longDescription path`, async () => {
|
||||||
|
const name = 'version';
|
||||||
|
const schemaPath = join(__dirname, './bad-sample.json');
|
||||||
|
const schemaJson = { ...baseSchemaJson, $longDescription: 'not a file ref' };
|
||||||
|
try {
|
||||||
|
await parseJsonSchemaToCommandDescription(name, schemaPath, registry, schemaJson);
|
||||||
|
} catch (error) {
|
||||||
|
const refPath = join(__dirname, schemaJson.$longDescription);
|
||||||
|
expect(error).toEqual(new CommandJsonPathException(refPath, name));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
expect(true).toBe(false, 'function should have thrown');
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should throw on invalid $usageNotes path`, async () => {
|
||||||
|
const name = 'version';
|
||||||
|
const schemaPath = join(__dirname, './bad-sample.json');
|
||||||
|
const schemaJson = { ...baseSchemaJson, $usageNotes: 'not a file ref' };
|
||||||
|
try {
|
||||||
|
await parseJsonSchemaToCommandDescription(name, schemaPath, registry, schemaJson);
|
||||||
|
} catch (error) {
|
||||||
|
const refPath = join(__dirname, schemaJson.$usageNotes);
|
||||||
|
expect(error).toEqual(new CommandJsonPathException(refPath, name));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
expect(true).toBe(false, 'function should have thrown');
|
||||||
|
});
|
||||||
|
});
|
@ -184,9 +184,9 @@ export default async function(opts: SnapshotsOptions, logger: logging.Logger) {
|
|||||||
const options = { cwd: newProjectRoot };
|
const options = { cwd: newProjectRoot };
|
||||||
const childLogger = logger.createChild(commandName);
|
const childLogger = logger.createChild(commandName);
|
||||||
const stdout = _exec(ngPath, [commandName, '--help=json'], options, childLogger);
|
const stdout = _exec(ngPath, [commandName, '--help=json'], options, childLogger);
|
||||||
if (stdout.trim()) {
|
// Make sure the output is JSON before printing it, and format it as well.
|
||||||
fs.writeFileSync(path.join(helpOutputRoot, commandName + '.json'), stdout);
|
const jsonOutput = JSON.stringify(JSON.parse(stdout.trim()), undefined, 2);
|
||||||
}
|
fs.writeFileSync(path.join(helpOutputRoot, commandName + '.json'), jsonOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!githubToken) {
|
if (!githubToken) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user