From 37a536990d655307b3deb44d4f3de78eee4935de Mon Sep 17 00:00:00 2001 From: Amar Zavery Date: Fri, 29 Apr 2016 16:51:42 -0700 Subject: [PATCH] UnixTime in node.js (#987) * Enhancement to x-ms-parameterized-host extension * positionInOperation defaults to first * fixed setting default value for a complex object containing constant properties. * result of executing gulp regenerate:expected * Fixed fxcop warnings * remove null check validation for unixtime as they are treated as long in java * unixTime in node.js * modification * UnixTime tests * FxCop warnings --- .../AcceptanceTests/acceptanceTests.ts | 30 +++++++++++++++++++ .../BodyInteger/operations/index.d.ts | 18 +++++------ .../BodyInteger/operations/intModel.js | 23 +++++++------- .../operations/index.d.ts | 18 +++++------ .../operations/intModel.js | 23 +++++++------- .../AcceptanceTests/Url/operations/index.d.ts | 6 ++-- .../AcceptanceTests/Url/operations/paths.js | 11 +++---- .../NodeJS/NodeJS/ClientModelExtensions.cs | 26 +++++++++++----- .../NodeJS/NodeJS/GlobalSuppressions.cs | 1 + .../NodeJS/NodeJS/NodeJsCodeNamer.cs | 8 ++--- ClientRuntimes/NodeJS/ms-rest/README.md | 3 +- .../NodeJS/ms-rest/lib/serialization.js | 30 +++++++++++++++++-- .../NodeJS/ms-rest/test/serializationTests.js | 6 ++++ 13 files changed, 141 insertions(+), 62 deletions(-) diff --git a/AutoRest/Generators/NodeJS/NodeJS.Tests/AcceptanceTests/acceptanceTests.ts b/AutoRest/Generators/NodeJS/NodeJS.Tests/AcceptanceTests/acceptanceTests.ts index 0a81b34200..db5042f716 100644 --- a/AutoRest/Generators/NodeJS/NodeJS.Tests/AcceptanceTests/acceptanceTests.ts +++ b/AutoRest/Generators/NodeJS/NodeJS.Tests/AcceptanceTests/acceptanceTests.ts @@ -199,6 +199,29 @@ describe('nodejs', function () { }); }); }); + + it('should put and get UnixTime date correctly', function (done) { + var d = new Date('2016-04-13T00:00:00.000Z'); + testClient.intModel.putUnixTimeDate(d, function (error, result) { + should.not.exist(error); + testClient.intModel.getUnixTime(function (error, result) { + should.not.exist(error); + assert.deepEqual(result, d); + done(); + }); + }); + }); + + it('should throw an error for invalid UnixTime date anf get null value for UnixTime', function (done) { + testClient.intModel.getInvalidUnixTime(function (error, result) { + should.exist(error); + testClient.intModel.getNullUnixTime(function (error, result) { + should.not.exist(error); + should.not.exist(result); + done(); + }); + }); + }); }); describe('CompositeBoolInt Client', function () { @@ -1891,6 +1914,13 @@ describe('nodejs', function () { }); }); + it('should work when path has a paramaeter in UnixTime format', function (done) { + testClient.paths.unixTimeUrl(new Date('2016-04-13T00:00:00.000Z'), function (error, result) { + should.not.exist(error); + done(); + }); + }); + it('should work when path has datetime', function (done) { testClient.paths.dateTimeValid(new Date('2012-01-01T01:01:01Z'), function (error, result) { should.not.exist(error); diff --git a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/BodyInteger/operations/index.d.ts b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/BodyInteger/operations/index.d.ts index 1b00b43d81..6fddcb9d06 100644 --- a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/BodyInteger/operations/index.d.ts +++ b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/BodyInteger/operations/index.d.ts @@ -179,13 +179,13 @@ export interface IntModel { * @param {ServiceCallback} [callback] callback function; see ServiceCallback * doc in ms-rest index.d.ts for details */ - getUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; - getUnixTime(callback: ServiceCallback): void; + getUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; + getUnixTime(callback: ServiceCallback): void; /** * Put datetime encoded as Unix time * - * @param {number} intBody + * @param {date} intBody * * @param {object} [options] Optional Parameters. * @@ -195,8 +195,8 @@ export interface IntModel { * @param {ServiceCallback} [callback] callback function; see ServiceCallback * doc in ms-rest index.d.ts for details */ - putUnixTimeDate(intBody: number, options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; - putUnixTimeDate(intBody: number, callback: ServiceCallback): void; + putUnixTimeDate(intBody: Date, options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; + putUnixTimeDate(intBody: Date, callback: ServiceCallback): void; /** * Get invalid Unix time value @@ -209,8 +209,8 @@ export interface IntModel { * @param {ServiceCallback} [callback] callback function; see ServiceCallback * doc in ms-rest index.d.ts for details */ - getInvalidUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; - getInvalidUnixTime(callback: ServiceCallback): void; + getInvalidUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; + getInvalidUnixTime(callback: ServiceCallback): void; /** * Get null Unix time value @@ -223,6 +223,6 @@ export interface IntModel { * @param {ServiceCallback} [callback] callback function; see ServiceCallback * doc in ms-rest index.d.ts for details */ - getNullUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; - getNullUnixTime(callback: ServiceCallback): void; + getNullUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; + getNullUnixTime(callback: ServiceCallback): void; } diff --git a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/BodyInteger/operations/intModel.js b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/BodyInteger/operations/intModel.js index b1ed3fbf47..290a93e9b3 100644 --- a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/BodyInteger/operations/intModel.js +++ b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/BodyInteger/operations/intModel.js @@ -1210,7 +1210,7 @@ IntModel.prototype.putMin64 = function (intBody, options, callback) { * * {Error} err - The Error object if an error occurred, null otherwise. * - * {number} [result] - The deserialized result object. + * {date} [result] - The deserialized result object. * * {object} [request] - The HTTP Request object if an error did not occur. * @@ -1293,7 +1293,7 @@ IntModel.prototype.getUnixTime = function (options, callback) { required: false, serializedName: 'parsedResponse', type: { - name: 'Number' + name: 'UnixTime' } }; result = client.deserialize(resultMapper, parsedResponse, 'result'); @@ -1313,7 +1313,7 @@ IntModel.prototype.getUnixTime = function (options, callback) { /** * Put datetime encoded as Unix time * - * @param {number} intBody + * @param {date} intBody * * @param {object} [options] Optional Parameters. * @@ -1343,9 +1343,10 @@ IntModel.prototype.putUnixTimeDate = function (intBody, options, callback) { } // Validate try { - if (intBody === null || intBody === undefined || typeof intBody !== 'number') { - throw new Error('intBody cannot be null or undefined and it must be of type number.'); - } + if(!intBody || !(intBody instanceof Date || + (typeof intBody.valueOf() === 'string' && !isNaN(Date.parse(intBody))))) { + throw new Error('intBody cannot be null or undefined and it must be of type date.'); + } } catch (error) { return callback(error); } @@ -1380,7 +1381,7 @@ IntModel.prototype.putUnixTimeDate = function (intBody, options, callback) { required: true, serializedName: 'intBody', type: { - name: 'Number' + name: 'UnixTime' } }; requestModel = client.serialize(requestModelMapper, intBody, 'intBody'); @@ -1445,7 +1446,7 @@ IntModel.prototype.putUnixTimeDate = function (intBody, options, callback) { * * {Error} err - The Error object if an error occurred, null otherwise. * - * {number} [result] - The deserialized result object. + * {date} [result] - The deserialized result object. * * {object} [request] - The HTTP Request object if an error did not occur. * @@ -1528,7 +1529,7 @@ IntModel.prototype.getInvalidUnixTime = function (options, callback) { required: false, serializedName: 'parsedResponse', type: { - name: 'Number' + name: 'UnixTime' } }; result = client.deserialize(resultMapper, parsedResponse, 'result'); @@ -1559,7 +1560,7 @@ IntModel.prototype.getInvalidUnixTime = function (options, callback) { * * {Error} err - The Error object if an error occurred, null otherwise. * - * {number} [result] - The deserialized result object. + * {date} [result] - The deserialized result object. * * {object} [request] - The HTTP Request object if an error did not occur. * @@ -1642,7 +1643,7 @@ IntModel.prototype.getNullUnixTime = function (options, callback) { required: false, serializedName: 'parsedResponse', type: { - name: 'Number' + name: 'UnixTime' } }; result = client.deserialize(resultMapper, parsedResponse, 'result'); diff --git a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/CompositeBoolIntClient/operations/index.d.ts b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/CompositeBoolIntClient/operations/index.d.ts index ac60442293..507488a58f 100644 --- a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/CompositeBoolIntClient/operations/index.d.ts +++ b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/CompositeBoolIntClient/operations/index.d.ts @@ -276,13 +276,13 @@ export interface IntModel { * @param {ServiceCallback} [callback] callback function; see ServiceCallback * doc in ms-rest index.d.ts for details */ - getUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; - getUnixTime(callback: ServiceCallback): void; + getUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; + getUnixTime(callback: ServiceCallback): void; /** * Put datetime encoded as Unix time * - * @param {number} intBody + * @param {date} intBody * * @param {object} [options] Optional Parameters. * @@ -292,8 +292,8 @@ export interface IntModel { * @param {ServiceCallback} [callback] callback function; see ServiceCallback * doc in ms-rest index.d.ts for details */ - putUnixTimeDate(intBody: number, options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; - putUnixTimeDate(intBody: number, callback: ServiceCallback): void; + putUnixTimeDate(intBody: Date, options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; + putUnixTimeDate(intBody: Date, callback: ServiceCallback): void; /** * Get invalid Unix time value @@ -306,8 +306,8 @@ export interface IntModel { * @param {ServiceCallback} [callback] callback function; see ServiceCallback * doc in ms-rest index.d.ts for details */ - getInvalidUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; - getInvalidUnixTime(callback: ServiceCallback): void; + getInvalidUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; + getInvalidUnixTime(callback: ServiceCallback): void; /** * Get null Unix time value @@ -320,6 +320,6 @@ export interface IntModel { * @param {ServiceCallback} [callback] callback function; see ServiceCallback * doc in ms-rest index.d.ts for details */ - getNullUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; - getNullUnixTime(callback: ServiceCallback): void; + getNullUnixTime(options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; + getNullUnixTime(callback: ServiceCallback): void; } diff --git a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/CompositeBoolIntClient/operations/intModel.js b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/CompositeBoolIntClient/operations/intModel.js index 42f1d72ab3..d00f8cb625 100644 --- a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/CompositeBoolIntClient/operations/intModel.js +++ b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/CompositeBoolIntClient/operations/intModel.js @@ -1210,7 +1210,7 @@ IntModel.prototype.putMin64 = function (intBody, options, callback) { * * {Error} err - The Error object if an error occurred, null otherwise. * - * {number} [result] - The deserialized result object. + * {date} [result] - The deserialized result object. * * {object} [request] - The HTTP Request object if an error did not occur. * @@ -1293,7 +1293,7 @@ IntModel.prototype.getUnixTime = function (options, callback) { required: false, serializedName: 'parsedResponse', type: { - name: 'Number' + name: 'UnixTime' } }; result = client.deserialize(resultMapper, parsedResponse, 'result'); @@ -1313,7 +1313,7 @@ IntModel.prototype.getUnixTime = function (options, callback) { /** * Put datetime encoded as Unix time * - * @param {number} intBody + * @param {date} intBody * * @param {object} [options] Optional Parameters. * @@ -1343,9 +1343,10 @@ IntModel.prototype.putUnixTimeDate = function (intBody, options, callback) { } // Validate try { - if (intBody === null || intBody === undefined || typeof intBody !== 'number') { - throw new Error('intBody cannot be null or undefined and it must be of type number.'); - } + if(!intBody || !(intBody instanceof Date || + (typeof intBody.valueOf() === 'string' && !isNaN(Date.parse(intBody))))) { + throw new Error('intBody cannot be null or undefined and it must be of type date.'); + } } catch (error) { return callback(error); } @@ -1380,7 +1381,7 @@ IntModel.prototype.putUnixTimeDate = function (intBody, options, callback) { required: true, serializedName: 'intBody', type: { - name: 'Number' + name: 'UnixTime' } }; requestModel = client.serialize(requestModelMapper, intBody, 'intBody'); @@ -1445,7 +1446,7 @@ IntModel.prototype.putUnixTimeDate = function (intBody, options, callback) { * * {Error} err - The Error object if an error occurred, null otherwise. * - * {number} [result] - The deserialized result object. + * {date} [result] - The deserialized result object. * * {object} [request] - The HTTP Request object if an error did not occur. * @@ -1528,7 +1529,7 @@ IntModel.prototype.getInvalidUnixTime = function (options, callback) { required: false, serializedName: 'parsedResponse', type: { - name: 'Number' + name: 'UnixTime' } }; result = client.deserialize(resultMapper, parsedResponse, 'result'); @@ -1559,7 +1560,7 @@ IntModel.prototype.getInvalidUnixTime = function (options, callback) { * * {Error} err - The Error object if an error occurred, null otherwise. * - * {number} [result] - The deserialized result object. + * {date} [result] - The deserialized result object. * * {object} [request] - The HTTP Request object if an error did not occur. * @@ -1642,7 +1643,7 @@ IntModel.prototype.getNullUnixTime = function (options, callback) { required: false, serializedName: 'parsedResponse', type: { - name: 'Number' + name: 'UnixTime' } }; result = client.deserialize(resultMapper, parsedResponse, 'result'); diff --git a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/Url/operations/index.d.ts b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/Url/operations/index.d.ts index 3f5e246438..36fd5ba34f 100644 --- a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/Url/operations/index.d.ts +++ b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/Url/operations/index.d.ts @@ -398,7 +398,7 @@ export interface Paths { /** * Get the date 2016-04-13 encoded value as '1460505600' (Unix time) * - * @param {number} unixTimeUrlPath Unix time encoded value + * @param {date} unixTimeUrlPath Unix time encoded value * * @param {object} [options] Optional Parameters. * @@ -408,8 +408,8 @@ export interface Paths { * @param {ServiceCallback} [callback] callback function; see ServiceCallback * doc in ms-rest index.d.ts for details */ - unixTimeUrl(unixTimeUrlPath: number, options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; - unixTimeUrl(unixTimeUrlPath: number, callback: ServiceCallback): void; + unixTimeUrl(unixTimeUrlPath: Date, options: { customHeaders? : { [headerName: string]: string; } }, callback: ServiceCallback): void; + unixTimeUrl(unixTimeUrlPath: Date, callback: ServiceCallback): void; } /** diff --git a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/Url/operations/paths.js b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/Url/operations/paths.js index 4039b0ce96..2b5ff16d6b 100644 --- a/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/Url/operations/paths.js +++ b/AutoRest/Generators/NodeJS/NodeJS.Tests/Expected/AcceptanceTests/Url/operations/paths.js @@ -2461,7 +2461,7 @@ Paths.prototype.arrayCsvInPath = function (arrayPath, options, callback) { /** * Get the date 2016-04-13 encoded value as '1460505600' (Unix time) * - * @param {number} unixTimeUrlPath Unix time encoded value + * @param {date} unixTimeUrlPath Unix time encoded value * * @param {object} [options] Optional Parameters. * @@ -2491,9 +2491,10 @@ Paths.prototype.unixTimeUrl = function (unixTimeUrlPath, options, callback) { } // Validate try { - if (unixTimeUrlPath === null || unixTimeUrlPath === undefined || typeof unixTimeUrlPath !== 'number') { - throw new Error('unixTimeUrlPath cannot be null or undefined and it must be of type number.'); - } + if(!unixTimeUrlPath || !(unixTimeUrlPath instanceof Date || + (typeof unixTimeUrlPath.valueOf() === 'string' && !isNaN(Date.parse(unixTimeUrlPath))))) { + throw new Error('unixTimeUrlPath cannot be null or undefined and it must be of type date.'); + } } catch (error) { return callback(error); } @@ -2501,7 +2502,7 @@ Paths.prototype.unixTimeUrl = function (unixTimeUrlPath, options, callback) { // Construct URL var requestUrl = this.client.baseUri + '//paths/int/1460505600/{unixTimeUrlPath}'; - requestUrl = requestUrl.replace('{unixTimeUrlPath}', encodeURIComponent(unixTimeUrlPath.toString())); + requestUrl = requestUrl.replace('{unixTimeUrlPath}', encodeURIComponent(client.serialize({required: true, serializedName: 'unixTimeUrlPath', type: {name: 'UnixTime'}}, unixTimeUrlPath, 'unixTimeUrlPath'))); // trim all duplicate forward slashes in the url var regex = /([^:]\/)\/+/gi; requestUrl = requestUrl.replace(regex, '$1'); diff --git a/AutoRest/Generators/NodeJS/NodeJS/ClientModelExtensions.cs b/AutoRest/Generators/NodeJS/NodeJS/ClientModelExtensions.cs index 8f36adeec8..ba3a24c17b 100644 --- a/AutoRest/Generators/NodeJS/NodeJS/ClientModelExtensions.cs +++ b/AutoRest/Generators/NodeJS/NodeJS/ClientModelExtensions.cs @@ -131,6 +131,12 @@ public static string ToString(this IType type, string reference) return string.Format(CultureInfo.InvariantCulture, "client.serialize({{required: true, serializedName: '{0}', type: {{name: 'Base64Url'}}}}, {0}, '{0}')", reference); } + + if (known.Type == KnownPrimaryType.UnixTime) + { + return string.Format(CultureInfo.InvariantCulture, + "client.serialize({{required: true, serializedName: '{0}', type: {{name: 'UnixTime'}}}}, {0}, '{0}')", reference); + } } return string.Format(CultureInfo.InvariantCulture, "{0}.toString()", reference); @@ -195,8 +201,7 @@ private static string ValidatePrimaryType(this PrimaryType primary, IScopeProvid primary.Type == KnownPrimaryType.Decimal || primary.Type == KnownPrimaryType.Int || primary.Type == KnownPrimaryType.Long || - primary.Type == KnownPrimaryType.Object || - primary.Type == KnownPrimaryType.UnixTime) + primary.Type == KnownPrimaryType.Object) { if (isRequired) { @@ -254,7 +259,8 @@ private static string ValidatePrimaryType(this PrimaryType primary, IScopeProvid builder.AppendLine("if ({0} && !Buffer.isBuffer({0})) {{", valueReference, lowercaseTypeName); return ConstructValidationCheck(builder, typeErrorMessage, valueReference, primary.Name).ToString(); } - else if (primary.Type == KnownPrimaryType.DateTime || primary.Type == KnownPrimaryType.Date || primary.Type == KnownPrimaryType.DateTimeRfc1123) + else if (primary.Type == KnownPrimaryType.DateTime || primary.Type == KnownPrimaryType.Date || + primary.Type == KnownPrimaryType.DateTimeRfc1123 || primary.Type == KnownPrimaryType.UnixTime) { if (isRequired) { @@ -303,11 +309,13 @@ private static string PrimaryTSType(this PrimaryType primary) if (primary.Type == KnownPrimaryType.Boolean) return "boolean"; - else if (primary.Type == KnownPrimaryType.Double || primary.Type == KnownPrimaryType.Decimal || primary.Type == KnownPrimaryType.Int || primary.Type == KnownPrimaryType.Long || primary.Type == KnownPrimaryType.UnixTime) + else if (primary.Type == KnownPrimaryType.Double || primary.Type == KnownPrimaryType.Decimal || + primary.Type == KnownPrimaryType.Int || primary.Type == KnownPrimaryType.Long) return "number"; else if (primary.Type == KnownPrimaryType.String || primary.Type == KnownPrimaryType.Uuid) return "string"; - else if (primary.Type == KnownPrimaryType.Date || primary.Type == KnownPrimaryType.DateTime || primary.Type == KnownPrimaryType.DateTimeRfc1123) + else if (primary.Type == KnownPrimaryType.Date || primary.Type == KnownPrimaryType.DateTime || + primary.Type == KnownPrimaryType.DateTimeRfc1123 || primary.Type == KnownPrimaryType.UnixTime) return "Date"; else if (primary.Type == KnownPrimaryType.Object) return "any"; // TODO: test this @@ -747,8 +755,8 @@ public static string ConstructMapper(this IType type, string serializedName, IPa { builder.AppendLine("type: {").Indent().AppendLine("name: 'Boolean'").Outdent().AppendLine("}"); } - else if(primary.Type == KnownPrimaryType.Int || primary.Type == KnownPrimaryType.Long || primary.Type == KnownPrimaryType.Decimal || - primary.Type == KnownPrimaryType.Double || primary.Type == KnownPrimaryType.UnixTime) + else if (primary.Type == KnownPrimaryType.Int || primary.Type == KnownPrimaryType.Long || + primary.Type == KnownPrimaryType.Decimal || primary.Type == KnownPrimaryType.Double) { builder.AppendLine("type: {").Indent().AppendLine("name: 'Number'").Outdent().AppendLine("}"); } @@ -784,6 +792,10 @@ public static string ConstructMapper(this IType type, string serializedName, IPa { builder.AppendLine("type: {").Indent().AppendLine("name: 'TimeSpan'").Outdent().AppendLine("}"); } + else if (primary.Type == KnownPrimaryType.UnixTime) + { + builder.AppendLine("type: {").Indent().AppendLine("name: 'UnixTime'").Outdent().AppendLine("}"); + } else if (primary.Type == KnownPrimaryType.Object) { builder.AppendLine("type: {").Indent().AppendLine("name: 'Object'").Outdent().AppendLine("}"); diff --git a/AutoRest/Generators/NodeJS/NodeJS/GlobalSuppressions.cs b/AutoRest/Generators/NodeJS/NodeJS/GlobalSuppressions.cs index a0c9b570f4..9fecaab118 100644 --- a/AutoRest/Generators/NodeJS/NodeJS/GlobalSuppressions.cs +++ b/AutoRest/Generators/NodeJS/NodeJS/GlobalSuppressions.cs @@ -193,4 +193,5 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "readOnly", Scope = "member", Target = "Microsoft.Rest.Generator.NodeJS.TemplateModels.ClientModelExtensions.#ConstructMapper(Microsoft.Rest.Generator.ClientModel.IType,System.String,Microsoft.Rest.Generator.ClientModel.IParameter,System.Boolean,System.Boolean)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Rest.Generator.NodeJS.TemplateModels.ClientModelExtensions.#ValidatePrimaryType(Microsoft.Rest.Generator.ClientModel.PrimaryType,Microsoft.Rest.Generator.Utilities.IScopeProvider,System.String,System.Boolean)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode", Scope = "member", Target = "Microsoft.Rest.Generator.NodeJS.TemplateModels.ClientModelExtensions.#ConstructMapper(Microsoft.Rest.Generator.ClientModel.IType,System.String,Microsoft.Rest.Generator.ClientModel.IParameter,System.Boolean,System.Boolean)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "UnixTime", Scope = "member", Target = "Microsoft.Rest.Generator.NodeJS.TemplateModels.ClientModelExtensions.#ConstructMapper(Microsoft.Rest.Generator.ClientModel.IType,System.String,Microsoft.Rest.Generator.ClientModel.IParameter,System.Boolean,System.Boolean)")] diff --git a/AutoRest/Generators/NodeJS/NodeJS/NodeJsCodeNamer.cs b/AutoRest/Generators/NodeJS/NodeJS/NodeJsCodeNamer.cs index d2f43a402f..2dc7c2f0ed 100644 --- a/AutoRest/Generators/NodeJS/NodeJS/NodeJsCodeNamer.cs +++ b/AutoRest/Generators/NodeJS/NodeJS/NodeJsCodeNamer.cs @@ -365,6 +365,10 @@ private static IType NormalizePrimaryType(PrimaryType primaryType) { primaryType.Name = "Date"; } + else if (primaryType.Type == KnownPrimaryType.UnixTime) + { + primaryType.Name = "Date"; + } else if (primaryType.Type == KnownPrimaryType.Double) { primaryType.Name = "Number"; @@ -393,10 +397,6 @@ private static IType NormalizePrimaryType(PrimaryType primaryType) { primaryType.Name = "moment.duration"; } - else if (primaryType.Type == KnownPrimaryType.UnixTime) - { - primaryType.Name = "Number"; - } else if (primaryType.Type == KnownPrimaryType.Uuid) { primaryType.Name = "Uuid"; diff --git a/ClientRuntimes/NodeJS/ms-rest/README.md b/ClientRuntimes/NodeJS/ms-rest/README.md index cb4aca73ab..1da52bff1a 100644 --- a/ClientRuntimes/NodeJS/ms-rest/README.md +++ b/ClientRuntimes/NodeJS/ms-rest/README.md @@ -18,7 +18,7 @@ var msrest = require('ms-rest'); ## Serialization/Deserialization Features - Type checking - - (String, Number, Boolean, ByteArray, Date, DateTime, Enum, TimeSpan, DateTimeRfc1123, Object, Stream, Sequence, Dictionary, Composite, Uuid(as a string)) + - (String, Number, Boolean, ByteArray, Base64Url, Date, DateTime, Enum, TimeSpan, DateTimeRfc1123, UnixTime, Object, Stream, Sequence, Dictionary, Composite, Uuid(as a string)) - Validation of specified constraints - ExclusiveMaximum, ExclusiveMinimum, InclusiveMaximum, InclusiveMinimum, MaxItems, MaxLength, MinItems, MinLength, MultipleOf, Pattern, UniqueItems - Flattening/Unflattening properties @@ -26,6 +26,7 @@ Features - Model Properties marked as constant are set during serialization, irrespective of they being provided or not - Required check (If a model or property is marked required and is not provided in the object then an error is thrown) - Readonly check (If a model or property is marked readonly then it is not sent on the wire during, serialization) +- Serializing Constant values - serialize an array of dictionary of primitive values ```javascript diff --git a/ClientRuntimes/NodeJS/ms-rest/lib/serialization.js b/ClientRuntimes/NodeJS/ms-rest/lib/serialization.js index de8d0778ef..671292b9f4 100644 --- a/ClientRuntimes/NodeJS/ms-rest/lib/serialization.js +++ b/ClientRuntimes/NodeJS/ms-rest/lib/serialization.js @@ -74,7 +74,7 @@ exports.serialize = function (mapper, object, objectName) { payload = serializeBasicTypes.call(this, mapperType, objectName, object); } else if (mapperType.match(/^Enum$/ig) !== null) { payload = serializeEnumType.call(this, objectName, mapper.type.allowedValues, object); - } else if (mapperType.match(/^(Date|DateTime|TimeSpan|DateTimeRfc1123)$/ig) !== null) { + } else if (mapperType.match(/^(Date|DateTime|TimeSpan|DateTimeRfc1123|UnixTime)$/ig) !== null) { payload = serializeDateTypes.call(this, mapperType, object, objectName); } else if (mapperType.match(/^ByteArray$/ig) !== null) { payload = serializeBufferType.call(this, objectName, object); @@ -370,6 +370,13 @@ function serializeDateTypes(typeName, value, objectName) { throw new Error(util.format('%s must be an instanceof Date or a string in RFC-1123 format.', objectName)); } value = (value instanceof Date) ? value.toUTCString() : new Date(value).toUTCString(); + } else if (typeName.match(/^UnixTime$/ig) !== null) { + if (!(value instanceof Date || + (typeof value.valueOf() === 'string' && !isNaN(Date.parse(value))))) { + throw new Error(util.format('%s must be an instanceof Date or a string in RFC-1123/ISO8601 format ' + + 'for it to be serialized in UnixTime/Epoch format.', objectName)); + } + value = dateToUnixTime(value); } else if (typeName.match(/^TimeSpan$/ig) !== null) { if (!moment.isDuration(value)) { throw new Error(util.format('%s must be a TimeSpan/Duration.', objectName)); @@ -402,8 +409,10 @@ exports.deserialize = function (mapper, responseBody, objectName) { payload = responseBody; } else if (mapperType.match(/^(Date|DateTime|DateTimeRfc1123)$/ig) !== null) { payload = new Date(responseBody); - } else if (mapperType.match(/^(TimeSpan)$/ig) !== null) { + } else if (mapperType.match(/^TimeSpan$/ig) !== null) { payload = moment.duration(responseBody); + } else if (mapperType.match(/^UnixTime$/ig) !== null) { + payload = unixTimeToDate(responseBody); } else if (mapperType.match(/^ByteArray$/ig) !== null) { payload = new Buffer(responseBody, 'base64'); } else if (mapperType.match(/^Base64Url$/ig) !== null) { @@ -595,4 +604,21 @@ function base64UrlToBuffer(str) { return new Buffer(str, 'base64'); } +function dateToUnixTime(d) { + if (!d) { + return null; + } + if (typeof d.valueOf() === 'string') { + d = new Date(d); + } + return parseInt(d.getTime() / 1000); +} + +function unixTimeToDate(n) { + if (!n) { + return null; + } + return new Date(n*1000); +} + exports = module.exports; \ No newline at end of file diff --git a/ClientRuntimes/NodeJS/ms-rest/test/serializationTests.js b/ClientRuntimes/NodeJS/ms-rest/test/serializationTests.js index d9be4bd39f..32c89671d3 100644 --- a/ClientRuntimes/NodeJS/ms-rest/test/serializationTests.js +++ b/ClientRuntimes/NodeJS/ms-rest/test/serializationTests.js @@ -195,6 +195,12 @@ describe('msrest', function () { serializedDateString.should.equal('+010000-01-01T11:59:59.000Z'); done(); }); + it('should correctly serialize a Date object with max value and format UnixTime', function (done) { + mapper = { type : { name: 'UnixTime' } }; + var serializedDate = msRest.serialize(mapper, new Date('9999-12-31T23:59:59-12:00'), 'dateTimeObj'); + serializedDate.should.equal(253402343999); + done(); + }); it('should correctly serialize a string in DateTimeRfc1123', function (done) { mapper = { type : { name: 'DateTimeRfc1123' } }; var rfc = new Date('Mon, 01 Jan 0001 00:00:00 GMT');