1 | import is from '@sindresorhus/is';
|
2 | import test from '../test.js';
|
3 | import { isPredicate } from '../predicates/base-predicate.js';
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | export function partial(object, shape, parent) {
|
14 | try {
|
15 | for (const key of Object.keys(shape)) {
|
16 | const label = parent ? `${parent}.${key}` : key;
|
17 | if (isPredicate(shape[key])) {
|
18 | test(object[key], label, shape[key]);
|
19 | }
|
20 | else if (is.plainObject(shape[key])) {
|
21 | const result = partial(object[key], shape[key], label);
|
22 | if (result !== true) {
|
23 | return result;
|
24 | }
|
25 | }
|
26 | }
|
27 | return true;
|
28 | }
|
29 | catch (error) {
|
30 | return error.message;
|
31 | }
|
32 | }
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 | export function exact(object, shape, parent, isArray) {
|
43 | try {
|
44 | const objectKeys = new Set(Object.keys(object));
|
45 | for (const key of Object.keys(shape)) {
|
46 | objectKeys.delete(key);
|
47 | const label = parent ? `${parent}.${key}` : key;
|
48 | if (isPredicate(shape[key])) {
|
49 | test(object[key], label, shape[key]);
|
50 | }
|
51 | else if (is.plainObject(shape[key])) {
|
52 | if (!Object.hasOwn(object, key)) {
|
53 | return `Expected \`${label}\` to exist`;
|
54 | }
|
55 | const result = exact(object[key], shape[key], label);
|
56 | if (result !== true) {
|
57 | return result;
|
58 | }
|
59 | }
|
60 | }
|
61 | if (objectKeys.size > 0) {
|
62 | const firstKey = [...objectKeys.keys()][0];
|
63 | const label = parent ? `${parent}.${firstKey}` : firstKey;
|
64 | return `Did not expect ${isArray ? 'element' : 'property'} \`${label}\` to exist, got \`${object[firstKey]}\``;
|
65 | }
|
66 | return true;
|
67 | }
|
68 | catch (error) {
|
69 | return error.message;
|
70 | }
|
71 | }
|