@microsoft.azure/autorest.incubator
Version:
AutoRest incubator project
430 lines • 21.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const command_operation_1 = require("../common/code-model/command-operation");
const components_1 = require("../common/code-model/components");
const schema_1 = require("../common/code-model/schema");
const dictionary_1 = require("../common/dictionary");
const pluralization_1 = require("../common/english-pluralization-service/pluralization");
const process_code_model_1 = require("../common/process-code-model");
const text_manipulation_1 = require("../common/text-manipulation");
const autorest_extension_base_1 = require("@microsoft.azure/autorest-extension-base");
const tasks_1 = require("@microsoft.azure/tasks");
async function process(service) {
const x = await service.ListInputs('');
const y = await service.ListInputs();
const z = await service.GetValue('configurationFiles');
try {
const txt = await service.GetConfigurationFile('readme.powershell.md');
// spit a configuration file back.
// service.UpdateConfigurationFile('readme.powershell.md', `${txt}\n\n and more.`);
}
catch (E) {
// console.error(E);
}
return process_code_model_1.processCodeModel(commandCreator, service);
}
exports.process = process;
async function commonParameters(service) {
const isAzure = await service.GetValue('azure') || await service.GetValue('azure-arm') || false;
return isAzure ? [
// 'resourceGroupName',
'subscriptionId'
] : [];
}
async function commandCreator(model, service) {
// check to see if there are already operations in the configuration that we should load
// and check to see if we should infer new operations
// perform the detection
model = await detect(model, service);
return model;
}
async function addVariant(vname, body, bodyParameterName, parameters, operation, variant, model, service) {
// const body = operation.requestBody && values(operation.requestBody.content).linq.first();
// const bodyParameterName = operation.requestBody ? operation.requestBody.extensions["x-ms-requestBody-name"] || "bodyParameter" : "";
const op = await addCommandOperation(vname, parameters, operation, variant, model, service);
// if this has a body with it, let's add that parameter
if (body && body.schema) {
op.details.powershell.hasBody = true;
op.parameters.push(new components_1.IParameter(bodyParameterName, body.schema, {
details: {
powershell: {
description: body.schema.details.default.description,
name: text_manipulation_1.pascalCase(text_manipulation_1.fixLeadingNumber(text_manipulation_1.deconstruct(bodyParameterName))),
isBodyParameter: true,
}
}
}));
}
//
}
async function addCommandOperation(vname, parameters, operation, variant, model, service) {
return model.commands.operations[`${dictionary_1.length(model.commands.operations)}`] = new command_operation_1.CommandOperation(operation.operationId, Object.assign({ asjob: operation.details.default.asjob ? true : false }, variant, { details: Object.assign({}, operation.details, { powershell: Object.assign({}, operation.details.csharp, { name: vname }) }), operationId: operation.operationId, parameters: parameters.map(each => {
each.details.powershell = Object.assign({}, each.details.csharp, { name: text_manipulation_1.pascalCase(text_manipulation_1.fixLeadingNumber(text_manipulation_1.deconstruct(each.details.csharp.name))) });
return each;
}), callGraph: [operation] }));
}
async function addVariants(parameters, operation, variant, model, service) {
// now synthesize parameter set variants multiplexed by the variants.
const [constants, params] = dictionary_1.values(parameters).linq.bifurcate(parameter => parameter.details.default.constantValue || parameter.details.default.fromHost ? true : false);
const [requiredParameters, optionalParameters] = dictionary_1.values(params).linq.bifurcate(parameter => parameter.required);
const constantParameters = constants.map(each => `'${each.details.default.constantValue}'`);
const combos = combinations(optionalParameters);
// the body parameter
const body = operation.requestBody;
const bodyParameterName = operation.requestBody ? operation.requestBody.extensions['x-ms-requestBody-name'] || 'bodyParameter' : '';
// all the properties in the body parameter
const bodyProperties = (body && body.schema) ? dictionary_1.values(schema_1.getAllProperties(body.schema)).linq.where(property => !property.schema.readOnly).linq.toArray() : [];
// console.error(`Number of Body Properties ${properties.length}`);
// smash body property names together
const bodyPropertyNames = bodyProperties.joinWith(each => each.details.csharp.name);
// for each polymorphic body, we should do a separate variant that takes the polymorphic body type instead of the base type
const polymorphicBodies = (body && body.schema && body.schema.details.csharp.polymorphicChildren && body.schema.details.csharp.polymorphicChildren.length) ? body.schema.details.csharp.polymorphicChildren.joinWith(child => child.details.csharp.name) : '';
// the variant name
const vname = text_manipulation_1.pascalCase(text_manipulation_1.deconstruct([variant.variant, ...requiredParameters.map(each => each.name), bodyPropertyNames /*, operation.operationId*/]));
// given the body property type, expand out body properties into parameters
// no optionals:
service.Message({ Channel: autorest_extension_base_1.Channel.Verbose, Text: `${variant.verb}-${variant.noun} // ${operation.operationId} => ${JSON.stringify(variant)} taking ${requiredParameters.joinWith(each => each.name)}; ${constantParameters} ; ${bodyPropertyNames} ${polymorphicBodies ? '; Polymorphic bodies: ${polymorphicBodies} ' : ''}` });
await addVariant(vname, body, bodyParameterName, [...constants, ...requiredParameters], operation, variant, model, service);
// handle optional parameter variants
for (const combo of combos) {
const vname = text_manipulation_1.pascalCase(text_manipulation_1.deconstruct([variant.variant, ...requiredParameters.map(each => each.name), ...combo.map(each => each.name), bodyPropertyNames /*, operation.operationId*/]));
service.Message({ Channel: autorest_extension_base_1.Channel.Verbose, Text: `${variant.verb}-${variant.noun} // ${operation.operationId} => ${JSON.stringify(variant)} taking ${requiredParameters.joinWith(each => each.name)}; ${constantParameters} ; ${combo.joinWith(each => each.name)} ; ${bodyPropertyNames} ${polymorphicBodies ? '; Polymorphic bodies: ${polymorphicBodies} ' : ''}` });
await addVariant(vname, body, bodyParameterName, [...constants, ...requiredParameters, ...combo], operation, variant, model, service);
}
}
async function detect(model, service) {
service.Message({ Channel: autorest_extension_base_1.Channel.Debug, Text: 'detecting high level commands...' });
// let count = 0;
// parameter names that are candidates to be changed to pull the value from the common module
const commonCandidates = await commonParameters(service);
for (const operation of dictionary_1.values(model.http.operations)) {
for (const variant of inferCommandNames(operation.operationId)) {
// no common parameters (standard variations)
await addVariants(operation.parameters, operation, variant, model, service);
// now see if we have parameters that can be made common
const possibleCommon = dictionary_1.values(operation.parameters).linq.where(parameter => commonCandidates.includes(parameter.name)).linq.toArray();
if (possibleCommon.length > 0) {
// yes! make some combos that include the common parameters
const combos = combinations(possibleCommon);
for (const combo of combos) {
// now, take the operation parameters, and find the ones where that are in our set of combo,
const some = operation.parameters.map(param => {
if (combo.includes(param)) {
const newParam = Object.assign({}, param, { details: Object.assign({}, param.details, { default: Object.assign({}, param.details.default, { originalParam: param, fromHost: true }) }) });
return newParam;
}
return param;
});
// and shallow copy the parameter, into a new one, and overw
await addVariants(some, operation, variant, model, service);
}
}
// make some variants where subscriptionId and resourceGroupName are pulled from common module
}
}
return model;
}
function fn(active, remaining, result) {
if (active.length || remaining.length) {
if (remaining.length) {
fn([...active, remaining[0]], remaining.slice(1), result);
fn(active, remaining.slice(1), result);
}
else {
result.push(active);
}
}
return result;
}
function combinations(elements) {
return fn([], elements, []);
}
const pluralizationService = new tasks_1.Lazy(() => {
const result = new pluralization_1.EnglishPluralizationService();
result.AddWord('Database', 'Databases');
result.AddWord('database', 'databases');
return result;
});
function inferCommandNames(operationId) {
const pluralization = pluralizationService.Value;
let [group, method] = operationId.split('_', 2);
if (!method) {
// no group given.
method = group;
group = 'service';
// todo: with no group, figure out a strategy for verb/nouning the method..
}
group = pluralization.Singularize(group);
const operation = text_manipulation_1.deconstruct(method);
if (operation.length > 1) {
// options supported
// OPERATION or OPERATION2 => OPERATION-GROUP, OPERATION2-GROUP
// OPERATION by FILTER => OPERATION-GROUP_FILTER
// OPERATION with FILTER => OPERATION-GROUP_FILTER
switch (operation[1].toLowerCase()) {
case 'or':
// create two operations -- OPERATION and OPERATION2
// there should be only three things in the collection -- otherwise, we need a better alg.
if (operation.length !== 3) {
throw new Error(`Unable to perform detection form operation '${group}'/'${method}' -- too many values in operation : '${JSON.stringify(operation)}'`);
}
return [getVariant(operation[0], group, operation.slice(3)), getVariant(operation[2], group, operation.slice(3))];
case 'by':
case 'with':
// create one operation -- OPERATION-GROUP_filter
return [getVariant(operation[0], group, operation.slice(2))];
}
// OPERATION[SUFFIX] => OPERATION-GROUP[SUFFIX]
return [getVariant(operation[0], [group, ...operation.slice(1)], operation.slice(1))];
// would generate simpler name, but I fear for collisions on things like Registries_ListCredentials => get-credentials or Registries_RegenerateCredential => new-credential
// return [getVariant(operation[0], `${pascalCase(operation.slice(1))}`, operation.slice(1))];
}
else {
// for now, the rest should look like:
// OPERATION => OPERATION-GROUP
return [getVariant(operation[0], group, [])];
}
}
function getVariant(operation, group, suffix) {
const pluralization = pluralizationService.Value;
group = !Array.isArray(group) ? [group] : group;
const v = getVerb(operation);
if (v === 'Invoke') {
group = [operation, ...group];
}
group = group.map(each => pluralization.Singularize(each));
const noun = text_manipulation_1.pascalCase(group);
return {
category: getCategory(v),
noun,
variant: text_manipulation_1.pascalCase(suffix),
verb: v,
};
}
function fail(message) {
throw new Error(message);
}
function getVerb(operation) {
operation = operation.toLowerCase();
const match = dictionary_1.items(verbs).linq.first(item => item.key.toLowerCase() === operation);
if (match) {
return match.value;
}
const matchDirect = dictionary_1.items(category).linq.first(item => item.key.toLowerCase() === operation);
if (matchDirect) {
return matchDirect.key;
}
return category[operation] ? operation : 'Invoke';
}
function getCategory(verb) {
const match = dictionary_1.items(category).linq.first(item => item.key === verb);
if (match) {
return match.value;
}
return fail(`Verb '${verb}' has no matching category.`);
}
const category = {
'Add': 'System.Management.Automation.VerbsCommon',
'Clear': 'System.Management.Automation.VerbsCommon',
'Close': 'System.Management.Automation.VerbsCommon',
'Copy': 'System.Management.Automation.VerbsCommon',
'Enter': 'System.Management.Automation.VerbsCommon',
'Exit': 'System.Management.Automation.VerbsCommon',
'Find': 'System.Management.Automation.VerbsCommon',
'Format': 'System.Management.Automation.VerbsCommon',
'Get': 'System.Management.Automation.VerbsCommon',
'Hide': 'System.Management.Automation.VerbsCommon',
'Join': 'System.Management.Automation.VerbsCommon',
'Lock': 'System.Management.Automation.VerbsCommon',
'Move': 'System.Management.Automation.VerbsCommon',
'New': 'System.Management.Automation.VerbsCommon',
'Open': 'System.Management.Automation.VerbsCommon',
'Optimize': 'System.Management.Automation.VerbsCommon',
'Pop': 'System.Management.Automation.VerbsCommon',
'Push': 'System.Management.Automation.VerbsCommon',
'Redo': 'System.Management.Automation.VerbsCommon',
'Remove': 'System.Management.Automation.VerbsCommon',
'Rename': 'System.Management.Automation.VerbsCommon',
'Reset': 'System.Management.Automation.VerbsCommon',
'Resize': 'System.Management.Automation.VerbsCommon',
'Search': 'System.Management.Automation.VerbsCommon',
'Select': 'System.Management.Automation.VerbsCommon',
'Set': 'System.Management.Automation.VerbsCommon',
'Show': 'System.Management.Automation.VerbsCommon',
'Skip': 'System.Management.Automation.VerbsCommon',
'Split': 'System.Management.Automation.VerbsCommon',
'Step': 'System.Management.Automation.VerbsCommon',
'Switch': 'System.Management.Automation.VerbsCommon',
'Undo': 'System.Management.Automation.VerbsCommon',
'Unlock': 'System.Management.Automation.VerbsCommon',
'Watch': 'System.Management.Automation.VerbsCommon',
'Backup': 'System.Management.Automation.VerbsData',
'Checkpoint': 'System.Management.Automation.VerbsData',
'Compare': 'System.Management.Automation.VerbsData',
'Compress': 'System.Management.Automation.VerbsData',
'Convert': 'System.Management.Automation.VerbsData',
'ConvertFrom': 'System.Management.Automation.VerbsData',
'ConvertTo': 'System.Management.Automation.VerbsData',
'Dismount': 'System.Management.Automation.VerbsData',
'Edit': 'System.Management.Automation.VerbsData',
'Expand': 'System.Management.Automation.VerbsData',
'Export': 'System.Management.Automation.VerbsData',
'Group': 'System.Management.Automation.VerbsData',
'Import': 'System.Management.Automation.VerbsData',
'Initialize': 'System.Management.Automation.VerbsData',
'Limit': 'System.Management.Automation.VerbsData',
'Merge': 'System.Management.Automation.VerbsData',
'Mount': 'System.Management.Automation.VerbsData',
'Out': 'System.Management.Automation.VerbsData',
'Publish': 'System.Management.Automation.VerbsData',
'Restore': 'System.Management.Automation.VerbsData',
'Save': 'System.Management.Automation.VerbsData',
'Sync': 'System.Management.Automation.VerbsData',
'Unpublish': 'System.Management.Automation.VerbsData',
'Update': 'System.Management.Automation.VerbsData',
'Approve': 'System.Management.Automation.VerbsLifecycle',
'Assert': 'System.Management.Automation.VerbsLifecycle',
'Complete': 'System.Management.Automation.VerbsLifecycle',
'Confirm': 'System.Management.Automation.VerbsLifecycle',
'Deny': 'System.Management.Automation.VerbsLifecycle',
'Disable': 'System.Management.Automation.VerbsLifecycle',
'Enable': 'System.Management.Automation.VerbsLifecycle',
'Install': 'System.Management.Automation.VerbsLifecycle',
'Invoke': 'System.Management.Automation.VerbsLifecycle',
'Register': 'System.Management.Automation.VerbsLifecycle',
'Request': 'System.Management.Automation.VerbsLifecycle',
'Restart': 'System.Management.Automation.VerbsLifecycle',
'Resume': 'System.Management.Automation.VerbsLifecycle',
'Start': 'System.Management.Automation.VerbsLifecycle',
'Stop': 'System.Management.Automation.VerbsLifecycle',
'Submit': 'System.Management.Automation.VerbsLifecycle',
'Suspend': 'System.Management.Automation.VerbsLifecycle',
'Uninstall': 'System.Management.Automation.VerbsLifecycle',
'Unregister': 'System.Management.Automation.VerbsLifecycle',
'Wait': 'System.Management.Automation.VerbsLifecycle',
'Debug': 'System.Management.Automation.VerbsDiagnostic',
'Measure': 'System.Management.Automation.VerbsDiagnostic',
'Ping': 'System.Management.Automation.VerbsDiagnostic',
'Repair': 'System.Management.Automation.VerbsDiagnostic',
'Resolve': 'System.Management.Automation.VerbsDiagnostic',
'Test': 'System.Management.Automation.VerbsDiagnostic',
'Trace': 'System.Management.Automation.VerbsDiagnostic',
'Connect': 'System.Management.Automation.VerbsCommunications',
'Disconnect': 'System.Management.Automation.VerbsCommunications',
'Read': 'System.Management.Automation.VerbsCommunications',
'Receive': 'System.Management.Automation.VerbsCommunications',
'Send': 'System.Management.Automation.VerbsCommunications',
'Write': 'System.Management.Automation.VerbsCommunications',
'Block': 'System.Management.Automation.VerbsSecurity',
'Grant': 'System.Management.Automation.VerbsSecurity',
'Protect': 'System.Management.Automation.VerbsSecurity',
'Revoke': 'System.Management.Automation.VerbsSecurity',
'Unblock': 'System.Management.Automation.VerbsSecurity',
'Unprotect': 'System.Management.Automation.VerbsSecurity',
'Use': 'System.Management.Automation.VerbsOther',
};
const verbs = {
'Access': 'Get',
'List': 'Get',
'Cat': 'Get',
'Type': 'Get',
'Dir': 'Get',
'Obtain': 'Get',
'Dump': 'Get',
'Acquire': 'Get',
'Examine': 'Get',
'Suggest': 'Get',
'Retrieve': 'Get',
'Create': 'New',
'Generate': 'New',
'Allocate': 'New',
'Provision': 'New',
'Make': 'New',
'Regenerate': 'New',
'Replace': 'Update',
'Failover': 'Set',
'Assign': 'Set',
'Configure': 'Set',
'Activate': 'Initialize',
'Build': 'Build',
'Compile': 'Build',
'Deploy': 'Deploy',
'Apply': 'Add',
'Append': 'Add',
'Attach': 'Add',
'Concatenate': 'Add',
'Insert': 'Add',
'Delete': 'Remove',
'Cut': 'Remove',
'Dispose': 'Remove',
'Discard': 'Remove',
'Generalize': 'Reset',
'Patch': 'Update',
'Refresh': 'Update',
'Reprocess': 'Update',
'Upgrade': 'Update',
'Reimage': 'Update',
'Retarget': 'Update',
'Validate': 'Test',
'Check': 'Test',
'Verify': 'Test',
'Analyze': 'Test',
'Is': 'Test',
'Evaluate': 'Test',
'Power': 'Start',
'PowerOn': 'Start',
'Run': 'Start',
'Trigger': 'Start',
'Pause': 'Suspend',
'Cancel': 'Stop',
'PowerOff': 'Stop',
'End': 'Stop',
'Shutdown': 'Stop',
'Reboot': 'Restart',
'ForceReboot': 'Restart',
'Finish': 'Complete',
'Wipe': 'Clear',
'Purge': 'Clear',
'Flush': 'Clear',
'Erase': 'Clear',
'Unmark': 'Clear',
'Unset': 'Clear',
'Nullify': 'Clear',
'Recover': 'Restore',
'Undelete': 'Restore',
'Synchronize': 'Sync',
'Synch': 'Sync',
'Load': 'Import',
'Capture': 'Export',
'Migrate': 'Move',
'Transfer': 'Move',
'Name': 'Move',
'Reassociate': 'Move',
'Change': 'Rename',
'Swap': 'Switch',
'Execute': 'Invoke',
'Perform': 'Invoke',
'Discover': 'Find',
'Locate': 'Find',
'Release': 'Publish',
'Resubmit': 'Submit',
'Duplicate': 'Copy',
'Clone': 'Copy',
'Replicate': 'Copy',
'Into': 'Enter',
'Combine': 'Join',
'Unite': 'Join',
'Associate': 'Join',
'Restrict': 'Lock',
'Secure': 'Lock',
'Unrestrict': 'Unlock',
'Unsecure': 'Unlock',
'Display': 'Show',
'Produce': 'Show',
'Bypass': 'Skip',
'Jump': 'Skip',
'Separate': 'Split',
'Notify': 'Send',
'Authorize': 'Grant'
};
//# sourceMappingURL=create-commands.js.map