ts-data-forge 5.1.0 → 5.1.1
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.
- package/README.md +46 -44
- package/dist/array/impl/array-utils-modification.d.mts.map +1 -1
- package/dist/array/impl/array-utils-modification.mjs.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.d.mts +8 -8
- package/dist/array/impl/array-utils-search.d.mts +4 -4
- package/dist/array/impl/array-utils-set-op.d.mts +7 -7
- package/dist/array/impl/array-utils-set-op.mjs +7 -7
- package/dist/array/impl/array-utils-size.d.mts +2 -2
- package/dist/array/impl/array-utils-size.mjs +2 -2
- package/dist/array/impl/array-utils-slicing.d.mts +2 -2
- package/dist/array/impl/array-utils-slicing.mjs +2 -2
- package/dist/array/impl/array-utils-validation.d.mts +18 -18
- package/dist/array/impl/array-utils-validation.mjs +14 -14
- package/dist/collections/imap.d.mts +15 -15
- package/dist/collections/imap.mjs +3 -3
- package/dist/collections/iset-mapped.d.mts +19 -19
- package/dist/collections/iset-mapped.mjs +2 -2
- package/dist/collections/iset.d.mts +19 -19
- package/dist/collections/iset.mjs +2 -2
- package/dist/collections/queue.d.mts +25 -25
- package/dist/collections/queue.mjs +5 -5
- package/dist/collections/stack.d.mts +25 -25
- package/dist/collections/stack.mjs +5 -5
- package/dist/functional/match.d.mts +1 -1
- package/dist/functional/optional/impl/optional-expect-to-be.d.mts +2 -2
- package/dist/functional/optional/impl/optional-is-none.d.mts +1 -1
- package/dist/functional/optional/impl/optional-is-none.mjs +1 -1
- package/dist/functional/optional/impl/optional-is-optional.d.mts +2 -2
- package/dist/functional/optional/impl/optional-is-optional.mjs +2 -2
- package/dist/functional/optional/impl/optional-is-some.d.mts +1 -1
- package/dist/functional/optional/impl/optional-is-some.mjs +1 -1
- package/dist/functional/optional/impl/optional-none.d.mts +2 -2
- package/dist/functional/optional/impl/optional-none.mjs +2 -2
- package/dist/functional/optional/impl/optional-some.d.mts +2 -2
- package/dist/functional/optional/impl/optional-some.mjs +2 -2
- package/dist/functional/optional/impl/optional-to-nullable.d.mts +2 -2
- package/dist/functional/optional/impl/optional-to-nullable.mjs +2 -2
- package/dist/functional/optional/impl/optional-unwrap-or.d.mts +4 -4
- package/dist/functional/optional/impl/optional-unwrap-throw.d.mts +1 -1
- package/dist/functional/optional/impl/optional-unwrap-throw.mjs +1 -1
- package/dist/functional/optional/impl/optional-unwrap.d.mts +2 -2
- package/dist/functional/optional/impl/optional-zip.d.mts +1 -1
- package/dist/functional/optional/impl/optional-zip.mjs +1 -1
- package/dist/functional/pipe.d.mts +2 -2
- package/dist/functional/result/impl/result-err.d.mts +1 -1
- package/dist/functional/result/impl/result-err.mjs +1 -1
- package/dist/functional/result/impl/result-expect-to-be.d.mts +2 -2
- package/dist/functional/result/impl/result-from-promise.d.mts +1 -1
- package/dist/functional/result/impl/result-from-promise.mjs +1 -1
- package/dist/functional/result/impl/result-from-throwable.d.mts +1 -1
- package/dist/functional/result/impl/result-from-throwable.mjs +1 -1
- package/dist/functional/result/impl/result-is-err.d.mts +2 -2
- package/dist/functional/result/impl/result-is-err.mjs +2 -2
- package/dist/functional/result/impl/result-is-ok.d.mts +2 -2
- package/dist/functional/result/impl/result-is-ok.mjs +2 -2
- package/dist/functional/result/impl/result-is-result.d.mts +3 -3
- package/dist/functional/result/impl/result-is-result.mjs +3 -3
- package/dist/functional/result/impl/result-ok.d.mts +1 -1
- package/dist/functional/result/impl/result-ok.mjs +1 -1
- package/dist/functional/result/impl/result-unwrap-err-or.d.mts +4 -4
- package/dist/functional/result/impl/result-unwrap-err-throw.d.mts +1 -1
- package/dist/functional/result/impl/result-unwrap-err-throw.mjs +1 -1
- package/dist/functional/result/impl/result-unwrap-err.d.mts +2 -2
- package/dist/functional/result/impl/result-unwrap-err.mjs +2 -2
- package/dist/functional/result/impl/result-unwrap-ok-or.d.mts +4 -4
- package/dist/functional/result/impl/result-unwrap-ok.d.mts +2 -2
- package/dist/functional/result/impl/result-unwrap-throw.d.mts +1 -1
- package/dist/functional/result/impl/result-unwrap-throw.mjs +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-err.d.mts +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-err.mjs +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-promise.d.mts +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-promise.mjs +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.d.mts +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.mjs +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-is-ternary-result.d.mts +3 -3
- package/dist/functional/ternary-result/impl/ternary-result-is-ternary-result.mjs +3 -3
- package/dist/globals.d.mts +2 -1
- package/dist/guard/has-key.d.mts +6 -3
- package/dist/guard/has-key.d.mts.map +1 -1
- package/dist/guard/has-key.mjs +2 -2
- package/dist/guard/key-is-in.d.mts +2 -2
- package/dist/guard/key-is-in.mjs +2 -2
- package/dist/json/json.d.mts +21 -21
- package/dist/json/json.mjs +21 -21
- package/dist/number/branded-types/int.d.mts +19 -19
- package/dist/number/branded-types/int.mjs +19 -19
- package/dist/number/branded-types/positive-int.d.mts +20 -20
- package/dist/number/branded-types/positive-int.mjs +20 -20
- package/dist/number/branded-types/positive-safe-int.d.mts +26 -26
- package/dist/number/branded-types/positive-safe-int.mjs +26 -26
- package/dist/number/branded-types/safe-int.d.mts +27 -27
- package/dist/number/branded-types/safe-int.mjs +27 -27
- package/dist/number/branded-types/uint.d.mts +19 -19
- package/dist/number/branded-types/uint.mjs +19 -19
- package/dist/number/num.d.mts +20 -20
- package/dist/number/num.mjs +16 -16
- package/dist/number/refined-number-utils.d.mts +11 -11
- package/dist/number/refined-number-utils.d.mts.map +1 -1
- package/dist/number/refined-number-utils.mjs +11 -11
- package/dist/object/object.d.mts +3 -3
- package/dist/object/object.d.mts.map +1 -1
- package/dist/object/object.mjs +3 -3
- package/dist/object/object.mjs.map +1 -1
- package/dist/others/tuple.d.mts +3 -3
- package/dist/others/tuple.mjs +3 -3
- package/dist/promise/promise.d.mts +4 -4
- package/dist/promise/promise.mjs +4 -4
- package/package.json +15 -13
- package/src/array/impl/array-utils-creation.test.mts +1 -1
- package/src/array/impl/array-utils-element-access.test.mts +16 -16
- package/src/array/impl/array-utils-modification.mts +38 -19
- package/src/array/impl/array-utils-reducing-value.mts +8 -8
- package/src/array/impl/array-utils-reducing-value.test.mts +23 -31
- package/src/array/impl/array-utils-search.mts +4 -4
- package/src/array/impl/array-utils-search.test.mts +10 -10
- package/src/array/impl/array-utils-set-op.mts +7 -7
- package/src/array/impl/array-utils-set-op.test.mts +13 -13
- package/src/array/impl/array-utils-size.mts +2 -2
- package/src/array/impl/array-utils-slicing.mts +2 -2
- package/src/array/impl/array-utils-transformation.test.mts +2 -2
- package/src/array/impl/array-utils-validation.mts +18 -18
- package/src/array/impl/array-utils-validation.test.mts +80 -78
- package/src/array/impl/array.test.mts +6 -6
- package/src/collections/imap-mapped.test.mts +16 -18
- package/src/collections/imap.mts +15 -15
- package/src/collections/imap.test.mts +31 -31
- package/src/collections/iset-mapped.mts +19 -19
- package/src/collections/iset-mapped.test.mts +52 -52
- package/src/collections/iset.mts +19 -19
- package/src/collections/iset.test.mts +130 -130
- package/src/collections/queue.mts +25 -25
- package/src/collections/queue.test.mts +33 -35
- package/src/collections/stack.mts +25 -25
- package/src/collections/stack.test.mts +15 -15
- package/src/functional/match.mts +1 -1
- package/src/functional/optional/impl/optional-expect-to-be.mts +2 -2
- package/src/functional/optional/impl/optional-is-none.mts +1 -1
- package/src/functional/optional/impl/optional-is-optional.mts +2 -2
- package/src/functional/optional/impl/optional-is-some.mts +1 -1
- package/src/functional/optional/impl/optional-none.mts +2 -2
- package/src/functional/optional/impl/optional-some.mts +2 -2
- package/src/functional/optional/impl/optional-to-nullable.mts +2 -2
- package/src/functional/optional/impl/optional-unwrap-or.mts +4 -4
- package/src/functional/optional/impl/optional-unwrap-throw.mts +1 -1
- package/src/functional/optional/impl/optional-unwrap.mts +2 -2
- package/src/functional/optional/impl/optional-zip.mts +1 -1
- package/src/functional/optional.test.mts +53 -54
- package/src/functional/pipe.mts +2 -2
- package/src/functional/pipe.test.mts +4 -4
- package/src/functional/result/impl/result-err.mts +1 -1
- package/src/functional/result/impl/result-expect-to-be.mts +2 -2
- package/src/functional/result/impl/result-from-promise.mts +1 -1
- package/src/functional/result/impl/result-from-throwable.mts +1 -1
- package/src/functional/result/impl/result-is-err.mts +2 -2
- package/src/functional/result/impl/result-is-ok.mts +2 -2
- package/src/functional/result/impl/result-is-result.mts +3 -3
- package/src/functional/result/impl/result-ok.mts +1 -1
- package/src/functional/result/impl/result-unwrap-err-or.mts +4 -4
- package/src/functional/result/impl/result-unwrap-err-throw.mts +1 -1
- package/src/functional/result/impl/result-unwrap-err.mts +2 -2
- package/src/functional/result/impl/result-unwrap-ok-or.mts +4 -4
- package/src/functional/result/impl/result-unwrap-ok.mts +2 -2
- package/src/functional/result/impl/result-unwrap-throw.mts +1 -1
- package/src/functional/result.test.mts +94 -152
- package/src/functional/ternary-result/impl/ternary-result-err.mts +1 -1
- package/src/functional/ternary-result/impl/ternary-result-from-promise.mts +1 -1
- package/src/functional/ternary-result/impl/ternary-result-from-throwable.mts +1 -1
- package/src/functional/ternary-result/impl/ternary-result-is-ternary-result.mts +3 -3
- package/src/functional/ternary-result.test.mts +8 -8
- package/src/globals.d.mts +2 -1
- package/src/guard/has-key.mts +8 -5
- package/src/guard/has-key.test.mts +0 -5
- package/src/guard/is-error.test.mts +143 -0
- package/src/guard/is-non-empty-string.test.mts +24 -24
- package/src/guard/is-non-null-object.test.mts +26 -26
- package/src/guard/is-primitive.test.mts +28 -28
- package/src/guard/is-record.test.mts +7 -7
- package/src/guard/is-type.test.mts +151 -155
- package/src/guard/key-is-in.mts +2 -2
- package/src/guard/key-is-in.test.mts +2 -2
- package/src/json/json.mts +21 -21
- package/src/json/json.test.mts +135 -174
- package/src/number/branded-types/finite-number.test.mts +13 -11
- package/src/number/branded-types/int.mts +19 -19
- package/src/number/branded-types/int.test.mts +14 -14
- package/src/number/branded-types/int16.test.mts +16 -16
- package/src/number/branded-types/int32.test.mts +16 -16
- package/src/number/branded-types/non-negative-finite-number.test.mts +12 -12
- package/src/number/branded-types/non-negative-int16.test.mts +16 -16
- package/src/number/branded-types/non-negative-int32.test.mts +16 -16
- package/src/number/branded-types/non-zero-finite-number.test.mts +14 -14
- package/src/number/branded-types/non-zero-int.test.mts +19 -19
- package/src/number/branded-types/non-zero-int16.test.mts +16 -16
- package/src/number/branded-types/non-zero-int32.test.mts +16 -16
- package/src/number/branded-types/non-zero-safe-int.test.mts +23 -23
- package/src/number/branded-types/non-zero-uint16.test.mts +16 -16
- package/src/number/branded-types/non-zero-uint32.test.mts +16 -16
- package/src/number/branded-types/positive-finite-number.test.mts +14 -14
- package/src/number/branded-types/positive-int.mts +20 -20
- package/src/number/branded-types/positive-int.test.mts +17 -17
- package/src/number/branded-types/positive-int16.test.mts +15 -15
- package/src/number/branded-types/positive-int32.test.mts +15 -15
- package/src/number/branded-types/positive-safe-int.mts +26 -26
- package/src/number/branded-types/positive-safe-int.test.mts +19 -19
- package/src/number/branded-types/positive-uint16.test.mts +16 -16
- package/src/number/branded-types/positive-uint32.test.mts +16 -16
- package/src/number/branded-types/safe-int.mts +27 -27
- package/src/number/branded-types/safe-int.test.mts +18 -18
- package/src/number/branded-types/safe-uint.test.mts +17 -17
- package/src/number/branded-types/uint.mts +19 -19
- package/src/number/branded-types/uint.test.mts +15 -15
- package/src/number/branded-types/uint16.test.mts +15 -15
- package/src/number/branded-types/uint32.test.mts +15 -15
- package/src/number/enum/int8.test.mts +1 -1
- package/src/number/enum/uint8.test.mts +1 -1
- package/src/number/num.mts +20 -20
- package/src/number/num.test.mts +26 -26
- package/src/number/refined-number-utils.mts +13 -13
- package/src/object/object.mts +4 -3
- package/src/object/object.test.mts +6 -6
- package/src/others/cast-mutable.test.mts +1 -1
- package/src/others/cast-readonly.test.mts +4 -4
- package/src/others/if-then.test.mts +24 -24
- package/src/others/tuple.mts +3 -3
- package/src/promise/promise.mts +4 -4
- package/src/promise/promise.test.mts +7 -13
package/src/json/json.mts
CHANGED
|
@@ -28,13 +28,13 @@ export namespace Json {
|
|
|
28
28
|
*
|
|
29
29
|
* const failed = Json.parse(invalidJson);
|
|
30
30
|
*
|
|
31
|
-
* assert.
|
|
31
|
+
* assert.isTrue(Result.isOk(parsed));
|
|
32
32
|
*
|
|
33
33
|
* if (Result.isOk(parsed)) {
|
|
34
34
|
* assert.deepStrictEqual(parsed.value, { name: 'Alice', age: 30 });
|
|
35
35
|
* }
|
|
36
36
|
*
|
|
37
|
-
* assert.
|
|
37
|
+
* assert.isTrue(Result.isErr(failed));
|
|
38
38
|
*
|
|
39
39
|
* // With reviver
|
|
40
40
|
* const jsonWithDate = '{"created": "2024-01-01T00:00:00.000Z"}';
|
|
@@ -47,7 +47,7 @@ export namespace Json {
|
|
|
47
47
|
* return value;
|
|
48
48
|
* });
|
|
49
49
|
*
|
|
50
|
-
* assert.
|
|
50
|
+
* assert.isTrue(Result.isOk(withReviver));
|
|
51
51
|
* ```
|
|
52
52
|
*
|
|
53
53
|
* @param text - A valid JSON string to parse. Can contain any valid JSON data
|
|
@@ -98,16 +98,16 @@ export namespace Json {
|
|
|
98
98
|
* // Basic stringify
|
|
99
99
|
* const basic = Json.stringify(data);
|
|
100
100
|
*
|
|
101
|
-
* assert.
|
|
101
|
+
* assert.isTrue(Result.isOk(basic));
|
|
102
102
|
*
|
|
103
103
|
* if (Result.isOk(basic)) {
|
|
104
|
-
* assert(basic.value === '{"name":"Bob","age":25,"active":true}');
|
|
104
|
+
* assert.isTrue(basic.value === '{"name":"Bob","age":25,"active":true}');
|
|
105
105
|
* }
|
|
106
106
|
*
|
|
107
107
|
* // With formatting
|
|
108
108
|
* const formatted = Json.stringify(data, undefined, 2);
|
|
109
109
|
*
|
|
110
|
-
* assert.
|
|
110
|
+
* assert.isTrue(Result.isOk(formatted));
|
|
111
111
|
*
|
|
112
112
|
* // With replacer
|
|
113
113
|
* const filtered = Json.stringify(data, (key, value) => {
|
|
@@ -116,12 +116,12 @@ export namespace Json {
|
|
|
116
116
|
* return value;
|
|
117
117
|
* });
|
|
118
118
|
*
|
|
119
|
-
* assert.
|
|
119
|
+
* assert.isTrue(Result.isOk(filtered));
|
|
120
120
|
*
|
|
121
121
|
* if (Result.isOk(filtered)) {
|
|
122
|
-
* assert(isString(filtered.value));
|
|
122
|
+
* assert.isTrue(isString(filtered.value));
|
|
123
123
|
*
|
|
124
|
-
* assert.
|
|
124
|
+
* assert.isFalse(filtered.value.includes('age'));
|
|
125
125
|
* }
|
|
126
126
|
* ```
|
|
127
127
|
*
|
|
@@ -182,10 +182,10 @@ export namespace Json {
|
|
|
182
182
|
* // Select only safe properties to serialize
|
|
183
183
|
* const safeJson = Json.stringifySelected(user, ['id', 'name', 'role']);
|
|
184
184
|
*
|
|
185
|
-
* assert.
|
|
185
|
+
* assert.isTrue(Result.isOk(safeJson));
|
|
186
186
|
*
|
|
187
187
|
* if (Result.isOk(safeJson)) {
|
|
188
|
-
* assert(isString(safeJson.value));
|
|
188
|
+
* assert.isTrue(isString(safeJson.value));
|
|
189
189
|
*
|
|
190
190
|
* const parsed: unknown = JSON.parse(safeJson.value);
|
|
191
191
|
*
|
|
@@ -195,15 +195,15 @@ export namespace Json {
|
|
|
195
195
|
* role: 'admin',
|
|
196
196
|
* });
|
|
197
197
|
*
|
|
198
|
-
* assert.
|
|
198
|
+
* assert.isFalse(safeJson.value.includes('password'));
|
|
199
199
|
*
|
|
200
|
-
* assert.
|
|
200
|
+
* assert.isFalse(safeJson.value.includes('email'));
|
|
201
201
|
* }
|
|
202
202
|
*
|
|
203
203
|
* // With formatting
|
|
204
204
|
* const formatted = Json.stringifySelected(user, ['id', 'name'], 2);
|
|
205
205
|
*
|
|
206
|
-
* assert.
|
|
206
|
+
* assert.isTrue(Result.isOk(formatted));
|
|
207
207
|
* ```
|
|
208
208
|
*
|
|
209
209
|
* @param value - The JavaScript value to serialize. While any value is
|
|
@@ -267,34 +267,34 @@ export namespace Json {
|
|
|
267
267
|
* // Keys will be sorted alphabetically at all levels
|
|
268
268
|
* const sorted = Json.stringifySortedKey(unorderedData);
|
|
269
269
|
*
|
|
270
|
-
* assert.
|
|
270
|
+
* assert.isTrue(Result.isOk(sorted));
|
|
271
271
|
*
|
|
272
272
|
* if (Result.isOk(sorted)) {
|
|
273
273
|
* // Keys should appear in alphabetical order
|
|
274
274
|
* const expected =
|
|
275
275
|
* '{"apple":2,"mango":3,"nested":{"alpha":"a","beta":"b","zulu":"z"},"zebra":1}';
|
|
276
276
|
*
|
|
277
|
-
* assert(sorted.value === expected);
|
|
277
|
+
* assert.isTrue(sorted.value === expected);
|
|
278
278
|
* }
|
|
279
279
|
*
|
|
280
280
|
* // With formatting
|
|
281
281
|
* const formatted = Json.stringifySortedKey(unorderedData, 2);
|
|
282
282
|
*
|
|
283
|
-
* assert.
|
|
283
|
+
* assert.isTrue(Result.isOk(formatted));
|
|
284
284
|
*
|
|
285
285
|
* if (Result.isOk(formatted)) {
|
|
286
|
-
* assert(isString(formatted.value));
|
|
286
|
+
* assert.isTrue(isString(formatted.value));
|
|
287
287
|
*
|
|
288
288
|
* // Check that keys are in order (first key should be "apple")
|
|
289
|
-
* assert.
|
|
289
|
+
* assert.isTrue(
|
|
290
290
|
* formatted.value.indexOf('"apple"') < formatted.value.indexOf('"mango"'),
|
|
291
291
|
* );
|
|
292
292
|
*
|
|
293
|
-
* assert.
|
|
293
|
+
* assert.isTrue(
|
|
294
294
|
* formatted.value.indexOf('"mango"') < formatted.value.indexOf('"nested"'),
|
|
295
295
|
* );
|
|
296
296
|
*
|
|
297
|
-
* assert.
|
|
297
|
+
* assert.isTrue(
|
|
298
298
|
* formatted.value.indexOf('"nested"') < formatted.value.indexOf('"zebra"'),
|
|
299
299
|
* );
|
|
300
300
|
* }
|
package/src/json/json.test.mts
CHANGED
|
@@ -72,13 +72,13 @@ describe('parse', () => {
|
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
test('should return error for invalid JSON', () => {
|
|
75
|
-
|
|
75
|
+
assert.isTrue(Result.isErr(Json.parse('invalid')));
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
assert.isTrue(Result.isErr(Json.parse('{missing quotes: true}')));
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
assert.isTrue(Result.isErr(Json.parse('[1,2,]'))); // Trailing comma
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
assert.isTrue(Result.isErr(Json.parse('undefined')));
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
test('should return parsed value for valid JSON', () => {
|
|
@@ -96,15 +96,15 @@ describe('parse', () => {
|
|
|
96
96
|
});
|
|
97
97
|
|
|
98
98
|
test('should return error for invalid JSON cases', () => {
|
|
99
|
-
|
|
99
|
+
assert.isTrue(Result.isErr(Json.parse('invalid')));
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
assert.isTrue(Result.isErr(Json.parse('{bad json}')));
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
assert.isTrue(Result.isErr(Json.parse('[1,2,]')));
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
assert.isTrue(Result.isErr(Json.parse('undefined')));
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
assert.isTrue(Result.isErr(Json.parse('')));
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
test('should handle edge cases', () => {
|
|
@@ -138,10 +138,9 @@ describe('parse', () => {
|
|
|
138
138
|
|
|
139
139
|
const result = Json.parse(jsonString, dateReviver);
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
assert.isTrue(Result.isOk(result));
|
|
142
142
|
|
|
143
143
|
if (
|
|
144
|
-
Result.isOk(result) &&
|
|
145
144
|
isRecord(result.value) &&
|
|
146
145
|
hasKey(result.value, 'name') &&
|
|
147
146
|
hasKey(result.value, 'created')
|
|
@@ -166,22 +165,20 @@ describe('parse', () => {
|
|
|
166
165
|
transformReviver,
|
|
167
166
|
);
|
|
168
167
|
|
|
169
|
-
|
|
168
|
+
assert.isTrue(Result.isOk(result));
|
|
170
169
|
|
|
171
|
-
|
|
172
|
-
expect(result.value).toHaveProperty('number');
|
|
170
|
+
expect(result.value).toHaveProperty('number');
|
|
173
171
|
|
|
174
|
-
|
|
172
|
+
expect(result.value).toHaveProperty('text');
|
|
175
173
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
174
|
+
if (
|
|
175
|
+
isRecord(result.value) &&
|
|
176
|
+
hasKey(result.value, 'number') &&
|
|
177
|
+
hasKey(result.value, 'text')
|
|
178
|
+
) {
|
|
179
|
+
expect(result.value.number).toBe(42);
|
|
182
180
|
|
|
183
|
-
|
|
184
|
-
}
|
|
181
|
+
expect(result.value.text).toBe('hello');
|
|
185
182
|
}
|
|
186
183
|
});
|
|
187
184
|
});
|
|
@@ -289,7 +286,7 @@ describe('stringify', () => {
|
|
|
289
286
|
);
|
|
290
287
|
|
|
291
288
|
// BigInt should cause an error
|
|
292
|
-
|
|
289
|
+
assert.isTrue(Result.isErr(Json.stringify(123n)));
|
|
293
290
|
});
|
|
294
291
|
|
|
295
292
|
test('should handle circular references', () => {
|
|
@@ -298,7 +295,7 @@ describe('stringify', () => {
|
|
|
298
295
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
299
296
|
mut_obj.circular = mut_obj;
|
|
300
297
|
|
|
301
|
-
|
|
298
|
+
assert.isTrue(Result.isErr(Json.stringify(mut_obj)));
|
|
302
299
|
});
|
|
303
300
|
|
|
304
301
|
test('should handle objects with toJSON method', () => {
|
|
@@ -346,13 +343,11 @@ describe('stringify', () => {
|
|
|
346
343
|
|
|
347
344
|
const result = Json.stringify(data, secureReplacer);
|
|
348
345
|
|
|
349
|
-
|
|
346
|
+
assert.isTrue(Result.isOk(result));
|
|
350
347
|
|
|
351
|
-
|
|
352
|
-
expect(result.value).toContain('[REDACTED]');
|
|
348
|
+
expect(result.value).toContain('[REDACTED]');
|
|
353
349
|
|
|
354
|
-
|
|
355
|
-
}
|
|
350
|
+
expect(result.value).not.toContain('secret123');
|
|
356
351
|
});
|
|
357
352
|
|
|
358
353
|
test('should format output with space parameter (number)', () => {
|
|
@@ -360,13 +355,11 @@ describe('stringify', () => {
|
|
|
360
355
|
|
|
361
356
|
const result = Json.stringify(data, undefined, 2);
|
|
362
357
|
|
|
363
|
-
|
|
358
|
+
assert.isTrue(Result.isOk(result));
|
|
364
359
|
|
|
365
|
-
|
|
366
|
-
expect(result.value).toContain('\n');
|
|
360
|
+
expect(result.value).toContain('\n');
|
|
367
361
|
|
|
368
|
-
|
|
369
|
-
}
|
|
362
|
+
expect(result.value).toContain(' '); // 2 spaces indentation
|
|
370
363
|
});
|
|
371
364
|
|
|
372
365
|
test('should format output with space parameter (string)', () => {
|
|
@@ -374,13 +367,11 @@ describe('stringify', () => {
|
|
|
374
367
|
|
|
375
368
|
const result = Json.stringify(data, undefined, '\t');
|
|
376
369
|
|
|
377
|
-
|
|
370
|
+
assert.isTrue(Result.isOk(result));
|
|
378
371
|
|
|
379
|
-
|
|
380
|
-
expect(result.value).toContain('\n');
|
|
372
|
+
expect(result.value).toContain('\n');
|
|
381
373
|
|
|
382
|
-
|
|
383
|
-
}
|
|
374
|
+
expect(result.value).toContain('\t'); // tab indentation
|
|
384
375
|
});
|
|
385
376
|
});
|
|
386
377
|
|
|
@@ -396,23 +387,21 @@ describe('stringifySelected', () => {
|
|
|
396
387
|
|
|
397
388
|
const result = Json.stringifySelected(user, ['id', 'name', 'email']);
|
|
398
389
|
|
|
399
|
-
|
|
390
|
+
assert.isTrue(Result.isOk(result));
|
|
400
391
|
|
|
401
|
-
|
|
402
|
-
assert(isString(result.value));
|
|
392
|
+
assert.isTrue(isString(result.value));
|
|
403
393
|
|
|
404
|
-
|
|
394
|
+
const parsed: unknown = JSON.parse(result.value);
|
|
405
395
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
396
|
+
assert.deepStrictEqual(parsed, {
|
|
397
|
+
id: 1,
|
|
398
|
+
name: 'Alice',
|
|
399
|
+
email: 'alice@example.com',
|
|
400
|
+
});
|
|
411
401
|
|
|
412
|
-
|
|
402
|
+
expect(parsed).not.toHaveProperty('password');
|
|
413
403
|
|
|
414
|
-
|
|
415
|
-
}
|
|
404
|
+
expect(parsed).not.toHaveProperty('lastLogin');
|
|
416
405
|
});
|
|
417
406
|
|
|
418
407
|
test('should work with nested objects', () => {
|
|
@@ -432,31 +421,29 @@ describe('stringifySelected', () => {
|
|
|
432
421
|
'total',
|
|
433
422
|
]);
|
|
434
423
|
|
|
435
|
-
|
|
424
|
+
assert.isTrue(Result.isOk(result));
|
|
436
425
|
|
|
437
|
-
|
|
438
|
-
assert(isString(result.value));
|
|
426
|
+
assert.isTrue(isString(result.value));
|
|
439
427
|
|
|
440
|
-
|
|
428
|
+
const parsed: unknown = JSON.parse(result.value);
|
|
441
429
|
|
|
442
|
-
|
|
443
|
-
|
|
430
|
+
if (isRecord(parsed) && hasKey(parsed, 'users')) {
|
|
431
|
+
assert.isTrue(Arr.isArray(parsed.users));
|
|
444
432
|
|
|
445
|
-
|
|
433
|
+
expect(parsed.users).toHaveLength(2);
|
|
446
434
|
|
|
447
|
-
|
|
448
|
-
|
|
435
|
+
if (Arr.isArray(parsed.users)) {
|
|
436
|
+
assert.deepStrictEqual(parsed.users[0], { id: 1, name: 'Alice' });
|
|
449
437
|
|
|
450
|
-
|
|
451
|
-
|
|
438
|
+
expect(parsed.users[0]).not.toHaveProperty('secret');
|
|
439
|
+
}
|
|
452
440
|
|
|
453
|
-
|
|
454
|
-
|
|
441
|
+
if (isRecord(parsed) && hasKey(parsed, 'metadata')) {
|
|
442
|
+
assert.deepStrictEqual(parsed.metadata, { total: 2 });
|
|
455
443
|
|
|
456
|
-
|
|
444
|
+
expect(parsed.metadata).not.toHaveProperty('page');
|
|
457
445
|
|
|
458
|
-
|
|
459
|
-
}
|
|
446
|
+
expect(parsed.metadata).not.toHaveProperty('internal');
|
|
460
447
|
}
|
|
461
448
|
}
|
|
462
449
|
});
|
|
@@ -470,19 +457,17 @@ describe('stringifySelected', () => {
|
|
|
470
457
|
|
|
471
458
|
const result = Json.stringifySelected(matrix, [0, 1]);
|
|
472
459
|
|
|
473
|
-
|
|
460
|
+
assert.isTrue(Result.isOk(result));
|
|
474
461
|
|
|
475
|
-
|
|
476
|
-
assert(isString(result.value));
|
|
462
|
+
assert.isTrue(isString(result.value));
|
|
477
463
|
|
|
478
|
-
|
|
464
|
+
const parsed: unknown = JSON.parse(result.value);
|
|
479
465
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
466
|
+
// Note: stringifySelected works with JSON.stringify's replacer parameter
|
|
467
|
+
// which may not work as expected with arrays
|
|
468
|
+
assert.isTrue(Array.isArray(parsed));
|
|
483
469
|
|
|
484
|
-
|
|
485
|
-
}
|
|
470
|
+
expect(parsed).toHaveLength(3);
|
|
486
471
|
});
|
|
487
472
|
|
|
488
473
|
test('should handle formatting with space parameter', () => {
|
|
@@ -490,13 +475,11 @@ describe('stringifySelected', () => {
|
|
|
490
475
|
|
|
491
476
|
const result = Json.stringifySelected(data, ['a', 'b', 'c'], 2);
|
|
492
477
|
|
|
493
|
-
|
|
478
|
+
assert.isTrue(Result.isOk(result));
|
|
494
479
|
|
|
495
|
-
|
|
496
|
-
expect(result.value).toContain('\n');
|
|
480
|
+
expect(result.value).toContain('\n');
|
|
497
481
|
|
|
498
|
-
|
|
499
|
-
}
|
|
482
|
+
expect(result.value).toContain(' ');
|
|
500
483
|
});
|
|
501
484
|
|
|
502
485
|
test('should handle empty selection array', () => {
|
|
@@ -504,11 +487,9 @@ describe('stringifySelected', () => {
|
|
|
504
487
|
|
|
505
488
|
const result = Json.stringifySelected(data, []);
|
|
506
489
|
|
|
507
|
-
|
|
490
|
+
assert.isTrue(Result.isOk(result));
|
|
508
491
|
|
|
509
|
-
|
|
510
|
-
expect(result.value).toBe('{}');
|
|
511
|
-
}
|
|
492
|
+
expect(result.value).toBe('{}');
|
|
512
493
|
});
|
|
513
494
|
|
|
514
495
|
test('should handle undefined properties parameter', () => {
|
|
@@ -516,15 +497,13 @@ describe('stringifySelected', () => {
|
|
|
516
497
|
|
|
517
498
|
const result = Json.stringifySelected(data, undefined);
|
|
518
499
|
|
|
519
|
-
|
|
500
|
+
assert.isTrue(Result.isOk(result));
|
|
520
501
|
|
|
521
|
-
|
|
522
|
-
assert(isString(result.value));
|
|
502
|
+
assert.isTrue(isString(result.value));
|
|
523
503
|
|
|
524
|
-
|
|
504
|
+
const parsed: unknown = JSON.parse(result.value);
|
|
525
505
|
|
|
526
|
-
|
|
527
|
-
}
|
|
506
|
+
assert.deepStrictEqual(parsed, { a: 1, b: 2 });
|
|
528
507
|
});
|
|
529
508
|
|
|
530
509
|
test('should handle circular references with error', () => {
|
|
@@ -537,7 +516,7 @@ describe('stringifySelected', () => {
|
|
|
537
516
|
const result = Json.stringifySelected(mut_circular, ['name', 'self']);
|
|
538
517
|
|
|
539
518
|
// Note: JSON.stringify may handle circular references differently depending on the replacer
|
|
540
|
-
|
|
519
|
+
assert.isTrue(Result.isOk(result) || Result.isErr(result));
|
|
541
520
|
|
|
542
521
|
if (Result.isErr(result)) {
|
|
543
522
|
expectTypeOf(result.value).toBeString();
|
|
@@ -556,13 +535,11 @@ describe('stringifySortedKey', () => {
|
|
|
556
535
|
|
|
557
536
|
const result = Json.stringifySortedKey(unsortedObj);
|
|
558
537
|
|
|
559
|
-
|
|
538
|
+
assert.isTrue(Result.isOk(result));
|
|
560
539
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
);
|
|
565
|
-
}
|
|
540
|
+
expect(result.value).toBe(
|
|
541
|
+
'{"aardvark":"animal","apple":"fruit","banana":"fruit","zebra":"animal"}',
|
|
542
|
+
);
|
|
566
543
|
});
|
|
567
544
|
|
|
568
545
|
test('should sort nested object keys', () => {
|
|
@@ -584,28 +561,26 @@ describe('stringifySortedKey', () => {
|
|
|
584
561
|
|
|
585
562
|
const result = Json.stringifySortedKey(nestedObj);
|
|
586
563
|
|
|
587
|
-
|
|
564
|
+
assert.isTrue(Result.isOk(result));
|
|
588
565
|
|
|
589
|
-
|
|
590
|
-
assert(isString(result.value));
|
|
566
|
+
assert.isTrue(isString(result.value));
|
|
591
567
|
|
|
592
|
-
|
|
568
|
+
const parsed: unknown = JSON.parse(result.value);
|
|
593
569
|
|
|
594
|
-
|
|
595
|
-
|
|
570
|
+
if (isRecord(parsed)) {
|
|
571
|
+
const keys = Object.keys(parsed);
|
|
596
572
|
|
|
597
|
-
|
|
573
|
+
assert.deepStrictEqual(keys, ['settings', 'user']); // sorted top-level keys
|
|
598
574
|
|
|
599
|
-
|
|
600
|
-
|
|
575
|
+
if (hasKey(parsed, 'user') && isRecord(parsed.user)) {
|
|
576
|
+
const userKeys = Object.keys(parsed.user);
|
|
601
577
|
|
|
602
|
-
|
|
578
|
+
assert.deepStrictEqual(userKeys, ['address', 'age', 'name']); // sorted nested keys
|
|
603
579
|
|
|
604
|
-
|
|
605
|
-
|
|
580
|
+
if (hasKey(parsed.user, 'address') && isRecord(parsed.user.address)) {
|
|
581
|
+
const addressKeys = Object.keys(parsed.user.address);
|
|
606
582
|
|
|
607
|
-
|
|
608
|
-
}
|
|
583
|
+
assert.deepStrictEqual(addressKeys, ['city', 'country', 'zip']); // sorted deeper nested keys
|
|
609
584
|
}
|
|
610
585
|
}
|
|
611
586
|
}
|
|
@@ -626,43 +601,37 @@ describe('stringifySortedKey', () => {
|
|
|
626
601
|
|
|
627
602
|
const result = Json.stringifySortedKey(dataWithArrays);
|
|
628
603
|
|
|
629
|
-
|
|
604
|
+
assert.isTrue(Result.isOk(result));
|
|
630
605
|
|
|
631
|
-
|
|
632
|
-
assert(isString(result.value));
|
|
606
|
+
assert.isTrue(isString(result.value));
|
|
633
607
|
|
|
634
|
-
|
|
608
|
+
const parsed: unknown = JSON.parse(result.value);
|
|
635
609
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
610
|
+
if (isRecord(parsed)) {
|
|
611
|
+
// Check top-level keys are sorted
|
|
612
|
+
const topKeys = Object.keys(parsed);
|
|
639
613
|
|
|
640
|
-
|
|
614
|
+
assert.deepStrictEqual(topKeys, ['metadata', 'users']);
|
|
641
615
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
616
|
+
// Check metadata keys are sorted
|
|
617
|
+
if (hasKey(parsed, 'metadata') && isRecord(parsed.metadata)) {
|
|
618
|
+
const metadataKeys = Object.keys(parsed.metadata);
|
|
645
619
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
'created',
|
|
649
|
-
'version',
|
|
650
|
-
]);
|
|
651
|
-
}
|
|
620
|
+
assert.deepStrictEqual(metadataKeys, ['author', 'created', 'version']);
|
|
621
|
+
}
|
|
652
622
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
623
|
+
// Check user object keys are sorted
|
|
624
|
+
if (
|
|
625
|
+
hasKey(parsed, 'users') &&
|
|
626
|
+
Arr.isArray(parsed.users) &&
|
|
627
|
+
Arr.isNonEmpty(parsed.users)
|
|
628
|
+
) {
|
|
629
|
+
const firstUser = parsed.users[0];
|
|
660
630
|
|
|
661
|
-
|
|
662
|
-
|
|
631
|
+
if (isRecord(firstUser)) {
|
|
632
|
+
const userKeys = Object.keys(firstUser);
|
|
663
633
|
|
|
664
|
-
|
|
665
|
-
}
|
|
634
|
+
assert.deepStrictEqual(userKeys, ['active', 'id', 'name']);
|
|
666
635
|
}
|
|
667
636
|
}
|
|
668
637
|
}
|
|
@@ -673,15 +642,13 @@ describe('stringifySortedKey', () => {
|
|
|
673
642
|
|
|
674
643
|
const result = Json.stringifySortedKey(obj, 2);
|
|
675
644
|
|
|
676
|
-
|
|
645
|
+
assert.isTrue(Result.isOk(result));
|
|
677
646
|
|
|
678
|
-
|
|
679
|
-
expect(result.value).toContain('\n');
|
|
647
|
+
expect(result.value).toContain('\n');
|
|
680
648
|
|
|
681
|
-
|
|
649
|
+
expect(result.value).toContain(' ');
|
|
682
650
|
|
|
683
|
-
|
|
684
|
-
}
|
|
651
|
+
expect(result.value).toMatch(/\{\s+"a": 1,\s+"b": 2\s+\}/u);
|
|
685
652
|
});
|
|
686
653
|
|
|
687
654
|
test('should produce deterministic output', () => {
|
|
@@ -693,13 +660,11 @@ describe('stringifySortedKey', () => {
|
|
|
693
660
|
|
|
694
661
|
const result2 = Json.stringifySortedKey(obj2);
|
|
695
662
|
|
|
696
|
-
|
|
663
|
+
assert.isTrue(Result.isOk(result1));
|
|
697
664
|
|
|
698
|
-
|
|
665
|
+
assert.isTrue(Result.isOk(result2));
|
|
699
666
|
|
|
700
|
-
|
|
701
|
-
expect(result1.value).toBe(result2.value);
|
|
702
|
-
}
|
|
667
|
+
expect(result1.value).toBe(result2.value);
|
|
703
668
|
});
|
|
704
669
|
|
|
705
670
|
test('should handle problematic objects', () => {
|
|
@@ -719,7 +684,7 @@ describe('stringifySortedKey', () => {
|
|
|
719
684
|
const result = Json.stringifySortedKey(mut_problematicObj);
|
|
720
685
|
|
|
721
686
|
// This may throw due to circular reference during key extraction
|
|
722
|
-
|
|
687
|
+
assert.isTrue(Result.isErr(result));
|
|
723
688
|
|
|
724
689
|
if (Result.isErr(result)) {
|
|
725
690
|
expectTypeOf(result.value).toBeString();
|
|
@@ -733,11 +698,9 @@ describe('stringifySortedKey', () => {
|
|
|
733
698
|
test('should handle empty object', () => {
|
|
734
699
|
const result = Json.stringifySortedKey({});
|
|
735
700
|
|
|
736
|
-
|
|
701
|
+
assert.isTrue(Result.isOk(result));
|
|
737
702
|
|
|
738
|
-
|
|
739
|
-
expect(result.value).toBe('{}');
|
|
740
|
-
}
|
|
703
|
+
expect(result.value).toBe('{}');
|
|
741
704
|
});
|
|
742
705
|
|
|
743
706
|
test('should handle deeply nested structures', () => {
|
|
@@ -755,29 +718,27 @@ describe('stringifySortedKey', () => {
|
|
|
755
718
|
|
|
756
719
|
const result = Json.stringifySortedKey(deep);
|
|
757
720
|
|
|
758
|
-
|
|
721
|
+
assert.isTrue(Result.isOk(result));
|
|
759
722
|
|
|
760
|
-
|
|
761
|
-
assert(isString(result.value));
|
|
723
|
+
assert.isTrue(isString(result.value));
|
|
762
724
|
|
|
763
|
-
|
|
725
|
+
const parsed: unknown = JSON.parse(result.value);
|
|
764
726
|
|
|
765
|
-
|
|
766
|
-
|
|
727
|
+
if (isRecord(parsed) && hasKey(parsed, 'level1')) {
|
|
728
|
+
const level1 = parsed.level1;
|
|
767
729
|
|
|
768
|
-
|
|
769
|
-
|
|
730
|
+
if (isRecord(level1)) {
|
|
731
|
+
assert.deepStrictEqual(Object.keys(level1), ['a', 'z']);
|
|
770
732
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
733
|
+
if (
|
|
734
|
+
hasKey(level1, 'a') &&
|
|
735
|
+
isRecord(level1.a) &&
|
|
736
|
+
hasKey(level1.a, 'nested')
|
|
737
|
+
) {
|
|
738
|
+
const nested = level1.a.nested;
|
|
777
739
|
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
}
|
|
740
|
+
if (isRecord(nested)) {
|
|
741
|
+
assert.deepStrictEqual(Object.keys(nested), ['x', 'y']);
|
|
781
742
|
}
|
|
782
743
|
}
|
|
783
744
|
}
|