in powershell/plugins/create-commands-v2.ts [561:697]
async addVariants(parameters: Array<Parameter> | undefined, operation: Operation, variant: CommandVariant, vname: string, state: State, preOperations?: Array<Operation>, commandType?: CommandType) {
// now synthesize parameter set variants multiplexed by the variants.
const [constants, requiredParameters] = values(parameters).bifurcate(parameter => parameter.language.default.constantValue || parameter.language.default.fromHost ? true : false);
const constantParameters = constants.map(each => `'${each.language.default.constantValue}'`);
// the body parameter
// xichen: How to handle if has multiple requests?
const body = operation.requests?.[0].parameters?.find((p) => !p.origin || p.origin.indexOf('modelerfour:synthesized') < 0) || null;
// skip-for-time-being, looks x-ms-requestBody-name is not supported any more
//const bodyParameterName = (operation.requestBody && operation.requestBody.extensions) ? operation.requestBody.extensions['x-ms-requestBody-name'] || 'bodyParameter' : '';
const bodyParameterName = body ? body.language.default.name : '';
// all the properties in the body parameter
const bodyProperties = (body && body.schema && isObjectSchema(body.schema)) ? values(getAllProperties(body.schema)).where(property => !property.language.default.readOnly).toArray() : [];
// smash body property names together
const bodyPropertyNames = bodyProperties.joinWith(each => each.language.default.name);
// for each polymorphic body, we should do a separate variant that takes the polymorphic body type instead of the base type
// skip-for-time-being, this is for polymorphism
//const polymorphicBodies = (body && body.schema && body.schema.details.default.polymorphicChildren && length(body.schema.details.default.polymorphicChildren)) ? (<Array<Schema>>body.schema.details.default.polymorphicChildren).joinWith(child => child.details.default.name) : '';
// wait! "update" should be "set" if it's a PUT
if (variant.verb === 'Update' && operation.requests && operation.requests[0].protocol?.http?.method === HttpMethod.Put) {
variant.verb = 'Set';
}
//for operations which has pre operations (only support GET+PUT for now), change it's action to update
if (preOperations && preOperations.length > 0) {
variant.action = variant.verb = 'Update';
}
// create variant
// skip-for-time-being, since operationId looks not included in m4.
//state.message({ Channel: Channel.Debug, Text: `${variant.verb}-${variant.subject} // ${operation.operationId} => ${JSON.stringify(variant)} taking ${requiredParameters.joinWith(each => each.name)}; ${constantParameters} ; ${bodyPropertyNames} ${polymorphicBodies ? `; Polymorphic bodies: ${polymorphicBodies} ` : ''}` });
await this.addVariant(pascalCase([variant.action, vname]), body, bodyParameterName, [...constants, ...requiredParameters], operation, variant, state, preOperations, commandType);
if (await state.getValue('disable-via-identity', false)) {
return;
}
// eslint-disable-next-line prefer-const
let [pathParams, otherParams] = values(requiredParameters).bifurcate(each => each?.protocol?.http?.in === ParameterLocation.Path);
//exclude subscriptionId and resourceGroupName from path parameters
pathParams = pathParams.filter(pathParam => !this.reservedPathParam.has(pathParam.language.default.name));
//if parent pipline input is disabled, only generate identity for current resource itself
if (!await state.getValue('enable-parent-pipeline-input', this.isAzure)) {
if (length(pathParams) > 0 && variant.action.toLowerCase() != 'list') {
await this.addVariant(pascalCase([variant.action, vname, 'via-identity']), body, bodyParameterName, [...constants, ...otherParams], operation, variant, state, preOperations, commandType);
}
return;
}
const disableGetEnableList = await this.state.getValue('enable-parent-pipeline-input-for-list', false);
/*
for resource /A1/A2/.../An-1/An, generate variants that take
ViaIdentity: An as identity
ViaIdentity{An-1}: An-1 as identity + An Name
...
ViaIdentity{A1}: A1 as identity + [A2 + A3 + ... + An-1 + An] Names
*/
for (let i = pathParams.length - 1; i >= 0; i--) {
if ((!disableGetEnableList && variant.action.toLowerCase() === 'list') || (disableGetEnableList && i === pathParams.length - 1 && variant.action.toLowerCase() === 'get')) {
continue;
}
let resourceName = getResourceNameFromPath(operation.requests?.[0].protocol.http?.path, pathParams[i].language.default.name, true);
//cannot get resource name from path, give up generate ViaIdentity variant
if (!resourceName) {
break;
}
//variant for current resource is simply named ViaIdentity otherwise ViaIdentity${resourceName}
if (i === pathParams.length - 1 && variant.action.toLowerCase() !== 'list') {
resourceName = '';
}
await this.addVariant(pascalCase([variant.action, vname, `via-identity${resourceName}`]), body, bodyParameterName, [...constants, ...otherParams, ...pathParams.slice(i + 1)], operation, variant, state, preOperations, commandType);
}
if (this.supportJsonInput && hasValidBodyParameters(operation) &&
commandType != CommandType.GetPut && commandType != CommandType.ManagedIdentityUpdate) {
const createStringParameter = (name: string, description: string, serializedName: string): IParameter => {
const schema = new SchemaModel(name, description, SchemaType.String);
const language = {
default: {
name: name,
description: description,
serializedName: serializedName,
},
};
schema.language = language;
const httpParameter = {
implementation: 'Method',
language: language,
schema: schema,
required: true,
};
const parameter = new IParameter(name, schema, {
description: description,
required: true,
details: {
default: {
description: description,
name: name,
isBodyParameter: false,
httpParameter: httpParameter,
},
},
schema: schema,
allowEmptyValue: false,
deprecated: false,
});
(<any>parameter).httpParameter = httpParameter;
return parameter;
};
const jsonVariant = pascalCase([variant.action, vname]);
const parameter = new IParameter(`${bodyParameterName}Body`, body!.schema, {
details: {
default: {
description: body!.schema.language.default.description,
name: pascalCase(`${bodyParameterName}Body`),
isBodyParameter: true,
}
}
});
const opJsonString = await this.addVariant(`${jsonVariant}ViaJsonString`, null, '', [...constants, ...requiredParameters], operation, variant, state, preOperations, commandType);
opJsonString.details.default.dropBodyParameter = true;
opJsonString.parameters = opJsonString.parameters.filter(each => each.details.default.isBodyParameter !== true);
opJsonString.parameters.push(createStringParameter('JsonString', `Json string supplied to the ${jsonVariant} operation`, 'jsonString'));
opJsonString.parameters.push(parameter);
opJsonString.details.default.dropBodyParameter = true;
const opJsonFilePath = await this.addVariant(`${jsonVariant}ViaJsonFilePath`, null, '', [...constants, ...requiredParameters], operation, variant, state, preOperations, commandType);
opJsonFilePath.details.default.dropBodyParameter = true;
opJsonFilePath.parameters = opJsonFilePath.parameters.filter(each => each.details.default.isBodyParameter !== true);
opJsonFilePath.parameters.push(createStringParameter('JsonFilePath', `Path of Json file supplied to the ${jsonVariant} operation`, 'jsonFilePath'));
opJsonFilePath.parameters.push(parameter);
opJsonFilePath.details.default.dropBodyParameter = true;
}
}