ts-data-forge 14.11.0 → 14.11.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.
@@ -41,6 +41,15 @@ export declare namespace Json {
41
41
  * );
42
42
  *
43
43
  * assert.isTrue(Result.isOk(withReviver));
44
+ *
45
+ * // With a reviver, the result is whatever the reviver returned, not JSON:
46
+ * // `created` is a `Date` here although it is typed `JsonValue`. Widen it to
47
+ * // `unknown` before narrowing it.
48
+ * const revived: unknown = withReviver.value;
49
+ *
50
+ * assert.isTrue(isRecord(revived));
51
+ *
52
+ * assert.instanceOf(revived['created'], Date);
44
53
  * ```
45
54
  *
46
55
  * @param text - A valid JSON string to parse. Can contain any valid JSON data
@@ -48,10 +57,19 @@ export declare namespace Json {
48
57
  * @param reviver - Optional function that transforms parsed values. Called
49
58
  * for each key-value pair in the JSON. The function receives the key name
50
59
  * and parsed value, and should return the transformed value. For nested
51
- * objects, inner objects are processed before outer objects.
60
+ * objects, inner objects are processed before outer objects, so the
61
+ * `value` an outer object is passed holds what the reviver already
62
+ * returned for its children, which need not be JSON (see `@returns`).
63
+ * Returning
64
+ * `undefined` for a child deletes that property from an object and leaves
65
+ * a hole in an array. The root is passed with the key `''`.
52
66
  * @returns A `Result<JsonValue, string>` containing:
53
67
  *
54
- * - On success: `Result.ok(parsedValue)` where `parsedValue` is the parsed JSON
68
+ * - On success: `Result.ok(parsedValue)` where `parsedValue` is the parsed
69
+ * JSON. With a reviver it is whatever the reviver returned for the root
70
+ * (a `Date`, `undefined`, ...), which is not checked to be JSON although
71
+ * it is typed `JsonValue`; widen it to `unknown` before narrowing it,
72
+ * as the example does.
55
73
  * - On failure: `Result.err(errorMessage)` where `errorMessage` describes the
56
74
  * parsing error
57
75
  */
@@ -1 +1 @@
1
- {"version":3,"file":"json.d.mts","sourceRoot":"","sources":["../../src/json/json.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,kBAAkB,EAClB,aAAa,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAIjD;;;;GAIG;AACH,yBAAiB,IAAI,CAAC;IACpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDG;IACI,MAAM,KAAK,SACV,MAAM,YACF,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,KAAK,OAAO,KAClE,MAAM,CAAC,SAAS,EAAE,MAAM,CAc1B,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgEG;IACI,MAAM,SAAS,UACb,OAAO,aACH,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,UACxD,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KACzC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,MAAM,CAQnC,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgEG;IACI,MAAM,iBAAiB,UACrB,OAAO,2BACW,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,UAC7C,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KACzC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,MAAM,CAUnC,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4EG;IACI,MAAM,kBAAkB,UACtB,aAAa,UACZ,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KACzC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,MAAM,CAoBnC,CAAC;CACH"}
1
+ {"version":3,"file":"json.d.mts","sourceRoot":"","sources":["../../src/json/json.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,kBAAkB,EAClB,aAAa,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAIjD;;;;GAIG;AACH,yBAAiB,IAAI,CAAC;IACpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkEG;IACI,MAAM,KAAK,SACV,MAAM,YACF,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,KAAK,OAAO,KAClE,MAAM,CAAC,SAAS,EAAE,MAAM,CAc1B,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgEG;IACI,MAAM,SAAS,UACb,OAAO,aACH,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,UACxD,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KACzC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,MAAM,CAQnC,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgEG;IACI,MAAM,iBAAiB,UACrB,OAAO,2BACW,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,UAC7C,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KACzC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,MAAM,CAUnC,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4EG;IACI,MAAM,kBAAkB,UACtB,aAAa,UACZ,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KACzC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,MAAM,CAoBnC,CAAC;CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"json.mjs","sourceRoot":"","sources":["../../src/json/json.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"json.mjs","sourceRoot":"","sources":["../../src/json/json.mts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-data-forge",
3
- "version": "14.11.0",
3
+ "version": "14.11.1",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript",
@@ -49,7 +49,7 @@
49
49
  ],
50
50
  "dependencies": {
51
51
  "ts-std-forge": "^0.5.3",
52
- "ts-type-forge": "~9.2.2"
52
+ "ts-type-forge": "~9.2.3"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@emotion/react": "11.14.0",
@@ -59,16 +59,16 @@
59
59
  "@types/react": "19.3.0",
60
60
  "@vitest/browser-playwright": "5.0.5",
61
61
  "eslint": "10.13.0",
62
- "eslint-config-typed": "7.4.0",
63
- "eslint-plugin-ts-fortress": "1.3.13",
64
- "eslint-plugin-ts-type-forge": "0.8.18",
62
+ "eslint-config-typed": "7.6.0",
63
+ "eslint-plugin-ts-fortress": "1.3.15",
64
+ "eslint-plugin-ts-type-forge": "0.8.20",
65
65
  "immer": "11.2.7",
66
66
  "playwright": "1.64.1",
67
67
  "prettier": "3.9.10",
68
68
  "prettier-plugin-organize-imports": "4.3.0",
69
69
  "prettier-plugin-packagejson": "3.0.2",
70
70
  "react": "19.3.1",
71
- "ts-repo-utils": "10.7.2",
71
+ "ts-repo-utils": "10.7.4",
72
72
  "typedoc": "0.28.20",
73
73
  "typedoc-github-theme": "0.4.0",
74
74
  "vite": "8.3.5"
@@ -1107,13 +1107,56 @@ describe('Arr transformations', () => {
1107
1107
 
1108
1108
  const zipped = zip(xs, ys);
1109
1109
 
1110
- expectType<typeof zipped, readonly [readonly [1, number]]>('=');
1110
+ // `ys` may be shorter than `xs`, so the pair is optional.
1111
+ expectType<typeof zipped, readonly [(readonly [1, number])?]>('=');
1111
1112
 
1112
1113
  test('case 3', () => {
1113
1114
  assert.deepStrictEqual(zipped, [[1, 4]]);
1114
1115
  });
1115
1116
  }
1116
1117
 
1118
+ {
1119
+ const xs = [1, 2] as const;
1120
+
1121
+ const ys: readonly number[] = [] as const;
1122
+
1123
+ const zipped = zip(xs, ys);
1124
+
1125
+ expectType<
1126
+ typeof zipped,
1127
+ readonly [(readonly [1, number])?, (readonly [2, number])?]
1128
+ >('=');
1129
+
1130
+ test('a tuple zipped with an empty plain array is empty', () => {
1131
+ assert.deepStrictEqual(zipped, []);
1132
+
1133
+ expectType<(typeof zipped)[0], readonly [1, number] | undefined>('=');
1134
+
1135
+ assert.isUndefined(zipped[0]);
1136
+ });
1137
+ }
1138
+
1139
+ {
1140
+ const xs: readonly number[] = [] as const;
1141
+
1142
+ const ys = [1, 2] as const;
1143
+
1144
+ const zipped = zip(xs, ys);
1145
+
1146
+ expectType<
1147
+ typeof zipped,
1148
+ readonly [(readonly [number, 1])?, (readonly [number, 2])?]
1149
+ >('=');
1150
+
1151
+ test('an empty plain array zipped with a tuple is empty', () => {
1152
+ assert.deepStrictEqual(zipped, []);
1153
+
1154
+ expectType<(typeof zipped)[0], readonly [number, 1] | undefined>('=');
1155
+
1156
+ assert.isUndefined(zipped[0]);
1157
+ });
1158
+ }
1159
+
1117
1160
  // testArrayEquality({
1118
1161
  // testName: 'zip',
1119
1162
  // target: zip([0, 1, 2, 3, 4], [5, 6, 7, 8, 9]),
package/src/json/json.mts CHANGED
@@ -48,6 +48,15 @@ export namespace Json {
48
48
  * );
49
49
  *
50
50
  * assert.isTrue(Result.isOk(withReviver));
51
+ *
52
+ * // With a reviver, the result is whatever the reviver returned, not JSON:
53
+ * // `created` is a `Date` here although it is typed `JsonValue`. Widen it to
54
+ * // `unknown` before narrowing it.
55
+ * const revived: unknown = withReviver.value;
56
+ *
57
+ * assert.isTrue(isRecord(revived));
58
+ *
59
+ * assert.instanceOf(revived['created'], Date);
51
60
  * ```
