UNPKG

12.6 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.ContractSerializer = void 0;
4/**
5* Module for handling serialization and deserialization of data contracts
6* (contracts sent from the server using the VSO default REST api serialization settings)
7*/
8var ContractSerializer;
9(function (ContractSerializer) {
10 var _legacyDateRegExp;
11 /**
12 * Process a contract in its raw form (e.g. date fields are Dates, and Enums are numbers) and
13 * return a pure JSON object that can be posted to REST endpoint.
14 *
15 * @param data The object to serialize
16 * @param contractMetadata The type info/metadata for the contract type being serialized
17 * @param preserveOriginal If true, don't modify the original object. False modifies the original object (the return value points to the data argument).
18 */
19 function serialize(data, contractMetadata, preserveOriginal) {
20 if (data && contractMetadata) {
21 if (Array.isArray(data)) {
22 return _getTranslatedArray(data, contractMetadata, true, preserveOriginal);
23 }
24 else {
25 return _getTranslatedObject(data, contractMetadata, true, preserveOriginal);
26 }
27 }
28 else {
29 return data;
30 }
31 }
32 ContractSerializer.serialize = serialize;
33 /**
34 * Process a pure JSON object (e.g. that came from a REST call) and transform it into a JS object
35 * where date strings are converted to Date objects and enum values are converted from strings into
36 * their numerical value.
37 *
38 * @param data The object to deserialize
39 * @param contractMetadata The type info/metadata for the contract type being deserialize
40 * @param preserveOriginal If true, don't modify the original object. False modifies the original object (the return value points to the data argument).
41 * @param unwrapWrappedCollections If true check for wrapped arrays (REST apis will not return arrays directly as the root result but will instead wrap them in a { values: [], count: 0 } object.
42 */
43 function deserialize(data, contractMetadata, preserveOriginal, unwrapWrappedCollections) {
44 if (data) {
45 if (unwrapWrappedCollections && Array.isArray(data.value)) {
46 // Wrapped json array - unwrap it and send the array as the result
47 data = data.value;
48 }
49 if (contractMetadata) {
50 if (Array.isArray(data)) {
51 data = _getTranslatedArray(data, contractMetadata, false, preserveOriginal);
52 }
53 else {
54 data = _getTranslatedObject(data, contractMetadata, false, preserveOriginal);
55 }
56 }
57 }
58 return data;
59 }
60 ContractSerializer.deserialize = deserialize;
61 function _getTranslatedArray(array, typeMetadata, serialize, preserveOriginal) {
62 var resultArray = array;
63 var arrayCopy = [];
64 var i;
65 for (i = 0; i < array.length; i++) {
66 var item = array[i];
67 var processedItem;
68 // handle arrays of arrays
69 if (Array.isArray(item)) {
70 processedItem = _getTranslatedArray(item, typeMetadata, serialize, preserveOriginal);
71 }
72 else {
73 processedItem = _getTranslatedObject(item, typeMetadata, serialize, preserveOriginal);
74 }
75 if (preserveOriginal) {
76 arrayCopy.push(processedItem);
77 if (processedItem !== item) {
78 resultArray = arrayCopy;
79 }
80 }
81 else {
82 array[i] = processedItem;
83 }
84 }
85 return resultArray;
86 }
87 function _getTranslatedObject(typeObject, typeMetadata, serialize, preserveOriginal) {
88 var processedItem = typeObject, copiedItem = false;
89 if (typeObject && typeMetadata.fields) {
90 for (var fieldName in typeMetadata.fields) {
91 var fieldMetadata = typeMetadata.fields[fieldName];
92 var fieldValue = typeObject[fieldName];
93 var translatedValue = _getTranslatedField(fieldValue, fieldMetadata, serialize, preserveOriginal);
94 if (fieldValue !== translatedValue) {
95 if (preserveOriginal && !copiedItem) {
96 processedItem = this._extend({}, typeObject);
97 copiedItem = true;
98 }
99 processedItem[fieldName] = translatedValue;
100 }
101 }
102 }
103 return processedItem;
104 }
105 function _getTranslatedField(fieldValue, fieldMetadata, serialize, preserveOriginal) {
106 if (!fieldValue) {
107 return fieldValue;
108 }
109 if (fieldMetadata.isArray) {
110 if (Array.isArray(fieldValue)) {
111 var newArray = [], processedArray = fieldValue;
112 for (var index = 0; index < fieldValue.length; index++) {
113 var arrayValue = fieldValue[index];
114 var processedValue = arrayValue;
115 if (fieldMetadata.isDate) {
116 processedValue = _getTranslatedDateValue(arrayValue, serialize);
117 }
118 else if (fieldMetadata.enumType) {
119 processedValue = _getTranslatedEnumValue(fieldMetadata.enumType, arrayValue, serialize);
120 }
121 else if (fieldMetadata.typeInfo) {
122 if (Array.isArray(arrayValue)) {
123 processedValue = _getTranslatedArray(arrayValue, fieldMetadata.typeInfo, serialize, preserveOriginal);
124 }
125 else {
126 processedValue = _getTranslatedObject(arrayValue, fieldMetadata.typeInfo, serialize, preserveOriginal);
127 }
128 }
129 if (preserveOriginal) {
130 newArray.push(processedValue);
131 if (processedValue !== arrayValue) {
132 processedArray = newArray;
133 }
134 }
135 else {
136 fieldValue[index] = processedValue;
137 }
138 }
139 return processedArray;
140 }
141 else {
142 return fieldValue;
143 }
144 }
145 else if (fieldMetadata.isDictionary) {
146 var dictionaryModified = false;
147 var newDictionary = {};
148 for (var key in fieldValue) {
149 var dictionaryValue = fieldValue[key];
150 var newKey = key, newValue = dictionaryValue;
151 if (fieldMetadata.dictionaryKeyIsDate) {
152 newKey = _getTranslatedDateValue(key, serialize);
153 }
154 else if (fieldMetadata.dictionaryKeyEnumType) {
155 newKey = _getTranslatedEnumValue(fieldMetadata.dictionaryKeyEnumType, key, serialize);
156 }
157 if (fieldMetadata.dictionaryValueIsDate) {
158 newValue = _getTranslatedDateValue(dictionaryValue, serialize);
159 }
160 else if (fieldMetadata.dictionaryValueEnumType) {
161 newValue = _getTranslatedEnumValue(fieldMetadata.dictionaryValueEnumType, dictionaryValue, serialize);
162 }
163 else if (fieldMetadata.dictionaryValueTypeInfo) {
164 newValue = _getTranslatedObject(newValue, fieldMetadata.dictionaryValueTypeInfo, serialize, preserveOriginal);
165 }
166 else if (fieldMetadata.dictionaryValueFieldInfo) {
167 newValue = _getTranslatedField(dictionaryValue, fieldMetadata.dictionaryValueFieldInfo, serialize, preserveOriginal);
168 }
169 newDictionary[newKey] = newValue;
170 if (key !== newKey || dictionaryValue !== newValue) {
171 dictionaryModified = true;
172 }
173 }
174 return dictionaryModified ? newDictionary : fieldValue;
175 }
176 else {
177 if (fieldMetadata.isDate) {
178 return _getTranslatedDateValue(fieldValue, serialize);
179 }
180 else if (fieldMetadata.enumType) {
181 return _getTranslatedEnumValue(fieldMetadata.enumType, fieldValue, serialize);
182 }
183 else if (fieldMetadata.typeInfo) {
184 return _getTranslatedObject(fieldValue, fieldMetadata.typeInfo, serialize, preserveOriginal);
185 }
186 else {
187 return fieldValue;
188 }
189 }
190 }
191 function _getTranslatedEnumValue(enumType, valueToConvert, serialize) {
192 if (serialize && typeof valueToConvert === "number") {
193 // Serialize: number --> String
194 // Because webapi handles the numerical value for enums, there is no need to convert to string.
195 // Let this fall through to return the numerical value.
196 }
197 else if (!serialize && typeof valueToConvert === "string") {
198 // Deserialize: String --> number
199 var result = 0;
200 if (valueToConvert) {
201 var splitValue = valueToConvert.split(",");
202 for (var i = 0; i < splitValue.length; i++) {
203 var valuePart = splitValue[i];
204 //equivalent to jquery trim
205 //copied from https://github.com/HubSpot/youmightnotneedjquery/blob/ef987223c20e480fcbfb5924d96c11cd928e1226/comparisons/utils/trim/ie8.js
206 var enumName = valuePart.replace(/^\s+|\s+$/g, '') || "";
207 if (enumName) {
208 var resultPart = enumType.enumValues[enumName];
209 if (!resultPart) {
210 // No matching enum value. Try again but case insensitive
211 var lowerCaseEnumName = enumName.toLowerCase();
212 if (lowerCaseEnumName !== enumName) {
213 for (var name in enumType.enumValues) {
214 var value = enumType.enumValues[name];
215 if (name.toLowerCase() === lowerCaseEnumName) {
216 resultPart = value;
217 break;
218 }
219 }
220 }
221 }
222 if (resultPart) {
223 result |= resultPart;
224 }
225 }
226 }
227 }
228 return result;
229 }
230 return valueToConvert;
231 }
232 function _getTranslatedDateValue(valueToConvert, serialize) {
233 if (!serialize && typeof valueToConvert === "string") {
234 // Deserialize: String --> Date
235 var dateValue = new Date(valueToConvert);
236 if (isNaN(dateValue) && navigator.userAgent && /msie/i.test(navigator.userAgent)) {
237 dateValue = _convertLegacyIEDate(valueToConvert);
238 }
239 return dateValue;
240 }
241 return valueToConvert;
242 }
243 function _convertLegacyIEDate(dateStringValue) {
244 // IE 8/9 does not handle parsing dates in ISO form like:
245 // 2013-05-13T14:26:54.397Z
246 var match;
247 if (!_legacyDateRegExp) {
248 _legacyDateRegExp = new RegExp("(\\d+)-(\\d+)-(\\d+)T(\\d+):(\\d+):(\\d+).(\\d+)Z");
249 }
250 match = _legacyDateRegExp.exec(dateStringValue);
251 if (match) {
252 return new Date(Date.UTC(parseInt(match[1]), parseInt(match[2]) - 1, parseInt(match[3]), parseInt(match[4]), parseInt(match[5]), parseInt(match[6]), parseInt(match[7])));
253 }
254 else {
255 return null;
256 }
257 }
258 // jquery extend method in native javascript (used to clone objects)
259 // copied from https://github.com/HubSpot/youmightnotneedjquery/blob/ef987223c20e480fcbfb5924d96c11cd928e1226/comparisons/utils/extend/ie8.js
260 var _extend = function (out) {
261 out = out || {};
262 for (var i = 1; i < arguments.length; i++) {
263 if (!arguments[i])
264 continue;
265 for (var key in arguments[i]) {
266 if (arguments[i].hasOwnProperty(key))
267 out[key] = arguments[i][key];
268 }
269 }
270 return out;
271 };
272})(ContractSerializer = exports.ContractSerializer || (exports.ContractSerializer = {}));