@jiovan-labs/ts-multi-map 0.0.0-stage → 2.0.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.
Files changed (38) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +46 -2
  3. package/README.zh-CN.md +47 -0
  4. package/README.zh-TW.md +47 -0
  5. package/dist/cjs/index.d.ts +7 -0
  6. package/dist/cjs/index.js +47 -0
  7. package/dist/cjs/type/declaration.d.ts +10 -0
  8. package/dist/cjs/type/declaration.js +17 -0
  9. package/dist/cjs/util/MultiKeyMap.d.ts +34 -0
  10. package/dist/cjs/util/MultiKeyMap.js +530 -0
  11. package/dist/cjs/util/MultiValueMap.d.ts +35 -0
  12. package/dist/cjs/util/MultiValueMap.js +527 -0
  13. package/dist/cjs/util/RangeMap.d.ts +36 -0
  14. package/dist/cjs/util/RangeMap.js +584 -0
  15. package/dist/cjs/util/ReadonlyMultiKeyMap.d.ts +27 -0
  16. package/dist/cjs/util/ReadonlyMultiKeyMap.js +364 -0
  17. package/dist/cjs/util/ReadonlyMultiValueMap.d.ts +27 -0
  18. package/dist/cjs/util/ReadonlyMultiValueMap.js +365 -0
  19. package/dist/cjs/util/ReadonlyRangeMap.d.ts +27 -0
  20. package/dist/cjs/util/ReadonlyRangeMap.js +376 -0
  21. package/dist/esm/index.d.ts +7 -0
  22. package/dist/esm/index.js +7 -0
  23. package/dist/esm/type/declaration.d.ts +10 -0
  24. package/dist/esm/type/declaration.js +1 -0
  25. package/dist/esm/util/MultiKeyMap.d.ts +34 -0
  26. package/dist/esm/util/MultiKeyMap.js +318 -0
  27. package/dist/esm/util/MultiValueMap.d.ts +35 -0
  28. package/dist/esm/util/MultiValueMap.js +328 -0
  29. package/dist/esm/util/RangeMap.d.ts +36 -0
  30. package/dist/esm/util/RangeMap.js +358 -0
  31. package/dist/esm/util/ReadonlyMultiKeyMap.d.ts +27 -0
  32. package/dist/esm/util/ReadonlyMultiKeyMap.js +136 -0
  33. package/dist/esm/util/ReadonlyMultiValueMap.d.ts +27 -0
  34. package/dist/esm/util/ReadonlyMultiValueMap.js +136 -0
  35. package/dist/esm/util/ReadonlyRangeMap.d.ts +27 -0
  36. package/dist/esm/util/ReadonlyRangeMap.js +135 -0
  37. package/dist/umd/ts-multi-map.min.js +1 -0
  38. package/package.json +111 -5
