Skip to content

Commit 2651ff9

Browse files
committed
fix(core): fix coerceTypesInOptions for schemas with oneOf
1 parent 96f25ce commit 2651ff9

File tree

3 files changed

+64
-22
lines changed

3 files changed

+64
-22
lines changed

packages/tao/src/commands/run.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ function parseRunOpts(
3838
minimist(args, {
3939
boolean: ['help', 'prod'],
4040
string: ['configuration', 'project'],
41+
alias: {
42+
c: 'configuration',
43+
},
4144
})
4245
);
4346
const help = runOptions.help as boolean;
@@ -73,6 +76,7 @@ function parseRunOpts(
7376
const res = { project, target, configuration, help, runOptions };
7477
delete runOptions['help'];
7578
delete runOptions['_'];
79+
delete runOptions['c'];
7680
delete runOptions['configuration'];
7781
delete runOptions['prod'];
7882
delete runOptions['project'];

packages/tao/src/shared/params.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,33 @@ describe('params', () => {
6161
a: ['one', 'two'],
6262
b: 'three,four',
6363
});
64+
65+
const opts2 = coerceTypesInOptions({ a: '1,2', b: 'true,false' }, {
66+
properties: {
67+
a: { type: 'array', items: { type: 'number' } },
68+
b: { type: 'array', items: { type: 'boolean' } },
69+
},
70+
} as Schema);
71+
72+
expect(opts2).toEqual({
73+
a: [1, 2],
74+
b: [true, false],
75+
});
76+
});
77+
78+
it('should handle oneOf', () => {
79+
const opts = coerceTypesInOptions(
80+
{ a: 'false' } as any,
81+
{
82+
properties: {
83+
a: { oneOf: [{ type: 'object' }, { type: 'boolean' }] },
84+
},
85+
} as Schema
86+
);
87+
88+
expect(opts).toEqual({
89+
a: false,
90+
});
6491
});
6592
});
6693

packages/tao/src/shared/params.ts

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,21 @@ import { TargetConfiguration, WorkspaceConfiguration } from './workspace';
33
import * as inquirer from 'inquirer';
44
import { logger } from './logger';
55

6+
type PropertyDescription = {
7+
type?: string;
8+
properties?: any;
9+
oneOf?: any;
10+
items?: any;
11+
alias?: string;
12+
description?: string;
13+
default?: string | number | boolean | string[];
14+
$ref?: string;
15+
$default?: { $source: 'argv'; index: number };
16+
'x-prompt'?: string | { message: string; type: string; items: any[] };
17+
};
18+
619
type Properties = {
7-
[p: string]: {
8-
type?: string;
9-
properties?: any;
10-
oneOf?: any;
11-
items?: any;
12-
alias?: string;
13-
description?: string;
14-
default?: string | number | boolean | string[];
15-
$ref?: string;
16-
$default?: { $source: 'argv'; index: number };
17-
'x-prompt'?: string | { message: string; type: string; items: any[] };
18-
};
20+
[p: string]: PropertyDescription;
1921
};
2022
export type Schema = {
2123
properties: Properties;
@@ -76,21 +78,30 @@ export function convertToCamelCase(parsed: ParsedArgs): Options {
7678
*/
7779
export function coerceTypesInOptions(opts: Options, schema: Schema): Options {
7880
Object.keys(opts).forEach((k) => {
79-
opts[k] = coerceType(
80-
schema.properties[k] ? schema.properties[k].type : 'unknown',
81-
opts[k]
82-
);
81+
opts[k] = coerceType(schema.properties[k], opts[k]);
8382
});
8483
return opts;
8584
}
8685

87-
function coerceType(type: string, value: any) {
88-
if (type == 'boolean') {
86+
function coerceType(prop: PropertyDescription | undefined, value: any) {
87+
if (!prop) return value;
88+
if (prop.oneOf) {
89+
for (let i = 0; i < prop.oneOf.length; ++i) {
90+
const coerced = coerceType(prop.oneOf[i], value);
91+
if (coerced !== value) {
92+
return coerced;
93+
}
94+
}
95+
return value;
96+
} else if (prop.type == 'boolean') {
8997
return value === true || value == 'true';
90-
} else if (type == 'number') {
98+
} else if (prop.type == 'number') {
9199
return Number(value);
92-
} else if (type == 'array') {
93-
return value.toString().split(',');
100+
} else if (prop.type == 'array') {
101+
return value
102+
.toString()
103+
.split(',')
104+
.map((v) => coerceType(prop.items, v));
94105
} else {
95106
return value;
96107
}
@@ -297,7 +308,7 @@ export function convertPositionParamsIntoNamedParams(
297308
v.$default !== undefined &&
298309
argv[v.$default.index]
299310
) {
300-
opts[k] = coerceType(v.type, argv[v.$default.index]);
311+
opts[k] = coerceType(v, argv[v.$default.index]);
301312
}
302313
});
303314
delete opts['_'];

0 commit comments

Comments
 (0)