@ls-stack/utils 3.65.0 → 3.67.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/{arrayUtils.d.cts → arrayUtils.d.mts} +24 -23
- package/dist/arrayUtils.mjs +249 -0
- package/dist/assertions-qMxfVhSu.mjs +207 -0
- package/dist/{assertions.d.ts → assertions.d.mts} +4 -3
- package/dist/assertions.mjs +3 -0
- package/dist/asyncQueue.d.mts +497 -0
- package/dist/asyncQueue.mjs +757 -0
- package/dist/{awaitDebounce.d.cts → awaitDebounce.d.mts} +11 -6
- package/dist/awaitDebounce.mjs +54 -0
- package/dist/{cache.d.ts → cache.d.mts} +76 -68
- package/dist/cache.mjs +355 -0
- package/dist/castValues-DfICShCc.mjs +19 -0
- package/dist/{castValues.d.cts → castValues.d.mts} +3 -2
- package/dist/castValues.mjs +3 -0
- package/dist/{concurrentCalls.d.ts → concurrentCalls.d.mts} +74 -65
- package/dist/concurrentCalls.mjs +295 -0
- package/dist/consoleFmt.d.mts +55 -0
- package/dist/consoleFmt.mjs +63 -0
- package/dist/conversions-DTmwEMIu.mjs +12 -0
- package/dist/conversions.d.mts +4 -0
- package/dist/conversions.mjs +3 -0
- package/dist/createThrottleController.d.mts +18 -0
- package/dist/createThrottleController.mjs +40 -0
- package/dist/debounce.d.mts +47 -0
- package/dist/debounce.mjs +117 -0
- package/dist/dedent.d.mts +74 -0
- package/dist/dedent.mjs +80 -0
- package/dist/deepEqual-C7EZEixx.mjs +78 -0
- package/dist/{deepEqual.d.cts → deepEqual.d.mts} +3 -2
- package/dist/deepEqual.mjs +3 -0
- package/dist/{deepReplaceValues.d.cts → deepReplaceValues.d.mts} +4 -3
- package/dist/deepReplaceValues.mjs +61 -0
- package/dist/diffParser.d.mts +79 -0
- package/dist/diffParser.mjs +424 -0
- package/dist/enhancedMap.d.mts +21 -0
- package/dist/enhancedMap.mjs +69 -0
- package/dist/exhaustiveMatch.d.mts +10 -0
- package/dist/exhaustiveMatch.mjs +48 -0
- package/dist/{filterObjectOrArrayKeys.d.cts → filterObjectOrArrayKeys.d.mts} +15 -8
- package/dist/filterObjectOrArrayKeys.mjs +497 -0
- package/dist/{getAutoIncrementId.d.cts → getAutoIncrementId.d.mts} +9 -5
- package/dist/getAutoIncrementId.mjs +53 -0
- package/dist/{getCompositeKey.d.cts → getCompositeKey.d.mts} +3 -2
- package/dist/getCompositeKey.mjs +50 -0
- package/dist/{getValueStableKey.d.cts → getValueStableKey.d.mts} +5 -3
- package/dist/getValueStableKey.mjs +17 -0
- package/dist/{hash.d.cts → hash.d.mts} +3 -2
- package/dist/hash.mjs +28 -0
- package/dist/interpolate.d.mts +17 -0
- package/dist/interpolate.mjs +28 -0
- package/dist/{iteratorUtils.d.cts → iteratorUtils.d.mts} +5 -4
- package/dist/iteratorUtils.mjs +39 -0
- package/dist/keepPrevIfUnchanged.d.mts +12 -0
- package/dist/keepPrevIfUnchanged.mjs +9 -0
- package/dist/keyedMap.d.mts +76 -0
- package/dist/keyedMap.mjs +139 -0
- package/dist/keyedSet.d.mts +77 -0
- package/dist/keyedSet.mjs +129 -0
- package/dist/{levenshtein.d.cts → levenshtein.d.mts} +3 -2
- package/dist/levenshtein.mjs +121 -0
- package/dist/main.d.mts +4 -0
- package/dist/main.mjs +7 -0
- package/dist/matchPath.d.mts +50 -0
- package/dist/matchPath.mjs +81 -0
- package/dist/mathUtils-BDP1lM_z.mjs +81 -0
- package/dist/{mathUtils.d.cts → mathUtils.d.mts} +3 -2
- package/dist/mathUtils.mjs +3 -0
- package/dist/{mutationUtils.d.cts → mutationUtils.d.mts} +6 -5
- package/dist/mutationUtils.mjs +44 -0
- package/dist/{objUtils.d.ts → objUtils.d.mts} +8 -6
- package/dist/objUtils.mjs +115 -0
- package/dist/parallelAsyncCalls.d.mts +83 -0
- package/dist/parallelAsyncCalls.mjs +121 -0
- package/dist/partialEqual.d.mts +139 -0
- package/dist/partialEqual.mjs +1055 -0
- package/dist/promiseUtils.d.mts +9 -0
- package/dist/promiseUtils.mjs +17 -0
- package/dist/regexUtils.d.mts +18 -0
- package/dist/regexUtils.mjs +34 -0
- package/dist/{retryOnError.d.cts → retryOnError.d.mts} +38 -37
- package/dist/retryOnError.mjs +91 -0
- package/dist/{runShellCmd.d.ts → runShellCmd.d.mts} +24 -15
- package/dist/runShellCmd.mjs +151 -0
- package/dist/{safeJson.d.cts → safeJson.d.mts} +3 -2
- package/dist/safeJson.mjs +30 -0
- package/dist/{saferTyping.d.cts → saferTyping.d.mts} +4 -3
- package/dist/saferTyping.mjs +45 -0
- package/dist/serializeXML.d.mts +23 -0
- package/dist/serializeXML.mjs +74 -0
- package/dist/{shallowEqual.d.cts → shallowEqual.d.mts} +3 -2
- package/dist/shallowEqual.mjs +54 -0
- package/dist/sleep.d.mts +4 -0
- package/dist/sleep.mjs +7 -0
- package/dist/stringUtils-DjhWOiYn.mjs +113 -0
- package/dist/{stringUtils.d.cts → stringUtils.d.mts} +3 -2
- package/dist/stringUtils.mjs +3 -0
- package/dist/{testUtils.d.ts → testUtils.d.mts} +83 -52
- package/dist/testUtils.mjs +310 -0
- package/dist/{throttle.d.ts → throttle.d.mts} +18 -17
- package/dist/throttle.mjs +102 -0
- package/dist/time-sr2lhQRw.mjs +67 -0
- package/dist/{time.d.ts → time.d.mts} +8 -7
- package/dist/time.mjs +3 -0
- package/dist/{timers.d.cts → timers.d.mts} +22 -13
- package/dist/timers.mjs +220 -0
- package/dist/{tsResult.d.cts → tsResult.d.mts} +52 -48
- package/dist/tsResult.mjs +142 -0
- package/dist/typeGuards-B1mzA-Rz.mjs +128 -0
- package/dist/{typeGuards.d.cts → typeGuards.d.mts} +3 -2
- package/dist/typeGuards.mjs +3 -0
- package/dist/{typeUtils.d.ts → typeUtils.d.mts} +13 -34
- package/dist/typeUtils.mjs +1 -0
- package/dist/{typedStrings.d.cts → typedStrings.d.mts} +5 -4
- package/dist/typedStrings.mjs +131 -0
- package/dist/typingFnUtils-Bb8drgKF.mjs +101 -0
- package/dist/{typingFnUtils.d.cts → typingFnUtils.d.mts} +13 -22
- package/dist/typingFnUtils.mjs +3 -0
- package/dist/{typingTestUtils.d.cts → typingTestUtils.d.mts} +11 -15
- package/dist/typingTestUtils.mjs +80 -0
- package/dist/typingUtils.d.mts +20 -0
- package/dist/typingUtils.mjs +1 -0
- package/dist/yamlStringify.d.mts +17 -0
- package/dist/yamlStringify.mjs +189 -0
- package/package.json +65 -242
- package/dist/arrayUtils.cjs +0 -229
- package/dist/arrayUtils.d.ts +0 -171
- package/dist/arrayUtils.js +0 -42
- package/dist/assertions.cjs +0 -107
- package/dist/assertions.d.cts +0 -192
- package/dist/assertions.js +0 -25
- package/dist/asyncQueue.cjs +0 -672
- package/dist/asyncQueue.d.cts +0 -488
- package/dist/asyncQueue.d.ts +0 -488
- package/dist/asyncQueue.js +0 -631
- package/dist/awaitDebounce.cjs +0 -106
- package/dist/awaitDebounce.d.ts +0 -41
- package/dist/awaitDebounce.js +0 -28
- package/dist/cache.cjs +0 -367
- package/dist/cache.d.cts +0 -228
- package/dist/cache.js +0 -19
- package/dist/castValues.cjs +0 -50
- package/dist/castValues.d.ts +0 -4
- package/dist/castValues.js +0 -8
- package/dist/chunk-5DZT3Z5Z.js +0 -8
- package/dist/chunk-6FBIEPWU.js +0 -96
- package/dist/chunk-6FIBVC2P.js +0 -56
- package/dist/chunk-7CQPOM5I.js +0 -100
- package/dist/chunk-B6DNOZCP.js +0 -369
- package/dist/chunk-BM4PYVOX.js +0 -109
- package/dist/chunk-C2SVCIWE.js +0 -57
- package/dist/chunk-CCUPDGSZ.js +0 -132
- package/dist/chunk-DBOWTYR4.js +0 -49
- package/dist/chunk-DFXNVEH6.js +0 -14
- package/dist/chunk-DX2524CZ.js +0 -314
- package/dist/chunk-GMJTLFM6.js +0 -60
- package/dist/chunk-IATIXMCE.js +0 -20
- package/dist/chunk-II4R3VVX.js +0 -25
- package/dist/chunk-JF2MDHOJ.js +0 -40
- package/dist/chunk-JQFUKJU5.js +0 -71
- package/dist/chunk-MI4UE2PQ.js +0 -561
- package/dist/chunk-PUKVXYYL.js +0 -52
- package/dist/chunk-QQS7I7ZL.js +0 -16
- package/dist/chunk-VAAMRG4K.js +0 -20
- package/dist/chunk-WFQJUJTC.js +0 -182
- package/dist/chunk-ZXIKIA5B.js +0 -178
- package/dist/concurrentCalls.cjs +0 -406
- package/dist/concurrentCalls.d.cts +0 -116
- package/dist/concurrentCalls.js +0 -346
- package/dist/consoleFmt.cjs +0 -85
- package/dist/consoleFmt.d.cts +0 -54
- package/dist/consoleFmt.d.ts +0 -54
- package/dist/consoleFmt.js +0 -60
- package/dist/conversions.cjs +0 -44
- package/dist/conversions.d.cts +0 -3
- package/dist/conversions.d.ts +0 -3
- package/dist/conversions.js +0 -6
- package/dist/createThrottleController.cjs +0 -193
- package/dist/createThrottleController.d.cts +0 -13
- package/dist/createThrottleController.d.ts +0 -13
- package/dist/createThrottleController.js +0 -61
- package/dist/debounce.cjs +0 -157
- package/dist/debounce.d.cts +0 -46
- package/dist/debounce.d.ts +0 -46
- package/dist/debounce.js +0 -8
- package/dist/dedent.cjs +0 -104
- package/dist/dedent.d.cts +0 -73
- package/dist/dedent.d.ts +0 -73
- package/dist/dedent.js +0 -79
- package/dist/deepEqual.cjs +0 -96
- package/dist/deepEqual.d.ts +0 -21
- package/dist/deepEqual.js +0 -8
- package/dist/deepReplaceValues.cjs +0 -87
- package/dist/deepReplaceValues.d.ts +0 -27
- package/dist/deepReplaceValues.js +0 -7
- package/dist/enhancedMap.cjs +0 -131
- package/dist/enhancedMap.d.cts +0 -20
- package/dist/enhancedMap.d.ts +0 -20
- package/dist/enhancedMap.js +0 -10
- package/dist/exhaustiveMatch.cjs +0 -66
- package/dist/exhaustiveMatch.d.cts +0 -9
- package/dist/exhaustiveMatch.d.ts +0 -9
- package/dist/exhaustiveMatch.js +0 -40
- package/dist/filterObjectOrArrayKeys.cjs +0 -619
- package/dist/filterObjectOrArrayKeys.d.ts +0 -88
- package/dist/filterObjectOrArrayKeys.js +0 -9
- package/dist/getAutoIncrementId.cjs +0 -44
- package/dist/getAutoIncrementId.d.ts +0 -46
- package/dist/getAutoIncrementId.js +0 -18
- package/dist/getCompositeKey.cjs +0 -86
- package/dist/getCompositeKey.d.ts +0 -11
- package/dist/getCompositeKey.js +0 -8
- package/dist/getValueStableKey.cjs +0 -89
- package/dist/getValueStableKey.d.ts +0 -15
- package/dist/getValueStableKey.js +0 -11
- package/dist/hash.cjs +0 -57
- package/dist/hash.d.ts +0 -7
- package/dist/hash.js +0 -32
- package/dist/interpolate.cjs +0 -88
- package/dist/interpolate.d.cts +0 -11
- package/dist/interpolate.d.ts +0 -11
- package/dist/interpolate.js +0 -46
- package/dist/iteratorUtils.cjs +0 -73
- package/dist/iteratorUtils.d.ts +0 -10
- package/dist/iteratorUtils.js +0 -44
- package/dist/keepPrevIfUnchanged.cjs +0 -102
- package/dist/keepPrevIfUnchanged.d.cts +0 -7
- package/dist/keepPrevIfUnchanged.d.ts +0 -7
- package/dist/keepPrevIfUnchanged.js +0 -7
- package/dist/keyedMap.cjs +0 -224
- package/dist/keyedMap.d.cts +0 -75
- package/dist/keyedMap.d.ts +0 -75
- package/dist/keyedMap.js +0 -145
- package/dist/keyedSet.cjs +0 -205
- package/dist/keyedSet.d.cts +0 -76
- package/dist/keyedSet.d.ts +0 -76
- package/dist/keyedSet.js +0 -126
- package/dist/levenshtein.cjs +0 -180
- package/dist/levenshtein.d.ts +0 -5
- package/dist/levenshtein.js +0 -153
- package/dist/main.cjs +0 -32
- package/dist/main.d.cts +0 -3
- package/dist/main.d.ts +0 -3
- package/dist/main.js +0 -7
- package/dist/matchPath.cjs +0 -155
- package/dist/matchPath.d.cts +0 -53
- package/dist/matchPath.d.ts +0 -53
- package/dist/matchPath.js +0 -108
- package/dist/mathUtils.cjs +0 -81
- package/dist/mathUtils.d.ts +0 -54
- package/dist/mathUtils.js +0 -22
- package/dist/mutationUtils.cjs +0 -153
- package/dist/mutationUtils.d.ts +0 -15
- package/dist/mutationUtils.js +0 -55
- package/dist/objUtils.cjs +0 -242
- package/dist/objUtils.d.cts +0 -28
- package/dist/objUtils.js +0 -38
- package/dist/parallelAsyncCalls.cjs +0 -162
- package/dist/parallelAsyncCalls.d.cts +0 -82
- package/dist/parallelAsyncCalls.d.ts +0 -82
- package/dist/parallelAsyncCalls.js +0 -126
- package/dist/partialEqual.cjs +0 -1196
- package/dist/partialEqual.d.cts +0 -141
- package/dist/partialEqual.d.ts +0 -141
- package/dist/partialEqual.js +0 -1168
- package/dist/promiseUtils.cjs +0 -38
- package/dist/promiseUtils.d.cts +0 -8
- package/dist/promiseUtils.d.ts +0 -8
- package/dist/promiseUtils.js +0 -6
- package/dist/regexUtils.cjs +0 -60
- package/dist/regexUtils.d.cts +0 -17
- package/dist/regexUtils.d.ts +0 -17
- package/dist/regexUtils.js +0 -33
- package/dist/retryOnError.cjs +0 -130
- package/dist/retryOnError.d.ts +0 -83
- package/dist/retryOnError.js +0 -101
- package/dist/runShellCmd.cjs +0 -127
- package/dist/runShellCmd.d.cts +0 -90
- package/dist/runShellCmd.js +0 -98
- package/dist/safeJson.cjs +0 -45
- package/dist/safeJson.d.ts +0 -16
- package/dist/safeJson.js +0 -8
- package/dist/saferTyping.cjs +0 -52
- package/dist/saferTyping.d.ts +0 -47
- package/dist/saferTyping.js +0 -23
- package/dist/serializeXML.cjs +0 -154
- package/dist/serializeXML.d.cts +0 -22
- package/dist/serializeXML.d.ts +0 -22
- package/dist/serializeXML.js +0 -116
- package/dist/shallowEqual.cjs +0 -88
- package/dist/shallowEqual.d.ts +0 -4
- package/dist/shallowEqual.js +0 -63
- package/dist/sleep.cjs +0 -32
- package/dist/sleep.d.cts +0 -3
- package/dist/sleep.d.ts +0 -3
- package/dist/sleep.js +0 -6
- package/dist/stringUtils.cjs +0 -155
- package/dist/stringUtils.d.ts +0 -55
- package/dist/stringUtils.js +0 -50
- package/dist/testUtils.cjs +0 -1490
- package/dist/testUtils.d.cts +0 -133
- package/dist/testUtils.js +0 -359
- package/dist/throttle.cjs +0 -282
- package/dist/throttle.d.cts +0 -98
- package/dist/throttle.js +0 -38
- package/dist/time.cjs +0 -152
- package/dist/time.d.cts +0 -25
- package/dist/time.js +0 -38
- package/dist/timers.cjs +0 -194
- package/dist/timers.d.ts +0 -121
- package/dist/timers.js +0 -156
- package/dist/tsResult.cjs +0 -226
- package/dist/tsResult.d.ts +0 -114
- package/dist/tsResult.js +0 -180
- package/dist/typeGuards.cjs +0 -70
- package/dist/typeGuards.d.ts +0 -111
- package/dist/typeGuards.js +0 -18
- package/dist/typeUtils.cjs +0 -18
- package/dist/typeUtils.d.cts +0 -61
- package/dist/typeUtils.js +0 -0
- package/dist/typedStrings.cjs +0 -90
- package/dist/typedStrings.d.ts +0 -163
- package/dist/typedStrings.js +0 -57
- package/dist/typingFnUtils.cjs +0 -96
- package/dist/typingFnUtils.d.ts +0 -100
- package/dist/typingFnUtils.js +0 -30
- package/dist/typingTestUtils.cjs +0 -52
- package/dist/typingTestUtils.d.ts +0 -79
- package/dist/typingTestUtils.js +0 -27
- package/dist/typingUtils.cjs +0 -18
- package/dist/typingUtils.d.cts +0 -35
- package/dist/typingUtils.d.ts +0 -35
- package/dist/typingUtils.js +0 -0
- package/dist/yamlStringify.cjs +0 -423
- package/dist/yamlStringify.d.cts +0 -10
- package/dist/yamlStringify.d.ts +0 -10
- package/dist/yamlStringify.js +0 -9
package/dist/partialEqual.js
DELETED
|
@@ -1,1168 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
exhaustiveCheck
|
|
3
|
-
} from "./chunk-C2SVCIWE.js";
|
|
4
|
-
import "./chunk-JF2MDHOJ.js";
|
|
5
|
-
|
|
6
|
-
// src/partialEqual.ts
|
|
7
|
-
import { err, ok } from "t-result";
|
|
8
|
-
var has = Object.prototype.hasOwnProperty;
|
|
9
|
-
function createComparison(type) {
|
|
10
|
-
return { "~sc": type };
|
|
11
|
-
}
|
|
12
|
-
var match = {
|
|
13
|
-
noExtraKeys: (partialShape) => createComparison(["withNoExtraKeys", partialShape]),
|
|
14
|
-
deepNoExtraKeys: (partialShape) => createComparison(["withDeepNoExtraKeys", partialShape]),
|
|
15
|
-
noExtraDefinedKeys: (partialShape) => createComparison(["noExtraDefinedKeys", partialShape]),
|
|
16
|
-
deepNoExtraDefinedKeys: (partialShape) => createComparison(["deepNoExtraDefinedKeys", partialShape]),
|
|
17
|
-
hasType: {
|
|
18
|
-
string: createComparison(["hasType", "string"]),
|
|
19
|
-
number: createComparison(["hasType", "number"]),
|
|
20
|
-
boolean: createComparison(["hasType", "boolean"]),
|
|
21
|
-
object: createComparison(["hasType", "object"]),
|
|
22
|
-
array: createComparison(["hasType", "array"]),
|
|
23
|
-
function: createComparison(["hasType", "function"])
|
|
24
|
-
},
|
|
25
|
-
isInstanceOf: (constructor) => createComparison(["isInstanceOf", constructor]),
|
|
26
|
-
str: {
|
|
27
|
-
contains: (substring) => createComparison(["strContains", substring]),
|
|
28
|
-
startsWith: (substring) => createComparison(["strStartsWith", substring]),
|
|
29
|
-
endsWith: (substring) => createComparison(["strEndsWith", substring]),
|
|
30
|
-
matchesRegex: (regex) => createComparison(["strMatchesRegex", regex])
|
|
31
|
-
},
|
|
32
|
-
num: {
|
|
33
|
-
isGreaterThan: (value) => createComparison(["numIsGreaterThan", value]),
|
|
34
|
-
isGreaterThanOrEqual: (value) => createComparison(["numIsGreaterThanOrEqual", value]),
|
|
35
|
-
isLessThan: (value) => createComparison(["numIsLessThan", value]),
|
|
36
|
-
isLessThanOrEqual: (value) => createComparison(["numIsLessThanOrEqual", value]),
|
|
37
|
-
isInRange: (value) => createComparison(["numIsInRange", value])
|
|
38
|
-
},
|
|
39
|
-
array: {
|
|
40
|
-
contains: (elements) => createComparison(["arrayContains", elements]),
|
|
41
|
-
containsInOrder: (elements) => createComparison(["arrayContainsInOrder", elements]),
|
|
42
|
-
startsWith: (elements) => createComparison(["arrayStartsWith", elements]),
|
|
43
|
-
endsWith: (elements) => createComparison(["arrayEndsWith", elements]),
|
|
44
|
-
length: (n) => createComparison(["arrayLength", n]),
|
|
45
|
-
minLength: (n) => createComparison(["arrayMinLength", n]),
|
|
46
|
-
maxLength: (n) => createComparison(["arrayMaxLength", n]),
|
|
47
|
-
includes: (element) => createComparison(["arrayIncludes", element]),
|
|
48
|
-
every: (matcher) => createComparison(["arrayEvery", matcher["~sc"]]),
|
|
49
|
-
some: (matcher) => createComparison(["arraySome", matcher["~sc"]])
|
|
50
|
-
},
|
|
51
|
-
jsonString: {
|
|
52
|
-
hasPartial: (value) => createComparison(["jsonStringHasPartial", value])
|
|
53
|
-
},
|
|
54
|
-
equal: (value) => createComparison(["deepEqual", value]),
|
|
55
|
-
partialEqual: (value) => createComparison(["partialEqual", value]),
|
|
56
|
-
custom: (isEqual) => createComparison(["custom", isEqual]),
|
|
57
|
-
keyNotBePresent: createComparison(["keyNotBePresent", null]),
|
|
58
|
-
any: (...values) => createComparison([
|
|
59
|
-
"any",
|
|
60
|
-
values.map((v) => {
|
|
61
|
-
if (isComparison(v)) return v["~sc"];
|
|
62
|
-
if (typeof v === "object" && v !== null)
|
|
63
|
-
return ["partialEqual", v];
|
|
64
|
-
return ["deepEqual", v];
|
|
65
|
-
})
|
|
66
|
-
]),
|
|
67
|
-
all: (...values) => createComparison([
|
|
68
|
-
"all",
|
|
69
|
-
values.map((v) => {
|
|
70
|
-
if (isComparison(v)) return v["~sc"];
|
|
71
|
-
if (typeof v === "object" && v !== null)
|
|
72
|
-
return ["partialEqual", v];
|
|
73
|
-
return ["deepEqual", v];
|
|
74
|
-
})
|
|
75
|
-
]),
|
|
76
|
-
key: {
|
|
77
|
-
any: "$pqkc:any$",
|
|
78
|
-
anyOther: "$pqkc:anyOther$",
|
|
79
|
-
numeric: "$pqkc:numeric$",
|
|
80
|
-
startingWith: (substring) => `$pqkc:startingWith:${substring}$`,
|
|
81
|
-
endingWith: (substring) => `$pqkc:endingWith:${substring}$`,
|
|
82
|
-
containing: (substring) => `$pqkc:contains:${substring}$`,
|
|
83
|
-
matchingRegex: (regex) => `$pqkc:matchesRegex:${regex}$`
|
|
84
|
-
},
|
|
85
|
-
not: {
|
|
86
|
-
hasType: {
|
|
87
|
-
string: createComparison(["not", ["hasType", "string"]]),
|
|
88
|
-
number: createComparison(["not", ["hasType", "number"]]),
|
|
89
|
-
boolean: createComparison(["not", ["hasType", "boolean"]]),
|
|
90
|
-
object: createComparison(["not", ["hasType", "object"]]),
|
|
91
|
-
array: createComparison(["not", ["hasType", "array"]]),
|
|
92
|
-
function: createComparison(["not", ["hasType", "function"]])
|
|
93
|
-
},
|
|
94
|
-
keyNotBePresent: createComparison(["not", ["keyNotBePresent", null]]),
|
|
95
|
-
isInstanceOf: (constructor) => createComparison(["not", ["isInstanceOf", constructor]]),
|
|
96
|
-
str: {
|
|
97
|
-
contains: (substring) => createComparison(["not", ["strContains", substring]]),
|
|
98
|
-
startsWith: (substring) => createComparison(["not", ["strStartsWith", substring]]),
|
|
99
|
-
endsWith: (substring) => createComparison(["not", ["strEndsWith", substring]]),
|
|
100
|
-
matchesRegex: (regex) => createComparison(["not", ["strMatchesRegex", regex]])
|
|
101
|
-
},
|
|
102
|
-
num: {
|
|
103
|
-
isGreaterThan: (value) => createComparison(["not", ["numIsGreaterThan", value]]),
|
|
104
|
-
isGreaterThanOrEqual: (value) => createComparison(["not", ["numIsGreaterThanOrEqual", value]]),
|
|
105
|
-
isLessThan: (value) => createComparison(["not", ["numIsLessThan", value]]),
|
|
106
|
-
isLessThanOrEqual: (value) => createComparison(["not", ["numIsLessThanOrEqual", value]]),
|
|
107
|
-
isInRange: (value) => createComparison(["not", ["numIsInRange", value]])
|
|
108
|
-
},
|
|
109
|
-
array: {
|
|
110
|
-
contains: (elements) => createComparison(["not", ["arrayContains", elements]]),
|
|
111
|
-
containsInOrder: (elements) => createComparison(["not", ["arrayContainsInOrder", elements]]),
|
|
112
|
-
startsWith: (elements) => createComparison(["not", ["arrayStartsWith", elements]]),
|
|
113
|
-
endsWith: (elements) => createComparison(["not", ["arrayEndsWith", elements]]),
|
|
114
|
-
length: (n) => createComparison(["not", ["arrayLength", n]]),
|
|
115
|
-
minLength: (n) => createComparison(["not", ["arrayMinLength", n]]),
|
|
116
|
-
maxLength: (n) => createComparison(["not", ["arrayMaxLength", n]]),
|
|
117
|
-
includes: (element) => createComparison(["not", ["arrayIncludes", element]]),
|
|
118
|
-
every: (matcher) => createComparison(["not", ["arrayEvery", matcher["~sc"]]]),
|
|
119
|
-
some: (matcher) => createComparison(["not", ["arraySome", matcher["~sc"]]])
|
|
120
|
-
},
|
|
121
|
-
jsonString: {
|
|
122
|
-
hasPartial: (value) => createComparison(["not", ["jsonStringHasPartial", value]])
|
|
123
|
-
},
|
|
124
|
-
equal: (value) => createComparison(["not", ["deepEqual", value]]),
|
|
125
|
-
partialEqual: (value) => createComparison(["not", ["partialEqual", value]]),
|
|
126
|
-
custom: (value) => createComparison(["not", ["custom", value]]),
|
|
127
|
-
any: (...values) => createComparison([
|
|
128
|
-
"not",
|
|
129
|
-
[
|
|
130
|
-
"any",
|
|
131
|
-
values.map((v) => {
|
|
132
|
-
if (isComparison(v)) return v["~sc"];
|
|
133
|
-
if (typeof v === "object" && v !== null)
|
|
134
|
-
return ["partialEqual", v];
|
|
135
|
-
return ["deepEqual", v];
|
|
136
|
-
})
|
|
137
|
-
]
|
|
138
|
-
]),
|
|
139
|
-
all: (...values) => createComparison([
|
|
140
|
-
"not",
|
|
141
|
-
[
|
|
142
|
-
"all",
|
|
143
|
-
values.map((v) => {
|
|
144
|
-
if (isComparison(v)) return v["~sc"];
|
|
145
|
-
if (typeof v === "object" && v !== null)
|
|
146
|
-
return ["partialEqual", v];
|
|
147
|
-
return ["deepEqual", v];
|
|
148
|
-
})
|
|
149
|
-
]
|
|
150
|
-
]),
|
|
151
|
-
noExtraKeys: (partialShape) => createComparison(["not", ["withNoExtraKeys", partialShape]]),
|
|
152
|
-
deepNoExtraKeys: (partialShape) => createComparison(["not", ["withDeepNoExtraKeys", partialShape]]),
|
|
153
|
-
noExtraDefinedKeys: (partialShape) => createComparison(["not", ["noExtraDefinedKeys", partialShape]]),
|
|
154
|
-
deepNoExtraDefinedKeys: (partialShape) => createComparison(["not", ["deepNoExtraDefinedKeys", partialShape]]),
|
|
155
|
-
key: {
|
|
156
|
-
any: "$pqkc-not:any$",
|
|
157
|
-
anyOther: "$pqkc-not:anyOther$",
|
|
158
|
-
numeric: "$pqkc-not:numeric$",
|
|
159
|
-
startingWith: (substring) => `$pqkc-not:startingWith:${substring}$`,
|
|
160
|
-
endingWith: (substring) => `$pqkc-not:endingWith:${substring}$`,
|
|
161
|
-
containing: (substring) => `$pqkc-not:contains:${substring}$`,
|
|
162
|
-
matchingRegex: (regex) => `$pqkc-not:matchesRegex:${regex}$`
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
function isComparison(value) {
|
|
167
|
-
return value && typeof value === "object" && "~sc" in value;
|
|
168
|
-
}
|
|
169
|
-
function isKeyMatcher(key) {
|
|
170
|
-
return typeof key === "string" && (key.startsWith("$pqkc:") || key.startsWith("$pqkc-not:"));
|
|
171
|
-
}
|
|
172
|
-
function parseKeyMatcher(key) {
|
|
173
|
-
if (!isKeyMatcher(key)) return null;
|
|
174
|
-
const negated = key.startsWith("$pqkc-not:");
|
|
175
|
-
const prefix = negated ? "$pqkc-not:" : "$pqkc:";
|
|
176
|
-
const suffix = "$";
|
|
177
|
-
if (!key.endsWith(suffix)) return null;
|
|
178
|
-
const content = key.slice(prefix.length, -suffix.length);
|
|
179
|
-
if (content === "any") {
|
|
180
|
-
return { type: "any", negated };
|
|
181
|
-
}
|
|
182
|
-
if (content === "anyOther") {
|
|
183
|
-
return { type: "anyOther", negated };
|
|
184
|
-
}
|
|
185
|
-
if (content === "numeric") {
|
|
186
|
-
return { type: "numeric", negated };
|
|
187
|
-
}
|
|
188
|
-
if (content.startsWith("startingWith:")) {
|
|
189
|
-
return { type: "startingWith", parameter: content.slice("startingWith:".length), negated };
|
|
190
|
-
}
|
|
191
|
-
if (content.startsWith("endingWith:")) {
|
|
192
|
-
return { type: "endingWith", parameter: content.slice("endingWith:".length), negated };
|
|
193
|
-
}
|
|
194
|
-
if (content.startsWith("contains:")) {
|
|
195
|
-
return { type: "contains", parameter: content.slice("contains:".length), negated };
|
|
196
|
-
}
|
|
197
|
-
if (content.startsWith("matchesRegex:")) {
|
|
198
|
-
const regexStr = content.slice("matchesRegex:".length);
|
|
199
|
-
try {
|
|
200
|
-
if (regexStr.startsWith("/") && regexStr.lastIndexOf("/") > 0) {
|
|
201
|
-
const lastSlashIndex = regexStr.lastIndexOf("/");
|
|
202
|
-
const pattern = regexStr.slice(1, lastSlashIndex);
|
|
203
|
-
const flags = regexStr.slice(lastSlashIndex + 1);
|
|
204
|
-
return { type: "matchesRegex", parameter: new RegExp(pattern, flags), negated };
|
|
205
|
-
} else {
|
|
206
|
-
return { type: "matchesRegex", parameter: new RegExp(regexStr), negated };
|
|
207
|
-
}
|
|
208
|
-
} catch {
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
214
|
-
function keyMatchesPattern(key, matcher) {
|
|
215
|
-
let matches = false;
|
|
216
|
-
switch (matcher.type) {
|
|
217
|
-
case "any":
|
|
218
|
-
matches = true;
|
|
219
|
-
break;
|
|
220
|
-
case "anyOther":
|
|
221
|
-
matches = true;
|
|
222
|
-
break;
|
|
223
|
-
case "numeric":
|
|
224
|
-
matches = /^\d+$/.test(key);
|
|
225
|
-
break;
|
|
226
|
-
case "startingWith":
|
|
227
|
-
matches = key.startsWith(matcher.parameter);
|
|
228
|
-
break;
|
|
229
|
-
case "endingWith":
|
|
230
|
-
matches = key.endsWith(matcher.parameter);
|
|
231
|
-
break;
|
|
232
|
-
case "contains":
|
|
233
|
-
matches = key.includes(matcher.parameter);
|
|
234
|
-
break;
|
|
235
|
-
case "matchesRegex":
|
|
236
|
-
matches = matcher.parameter.test(key);
|
|
237
|
-
break;
|
|
238
|
-
}
|
|
239
|
-
return matcher.negated ? !matches : matches;
|
|
240
|
-
}
|
|
241
|
-
function executeComparison(target, comparison, context) {
|
|
242
|
-
const [type, value] = comparison;
|
|
243
|
-
switch (type) {
|
|
244
|
-
case "strStartsWith":
|
|
245
|
-
if (typeof target !== "string") {
|
|
246
|
-
addError(context, {
|
|
247
|
-
message: `Expected string starting with "${value}"`,
|
|
248
|
-
received: target
|
|
249
|
-
});
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
if (!target.startsWith(value)) {
|
|
253
|
-
addError(context, {
|
|
254
|
-
message: `Expected string starting with "${value}"`,
|
|
255
|
-
received: target
|
|
256
|
-
});
|
|
257
|
-
return false;
|
|
258
|
-
}
|
|
259
|
-
return true;
|
|
260
|
-
case "strEndsWith":
|
|
261
|
-
if (typeof target !== "string") {
|
|
262
|
-
addError(context, {
|
|
263
|
-
message: `Expected string ending with "${value}"`,
|
|
264
|
-
received: target
|
|
265
|
-
});
|
|
266
|
-
return false;
|
|
267
|
-
}
|
|
268
|
-
if (!target.endsWith(value)) {
|
|
269
|
-
addError(context, {
|
|
270
|
-
message: `Expected string ending with "${value}"`,
|
|
271
|
-
received: target
|
|
272
|
-
});
|
|
273
|
-
return false;
|
|
274
|
-
}
|
|
275
|
-
return true;
|
|
276
|
-
case "strContains":
|
|
277
|
-
if (typeof target !== "string") {
|
|
278
|
-
addError(context, {
|
|
279
|
-
message: `Expected string containing "${value}"`,
|
|
280
|
-
received: target
|
|
281
|
-
});
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
284
|
-
if (!target.includes(value)) {
|
|
285
|
-
addError(context, {
|
|
286
|
-
message: `Expected string containing "${value}"`,
|
|
287
|
-
received: target
|
|
288
|
-
});
|
|
289
|
-
return false;
|
|
290
|
-
}
|
|
291
|
-
return true;
|
|
292
|
-
case "strMatchesRegex":
|
|
293
|
-
if (typeof target !== "string") {
|
|
294
|
-
addError(context, {
|
|
295
|
-
message: `Expected string matching regex ${value}`,
|
|
296
|
-
received: target
|
|
297
|
-
});
|
|
298
|
-
return false;
|
|
299
|
-
}
|
|
300
|
-
if (!value.test(target)) {
|
|
301
|
-
addError(context, {
|
|
302
|
-
message: `Expected string matching regex ${value}`,
|
|
303
|
-
received: target
|
|
304
|
-
});
|
|
305
|
-
return false;
|
|
306
|
-
}
|
|
307
|
-
return true;
|
|
308
|
-
case "hasType": {
|
|
309
|
-
let actualType;
|
|
310
|
-
if (value === "array") {
|
|
311
|
-
actualType = Array.isArray(target) ? "array" : typeof target;
|
|
312
|
-
} else if (value === "object") {
|
|
313
|
-
if (target === null || Array.isArray(target)) {
|
|
314
|
-
actualType = "not-object";
|
|
315
|
-
} else {
|
|
316
|
-
actualType = typeof target;
|
|
317
|
-
}
|
|
318
|
-
} else {
|
|
319
|
-
actualType = typeof target;
|
|
320
|
-
}
|
|
321
|
-
if (actualType !== value) {
|
|
322
|
-
addError(context, {
|
|
323
|
-
message: `Expected type ${value}`,
|
|
324
|
-
received: target
|
|
325
|
-
});
|
|
326
|
-
return false;
|
|
327
|
-
}
|
|
328
|
-
return true;
|
|
329
|
-
}
|
|
330
|
-
case "deepEqual":
|
|
331
|
-
if (!deepEqual(target, value)) {
|
|
332
|
-
addError(context, {
|
|
333
|
-
message: "Values are not deeply equal",
|
|
334
|
-
received: target,
|
|
335
|
-
expected: value
|
|
336
|
-
});
|
|
337
|
-
return false;
|
|
338
|
-
}
|
|
339
|
-
return true;
|
|
340
|
-
case "numIsGreaterThan":
|
|
341
|
-
if (typeof target !== "number" || target <= value) {
|
|
342
|
-
addError(context, {
|
|
343
|
-
message: `Expected number greater than ${value}`,
|
|
344
|
-
received: target
|
|
345
|
-
});
|
|
346
|
-
return false;
|
|
347
|
-
}
|
|
348
|
-
return true;
|
|
349
|
-
case "numIsGreaterThanOrEqual":
|
|
350
|
-
if (typeof target !== "number" || target < value) {
|
|
351
|
-
addError(context, {
|
|
352
|
-
message: `Expected number greater than or equal to ${value}`,
|
|
353
|
-
received: target
|
|
354
|
-
});
|
|
355
|
-
return false;
|
|
356
|
-
}
|
|
357
|
-
return true;
|
|
358
|
-
case "numIsLessThan":
|
|
359
|
-
if (typeof target !== "number" || target >= value) {
|
|
360
|
-
addError(context, {
|
|
361
|
-
message: `Expected number less than ${value}`,
|
|
362
|
-
received: target
|
|
363
|
-
});
|
|
364
|
-
return false;
|
|
365
|
-
}
|
|
366
|
-
return true;
|
|
367
|
-
case "numIsLessThanOrEqual":
|
|
368
|
-
if (typeof target !== "number" || target > value) {
|
|
369
|
-
addError(context, {
|
|
370
|
-
message: `Expected number less than or equal to ${value}`,
|
|
371
|
-
received: target
|
|
372
|
-
});
|
|
373
|
-
return false;
|
|
374
|
-
}
|
|
375
|
-
return true;
|
|
376
|
-
case "numIsInRange":
|
|
377
|
-
if (typeof target !== "number" || target < value[0] || target > value[1]) {
|
|
378
|
-
addError(context, {
|
|
379
|
-
message: `Expected number in range [${value[0]}, ${value[1]}]`,
|
|
380
|
-
received: target
|
|
381
|
-
});
|
|
382
|
-
return false;
|
|
383
|
-
}
|
|
384
|
-
return true;
|
|
385
|
-
case "jsonStringHasPartial":
|
|
386
|
-
if (typeof target !== "string") {
|
|
387
|
-
addError(context, {
|
|
388
|
-
message: "Expected JSON string",
|
|
389
|
-
received: target
|
|
390
|
-
});
|
|
391
|
-
return false;
|
|
392
|
-
}
|
|
393
|
-
try {
|
|
394
|
-
const parsed = JSON.parse(target);
|
|
395
|
-
if (!partialEqualInternal(parsed, value, context)) {
|
|
396
|
-
return false;
|
|
397
|
-
}
|
|
398
|
-
} catch {
|
|
399
|
-
addError(context, {
|
|
400
|
-
message: "Expected valid JSON string",
|
|
401
|
-
received: target
|
|
402
|
-
});
|
|
403
|
-
return false;
|
|
404
|
-
}
|
|
405
|
-
return true;
|
|
406
|
-
case "partialEqual":
|
|
407
|
-
return partialEqualInternal(target, value, context);
|
|
408
|
-
case "custom": {
|
|
409
|
-
const result = value(target);
|
|
410
|
-
if (result !== true) {
|
|
411
|
-
addError(context, {
|
|
412
|
-
message: `Custom validation failed ${typeof result === "object" ? `: ${result.error}` : ""}`,
|
|
413
|
-
received: target
|
|
414
|
-
});
|
|
415
|
-
return false;
|
|
416
|
-
}
|
|
417
|
-
return true;
|
|
418
|
-
}
|
|
419
|
-
case "isInstanceOf":
|
|
420
|
-
if (!(target instanceof value)) {
|
|
421
|
-
addError(context, {
|
|
422
|
-
message: `Expected instance of ${value.name}`,
|
|
423
|
-
received: target
|
|
424
|
-
});
|
|
425
|
-
return false;
|
|
426
|
-
}
|
|
427
|
-
return true;
|
|
428
|
-
case "keyNotBePresent":
|
|
429
|
-
addError(context, {
|
|
430
|
-
message: "This property should not be present",
|
|
431
|
-
received: target
|
|
432
|
-
});
|
|
433
|
-
return false;
|
|
434
|
-
case "not": {
|
|
435
|
-
const tempContext = {
|
|
436
|
-
errors: [],
|
|
437
|
-
path: context.path
|
|
438
|
-
};
|
|
439
|
-
const result = executeComparison(target, value, tempContext);
|
|
440
|
-
if (result) {
|
|
441
|
-
addError(context, {
|
|
442
|
-
message: "Expected negated condition to fail",
|
|
443
|
-
received: target,
|
|
444
|
-
expected: { "not match": value }
|
|
445
|
-
});
|
|
446
|
-
return false;
|
|
447
|
-
}
|
|
448
|
-
return true;
|
|
449
|
-
}
|
|
450
|
-
case "any": {
|
|
451
|
-
for (const subComparison of value) {
|
|
452
|
-
const anyTempContext = {
|
|
453
|
-
errors: [],
|
|
454
|
-
path: context.path
|
|
455
|
-
};
|
|
456
|
-
if (executeComparison(target, subComparison, anyTempContext)) {
|
|
457
|
-
return true;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
addError(context, {
|
|
461
|
-
message: "None of the alternative comparisons matched",
|
|
462
|
-
received: target,
|
|
463
|
-
expected: {
|
|
464
|
-
matchAny: value
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
return false;
|
|
468
|
-
}
|
|
469
|
-
case "all": {
|
|
470
|
-
let allMatch = true;
|
|
471
|
-
for (const subComparison of value) {
|
|
472
|
-
if (!executeComparison(target, subComparison, context)) {
|
|
473
|
-
allMatch = false;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
return allMatch;
|
|
477
|
-
}
|
|
478
|
-
case "withNoExtraKeys":
|
|
479
|
-
return checkNoExtraKeys(target, value, context, false);
|
|
480
|
-
case "withDeepNoExtraKeys":
|
|
481
|
-
return checkNoExtraKeys(target, value, context, true);
|
|
482
|
-
case "noExtraDefinedKeys":
|
|
483
|
-
return checkNoExtraDefinedKeys(target, value, context, false);
|
|
484
|
-
case "deepNoExtraDefinedKeys":
|
|
485
|
-
return checkNoExtraDefinedKeys(target, value, context, true);
|
|
486
|
-
case "arrayContains": {
|
|
487
|
-
if (!Array.isArray(target)) {
|
|
488
|
-
addError(context, {
|
|
489
|
-
message: "Expected array",
|
|
490
|
-
received: target
|
|
491
|
-
});
|
|
492
|
-
return false;
|
|
493
|
-
}
|
|
494
|
-
for (const element of value) {
|
|
495
|
-
let found = false;
|
|
496
|
-
for (const targetElement of target) {
|
|
497
|
-
const tempContext = {
|
|
498
|
-
errors: [],
|
|
499
|
-
path: context.path
|
|
500
|
-
};
|
|
501
|
-
if (partialEqualInternal(targetElement, element, tempContext)) {
|
|
502
|
-
found = true;
|
|
503
|
-
break;
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
if (!found) {
|
|
507
|
-
addError(context, {
|
|
508
|
-
message: "Array does not contain expected element",
|
|
509
|
-
received: target,
|
|
510
|
-
expected: element
|
|
511
|
-
});
|
|
512
|
-
return false;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
return true;
|
|
516
|
-
}
|
|
517
|
-
case "arrayContainsInOrder": {
|
|
518
|
-
if (!Array.isArray(target)) {
|
|
519
|
-
addError(context, {
|
|
520
|
-
message: "Expected array",
|
|
521
|
-
received: target
|
|
522
|
-
});
|
|
523
|
-
return false;
|
|
524
|
-
}
|
|
525
|
-
let targetIndex = 0;
|
|
526
|
-
for (const element of value) {
|
|
527
|
-
let found = false;
|
|
528
|
-
for (let i = targetIndex; i < target.length; i++) {
|
|
529
|
-
const tempContext = {
|
|
530
|
-
errors: [],
|
|
531
|
-
path: context.path
|
|
532
|
-
};
|
|
533
|
-
if (partialEqualInternal(target[i], element, tempContext)) {
|
|
534
|
-
targetIndex = i + 1;
|
|
535
|
-
found = true;
|
|
536
|
-
break;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
if (!found) {
|
|
540
|
-
addError(context, {
|
|
541
|
-
message: "Array does not contain expected elements in order",
|
|
542
|
-
received: target,
|
|
543
|
-
expected: value
|
|
544
|
-
});
|
|
545
|
-
return false;
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
return true;
|
|
549
|
-
}
|
|
550
|
-
case "arrayStartsWith": {
|
|
551
|
-
if (!Array.isArray(target)) {
|
|
552
|
-
addError(context, {
|
|
553
|
-
message: "Expected array",
|
|
554
|
-
received: target
|
|
555
|
-
});
|
|
556
|
-
return false;
|
|
557
|
-
}
|
|
558
|
-
if (target.length < value.length) {
|
|
559
|
-
addError(context, {
|
|
560
|
-
message: `Array too short: expected to start with ${value.length} elements, got ${target.length}`,
|
|
561
|
-
received: target,
|
|
562
|
-
expected: value
|
|
563
|
-
});
|
|
564
|
-
return false;
|
|
565
|
-
}
|
|
566
|
-
let allMatch = true;
|
|
567
|
-
for (let i = 0; i < value.length; i++) {
|
|
568
|
-
const oldPath = context.path;
|
|
569
|
-
context.path = [...oldPath, `[${i}]`];
|
|
570
|
-
const result = partialEqualInternal(target[i], value[i], context);
|
|
571
|
-
context.path = oldPath;
|
|
572
|
-
if (!result) allMatch = false;
|
|
573
|
-
}
|
|
574
|
-
return allMatch;
|
|
575
|
-
}
|
|
576
|
-
case "arrayEndsWith": {
|
|
577
|
-
if (!Array.isArray(target)) {
|
|
578
|
-
addError(context, {
|
|
579
|
-
message: "Expected array",
|
|
580
|
-
received: target
|
|
581
|
-
});
|
|
582
|
-
return false;
|
|
583
|
-
}
|
|
584
|
-
if (target.length < value.length) {
|
|
585
|
-
addError(context, {
|
|
586
|
-
message: `Array too short: expected to end with ${value.length} elements, got ${target.length}`,
|
|
587
|
-
received: target,
|
|
588
|
-
expected: value
|
|
589
|
-
});
|
|
590
|
-
return false;
|
|
591
|
-
}
|
|
592
|
-
let allMatch = true;
|
|
593
|
-
const startIndex = target.length - value.length;
|
|
594
|
-
for (let i = 0; i < value.length; i++) {
|
|
595
|
-
const oldPath = context.path;
|
|
596
|
-
context.path = [...oldPath, `[${startIndex + i}]`];
|
|
597
|
-
const result = partialEqualInternal(
|
|
598
|
-
target[startIndex + i],
|
|
599
|
-
value[i],
|
|
600
|
-
context
|
|
601
|
-
);
|
|
602
|
-
context.path = oldPath;
|
|
603
|
-
if (!result) allMatch = false;
|
|
604
|
-
}
|
|
605
|
-
return allMatch;
|
|
606
|
-
}
|
|
607
|
-
case "arrayLength": {
|
|
608
|
-
if (!Array.isArray(target)) {
|
|
609
|
-
addError(context, {
|
|
610
|
-
message: "Expected array",
|
|
611
|
-
received: target
|
|
612
|
-
});
|
|
613
|
-
return false;
|
|
614
|
-
}
|
|
615
|
-
if (target.length !== value) {
|
|
616
|
-
addError(context, {
|
|
617
|
-
message: `Expected array length ${value}, got ${target.length}`,
|
|
618
|
-
received: target
|
|
619
|
-
});
|
|
620
|
-
return false;
|
|
621
|
-
}
|
|
622
|
-
return true;
|
|
623
|
-
}
|
|
624
|
-
case "arrayMinLength": {
|
|
625
|
-
if (!Array.isArray(target)) {
|
|
626
|
-
addError(context, {
|
|
627
|
-
message: "Expected array",
|
|
628
|
-
received: target
|
|
629
|
-
});
|
|
630
|
-
return false;
|
|
631
|
-
}
|
|
632
|
-
if (target.length < value) {
|
|
633
|
-
addError(context, {
|
|
634
|
-
message: `Expected array with at least ${value} elements, got ${target.length}`,
|
|
635
|
-
received: target
|
|
636
|
-
});
|
|
637
|
-
return false;
|
|
638
|
-
}
|
|
639
|
-
return true;
|
|
640
|
-
}
|
|
641
|
-
case "arrayMaxLength": {
|
|
642
|
-
if (!Array.isArray(target)) {
|
|
643
|
-
addError(context, {
|
|
644
|
-
message: "Expected array",
|
|
645
|
-
received: target
|
|
646
|
-
});
|
|
647
|
-
return false;
|
|
648
|
-
}
|
|
649
|
-
if (target.length > value) {
|
|
650
|
-
addError(context, {
|
|
651
|
-
message: `Expected array with at most ${value} elements, got ${target.length}`,
|
|
652
|
-
received: target
|
|
653
|
-
});
|
|
654
|
-
return false;
|
|
655
|
-
}
|
|
656
|
-
return true;
|
|
657
|
-
}
|
|
658
|
-
case "arrayIncludes": {
|
|
659
|
-
if (!Array.isArray(target)) {
|
|
660
|
-
addError(context, {
|
|
661
|
-
message: "Expected array",
|
|
662
|
-
received: target
|
|
663
|
-
});
|
|
664
|
-
return false;
|
|
665
|
-
}
|
|
666
|
-
let found = false;
|
|
667
|
-
for (const targetElement of target) {
|
|
668
|
-
const tempContext = {
|
|
669
|
-
errors: [],
|
|
670
|
-
path: context.path
|
|
671
|
-
};
|
|
672
|
-
if (partialEqualInternal(targetElement, value, tempContext)) {
|
|
673
|
-
found = true;
|
|
674
|
-
break;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
if (!found) {
|
|
678
|
-
addError(context, {
|
|
679
|
-
message: "Array does not include expected element",
|
|
680
|
-
received: target,
|
|
681
|
-
expected: value
|
|
682
|
-
});
|
|
683
|
-
return false;
|
|
684
|
-
}
|
|
685
|
-
return true;
|
|
686
|
-
}
|
|
687
|
-
case "arrayEvery": {
|
|
688
|
-
if (!Array.isArray(target)) {
|
|
689
|
-
addError(context, {
|
|
690
|
-
message: "Expected array",
|
|
691
|
-
received: target
|
|
692
|
-
});
|
|
693
|
-
return false;
|
|
694
|
-
}
|
|
695
|
-
let allMatch = true;
|
|
696
|
-
for (let i = 0; i < target.length; i++) {
|
|
697
|
-
const oldPath = context.path;
|
|
698
|
-
context.path = [...oldPath, `[${i}]`];
|
|
699
|
-
const result = executeComparison(target[i], value, context);
|
|
700
|
-
context.path = oldPath;
|
|
701
|
-
if (!result) allMatch = false;
|
|
702
|
-
}
|
|
703
|
-
return allMatch;
|
|
704
|
-
}
|
|
705
|
-
case "arraySome": {
|
|
706
|
-
if (!Array.isArray(target)) {
|
|
707
|
-
addError(context, {
|
|
708
|
-
message: "Expected array",
|
|
709
|
-
received: target
|
|
710
|
-
});
|
|
711
|
-
return false;
|
|
712
|
-
}
|
|
713
|
-
for (let i = 0; i < target.length; i++) {
|
|
714
|
-
const tempContext = {
|
|
715
|
-
errors: [],
|
|
716
|
-
path: [...context.path, `[${i}]`]
|
|
717
|
-
};
|
|
718
|
-
if (executeComparison(target[i], value, tempContext)) {
|
|
719
|
-
return true;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
addError(context, {
|
|
723
|
-
message: "No array element matches the condition",
|
|
724
|
-
received: target
|
|
725
|
-
});
|
|
726
|
-
return false;
|
|
727
|
-
}
|
|
728
|
-
default:
|
|
729
|
-
throw exhaustiveCheck(type);
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
function formatPath(path) {
|
|
733
|
-
if (path.length === 0) return "";
|
|
734
|
-
let result = path[0] || "";
|
|
735
|
-
for (let i = 1; i < path.length; i++) {
|
|
736
|
-
const segment = path[i];
|
|
737
|
-
if (segment && segment.startsWith("[") && segment.endsWith("]")) {
|
|
738
|
-
result += segment;
|
|
739
|
-
} else if (segment) {
|
|
740
|
-
if (result) {
|
|
741
|
-
result += `.${segment}`;
|
|
742
|
-
} else {
|
|
743
|
-
result += segment;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
return result;
|
|
748
|
-
}
|
|
749
|
-
function addError(context, error) {
|
|
750
|
-
context.errors.push({
|
|
751
|
-
path: formatPath(context.path),
|
|
752
|
-
...error
|
|
753
|
-
});
|
|
754
|
-
}
|
|
755
|
-
function deepEqual(a, b) {
|
|
756
|
-
if (a === b) return true;
|
|
757
|
-
if (Number.isNaN(a) && Number.isNaN(b)) return true;
|
|
758
|
-
if (a === null || b === null) return false;
|
|
759
|
-
if (typeof a !== typeof b) return false;
|
|
760
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
761
|
-
if (a.length !== b.length) return false;
|
|
762
|
-
for (let i = 0; i < a.length; i++) {
|
|
763
|
-
if (!deepEqual(a[i], b[i])) return false;
|
|
764
|
-
}
|
|
765
|
-
return true;
|
|
766
|
-
}
|
|
767
|
-
if (typeof a === "object") {
|
|
768
|
-
const keysA = Object.keys(a);
|
|
769
|
-
const keysB = Object.keys(b);
|
|
770
|
-
if (keysA.length !== keysB.length) return false;
|
|
771
|
-
for (const key of keysA) {
|
|
772
|
-
if (!has.call(b, key) || !deepEqual(a[key], b[key])) return false;
|
|
773
|
-
}
|
|
774
|
-
return true;
|
|
775
|
-
}
|
|
776
|
-
return false;
|
|
777
|
-
}
|
|
778
|
-
function partialEqualInternal(target, sub, context) {
|
|
779
|
-
if (isComparison(sub)) {
|
|
780
|
-
return executeComparison(target, sub["~sc"], context);
|
|
781
|
-
}
|
|
782
|
-
if (isComparison(sub) && sub["~sc"][0] === "keyNotBePresent") {
|
|
783
|
-
addError(context, {
|
|
784
|
-
message: "This property should not be present",
|
|
785
|
-
received: target
|
|
786
|
-
});
|
|
787
|
-
return false;
|
|
788
|
-
}
|
|
789
|
-
if (target === sub) return true;
|
|
790
|
-
if (Number.isNaN(target) && Number.isNaN(sub)) return true;
|
|
791
|
-
if (target === null || sub === null || target === void 0 || sub === void 0) {
|
|
792
|
-
if (target !== sub) {
|
|
793
|
-
addError(context, {
|
|
794
|
-
message: "Value mismatch",
|
|
795
|
-
received: target,
|
|
796
|
-
expected: sub
|
|
797
|
-
});
|
|
798
|
-
return false;
|
|
799
|
-
}
|
|
800
|
-
return true;
|
|
801
|
-
}
|
|
802
|
-
if (target instanceof Date && sub instanceof Date) {
|
|
803
|
-
if (target.getTime() !== sub.getTime()) {
|
|
804
|
-
addError(context, {
|
|
805
|
-
message: "Date mismatch",
|
|
806
|
-
received: target,
|
|
807
|
-
expected: sub
|
|
808
|
-
});
|
|
809
|
-
return false;
|
|
810
|
-
}
|
|
811
|
-
return true;
|
|
812
|
-
}
|
|
813
|
-
if (target instanceof RegExp && sub instanceof RegExp) {
|
|
814
|
-
if (target.source !== sub.source || target.flags !== sub.flags) {
|
|
815
|
-
addError(context, {
|
|
816
|
-
message: "RegExp mismatch",
|
|
817
|
-
received: target,
|
|
818
|
-
expected: sub
|
|
819
|
-
});
|
|
820
|
-
return false;
|
|
821
|
-
}
|
|
822
|
-
return true;
|
|
823
|
-
}
|
|
824
|
-
if (target instanceof Set && sub instanceof Set) {
|
|
825
|
-
if (sub.size > target.size) {
|
|
826
|
-
addError(context, {
|
|
827
|
-
message: "Set too small",
|
|
828
|
-
received: target,
|
|
829
|
-
expected: sub
|
|
830
|
-
});
|
|
831
|
-
return false;
|
|
832
|
-
}
|
|
833
|
-
for (const subValue of sub) {
|
|
834
|
-
let found = false;
|
|
835
|
-
for (const targetValue of target) {
|
|
836
|
-
const tempContext = {
|
|
837
|
-
errors: [],
|
|
838
|
-
path: context.path
|
|
839
|
-
};
|
|
840
|
-
if (partialEqualInternal(targetValue, subValue, tempContext)) {
|
|
841
|
-
found = true;
|
|
842
|
-
break;
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
if (!found) {
|
|
846
|
-
addError(context, {
|
|
847
|
-
message: "Set element not found",
|
|
848
|
-
received: target,
|
|
849
|
-
expected: sub
|
|
850
|
-
});
|
|
851
|
-
return false;
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
return true;
|
|
855
|
-
}
|
|
856
|
-
if (target instanceof Map && sub instanceof Map) {
|
|
857
|
-
if (sub.size > target.size) {
|
|
858
|
-
addError(context, {
|
|
859
|
-
message: "Map has less entries than expected",
|
|
860
|
-
received: `${target.size} entries`,
|
|
861
|
-
expected: `${sub.size} entries`
|
|
862
|
-
});
|
|
863
|
-
return false;
|
|
864
|
-
}
|
|
865
|
-
for (const [subKey, subValue] of sub) {
|
|
866
|
-
let found = false;
|
|
867
|
-
for (const [targetKey, targetValue] of target) {
|
|
868
|
-
const tempContextKey = {
|
|
869
|
-
errors: [],
|
|
870
|
-
path: context.path
|
|
871
|
-
};
|
|
872
|
-
const tempContextValue = {
|
|
873
|
-
errors: [],
|
|
874
|
-
path: context.path
|
|
875
|
-
};
|
|
876
|
-
if (partialEqualInternal(targetKey, subKey, tempContextKey) && partialEqualInternal(targetValue, subValue, tempContextValue)) {
|
|
877
|
-
found = true;
|
|
878
|
-
break;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
if (!found) {
|
|
882
|
-
addError(context, {
|
|
883
|
-
message: "Map entry not found",
|
|
884
|
-
received: target,
|
|
885
|
-
expected: sub
|
|
886
|
-
});
|
|
887
|
-
return false;
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
return true;
|
|
891
|
-
}
|
|
892
|
-
if (typeof target !== typeof sub) {
|
|
893
|
-
addError(context, {
|
|
894
|
-
message: "Value mismatch",
|
|
895
|
-
received: target,
|
|
896
|
-
expected: sub
|
|
897
|
-
});
|
|
898
|
-
return false;
|
|
899
|
-
}
|
|
900
|
-
if (Array.isArray(sub)) {
|
|
901
|
-
if (!Array.isArray(target)) {
|
|
902
|
-
addError(context, {
|
|
903
|
-
message: "Expected array",
|
|
904
|
-
received: target,
|
|
905
|
-
expected: sub
|
|
906
|
-
});
|
|
907
|
-
return false;
|
|
908
|
-
}
|
|
909
|
-
if (target.length < sub.length) {
|
|
910
|
-
addError(context, {
|
|
911
|
-
message: `Array too short: expected at least ${sub.length} elements, got ${target.length}`,
|
|
912
|
-
received: target,
|
|
913
|
-
expected: sub
|
|
914
|
-
});
|
|
915
|
-
return false;
|
|
916
|
-
}
|
|
917
|
-
let allMatch = true;
|
|
918
|
-
for (let i = 0; i < sub.length; i++) {
|
|
919
|
-
const oldPath = context.path;
|
|
920
|
-
context.path = [...oldPath, `[${i}]`];
|
|
921
|
-
const result = partialEqualInternal(target[i], sub[i], context);
|
|
922
|
-
context.path = oldPath;
|
|
923
|
-
if (!result) allMatch = false;
|
|
924
|
-
}
|
|
925
|
-
return allMatch;
|
|
926
|
-
}
|
|
927
|
-
if (typeof sub === "object") {
|
|
928
|
-
if (typeof target !== "object" || Array.isArray(target)) {
|
|
929
|
-
addError(context, {
|
|
930
|
-
message: "Expected object",
|
|
931
|
-
received: target,
|
|
932
|
-
expected: sub
|
|
933
|
-
});
|
|
934
|
-
return false;
|
|
935
|
-
}
|
|
936
|
-
let allMatch = true;
|
|
937
|
-
const regularKeys = [];
|
|
938
|
-
const keyMatchers = [];
|
|
939
|
-
for (const key of Object.keys(sub)) {
|
|
940
|
-
if (isKeyMatcher(key)) {
|
|
941
|
-
const matcher = parseKeyMatcher(key);
|
|
942
|
-
if (matcher) {
|
|
943
|
-
keyMatchers.push({ key, matcher, value: sub[key] });
|
|
944
|
-
}
|
|
945
|
-
} else {
|
|
946
|
-
regularKeys.push(key);
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
const explicitlySpecifiedKeys = /* @__PURE__ */ new Set();
|
|
950
|
-
for (const key of regularKeys) {
|
|
951
|
-
explicitlySpecifiedKeys.add(key);
|
|
952
|
-
if (isComparison(sub[key]) && sub[key]["~sc"][0] === "keyNotBePresent") {
|
|
953
|
-
if (has.call(target, key)) {
|
|
954
|
-
const oldPath2 = context.path;
|
|
955
|
-
context.path = [...oldPath2, key];
|
|
956
|
-
addError(context, {
|
|
957
|
-
message: "Key should not be present",
|
|
958
|
-
received: target[key]
|
|
959
|
-
});
|
|
960
|
-
context.path = oldPath2;
|
|
961
|
-
allMatch = false;
|
|
962
|
-
}
|
|
963
|
-
continue;
|
|
964
|
-
}
|
|
965
|
-
if (!has.call(target, key)) {
|
|
966
|
-
if (isComparison(sub[key])) {
|
|
967
|
-
const comparison = sub[key]["~sc"];
|
|
968
|
-
if (comparison[0] === "any") {
|
|
969
|
-
const anyComparisons = comparison[1];
|
|
970
|
-
const hasKeyNotBePresent = anyComparisons.some(
|
|
971
|
-
(comp) => comp[0] === "keyNotBePresent"
|
|
972
|
-
);
|
|
973
|
-
if (hasKeyNotBePresent) {
|
|
974
|
-
continue;
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
const oldPath2 = context.path;
|
|
979
|
-
context.path = [...oldPath2, key];
|
|
980
|
-
addError(context, {
|
|
981
|
-
message: "Missing property",
|
|
982
|
-
expected: sub[key],
|
|
983
|
-
received: { objectWithKeys: Object.keys(target) }
|
|
984
|
-
});
|
|
985
|
-
context.path = oldPath2;
|
|
986
|
-
allMatch = false;
|
|
987
|
-
continue;
|
|
988
|
-
}
|
|
989
|
-
const oldPath = context.path;
|
|
990
|
-
context.path = [...oldPath, key];
|
|
991
|
-
const result = partialEqualInternal(target[key], sub[key], context);
|
|
992
|
-
context.path = oldPath;
|
|
993
|
-
if (!result) allMatch = false;
|
|
994
|
-
}
|
|
995
|
-
for (const { matcher, value } of keyMatchers) {
|
|
996
|
-
let foundMatch = false;
|
|
997
|
-
const matchedKeys = [];
|
|
998
|
-
if (matcher.type === "anyOther") {
|
|
999
|
-
for (const targetKey of Object.keys(target)) {
|
|
1000
|
-
if (!explicitlySpecifiedKeys.has(targetKey)) {
|
|
1001
|
-
const matches = keyMatchesPattern(targetKey, matcher);
|
|
1002
|
-
if (matches) {
|
|
1003
|
-
foundMatch = true;
|
|
1004
|
-
matchedKeys.push(targetKey);
|
|
1005
|
-
const oldPath = context.path;
|
|
1006
|
-
context.path = [...oldPath, targetKey];
|
|
1007
|
-
const result = partialEqualInternal(target[targetKey], value, context);
|
|
1008
|
-
context.path = oldPath;
|
|
1009
|
-
if (!result) allMatch = false;
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
} else if (matcher.type === "any") {
|
|
1014
|
-
let anyKeyMatched = false;
|
|
1015
|
-
for (const targetKey of Object.keys(target)) {
|
|
1016
|
-
if (keyMatchesPattern(targetKey, matcher)) {
|
|
1017
|
-
foundMatch = true;
|
|
1018
|
-
matchedKeys.push(targetKey);
|
|
1019
|
-
explicitlySpecifiedKeys.add(targetKey);
|
|
1020
|
-
const tempContext = {
|
|
1021
|
-
errors: [],
|
|
1022
|
-
path: [...context.path, targetKey]
|
|
1023
|
-
};
|
|
1024
|
-
const result = partialEqualInternal(target[targetKey], value, tempContext);
|
|
1025
|
-
if (result) {
|
|
1026
|
-
anyKeyMatched = true;
|
|
1027
|
-
break;
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
if (foundMatch && !anyKeyMatched) {
|
|
1032
|
-
addError(context, {
|
|
1033
|
-
message: `No keys matching pattern had the expected value`,
|
|
1034
|
-
received: { keysChecked: matchedKeys, availableKeys: Object.keys(target) }
|
|
1035
|
-
});
|
|
1036
|
-
allMatch = false;
|
|
1037
|
-
}
|
|
1038
|
-
} else {
|
|
1039
|
-
for (const targetKey of Object.keys(target)) {
|
|
1040
|
-
if (keyMatchesPattern(targetKey, matcher)) {
|
|
1041
|
-
foundMatch = true;
|
|
1042
|
-
matchedKeys.push(targetKey);
|
|
1043
|
-
explicitlySpecifiedKeys.add(targetKey);
|
|
1044
|
-
const oldPath = context.path;
|
|
1045
|
-
context.path = [...oldPath, targetKey];
|
|
1046
|
-
const result = partialEqualInternal(target[targetKey], value, context);
|
|
1047
|
-
context.path = oldPath;
|
|
1048
|
-
if (!result) allMatch = false;
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
if (!foundMatch) {
|
|
1053
|
-
const patternDescription = matcher.type === "anyOther" ? "anyOther (keys not explicitly specified)" : `${matcher.type}${matcher.parameter ? ` (${matcher.parameter})` : ""}`;
|
|
1054
|
-
addError(context, {
|
|
1055
|
-
message: `No keys found matching pattern: ${patternDescription}`,
|
|
1056
|
-
received: { availableKeys: Object.keys(target), explicitKeys: Array.from(explicitlySpecifiedKeys) }
|
|
1057
|
-
});
|
|
1058
|
-
allMatch = false;
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
return allMatch;
|
|
1062
|
-
}
|
|
1063
|
-
if (target !== sub) {
|
|
1064
|
-
addError(context, {
|
|
1065
|
-
message: "Value mismatch",
|
|
1066
|
-
received: target,
|
|
1067
|
-
expected: sub
|
|
1068
|
-
});
|
|
1069
|
-
return false;
|
|
1070
|
-
}
|
|
1071
|
-
return true;
|
|
1072
|
-
}
|
|
1073
|
-
function checkNoExtraKeys(target, partialShape, context, deep) {
|
|
1074
|
-
if (typeof target !== "object" || target === null || Array.isArray(target)) {
|
|
1075
|
-
addError(context, {
|
|
1076
|
-
message: "Expected object for key validation",
|
|
1077
|
-
received: target
|
|
1078
|
-
});
|
|
1079
|
-
return false;
|
|
1080
|
-
}
|
|
1081
|
-
if (!partialEqualInternal(target, partialShape, context)) {
|
|
1082
|
-
return false;
|
|
1083
|
-
}
|
|
1084
|
-
const allowedKeys = new Set(Object.keys(partialShape));
|
|
1085
|
-
for (const key of Object.keys(target)) {
|
|
1086
|
-
if (!allowedKeys.has(key)) {
|
|
1087
|
-
const oldPath = context.path;
|
|
1088
|
-
context.path = [...oldPath, key];
|
|
1089
|
-
addError(context, {
|
|
1090
|
-
message: `Extra key "${key}" should not be present`,
|
|
1091
|
-
received: target[key]
|
|
1092
|
-
});
|
|
1093
|
-
context.path = oldPath;
|
|
1094
|
-
return false;
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
if (deep) {
|
|
1098
|
-
for (const key of Object.keys(partialShape)) {
|
|
1099
|
-
if (typeof partialShape[key] === "object" && partialShape[key] !== null && !Array.isArray(partialShape[key]) && !isComparison(partialShape[key])) {
|
|
1100
|
-
const oldPath = context.path;
|
|
1101
|
-
context.path = [...oldPath, key];
|
|
1102
|
-
const result = checkNoExtraKeys(
|
|
1103
|
-
target[key],
|
|
1104
|
-
partialShape[key],
|
|
1105
|
-
context,
|
|
1106
|
-
true
|
|
1107
|
-
);
|
|
1108
|
-
context.path = oldPath;
|
|
1109
|
-
if (!result) return false;
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
return true;
|
|
1114
|
-
}
|
|
1115
|
-
function checkNoExtraDefinedKeys(target, partialShape, context, deep) {
|
|
1116
|
-
if (typeof target !== "object" || target === null || Array.isArray(target)) {
|
|
1117
|
-
addError(context, {
|
|
1118
|
-
message: "Expected object for key validation",
|
|
1119
|
-
received: target
|
|
1120
|
-
});
|
|
1121
|
-
return false;
|
|
1122
|
-
}
|
|
1123
|
-
if (!partialEqualInternal(target, partialShape, context)) {
|
|
1124
|
-
return false;
|
|
1125
|
-
}
|
|
1126
|
-
const allowedKeys = new Set(Object.keys(partialShape));
|
|
1127
|
-
for (const key of Object.keys(target)) {
|
|
1128
|
-
if (!allowedKeys.has(key) && target[key] !== void 0) {
|
|
1129
|
-
const oldPath = context.path;
|
|
1130
|
-
context.path = [...oldPath, key];
|
|
1131
|
-
addError(context, {
|
|
1132
|
-
message: `Extra defined key "${key}" should not be present`,
|
|
1133
|
-
received: target[key]
|
|
1134
|
-
});
|
|
1135
|
-
context.path = oldPath;
|
|
1136
|
-
return false;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
if (deep) {
|
|
1140
|
-
for (const key of Object.keys(partialShape)) {
|
|
1141
|
-
if (typeof partialShape[key] === "object" && partialShape[key] !== null && !Array.isArray(partialShape[key]) && !isComparison(partialShape[key])) {
|
|
1142
|
-
const oldPath = context.path;
|
|
1143
|
-
context.path = [...oldPath, key];
|
|
1144
|
-
const result = checkNoExtraDefinedKeys(
|
|
1145
|
-
target[key],
|
|
1146
|
-
partialShape[key],
|
|
1147
|
-
context,
|
|
1148
|
-
true
|
|
1149
|
-
);
|
|
1150
|
-
context.path = oldPath;
|
|
1151
|
-
if (!result) return false;
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
return true;
|
|
1156
|
-
}
|
|
1157
|
-
function partialEqual(target, sub, returnErrors) {
|
|
1158
|
-
const context = { errors: [], path: [] };
|
|
1159
|
-
const result = partialEqualInternal(target, sub, context);
|
|
1160
|
-
if (returnErrors) {
|
|
1161
|
-
return result ? ok(void 0) : err(context.errors);
|
|
1162
|
-
}
|
|
1163
|
-
return result;
|
|
1164
|
-
}
|
|
1165
|
-
export {
|
|
1166
|
-
match,
|
|
1167
|
-
partialEqual
|
|
1168
|
-
};
|