@3dsource/utils 1.0.19 → 1.0.20
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/LICENSE +14 -14
- package/README.md +149 -46
- package/fesm2022/3dsource-utils.mjs +69 -32
- package/fesm2022/3dsource-utils.mjs.map +1 -1
- package/index.d.ts +865 -3
- package/package.json +2 -2
- package/lib/color/CMYKtoRGB.d.ts +0 -10
- package/lib/color/HEXtoRGB.d.ts +0 -5
- package/lib/color/HSVtoRGB.d.ts +0 -21
- package/lib/color/RGBtoCMYK.d.ts +0 -20
- package/lib/color/RGBtoHEX.d.ts +0 -1
- package/lib/color/RGBtoHSV.d.ts +0 -19
- package/lib/color/hsv.d.ts +0 -1
- package/lib/color/index.d.ts +0 -16
- package/lib/color/max.d.ts +0 -1
- package/lib/color/min.d.ts +0 -1
- package/lib/color/overlay.d.ts +0 -1
- package/lib/color/rgb.d.ts +0 -8
- package/lib/color/sub.d.ts +0 -1
- package/lib/color/subtract.d.ts +0 -1
- package/lib/color/sum.d.ts +0 -1
- package/lib/color/toRGB.d.ts +0 -8
- package/lib/color/toRGBA.d.ts +0 -1
- package/lib/constants/color-codes.constant.d.ts +0 -9
- package/lib/constants/index.d.ts +0 -1
- package/lib/csv/CSV2Array.d.ts +0 -1
- package/lib/csv/CSV2Records.d.ts +0 -1
- package/lib/csv/ObjectToCSV.d.ts +0 -1
- package/lib/csv/index.d.ts +0 -3
- package/lib/dev/dev3d.d.ts +0 -1
- package/lib/dev/index.d.ts +0 -3
- package/lib/dev/logger.d.ts +0 -11
- package/lib/dev/timeToString.d.ts +0 -5
- package/lib/filenaming/cleanupFileName.d.ts +0 -1
- package/lib/filenaming/index.d.ts +0 -3
- package/lib/filenaming/makePath.d.ts +0 -1
- package/lib/filenaming/normalizePath.d.ts +0 -1
- package/lib/geom/expandOverRectangle.d.ts +0 -2
- package/lib/geom/fitIntoRectangle.d.ts +0 -2
- package/lib/geom/index.d.ts +0 -3
- package/lib/geom/interfaces/area.interface.d.ts +0 -4
- package/lib/geom/interfaces/index.d.ts +0 -4
- package/lib/geom/interfaces/rect.interface.d.ts +0 -4
- package/lib/geom/interfaces/size.interface.d.ts +0 -4
- package/lib/geom/interfaces//321/201oords.interface.d.ts +0 -4
- package/lib/helpers/BatchLoader.d.ts +0 -47
- package/lib/helpers/KeyboardNumericCode.d.ts +0 -103
- package/lib/helpers/debounce.d.ts +0 -1
- package/lib/helpers/generate-uuid.d.ts +0 -1
- package/lib/helpers/index.d.ts +0 -12
- package/lib/helpers/is-desktop.d.ts +0 -1
- package/lib/helpers/media.d.ts +0 -1
- package/lib/helpers/save-to-local-drive.d.ts +0 -1
- package/lib/helpers/serialize.d.ts +0 -1
- package/lib/helpers/short-hash.d.ts +0 -2
- package/lib/helpers/signal.d.ts +0 -23
- package/lib/helpers/sleep.d.ts +0 -1
- package/lib/helpers/trimLastSlashFromUrl.d.ts +0 -1
- package/lib/image/SaveImage.d.ts +0 -18
- package/lib/image/getCanvasCached.d.ts +0 -4
- package/lib/image/getSnapshot.d.ts +0 -2
- package/lib/image/index.d.ts +0 -4
- package/lib/image/loadImage.d.ts +0 -1
- package/lib/interfaces/image-output.d.ts +0 -7
- package/lib/interfaces/index.d.ts +0 -3
- package/lib/interfaces/load-args-tmp.interface.d.ts +0 -4
- package/lib/interfaces/load-args.interface.d.ts +0 -15
- package/lib/math/baseSortedIndex.d.ts +0 -25
- package/lib/math/calculateMedian.d.ts +0 -17
- package/lib/math/circularIndex.d.ts +0 -35
- package/lib/math/clampf.d.ts +0 -8
- package/lib/math/degrees.d.ts +0 -2
- package/lib/math/floatCompare.d.ts +0 -42
- package/lib/math/index.d.ts +0 -8
- package/lib/math/inverseLerp.d.ts +0 -17
- package/lib/math/lerp.d.ts +0 -7
- package/lib/mutex/Mutex.d.ts +0 -43
- package/lib/mutex/Semaphore.d.ts +0 -42
- package/lib/mutex/TaskRunner.d.ts +0 -5
- package/lib/mutex/index.d.ts +0 -3
- package/lib/predicates/index.d.ts +0 -3
- package/lib/predicates/operators.d.ts +0 -32
- package/lib/predicates/textForSearch.d.ts +0 -18
- package/lib/predicates/where.d.ts +0 -46
- package/lib/rxjs/index.d.ts +0 -3
- package/lib/rxjs/leadingTrailingDebounceTime.d.ts +0 -15
- package/lib/rxjs/smoothTransition.d.ts +0 -11
- package/lib/rxjs/tapLog.d.ts +0 -2
- package/lib/strings/index.d.ts +0 -1
- package/lib/strings/pad.d.ts +0 -8
- package/lib/tokens/index.d.ts +0 -3
- package/public-api.d.ts +0 -15
package/LICENSE
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
Copyright (c) 2025 3dsource
|
|
2
|
-
All Rights Reserved.
|
|
3
|
-
|
|
4
|
-
This software and associated documentation files (the “Software”) are proprietary
|
|
5
|
-
and confidential. Unauthorized copying, modification, distribution, or any other
|
|
6
|
-
use of the Software, in whole or in part, without the prior written consent of
|
|
7
|
-
the copyright holder is strictly prohibited.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
10
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
11
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
|
12
|
-
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
13
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
14
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
Copyright (c) 2025 3dsource
|
|
2
|
+
All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
This software and associated documentation files (the “Software”) are proprietary
|
|
5
|
+
and confidential. Unauthorized copying, modification, distribution, or any other
|
|
6
|
+
use of the Software, in whole or in part, without the prior written consent of
|
|
7
|
+
the copyright holder is strictly prohibited.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
10
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
11
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
|
12
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
13
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
14
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,46 +1,149 @@
|
|
|
1
|
-
# @3dsource/utils
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
1
|
+
# @3dsource/utils
|
|
2
|
+
|
|
3
|
+
A comprehensive collection of utility functions and helpers for 3dsource projects. This library provides common
|
|
4
|
+
functionality used across different 3dsource applications and libraries.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
The utils library offers a wide range of utility functions organized by category:
|
|
9
|
+
|
|
10
|
+
- Color manipulation and conversion
|
|
11
|
+
- Mathematical operations for 3D applications
|
|
12
|
+
- Geometry utilities
|
|
13
|
+
- File and image processing
|
|
14
|
+
- String manipulation
|
|
15
|
+
- RxJS operators and utilities
|
|
16
|
+
- Development helpers
|
|
17
|
+
- And more
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
### Prerequisites
|
|
22
|
+
|
|
23
|
+
- Node.js 20+
|
|
24
|
+
- TypeScript 5.8+
|
|
25
|
+
|
|
26
|
+
### Peer Dependencies
|
|
27
|
+
|
|
28
|
+
This library requires the following peer dependencies:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"rxjs": "^7.8.2",
|
|
33
|
+
"ts-md5": "^1.3.1",
|
|
34
|
+
"uuid": "^11.1.0"
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Library Installation
|
|
39
|
+
|
|
40
|
+
```shell
|
|
41
|
+
npm i @3dsource/utils
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
Import the specific utility functions you need:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { hexToRgb } from '@3dsource/utils/color';
|
|
50
|
+
import { clamp } from '@3dsource/utils/math';
|
|
51
|
+
import { generateUUID } from '@3dsource/utils/helpers';
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Available Utilities
|
|
55
|
+
|
|
56
|
+
### Color Utilities
|
|
57
|
+
|
|
58
|
+
The `color` module provides functions for working with colors:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { hexToRgb, rgbToHex, darken, lighten } from '@3dsource/utils/color';
|
|
62
|
+
|
|
63
|
+
// Convert hex color to RGB
|
|
64
|
+
const rgb = hexToRgb('#ff0000'); // { r: 255, g: 0, b: 0 }
|
|
65
|
+
|
|
66
|
+
// Convert RGB to hex
|
|
67
|
+
const hex = rgbToHex(255, 0, 0); // '#ff0000'
|
|
68
|
+
|
|
69
|
+
// Darken a color by 20%
|
|
70
|
+
const darkRed = darken('#ff0000', 0.2);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Math Utilities
|
|
74
|
+
|
|
75
|
+
The `math` module provides mathematical functions:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { clamp, lerp, degToRad } from '@3dsource/utils/math';
|
|
79
|
+
|
|
80
|
+
// Clamp a value between min and max
|
|
81
|
+
const clampedValue = clamp(150, 0, 100); // 100
|
|
82
|
+
|
|
83
|
+
// Linear interpolation
|
|
84
|
+
const interpolated = lerp(0, 100, 0.5); // 50
|
|
85
|
+
|
|
86
|
+
// Convert degrees to radians
|
|
87
|
+
const radians = degToRad(180); // 3.14159...
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Geometry Utilities
|
|
91
|
+
|
|
92
|
+
The `geom` module provides geometry-related functions:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { calculateDistance, isPointInPolygon } from '@3dsource/utils/geom';
|
|
96
|
+
|
|
97
|
+
// Calculate distance between two points
|
|
98
|
+
const distance = calculateDistance({ x: 0, y: 0 }, { x: 3, y: 4 }); // 5
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Complete List of Utility Categories
|
|
102
|
+
|
|
103
|
+
- **[color](src/lib/color)** - Color manipulation and conversion
|
|
104
|
+
- **[constants](src/lib/constants)** - Common constants used across the project
|
|
105
|
+
- **[csv](src/lib/csv)** - CSV parsing and generation
|
|
106
|
+
- **[dev](src/lib/dev)** - Development utilities
|
|
107
|
+
- **[filenaming](src/lib/filenaming)** - File naming utilities
|
|
108
|
+
- **[geom](src/lib/geom)** - Geometry utilities
|
|
109
|
+
- **[helpers](src/lib/helpers)** - General helper functions
|
|
110
|
+
- **[image](src/lib/image)** - Image processing utilities
|
|
111
|
+
- **[interfaces](src/lib/interfaces)** - Common TypeScript interfaces
|
|
112
|
+
- **[math](src/lib/math)** - Mathematical functions
|
|
113
|
+
- **[mutex](src/lib/mutex)** - Mutex implementation for async operations
|
|
114
|
+
- **[predicates](src/lib/predicates)** - Type guards and predicates
|
|
115
|
+
- **[rxjs](src/lib/rxjs)** - RxJS operators and utilities
|
|
116
|
+
- **[strings](src/lib/strings)** - String manipulation functions
|
|
117
|
+
|
|
118
|
+
## Examples
|
|
119
|
+
|
|
120
|
+
### Working with UUIDs
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { generateUUID, isValidUUID } from '@3dsource/utils/helpers';
|
|
124
|
+
|
|
125
|
+
// Generate a new UUID
|
|
126
|
+
const id = generateUUID();
|
|
127
|
+
|
|
128
|
+
// Check if a string is a valid UUID
|
|
129
|
+
const isValid = isValidUUID(id); // true
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Using RxJS Utilities
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { retryWithBackoff } from '@3dsource/utils/rxjs';
|
|
136
|
+
import { of, throwError } from 'rxjs';
|
|
137
|
+
import { mergeMap } from 'rxjs/operators';
|
|
138
|
+
|
|
139
|
+
// Retry an operation with exponential backoff
|
|
140
|
+
function getData() {
|
|
141
|
+
return of(Math.random()).pipe(
|
|
142
|
+
mergeMap((val) => (val < 0.5 ? throwError(() => new Error('Failed')) : of(val))),
|
|
143
|
+
retryWithBackoff({
|
|
144
|
+
initialInterval: 100,
|
|
145
|
+
maxRetries: 3,
|
|
146
|
+
}),
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
@@ -2,8 +2,7 @@ import { Subject, fromEvent, startWith, map as map$1, from, switchMap, finalize,
|
|
|
2
2
|
import { filter, map, distinctUntilChanged, tap } from 'rxjs/operators';
|
|
3
3
|
import { v4 } from 'uuid';
|
|
4
4
|
import { Md5 } from 'ts-md5';
|
|
5
|
-
import { InjectionToken, inject } from '@angular/core';
|
|
6
|
-
import { DOCUMENT } from '@angular/common';
|
|
5
|
+
import { InjectionToken, inject, DOCUMENT } from '@angular/core';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* RGB from each of the CMYK values to determine a return as an any[].
|
|
@@ -633,47 +632,58 @@ function textForSearch(value, caseSensitive = false) {
|
|
|
633
632
|
}
|
|
634
633
|
|
|
635
634
|
/**
|
|
636
|
-
*
|
|
635
|
+
* Builds a predicate that checks whether a record matches **all** provided criteria.
|
|
637
636
|
*
|
|
638
|
-
*
|
|
639
|
-
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
637
|
+
* Behavior:
|
|
638
|
+
* - Only keys with **defined** values in `criteria` are considered; keys with `undefined` are ignored.
|
|
639
|
+
* - Both the criterion value and the corresponding record value are normalized using `textForSearch(value, caseSensitive)`,
|
|
640
|
+
* then compared for **equality** (not substring/contains).
|
|
641
|
+
* - By default (`caseSensitive = false`), comparisons are case-insensitive and tolerant to extra spacing
|
|
642
|
+
* (per `textForSearch`). When `caseSensitive = true`, comparisons preserve original casing.
|
|
643
|
+
* - If **no** criteria have defined values, the resulting predicate always returns **false**.
|
|
643
644
|
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
645
|
+
* @remarks
|
|
646
|
+
* **Nested object stringification (runtime edge case):**
|
|
647
|
+
* Although the TypeScript types constrain comparisons to primitive fields via `ISearchable<T>`,
|
|
648
|
+
* at runtime any non-primitive value that slips through (e.g., due to loose typing) will be coerced to a string
|
|
649
|
+
* before normalization. For example:
|
|
647
650
|
*
|
|
648
|
-
*
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
+
* ```ts
|
|
652
|
+
* // Runtime behavior with nested objects (typing omitted for brevity)
|
|
653
|
+
* const record = { age: 20, test: { hello: 'world' } } as any;
|
|
654
|
+
* // textForSearch(record.test, false) => "[object_object]" (e.g., "[object Object]" normalized)
|
|
655
|
+
* const criteria = { age: 20, test: "[object_object]" } as any;
|
|
656
|
+
* const matches = where<any>(criteria)(record);
|
|
657
|
+
* // matches === true
|
|
658
|
+
* ```
|
|
651
659
|
*
|
|
652
|
-
*
|
|
653
|
-
*
|
|
654
|
-
* If set to false (default), the function will convert the input strings to lowercase for case-insensitive comparisons
|
|
660
|
+
* In other words, `{ hello: 'world' }` is interpreted as the string `"[object_object]"` after normalization,
|
|
661
|
+
* so a criterion with `test: "[object_object]"` will successfully match.
|
|
655
662
|
*
|
|
656
|
-
* @
|
|
657
|
-
*
|
|
663
|
+
* @typeParam T - The object type whose **primitive** fields are comparable via `ISearchable<T>`.
|
|
664
|
+
*
|
|
665
|
+
* @param criteria - A partial set of key–value pairs over `ISearchable<T>` to match against.
|
|
666
|
+
* Only keys with defined values participate in the comparison.
|
|
667
|
+
* @param caseSensitive - Whether comparisons should be case-sensitive. Defaults to `false`.
|
|
668
|
+
*
|
|
669
|
+
* @returns A predicate `(record: ISearchable<T>) => boolean` that is `true` iff the record matches **all** criteria.
|
|
658
670
|
*
|
|
659
671
|
* @example
|
|
660
|
-
*
|
|
661
|
-
* const items = [
|
|
662
|
-
* { name: "Apple",
|
|
672
|
+
* type Item = { name: string; category: string; note?: string };
|
|
673
|
+
* const items: Item[] = [
|
|
674
|
+
* { name: "Apple", category: "Fruit" },
|
|
663
675
|
* { name: "Carrot", category: "Vegetable" },
|
|
664
676
|
* { name: "Banana", category: "Fruit" }
|
|
665
677
|
* ];
|
|
666
678
|
*
|
|
667
|
-
* //
|
|
668
|
-
* const isFruit = where({ category: "fruit" });
|
|
669
|
-
*
|
|
670
|
-
* // Filter the collection with the predicate
|
|
679
|
+
* // Case-insensitive equality match on category ("fruit" matches "Fruit")
|
|
680
|
+
* const isFruit = where<Item>({ category: "fruit" });
|
|
671
681
|
* const fruits = items.filter(isFruit);
|
|
672
|
-
* //
|
|
682
|
+
* // → [{ name: "Apple", category: "Fruit" }, { name: "Banana", category: "Fruit" }]
|
|
673
683
|
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
*
|
|
684
|
+
* // Empty criteria → predicate always false
|
|
685
|
+
* const matchNothing = where<Item>({});
|
|
686
|
+
* items.filter(matchNothing); // → []
|
|
677
687
|
*/
|
|
678
688
|
function where(criteria, caseSensitive = false) {
|
|
679
689
|
const preComputedEntries = Object.entries(criteria)
|
|
@@ -682,11 +692,38 @@ function where(criteria, caseSensitive = false) {
|
|
|
682
692
|
return (record) => {
|
|
683
693
|
return (preComputedEntries.length > 0 &&
|
|
684
694
|
preComputedEntries.every(([key, criterionValue]) => {
|
|
685
|
-
return (textForSearch(record[key] ?? '', caseSensitive) ===
|
|
686
|
-
criterionValue);
|
|
695
|
+
return (textForSearch(record[key] ?? '', caseSensitive) === criterionValue);
|
|
687
696
|
}));
|
|
688
697
|
};
|
|
689
698
|
}
|
|
699
|
+
/**
|
|
700
|
+
* Builds a predicate that is the logical **negation** of `where`.
|
|
701
|
+
*
|
|
702
|
+
* Behavior mirrors `where(criteria, caseSensitive)` but returns `true` when a record **does not**
|
|
703
|
+
* satisfy all criteria. Notable edge cases:
|
|
704
|
+
* - If `criteria` has no defined values (i.e., `where` would always return `false`), this negated predicate
|
|
705
|
+
* will always return **true**.
|
|
706
|
+
* - **Nested object stringification (runtime edge case):** If a nested object is compared against a criterion
|
|
707
|
+
* like `"[object_object]"` (after normalization), the original `where` would return `true`, so `whereNot` will return `false`.
|
|
708
|
+
*
|
|
709
|
+
* @typeParam T - The object type whose **primitive** fields are comparable via `ISearchable<T>`.
|
|
710
|
+
*
|
|
711
|
+
* @param criteria - Same as in `where`.
|
|
712
|
+
* @param caseSensitive - Same as in `where`. Defaults to `false`.
|
|
713
|
+
*
|
|
714
|
+
* @returns A predicate `(record: ISearchable<T>) => boolean` that is `true` iff the record **fails** the `where` check.
|
|
715
|
+
*
|
|
716
|
+
* @example
|
|
717
|
+
* type Item = { name: string; category: string };
|
|
718
|
+
* const items: Item[] = [
|
|
719
|
+
* { name: "Apple", category: "Fruit" },
|
|
720
|
+
* { name: "Carrot", category: "Vegetable" }
|
|
721
|
+
* ];
|
|
722
|
+
*
|
|
723
|
+
* const isNotFruit = whereNot<Item>({ category: "fruit" });
|
|
724
|
+
* items.filter(isNotFruit);
|
|
725
|
+
* // → [{ name: "Carrot", category: "Vegetable" }]
|
|
726
|
+
*/
|
|
690
727
|
function whereNot(criteria, caseSensitive = false) {
|
|
691
728
|
const whereFunc = where(criteria, caseSensitive);
|
|
692
729
|
return (record) => {
|