@microsoft.azure/autorest.incubator
Version:
AutoRest incubator project
293 lines • 16.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const project_1 = require("../csharp/code-dom/project");
const schema_1 = require("../common/code-model/schema");
const dictionary_1 = require("../common/dictionary");
const access_modifier_1 = require("../csharp/code-dom/access-modifier");
const attribute_1 = require("../csharp/code-dom/attribute");
const class_1 = require("../csharp/code-dom/class");
const expression_1 = require("../csharp/code-dom/expression");
const import_1 = require("../csharp/code-dom/import");
const interface_1 = require("../csharp/code-dom/interface");
const method_1 = require("../csharp/code-dom/method");
const dotnet = require("../csharp/code-dom/mscorlib");
const namespace_1 = require("../csharp/code-dom/namespace");
const parameter_1 = require("../csharp/code-dom/parameter");
const if_1 = require("../csharp/code-dom/statements/if");
const return_1 = require("../csharp/code-dom/statements/return");
const try_1 = require("../csharp/code-dom/statements/try");
const clientruntime_1 = require("../csharp/lowlevel-generator/clientruntime");
const object_1 = require("../csharp/schema/object");
const schema_resolver_1 = require("../csharp/schema/schema-resolver");
const model_cmdlet_1 = require("../powershell/model-cmdlet");
const module_class_1 = require("../powershell/module-class");
const powershell_declarations_1 = require("../powershell/powershell-declarations");
const cmdlet_class_1 = require("./cmdlet-class");
const text_manipulation_1 = require("../common/text-manipulation");
class ServiceNamespace extends namespace_1.Namespace {
constructor(state, objectInitializer) {
super(state.model.details.csharp.namespace || 'INVALID.NAMESPACE', state.project);
this.state = state;
this.apply(objectInitializer);
// module class
this.moduleClass = new module_class_1.ModuleClass(this, state);
}
get outputFolder() {
return this.state.project.moduleFolder;
}
}
exports.ServiceNamespace = ServiceNamespace;
class ModelExtensionsNamespace extends namespace_1.Namespace {
constructor(parent, schemas, state, objectInitializer) {
super('Models', parent);
this.schemas = schemas;
this.state = state;
this.resolver = new schema_resolver_1.SchemaDefinitionResolver();
this.apply(objectInitializer);
const $this = this;
// Add typeconverters to model classes (partial)
for (const { key: schemaName, value: schema } of dictionary_1.items(schemas)) {
if (!schema) {
continue;
}
const td = this.resolver.resolveTypeDeclaration(schema, true, state);
if (td instanceof object_1.ObjectImplementation) {
// it's a class object.
const className = td.schema.details.csharp.name;
const interfaceName = td.schema.details.csharp.interfaceName || '';
const converterClass = `${className}TypeConverter`;
// create the model extensions for each object model
// 2. A partial interface with the type converter attribute
const modelInterface = new interface_1.Interface(this, interfaceName, {
partial: true,
});
modelInterface.add(new attribute_1.Attribute(powershell_declarations_1.TypeConverterAttribute, { parameters: [new expression_1.LiteralExpression(`typeof(${converterClass})`)] }));
// 1. A partial class with the type converter attribute
const model = new class_1.Class(this, className, undefined, {
partial: true,
});
model.add(new attribute_1.Attribute(powershell_declarations_1.TypeConverterAttribute, { parameters: [new expression_1.LiteralExpression(`typeof(${converterClass})`)] }));
model.add(new method_1.LambdaMethod('FromJsonString', modelInterface, new expression_1.LiteralExpression(`FromJson(${clientruntime_1.ClientRuntime.JsonNode.declaration}.Parse(jsonText))`), {
static: access_modifier_1.Modifier.Static,
parameters: [new parameter_1.Parameter('jsonText', dotnet.String)]
}));
model.add(new method_1.LambdaMethod('ToJsonString', dotnet.String, new expression_1.LiteralExpression(`ToJson(${dotnet.Null}, ${clientruntime_1.ClientRuntime.SerializationMode.IncludeAll})?.ToString(System.Globalization.CultureInfo.InvariantCulture)`), {}));
// + static <interfaceType> FromJsonString(string json);
// + string ToJsonString()
// 3. A TypeConverter class
const typeConverter = new class_1.Class(this, converterClass, powershell_declarations_1.PSTypeConverter);
typeConverter.add(new method_1.LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, {
override: access_modifier_1.Modifier.Override,
parameters: [
new parameter_1.Parameter('sourceValue', dotnet.Object),
new parameter_1.Parameter('destinationType', dotnet.System.Type)
]
}));
typeConverter.add(new method_1.LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, {
override: access_modifier_1.Modifier.Override,
parameters: [
new parameter_1.Parameter('sourceValue', dotnet.Object),
new parameter_1.Parameter('destinationType', dotnet.System.Type),
new parameter_1.Parameter('formatProvider', dotnet.System.IFormatProvider),
new parameter_1.Parameter('ignoreCase', dotnet.Bool),
]
}));
typeConverter.add(new method_1.LambdaMethod('CanConvertFrom', dotnet.Bool, new expression_1.LiteralExpression(`CanConvertFrom(sourceValue)`), {
override: access_modifier_1.Modifier.Override,
parameters: [
new parameter_1.Parameter('sourceValue', dotnet.Object),
new parameter_1.Parameter('destinationType', dotnet.System.Type)
]
}));
typeConverter.add(new method_1.LambdaMethod('ConvertFrom', dotnet.Object, new expression_1.LiteralExpression('ConvertFrom(sourceValue)'), {
override: access_modifier_1.Modifier.Override,
parameters: [
new parameter_1.Parameter('sourceValue', dotnet.Object),
new parameter_1.Parameter('destinationType', dotnet.System.Type),
new parameter_1.Parameter('formatProvider', dotnet.System.IFormatProvider),
new parameter_1.Parameter('ignoreCase', dotnet.Bool),
]
}));
typeConverter.add(new method_1.Method('CanConvertFrom', dotnet.Bool, {
static: access_modifier_1.Modifier.Static,
parameters: [
new parameter_1.Parameter('sourceValue', dotnet.Dynamic),
]
})).add(function* () {
yield if_1.If(`null == sourceValue`, return_1.Return(dotnet.True));
yield try_1.Try(function* () {
yield if_1.If(`sourceValue.GetType() == typeof(${powershell_declarations_1.PSObject.declaration})`, function* () {
yield `// does it have the properties we need`;
});
yield if_1.ElseIf(`sourceValue.GetType() == typeof(${dotnet.System.Collections.Hashtable.declaration})`, function* () {
yield `// a hashtable?`;
});
yield if_1.Else(function* () {
yield `// object `;
});
// is the source a PSType or a hashtable?
// is the source a string? has a ToJson?
// try deserializing, and validate. if successful, return true
// does it have the same members as I do?
});
yield try_1.Catch(undefined, `// Unable to use JSON pattern`);
yield return_1.Return(dotnet.False);
});
typeConverter.add(new method_1.Method('ConvertFrom', dotnet.Object, {
static: access_modifier_1.Modifier.Static,
parameters: [
new parameter_1.Parameter('sourceValue', dotnet.Dynamic),
]
})).add(function* () {
// null begets null
yield if_1.If(`null == sourceValue`, return_1.Return(dotnet.Null));
// try using json first (either from string or toJsonString())
yield try_1.Try(`${className}.FromJsonString(typeof(string) == sourceValue.GetType() ? sourceValue : sourceValue.ToJsonString());`);
yield try_1.Catch(undefined, `// Unable to use JSON pattern`);
yield try_1.Try(function* () {
yield `return new ${className}`;
yield `{`;
// loop thru members...
for (const member of dictionary_1.values(td.schema.properties)) {
// if it's a primitive field
const memTD = $this.resolver.resolveTypeDeclaration(member.schema, true, state);
if (memTD instanceof object_1.ObjectImplementation) {
// it's an object, try the typeconverter
yield `${member.details.csharp.name} = ${member.schema.details.csharp.name}TypeConverter.ConvertFrom(sourceValue.${member.details.csharp.name}),`;
}
else {
// just assign it.
yield `${member.details.csharp.name} = sourceValue.${member.details.csharp.name},`;
}
// otherwise use the field's typeconverter
}
yield `};`;
});
yield try_1.Catch(undefined, ``);
// null if not successful
yield return_1.Return(dotnet.Null);
});
}
}
}
get outputFolder() {
return this.state.project.apiextensionsfolder;
}
}
exports.ModelExtensionsNamespace = ModelExtensionsNamespace;
class ModelCmdletNamespace extends namespace_1.Namespace {
constructor(parent, state, objectInitializer) {
super('ModelCmdlets', parent);
this.state = state;
this.inputModels = new Array();
this.apply(objectInitializer);
this.addUsing(new import_1.Import('static Microsoft.Rest.ClientRuntime.IEventListenerExtensions'));
this.addUsing(new import_1.Import('static Microsoft.Rest.ClientRuntime.HttpRequestMessageExtensions'));
}
get outputFolder() {
return this.state.project.modelCmdletFolder;
}
createModelCmdlets() {
// generate the model cmdlets unless they dont want them.
if (!this.state.project.skipModelCmdlets) {
for (const { key: id, value: schema } of dictionary_1.items(this.state.model.schemas)) {
if (schema.type !== schema_1.JsonType.Object) {
continue;
}
let found = false;
// check if a cmdlet uses this as a parameter
for (const sch of dictionary_1.values(this.inputModels)) {
if (sch === schema) {
found = true;
break;
}
}
if (found) {
this.addClass(new model_cmdlet_1.ModelCmdlet(this, schema, this.state.path('schemas', id)));
}
}
}
}
addInputSchema(schema) {
if (schema.type === schema_1.JsonType.Object) {
if (this.inputModels.indexOf(schema) === -1) {
this.inputModels.push(schema);
for (const p of dictionary_1.values(schema.properties)) {
if (!p.schema.readOnly && !p.details.csharp.HeaderProperty && !p.schema.additionalProperties) {
this.addInputSchema(p.schema);
}
}
}
}
}
}
exports.ModelCmdletNamespace = ModelCmdletNamespace;
class CmdletNamespace extends namespace_1.Namespace {
constructor(parent, state, objectInitializer) {
super('Cmdlets', parent);
this.state = state;
this.inputModels = new Array();
this.apply(objectInitializer);
this.addUsing(new import_1.Import('static Microsoft.Rest.ClientRuntime.IEventListenerExtensions'));
this.addUsing(new import_1.Import('static Microsoft.Rest.ClientRuntime.HttpRequestMessageExtensions'));
// generate cmdlet classes on top of the SDK
for (const { key: id, value: operation } of dictionary_1.items(state.model.commands.operations)) {
this.addClass(new cmdlet_class_1.CmdletClass(this, operation, state.path('commands', 'operations', id)));
if (operation.details.powershell.hasBody) {
// make a copy that doesn't use the body parameter
this.addClass(new cmdlet_class_1.CmdletClass(this, operation, state.path('commands', 'operations', id), true));
}
for (const p of operation.parameters) {
state.project.modelCmdlets.addInputSchema(p.schema);
}
}
}
get outputFolder() {
return this.state.project.cmdletFolder;
}
}
exports.CmdletNamespace = CmdletNamespace;
class Project extends project_1.Project {
constructor(state) {
super();
this.state = state;
this.schemaDefinitionResolver = new schema_resolver_1.SchemaDefinitionResolver();
state.project = this;
}
async init() {
await super.init();
const service = this.state.service;
const model = this.state.model;
const state = this.state;
const mil = await service.GetValue('max-inlined-parameters');
this.maxInlinedParameters = typeof mil === 'number' ? mil : 4;
const smc = await service.GetValue('skip-model-cmdlets');
this.skipModelCmdlets = smc ? true : false;
this.azure = await service.GetValue('azure') || await service.GetValue('azure-arm') || false;
this.moduleName = text_manipulation_1.pascalCase(text_manipulation_1.deconstruct(await service.GetValue('module-name') || model.info.title.replace(/client/ig, '')));
this.moduleFolder = await service.GetValue('module-folder') || './private';
this.cmdletFolder = await service.GetValue('cmdlet-folder') || `${this.moduleFolder}/cmdlets/generated`;
this.modelCmdletFolder = await service.GetValue('model-cmdlet-folder') || `${this.moduleFolder}/cmdlets/models`;
this.customFolder = await service.GetValue('custom-cmdlet-folder') || `${this.moduleFolder}/cmdlets/custom`;
this.runtimefolder = await service.GetValue('runtime-folder') || `${this.moduleFolder}/runtime`;
this.apifolder = await service.GetValue('api-folder') || `${this.moduleFolder}/api`;
this.apiextensionsfolder = await service.GetValue('api-extensions-folder') || `${this.moduleFolder}/api-extensions`;
this.csproj = await service.GetValue('csproj') || `${this.moduleName}.private.csproj`;
this.psd1 = await service.GetValue('psd1') || `${this.moduleName}.psd1`;
this.psm1 = await service.GetValue('psm1') || `${this.moduleName}.psm1`;
// add project namespace
this.addNamespace(this.serviceNamespace = new ServiceNamespace(state));
this.addNamespace(this.modelCmdlets = new ModelCmdletNamespace(this.serviceNamespace, state));
// add cmdlet namespace
this.addNamespace(this.cmdlets = new CmdletNamespace(this.serviceNamespace, state));
this.addNamespace(this.modelsExtensions = new ModelExtensionsNamespace(this.serviceNamespace, state.model.schemas, state.path('components', 'schemas')));
if (!this.skipModelCmdlets) {
this.modelCmdlets.createModelCmdlets();
}
// abort now if we have any errors.
state.checkpoint();
return this;
}
}
exports.Project = Project;
//# sourceMappingURL=project.js.map