diff --git a/README.md b/README.md index 95b62dc023..594a1ef5e0 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ autorest --typescript --output-folder= --license-header=MICROSOFT_MIT_NO_VERSION -package-name= --package-version ``` -- If you want to generate metadata files (package.json, .npmignore, webpack.config.js, tsconfig.json), then provide `--generate-metadata=true`: +- If you want to generate metadata files **__(package.json, .npmignore, webpack.config.js, tsconfig.json, README.md(with a sample))__**, then provide `--generate-metadata=true`: -**NOTE: This will generate all the _metadata_ files one level above the output-folder.** +**NOTE: This will generate all the __metadata__ files one level above the output-folder.** ``` autorest --typescript --output-folder= --license-header=MICROSOFT_MIT_NO_VERSION --input-file= --package-name= --package-version --generate-metadata=true ``` diff --git a/src/azure/CodeGeneratorTSa.cs b/src/azure/CodeGeneratorTSa.cs index fdcbecb74d..d1581bd99e 100644 --- a/src/azure/CodeGeneratorTSa.cs +++ b/src/azure/CodeGeneratorTSa.cs @@ -82,6 +82,10 @@ public override async Task Generate(CodeModel cm) // .npmignore var npmIgnore = new NpmIgnore { Model = codeModel }; await Write(npmIgnore, Path.Combine("../", ".npmignore")); + + //README.md + var readme = new AzureReadmeTemplate { Model = codeModel }; + await Write(readme, Path.Combine("../", "README.md")); } } } diff --git a/src/azure/Templates/AzureReadmeTemplate.cshtml b/src/azure/Templates/AzureReadmeTemplate.cshtml new file mode 100644 index 0000000000..0b4e90693e --- /dev/null +++ b/src/azure/Templates/AzureReadmeTemplate.cshtml @@ -0,0 +1,74 @@ +@using AutoRest.Core.Utilities +@using AutoRest.TypeScript.Azure.Model +@inherits AutoRest.Core.Template + +# Microsoft Azure SDK for isomorphic javascript - @(Model.Name) +This project provides an isomorphic javascript package for accessing Azure. Right now it supports: +- node.js version 6.x.x or higher +- browser javascript +@EmptyLine +## How to Install +@EmptyLine +- nodejs +``` +npm install @(Model.PackageName) +``` +- browser +```html +@{ +@: +} +``` +@EmptyLine +## How to use +@EmptyLine +### nodejs - Authentication, client creation and @(Model.GetSampleMethod()?.Name) @(Model.GetSampleMethodGroupName()) as an example written in TypeScript. +@EmptyLine +```javascript +import * as msRest from "ms-rest-js"; +import * as msRestAzure from "ms-rest-azure-js"; +import * as msRestNodeAuth from "ms-rest-nodeauth"; +import { @(Model.Name), @(Model.ClientPrefix)Models, @(Model.ClientPrefix)Mappers } from "@(Model.PackageName)"; +const subscriptionId = process.env["AZURE_SUBSCRIPTION_ID"]; +@EmptyLine +msRestNodeAuth.interactiveLogin().then((creds) => { + const client = new @(Model.Name)(creds, subscriptionId); + @(Model.GenerateSampleMethod()) +}).catch((err) => { + console.log('An error ocurred:'); + console.dir(err, {depth: null, colors: true}); +}); +``` +@EmptyLine +### browser - Authentication, client creation and @(Model.GetSampleMethod().Name) @(Model.GetSampleMethodGroupName()) as an example written in javascript. +@EmptyLine +- index.html +```html +@{ +@: +@: +@: +@: My Todos +@: +@: +@: +@: +@: +@: +@: +@: +} +``` +@EmptyLine +# Related projects + - [Microsoft Azure SDK for Javascript](https://github.com/Azure/azure-sdk-for-js) diff --git a/src/azure/Templates/AzureServiceClientTemplate.cshtml b/src/azure/Templates/AzureServiceClientTemplate.cshtml index 5ad20af35a..c7ce09deca 100644 --- a/src/azure/Templates/AzureServiceClientTemplate.cshtml +++ b/src/azure/Templates/AzureServiceClientTemplate.cshtml @@ -3,7 +3,8 @@ @using AutoRest.Core.Utilities @using AutoRest.TypeScript.vanilla.Templates @using AutoRest.TypeScript -@inherits AutoRest.Core.Template +@using AutoRest.TypeScript.Azure.Model +@inherits AutoRest.Core.Template /* @Header(" * ") */ diff --git a/src/vanilla/ClientModelExtensions.cs b/src/vanilla/ClientModelExtensions.cs index 6698612e6b..6befe4d033 100644 --- a/src/vanilla/ClientModelExtensions.cs +++ b/src/vanilla/ClientModelExtensions.cs @@ -518,7 +518,7 @@ public static string TSType(this IModelType type, bool inModelsModule) { { var enumName = enumType.Name.ToPascalCase(); tsType = "Models." + enumName; - if (inModelsModule || enumName.Contains('.')) + if (inModelsModule || enumName.Contains('.')) { tsType = enumName; } @@ -959,5 +959,148 @@ public static bool IsCompositeOrEnumType(this IModelType type) return false; } } + + public static string InitializeType(this IModelType paramType, string paramName, bool isBrowser = false) + { + if (paramType is EnumType) + { + return paramType.InitializeEnumType(isBrowser); + } + else if (paramType is PrimaryType) + { + return paramType.InitializePrimaryType(paramName, isBrowser); + } + else if (paramType is SequenceType) + { + return paramType.InitializeSequenceType(paramName, isBrowser); + } + else if (paramType is DictionaryType) + { + return paramType.InitializeDictionaryType(paramName, isBrowser); + } + else if (paramType is CompositeType) + { + return paramType.InitializeCompositeType(paramName, isBrowser); + } + + return null; + } + + public static string InitializeCompositeType(this IModelType paramType, string paramName, bool isBrowser = false) + { + var builder = new IndentedStringBuilder(" "); + var composite = (CompositeType)paramType; + if (composite.ComposedProperties.Any()) + { + builder.AppendLine("{").Indent(); + var composedPropertyList = new List(composite.ComposedProperties.Where(p => /**p.IsRequired &&**/ !p.IsReadOnly)); + for (var i = 0; i < composedPropertyList.Count; i++) + { + var prop = composedPropertyList[i]; + if (i != composedPropertyList.Count - 1) + { + builder.AppendLine("{0}: {1},", prop.Name, prop.ModelType.InitializeType(prop.Name, isBrowser)); + } + else + { + builder.AppendLine("{0}: {1}", prop.Name, prop.ModelType.InitializeType(prop.Name, isBrowser)); + } + } + builder.Outdent().Append("}"); + } + else + { + builder.AppendLine("{}"); + } + return builder.ToString(); + } + + public static string InitializeDictionaryType(this IModelType paramType, string paramName, bool isBrowser = false) + { + var dictionary = (DictionaryType)paramType; + var paramValue = $"{{ \"key1\": {dictionary.ValueType.InitializeType(paramName, isBrowser)} }}"; + return paramValue; + } + + public static string InitializeSequenceType(this IModelType paramType, string paramName, bool isBrowser = false) + { + var sequence = (SequenceType)paramType; + var paramValue = $"[{sequence.ElementType.InitializeType(paramName, isBrowser)}]"; + return paramValue; + } + + public static string InitializeEnumType(this IModelType paramType, bool isBrowser = false) + { + var paramValue = "\"\""; + var enumValue = ((EnumType)paramType).Values[0].SerializedName; + paramValue = $"\"{enumValue}\""; + // TODO: Till we support setting UnderlyingType in autorest.modeler we wil default to string type as the enum value + // if ( ((EnumType)paramType).UnderlyingType.IsPrimaryType(KnownPrimaryType.String)) + // { + // paramValue = $"\"{enumValue}\""; + // } + return paramValue; + } + + public static string InitializePrimaryType(this IModelType paramType, string paramName, bool isBrowser = false) + { + var paramValue = "\"\""; + if (paramType.IsPrimaryType(KnownPrimaryType.String)) + { + if (paramName.EqualsIgnoreCase("location")) + { + paramValue = "\"westus\""; + } + else + { + paramValue = $"\"test{paramName.ToCamelCase()}\""; + } + } + else if (paramType.IsPrimaryType(KnownPrimaryType.Date)) + { + paramValue = "new Date().toISOString().substring(0, 10)"; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.DateTime)) + { + paramValue = "new Date().toISOString()"; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.DateTimeRfc1123)) + { + paramValue = "new Date().toUTCString()"; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.UnixTime)) + { + paramValue = "new Date()"; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.TimeSpan)) + { + paramValue = "\"P1Y2M3DT4H5M6S\""; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.Boolean)) + { + paramValue = "true"; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.Int) || paramType.IsPrimaryType(KnownPrimaryType.Long)) + { + paramValue = "1"; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.Decimal) || paramType.IsPrimaryType(KnownPrimaryType.Double)) + { + paramValue = "1.01"; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.Object)) + { + paramValue = "{}"; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.Uuid)) + { + paramValue = "ec7b1657-199d-4d8a-bbb2-89a11a42e02a"; + } + else if (paramType.IsPrimaryType(KnownPrimaryType.Stream)) + { + paramValue = isBrowser ? "new ReadableStream()" : "new require(\"stream\").Readable()"; + } + return paramValue; + } } } diff --git a/src/vanilla/CodeGeneratorTS.cs b/src/vanilla/CodeGeneratorTS.cs index fd7eb60501..2b6cb816ef 100644 --- a/src/vanilla/CodeGeneratorTS.cs +++ b/src/vanilla/CodeGeneratorTS.cs @@ -3,7 +3,6 @@ // using System; -using System.Globalization; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -86,6 +85,10 @@ public override async Task Generate(CodeModel cm) // .npmignore var npmIgnore = new NpmIgnore { Model = codeModel }; await Write(npmIgnore, Path.Combine("../", ".npmignore")); + + //README.md + var readme = new ReadmeTemplate { Model = codeModel }; + await Write(readme, Path.Combine("../", "README.md")); } } } diff --git a/src/vanilla/Model/CodeModelTS.cs b/src/vanilla/Model/CodeModelTS.cs index 1d47892a05..ee3da36c63 100644 --- a/src/vanilla/Model/CodeModelTS.cs +++ b/src/vanilla/Model/CodeModelTS.cs @@ -13,7 +13,7 @@ namespace AutoRest.TypeScript.Model { - public class CodeModelTS : CodeModel + public class CodeModelTS : CodeModel { public CodeModelTS() { @@ -29,7 +29,7 @@ public CodeModelTS(string packageName = "test-client", string packageVersion = " public bool IsCustomBaseUri => Extensions.ContainsKey(SwaggerExtensions.ParameterizedHostExtension); [JsonIgnore] - public IEnumerable MethodTemplateModels => Methods.Cast().Where( each => each.MethodGroup.IsCodeModelMethodGroup); + public IEnumerable MethodTemplateModels => Methods.Cast().Where(each => each.MethodGroup.IsCodeModelMethodGroup); [JsonIgnore] public virtual IEnumerable ModelTemplateModels => ModelTypes.Cast(); @@ -38,7 +38,7 @@ public CodeModelTS(string packageName = "test-client", string packageVersion = " public virtual IEnumerable EnumTemplateModels => EnumTypes.Cast(); [JsonIgnore] - public virtual IEnumerable MethodGroupModels => Operations.Cast().Where( each => !each.IsCodeModelMethodGroup ); + public virtual IEnumerable MethodGroupModels => Operations.Cast().Where(each => !each.IsCodeModelMethodGroup); /// /// Provides an ordered ModelTemplateModel list such that the parent @@ -46,7 +46,7 @@ public CodeModelTS(string packageName = "test-client", string packageVersion = " /// requiring models in index.js /// [JsonIgnore] - public virtual IEnumerable OrderedModelTemplateModels + public virtual IEnumerable OrderedModelTemplateModels { get { @@ -83,10 +83,10 @@ public bool ContainsDurationProperty() public bool ContainsDurationPropertyInModels() { - return OrderedModelTemplateModels.Any(m => m.Properties.FirstOrDefault(p => - (p.ModelType is PrimaryTypeTS && (p.ModelType as PrimaryTypeTS).KnownPrimaryType == KnownPrimaryType.TimeSpan) || - (p.ModelType is SequenceType && (p.ModelType as SequenceType).ElementType.IsPrimaryType(KnownPrimaryType.TimeSpan)) || - (p.ModelType is DictionaryType && (p.ModelType as DictionaryType).ValueType.IsPrimaryType(KnownPrimaryType.TimeSpan))) != null); + return OrderedModelTemplateModels.Any(m => m.Properties.FirstOrDefault(p => + (p.ModelType is PrimaryTypeTS && (p.ModelType as PrimaryTypeTS).KnownPrimaryType == KnownPrimaryType.TimeSpan) || + (p.ModelType is SequenceType && (p.ModelType as SequenceType).ElementType.IsPrimaryType(KnownPrimaryType.TimeSpan)) || + (p.ModelType is DictionaryType && (p.ModelType as DictionaryType).ValueType.IsPrimaryType(KnownPrimaryType.TimeSpan))) != null); } private void constructOrderedList(CompositeTypeTS model, List orderedList) @@ -100,8 +100,8 @@ private void constructOrderedList(CompositeTypeTS model, List o // They are required explicitly in a different way. Hence, they // are not included in the ordered list. if (model.BaseModelType == null || - (model.BaseModelType != null && - (model.BaseModelType.Name == "BaseResource" || + (model.BaseModelType != null && + (model.BaseModelType.Name == "BaseResource" || model.BaseModelType.Name == "CloudError"))) { if (!orderedList.Contains(model)) @@ -130,7 +130,7 @@ public string PolymorphicDictionary IndentedStringBuilder builder = new IndentedStringBuilder(IndentedStringBuilder.TwoSpaces); var polymorphicTypes = ModelTemplateModels.Where(m => m.BaseIsPolymorphic); - for (int i = 0; i < polymorphicTypes.Count(); i++ ) + for (int i = 0; i < polymorphicTypes.Count(); i++) { string discriminatorField = polymorphicTypes.ElementAt(i).SerializedName; var polymorphicType = polymorphicTypes.ElementAt(i) as CompositeType; @@ -155,13 +155,13 @@ public string PolymorphicDictionary discriminatorField, polymorphicTypes.ElementAt(i).Name)); } - - if(i == polymorphicTypes.Count() -1) + + if (i == polymorphicTypes.Count() - 1) { builder.AppendLine(); } - else + else { builder.AppendLine(","); } @@ -183,7 +183,7 @@ public string RequiredConstructorParameters requireParams.Add("baseUri"); } - if(requireParams == null || requireParams.Count == 0) + if (requireParams == null || requireParams.Count == 0) { return string.Empty; } @@ -195,12 +195,15 @@ public string RequiredConstructorParameters /// /// Return the service client constructor required parameters, in TypeScript syntax. /// - public string RequiredConstructorParametersTS { - get { + public string RequiredConstructorParametersTS + { + get + { StringBuilder requiredParams = new StringBuilder(); bool first = true; - foreach (var p in this.Properties) { + foreach (var p in this.Properties) + { if (!p.IsRequired || p.IsConstant || (p.IsRequired && !string.IsNullOrEmpty(p.DefaultValue))) continue; @@ -248,21 +251,21 @@ public string ExportMethodGroupNames() var length = methodGroups.Count(); for (var i = 0; i < methodGroups.Count(); i++) { - if (i == length-1) + if (i == length - 1) { builder.Append(methodGroups[i].TypeName); } else { builder.Append(methodGroups[i].TypeName + ", "); - } + } } return builder.ToString(); } public bool IsAnyModelInheritingFromRequestOptionsBase() { - return ModelTemplateModels.Any(m => m != null && m.BaseModelType!= null && m.BaseModelType.Name.EqualsIgnoreCase("RequestOptionsBase")); + return ModelTemplateModels.Any(m => m != null && m.BaseModelType != null && m.BaseModelType.Name.EqualsIgnoreCase("RequestOptionsBase")); } public virtual string ConstructRuntimeImportForModelIndex() @@ -279,5 +282,75 @@ public virtual string PackageDependencies() { return "\"ms-rest-js\": \"^0.2.1\""; } + + public virtual Method GetSampleMethod() + { + var getMethod = Methods.Where(m => m.HttpMethod == HttpMethod.Get).FirstOrDefault(); + return getMethod != null ? getMethod : Methods.FirstOrDefault(); + } + + public virtual string GetSampleMethodGroupName() + { + return GetSampleMethod()?.MethodGroup?.Name?.ToCamelCase(); + } + + public virtual string GenerateSampleMethod(bool isBrowser = false) + { + var method = GetSampleMethod(); + var methodGroup = GetSampleMethodGroupName(); + var requiredParameters = method.LogicalParameters.Where( + p => p != null && !p.IsClientProperty && !string.IsNullOrWhiteSpace(p.Name) && !p.IsConstant).OrderBy(item => !item.IsRequired).ToList(); + var builder = new IndentedStringBuilder(" "); + var paramInit = InitializeParametersForSampleMethod(requiredParameters, isBrowser); + builder.AppendLine(paramInit); + var declaration = new StringBuilder(); + bool first = true; + foreach (var param in requiredParameters) + { + if (!first) + declaration.Append(", "); + declaration.Append(param.Name); + first = false; + } + var clientRef = "client."; + if (!string.IsNullOrEmpty(methodGroup)) + { + clientRef = $"client.{methodGroup}."; + } + var methodRef = $"{clientRef}{method.Name.ToCamelCase()}({declaration.ToString()}).then((result) => {{"; + builder.AppendLine(methodRef) + .Indent() + .AppendLine("console.log(\"The result is:\");") + .AppendLine("console.log(result);") + .Outdent(); + if (isBrowser) + { + builder.Append("})"); + } + else + { + builder.AppendLine("});"); + } + + return builder.ToString(); + } + + public string InitializeParametersForSampleMethod(List requiredParameters, bool isBrowser = false) + { + var builder = new IndentedStringBuilder(" "); + foreach (var param in requiredParameters) + { + var paramValue = "\"\""; + paramValue = param.ModelType.InitializeType(param.Name, isBrowser); + var paramDeclaration = $"const {param.Name}"; + if (param.ModelType is CompositeType && !isBrowser) + { + paramDeclaration += $": {ClientPrefix}Models.{param.ModelTypeName}"; + } + paramDeclaration += $" = {paramValue};"; + builder.AppendLine(paramDeclaration); + } + return builder.ToString(); + } } } \ No newline at end of file diff --git a/src/vanilla/Templates/ReadmeTemplate.cshtml b/src/vanilla/Templates/ReadmeTemplate.cshtml new file mode 100644 index 0000000000..bc85f4cbb6 --- /dev/null +++ b/src/vanilla/Templates/ReadmeTemplate.cshtml @@ -0,0 +1,71 @@ +@using AutoRest.Core.Utilities +@using AutoRest.TypeScript.Model +@inherits AutoRest.Core.Template + +# An isomorphic javascript sdk for - @(Model.Name) +This project provides an isomorphic javascript package. Right now it supports: +- node.js version 6.x.x or higher +- browser javascript +@EmptyLine +## How to Install +@EmptyLine +- nodejs +``` +npm install @(Model.PackageName) +``` +- browser +```html +@{ +@: +} +``` +@EmptyLine +## How to use +@EmptyLine +### nodejs - Authentication, client creation and @(Model.GetSampleMethod()?.Name) @(Model.GetSampleMethodGroupName()) as an example written in TypeScript. +@EmptyLine +```javascript +import * as msRest from "ms-rest-js"; +import { @(Model.Name), @(Model.ClientPrefix)Models, @(Model.ClientPrefix)Mappers } from "@(Model.PackageName)"; +const subscriptionId = process.env["AZURE_SUBSCRIPTION_ID"]; +@EmptyLine +const token = ""; +const creds = new msRest.TokenCredentials(token); +const client = new @(Model.Name)(creds, subscriptionId); +@(Model.GenerateSampleMethod(true)).catch((err) => { + console.log('An error ocurred:'); + console.dir(err, {depth: null, colors: true}); +}); +``` +@EmptyLine +### browser - Authentication, client creation and @(Model.GetSampleMethod().Name) @(Model.GetSampleMethodGroupName()) as an example written in javascript. +@EmptyLine +- index.html +```html +@{ +@: +@: +@: +@: My Todos +@: +@: +@: +@: +@: +@: +@: +} +``` +@EmptyLine +# Related projects + - [Microsoft Azure SDK for Javascript](https://github.com/Azure/azure-sdk-for-js)