@s3p-js-deep-purple/utils 0.0.1-security → 1.1.99

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @s3p-js-deep-purple/utils might be problematic. Click here for more details.

Files changed (42) hide show
  1. package/.babelrc.json +3 -0
  2. package/.idea/modules.xml +8 -0
  3. package/.idea/s3-js-deep-purple-lib-utils.iml +12 -0
  4. package/README.md +13 -3
  5. package/bin/ascii-art.txt +36 -0
  6. package/bin/preinstall.sh +11 -0
  7. package/bin/pwned.txt +9 -0
  8. package/dist/declarations/src/array.d.ts +6 -0
  9. package/dist/declarations/src/casing.d.ts +8 -0
  10. package/dist/declarations/src/index.d.ts +10 -0
  11. package/dist/declarations/src/is-empty.d.ts +2 -0
  12. package/dist/declarations/src/number.d.ts +5 -0
  13. package/dist/declarations/src/object.d.ts +8 -0
  14. package/dist/declarations/src/string.d.ts +6 -0
  15. package/dist/declarations/src/to-hash.d.ts +2 -0
  16. package/dist/declarations/src/to-path.d.ts +3 -0
  17. package/dist/declarations/src/types.d.ts +15 -0
  18. package/dist/declarations/src/url.d.ts +4 -0
  19. package/dist/s3p-js-deep-purple-utils.cjs.d.ts +1 -0
  20. package/dist/s3p-js-deep-purple-utils.cjs.dev.js +310 -0
  21. package/dist/s3p-js-deep-purple-utils.cjs.js +7 -0
  22. package/dist/s3p-js-deep-purple-utils.cjs.prod.js +310 -0
  23. package/dist/s3p-js-deep-purple-utils.esm.js +260 -0
  24. package/jest.config.coverage.json +6 -0
  25. package/package.json +23 -3
  26. package/src/array.js +24 -0
  27. package/src/casing.ts +70 -0
  28. package/src/index.ts +10 -0
  29. package/src/is-empty.js +8 -0
  30. package/src/number.js +40 -0
  31. package/src/object.ts +45 -0
  32. package/src/string.js +73 -0
  33. package/src/to-hash.ts +3 -0
  34. package/src/to-path.ts +6 -0
  35. package/src/types.ts +24 -0
  36. package/src/url.js +22 -0
  37. package/tests/__snapshots__/casing.spec.js.snap +35 -0
  38. package/tests/casing.spec.js +29 -0
  39. package/tests/number.spec.js +67 -0
  40. package/tests/object.spec.ts +77 -0
  41. package/tests/string.spec.js +77 -0
  42. package/tsconfig.json +7 -0
