@sd-jwt/present 0.3.0 → 2.0.2-next.26
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 +201 -0
- package/dist/index.d.mts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +116 -0
- package/dist/index.mjs +96 -0
- package/package.json +59 -46
- package/src/index.ts +1 -0
- package/src/present.ts +120 -0
- package/src/test/present.spec.ts +81 -0
- package/tsconfig.json +7 -0
- package/vitest.config.mts +4 -0
- package/README.md +0 -97
- package/build/disclosureMapping.d.ts +0 -43
- package/build/disclosureMapping.js +0 -276
- package/build/disclosureMapping.js.map +0 -1
- package/build/index.d.ts +0 -2
- package/build/index.js +0 -6
- package/build/index.js.map +0 -1
- package/build/presentationFrame.d.ts +0 -3
- package/build/presentationFrame.js +0 -64
- package/build/presentationFrame.js.map +0 -1
- package/build/traverse.d.ts +0 -8
- package/build/traverse.js +0 -29
- package/build/traverse.js.map +0 -1
- package/build/types.d.ts +0 -2
- package/build/types.js +0 -3
- package/build/types.js.map +0 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { digest } from '@sd-jwt/crypto-nodejs';
|
|
3
|
+
import {
|
|
4
|
+
present,
|
|
5
|
+
presentSync,
|
|
6
|
+
presentableKeys,
|
|
7
|
+
presentableKeysSync,
|
|
8
|
+
} from '../present';
|
|
9
|
+
import { decodeSdJwt, decodeSdJwtSync } from '@sd-jwt/decode';
|
|
10
|
+
|
|
11
|
+
describe('Present tests', () => {
|
|
12
|
+
test('presentableKeys', async () => {
|
|
13
|
+
const sdjwt =
|
|
14
|
+
'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
|
|
15
|
+
const decodedSdJwt = await decodeSdJwt(sdjwt, digest);
|
|
16
|
+
const keys = await presentableKeys(
|
|
17
|
+
decodedSdJwt.jwt.payload,
|
|
18
|
+
decodedSdJwt.disclosures,
|
|
19
|
+
digest,
|
|
20
|
+
);
|
|
21
|
+
expect(keys).toStrictEqual(['arr', 'arr.0', 'arr.2.a', 'foo', 'test.zzz']);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('presentableKeys sync', () => {
|
|
25
|
+
const sdjwt =
|
|
26
|
+
'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
|
|
27
|
+
const decodedSdJwt = decodeSdJwtSync(sdjwt, digest);
|
|
28
|
+
const keys = presentableKeysSync(
|
|
29
|
+
decodedSdJwt.jwt.payload,
|
|
30
|
+
decodedSdJwt.disclosures,
|
|
31
|
+
digest,
|
|
32
|
+
);
|
|
33
|
+
expect(keys).toStrictEqual(['arr', 'arr.0', 'arr.2.a', 'foo', 'test.zzz']);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('present', async () => {
|
|
37
|
+
const sdjwt =
|
|
38
|
+
'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
|
|
39
|
+
const presentedSdJwt = await present(
|
|
40
|
+
sdjwt,
|
|
41
|
+
['foo', 'arr.0', 'test.zzz'],
|
|
42
|
+
digest,
|
|
43
|
+
);
|
|
44
|
+
expect(presentedSdJwt).toStrictEqual(
|
|
45
|
+
'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~',
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('present sync', () => {
|
|
50
|
+
const sdjwt =
|
|
51
|
+
'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
|
|
52
|
+
const presentedSdJwt = presentSync(
|
|
53
|
+
sdjwt,
|
|
54
|
+
['foo', 'arr.0', 'test.zzz'],
|
|
55
|
+
digest,
|
|
56
|
+
);
|
|
57
|
+
expect(presentedSdJwt).toStrictEqual(
|
|
58
|
+
'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~',
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('present error', async () => {
|
|
63
|
+
const sdjwt =
|
|
64
|
+
'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
|
|
65
|
+
try {
|
|
66
|
+
await present(sdjwt, ['notthekey'], digest);
|
|
67
|
+
} catch (e) {
|
|
68
|
+
expect(e).toBeDefined();
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('present error sync', () => {
|
|
73
|
+
const sdjwt =
|
|
74
|
+
'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
|
|
75
|
+
try {
|
|
76
|
+
presentSync(sdjwt, ['notthekey'], digest);
|
|
77
|
+
} catch (e) {
|
|
78
|
+
expect(e).toBeDefined();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
});
|
package/tsconfig.json
ADDED
package/README.md
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# Selective Disclosure JWT (SD-JWT) Draft 06 & Selective Disclosure JWT VC 01
|
|
2
|
-
|
|
3
|
-
## Compliant with
|
|
4
|
-
|
|
5
|
-
- [sd-jwt
|
|
6
|
-
06](https://datatracker.ietf.org/doc/draft-ietf-oauth-selective-disclosure-jwt/06/)
|
|
7
|
-
- [sd-jwt-vc
|
|
8
|
-
01](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/01/)
|
|
9
|
-
|
|
10
|
-
## Design decisions
|
|
11
|
-
|
|
12
|
-
### Bring your own crypto
|
|
13
|
-
|
|
14
|
-
This library does not provide any of the cryptographic primitives required for
|
|
15
|
-
encryption, decryption, signing, verification and hashing. It is expected that
|
|
16
|
-
the user of this library provides this. The main reason for this is that most
|
|
17
|
-
libraries have their own library and KMS. Providing private keys to this
|
|
18
|
-
library adds another layer of insecurity which should be avoided. Hashing has
|
|
19
|
-
not been added for platform compatibility between node,js, browser and React
|
|
20
|
-
Native. In the future a platform-independent sha2-256 may be provided.
|
|
21
|
-
|
|
22
|
-
### Specification backwards compatibility
|
|
23
|
-
|
|
24
|
-
Since these specifications are in early drafts, no time will be spend in
|
|
25
|
-
supporting earlier versions of the specifications. This library may work for
|
|
26
|
-
older versions, e.g. the addition of selectively disclosable items in an array
|
|
27
|
-
does not break previous implementations. Once a non-draft specification is
|
|
28
|
-
released it will stay up-to-date with that version.
|
|
29
|
-
|
|
30
|
-
### Dependencies
|
|
31
|
-
|
|
32
|
-
This library only has one dependency on `buffer` which makes sure this library
|
|
33
|
-
works in Node.js, the browser and React Native. Buffer is used internally for
|
|
34
|
-
`base64-url-no-pad` encoding.
|
|
35
|
-
|
|
36
|
-
### Usage
|
|
37
|
-
|
|
38
|
-
I'd highly recommend to check out the [examples folder](example) to see how
|
|
39
|
-
this library can be leveraged.
|
|
40
|
-
|
|
41
|
-
### Issuance API
|
|
42
|
-
|
|
43
|
-
The issuance API takes an object called a `disclosureFrame`. This
|
|
44
|
-
`disclosureFrame` is a Boolean Map of the payload which allows you to specify
|
|
45
|
-
which attributes of the payload may be selectively disclosed. If an attribute is not provided in the `disclosureFrame`, it will be included in the clear-text payload. For example:
|
|
46
|
-
|
|
47
|
-
```jsonc
|
|
48
|
-
// The payload
|
|
49
|
-
{
|
|
50
|
-
"iss": "https://example.org/issuer",
|
|
51
|
-
"is_age_over_21": true,
|
|
52
|
-
"is_age_over_24": true,
|
|
53
|
-
"is_age_over_65": false,
|
|
54
|
-
"date_of_birth": "1990-01-01",
|
|
55
|
-
"address": {
|
|
56
|
-
"street": "some street",
|
|
57
|
-
"house_number": 200,
|
|
58
|
-
"zipcode": "2344GH"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
```jsonc
|
|
64
|
-
// The disclosure frame
|
|
65
|
-
{
|
|
66
|
-
"is_age_over_21": true,
|
|
67
|
-
"is_age_over_24": true,
|
|
68
|
-
"is_age_over_65": true,
|
|
69
|
-
"date_of_birth": true,
|
|
70
|
-
"address": {
|
|
71
|
-
"street": true,
|
|
72
|
-
"house_number": true,
|
|
73
|
-
"zipcode": true
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// or to only disclose the address as a group
|
|
78
|
-
{
|
|
79
|
-
"is_age_over_21": true,
|
|
80
|
-
"is_age_over_24": true,
|
|
81
|
-
"is_age_over_65": true,
|
|
82
|
-
"date_of_birth": true,
|
|
83
|
-
"address": true
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Presentation and verification API
|
|
88
|
-
|
|
89
|
-
Since there is officially standardized way to request and present a
|
|
90
|
-
presentation, [High Assurance Interoperability
|
|
91
|
-
Profile](https://vcstuff.github.io/oid4vc-haip-sd-jwt-vc/draft-oid4vc-haip-sd-jwt-vc.html)
|
|
92
|
-
may be used, the API is defined in a way which works in a primitive manner for
|
|
93
|
-
now. For example, to present you can provide a list of indices of the
|
|
94
|
-
disclosures which will be included. Examples of this can be found in the
|
|
95
|
-
[examples folder](example). For verification a list of keys or required
|
|
96
|
-
claims can be provided. It does not matter whether these are selectively
|
|
97
|
-
disclosable claims, or if they are included inside the payload.
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { DisclosureWithDigest } from '@sd-jwt/types';
|
|
2
|
-
/**
|
|
3
|
-
* Mapping from a digest to the corresponding disclosure and its parent disclosures.
|
|
4
|
-
*/
|
|
5
|
-
export type DisclosureMap = {
|
|
6
|
-
[digest: string]: {
|
|
7
|
-
disclosure: DisclosureWithDigest;
|
|
8
|
-
parentDisclosures: DisclosureWithDigest[];
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* Get a mapping in the structure of the pretty payload, to indicate which digests should be disclosed for a
|
|
13
|
-
* given entry.
|
|
14
|
-
*
|
|
15
|
-
* For example if you call this method with the following payload:
|
|
16
|
-
* ```ts
|
|
17
|
-
* {
|
|
18
|
-
* _sd: ['iss_digest', 'nested_field_digest'],
|
|
19
|
-
* }
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* It can return the following mapping:
|
|
23
|
-
* ```ts
|
|
24
|
-
* {
|
|
25
|
-
* iss: 'iss_digest',
|
|
26
|
-
* nested_field: {
|
|
27
|
-
* __digest: 'nested_field_digest',
|
|
28
|
-
* more_nested_field: {
|
|
29
|
-
* // index 1 is null, as it's always in the payload, so doesn't need to be disclosed
|
|
30
|
-
* // separately
|
|
31
|
-
* a: ['a_0_digest', null, 'a_2_digest'],
|
|
32
|
-
* }
|
|
33
|
-
* }
|
|
34
|
-
* }
|
|
35
|
-
* ```
|
|
36
|
-
*
|
|
37
|
-
* This method will recursively call itself and `getArrayPayloadDisclosureMapping` if the value of a property is an object or array.
|
|
38
|
-
*/
|
|
39
|
-
export declare function getPayloadDisclosureMapping(payload: any, map: DisclosureMap): any[] | Record<string, unknown> | null;
|
|
40
|
-
/**
|
|
41
|
-
* Get a mapping from a digest to the corresponding disclosure and its parent disclosures.
|
|
42
|
-
*/
|
|
43
|
-
export declare const getDisclosureMap: (disclosures: DisclosureWithDigest[]) => DisclosureMap;
|
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDisclosureMap = exports.getPayloadDisclosureMapping = void 0;
|
|
4
|
-
const utils_1 = require("@sd-jwt/utils");
|
|
5
|
-
const traverse_1 = require("./traverse");
|
|
6
|
-
/**
|
|
7
|
-
* Returns an array that includes the digests that should be disclosed for each item in the array.
|
|
8
|
-
*
|
|
9
|
-
* E.g. if the following array is passed:
|
|
10
|
-
* ```ts
|
|
11
|
-
* [ { '...': <SD_HASH_DIGEST_1> }, 'string_value', { '...': <SD_HASH_DIGEST_2> } ]
|
|
12
|
-
* ```
|
|
13
|
-
*
|
|
14
|
-
* The return value will be:
|
|
15
|
-
* ```ts
|
|
16
|
-
* ['<SD_HASH_DIGEST_1>', null, '<SD_HASH_DIGEST_2>']
|
|
17
|
-
* ```
|
|
18
|
-
*
|
|
19
|
-
* The second value will be null, as it's already disclosed, and thus there's no digests that
|
|
20
|
-
* need to be disclosed to reveal it. For the other values, it will include the digest that needs
|
|
21
|
-
* to be disclosed to reveal that array entry.
|
|
22
|
-
*
|
|
23
|
-
* In the case the array entry contains nested disclosures, the value will not be a digest, but rather
|
|
24
|
-
* the structure of the nested disclosures.
|
|
25
|
-
*
|
|
26
|
-
* Let's say the `<SD_HASH_DIGEST_1>` is the digest of the following disclosure:
|
|
27
|
-
* ```ts
|
|
28
|
-
* {
|
|
29
|
-
* // `<SD_HASH_DIGEST_3>` is the digest of the dateOfBirth property
|
|
30
|
-
* _sd: ['<SD_HASH_DIGEST_3>'],
|
|
31
|
-
* name: 'Jane Doe',
|
|
32
|
-
* }
|
|
33
|
-
* ```
|
|
34
|
-
*
|
|
35
|
-
* In this case the return value will be:
|
|
36
|
-
* ```ts
|
|
37
|
-
* [{ __digest: '<SD_HASH_DIGEST_1>', dateOfBirth: '<SD_HASH_DIGEST_3>' }, null, '<SD_HASH_DIGEST_2>']
|
|
38
|
-
* ```
|
|
39
|
-
* The `__digest` property indicates the digest of the encapsulating disclosure, and it being an object
|
|
40
|
-
* indicates that there's nested disclosures that need to be revealed.
|
|
41
|
-
*
|
|
42
|
-
* In the end the result value is an array, and all the string values in the return value are the digests.
|
|
43
|
-
* This allows you to easily build a path of digests to disclose to reveal a certain value.
|
|
44
|
-
*
|
|
45
|
-
* The return value can be endlessly nested, and will also call `getPayloadDisclosureMapping` recursively
|
|
46
|
-
* if the inner values are not arrays, but objects. That method in turn can call this method if the value
|
|
47
|
-
* of an object property is an array.
|
|
48
|
-
*/
|
|
49
|
-
function getArrayPayloadDisclosureMapping(array, map) {
|
|
50
|
-
const arrayPayloadDisclosureMapping = [];
|
|
51
|
-
// Loop through all the payload values of the array
|
|
52
|
-
for (const item of array) {
|
|
53
|
-
// If the item is an object, (both array and object are objects)
|
|
54
|
-
// it means there may be some values in here that need to be disclosed to
|
|
55
|
-
// reveal this array entry
|
|
56
|
-
if (item instanceof Object) {
|
|
57
|
-
// if Array item is { '...': <SD_HASH_DIGEST> }
|
|
58
|
-
// It means this item can be disclosed.
|
|
59
|
-
if ('...' in item) {
|
|
60
|
-
const digest = item['...'];
|
|
61
|
-
if (typeof digest !== 'string') {
|
|
62
|
-
throw new Error(`Expected value of key '...' to be of type string, but found ${typeof digest}`);
|
|
63
|
-
}
|
|
64
|
-
// Look up disclosure. It's valid that the disclosure is not present (decoy digests)
|
|
65
|
-
const disclosed = map[digest];
|
|
66
|
-
if (disclosed) {
|
|
67
|
-
// value is always the last item in the disclosure array
|
|
68
|
-
const value = disclosed.disclosure.value;
|
|
69
|
-
// Recursively look if the disclosed value contains any disclosure references
|
|
70
|
-
// of itself. Based on the type we can decide how to handle it.
|
|
71
|
-
if ((0, utils_1.isObject)(value)) {
|
|
72
|
-
// Get nested disclosures for the object value
|
|
73
|
-
const unpacked = getPayloadDisclosureMapping(value, map);
|
|
74
|
-
// If there's any nested disclosures, we need to include both this item's
|
|
75
|
-
// disclosure, as well as the nested disclosures
|
|
76
|
-
if (unpacked && Object.keys(unpacked).length > 0) {
|
|
77
|
-
arrayPayloadDisclosureMapping.push(Object.assign(Object.assign({}, unpacked), { __digest: digest }));
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
arrayPayloadDisclosureMapping.push(digest);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
else if (Array.isArray(value)) {
|
|
84
|
-
// Get nested disclosures for the array value
|
|
85
|
-
const nestedUnpackedArray = getArrayPayloadDisclosureMapping(value, map);
|
|
86
|
-
// If all entries are null, it means there's no nested disclosures
|
|
87
|
-
// And thus we push the digest directly
|
|
88
|
-
if (nestedUnpackedArray.every((item) => item === null)) {
|
|
89
|
-
arrayPayloadDisclosureMapping.push(digest);
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
arrayPayloadDisclosureMapping.push(Object.assign(Object.assign({}, nestedUnpackedArray), {
|
|
93
|
-
// __digest is for encapsulating disclosure
|
|
94
|
-
__digest: digest }));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// If the value is not an object or a array, it means there's no nested disclosures
|
|
98
|
-
// and thus we can push the digest directly
|
|
99
|
-
else {
|
|
100
|
-
arrayPayloadDisclosureMapping.push(digest);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
// Value is not a disclosure for an array ('...') so we unpack the object recursively
|
|
105
|
-
const claims = getPayloadDisclosureMapping(item, map);
|
|
106
|
-
if (claims && Object.keys(claims).length > 0) {
|
|
107
|
-
arrayPayloadDisclosureMapping.push(claims);
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
arrayPayloadDisclosureMapping.push(null);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
// If the value is not an Object it means the actual value is disclosed
|
|
116
|
-
// in the array directly (so we don't need to disclose anything to reveal it)
|
|
117
|
-
else {
|
|
118
|
-
arrayPayloadDisclosureMapping.push(null);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return arrayPayloadDisclosureMapping;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Get a mapping in the structure of the pretty payload, to indicate which digests should be disclosed for a
|
|
125
|
-
* given entry.
|
|
126
|
-
*
|
|
127
|
-
* For example if you call this method with the following payload:
|
|
128
|
-
* ```ts
|
|
129
|
-
* {
|
|
130
|
-
* _sd: ['iss_digest', 'nested_field_digest'],
|
|
131
|
-
* }
|
|
132
|
-
* ```
|
|
133
|
-
*
|
|
134
|
-
* It can return the following mapping:
|
|
135
|
-
* ```ts
|
|
136
|
-
* {
|
|
137
|
-
* iss: 'iss_digest',
|
|
138
|
-
* nested_field: {
|
|
139
|
-
* __digest: 'nested_field_digest',
|
|
140
|
-
* more_nested_field: {
|
|
141
|
-
* // index 1 is null, as it's always in the payload, so doesn't need to be disclosed
|
|
142
|
-
* // separately
|
|
143
|
-
* a: ['a_0_digest', null, 'a_2_digest'],
|
|
144
|
-
* }
|
|
145
|
-
* }
|
|
146
|
-
* }
|
|
147
|
-
* ```
|
|
148
|
-
*
|
|
149
|
-
* This method will recursively call itself and `getArrayPayloadDisclosureMapping` if the value of a property is an object or array.
|
|
150
|
-
*/
|
|
151
|
-
function getPayloadDisclosureMapping(payload, map) {
|
|
152
|
-
// Handle array
|
|
153
|
-
if (payload instanceof Array) {
|
|
154
|
-
return getArrayPayloadDisclosureMapping(payload, map);
|
|
155
|
-
}
|
|
156
|
-
// Not an array or object, so it means the top-level value is already disclosed
|
|
157
|
-
if (!(0, utils_1.isObject)(payload)) {
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
const payloadDisclosureMapping = {};
|
|
161
|
-
for (const key in payload) {
|
|
162
|
-
// if obj property value is an object or array
|
|
163
|
-
// recursively unpack
|
|
164
|
-
if (key !== '_sd' && key !== '...' && payload[key] instanceof Object) {
|
|
165
|
-
const claim = getPayloadDisclosureMapping(payload[key], map);
|
|
166
|
-
if (claim && Object.keys(claim).length > 0) {
|
|
167
|
-
payloadDisclosureMapping[key] = claim;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
// If the payload contains a _sd property, it means there's disclosures
|
|
172
|
-
if (payload._sd) {
|
|
173
|
-
if (!Array.isArray(payload._sd)) {
|
|
174
|
-
throw new Error(`Expect value of '_sd' to be of type array, but found ${typeof payload._sd}`);
|
|
175
|
-
}
|
|
176
|
-
// We are going to resolve all digests
|
|
177
|
-
for (const digest of payload._sd) {
|
|
178
|
-
if (typeof digest !== 'string') {
|
|
179
|
-
throw new Error(`Expected entries in '_sd' property to be of type string, found ${typeof digest}`);
|
|
180
|
-
}
|
|
181
|
-
// Look up disclosure. It's valid that the disclosure is not present (decoy digests)
|
|
182
|
-
const disclosed = map[digest];
|
|
183
|
-
if (disclosed) {
|
|
184
|
-
// value is always the last item in the disclosure array
|
|
185
|
-
// We know this is an object, so the associated disclosure MUST have length 3
|
|
186
|
-
const value = disclosed.disclosure.value;
|
|
187
|
-
const key = disclosed.disclosure.key;
|
|
188
|
-
if (!key) {
|
|
189
|
-
throw new Error(`Expected disclosure for value ${value} to have a key, but key was undefined`);
|
|
190
|
-
}
|
|
191
|
-
// This checks if there's a nested disclosure anywhere down the tree
|
|
192
|
-
// So when a disclosure value is an object or array, it can contain disclosures
|
|
193
|
-
// of itself (using `_sd` and `...` keys)
|
|
194
|
-
if ((0, utils_1.isObject)(value)) {
|
|
195
|
-
const unpacked = getPayloadDisclosureMapping(value, map);
|
|
196
|
-
if (unpacked && Object.keys(unpacked).length > 0) {
|
|
197
|
-
payloadDisclosureMapping[key] = Object.assign(Object.assign({}, unpacked), { __digest: digest });
|
|
198
|
-
}
|
|
199
|
-
// If there's no nested disclosures, we add the digest directly
|
|
200
|
-
else {
|
|
201
|
-
payloadDisclosureMapping[key] = digest;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
else if (Array.isArray(value)) {
|
|
205
|
-
// Get nested disclosures for the array value
|
|
206
|
-
const nestedUnpackedArray = getArrayPayloadDisclosureMapping(value, map);
|
|
207
|
-
// If all entries are null, it means there's no nested disclosures
|
|
208
|
-
// And thus we push the digest directly
|
|
209
|
-
if (nestedUnpackedArray.every((item) => item === null)) {
|
|
210
|
-
payloadDisclosureMapping[key] = digest;
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
payloadDisclosureMapping[key] = Object.assign(Object.assign({}, nestedUnpackedArray), {
|
|
214
|
-
// __digest is for encapsulating disclosure
|
|
215
|
-
__digest: digest });
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
payloadDisclosureMapping[key] = digest;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return payloadDisclosureMapping;
|
|
225
|
-
}
|
|
226
|
-
exports.getPayloadDisclosureMapping = getPayloadDisclosureMapping;
|
|
227
|
-
const getParentDisclosure = (disclosure, digestMap) => {
|
|
228
|
-
const parent = digestMap[disclosure.digest];
|
|
229
|
-
if (!parent) {
|
|
230
|
-
return [];
|
|
231
|
-
}
|
|
232
|
-
if (digestMap[disclosure.digest]) {
|
|
233
|
-
return [parent].concat(getParentDisclosure(parent, digestMap));
|
|
234
|
-
}
|
|
235
|
-
return [parent];
|
|
236
|
-
};
|
|
237
|
-
/**
|
|
238
|
-
* Get a mapping from a digest to the corresponding disclosure and its parent disclosures.
|
|
239
|
-
*/
|
|
240
|
-
const getDisclosureMap = (disclosures) => {
|
|
241
|
-
const map = {};
|
|
242
|
-
const parentMap = {};
|
|
243
|
-
for (const disclosure of disclosures) {
|
|
244
|
-
const value = disclosure.value;
|
|
245
|
-
(0, traverse_1.traverseNodes)(value).forEach(({ path, value }) => {
|
|
246
|
-
const lastPathItem = path[path.length - 1];
|
|
247
|
-
if (lastPathItem === '_sd') {
|
|
248
|
-
if (!Array.isArray(value)) {
|
|
249
|
-
throw new Error(`Expect value of '_sd' to be of type array, but found ${typeof value}`);
|
|
250
|
-
}
|
|
251
|
-
value.forEach((digest) => {
|
|
252
|
-
if (typeof digest !== 'string') {
|
|
253
|
-
throw new Error(`Expected entries in '_sd' property to be of type string, found ${typeof digest}`);
|
|
254
|
-
}
|
|
255
|
-
parentMap[digest] = disclosure;
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
else if (lastPathItem === '...') {
|
|
259
|
-
if (typeof value !== 'string') {
|
|
260
|
-
throw new Error(`Expected value of '...' to be of type string, but found ${typeof value}`);
|
|
261
|
-
}
|
|
262
|
-
parentMap[value] = disclosure;
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
for (const disclosure of disclosures) {
|
|
267
|
-
const parent = getParentDisclosure(disclosure, parentMap);
|
|
268
|
-
map[disclosure.digest] = {
|
|
269
|
-
disclosure,
|
|
270
|
-
parentDisclosures: parent
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
return map;
|
|
274
|
-
};
|
|
275
|
-
exports.getDisclosureMap = getDisclosureMap;
|
|
276
|
-
//# sourceMappingURL=disclosureMapping.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"disclosureMapping.js","sourceRoot":"","sources":["../src/disclosureMapping.ts"],"names":[],"mappings":"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"}
|
package/build/index.d.ts
DELETED
package/build/index.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDisclosuresForPresentationFrame = void 0;
|
|
4
|
-
var presentationFrame_1 = require("./presentationFrame");
|
|
5
|
-
Object.defineProperty(exports, "getDisclosuresForPresentationFrame", { enumerable: true, get: function () { return presentationFrame_1.getDisclosuresForPresentationFrame; } });
|
|
6
|
-
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAAwE;AAA/D,uIAAA,kCAAkC,OAAA"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { DisclosureWithDigest } from '@sd-jwt/types';
|
|
2
|
-
import { PresentationFrame } from './types';
|
|
3
|
-
export declare function getDisclosuresForPresentationFrame<Payload extends Record<string, unknown> = Record<string, unknown>>(signedPayload: Payload, presentationFrame: PresentationFrame<Payload>, prettyClaims: Payload, disclosures?: Array<DisclosureWithDigest>): Array<DisclosureWithDigest>;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDisclosuresForPresentationFrame = void 0;
|
|
4
|
-
const utils_1 = require("@sd-jwt/utils");
|
|
5
|
-
const disclosureMapping_1 = require("./disclosureMapping");
|
|
6
|
-
const traverse_1 = require("./traverse");
|
|
7
|
-
function getDisclosuresForPresentationFrame(signedPayload, presentationFrame, prettyClaims, disclosures = []) {
|
|
8
|
-
const requiredDisclosureDigests = new Set();
|
|
9
|
-
const disclosureMap = (0, disclosureMapping_1.getDisclosureMap)(disclosures);
|
|
10
|
-
const payloadDisclosureMapping = (0, disclosureMapping_1.getPayloadDisclosureMapping)(signedPayload, disclosureMap);
|
|
11
|
-
// No disclosures needed
|
|
12
|
-
if (payloadDisclosureMapping === null) {
|
|
13
|
-
if (disclosures.length > 0) {
|
|
14
|
-
throw new Error('Payload disclosure mapping is null, but disclosures are present.');
|
|
15
|
-
}
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
for (const node of (0, traverse_1.traverseNodes)(presentationFrame)) {
|
|
19
|
-
// We only want to process leaf nodes here
|
|
20
|
-
if (!node.isLeaf)
|
|
21
|
-
continue;
|
|
22
|
-
if (typeof node.value !== 'boolean') {
|
|
23
|
-
throw new Error(`Expected leaf value in presentation frame to be of type boolean, but found ${typeof node.value}`);
|
|
24
|
-
}
|
|
25
|
-
// If the value is false, it means we don't want to disclose it
|
|
26
|
-
if (node.value === false)
|
|
27
|
-
continue;
|
|
28
|
-
if (!(0, utils_1.hasByPath)(prettyClaims, node.path)) {
|
|
29
|
-
throw new Error(`Path ${node.path.join('.')} from presentation frame is not present in pretty SD-JWT payload. The presentation frame may only include properties that are present in the SD-JWT payload.`);
|
|
30
|
-
}
|
|
31
|
-
let path = [...node.path];
|
|
32
|
-
while (!(0, utils_1.hasByPath)(payloadDisclosureMapping, path)) {
|
|
33
|
-
if (path.pop() === undefined)
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
// There are no disclosures on this path, meaning the property is disclosed by default in the signed payload
|
|
37
|
-
if (path.length === 0)
|
|
38
|
-
continue;
|
|
39
|
-
const disclosure = (0, utils_1.getByPath)(payloadDisclosureMapping, path);
|
|
40
|
-
// If disclosure is string, it means it's already the digest
|
|
41
|
-
if (typeof disclosure === 'string')
|
|
42
|
-
requiredDisclosureDigests.add(disclosure);
|
|
43
|
-
// Otherwise we want to get all the child digests as well
|
|
44
|
-
else {
|
|
45
|
-
for (const nestedItem of (0, traverse_1.traverseNodes)(disclosure)) {
|
|
46
|
-
if (!nestedItem.isLeaf ||
|
|
47
|
-
typeof nestedItem.value !== 'string') {
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
requiredDisclosureDigests.add(nestedItem.value);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
for (const disclosureDigest of requiredDisclosureDigests.values()) {
|
|
55
|
-
const disclosure = disclosureMap[disclosureDigest];
|
|
56
|
-
if (!disclosure) {
|
|
57
|
-
throw new Error('disclosure not found');
|
|
58
|
-
}
|
|
59
|
-
disclosure.parentDisclosures.forEach((d) => requiredDisclosureDigests.add(d.digest));
|
|
60
|
-
}
|
|
61
|
-
return Array.from(requiredDisclosureDigests).map((digest) => disclosureMap[digest].disclosure);
|
|
62
|
-
}
|
|
63
|
-
exports.getDisclosuresForPresentationFrame = getDisclosuresForPresentationFrame;
|
|
64
|
-
//# sourceMappingURL=presentationFrame.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"presentationFrame.js","sourceRoot":"","sources":["../src/presentationFrame.ts"],"names":[],"mappings":"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"}
|
package/build/traverse.d.ts
DELETED
package/build/traverse.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.traverseNodes = void 0;
|
|
4
|
-
function traverseNodes(object, path = []) {
|
|
5
|
-
const result = [];
|
|
6
|
-
if (typeof object !== 'object' || object === null) {
|
|
7
|
-
return [{ path: [], value: object, isLeaf: true }];
|
|
8
|
-
}
|
|
9
|
-
for (const key in object) {
|
|
10
|
-
if (object.hasOwnProperty(key)) {
|
|
11
|
-
const currentPath = [...path, key];
|
|
12
|
-
const value = object[key];
|
|
13
|
-
// Value must be object / array, and have at least some values in it
|
|
14
|
-
if (typeof value === 'object' &&
|
|
15
|
-
value !== null &&
|
|
16
|
-
Object.keys(value).length > 0) {
|
|
17
|
-
// Recursively traverse nested objects or arrays
|
|
18
|
-
result.push(...traverseNodes(value, currentPath));
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
// Leaf node found
|
|
22
|
-
result.push({ path: currentPath, value, isLeaf: true });
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return result;
|
|
27
|
-
}
|
|
28
|
-
exports.traverseNodes = traverseNodes;
|
|
29
|
-
//# sourceMappingURL=traverse.js.map
|