@autorest/powershell
Version:
AutoRest PowerShell Cmdlet Generator
240 lines • 15.2 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.csnamerV2 = exports.nameStuffRight = void 0;
const codemodel_1 = require("@autorest/codemodel");
const codegen_1 = require("@azure-tools/codegen");
const linq_1 = require("@azure-tools/linq");
const codegen_csharp_1 = require("@azure-tools/codegen-csharp");
const schema_resolver_1 = require("../llcsharp/schema/schema-resolver");
const model_state_1 = require("../utils/model-state");
const schema_1 = require("../utils/schema");
function setPropertyNames(schema) {
var _a, _b, _c;
// name each property in this schema
// skip-for-time-being
if (!(0, codemodel_1.isObjectSchema)(schema)) {
return;
}
for (const propertySchema of (0, linq_1.values)(schema.properties)) {
const propertyDetails = propertySchema.language.default;
const mutability = (0, schema_1.getMutability)(propertySchema);
propertyDetails.required = (_a = propertySchema.required) !== null && _a !== void 0 ? _a : false;
propertyDetails.readOnly = (_b = propertySchema.readOnly) !== null && _b !== void 0 ? _b : false;
propertyDetails.read = mutability.read;
propertyDetails.update = mutability.update && !propertyDetails.readOnly;
propertyDetails.create = mutability.create && !propertyDetails.readOnly;
const className = (_c = schema.language.csharp) === null || _c === void 0 ? void 0 : _c.name;
let pname = (0, codegen_1.getPascalIdentifier)(propertyDetails.name);
if (pname === className) {
pname = `${pname}Property`;
}
if (pname === 'default') {
pname = '@default';
}
propertySchema.language.csharp = {
...propertyDetails,
name: pname // and so are the propertyNmaes
};
if (propertyDetails.isNamedStream) {
propertySchema.language.csharp.namedStreamPropertyName = (0, codegen_1.pascalCase)((0, codegen_1.fixLeadingNumber)([...(0, codegen_1.deconstruct)(propertyDetails.name), 'filename']));
}
}
}
function setSchemaNames(schemaGroups, azure, serviceNamespace, keepNames, addAPIVersion = false) {
var _a, _b;
const baseNamespace = new Set();
const subNamespace = new Map();
// dolauli need to notice this -- schemas in the namespace of the lowest supported api version
// in Azure Mode, we want to always put schemas into the namespace of the lowest supported apiversion.
// otherwise, we just want to differentiate with a simple incremental numbering scheme.
for (const group of (0, linq_1.values)(schemaGroups)) {
for (const schema of group) {
if (schema.language.default.skip) {
continue;
}
let thisNamespace = baseNamespace;
let thisApiversion = '';
// create the namespace if required
if (azure) {
const versions = [...(0, linq_1.values)(schema.apiVersions).select(v => v.version)];
if (((_a = schema.language.default) === null || _a === void 0 ? void 0 : _a.uid) !== 'universal-parameter-type') {
if (addAPIVersion && versions && (0, linq_1.length)(versions) > 0) {
thisApiversion = (0, codegen_1.minimum)(versions);
thisNamespace = subNamespace.get(thisApiversion) || new Set();
subNamespace.set(thisApiversion, thisNamespace);
}
}
}
// for each schema, we're going to set the name
// to the suggested name, unless we have collisions
// at which point, we're going to add a number (for now?)
const details = schema.language.default;
let schemaName = (0, codegen_1.getPascalIdentifier)(details.name);
const apiName = (!thisApiversion) ? '' : (0, codegen_1.getPascalIdentifier)(`Api ${thisApiversion}`);
const ns = addAPIVersion && !!thisApiversion ? ['.', apiName] : [];
let n = 1;
while (thisNamespace.has(schemaName) ||
(keepNames.includes(schemaName) && ((_b = schema.language.default) === null || _b === void 0 ? void 0 : _b.uid) !== 'universal-parameter-type')) {
schemaName = (0, codegen_1.getPascalIdentifier)(`${details.name}_${n++}`);
}
thisNamespace.add(schemaName);
// object types.
if (schema.type === codemodel_1.SchemaType.Object || schema.type === codemodel_1.SchemaType.Dictionary || schema.type === codemodel_1.SchemaType.Any) {
schema.language.csharp = {
...details,
apiversion: thisApiversion,
apiname: apiName,
interfaceName: 'I' + (0, codegen_1.pascalCase)((0, codegen_1.fixLeadingNumber)([...(0, codegen_1.deconstruct)(schemaName)])),
internalInterfaceName: 'I' + (0, codegen_1.pascalCase)((0, codegen_1.fixLeadingNumber)([...(0, codegen_1.deconstruct)(schemaName), 'Internal'])),
fullInternalInterfaceName: `${(0, codegen_1.pascalCase)([serviceNamespace, '.', 'Models', ...ns])}.${'I' + (0, codegen_1.pascalCase)((0, codegen_1.fixLeadingNumber)([...(0, codegen_1.deconstruct)(schemaName), 'Internal']))}`,
name: (0, codegen_1.getPascalIdentifier)(schemaName),
namespace: (0, codegen_1.pascalCase)([serviceNamespace, '.', 'Models', ...ns]),
fullname: `${(0, codegen_1.pascalCase)([serviceNamespace, '.', 'Models', ...ns])}.${(0, codegen_1.getPascalIdentifier)(schemaName)}`,
};
}
else if (schema.type === codemodel_1.SchemaType.Choice || schema.type === codemodel_1.SchemaType.SealedChoice) {
// oh, it's an enum type
const choiceSchema = schema;
schema.language.csharp = {
...details,
interfaceName: 'I' + (0, codegen_1.pascalCase)((0, codegen_1.fixLeadingNumber)([...(0, codegen_1.deconstruct)(schemaName)])),
name: (0, codegen_1.getPascalIdentifier)(schemaName),
namespace: (0, codegen_1.pascalCase)([serviceNamespace, '.', 'Support']),
fullname: `${(0, codegen_1.pascalCase)([serviceNamespace, '.', 'Support'])}.${(0, codegen_1.getPascalIdentifier)(schemaName)}`,
enum: {
...schema.language.default.enum,
name: (0, codegen_1.getPascalIdentifier)(schema.language.default.name),
values: choiceSchema.choices.map(each => {
return {
...each,
name: (0, codegen_1.getPascalIdentifier)(each.language.default.name),
description: each.language.default.description
};
})
}
};
}
else {
schema.language.csharp = {
...details,
interfaceName: '<INVALID_INTERFACE>',
internalInterfaceName: '<INVALID_INTERFACE>',
name: schemaName,
namespace: '<INVALID_NAMESPACE>',
fullname: '<INVALID_FULLNAME>'
};
// xichen: for invalid namespace case, we won't create model class. So we do not need consider dup case
thisNamespace.delete(schemaName);
}
// name each property in this schema
setPropertyNames(schema);
// fix enum names
if (schema.type === codemodel_1.SchemaType.Choice || schema.type === codemodel_1.SchemaType.SealedChoice) {
schema.language.csharp.enum.name = (0, codegen_1.getPascalIdentifier)(schema.language.default.name);
// and the value names themselves
for (const value of (0, linq_1.values)(schema.language.csharp.enum.values)) {
// In m3, enum.name and enum.value are same. But in m4, enum.name is named by m4.
// To keep same action as m3, use enum.value here
value.name = (0, codegen_1.getPascalIdentifier)(value.value);
}
}
}
}
}
async function setOperationNames(state, resolver) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
// keep a list of operation names that we've assigned.
const operationNames = new Set();
for (const operationGroup of (0, linq_1.values)(state.model.operationGroups)) {
for (const operation of (0, linq_1.values)(operationGroup.operations)) {
const details = operation.language.default;
// come up with a name
const oName = (0, codegen_1.getPascalIdentifier)(operationGroup.$key + '_' + details.name);
let i = 1;
let operationName = oName;
while (operationNames.has(operationName)) {
// if we have used that name, try again.
operationName = `${oName}${i++}`;
}
operationNames.add(operationName);
operation.language.csharp = {
...details,
name: operationName,
};
// parameters are camelCased.
for (const parameter of (0, linq_1.values)(operation.parameters)) {
const parameterDetails = parameter.language.default;
let propName = (0, codegen_1.camelCase)((0, codegen_1.fixLeadingNumber)((0, codegen_1.deconstruct)(parameterDetails.serializedName)));
if (propName === 'default') {
propName = '@default';
}
parameter.language.csharp = {
...parameterDetails,
name: propName
};
}
const responses = [...(0, linq_1.values)(operation.responses), ...(0, linq_1.values)(operation.exceptions)];
for (const rsp of responses) {
// per responseCode
const response = rsp;
const responseTypeDefinition = response.schema ? resolver.resolveTypeDeclaration(response.schema, true, state, await state.getValue('fixed-array', false)) : undefined;
const headerSchema = response.language.default.headerSchema;
const headerTypeDefinition = headerSchema ? resolver.resolveTypeDeclaration(headerSchema, true, state.path('schemas', headerSchema.language.default.name), await state.getValue('fixed-array', false)) : undefined;
let code = (codegen_csharp_1.System.Net.HttpStatusCode[(_a = response.protocol.http) === null || _a === void 0 ? void 0 : _a.statusCodes[0]] ? codegen_csharp_1.System.Net.HttpStatusCode[(_b = response.protocol.http) === null || _b === void 0 ? void 0 : _b.statusCodes[0]].value : (((_c = response.protocol.http) === null || _c === void 0 ? void 0 : _c.statusCodes[0]) || '')).replace('global::System.Net.HttpStatusCode', '');
let rawValue = code.replace(/\./, '');
if (((_d = response.protocol.http) === null || _d === void 0 ? void 0 : _d.statusCodes[0]) === 'default' || rawValue === 'default' || '') {
rawValue = 'any response code not handled elsewhere';
code = 'default';
response.language.default.isErrorResponse = true;
}
response.language.csharp = {
...response.language.default,
responseType: responseTypeDefinition ? responseTypeDefinition.declaration : '',
headerType: headerTypeDefinition ? headerTypeDefinition.declaration : '',
name: ((0, linq_1.length)((_e = response.protocol.http) === null || _e === void 0 ? void 0 : _e.mimeTypes) <= 1) ?
(0, codegen_1.camelCase)((0, codegen_1.fixLeadingNumber)((0, codegen_1.deconstruct)(`on ${code}`))) : // the common type (or the only one.)
(0, codegen_1.camelCase)((0, codegen_1.fixLeadingNumber)((0, codegen_1.deconstruct)(`on ${code} ${(_f = response.protocol.http) === null || _f === void 0 ? void 0 : _f.mimeTypes[0]}`))),
description: ((0, linq_1.length)((_g = response.protocol.http) === null || _g === void 0 ? void 0 : _g.mimeTypes) <= 1) ?
`a delegate that is called when the remote service returns ${(_h = response.protocol.http) === null || _h === void 0 ? void 0 : _h.statusCodes[0]} (${rawValue}).` :
`a delegate that is called when the remote service returns ${(_j = response.protocol.http) === null || _j === void 0 ? void 0 : _j.statusCodes[0]} (${rawValue}) with a Content-Type matching ${(_k = response.protocol.http) === null || _k === void 0 ? void 0 : _k.mimeTypes.join(',')}.`
};
}
}
}
}
async function nameStuffRight(state) {
const resolver = new schema_resolver_1.SchemaDefinitionResolver(await state.getValue('fixed-array', false));
const model = state.model;
// set the namespace for the service
const serviceNamespace = await state.getValue('namespace', 'Sample.API');
const azure = await state.getValue('azure', false) || await state.getValue('azure-arm', false);
const clientName = (0, codegen_1.getPascalIdentifier)(model.language.default.name);
const addAPIVersion = await state.getValue('add-api-version-in-model-namespace', false);
// dolauli see model.details.csharp for c# related staff
// set c# client details (name)
model.language.csharp = {
...model.language.default,
name: clientName,
namespace: serviceNamespace,
fullname: `${serviceNamespace}.${clientName}`
};
const universalIdName = `${await state.getValue('service-name')}Identity`;
setSchemaNames(model.schemas, azure, serviceNamespace, [universalIdName], addAPIVersion);
await setOperationNames(state, resolver);
return model;
}
exports.nameStuffRight = nameStuffRight;
async function csnamerV2(service) {
// dolauli add names for http operations and schemas
//return processCodeModel(nameStuffRight, service, 'csnamer');
//const session = await startSession<PwshModel>(service, {}, codeModelSchema);
//const result = tweakModelV2(session);
const state = await new model_state_1.ModelState(service).init();
await service.writeFile({ filename: 'code-model-v4-csnamer-v2.yaml', content: (0, codegen_1.serialize)(await nameStuffRight(state)), sourceMap: undefined, artifactType: 'code-model-v4' });
}
exports.csnamerV2 = csnamerV2;
//# sourceMappingURL=cs-namer-v2.js.map
;