Skip to content

Commit c92d653

Browse files
committed
Fix strict value for date and number
1 parent 69a68f9 commit c92d653

2 files changed

Lines changed: 543 additions & 500 deletions

File tree

src/utils/parser.js

Lines changed: 65 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
"use strict";
1+
'use strict'
22

3-
const loGet = require("lodash/get");
4-
const loValues = require("lodash/values");
5-
const moment = require("moment");
6-
const detector = require("./detector");
7-
const extractMapKey = require("./mapkey_extractor");
3+
const loGet = require('lodash/get')
4+
const loValues = require('lodash/values')
5+
const nilValue = require('lodash/isNil')
6+
const moment = require('moment')
7+
const detector = require('./detector')
8+
const extractMapKey = require('./mapkey_extractor')
89
const {
910
STRING,
1011
STRING_ONLY,
@@ -27,70 +28,66 @@ const {
2728
nonNullableTypes,
2829
isPredefinedTypes,
2930
isDeleteProperty
30-
} = require("../datatypes");
31+
} = require('../datatypes')
32+
33+
const validDateFromString = (dateVal, utcAware = true) => {
34+
if (detector.isString(dateVal)) {
35+
try {
36+
// detect ISO 8601
37+
const date = utcAware ? moment(dateVal) : moment.utc(dateVal)
38+
if (date.isValid()) return date
39+
} catch (err) {
40+
return false
41+
}
42+
}
43+
return false
44+
}
3145

3246
const parser = {
3347
[STRING]: val => {
34-
if (detector.isString(val) && val.length) return val;
35-
const parsed = val ? JSON.stringify(val) : null;
36-
return detector.isString(parsed) && parsed.length > 0 ? parsed : null;
48+
if (detector.isString(val) && val.length) return val
49+
const parsed = val ? JSON.stringify(val) : null
50+
return detector.isString(parsed) && parsed.length > 0 ? parsed : null
3751
},
3852
[ARRAY]: val => (detector.isArray(val) ? val : null),
3953
[BOOLEAN]: val => (detector.isBoolean(val) ? val : null),
4054
[DATE]: val => {
41-
if (detector.isDate(val)) return val;
42-
if (detector.isString(val)) {
43-
try {
44-
// detect ISO 8601
45-
const date = moment(val);
46-
if (date.isValid()) return date;
47-
} catch (err) {
48-
return null;
49-
}
50-
}
51-
return null;
55+
if (detector.isDate(val)) return val
56+
return validDateFromString(val) || null
5257
},
5358
[DATE_PLAIN]: val => {
54-
if (detector.isDate(val)) return val;
55-
if (detector.isString(val)) {
56-
try {
57-
// detect ISO 8601
58-
const date = moment.utc(val); // unaware timezone, all parses with utc timezone
59-
if (date.isValid()) return date;
60-
} catch (err) {
61-
return null;
62-
}
63-
}
64-
return null;
59+
if (detector.isDate(val)) return val
60+
return validDateFromString(val, false) || null
6561
},
6662
[FUNCTION]: val => (detector.isFunction(val) ? val : null),
6763
[NUMBER]: val => {
68-
if (detector.isNumber(val)) return val;
64+
if (detector.isNumber(val)) return val
6965
if (!isNaN(val)) {
70-
return detector.isStringFloat(val) ? parseFloat(val) : parseInt(val);
66+
return detector.isStringFloat(val) ? parseFloat(val) : parseInt(val)
7167
}
72-
return null;
68+
return null
7369
},
7470
[OBJECT]: val => (detector.isObject ? val : null),
7571
[ANY]: val => val
76-
};
72+
}
7773

7874
const nonNullableChecker = {
7975
[STRING_ONLY]: val => detector.isString(val),
8076
[ARRAY_ONLY]: val => detector.isArray(val),
8177
[BOOLEAN_ONLY]: val => detector.isBoolean(val),
82-
[DATE_ONLY]: val => detector.isDate(val),
83-
[DATE_PLAIN_ONLY]: val => detector.isDate(val),
78+
[DATE_ONLY]: val => detector.isDate(val) || validDateFromString(val) !== null,
79+
[DATE_PLAIN_ONLY]: val =>
80+
detector.isDate(val) || validDateFromString(val, false) !== null,
8481
[FUNCTION_ONLY]: val => detector.isFunction(val),
8582
[NUMBER_ONLY]: val => {
8683
if (!isNaN(val)) {
87-
return detector.isStringFloat(val) ? parseFloat(val) : parseInt(val);
84+
return detector.isStringFloat(val) ? parseFloat(val) : parseInt(val)
8885
}
8986

90-
return false;
87+
return false
9188
},
9289
[OBJECT_ONLY]: val => detector.isObject(val)
93-
};
90+
}
9491

