ts-data-forge 4.0.0 → 5.0.0
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/dist/entry-point.mjs +2 -0
- package/dist/entry-point.mjs.map +1 -1
- package/dist/functional/index.d.mts +1 -0
- package/dist/functional/index.d.mts.map +1 -1
- package/dist/functional/index.mjs +2 -0
- package/dist/functional/index.mjs.map +1 -1
- package/dist/functional/ternary-result/impl/index.d.mts +29 -0
- package/dist/functional/ternary-result/impl/index.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/index.mjs +28 -0
- package/dist/functional/ternary-result/impl/index.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/tag.d.mts +7 -0
- package/dist/functional/ternary-result/impl/tag.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/tag.mjs +9 -0
- package/dist/functional/ternary-result/impl/tag.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-err.d.mts +14 -0
- package/dist/functional/ternary-result/impl/ternary-result-err.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-err.mjs +21 -0
- package/dist/functional/ternary-result/impl/ternary-result-err.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-expect-to-be.d.mts +18 -0
- package/dist/functional/ternary-result/impl/ternary-result-expect-to-be.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-expect-to-be.mjs +24 -0
- package/dist/functional/ternary-result/impl/ternary-result-expect-to-be.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-flat-map.d.mts +29 -0
- package/dist/functional/ternary-result/impl/ternary-result-flat-map.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-flat-map.mjs +41 -0
- package/dist/functional/ternary-result/impl/ternary-result-flat-map.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-fold.d.mts +27 -0
- package/dist/functional/ternary-result/impl/ternary-result-fold.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-fold.mjs +36 -0
- package/dist/functional/ternary-result/impl/ternary-result-fold.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-from-promise.d.mts +20 -0
- package/dist/functional/ternary-result/impl/ternary-result-from-promise.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-from-promise.mjs +24 -0
- package/dist/functional/ternary-result/impl/ternary-result-from-promise.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.d.mts +17 -0
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.mjs +33 -0
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-err.d.mts +20 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-err.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-err.mjs +23 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-err.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-ok.d.mts +21 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-ok.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-ok.mjs +24 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-ok.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-ternary-result.d.mts +17 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-ternary-result.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-ternary-result.mjs +28 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-ternary-result.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-warn.d.mts +21 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-warn.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-warn.mjs +24 -0
- package/dist/functional/ternary-result/impl/ternary-result-is-warn.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-map-err.d.mts +23 -0
- package/dist/functional/ternary-result/impl/ternary-result-map-err.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-map-err.mjs +26 -0
- package/dist/functional/ternary-result/impl/ternary-result-map-err.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-map-warn.d.mts +21 -0
- package/dist/functional/ternary-result/impl/ternary-result-map-warn.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-map-warn.mjs +29 -0
- package/dist/functional/ternary-result/impl/ternary-result-map-warn.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-map.d.mts +29 -0
- package/dist/functional/ternary-result/impl/ternary-result-map.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-map.mjs +35 -0
- package/dist/functional/ternary-result/impl/ternary-result-map.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-ok.d.mts +16 -0
- package/dist/functional/ternary-result/impl/ternary-result-ok.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-ok.mjs +23 -0
- package/dist/functional/ternary-result/impl/ternary-result-ok.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-or-else.d.mts +26 -0
- package/dist/functional/ternary-result/impl/ternary-result-or-else.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-or-else.mjs +19 -0
- package/dist/functional/ternary-result/impl/ternary-result-or-else.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-to-optional.d.mts +16 -0
- package/dist/functional/ternary-result/impl/ternary-result-to-optional.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-to-optional.mjs +25 -0
- package/dist/functional/ternary-result/impl/ternary-result-to-optional.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-or.d.mts +22 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-or.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-or.mjs +17 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-or.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-throw.d.mts +18 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-throw.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-throw.mjs +36 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-throw.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err.d.mts +17 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err.mjs +22 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-ok-or.d.mts +22 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-ok-or.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-ok-or.mjs +17 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-ok-or.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-ok.d.mts +17 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-ok.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-ok.mjs +13 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-ok.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-throw.d.mts +18 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-throw.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-throw.mjs +36 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-throw.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-or.d.mts +19 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-or.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-or.mjs +17 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-or.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-throw.d.mts +18 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-throw.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-throw.mjs +32 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-throw.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn.d.mts +17 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn.mjs +22 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-warn.d.mts +18 -0
- package/dist/functional/ternary-result/impl/ternary-result-warn.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-warn.mjs +26 -0
- package/dist/functional/ternary-result/impl/ternary-result-warn.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-zip.d.mts +26 -0
- package/dist/functional/ternary-result/impl/ternary-result-zip.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-zip.mjs +48 -0
- package/dist/functional/ternary-result/impl/ternary-result-zip.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/types.d.mts +25 -0
- package/dist/functional/ternary-result/impl/types.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/types.mjs +2 -0
- package/dist/functional/ternary-result/impl/types.mjs.map +1 -0
- package/dist/functional/ternary-result/impl/variant-name.d.mts +3 -0
- package/dist/functional/ternary-result/impl/variant-name.d.mts.map +1 -0
- package/dist/functional/ternary-result/impl/variant-name.mjs +16 -0
- package/dist/functional/ternary-result/impl/variant-name.mjs.map +1 -0
- package/dist/functional/ternary-result/index.d.mts +2 -0
- package/dist/functional/ternary-result/index.d.mts.map +1 -0
- package/dist/functional/ternary-result/index.mjs +3 -0
- package/dist/functional/ternary-result/index.mjs.map +1 -0
- package/dist/globals.d.mts +55 -2
- package/dist/json/json.d.mts +9 -3
- package/dist/json/json.d.mts.map +1 -1
- package/dist/json/json.mjs +6 -0
- package/dist/json/json.mjs.map +1 -1
- package/package.json +13 -13
- package/src/array/impl/array-utils-creation.test.mts +187 -74
- package/src/array/impl/array-utils-element-access.test.mts +19 -3
- package/src/array/impl/array-utils-iterators.test.mts +44 -24
- package/src/array/impl/array-utils-modification.test.mts +36 -33
- package/src/array/impl/array-utils-reducing-value.test.mts +47 -16
- package/src/array/impl/array-utils-search.test.mts +42 -9
- package/src/array/impl/array-utils-set-op.test.mts +54 -26
- package/src/array/impl/array-utils-size.test.mts +1 -0
- package/src/array/impl/array-utils-slice-clamped.test.mts +20 -11
- package/src/array/impl/array-utils-slicing.test.mts +27 -21
- package/src/array/impl/array-utils-transformation.test.mts +140 -92
- package/src/array/impl/array-utils-validation.test.mts +58 -10
- package/src/array/impl/array.test.mts +5 -5
- package/src/collections/imap-mapped.test.mts +63 -18
- package/src/collections/imap.test.mts +74 -26
- package/src/collections/iset-mapped.test.mts +81 -30
- package/src/collections/iset.test.mts +168 -68
- package/src/collections/queue.test.mts +32 -1
- package/src/collections/stack.test.mts +22 -8
- package/src/functional/index.mts +1 -0
- package/src/functional/match.test.mts +1 -1
- package/src/functional/optional.test.mts +61 -4
- package/src/functional/pipe.test.mts +10 -1
- package/src/functional/result.test.mts +127 -4
- package/src/functional/ternary-result/impl/index.mts +28 -0
- package/src/functional/ternary-result/impl/tag.mts +11 -0
- package/src/functional/ternary-result/impl/ternary-result-err.mts +18 -0
- package/src/functional/ternary-result/impl/ternary-result-expect-to-be.mts +53 -0
- package/src/functional/ternary-result/impl/ternary-result-flat-map.mts +95 -0
- package/src/functional/ternary-result/impl/ternary-result-fold.mts +93 -0
- package/src/functional/ternary-result/impl/ternary-result-from-promise.mts +27 -0
- package/src/functional/ternary-result/impl/ternary-result-from-throwable.mts +31 -0
- package/src/functional/ternary-result/impl/ternary-result-is-err.mts +23 -0
- package/src/functional/ternary-result/impl/ternary-result-is-ok.mts +24 -0
- package/src/functional/ternary-result/impl/ternary-result-is-ternary-result.mts +27 -0
- package/src/functional/ternary-result/impl/ternary-result-is-warn.mts +24 -0
- package/src/functional/ternary-result/impl/ternary-result-map-err.mts +64 -0
- package/src/functional/ternary-result/impl/ternary-result-map-warn.mts +66 -0
- package/src/functional/ternary-result/impl/ternary-result-map.mts +81 -0
- package/src/functional/ternary-result/impl/ternary-result-ok.mts +20 -0
- package/src/functional/ternary-result/impl/ternary-result-or-else.mts +66 -0
- package/src/functional/ternary-result/impl/ternary-result-to-optional.mts +25 -0
- package/src/functional/ternary-result/impl/ternary-result-unwrap-err-or.mts +45 -0
- package/src/functional/ternary-result/impl/ternary-result-unwrap-err-throw.mts +40 -0
- package/src/functional/ternary-result/impl/ternary-result-unwrap-err.mts +22 -0
- package/src/functional/ternary-result/impl/ternary-result-unwrap-ok-or.mts +45 -0
- package/src/functional/ternary-result/impl/ternary-result-unwrap-ok.mts +32 -0
- package/src/functional/ternary-result/impl/ternary-result-unwrap-throw.mts +45 -0
- package/src/functional/ternary-result/impl/ternary-result-unwrap-warn-or.mts +42 -0
- package/src/functional/ternary-result/impl/ternary-result-unwrap-warn-throw.mts +38 -0
- package/src/functional/ternary-result/impl/ternary-result-unwrap-warn.mts +22 -0
- package/src/functional/ternary-result/impl/ternary-result-warn.mts +23 -0
- package/src/functional/ternary-result/impl/ternary-result-zip.mts +53 -0
- package/src/functional/ternary-result/impl/types.mts +39 -0
- package/src/functional/ternary-result/impl/variant-name.mts +17 -0
- package/src/functional/ternary-result/index.mts +1 -0
- package/src/functional/ternary-result.test.mts +214 -0
- package/src/globals.d.mts +55 -2
- package/src/guard/is-non-empty-string.test.mts +5 -2
- package/src/guard/is-non-null-object.test.mts +3 -5
- package/src/guard/is-primitive.test.mts +5 -3
- package/src/guard/is-record.test.mts +1 -1
- package/src/guard/is-type.test.mts +35 -20
- package/src/guard/key-is-in.test.mts +1 -1
- package/src/iterator/range.test.mts +22 -16
- package/src/json/json.mts +9 -3
- package/src/json/json.test.mts +140 -64
- package/src/number/branded-types/finite-number.test.mts +3 -2
- package/src/number/branded-types/int.test.mts +4 -3
- package/src/number/branded-types/int16.test.mts +9 -3
- package/src/number/branded-types/int32.test.mts +9 -3
- package/src/number/branded-types/non-negative-finite-number.test.mts +6 -4
- package/src/number/branded-types/non-negative-int16.test.mts +8 -3
- package/src/number/branded-types/non-negative-int32.test.mts +8 -3
- package/src/number/branded-types/non-zero-finite-number.test.mts +6 -3
- package/src/number/branded-types/non-zero-int.test.mts +6 -3
- package/src/number/branded-types/non-zero-int16.test.mts +9 -3
- package/src/number/branded-types/non-zero-int32.test.mts +9 -3
- package/src/number/branded-types/non-zero-safe-int.test.mts +10 -3
- package/src/number/branded-types/non-zero-uint16.test.mts +8 -3
- package/src/number/branded-types/non-zero-uint32.test.mts +8 -3
- package/src/number/branded-types/positive-finite-number.test.mts +7 -3
- package/src/number/branded-types/positive-int.test.mts +5 -3
- package/src/number/branded-types/positive-int16.test.mts +8 -3
- package/src/number/branded-types/positive-int32.test.mts +8 -3
- package/src/number/branded-types/positive-safe-int.test.mts +8 -3
- package/src/number/branded-types/positive-uint16.test.mts +8 -3
- package/src/number/branded-types/positive-uint32.test.mts +8 -3
- package/src/number/branded-types/safe-int.test.mts +8 -2
- package/src/number/branded-types/safe-uint.test.mts +8 -3
- package/src/number/branded-types/uint.test.mts +5 -3
- package/src/number/branded-types/uint16.test.mts +8 -3
- package/src/number/branded-types/uint32.test.mts +8 -3
- package/src/number/enum/int8.test.mts +8 -3
- package/src/number/enum/uint8.test.mts +6 -3
- package/src/number/num.test.mts +16 -2
- package/src/object/object.test.mts +26 -13
- package/src/others/cast-mutable.test.mts +10 -8
- package/src/others/cast-readonly.test.mts +9 -5
- package/src/others/if-then.test.mts +4 -1
- package/src/others/map-nullable.test.mts +28 -1
- package/src/others/memoize-function.test.mts +20 -17
- package/src/others/tuple.test.mts +3 -2
- package/src/others/unknown-to-string.test.mts +15 -2
- package/src/promise/promise.test.mts +6 -1
|
@@ -1,46 +1,52 @@
|
|
|
1
1
|
import { range } from './range.mjs';
|
|
2
2
|
|
|
3
|
-
describe(
|
|
3
|
+
describe(range, () => {
|
|
4
4
|
test('range(0, 10)', () => {
|
|
5
|
-
|
|
6
|
-
0,
|
|
7
|
-
|
|
5
|
+
assert.deepStrictEqual(
|
|
6
|
+
Array.from(range(0, 10)),
|
|
7
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
|
8
|
+
);
|
|
8
9
|
});
|
|
9
10
|
|
|
10
11
|
test('range(10)', () => {
|
|
11
|
-
|
|
12
|
+
assert.deepStrictEqual(
|
|
13
|
+
Array.from(range(10)),
|
|
14
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
|
15
|
+
);
|
|
12
16
|
});
|
|
13
17
|
|
|
14
18
|
test('range(0)', () => {
|
|
15
|
-
|
|
19
|
+
assert.deepStrictEqual(Array.from(range(0)), []);
|
|
16
20
|
});
|
|
17
21
|
|
|
18
22
|
test('range(-1)', () => {
|
|
19
23
|
// @ts-expect-error negative end is not allowed
|
|
20
|
-
|
|
24
|
+
assert.deepStrictEqual(Array.from(range(-1)), []);
|
|
21
25
|
});
|
|
22
26
|
|
|
23
27
|
test('range(10, 0, -1)', () => {
|
|
24
|
-
|
|
25
|
-
10,
|
|
26
|
-
|
|
28
|
+
assert.deepStrictEqual(
|
|
29
|
+
Array.from(range(10, 0, -1)),
|
|
30
|
+
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
|
|
31
|
+
);
|
|
27
32
|
});
|
|
28
33
|
|
|
29
34
|
test('range(0, -10, -1)', () => {
|
|
30
|
-
|
|
31
|
-
0, -
|
|
32
|
-
|
|
35
|
+
assert.deepStrictEqual(
|
|
36
|
+
Array.from(range(0, -10, -1)),
|
|
37
|
+
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9],
|
|
38
|
+
);
|
|
33
39
|
});
|
|
34
40
|
|
|
35
41
|
test('range(0, 0)', () => {
|
|
36
|
-
|
|
42
|
+
assert.deepStrictEqual(Array.from(range(0, 0)), []);
|
|
37
43
|
});
|
|
38
44
|
|
|
39
45
|
test('range(0, 11, 2)', () => {
|
|
40
|
-
|
|
46
|
+
assert.deepStrictEqual(Array.from(range(0, 11, 2)), [0, 2, 4, 6, 8, 10]);
|
|
41
47
|
});
|
|
42
48
|
|
|
43
49
|
test('range(1, 12, 2)', () => {
|
|
44
|
-
|
|
50
|
+
assert.deepStrictEqual(Array.from(range(1, 12, 2)), [1, 3, 5, 7, 9, 11]);
|
|
45
51
|
});
|
|
46
52
|
});
|
package/src/json/json.mts
CHANGED
|
@@ -108,6 +108,8 @@ export namespace Json {
|
|
|
108
108
|
*
|
|
109
109
|
* assert.ok(Result.isOk(filtered));
|
|
110
110
|
* if (Result.isOk(filtered)) {
|
|
111
|
+
* assert(isString(filtered.value));
|
|
112
|
+
*
|
|
111
113
|
* assert.ok(!filtered.value.includes('age'));
|
|
112
114
|
* }
|
|
113
115
|
* ```
|
|
@@ -136,7 +138,7 @@ export namespace Json {
|
|
|
136
138
|
value: unknown,
|
|
137
139
|
replacer?: (this: unknown, key: string, val: unknown) => unknown,
|
|
138
140
|
space?: UintRangeInclusive<1, 10> | string,
|
|
139
|
-
): Result<string, string> => {
|
|
141
|
+
): Result<string | undefined, string> => {
|
|
140
142
|
try {
|
|
141
143
|
return Result.ok(JSON.stringify(value, replacer, space));
|
|
142
144
|
} catch (error) {
|
|
@@ -170,6 +172,8 @@ export namespace Json {
|
|
|
170
172
|
*
|
|
171
173
|
* assert.ok(Result.isOk(safeJson));
|
|
172
174
|
* if (Result.isOk(safeJson)) {
|
|
175
|
+
* assert(isString(safeJson.value));
|
|
176
|
+
*
|
|
173
177
|
* const parsed: unknown = JSON.parse(safeJson.value);
|
|
174
178
|
* assert.deepStrictEqual(parsed, {
|
|
175
179
|
* id: 1,
|
|
@@ -207,7 +211,7 @@ export namespace Json {
|
|
|
207
211
|
value: unknown,
|
|
208
212
|
propertiesToBeSelected?: readonly (number | string)[],
|
|
209
213
|
space?: UintRangeInclusive<1, 10> | string,
|
|
210
|
-
): Result<string, string> => {
|
|
214
|
+
): Result<string | undefined, string> => {
|
|
211
215
|
try {
|
|
212
216
|
return Result.ok(
|
|
213
217
|
JSON.stringify(value, castMutable(propertiesToBeSelected), space),
|
|
@@ -257,6 +261,8 @@ export namespace Json {
|
|
|
257
261
|
* const formatted = Json.stringifySortedKey(unorderedData, 2);
|
|
258
262
|
* assert.ok(Result.isOk(formatted));
|
|
259
263
|
* if (Result.isOk(formatted)) {
|
|
264
|
+
* assert(isString(formatted.value));
|
|
265
|
+
*
|
|
260
266
|
* // Check that keys are in order (first key should be "apple")
|
|
261
267
|
* assert.ok(
|
|
262
268
|
* formatted.value.indexOf('"apple"') < formatted.value.indexOf('"mango"'),
|
|
@@ -288,7 +294,7 @@ export namespace Json {
|
|
|
288
294
|
export const stringifySortedKey = (
|
|
289
295
|
value: UnknownRecord,
|
|
290
296
|
space?: UintRangeInclusive<1, 10> | string,
|
|
291
|
-
): Result<string, string> => {
|
|
297
|
+
): Result<string | undefined, string> => {
|
|
292
298
|
const allKeys = pipe(keysDeep(value))
|
|
293
299
|
.map((keys) => Arr.uniq(keys))
|
|
294
300
|
.map((ks) => ks.toSorted()).value;
|
package/src/json/json.test.mts
CHANGED
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
import { Arr } from '../array/index.mjs';
|
|
2
2
|
import { Result } from '../functional/index.mjs';
|
|
3
|
-
import { hasKey, isRecord } from '../guard/index.mjs';
|
|
3
|
+
import { hasKey, isRecord, isString } from '../guard/index.mjs';
|
|
4
4
|
import { Json } from './json.mjs';
|
|
5
5
|
|
|
6
6
|
describe('parse', () => {
|
|
7
7
|
test('should parse primitive values', () => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
assert.deepStrictEqual(Json.parse('"hello"'), Result.ok('hello'));
|
|
9
|
+
assert.deepStrictEqual(Json.parse('42'), Result.ok(42));
|
|
10
|
+
assert.deepStrictEqual(Json.parse('true'), Result.ok(true));
|
|
11
|
+
assert.deepStrictEqual(Json.parse('false'), Result.ok(false));
|
|
12
|
+
assert.deepStrictEqual(Json.parse('null'), Result.ok(null));
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
test('should parse arrays', () => {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
assert.deepStrictEqual(Json.parse('[1,2,3]'), Result.ok([1, 2, 3]));
|
|
17
|
+
assert.deepStrictEqual(
|
|
18
|
+
Json.parse('["a","b","c"]'),
|
|
18
19
|
Result.ok(['a', 'b', 'c']),
|
|
19
20
|
);
|
|
20
|
-
|
|
21
|
+
assert.deepStrictEqual(
|
|
22
|
+
Json.parse('[1,"two",true,null]'),
|
|
21
23
|
Result.ok([1, 'two', true, null]),
|
|
22
24
|
);
|
|
23
25
|
});
|
|
24
26
|
|
|
25
27
|
test('should parse objects', () => {
|
|
26
|
-
|
|
28
|
+
assert.deepStrictEqual(
|
|
29
|
+
Json.parse('{"a":1,"b":2}'),
|
|
27
30
|
Result.ok({ a: 1, b: 2 }),
|
|
28
31
|
);
|
|
29
|
-
|
|
32
|
+
assert.deepStrictEqual(
|
|
33
|
+
Json.parse('{"name":"test","value":42}'),
|
|
30
34
|
Result.ok({
|
|
31
35
|
name: 'test',
|
|
32
36
|
value: 42,
|
|
@@ -43,14 +47,17 @@ describe('parse', () => {
|
|
|
43
47
|
},
|
|
44
48
|
},
|
|
45
49
|
};
|
|
46
|
-
|
|
50
|
+
|
|
51
|
+
assert.deepStrictEqual(Json.parse(json), Result.ok(expected));
|
|
47
52
|
});
|
|
48
53
|
|
|
49
54
|
test('should handle whitespace', () => {
|
|
50
|
-
|
|
55
|
+
assert.deepStrictEqual(
|
|
56
|
+
Json.parse(' { "a" : 1 , "b" : 2 } '),
|
|
51
57
|
Result.ok({ a: 1, b: 2 }),
|
|
52
58
|
);
|
|
53
|
-
|
|
59
|
+
assert.deepStrictEqual(
|
|
60
|
+
Json.parse('\n[\n 1,\n 2,\n 3\n]\n'),
|
|
54
61
|
Result.ok([1, 2, 3]),
|
|
55
62
|
);
|
|
56
63
|
});
|
|
@@ -63,12 +70,12 @@ describe('parse', () => {
|
|
|
63
70
|
});
|
|
64
71
|
|
|
65
72
|
test('should return parsed value for valid JSON', () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
assert.deepStrictEqual(Json.parse('{"a":1}'), Result.ok({ a: 1 }));
|
|
74
|
+
assert.deepStrictEqual(Json.parse('[1,2,3]'), Result.ok([1, 2, 3]));
|
|
75
|
+
assert.deepStrictEqual(Json.parse('"string"'), Result.ok('string'));
|
|
76
|
+
assert.deepStrictEqual(Json.parse('42'), Result.ok(42));
|
|
77
|
+
assert.deepStrictEqual(Json.parse('true'), Result.ok(true));
|
|
78
|
+
assert.deepStrictEqual(Json.parse('null'), Result.ok(null));
|
|
72
79
|
});
|
|
73
80
|
|
|
74
81
|
test('should return error for invalid JSON cases', () => {
|
|
@@ -80,10 +87,10 @@ describe('parse', () => {
|
|
|
80
87
|
});
|
|
81
88
|
|
|
82
89
|
test('should handle edge cases', () => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
assert.deepStrictEqual(Json.parse('0'), Result.ok(0));
|
|
91
|
+
assert.deepStrictEqual(Json.parse('""'), Result.ok(''));
|
|
92
|
+
assert.deepStrictEqual(Json.parse('[]'), Result.ok([]));
|
|
93
|
+
assert.deepStrictEqual(Json.parse('{}'), Result.ok({}));
|
|
87
94
|
});
|
|
88
95
|
|
|
89
96
|
test('should not throw errors', () => {
|
|
@@ -105,6 +112,7 @@ describe('parse', () => {
|
|
|
105
112
|
const result = Json.parse(jsonString, dateReviver);
|
|
106
113
|
|
|
107
114
|
expect(Result.isOk(result)).toBe(true);
|
|
115
|
+
|
|
108
116
|
if (
|
|
109
117
|
Result.isOk(result) &&
|
|
110
118
|
isRecord(result.value) &&
|
|
@@ -130,9 +138,11 @@ describe('parse', () => {
|
|
|
130
138
|
);
|
|
131
139
|
|
|
132
140
|
expect(Result.isOk(result)).toBe(true);
|
|
141
|
+
|
|
133
142
|
if (Result.isOk(result)) {
|
|
134
143
|
expect(result.value).toHaveProperty('number');
|
|
135
144
|
expect(result.value).toHaveProperty('text');
|
|
145
|
+
|
|
136
146
|
if (
|
|
137
147
|
isRecord(result.value) &&
|
|
138
148
|
hasKey(result.value, 'number') &&
|
|
@@ -147,27 +157,31 @@ describe('parse', () => {
|
|
|
147
157
|
|
|
148
158
|
describe('stringify', () => {
|
|
149
159
|
test('should stringify primitive values', () => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
160
|
+
assert.deepStrictEqual(Json.stringify('hello'), Result.ok('"hello"'));
|
|
161
|
+
assert.deepStrictEqual(Json.stringify(42), Result.ok('42'));
|
|
162
|
+
assert.deepStrictEqual(Json.stringify(true), Result.ok('true'));
|
|
163
|
+
assert.deepStrictEqual(Json.stringify(null), Result.ok('null'));
|
|
154
164
|
});
|
|
155
165
|
|
|
156
166
|
test('should stringify arrays', () => {
|
|
157
|
-
|
|
158
|
-
|
|
167
|
+
assert.deepStrictEqual(Json.stringify([1, 2, 3]), Result.ok('[1,2,3]'));
|
|
168
|
+
assert.deepStrictEqual(
|
|
169
|
+
Json.stringify(['a', 'b', 'c']),
|
|
159
170
|
Result.ok('["a","b","c"]'),
|
|
160
171
|
);
|
|
161
|
-
|
|
172
|
+
assert.deepStrictEqual(
|
|
173
|
+
Json.stringify([1, 'two', true, null]),
|
|
162
174
|
Result.ok('[1,"two",true,null]'),
|
|
163
175
|
);
|
|
164
176
|
});
|
|
165
177
|
|
|
166
178
|
test('should stringify objects', () => {
|
|
167
|
-
|
|
179
|
+
assert.deepStrictEqual(
|
|
180
|
+
Json.stringify({ a: 1, b: 2 }),
|
|
168
181
|
Result.ok('{"a":1,"b":2}'),
|
|
169
182
|
);
|
|
170
|
-
|
|
183
|
+
assert.deepStrictEqual(
|
|
184
|
+
Json.stringify({ name: 'test', value: 42 }),
|
|
171
185
|
Result.ok('{"name":"test","value":42}'),
|
|
172
186
|
);
|
|
173
187
|
});
|
|
@@ -180,41 +194,53 @@ describe('stringify', () => {
|
|
|
180
194
|
},
|
|
181
195
|
},
|
|
182
196
|
};
|
|
183
|
-
|
|
197
|
+
|
|
198
|
+
assert.deepStrictEqual(
|
|
199
|
+
Json.stringify(nested),
|
|
184
200
|
Result.ok('{"level1":{"level2":{"array":[1,2,{"level3":"deep"}]}}}'),
|
|
185
201
|
);
|
|
186
202
|
});
|
|
187
203
|
|
|
188
204
|
test('should handle empty structures', () => {
|
|
189
|
-
|
|
190
|
-
|
|
205
|
+
assert.deepStrictEqual(Json.stringify({}), Result.ok('{}'));
|
|
206
|
+
assert.deepStrictEqual(Json.stringify([]), Result.ok('[]'));
|
|
191
207
|
});
|
|
192
208
|
|
|
193
209
|
test('should handle special string values', () => {
|
|
194
|
-
|
|
210
|
+
assert.deepStrictEqual(
|
|
211
|
+
Json.stringify('with "quotes"'),
|
|
195
212
|
Result.ok(String.raw`"with \"quotes\""`),
|
|
196
213
|
);
|
|
197
|
-
|
|
214
|
+
assert.deepStrictEqual(
|
|
215
|
+
Json.stringify('with\nnewline'),
|
|
198
216
|
Result.ok(String.raw`"with\nnewline"`),
|
|
199
217
|
);
|
|
200
|
-
|
|
218
|
+
assert.deepStrictEqual(
|
|
219
|
+
Json.stringify('with\ttab'),
|
|
201
220
|
Result.ok(String.raw`"with\ttab"`),
|
|
202
221
|
);
|
|
203
222
|
});
|
|
204
223
|
|
|
205
224
|
test('should return stringified value for valid JSON values', () => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
225
|
+
assert.deepStrictEqual(Json.stringify({ a: 1 }), Result.ok('{"a":1}'));
|
|
226
|
+
assert.deepStrictEqual(Json.stringify([1, 2, 3]), Result.ok('[1,2,3]'));
|
|
227
|
+
assert.deepStrictEqual(Json.stringify('string'), Result.ok('"string"'));
|
|
228
|
+
assert.deepStrictEqual(Json.stringify(42), Result.ok('42'));
|
|
229
|
+
assert.deepStrictEqual(Json.stringify(true), Result.ok('true'));
|
|
230
|
+
assert.deepStrictEqual(Json.stringify(null), Result.ok('null'));
|
|
212
231
|
});
|
|
213
232
|
|
|
214
233
|
test('should handle non-serializable values', () => {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
234
|
+
assert.deepStrictEqual(Json.stringify(undefined), Result.ok(undefined));
|
|
235
|
+
assert.deepStrictEqual(
|
|
236
|
+
Json.stringify(Symbol('test')),
|
|
237
|
+
Result.ok(undefined),
|
|
238
|
+
);
|
|
239
|
+
assert.deepStrictEqual(
|
|
240
|
+
Json.stringify(() => {}),
|
|
241
|
+
Result.ok(undefined),
|
|
242
|
+
);
|
|
243
|
+
|
|
218
244
|
// BigInt should cause an error
|
|
219
245
|
expect(Result.isErr(Json.stringify(123n))).toBe(true);
|
|
220
246
|
});
|
|
@@ -223,6 +249,7 @@ describe('stringify', () => {
|
|
|
223
249
|
const mut_obj: any = { a: 1 };
|
|
224
250
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
225
251
|
mut_obj.circular = mut_obj;
|
|
252
|
+
|
|
226
253
|
expect(Result.isErr(Json.stringify(mut_obj))).toBe(true);
|
|
227
254
|
});
|
|
228
255
|
|
|
@@ -230,12 +257,18 @@ describe('stringify', () => {
|
|
|
230
257
|
const obj = {
|
|
231
258
|
toJSON: () => ({ custom: 'value' }),
|
|
232
259
|
};
|
|
233
|
-
|
|
260
|
+
|
|
261
|
+
assert.deepStrictEqual(
|
|
262
|
+
Json.stringify(obj),
|
|
263
|
+
Result.ok('{"custom":"value"}'),
|
|
264
|
+
);
|
|
234
265
|
});
|
|
235
266
|
|
|
236
267
|
test('should handle Date objects', () => {
|
|
237
268
|
const date = new Date('2023-01-01T00:00:00.000Z');
|
|
238
|
-
|
|
269
|
+
|
|
270
|
+
assert.deepStrictEqual(
|
|
271
|
+
Json.stringify(date),
|
|
239
272
|
Result.ok('"2023-01-01T00:00:00.000Z"'),
|
|
240
273
|
);
|
|
241
274
|
});
|
|
@@ -263,6 +296,7 @@ describe('stringify', () => {
|
|
|
263
296
|
const result = Json.stringify(data, secureReplacer);
|
|
264
297
|
|
|
265
298
|
expect(Result.isOk(result)).toBe(true);
|
|
299
|
+
|
|
266
300
|
if (Result.isOk(result)) {
|
|
267
301
|
expect(result.value).toContain('[REDACTED]');
|
|
268
302
|
expect(result.value).not.toContain('secret123');
|
|
@@ -274,6 +308,7 @@ describe('stringify', () => {
|
|
|
274
308
|
const result = Json.stringify(data, undefined, 2);
|
|
275
309
|
|
|
276
310
|
expect(Result.isOk(result)).toBe(true);
|
|
311
|
+
|
|
277
312
|
if (Result.isOk(result)) {
|
|
278
313
|
expect(result.value).toContain('\n');
|
|
279
314
|
expect(result.value).toContain(' '); // 2 spaces indentation
|
|
@@ -285,6 +320,7 @@ describe('stringify', () => {
|
|
|
285
320
|
const result = Json.stringify(data, undefined, '\t');
|
|
286
321
|
|
|
287
322
|
expect(Result.isOk(result)).toBe(true);
|
|
323
|
+
|
|
288
324
|
if (Result.isOk(result)) {
|
|
289
325
|
expect(result.value).toContain('\n');
|
|
290
326
|
expect(result.value).toContain('\t'); // tab indentation
|
|
@@ -305,13 +341,18 @@ describe('stringifySelected', () => {
|
|
|
305
341
|
const result = Json.stringifySelected(user, ['id', 'name', 'email']);
|
|
306
342
|
|
|
307
343
|
expect(Result.isOk(result)).toBe(true);
|
|
344
|
+
|
|
308
345
|
if (Result.isOk(result)) {
|
|
346
|
+
assert(isString(result.value));
|
|
347
|
+
|
|
309
348
|
const parsed: unknown = JSON.parse(result.value);
|
|
310
|
-
|
|
349
|
+
|
|
350
|
+
assert.deepStrictEqual(parsed, {
|
|
311
351
|
id: 1,
|
|
312
352
|
name: 'Alice',
|
|
313
353
|
email: 'alice@example.com',
|
|
314
354
|
});
|
|
355
|
+
|
|
315
356
|
expect(parsed).not.toHaveProperty('password');
|
|
316
357
|
expect(parsed).not.toHaveProperty('lastLogin');
|
|
317
358
|
}
|
|
@@ -335,17 +376,22 @@ describe('stringifySelected', () => {
|
|
|
335
376
|
]);
|
|
336
377
|
|
|
337
378
|
expect(Result.isOk(result)).toBe(true);
|
|
379
|
+
|
|
338
380
|
if (Result.isOk(result)) {
|
|
381
|
+
assert(isString(result.value));
|
|
339
382
|
const parsed: unknown = JSON.parse(result.value);
|
|
340
383
|
if (isRecord(parsed) && hasKey(parsed, 'users')) {
|
|
341
384
|
expect(isRecord(parsed.users)).toBe(false);
|
|
342
385
|
expect(parsed.users).toHaveLength(2);
|
|
386
|
+
|
|
343
387
|
if (Arr.isArray(parsed.users)) {
|
|
344
|
-
|
|
388
|
+
assert.deepStrictEqual(parsed.users[0], { id: 1, name: 'Alice' });
|
|
389
|
+
|
|
345
390
|
expect(parsed.users[0]).not.toHaveProperty('secret');
|
|
346
391
|
}
|
|
347
392
|
if (isRecord(parsed) && hasKey(parsed, 'metadata')) {
|
|
348
|
-
|
|
393
|
+
assert.deepStrictEqual(parsed.metadata, { total: 2 });
|
|
394
|
+
|
|
349
395
|
expect(parsed.metadata).not.toHaveProperty('page');
|
|
350
396
|
expect(parsed.metadata).not.toHaveProperty('internal');
|
|
351
397
|
}
|
|
@@ -363,8 +409,11 @@ describe('stringifySelected', () => {
|
|
|
363
409
|
const result = Json.stringifySelected(matrix, [0, 1]);
|
|
364
410
|
|
|
365
411
|
expect(Result.isOk(result)).toBe(true);
|
|
412
|
+
|
|
366
413
|
if (Result.isOk(result)) {
|
|
414
|
+
assert(isString(result.value));
|
|
367
415
|
const parsed: unknown = JSON.parse(result.value);
|
|
416
|
+
|
|
368
417
|
// Note: stringifySelected works with JSON.stringify's replacer parameter
|
|
369
418
|
// which may not work as expected with arrays
|
|
370
419
|
expect(Array.isArray(parsed)).toBe(true);
|
|
@@ -377,6 +426,7 @@ describe('stringifySelected', () => {
|
|
|
377
426
|
const result = Json.stringifySelected(data, ['a', 'b', 'c'], 2);
|
|
378
427
|
|
|
379
428
|
expect(Result.isOk(result)).toBe(true);
|
|
429
|
+
|
|
380
430
|
if (Result.isOk(result)) {
|
|
381
431
|
expect(result.value).toContain('\n');
|
|
382
432
|
expect(result.value).toContain(' ');
|
|
@@ -388,6 +438,7 @@ describe('stringifySelected', () => {
|
|
|
388
438
|
const result = Json.stringifySelected(data, []);
|
|
389
439
|
|
|
390
440
|
expect(Result.isOk(result)).toBe(true);
|
|
441
|
+
|
|
391
442
|
if (Result.isOk(result)) {
|
|
392
443
|
expect(result.value).toBe('{}');
|
|
393
444
|
}
|
|
@@ -398,9 +449,12 @@ describe('stringifySelected', () => {
|
|
|
398
449
|
const result = Json.stringifySelected(data, undefined);
|
|
399
450
|
|
|
400
451
|
expect(Result.isOk(result)).toBe(true);
|
|
452
|
+
|
|
401
453
|
if (Result.isOk(result)) {
|
|
454
|
+
assert(isString(result.value));
|
|
402
455
|
const parsed: unknown = JSON.parse(result.value);
|
|
403
|
-
|
|
456
|
+
|
|
457
|
+
assert.deepStrictEqual(parsed, { a: 1, b: 2 });
|
|
404
458
|
}
|
|
405
459
|
});
|
|
406
460
|
|
|
@@ -413,8 +467,9 @@ describe('stringifySelected', () => {
|
|
|
413
467
|
|
|
414
468
|
// Note: JSON.stringify may handle circular references differently depending on the replacer
|
|
415
469
|
expect(Result.isOk(result) || Result.isErr(result)).toBe(true);
|
|
470
|
+
|
|
416
471
|
if (Result.isErr(result)) {
|
|
417
|
-
|
|
472
|
+
expectTypeOf(result.value).toBeString();
|
|
418
473
|
}
|
|
419
474
|
});
|
|
420
475
|
});
|
|
@@ -431,6 +486,7 @@ describe('stringifySortedKey', () => {
|
|
|
431
486
|
const result = Json.stringifySortedKey(unsortedObj);
|
|
432
487
|
|
|
433
488
|
expect(Result.isOk(result)).toBe(true);
|
|
489
|
+
|
|
434
490
|
if (Result.isOk(result)) {
|
|
435
491
|
expect(result.value).toBe(
|
|
436
492
|
'{"aardvark":"animal","apple":"fruit","banana":"fruit","zebra":"animal"}',
|
|
@@ -458,19 +514,24 @@ describe('stringifySortedKey', () => {
|
|
|
458
514
|
const result = Json.stringifySortedKey(nestedObj);
|
|
459
515
|
|
|
460
516
|
expect(Result.isOk(result)).toBe(true);
|
|
517
|
+
|
|
461
518
|
if (Result.isOk(result)) {
|
|
519
|
+
assert(isString(result.value));
|
|
462
520
|
const parsed: unknown = JSON.parse(result.value);
|
|
463
521
|
if (isRecord(parsed)) {
|
|
464
522
|
const keys = Object.keys(parsed);
|
|
465
|
-
|
|
523
|
+
|
|
524
|
+
assert.deepStrictEqual(keys, ['settings', 'user']); // sorted top-level keys
|
|
466
525
|
|
|
467
526
|
if (hasKey(parsed, 'user') && isRecord(parsed.user)) {
|
|
468
527
|
const userKeys = Object.keys(parsed.user);
|
|
469
|
-
|
|
528
|
+
|
|
529
|
+
assert.deepStrictEqual(userKeys, ['address', 'age', 'name']); // sorted nested keys
|
|
470
530
|
|
|
471
531
|
if (hasKey(parsed.user, 'address') && isRecord(parsed.user.address)) {
|
|
472
532
|
const addressKeys = Object.keys(parsed.user.address);
|
|
473
|
-
|
|
533
|
+
|
|
534
|
+
assert.deepStrictEqual(addressKeys, ['city', 'country', 'zip']); // sorted deeper nested keys
|
|
474
535
|
}
|
|
475
536
|
}
|
|
476
537
|
}
|
|
@@ -493,18 +554,26 @@ describe('stringifySortedKey', () => {
|
|
|
493
554
|
const result = Json.stringifySortedKey(dataWithArrays);
|
|
494
555
|
|
|
495
556
|
expect(Result.isOk(result)).toBe(true);
|
|
557
|
+
|
|
496
558
|
if (Result.isOk(result)) {
|
|
559
|
+
assert(isString(result.value));
|
|
497
560
|
const parsed: unknown = JSON.parse(result.value);
|
|
498
561
|
|
|
499
562
|
if (isRecord(parsed)) {
|
|
500
563
|
// Check top-level keys are sorted
|
|
501
564
|
const topKeys = Object.keys(parsed);
|
|
502
|
-
|
|
565
|
+
|
|
566
|
+
assert.deepStrictEqual(topKeys, ['metadata', 'users']);
|
|
503
567
|
|
|
504
568
|
// Check metadata keys are sorted
|
|
505
569
|
if (hasKey(parsed, 'metadata') && isRecord(parsed.metadata)) {
|
|
506
570
|
const metadataKeys = Object.keys(parsed.metadata);
|
|
507
|
-
|
|
571
|
+
|
|
572
|
+
assert.deepStrictEqual(metadataKeys, [
|
|
573
|
+
'author',
|
|
574
|
+
'created',
|
|
575
|
+
'version',
|
|
576
|
+
]);
|
|
508
577
|
}
|
|
509
578
|
|
|
510
579
|
// Check user object keys are sorted
|
|
@@ -516,7 +585,8 @@ describe('stringifySortedKey', () => {
|
|
|
516
585
|
const firstUser = parsed.users[0];
|
|
517
586
|
if (isRecord(firstUser)) {
|
|
518
587
|
const userKeys = Object.keys(firstUser);
|
|
519
|
-
|
|
588
|
+
|
|
589
|
+
assert.deepStrictEqual(userKeys, ['active', 'id', 'name']);
|
|
520
590
|
}
|
|
521
591
|
}
|
|
522
592
|
}
|
|
@@ -528,6 +598,7 @@ describe('stringifySortedKey', () => {
|
|
|
528
598
|
const result = Json.stringifySortedKey(obj, 2);
|
|
529
599
|
|
|
530
600
|
expect(Result.isOk(result)).toBe(true);
|
|
601
|
+
|
|
531
602
|
if (Result.isOk(result)) {
|
|
532
603
|
expect(result.value).toContain('\n');
|
|
533
604
|
expect(result.value).toContain(' ');
|
|
@@ -566,8 +637,9 @@ describe('stringifySortedKey', () => {
|
|
|
566
637
|
|
|
567
638
|
// This may throw due to circular reference during key extraction
|
|
568
639
|
expect(Result.isErr(result)).toBe(true);
|
|
640
|
+
|
|
569
641
|
if (Result.isErr(result)) {
|
|
570
|
-
|
|
642
|
+
expectTypeOf(result.value).toBeString();
|
|
571
643
|
}
|
|
572
644
|
} catch (error) {
|
|
573
645
|
// Expected if circular reference causes stack overflow
|
|
@@ -579,6 +651,7 @@ describe('stringifySortedKey', () => {
|
|
|
579
651
|
const result = Json.stringifySortedKey({});
|
|
580
652
|
|
|
581
653
|
expect(Result.isOk(result)).toBe(true);
|
|
654
|
+
|
|
582
655
|
if (Result.isOk(result)) {
|
|
583
656
|
expect(result.value).toBe('{}');
|
|
584
657
|
}
|
|
@@ -600,12 +673,15 @@ describe('stringifySortedKey', () => {
|
|
|
600
673
|
const result = Json.stringifySortedKey(deep);
|
|
601
674
|
|
|
602
675
|
expect(Result.isOk(result)).toBe(true);
|
|
676
|
+
|
|
603
677
|
if (Result.isOk(result)) {
|
|
678
|
+
assert(isString(result.value));
|
|
604
679
|
const parsed: unknown = JSON.parse(result.value);
|
|
605
680
|
if (isRecord(parsed) && hasKey(parsed, 'level1')) {
|
|
606
681
|
const level1 = parsed.level1;
|
|
607
682
|
if (isRecord(level1)) {
|
|
608
|
-
|
|
683
|
+
assert.deepStrictEqual(Object.keys(level1), ['a', 'z']);
|
|
684
|
+
|
|
609
685
|
if (
|
|
610
686
|
hasKey(level1, 'a') &&
|
|
611
687
|
isRecord(level1.a) &&
|
|
@@ -613,7 +689,7 @@ describe('stringifySortedKey', () => {
|
|
|
613
689
|
) {
|
|
614
690
|
const nested = level1.a.nested;
|
|
615
691
|
if (isRecord(nested)) {
|
|
616
|
-
|
|
692
|
+
assert.deepStrictEqual(Object.keys(nested), ['x', 'y']);
|
|
617
693
|
}
|
|
618
694
|
}
|
|
619
695
|
}
|
|
@@ -3,8 +3,8 @@ import { range } from '../../iterator/index.mjs';
|
|
|
3
3
|
import { asFiniteNumber, FiniteNumber } from './finite-number.mjs';
|
|
4
4
|
import { asNonZeroFiniteNumber } from './non-zero-finite-number.mjs';
|
|
5
5
|
|
|
6
|
-
describe('FiniteNumber', () => {
|
|
7
|
-
describe(
|
|
6
|
+
describe('FiniteNumber test', () => {
|
|
7
|
+
describe(asFiniteNumber, () => {
|
|
8
8
|
test('accepts valid finite numbers', () => {
|
|
9
9
|
expect(() => asFiniteNumber(0)).not.toThrow();
|
|
10
10
|
expect(() => asFiniteNumber(1)).not.toThrow();
|
|
@@ -119,6 +119,7 @@ describe('FiniteNumber', () => {
|
|
|
119
119
|
|
|
120
120
|
for (const _ of range(10)) {
|
|
121
121
|
const result = FiniteNumber.random(min, max);
|
|
122
|
+
|
|
122
123
|
expect(result).toBeGreaterThanOrEqual(min);
|
|
123
124
|
expect(result).toBeLessThanOrEqual(max);
|
|
124
125
|
expect(FiniteNumber.is(result)).toBe(true);
|
|
@@ -3,8 +3,8 @@ import { range } from '../../iterator/index.mjs';
|
|
|
3
3
|
import { asInt, Int, isInt } from './int.mjs';
|
|
4
4
|
import { asNonZeroInt } from './non-zero-int.mjs';
|
|
5
5
|
|
|
6
|
-
describe('Int', () => {
|
|
7
|
-
describe(
|
|
6
|
+
describe('Int test', () => {
|
|
7
|
+
describe(asInt, () => {
|
|
8
8
|
test('accepts valid integers', () => {
|
|
9
9
|
expect(() => asInt(0)).not.toThrow();
|
|
10
10
|
expect(() => asInt(1)).not.toThrow();
|
|
@@ -42,7 +42,7 @@ describe('Int', () => {
|
|
|
42
42
|
});
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
describe(
|
|
45
|
+
describe(isInt, () => {
|
|
46
46
|
test('correctly identifies integers', () => {
|
|
47
47
|
expect(isInt(0)).toBe(true);
|
|
48
48
|
expect(isInt(1)).toBe(true);
|
|
@@ -123,6 +123,7 @@ describe('Int', () => {
|
|
|
123
123
|
|
|
124
124
|
for (const _ of range(10)) {
|
|
125
125
|
const result = Int.random(min, max);
|
|
126
|
+
|
|
126
127
|
expect(result).toBeGreaterThanOrEqual(min);
|
|
127
128
|
expect(result).toBeLessThanOrEqual(max);
|
|
128
129
|
expect(Int.is(result)).toBe(true);
|