flatpack-json 8.14.4 → 8.15.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.
@@ -27,6 +27,7 @@ export declare class FlatpackStore {
27
27
  private cachedObjects;
28
28
  private cachedSets;
29
29
  private cachedMaps;
30
+ private cachedProxies;
30
31
  /**
31
32
  * Cache of strings that have been deduped and stored in the data array.
32
33
  */
@@ -52,14 +53,19 @@ export declare class FlatpackStore {
52
53
  private stringToRef;
53
54
  private cvtSetToRef;
54
55
  private dedupeSetRefs;
56
+ private proxySetRef;
55
57
  private createUniqueKeys;
56
58
  private cvtMapToRef;
57
59
  private dedupeMapRefs;
60
+ private proxyMapRef;
58
61
  private cvtRegExpToRef;
59
62
  private cvtDateToRef;
63
+ private proxyDateRef;
60
64
  private cvtBigintToRef;
61
65
  private cvtObjToRef;
62
66
  private dedupeObject;
67
+ private proxyObjectRef;
68
+ private proxyObjectWrapperRef;
63
69
  /**
64
70
  *
65
71
  * @param value - The array converted to an ArrayRefElement.
@@ -76,6 +82,7 @@ export declare class FlatpackStore {
76
82
  * @returns the index of the array.
77
83
  */
78
84
  private arrToRef;
85
+ private proxyArrayRef;
79
86
  private valueToRef;
80
87
  /**
81
88
  * Reset things in a way that allows for reuse.
@@ -86,6 +93,7 @@ export declare class FlatpackStore {
86
93
  static parse(content: string): FlatpackStore;
87
94
  stringify(): string;
88
95
  toValue(): Unpacked;
96
+ _toValueProxy(): Unpacked;
89
97
  }
90
98
  export declare function toJSON<V extends Serializable>(json: V, options?: FlatpackOptions): Flatpacked;
91
99
  export declare function stringify(data: Unpacked, pretty?: boolean): string;
package/dist/Flatpack.mjs CHANGED
@@ -1,5 +1,7 @@
1
+ import assert from 'node:assert';
1
2
  import { FlatpackedWrapper } from './flatpackUtil.mjs';
2
- import { ArrayRefElement, BigIntRefElement, DateRefElement, isStringRefElements, MapRefElement, ObjectRefElement, ObjectWrapperRefElement, PrimitiveRefElement, RegExpRefElement, SetRefElement, StringConcatRefElement, StringPrimitiveRefElement, SubStringRefElement, } from './RefElements.mjs';
3
+ import { proxyDate, proxyObject, proxySet } from './proxy.mjs';
4
+ import { ArrayRefElement, BigIntRefElement, DateRefElement, isStringRefElements, MapRefElement, ObjectRefElement, ObjectWrapperRefElement, PrimitiveRefElement, PrimitiveRefElementBase, RegExpRefElement, SetRefElement, StringConcatRefElement, StringPrimitiveRefElement, SubStringRefElement, } from './RefElements.mjs';
3
5
  import { stringifyFlatpacked } from './stringify.mjs';
4
6
  import { Trie } from './Trie.mjs';
5
7
  import { blockSplitRegex, dataHeader } from './types.mjs';
@@ -43,6 +45,7 @@ export class FlatpackStore {
43
45
  cachedObjects = new Map();
44
46
  cachedSets = new Map();
45
47
  cachedMaps = new Map();
48
+ cachedProxies = new WeakMap();
46
49
  /**
47
50
  * Cache of strings that have been deduped and stored in the data array.
48
51
  */
@@ -212,7 +215,7 @@ export class FlatpackStore {
212
215
  dedupeSetRefs(value, element) {
213
216
  if (!this.dedupe)
214
217
  return element;
215
- const values = element.values();
218
+ const values = element.valueRefs();
216
219
  const found = this.cachedSets.get(values);
217
220
  if (!found) {
218
221
  this.cachedSets.set(values, element);
@@ -224,6 +227,9 @@ export class FlatpackStore {
224
227
  this.cache.set(value, found);
225
228
  return found;
226
229
  }
230
+ proxySetRef(ref) {
231
+ return proxySet(new Set(this.#toValue(ref.valueRefs())), () => { });
232
+ }
227
233
  createUniqueKeys(keys) {
228
234
  const cacheValue = false;
229
235
  let k = this.arrToRef(keys, cacheValue);
@@ -255,8 +261,8 @@ export class FlatpackStore {
255
261
  dedupeMapRefs(value, element) {
256
262
  if (!this.dedupe)
257
263
  return element;
258
- const keys = element.keys();
259
- const values = element.values();
264
+ const keys = element.keyRefs();
265
+ const values = element.valueRefs();
260
266
  let found = this.cachedMaps.get(keys);
261
267
  if (!found) {
262
268
  found = new Map();
@@ -275,6 +281,9 @@ export class FlatpackStore {
275
281
  found.set(values, element);
276
282
  return element;
277
283
  }
284
+ proxyMapRef(_ref) {
285
+ return new Map();
286
+ }
278
287
  cvtRegExpToRef(value) {
279
288
  const found = this.cache.get(value);
280
289
  if (found !== undefined) {
@@ -289,6 +298,9 @@ export class FlatpackStore {
289
298
  }
290
299
  return this.addValueAndElement(value, new DateRefElement(value.getTime()));
291
300
  }
301
+ proxyDateRef(ref) {
302
+ return proxyDate(ref.value, (date) => ref.setTime(date.getTime()));
303
+ }
292
304
  cvtBigintToRef(value) {
293
305
  const found = this.cache.get(value);
294
306
  if (found !== undefined) {
@@ -328,8 +340,8 @@ export class FlatpackStore {
328
340
  dedupeObject(value, element) {
329
341
  if (!this.dedupe)
330
342
  return element;
331
- const keys = element.keys();
332
- const values = element.values();
343
+ const keys = element.keyRefs();
344
+ const values = element.valueRefs();
333
345
  let found = this.cachedObjects.get(keys);
334
346
  if (!found) {
335
347
  found = new Map();
@@ -348,6 +360,16 @@ export class FlatpackStore {
348
360
  found.set(values, element);
349
361
  return element;
350
362
  }
363
+ proxyObjectRef(ref) {
364
+ const keys = this.#toValue(ref.keyRefs());
365
+ const values = this.#toValue(ref.valueRefs());
366
+ const obj = keys && values ? Object.fromEntries(keys.map((key, i) => [key, values[i]])) : {};
367
+ return proxyObject(obj, (_value) => { });
368
+ }
369
+ proxyObjectWrapperRef(ref) {
370
+ const value = Object(this.#toValue(ref.valueRef()));
371
+ return proxyObject(value, (_value) => { });
372
+ }
351
373
  /**
352
374
  *
353
375
  * @param value - The array converted to an ArrayRefElement.
@@ -394,6 +416,10 @@ export class FlatpackStore {
394
416
  element.setValues(value.map((v) => this.valueToRef(v)));
395
417
  return this.dedupeArray(value, element, cacheValue);
396
418
  }
419
+ proxyArrayRef(ref) {
420
+ const arr = ref.valueRefs().map((v) => this.#toValue(v));
421
+ return proxyObject(arr, (_value) => { });
422
+ }
397
423
  valueToRef(value) {
398
424
  if (value === null) {
399
425
  return this.primitiveToRef(value);
@@ -520,6 +546,36 @@ export class FlatpackStore {
520
546
  this.cache.delete(key);
521
547
  }
522
548
  }
549
+ #resolveToValueProxy(ref) {
550
+ if (!ref)
551
+ return undefined;
552
+ if (ref instanceof ArrayRefElement)
553
+ return this.proxyArrayRef(ref);
554
+ if (ref instanceof ObjectRefElement)
555
+ return this.proxyObjectRef(ref);
556
+ if (ref instanceof PrimitiveRefElementBase)
557
+ return ref.value;
558
+ if (isStringRefElements(ref))
559
+ return ref.value;
560
+ if (ref instanceof MapRefElement)
561
+ return this.proxyMapRef(ref);
562
+ if (ref instanceof SetRefElement)
563
+ return this.proxySetRef(ref);
564
+ if (ref instanceof BigIntRefElement)
565
+ return ref.value;
566
+ if (ref instanceof RegExpRefElement)
567
+ return ref.value;
568
+ if (ref instanceof DateRefElement)
569
+ return this.proxyDateRef(ref);
570
+ if (ref instanceof ObjectWrapperRefElement)
571
+ return this.proxyObjectWrapperRef(ref);
572
+ assert(false, 'Unknown ref type');
573
+ }
574
+ #toValue(ref) {
575
+ if (!ref)
576
+ return undefined;
577
+ return getOrResolve(this.cachedProxies, ref, (ref) => this.#resolveToValueProxy(ref));
578
+ }
523
579
  toJSON() {
524
580
  const data = [dataHeader];
525
581
  const idxLookup = this.assignedElements;
@@ -550,6 +606,9 @@ export class FlatpackStore {
550
606
  toValue() {
551
607
  return fromJSON(this.toJSON());
552
608
  }
609
+ _toValueProxy() {
610
+ return this.#toValue(this.root);
611
+ }
553
612
  }
554
613
  function isObjectWrapper(value) {
555
614
  return (typeof value === 'object' &&
@@ -572,4 +631,12 @@ export function toJSON(json, options) {
572
631
  export function stringify(data, pretty = true) {
573
632
  return pretty ? stringifyFlatpacked(toJSON(data)) : JSON.stringify(toJSON(data));
574
633
  }
634
+ function getOrResolve(map, key, resolver) {
635
+ let value = map.get(key);
636
+ if (value === undefined && !map.has(key)) {
637
+ value = resolver(key);
638
+ map.set(key, value);
639
+ }
640
+ return value;
641
+ }
575
642
  //# sourceMappingURL=Flatpack.mjs.map
@@ -39,8 +39,8 @@ export declare class StringPrimitiveRefElement extends PrimitiveRefElementBase<s
39
39
  export declare class ObjectRefElement extends BaseRefElement implements RefElement<ObjectElement> {
40
40
  #private;
41
41
  constructor(keys?: ArrayRefElement, values?: ArrayRefElement);
42
- keys(): ArrayRefElement | undefined;
43
- values(): ArrayRefElement | undefined;
42
+ keyRefs(): ArrayRefElement | undefined;
43
+ valueRefs(): ArrayRefElement | undefined;
44
44
  setKeysAndValues(keys: ArrayRefElement | undefined, values: ArrayRefElement): void;
45
45
  toElement(lookup: FnIndexLookup): ObjectElement;
46
46
  clone(): ObjectRefElement;
@@ -51,6 +51,7 @@ export declare class ObjectWrapperRefElement extends BaseRefElement implements R
51
51
  #private;
52
52
  constructor(value?: RefElements);
53
53
  setValue(value: RefElements): void;
54
+ valueRef(): RefElements | undefined;
54
55
  toElement(lookup: FnIndexLookup): ObjectWrapperElement;
55
56
  clone(): ObjectWrapperRefElement;
56
57
  getDependencies(): RefElements[] | undefined;
@@ -63,7 +64,7 @@ export declare class SetRefElement extends BaseRefElement implements RefElement<
63
64
  toElement(lookup: FnIndexLookup): SetElement;
64
65
  clone(): SetRefElement;
65
66
  getDependencies(): RefElements[] | undefined;
66
- values(): ArrayRefElement | undefined;
67
+ valueRefs(): ArrayRefElement | undefined;
67
68
  static fromJSON(elem: SetElement, resolve: (index: number) => RefElements): SetRefElement;
68
69
  }
69
70
  export declare class MapRefElement extends BaseRefElement implements RefElement<MapElement> {
@@ -73,14 +74,15 @@ export declare class MapRefElement extends BaseRefElement implements RefElement<
73
74
  toElement(lookup: FnIndexLookup): MapElement;
74
75
  clone(): MapRefElement;
75
76
  getDependencies(): RefElements[] | undefined;
76
- keys(): ArrayRefElement | undefined;
77
- values(): ArrayRefElement | undefined;
77
+ keyRefs(): ArrayRefElement | undefined;
78
+ valueRefs(): ArrayRefElement | undefined;
78
79
  static fromJSON(elem: MapElement, resolve: (index: number) => RefElements): MapRefElement;
79
80
  }
80
81
  export declare class RegExpRefElement extends BaseRefElement implements RefElement<RegExpElement> {
81
82
  #private;
82
83
  constructor(pattern: StringRefElements, flags: StringRefElements);
83
84
  toElement(lookup: FnIndexLookup): RegExpElement;
85
+ get value(): RegExp;
84
86
  clone(): RegExpRefElement;
85
87
  getDependencies(): RefElements[] | undefined;
86
88
  static fromJSON(elem: RegExpElement, resolve: (index: number) => RefElements): RegExpRefElement;
@@ -89,6 +91,8 @@ export declare class DateRefElement extends BaseRefElement implements RefElement
89
91
  #private;
90
92
  constructor(value: number);
91
93
  toElement(): DateElement;
94
+ get value(): Date;
95
+ setTime(time: number): void;
92
96
  clone(): DateRefElement;
93
97
  getDependencies(): undefined;
94
98
  static fromJSON(value: DateElement): DateRefElement;
@@ -96,6 +100,7 @@ export declare class DateRefElement extends BaseRefElement implements RefElement
96
100
  export declare class BigIntRefElement extends BaseRefElement implements RefElement<BigIntElement> {
97
101
  #private;
98
102
  constructor(value: PrimitiveRefElement<number> | StringRefElements);
103
+ get value(): bigint;
99
104
  toElement(lookup: FnIndexLookup): BigIntElement;
100
105
  clone(): BigIntRefElement;
101
106
  getDependencies(): RefElements[] | undefined;
@@ -60,10 +60,10 @@ export class ObjectRefElement extends BaseRefElement {
60
60
  this.#k = keys;
61
61
  this.#v = values;
62
62
  }
63
- keys() {
63
+ keyRefs() {
64
64
  return this.#k;
65
65
  }
66
- values() {
66
+ valueRefs() {
67
67
  return this.#v;
68
68
  }
69
69
  setKeysAndValues(keys, values) {
@@ -101,6 +101,9 @@ export class ObjectWrapperRefElement extends BaseRefElement {
101
101
  setValue(value) {
102
102
  this.#v = value;
103
103
  }
104
+ valueRef() {
105
+ return this.#v;
106
+ }
104
107
  toElement(lookup) {
105
108
  return [ElementType.Object, 0, lookup(this.#v)];
106
109
  }
@@ -134,7 +137,7 @@ export class SetRefElement extends BaseRefElement {
134
137
  getDependencies() {
135
138
  return this.#v ? [this.#v] : undefined;
136
139
  }
137
- values() {
140
+ valueRefs() {
138
141
  return this.#v;
139
142
  }
140
143
  static fromJSON(elem, resolve) {
@@ -165,10 +168,10 @@ export class MapRefElement extends BaseRefElement {
165
168
  getDependencies() {
166
169
  return [this.#k, this.#v].filter((r) => !!r);
167
170
  }
168
- keys() {
171
+ keyRefs() {
169
172
  return this.#k;
170
173
  }
171
- values() {
174
+ valueRefs() {
172
175
  return this.#v;
173
176
  }
174
177
  static fromJSON(elem, resolve) {
@@ -190,6 +193,9 @@ export class RegExpRefElement extends BaseRefElement {
190
193
  toElement(lookup) {
191
194
  return [ElementType.RegExp, lookup(this.#p), lookup(this.#f)];
192
195
  }
196
+ get value() {
197
+ return new RegExp(this.#p.value, this.#f.value);
198
+ }
193
199
  clone() {
194
200
  return new RegExpRefElement(this.#p, this.#f);
195
201
  }
@@ -213,6 +219,12 @@ export class DateRefElement extends BaseRefElement {
213
219
  toElement() {
214
220
  return [ElementType.Date, this.#v];
215
221
  }
222
+ get value() {
223
+ return new Date(this.#v);
224
+ }
225
+ setTime(time) {
226
+ this.#v = time;
227
+ }
216
228
  clone() {
217
229
  return new DateRefElement(this.#v);
218
230
  }
@@ -229,6 +241,9 @@ export class BigIntRefElement extends BaseRefElement {
229
241
  super();
230
242
  this.#v = value;
231
243
  }
244
+ get value() {
245
+ return BigInt(this.#v.value);
246
+ }
232
247
  toElement(lookup) {
233
248
  return [ElementType.BigInt, lookup(this.#v)];
234
249
  }
@@ -0,0 +1,6 @@
1
+ export declare function proxyDate(date: Date, onUpdate?: (date: Date) => void): Date;
2
+ export declare function proxyObject<T extends object>(obj: T, onUpdate?: (obj: T, prop: keyof T, value: T[keyof T]) => void): T;
3
+ export declare function deepEqual(a: any, b: any): boolean;
4
+ export declare function proxyMap<K, V>(values: Iterable<[K, V]>, onUpdate?: (map: Map<K, V>, key: K | undefined, value: V | undefined) => void): Map<K, V>;
5
+ export declare function proxySet<T>(values: Iterable<T>, onUpdate?: (set: Set<T>, value: T | undefined) => void): Set<T>;
6
+ //# sourceMappingURL=proxy.d.mts.map
package/dist/proxy.mjs ADDED
@@ -0,0 +1,180 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ export function proxyDate(date, onUpdate) {
3
+ class PDate extends Date {
4
+ constructor() {
5
+ super();
6
+ super.setTime(date.getTime());
7
+ proxy(this);
8
+ }
9
+ }
10
+ function proxy(obj) {
11
+ const props = Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(obj)));
12
+ for (const prop of props) {
13
+ if (prop.toString() === 'constructor')
14
+ continue;
15
+ if (typeof obj[prop] === 'function') {
16
+ const fn = obj[prop];
17
+ const callback = prop.toString().startsWith('set') ? onUpdate : undefined;
18
+ const fObj = obj;
19
+ fObj[prop] = function (...args) {
20
+ let r = fn.apply(obj, args);
21
+ if (date[prop] !== fn)
22
+ return r;
23
+ r = fn.apply(date, args);
24
+ callback?.(date);
25
+ return r;
26
+ };
27
+ }
28
+ }
29
+ return obj;
30
+ }
31
+ return new PDate();
32
+ }
33
+ const debug = false;
34
+ const log = debug ? console.log : () => { };
35
+ export function proxyObject(obj, onUpdate) {
36
+ const proxy = new Proxy(obj, {
37
+ get(target, prop, _receiver) {
38
+ const value = target[prop];
39
+ // log('get %o', { prop, match: value === obj[prop as keyof T] });
40
+ if (value instanceof Function) {
41
+ return value.bind(target);
42
+ }
43
+ return value;
44
+ },
45
+ ownKeys(target) {
46
+ const result = Reflect.ownKeys(target);
47
+ // log('ownKeys %o', { result, r_orig: Reflect.ownKeys(obj), match: deepEqual(result, Reflect.ownKeys(obj)) });
48
+ return result;
49
+ },
50
+ getOwnPropertyDescriptor(target, prop) {
51
+ const result = Reflect.getOwnPropertyDescriptor(target, prop);
52
+ // log('getOwnPropertyDescriptor %o', {
53
+ // prop,
54
+ // result,
55
+ // r_orig: Object.getOwnPropertyDescriptor(obj, prop),
56
+ // match: deepEqual(result, Object.getOwnPropertyDescriptor(obj, prop)),
57
+ // });
58
+ return result;
59
+ },
60
+ has(target, prop) {
61
+ const result = Reflect.has(target, prop);
62
+ // log('has %o', { prop, result, match: result === prop in obj });
63
+ return result;
64
+ },
65
+ set(target, prop, value) {
66
+ // log('set %o', { prop });
67
+ const r = Reflect.set(target, prop, value);
68
+ onUpdate?.(target, prop, value);
69
+ return r;
70
+ },
71
+ deleteProperty(target, prop) {
72
+ // log('deleteProperty %o', { prop });
73
+ return Reflect.deleteProperty(target, prop);
74
+ },
75
+ defineProperty(target, prop, descriptor) {
76
+ log('defineProperty %o', { prop });
77
+ return Reflect.defineProperty(target, prop, descriptor);
78
+ },
79
+ getPrototypeOf(target) {
80
+ const result = Reflect.getPrototypeOf(target);
81
+ // log('getPrototypeOf %o', {
82
+ // match: result === Object.getPrototypeOf(obj) ? true : Object.getPrototypeOf(obj),
83
+ // });
84
+ return result;
85
+ },
86
+ setPrototypeOf(target, prototype) {
87
+ log('setPrototypeOf');
88
+ return Reflect.setPrototypeOf(target, prototype);
89
+ },
90
+ isExtensible(target) {
91
+ const result = Reflect.isExtensible(target);
92
+ // log('isExtensible %o', { result, match: result === Object.isExtensible(obj) });
93
+ return result;
94
+ },
95
+ preventExtensions(target) {
96
+ log('preventExtensions');
97
+ return Reflect.preventExtensions(target);
98
+ },
99
+ apply(target, thisArg, argArray) {
100
+ log('apply');
101
+ return Reflect.apply(target, thisArg, argArray);
102
+ },
103
+ construct(target, argArray, newTarget) {
104
+ log('construct');
105
+ return Reflect.construct(target, argArray, newTarget);
106
+ },
107
+ });
108
+ return proxy;
109
+ }
110
+ export function deepEqual(a, b) {
111
+ if (a === b)
112
+ return true;
113
+ if (typeof a === 'function' && typeof b === 'function')
114
+ return true;
115
+ if (typeof a !== 'object' || typeof b !== 'object')
116
+ return false;
117
+ for (const key in a) {
118
+ if (!(key in b))
119
+ return false;
120
+ if (!deepEqual(a[key], b[key]))
121
+ return false;
122
+ }
123
+ return true;
124
+ }
125
+ export function proxyMap(values, onUpdate) {
126
+ class PMap extends Map {
127
+ constructor() {
128
+ super();
129
+ // Initialize the map with the values from the original map.
130
+ // This needs to be done instead of `super(fromMap)`, otherwise `this.set` will be called.
131
+ for (const [key, value] of values) {
132
+ super.set(key, value);
133
+ }
134
+ }
135
+ set(key, value) {
136
+ const r = super.set(key, value);
137
+ console.log('set', key, value);
138
+ onUpdate?.(this, key, value);
139
+ return r;
140
+ }
141
+ delete(key) {
142
+ const r = super.delete(key);
143
+ onUpdate?.(this, key, undefined);
144
+ return r;
145
+ }
146
+ clear() {
147
+ super.clear();
148
+ onUpdate?.(this, undefined, undefined);
149
+ }
150
+ }
151
+ return new PMap();
152
+ }
153
+ export function proxySet(values, onUpdate) {
154
+ class PSet extends Set {
155
+ constructor() {
156
+ super();
157
+ // Initialize the set with the values from the original set.
158
+ // This needs to be done instead of `super(fromSet)`, otherwise `this.add` will be called.
159
+ for (const value of values) {
160
+ super.add(value);
161
+ }
162
+ }
163
+ add(value) {
164
+ const r = super.add(value);
165
+ onUpdate?.(this, value);
166
+ return r;
167
+ }
168
+ delete(value) {
169
+ const r = super.delete(value);
170
+ onUpdate?.(this, value);
171
+ return r;
172
+ }
173
+ clear() {
174
+ super.clear();
175
+ onUpdate?.(this, undefined);
176
+ }
177
+ }
178
+ return new PSet();
179
+ }
180
+ //# sourceMappingURL=proxy.mjs.map
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "flatpack-json",
3
3
  "publishConfig": {
4
- "access": "public"
4
+ "access": "public",
5
+ "provenance": true
5
6
  },
6
- "version": "8.14.4",
7
+ "version": "8.15.1",
7
8
  "description": "A library to normalize JSON objects to reduce the size.",
8
9
  "keywords": [
9
10
  "cspell",
@@ -52,8 +53,8 @@
52
53
  "node": ">=18"
53
54
  },
54
55
  "devDependencies": {
55
- "@cspell/filetypes": "8.14.4",
56
+ "@cspell/filetypes": "8.15.1",
56
57
  "diff": "^7.0.0"
57
58
  },
58
- "gitHead": "aeedd49f6ef20799eed04076093291fcacbc4b84"
59
+ "gitHead": "6a99d22627f0e360fcfc5b98afa670464ec763f6"
59
60
  }