9592
const nonNullableParser = {
9693
[STRING_ONLY]: val => parser[STRING](val),
@@ -101,66 +98,67 @@ const nonNullableParser = {
10198
[FUNCTION_ONLY]: val => parser[FUNCTION](val),
10299
[NUMBER_ONLY]: val => parser[NUMBER](val),
103100
[OBJECT_ONLY]: val => parser[OBJECT](val)
104-
};
101+
}
105102

106103
const valueParser = (schema, valuesToParse) => {
107-
const parsedValues = {};
104+
const parsedValues = {}
108105
Object.keys(schema).forEach(key => {
109-
const valueType = schema[key];
110-
if (isDeleteProperty(valueType)) return;
106+
const valueType = schema[key]
107+
if (isDeleteProperty(valueType)) return
111108

112-
const [srcKey, mapKey] = extractMapKey(key);
113-
if (mapKey !== null) key = mapKey;
109+
const [srcKey, mapKey] = extractMapKey(key)
110+
if (mapKey !== null) key = mapKey
114111

115112
const value = detector.isUndefined(valuesToParse)
116113
? valuesToParse
117-
: valuesToParse[srcKey !== null ? srcKey : key];
114+
: valuesToParse[srcKey !== null ? srcKey : key]
118115

119116
if (!detector.isUndefined(value) || detector.isJKTObject(valueType)) {
120117
if (parserableTypes(valueType) && !detector.isJKTObject(valueType)) {
121-
parsedValues[key] = parser[valueType](value);
118+
parsedValues[key] = parser[valueType](value)
122119
} else if (detector.isJKTObject(valueType)) {
123120
// handle jkt obj
124-
parsedValues[key] = valueParser(valueType.__schema, value);
121+
parsedValues[key] = valueParser(valueType.__schema, value)
125122
} else if (detector.isENUMObject(valueType)) {
126123
// handle enum
127-
const validEnumValues = loValues(valueType.j());
128-
parsedValues[key] = validEnumValues.includes(value) ? value : null;
124+
const validEnumValues = loValues(valueType.j())
125+
parsedValues[key] = validEnumValues.includes(value) ? value : null
129126
} else if (detector.isTranslatorObject(valueType)) {
130127
// handle translator
131-
parsedValues[key] = valueType.translate(value);
128+
parsedValues[key] = valueType.translate(value)
132129
} else if (nonNullableTypes(valueType)) {
133-
if (nonNullableChecker[valueType](value))
134-
parsedValues[key] = nonNullableParser[valueType](value);
130+
if (!nilValue(nonNullableChecker[valueType](value))) {
131+
parsedValues[key] = nonNullableParser[valueType](value)
132+
}
135133
} else if (valueType.isContainer) {
136134
// struct inside of container
137-
parsedValues[key] = valueType.parse(valueParser, value);
135+
parsedValues[key] = valueType.parse(valueParser, value)
138136
} else {
139-
parsedValues[key] = value;
137+
parsedValues[key] = value
140138
}
141139
} else if (!parserableTypes(valueType) && isPredefinedTypes(valueType)) {
142140
// Do not parse enum value
143141
if (!detector.isENUMObject(valueType)) {
144142
// the predefined type is container type
145143
// so we put value handled with its container here
146144
if (valueType.isContainer) {
147-
parsedValues[key] = valueType.parse(valueParser, value);
145+
parsedValues[key] = valueType.parse(valueParser, value)
148146
} else {
149147
// custom defined values from the begining of struct creation
150-
parsedValues[key] = valueType;
148+
parsedValues[key] = valueType
151149
}
152150
}
153151
} else {
154152
// Value was undefined or not matched with available schema
155-
if (!nonNullableTypes(valueType)) parsedValues[key] = null;
153+
if (!nonNullableTypes(valueType)) parsedValues[key] = null
156154
}
157-
});
158-
return parsedValues;
159-
};
155+
})
156+
return parsedValues
157+
}
160158

161159
const parse = baseSchema => {
162-
return valuesToParse => valueParser(baseSchema, valuesToParse);
163-
};
160+
return valuesToParse => valueParser(baseSchema, valuesToParse)
161+
}
164162

165-
module.exports = parse;
166-
module.exports.valueParser = valueParser;
163+
module.exports = parse
164+
module.exports.valueParser = valueParser

0 commit comments

Comments
 (0)