@@ -0,0 +1,527 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/util/MultiValueMap.ts
20
+ var MultiValueMap_exports = {};
21
+ __export(MultiValueMap_exports, {
22
+ MultiValueMap: () => MultiValueMap
23
+ });
24
+ module.exports = __toCommonJS(MultiValueMap_exports);
25
+ var MultiValueMap = class {
26
+ /**
27
+ * Construct a multi value map instance
28
+ *
29
+ * @param entries the map entries that represented as [K, V[]][]
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const map = new MultiValueMap([
34
+ * ['color', ['red', 'green', 'blue']]
35
+ * ]);
36
+ * ```
37
+ */
38
+ constructor(entries) {
39
+ this.map = /* @__PURE__ */ new Map();
40
+ entries == null ? void 0 : entries.forEach((entry) => {
41
+ const [k, vs] = entry;
42
+ this.set(k, vs);
43
+ });
44
+ }
45
+ /**
46
+ * Construct a multi value map instance
47
+ *
48
+ * @param entries the map entries that represented as [K, V[]][]
49
+ *
50
+ * @returns a multi value map instance
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const map = MultiValueMap.of([
55
+ * ['color', ['red', 'green', 'blue']]
56
+ * ]);
57
+ * ```
58
+ */
59
+ static of(entries) {
60
+ return new MultiValueMap(entries);
61
+ }
62
+ /**
63
+ * Returns the values of the given key
64
+ *
65
+ * @param key the key to retrieve
66
+ * @param defaults the default values if not found
67
+ *
68
+ * @returns the values of the given key
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const map = MultiValueMap.of([
73
+ * ['color', ['red', 'green', 'blue']]
74
+ * ]);
75
+ * map.get('color'); // ['red', 'green', 'blue']
76
+ * map.get('foobar', ['foo', 'bar']); // ['foo', 'bar']
77
+ * ```
78
+ */
79
+ get(key, defaults) {
80
+ return this.map.get(key) ?? defaults;
81
+ }
82
+ /**
83
+ * Sets the values of the given key
84
+ *
85
+ * @param key the key to set
86
+ * @param values the values to set
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * map.set('color', ['red', 'green', 'blue']);
91
+ * ```
92
+ */
93
+ set(key, values) {
94
+ this.map.set(key, values);
95
+ }
96
+ /**
97
+ * Push values onto the given key, the values will be appended to the given key
98
+ *
99
+ * @param key the key to operate
100
+ * @param values the values to push
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * map.push('color', ['yellow', 'black']);
105
+ * ```
106
+ */
107
+ push(key, values) {
108
+ const array = this.get(key) || [];
109
+ array.push(...values);
110
+ this.map.set(key, array);
111
+ }
112
+ /**
113
+ * Clears the map
114
+ */
115
+ clear() {
116
+ this.map.clear();
117
+ }
118
+ /**
119
+ * Returns the keys of the map
120
+ *
121
+ * @returns the keys of the map
122
+ */
123
+ keys() {
124
+ return [...this.map.keys()];
125
+ }
126
+ /**
127
+ * Returns the values array of the map
128
+ *
129
+ * @returns the values array of the map
130
+ */
131
+ values() {
132
+ return [...this.map.values()];
133
+ }
134
+ /**
135
+ * Returns the key/values entries of the map
136
+ *
137
+ * @returns the key/values entries of the map
138
+ */
139
+ entries() {
140
+ return [...this.map.entries()];
141
+ }
142
+ /**
143
+ * Deletes the entry with the given key
144
+ *
145
+ * @param key the key to delete
146
+ *
147
+ * @returns whether the entry has been deleted
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * map.deleteByKey('color');
152
+ * ```
153
+ */
154
+ deleteByKey(key) {
155
+ return this.map.delete(key);
156
+ }
157
+ /**
158
+ * Deletes all the entries with any of the given keys
159
+ *
160
+ * @param keys the keys to delete
161
+ *
162
+ * @returns whether any of the entries has been deleted
163
+ *
164
+ * @example
165
+ * ```ts
166
+ * map.deleteByKeys(['color', 'position']);
167
+ * ```
168
+ */
169
+ deleteByKeys(keys) {
170
+ if (!keys.length || this.isEmpty()) {
171
+ return false;
172
+ }
173
+ let result = false;
174
+ for (const key of keys) {
175
+ if (this.deleteByKey(key)) {
176
+ result = true;
177
+ }
178
+ }
179
+ return result;
180
+ }
181
+ /**
182
+ * Deletes the entry/entries with the given value
183
+ *
184
+ * @param value the value to delete
185
+ *
186
+ * @returns whether the entry/entries has been deleted
187
+ *
188
+ * @example
189
+ * ```ts
190
+ * map.deleteByValue('red');
191
+ * ```
192
+ */
193
+ deleteByValue(value) {
194
+ if (this.isEmpty()) {
195
+ return false;
196
+ }
197
+ let result = false;
198
+ for (const [k, vs] of this.entries()) {
199
+ if ((vs == null ? void 0 : vs.includes(value)) && this.map.delete(k)) {
200
+ result = true;
201
+ }
202
+ }
203
+ return result;
204
+ }
205
+ /**
206
+ * Deletes all the entries with any of the given values
207
+ *
208
+ * @param values the values to delete
209
+ *
210
+ * @returns whether any of the entries has been deleted
211
+ *
212
+ * @example
213
+ * ```ts
214
+ * map.deleteByValues(['green', 'blue']);
215
+ * ```
216
+ */
217
+ deleteByValues(values) {
218
+ if (!values.length || this.isEmpty()) {
219
+ return false;
220
+ }
221
+ let result = false;
222
+ for (const value of values) {
223
+ if (this.deleteByValue(value)) {
224
+ result = true;
225
+ }
226
+ }
227
+ return result;
228
+ }
229
+ /**
230
+ * Deletes a value for the given key from the map, keeping other values
231
+ *
232
+ * @param key the key to operate
233
+ * @param value the value to delete
234
+ *
235
+ * @returns whether the value has been removed
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * map.deleteValueOfKey('color', 'blue');
240
+ * ```
241
+ */
242
+ deleteValueOfKey(key, value) {
243
+ let array = this.get(key) || [];
244
+ if (!array.includes(value)) {
245
+ return false;
246
+ }
247
+ array = array.filter((v) => v !== value);
248
+ this.map.set(key, array);
249
+ return true;
250
+ }
251
+ /**
252
+ * Processes each entry in the map
253
+ *
254
+ * @param callback a callback function that processes each entry
255
+ * @param thisArg any instance to retrieve 'this' reference in the callback function
256
+ *
257
+ * @example
258
+ * ```ts
259
+ * map.forEach((values, key) => {
260
+ * console.log(key);
261
+ * });
262
+ */
263
+ forEach(callback, thisArg) {
264
+ this.map.forEach((vs, k) => {
265
+ callback(vs, k);
266
+ }, thisArg);
267
+ }
268
+ /**
269
+ * Processes each entry in the map with index capability
270
+ *
271
+ * @param callback a callback function that processes each entry
272
+ * @param thisArg any instance to retrieve 'this' reference in the callback function
273
+ *
274
+ * @example
275
+ * ```ts
276
+ * map.forEachIndexing((values, key, index) => {
277
+ * console.log(index);
278
+ * });
279
+ */
280
+ forEachIndexing(callback, thisArg) {
281
+ let index = 0;
282
+ this.map.forEach((vs, k) => {
283
+ callback(vs, k, index++);
284
+ }, thisArg);
285
+ }
286
+ /**
287
+ * Processes each entry in the map with breakable capability
288
+ *
289
+ * @param callback a callback function that processes each entry. Returning false indicates to break the map iteration
290
+ * @param thisArg any instance to retrieve 'this' reference in the callback function
291
+ *
292
+ * @example
293
+ * ```ts
294
+ * map.forEachBreakable((values, key) => {
295
+ * return true;
296
+ * });
297
+ */
298
+ forEachBreakable(callback, thisArg) {
299
+ this.map.forEach((vs, k) => {
300
+ if (!callback(vs, k)) {
301
+ return;
302
+ }
303
+ }, thisArg);
304
+ }
305
+ /**
306
+ * Returns whether the map contains the given key
307
+ *
308
+ * @param key the key to check
309
+ *
310
+ * @returns whether the map contains the given key
311
+ *
312
+ * @example
313
+ * ```ts
314
+ * map.hasKey('color');
315
+ */
316
+ hasKey(key) {
317
+ return this.map.has(key);
318
+ }
319
+ /**
320
+ * Returns whether the map contains the given key/value pair
321
+ *
322
+ * @param key the key to check
323
+ * @param value the value to check
324
+ *
325
+ * @returns whether the map contains the given key/value pair
326
+ *
327
+ * @example
328
+ * ```ts
329
+ * const map = MultiValueMap.of([
330
+ * ['color', ['red', 'green', 'blue']]
331
+ * ]);
332
+ * map.hasKeyValue('color', 'red'); // true
333
+ * map.hasKeyValue('color', 'black'); // false
334
+ */
335
+ hasKeyValue(key, value) {
336
+ return this.isNotEmpty() && this.get(key, []).includes(value);
337
+ }
338
+ /**
339
+ * Returns whether the map contains any of the given keys
340
+ *
341
+ * @param keys the keys to check
342
+ *
343
+ * @returns whether the map contains any of the given keys
344
+ *
345
+ * @example
346
+ * ```ts
347
+ * const map = MultiValueMap.of([
348
+ * ['color', ['red', 'green', 'blue']]
349
+ * ]);
350
+ * map.hasAnyKeys(['color', 'position']); // true
351
+ */
352
+ hasAnyKeys(keys) {
353
+ return this.isNotEmpty() && keys.length > 0 && keys.some((item) => this.hasKey(item));
354
+ }
355
+ /**
356
+ * Returns whether the map contains all the given keys
357
+ *
358
+ * @param keys the keys to check
359
+ *
360
+ * @returns whether the map contains all the given keys
361
+ *
362
+ * @example
363
+ * ```ts
364
+ * map.hasAllKeys('color', 'position');
365
+ */
366
+ hasAllKeys(keys) {
367
+ return this.isNotEmpty() && keys.length > 0 && keys.every((item) => this.hasKey(item));
368
+ }
369
+ /**
370
+ * Returns whether any entries of the map that contains the given values
371
+ *
372
+ * @param values the values to check
373
+ * @param exact whether matching entry values exactly
374
+ *
375
+ * @returns whether any entries of the map that contains the given values
376
+ *
377
+ * @example
378
+ * ```ts
379
+ * const map = MultiValueMap.of([
380
+ * ['color', ['red', 'green', 'blue']],
381
+ * ['position', ['top', 'right', 'bottom', 'left']]
382
+ * ]);
383
+ * map.hasValue(['red', 'black'], true); // false
384
+ * map.hasValue(['top', 'right'], true); // false
385
+ * map.hasValue(['top', 'right'], false); // true
386
+ */
387
+ hasValue(values, exact = true) {
388
+ if (!values.length || this.isEmpty()) {
389
+ return false;
390
+ }
391
+ for (const vs of this.map.values()) {
392
+ const result = exact ? values.length === vs.length && values.every((item) => vs.includes(item)) : values.some((item) => vs.includes(item));
393
+ if (result) {
394
+ return true;
395
+ }
396
+ }
397
+ return false;
398
+ }
399
+ /**
400
+ * Returns whether the map contains any of the given values
401
+ *
402
+ * @param values the values to check
403
+ * @param exact whether matching entry values exactly
404
+ *
405
+ * @returns whether the map contains any of the given values
406
+ *
407
+ * @example
408
+ * ```ts
409
+ * const map = MultiValueMap.of([
410
+ * ['color', ['red', 'green', 'blue']],
411
+ * ['position', ['top', 'right', 'bottom', 'left']]
412
+ * ]);
413
+ * map.hasAnyValues([['red', 'black'], ['green', 'blue']]); // false
414
+ * map.hasAnyValues([['top', 'right'], ['top', 'right', 'bottom', 'left']]); // true
415
+ */
416
+ hasAnyValues(values, exact = true) {
417
+ return this.isNotEmpty() && values.length > 0 && values.some((item) => this.hasValue(item, exact));
418
+ }
419
+ /**
420
+ * Returns whether the map contains all the given values
421
+ *
422
+ * @param values the values to check
423
+ * @param exact whether matching entry values exactly
424
+ *
425
+ * @returns whether the map contains all the given values
426
+ *
427
+ * @example
428
+ * ```ts
429
+ * map.hasAllValues(['red', 'green', 'blue'], ['top', 'right', 'bottom', 'left']);
430
+ */
431
+ hasAllValues(values, exact = true) {
432
+ return this.isNotEmpty() && values.length > 0 && values.every((item) => this.hasValue(item, exact));
433
+ }
434
+ /**
435
+ * Returns whether the map is empty
436
+ *
437
+ * @returns whether the map is empty
438
+ */
439
+ isEmpty() {
440
+ return !this.map.size;
441
+ }
442
+ /**
443
+ * Returns whether the map is not empty
444
+ *
445
+ * @returns whether the map is not empty
446
+ */
447
+ isNotEmpty() {
448
+ return this.map.size > 0;
449
+ }
450
+ /**
451
+ * Returns the key with the given values
452
+ *
453
+ * @param values the values to inspect
454
+ * @param defaults the default key if nothing matches the given value
455
+ *
456
+ * @returns the key with the given value
457
+ *
458
+ * @example
459
+ * ```ts
460
+ * map.getKey(['foo', 'bar']);
461
+ * ```
462
+ */
463
+ getKey(values, defaults) {
464
+ if (this.isEmpty()) {
465
+ return defaults;
466
+ }
467
+ for (const [k, vs] of this.entries()) {
468
+ if (values.length === vs.length && values.every((item) => vs.includes(item))) {
469
+ return k;
470
+ }
471
+ }
472
+ return defaults;
473
+ }
474
+ /**
475
+ * Response for returning the list of key/values to iterate
476
+ *
477
+ * @example
478
+ * ```ts
479
+ * for (const [key, values] of map) {
480
+ * console.log(key);
481
+ * }
482
+ * ```
483
+ */
484
+ // @ts-ignore
485
+ [Symbol.iterator]() {
486
+ return this.map[Symbol.iterator]();
487
+ }
488
+ /**
489
+ * Returns the size of map
490
+ *
491
+ * @returns the size of map
492
+ */
493
+ get size() {
494
+ return this.map.size;
495
+ }
496
+ /**
497
+ * Returns the string representation of the map identifier ('MultiValueMap')
498
+ *
499
+ * @returns the string representation of the map identifier
500
+ */
501
+ get [Symbol.toStringTag]() {
502
+ return "MultiValueMap";
503
+ }
504
+ /**
505
+ * Returns the string representation of the map elements
506
+ *
507
+ * @returns the string representation of the map elements
508
+ *
509
+ * @example
510
+ * ```ts
511
+ * const map = MultiValueMap.of([
512
+ * ['color', ['red', 'green', 'blue']],
513
+ * ['position', ['top', 'right', 'bottom', 'left']]
514
+ * ]);
515
+ * console.log(map.toString()); // 'color:[red,green,blue];position:[top,right,bottom,left]'
516
+ */
517
+ toString() {
518
+ return [...this].map((entry) => {
519
+ const [k, vs] = entry.length <= 1 ? [[], entry[0]] : [entry.slice(0, -1), entry[entry.length - 1]];
520
+ return `${k}:[${vs.join()}]`;
521
+ }).join(";");
522
+ }
523
+ };
524
+ // Annotate the CommonJS export names for ESM import in node:
525
+ 0 && (module.exports = {
526
+ MultiValueMap
527
+ });
@@ -0,0 +1,36 @@
1
+ import { type RangeMapKey } from "..";
2
+ export declare class RangeMap<V> implements Omit<Map<RangeMapKey, V>, 'delete' | 'forEach' | 'get' | 'has' | 'set' | 'entries' | 'keys' | 'values' | 'push'> {
3
+ private readonly keyMap;
4
+ private readonly valueMap;
5
+ static of<V>(entries?: [RangeMapKey | [number, number] | [number, number, boolean, boolean], V][], validation?: boolean): RangeMap<V>;
6
+ constructor(entries?: [RangeMapKey | [number, number] | [number, number, boolean, boolean], V][], validation?: boolean);
7
+ get(key: RangeMapKey | [number, number] | [number, number, boolean, boolean], defaults?: V): V | undefined;
8
+ getByDigit(digit: number, defaults?: V): V | undefined;
9
+ set(key: RangeMapKey | [number, number] | [number, number, boolean, boolean], value: V, validation?: boolean): void;
10
+ clear(): void;
11
+ keys(): RangeMapKey[];
12
+ values(): V[];
13
+ entries(): [RangeMapKey, V][];
14
+ deleteByKey(key: RangeMapKey | [number, number] | [number, number, boolean, boolean]): boolean;
15
+ deleteByKeys(keys: Array<RangeMapKey | [number, number] | [number, number, boolean, boolean]>): boolean;
16
+ deleteByValue(value: V): boolean;
17
+ deleteByValues(values: V[]): boolean;
18
+ forEach(callback: (value?: V, key?: RangeMapKey) => void, thisArg?: any): void;
19
+ forEachIndexing(callback: (value?: V, key?: RangeMapKey, index?: number) => void, thisArg?: any): void;
20
+ forEachBreakable(callback: (value?: V, key?: RangeMapKey) => boolean, thisArg?: any): void;
21
+ hasKey(key: RangeMapKey | [number, number] | [number, number, boolean, boolean]): boolean;
22
+ hasKeyValue(key: RangeMapKey | [number, number] | [number, number, boolean, boolean], value: V): boolean;
23
+ hasAnyKeys(keys: Array<RangeMapKey | [number, number] | [number, number, boolean, boolean]>): boolean;
24
+ hasAllKeys(keys: Array<RangeMapKey | [number, number] | [number, number, boolean, boolean]>): boolean;
25
+ hasValue(value: V): boolean;
26
+ hasAnyValues(values: V[]): boolean;
27
+ hasAllValues(values: V[]): boolean;
28
+ isEmpty(): boolean;
29
+ isNotEmpty(): boolean;
30
+ [Symbol.iterator](): IterableIterator<[RangeMapKey, V]>;
31
+ get size(): number;
32
+ get [Symbol.toStringTag](): string;
33
+ toString(): string;
34
+ private toInternalKey;
35
+ private checkRangeConflict;
36
+ }