52
61
  *
53
62
  * @param text - A valid JSON string to parse. Can contain any valid JSON data
@@ -55,10 +64,19 @@ export namespace Json {
55
64
  * @param reviver - Optional function that transforms parsed values. Called
56
65
  * for each key-value pair in the JSON. The function receives the key name
57
66
  * and parsed value, and should return the transformed value. For nested
58
- * objects, inner objects are processed before outer objects.
67
+ * objects, inner objects are processed before outer objects, so the
68
+ * `value` an outer object is passed holds what the reviver already
69
+ * returned for its children, which need not be JSON (see `@returns`).
70
+ * Returning
71
+ * `undefined` for a child deletes that property from an object and leaves
72
+ * a hole in an array. The root is passed with the key `''`.
59
73
  * @returns A `Result<JsonValue, string>` containing:
60
74
  *
61
- * - On success: `Result.ok(parsedValue)` where `parsedValue` is the parsed JSON
75
+ * - On success: `Result.ok(parsedValue)` where `parsedValue` is the parsed
76
+ * JSON. With a reviver it is whatever the reviver returned for the root
77
+ * (a `Date`, `undefined`, ...), which is not checked to be JSON although
78
+ * it is typed `JsonValue`; widen it to `unknown` before narrowing it,
79
+ * as the example does.
62
80
  * - On failure: `Result.err(errorMessage)` where `errorMessage` describes the
63
81
  * parsing error
64
82
  */
@@ -180,6 +180,69 @@ describe('parse', () => {
180
180
 
181
181
  expect(result.value.text).toBe('hello');
182
182
  });
183
+
184
+ test('should return what the reviver returns for the root, even if it is not JSON', () => {
185
+ const result = Json.parse('{"a":1}', (key, value) =>
186
+ key === '' ? undefined : value,
187
+ );
188
+
189
+ assert.isTrue(Result.isOk(result));
190
+
191
+ expect(result.value).toBeUndefined();
192
+ });
193
+
194
+ test('should delete an object property and leave an array hole where the reviver returns undefined', () => {
195
+ const result = Json.parse('{"a":1,"b":[1,2,3]}', (key, value) =>
196
+ key === 'a' || key === '1' ? undefined : value,
197
+ );
198
+
199
+ assert.isTrue(Result.isOk(result));
200
+
201
+ const revived: unknown = result.value;
202
+
203
+ assert.isTrue(isRecord(revived));
204
+
205
+ assert.isFalse(hasKey(revived, 'a'));
206
+
207
+ assert.isTrue(hasKey(revived, 'b'));
208
+
209
+ const arr = revived.b;
210
+
211
+ assert.isTrue(Array.isArray(arr));
212
+
213
+ expect(arr).toHaveLength(3);
214
+
215
+ expect(arr[0]).toBe(1);
216
+
217
+ expect(arr[1]).toBeUndefined();
218
+
219
+ expect(arr[2]).toBe(3);
220
+
221
+ // With the same elements, only a hole at index 1 makes these differ.
222
+ expect(arr).not.toStrictEqual([1, undefined, 3]);
223
+ });
224
+
225
+ test('should pass the reviver the children it has already revived', () => {
226
+ const mut_seen: unknown[] = [];
227
+
228
+ const result = Json.parse('{"inner":{"n":1}}', (key, value) => {
229
+ if (key === 'inner') {
230
+ mut_seen.push(structuredClone(value));
231
+
232
+ return 'replaced';
233
+ }
234
+
235
+ if (key === '') {
236
+ mut_seen.push(structuredClone(value));
237
+ }
238
+
239
+ return value;
240
+ });
241
+
242
+ assert.isTrue(Result.isOk(result));
243
+
244
+ assert.deepStrictEqual(mut_seen, [{ n: 1 }, { inner: 'replaced' }]);
245
+ });
183
246
  });
184
247
 
185
248
  describe('stringify', () => {
@@ -1,5 +1,3 @@
1
- // A `Date` is one of the values compared whole, so the cases build some.
2
- /* eslint-disable unicorn/prefer-temporal */
3
1
  import type { DeepReadonly, ReadonlyRecord } from 'ts-type-forge';
4
2
  import { expectType } from '../expect-type.mjs';
5
3
  import { hasKey, isRecord } from '../guard/index.mjs';