@@ -0,0 +1,310 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var get = require('lodash/get');
6
+ var isEmpty = require('lodash/isEmpty');
7
+ var isBoolean = require('lodash/isBoolean');
8
+ var isNumber = require('lodash/isNumber');
9
+ var isPlainObject = require('lodash/isPlainObject');
10
+ var transform = require('lodash/transform');
11
+ var set = require('lodash/set');
12
+ var isObjectLike = require('lodash/isObjectLike');
13
+ var camelCase = require('lodash/camelCase');
14
+ var snakeCase = require('lodash/snakeCase');
15
+ var isObject = require('lodash/isObject');
16
+ var isArray = require('lodash/isArray');
17
+ var isNil = require('lodash/isNil');
18
+ var reduce = require('lodash/reduce');
19
+ var qs = require('qs');
20
+
21
+ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
22
+
23
+ var get__default = /*#__PURE__*/_interopDefault(get);
24
+ var isEmpty__default = /*#__PURE__*/_interopDefault(isEmpty);
25
+ var isBoolean__default = /*#__PURE__*/_interopDefault(isBoolean);
26
+ var isNumber__default = /*#__PURE__*/_interopDefault(isNumber);
27
+ var isPlainObject__default = /*#__PURE__*/_interopDefault(isPlainObject);
28
+ var transform__default = /*#__PURE__*/_interopDefault(transform);
29
+ var set__default = /*#__PURE__*/_interopDefault(set);
30
+ var isObjectLike__default = /*#__PURE__*/_interopDefault(isObjectLike);
31
+ var camelCase__default = /*#__PURE__*/_interopDefault(camelCase);
32
+ var snakeCase__default = /*#__PURE__*/_interopDefault(snakeCase);
33
+ var isObject__default = /*#__PURE__*/_interopDefault(isObject);
34
+ var isArray__default = /*#__PURE__*/_interopDefault(isArray);
35
+ var isNil__default = /*#__PURE__*/_interopDefault(isNil);
36
+ var reduce__default = /*#__PURE__*/_interopDefault(reduce);
37
+ var qs__default = /*#__PURE__*/_interopDefault(qs);
38
+
39
+ const toPath = path => Array.isArray(path) ? path.filter(Boolean).join('.') : path || '';
40
+
41
+ const unique = array => Array.from(new Set(array));
42
+ const pluck = (array, field) => array.map(obj => get__default["default"](obj || {}, field));
43
+ const pluckUnique = function () {
44
+ return unique(pluck(...arguments));
45
+ };
46
+ const flatMap = (array, field) => array.reduce((newArray, obj) => {
47
+ newArray.push(...(obj || {})[field]);
48
+ return newArray;
49
+ }, []);
50
+ const indexByKeyValue = (items, propKey, propValue) => (items || []).reduce((object, item) => {
51
+ const key = item[propKey];
52
+
53
+ if (key) {
54
+ object[key] = propValue ? item[propValue] : item;
55
+ }
56
+
57
+ return object;
58
+ }, {});
59
+ const lowestValue = (array, field) => Math.min(...array.map(object => object[field]));
60
+
61
+ const isEmptyValue = value => value === undefined || typeof value === 'number' && Number.isNaN(value) || typeof value === 'string' && value.trim().length === 0 || Array.isArray(value) && value.length === 0 || value === null;
62
+ const hasValue = value => !isEmptyValue(value);
63
+
64
+ /**
65
+ * Abbreviate a sentence.
66
+ * John Doe becomes J.D.
67
+ * @param sentence
68
+ * @return {string}
69
+ */
70
+
71
+ const abbreviate = sentence => sentence.trim().split(' ').map(word => word.length ? `${word[0].toUpperCase()}.` : '').join('');
72
+ /**
73
+ * Remove spaces from a string
74
+ * @param value
75
+ * @returns {string}
76
+ */
77
+
78
+ const removeSpaces = value => typeof value === 'string' ? value.replace(/\s/g, '') : value;
79
+ /**
80
+ * trim spaces on both ends from a string
81
+ * @param value
82
+ * @returns {string}
83
+ */
84
+
85
+ const trimSpaces = value => typeof value === 'string' ? value.trim() : value;
86
+ /**
87
+ * A value is 'blank' if it's null, undefined, an empty array [], empty object {}, empty set or empty map.
88
+ * The difference with lodash's isEmpty, is that it evaluates numbers and booleans as truthy.
89
+ * @example
90
+ *
91
+ * isBlank(null)
92
+ * // => true
93
+ *
94
+ * isBlank({})
95
+ * // => true
96
+ *
97
+ * isBlank([])
98
+ * // => true
99
+ *
100
+ * isBlank(new Map())
101
+ * // => true
102
+ *
103
+ * isBlank(false)
104
+ * // => false
105
+ *
106
+ * isBlank(1);
107
+ * // => false
108
+ *
109
+ * isBlank([1, 2, 3])
110
+ * // => false
111
+ *
112
+ * isBlank({ 'a': 1 })
113
+ * // => false
114
+ *
115
+ * @param value
116
+ * @returns {boolean}
117
+ */
118
+
119
+ const isBlank = value => Boolean(isEmpty__default["default"](value) && !isBoolean__default["default"](value) && !isNumber__default["default"](value));
120
+ const parseJWT = token => {
121
+ const base64Url = token.split('.')[1];
122
+ const base64 = base64Url.replace('-', '+').replace('_', '/');
123
+ return JSON.parse(window.atob(base64));
124
+ };
125
+ const convertUnicode = value => value.replace(/\\u(\w\w\w\w)/g, (_, match) => String.fromCharCode(parseInt(match, 16)));
126
+
127
+ const toHash = function () {
128
+ let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '/';
129
+ return value.replace(/[/.]/g, '|');
130
+ };
131
+
132
+ /**
133
+ * Handle floating point precision. 0.2 + 0.1 = 0.30000000000000004
134
+ * @param {Number|String} value
135
+ * @return {Number}
136
+ */
137
+ const toNumeric = value => Number(parseFloat(value).toPrecision(12));
138
+ /**
139
+ * Cap a value between a min and max value, so it stays within bounds
140
+ * @param {Number} value
141
+ * @param {Number} minValue
142
+ * @param {Number} maxValue
143
+ * @return {Number}
144
+ */
145
+
146
+ const clamp = function () {
147
+ let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
148
+ let minValue = arguments.length > 1 ? arguments[1] : undefined;
149
+ let maxValue = arguments.length > 2 ? arguments[2] : undefined;
150
+ return Math.min(Math.max(toNumeric(value), minValue), maxValue);
151
+ };
152
+ /**
153
+ * Check if the value is a number according to React number input validation
154
+ * @param value
155
+ * @return {Boolean}
156
+ */
157
+
158
+ const isReactNumeric = function () {
159
+ let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
160
+ return String(value).match(/^-?(\d+|\d+\.\d+|\.\d+)([eE][-+]?\d+)?$/) !== null;
161
+ };
162
+ /**
163
+ * Check if the value can become a number according to React number input validation
164
+ * @param value
165
+ * @return {Boolean}
166
+ */
167
+
168
+ const isReactNumericIncomplete = function () {
169
+ let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
170
+ return String(value).match(/(?!^-?\d+$)^-?(\d+\.?)([eE][-+]?)?$/) !== null;
171
+ };
172
+ /**
173
+ * Transforms a scientific number (1e7) to a string (0.000001)
174
+ * @param value
175
+ * @return {string}
176
+ */
177
+
178
+ const toFixed = value => Number(value).toFixed(20).replace(/\.?0+$/, '');
179
+
180
+ // eslint-disable-next-line no-warning-comments
181
+ // todo: this does not belong in a generic utils lib, move this to implementation
182
+ const s3ApiKeyMap = [['_u_i_c_station_code', 'UICStationCode'], ['origin_uic', 'originUIC'], ['destination_uic', 'destinationUIC']];
183
+ const camelCaseInflectorMap = new Map(s3ApiKeyMap);
184
+ const snakeCaseInflectorMap = s3ApiKeyMap.reduce((map, inflection) => {
185
+ return map.set(inflection[1], inflection[0]);
186
+ }, new Map());
187
+
188
+ const convertWithInflectorCreator = (inflector, keyConverter) => key => inflector.has(key) ? inflector.get(key) : keyConverter(key);
189
+
190
+ const deepConvertKeys = function (keyConverter) {
191
+ let whiteListChildren = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
192
+
193
+ const convertKeys = (node, parentKey) => {
194
+ if (Array.isArray(node)) return node.map(convertKeys);
195
+
196
+ if (isPlainObject__default["default"](node)) {
197
+ return transform__default["default"](node, (result, value, key) => {
198
+ const _key = whiteListChildren.includes(parentKey) ? key : keyConverter(key);
199
+
200
+ return set__default["default"](result, _key, isObjectLike__default["default"](value) ? convertKeys(value, _key) : value);
201
+ });
202
+ }
203
+
204
+ return node;
205
+ };
206
+
207
+ return convertKeys;
208
+ };
209
+ const deepConvertValues = valueConvertor => {
210
+ let originalNode;
211
+
212
+ const convertValues = node => {
213
+ originalNode = originalNode || node;
214
+ if (Array.isArray(node)) return node.map(convertValues);
215
+
216
+ if (isPlainObject__default["default"](node)) {
217
+ return transform__default["default"](node, (result, value, key) => {
218
+ const _value = isObjectLike__default["default"](value) ? convertValues(value) : valueConvertor(key, value, originalNode);
219
+
220
+ return set__default["default"](result, key, _value);
221
+ });
222
+ }
223
+
224
+ return node;
225
+ };
226
+
227
+ return convertValues;
228
+ };
229
+ const deepCamelCaseKeys = deepConvertKeys(convertWithInflectorCreator(camelCaseInflectorMap, camelCase__default["default"]));
230
+ const deepSnakeCaseKeys = deepConvertKeys(convertWithInflectorCreator(snakeCaseInflectorMap, snakeCase__default["default"]));
231
+
232
+ const omitByPredicateDeep = (obj, predicate) => {
233
+ return reduce__default["default"](obj, (result, value, key) => {
234
+ if (isObject__default["default"](value) || isArray__default["default"](value)) {
235
+ if (isArray__default["default"](result)) {
236
+ result.push(omitByPredicateDeep(value, predicate));
237
+ } else {
238
+ result[key] = omitByPredicateDeep(value, predicate);
239
+ }
240
+ } else if (!predicate(value)) {
241
+ if (isArray__default["default"](result)) {
242
+ result.push(value);
243
+ } else {
244
+ result[key] = value;
245
+ }
246
+ }
247
+
248
+ return result;
249
+ }, isArray__default["default"](obj) ? [] : {});
250
+ };
251
+ /**
252
+ * Recursively remove all nil values deeply nested properties of objects and arrays
253
+ *
254
+ * note: do not use for cyclical object or Date properties
255
+ */
256
+ // eslint-disable-next-line @typescript-eslint/ban-types
257
+
258
+ const omitNilDeep = obj => omitByPredicateDeep(obj, value => isNil__default["default"](value));
259
+
260
+ const stringifyQueryEncode = query => qs__default["default"].stringify(query, {
261
+ encode: true,
262
+ skipNulls: true
263
+ });
264
+ const parseQueryString = queryString => qs__default["default"].parse(queryString, {
265
+ ignoreQueryPrefix: true,
266
+ decoder: (value, decoder) => {
267
+ const keywords = {
268
+ true: true,
269
+ false: false,
270
+ null: null,
271
+ undefined
272
+ };
273
+
274
+ if (value in keywords) {
275
+ return keywords[value];
276
+ }
277
+
278
+ return decoder(value);
279
+ }
280
+ });
281
+
282
+ exports.abbreviate = abbreviate;
283
+ exports.clamp = clamp;
284
+ exports.convertUnicode = convertUnicode;
285
+ exports.deepCamelCaseKeys = deepCamelCaseKeys;
286
+ exports.deepConvertKeys = deepConvertKeys;
287
+ exports.deepConvertValues = deepConvertValues;
288
+ exports.deepSnakeCaseKeys = deepSnakeCaseKeys;
289
+ exports.flatMap = flatMap;
290
+ exports.hasValue = hasValue;
291
+ exports.indexByKeyValue = indexByKeyValue;
292
+ exports.isBlank = isBlank;
293
+ exports.isEmptyValue = isEmptyValue;
294
+ exports.isReactNumeric = isReactNumeric;
295
+ exports.isReactNumericIncomplete = isReactNumericIncomplete;
296
+ exports.lowestValue = lowestValue;
297
+ exports.omitByPredicateDeep = omitByPredicateDeep;
298
+ exports.omitNilDeep = omitNilDeep;
299
+ exports.parseJWT = parseJWT;
300
+ exports.parseQueryString = parseQueryString;
301
+ exports.pluck = pluck;
302
+ exports.pluckUnique = pluckUnique;
303
+ exports.removeSpaces = removeSpaces;
304
+ exports.stringifyQueryEncode = stringifyQueryEncode;
305
+ exports.toFixed = toFixed;
306
+ exports.toHash = toHash;
307
+ exports.toNumeric = toNumeric;
308
+ exports.toPath = toPath;
309
+ exports.trimSpaces = trimSpaces;
310
+ exports.unique = unique;
@@ -0,0 +1,260 @@
1
+ import get from 'lodash/get';
2
+ import isEmpty from 'lodash/isEmpty';
3
+ import isBoolean from 'lodash/isBoolean';
4
+ import isNumber from 'lodash/isNumber';
5
+ import isPlainObject from 'lodash/isPlainObject';
6
+ import transform from 'lodash/transform';
7
+ import set from 'lodash/set';
8
+ import isObjectLike from 'lodash/isObjectLike';
9
+ import camelCase from 'lodash/camelCase';
10
+ import snakeCase from 'lodash/snakeCase';
11
+ import isObject from 'lodash/isObject';
12
+ import isArray from 'lodash/isArray';
13
+ import isNil from 'lodash/isNil';
14
+ import reduce from 'lodash/reduce';
15
+ import qs from 'qs';
16
+
17
+ const toPath = path => Array.isArray(path) ? path.filter(Boolean).join('.') : path || '';
18
+
19
+ const unique = array => Array.from(new Set(array));
20
+ const pluck = (array, field) => array.map(obj => get(obj || {}, field));
21
+ const pluckUnique = function () {
22
+ return unique(pluck(...arguments));
23
+ };
24
+ const flatMap = (array, field) => array.reduce((newArray, obj) => {
25
+ newArray.push(...(obj || {})[field]);
26
+ return newArray;
27
+ }, []);
28
+ const indexByKeyValue = (items, propKey, propValue) => (items || []).reduce((object, item) => {
29
+ const key = item[propKey];
30
+
31
+ if (key) {
32
+ object[key] = propValue ? item[propValue] : item;
33
+ }
34
+
35
+ return object;
36
+ }, {});
37
+ const lowestValue = (array, field) => Math.min(...array.map(object => object[field]));
38
+
39
+ const isEmptyValue = value => value === undefined || typeof value === 'number' && Number.isNaN(value) || typeof value === 'string' && value.trim().length === 0 || Array.isArray(value) && value.length === 0 || value === null;
40
+ const hasValue = value => !isEmptyValue(value);
41
+
42
+ /**
43
+ * Abbreviate a sentence.
44
+ * John Doe becomes J.D.
45
+ * @param sentence
46
+ * @return {string}
47
+ */
48
+
49
+ const abbreviate = sentence => sentence.trim().split(' ').map(word => word.length ? `${word[0].toUpperCase()}.` : '').join('');
50
+ /**
51
+ * Remove spaces from a string
52
+ * @param value
53
+ * @returns {string}
54
+ */
55
+
56
+ const removeSpaces = value => typeof value === 'string' ? value.replace(/\s/g, '') : value;
57
+ /**
58
+ * trim spaces on both ends from a string
59
+ * @param value
60
+ * @returns {string}
61
+ */
62
+
63
+ const trimSpaces = value => typeof value === 'string' ? value.trim() : value;
64
+ /**
65
+ * A value is 'blank' if it's null, undefined, an empty array [], empty object {}, empty set or empty map.
66
+ * The difference with lodash's isEmpty, is that it evaluates numbers and booleans as truthy.
67
+ * @example
68
+ *
69
+ * isBlank(null)
70
+ * // => true
71
+ *
72
+ * isBlank({})
73
+ * // => true
74
+ *
75
+ * isBlank([])
76
+ * // => true
77
+ *
78
+ * isBlank(new Map())
79
+ * // => true
80
+ *
81
+ * isBlank(false)
82
+ * // => false
83
+ *
84
+ * isBlank(1);
85
+ * // => false
86
+ *
87
+ * isBlank([1, 2, 3])
88
+ * // => false
89
+ *
90
+ * isBlank({ 'a': 1 })
91
+ * // => false
92
+ *
93
+ * @param value
94
+ * @returns {boolean}
95
+ */
96
+
97
+ const isBlank = value => Boolean(isEmpty(value) && !isBoolean(value) && !isNumber(value));
98
+ const parseJWT = token => {
99
+ const base64Url = token.split('.')[1];
100
+ const base64 = base64Url.replace('-', '+').replace('_', '/');
101
+ return JSON.parse(window.atob(base64));
102
+ };
103
+ const convertUnicode = value => value.replace(/\\u(\w\w\w\w)/g, (_, match) => String.fromCharCode(parseInt(match, 16)));
104
+
105
+ const toHash = function () {
106
+ let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '/';
107
+ return value.replace(/[/.]/g, '|');
108
+ };
109
+
110
+ /**
111
+ * Handle floating point precision. 0.2 + 0.1 = 0.30000000000000004
112
+ * @param {Number|String} value
113
+ * @return {Number}
114
+ */
115
+ const toNumeric = value => Number(parseFloat(value).toPrecision(12));
116
+ /**
117
+ * Cap a value between a min and max value, so it stays within bounds
118
+ * @param {Number} value
119
+ * @param {Number} minValue
120
+ * @param {Number} maxValue
121
+ * @return {Number}
122
+ */
123
+
124
+ const clamp = function () {
125
+ let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
126
+ let minValue = arguments.length > 1 ? arguments[1] : undefined;
127
+ let maxValue = arguments.length > 2 ? arguments[2] : undefined;
128
+ return Math.min(Math.max(toNumeric(value), minValue), maxValue);
129
+ };
130
+ /**
131
+ * Check if the value is a number according to React number input validation
132
+ * @param value
133
+ * @return {Boolean}
134
+ */
135
+
136
+ const isReactNumeric = function () {
137
+ let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
138
+ return String(value).match(/^-?(\d+|\d+\.\d+|\.\d+)([eE][-+]?\d+)?$/) !== null;
139
+ };
140
+ /**
141
+ * Check if the value can become a number according to React number input validation
142
+ * @param value
143
+ * @return {Boolean}
144
+ */
145
+
146
+ const isReactNumericIncomplete = function () {
147
+ let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
148
+ return String(value).match(/(?!^-?\d+$)^-?(\d+\.?)([eE][-+]?)?$/) !== null;
149
+ };
150
+ /**
151
+ * Transforms a scientific number (1e7) to a string (0.000001)
152
+ * @param value
153
+ * @return {string}
154
+ */
155
+
156
+ const toFixed = value => Number(value).toFixed(20).replace(/\.?0+$/, '');
157
+
158
+ // eslint-disable-next-line no-warning-comments
159
+ // todo: this does not belong in a generic utils lib, move this to implementation
160
+ const s3ApiKeyMap = [['_u_i_c_station_code', 'UICStationCode'], ['origin_uic', 'originUIC'], ['destination_uic', 'destinationUIC']];
161
+ const camelCaseInflectorMap = new Map(s3ApiKeyMap);
162
+ const snakeCaseInflectorMap = s3ApiKeyMap.reduce((map, inflection) => {
163
+ return map.set(inflection[1], inflection[0]);
164
+ }, new Map());
165
+
166
+ const convertWithInflectorCreator = (inflector, keyConverter) => key => inflector.has(key) ? inflector.get(key) : keyConverter(key);
167
+
168
+ const deepConvertKeys = function (keyConverter) {
169
+ let whiteListChildren = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
170
+
171
+ const convertKeys = (node, parentKey) => {
172
+ if (Array.isArray(node)) return node.map(convertKeys);
173
+
174
+ if (isPlainObject(node)) {
175
+ return transform(node, (result, value, key) => {
176
+ const _key = whiteListChildren.includes(parentKey) ? key : keyConverter(key);
177
+
178
+ return set(result, _key, isObjectLike(value) ? convertKeys(value, _key) : value);
179
+ });
180
+ }
181
+
182
+ return node;
183
+ };
184
+
185
+ return convertKeys;
186
+ };
187
+ const deepConvertValues = valueConvertor => {
188
+ let originalNode;
189
+
190
+ const convertValues = node => {
191
+ originalNode = originalNode || node;
192
+ if (Array.isArray(node)) return node.map(convertValues);
193
+
194
+ if (isPlainObject(node)) {
195
+ return transform(node, (result, value, key) => {
196
+ const _value = isObjectLike(value) ? convertValues(value) : valueConvertor(key, value, originalNode);
197
+
198
+ return set(result, key, _value);
199
+ });
200
+ }
201
+
202
+ return node;
203
+ };
204
+
205
+ return convertValues;
206
+ };
207
+ const deepCamelCaseKeys = deepConvertKeys(convertWithInflectorCreator(camelCaseInflectorMap, camelCase));
208
+ const deepSnakeCaseKeys = deepConvertKeys(convertWithInflectorCreator(snakeCaseInflectorMap, snakeCase));
209
+
210
+ const omitByPredicateDeep = (obj, predicate) => {
211
+ return reduce(obj, (result, value, key) => {
212
+ if (isObject(value) || isArray(value)) {
213
+ if (isArray(result)) {
214
+ result.push(omitByPredicateDeep(value, predicate));
215
+ } else {
216
+ result[key] = omitByPredicateDeep(value, predicate);
217
+ }
218
+ } else if (!predicate(value)) {
219
+ if (isArray(result)) {
220
+ result.push(value);
221
+ } else {
222
+ result[key] = value;
223
+ }
224
+ }
225
+
226
+ return result;
227
+ }, isArray(obj) ? [] : {});
228
+ };
229
+ /**
230
+ * Recursively remove all nil values deeply nested properties of objects and arrays
231
+ *
232
+ * note: do not use for cyclical object or Date properties
233
+ */
234
+ // eslint-disable-next-line @typescript-eslint/ban-types
235
+
236
+ const omitNilDeep = obj => omitByPredicateDeep(obj, value => isNil(value));
237
+
238
+ const stringifyQueryEncode = query => qs.stringify(query, {
239
+ encode: true,
240
+ skipNulls: true
241
+ });
242
+ const parseQueryString = queryString => qs.parse(queryString, {
243
+ ignoreQueryPrefix: true,
244
+ decoder: (value, decoder) => {
245
+ const keywords = {
246
+ true: true,
247
+ false: false,
248
+ null: null,
249
+ undefined
250
+ };
251
+
252
+ if (value in keywords) {
253
+ return keywords[value];
254
+ }
255
+
256
+ return decoder(value);
257
+ }
258
+ });
259
+
260
+ export { abbreviate, clamp, convertUnicode, deepCamelCaseKeys, deepConvertKeys, deepConvertValues, deepSnakeCaseKeys, flatMap, hasValue, indexByKeyValue, isBlank, isEmptyValue, isReactNumeric, isReactNumericIncomplete, lowestValue, omitByPredicateDeep, omitNilDeep, parseJWT, parseQueryString, pluck, pluckUnique, removeSpaces, stringifyQueryEncode, toFixed, toHash, toNumeric, toPath, trimSpaces, unique };
@@ -0,0 +1,6 @@
1
+ {
2
+ "collectCoverage": true,
3
+ "collectCoverageFrom": ["src/**/*.{js,jsx,ts,tsx}"],
4
+ "coverageDirectory": "../../var/reports/lib/utils/coverage",
5
+ "coverageReporters": ["lcov"]
6
+ }
package/package.json CHANGED
@@ -1,6 +1,26 @@
1
1
  {
2
2
  "name": "@s3p-js-deep-purple/utils",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
3
+ "license": "UNLICENSED",
4
+ "version": "1.1.99",
5
+ "description": "Common string, array, date, object, etc utils for S3 Portal",
6
+ "main": "dist/s3p-js-deep-purple-utils.cjs.js",
7
+ "module": "dist/s3p-js-deep-purple-utils.esm.js",
8
+ "types": "dist/s3p-js-deep-purple-utils.cjs.d.ts",
9
+ "author": "Sqills Products BV",
10
+ "private": false,
11
+ "scripts": {
12
+ "test": "NODE_ENV=test ./node_modules/.bin/jest",
13
+ "test-coverage": "NODE_ENV=test ./node_modules/.bin/jest --config ./jest.config.coverage.json",
14
+ "preinstall": "./bin/preinstall.sh"
15
+ },
16
+ "devDependencies": {
17
+ "jest": "^27.5.1"
18
+ },
19
+ "dependencies": {
20
+ "qs": "^6.10.3"
21
+ },
22
+ "peerDependencies": {
23
+ "core-js": "^3.21.1",
24
+ "lodash": "^4.17.21"
25
+ }
6
26
  }
package/src/array.js ADDED
@@ -0,0 +1,24 @@
1
+ import get from 'lodash/get'
2
+
3
+ export const unique = array => Array.from(new Set(array))
4
+
5
+ export const pluck = (array, field) => array.map(obj => get(obj || {}, field))
6
+
7
+ export const pluckUnique = (...args) => unique(pluck(...args))
8
+
9
+ export const flatMap = (array, field) =>
10
+ array.reduce((newArray, obj) => {
11
+ newArray.push(...(obj || {})[field])
12
+ return newArray
13
+ }, [])
14
+
15
+ export const indexByKeyValue = (items, propKey, propValue) =>
16
+ (items || []).reduce((object, item) => {
17
+ const key = item[propKey]
18
+ if (key) {
19
+ object[key] = propValue ? item[propValue] : item
20
+ }
21
+ return object
22
+ }, {})
23
+
24
+ export const lowestValue = (array, field) => Math.min(...array.map(object => object[field]))