@sphereon/ssi-sdk.data-store 0.30.1-unstable.4 → 0.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/README.md +77 -77
- package/dist/contact/ContactStore.d.ts.map +1 -1
- package/dist/digitalCredential/DigitalCredentialStore.d.ts.map +1 -1
- package/dist/eventLogger/EventLoggerStore.d.ts.map +1 -1
- package/dist/issuanceBranding/IssuanceBrandingStore.d.ts.map +1 -1
- package/dist/migrations/internal-migrations-ormconfig.d.ts.map +1 -1
- package/dist/migrations/postgres/1708525189001-CreateDigitalCredential.js +33 -33
- package/dist/migrations/postgres/1708797018115-CreateMachineStateStore.js +16 -16
- package/dist/migrations/postgres/1715761125001-CreateContacts.js +33 -33
- package/dist/migrations/postgres/1716475165345-CreatePresentationDefinitions.js +12 -12
- package/dist/migrations/sqlite/1708525189002-CreateDigitalCredential.js +32 -32
- package/dist/migrations/sqlite/1708796002272-CreateMachineStateStore.js +15 -15
- package/dist/migrations/sqlite/1710438363002-CreateContacts.js +13 -13
- package/dist/migrations/sqlite/1715761125002-CreateContacts.js +32 -32
- package/dist/migrations/sqlite/1716475165344-CreatePresentationDefinitions.js +9 -9
- package/dist/presentationDefinition/PDStore.d.ts.map +1 -1
- package/dist/utils/SortingUtils.d.ts.map +1 -1
- package/dist/utils/contact/MappingUtils.d.ts.map +1 -1
- package/dist/utils/digitalCredential/MappingUtils.d.ts.map +1 -1
- package/dist/utils/digitalCredential/MappingUtils.js +4 -4
- package/dist/utils/digitalCredential/MappingUtils.js.map +1 -1
- package/dist/utils/presentationDefinition/MappingUtils.js +2 -2
- package/dist/utils/presentationDefinition/MappingUtils.js.map +1 -1
- package/package.json +8 -8
- package/src/__tests__/contact.entities.test.ts +2642 -2642
- package/src/__tests__/contact.store.test.ts +2649 -2649
- package/src/__tests__/digitalCredential.entities.test.ts +274 -274
- package/src/__tests__/digitalCredential.store.test.ts +330 -330
- package/src/__tests__/eventLogger.entities.test.ts +76 -76
- package/src/__tests__/eventLogger.store.test.ts +130 -130
- package/src/__tests__/issuanceBranding.entities.test.ts +846 -846
- package/src/__tests__/issuanceBranding.store.test.ts +1886 -1886
- package/src/__tests__/machineState.entities.test.ts +53 -53
- package/src/__tests__/machineState.store.test.ts +176 -176
- package/src/__tests__/pd-manager.entities.test.ts +73 -73
- package/src/__tests__/pd-manager.store.test.ts +193 -193
- package/src/contact/AbstractContactStore.ts +71 -71
- package/src/contact/ContactStore.ts +768 -768
- package/src/digitalCredential/AbstractDigitalCredentialStore.ts +21 -21
- package/src/digitalCredential/DigitalCredentialStore.ts +189 -189
- package/src/entities/contact/BaseContactEntity.ts +51 -51
- package/src/entities/contact/ConnectionEntity.ts +35 -35
- package/src/entities/contact/ContactMetadataItemEntity.ts +51 -51
- package/src/entities/contact/CorrelationIdentifierEntity.ts +43 -43
- package/src/entities/contact/DidAuthConfigEntity.ts +20 -20
- package/src/entities/contact/ElectronicAddressEntity.ts +70 -70
- package/src/entities/contact/IdentityEntity.ts +107 -107
- package/src/entities/contact/IdentityMetadataItemEntity.ts +48 -48
- package/src/entities/contact/NaturalPersonEntity.ts +44 -44
- package/src/entities/contact/OpenIdConfigEntity.ts +32 -32
- package/src/entities/contact/OrganizationEntity.ts +35 -35
- package/src/entities/contact/PartyEntity.ts +117 -117
- package/src/entities/contact/PartyRelationshipEntity.ts +68 -68
- package/src/entities/contact/PartyTypeEntity.ts +63 -63
- package/src/entities/contact/PhysicalAddressEntity.ts +95 -95
- package/src/entities/digitalCredential/DigitalCredentialEntity.ts +98 -98
- package/src/entities/eventLogger/AuditEventEntity.ts +92 -92
- package/src/entities/issuanceBranding/BackgroundAttributesEntity.ts +42 -42
- package/src/entities/issuanceBranding/BaseLocaleBrandingEntity.ts +87 -87
- package/src/entities/issuanceBranding/CredentialBrandingEntity.ts +79 -79
- package/src/entities/issuanceBranding/CredentialLocaleBrandingEntity.ts +33 -33
- package/src/entities/issuanceBranding/ImageAttributesEntity.ts +57 -57
- package/src/entities/issuanceBranding/ImageDimensionsEntity.ts +22 -22
- package/src/entities/issuanceBranding/IssuerBrandingEntity.ts +73 -73
- package/src/entities/issuanceBranding/IssuerLocaleBrandingEntity.ts +33 -33
- package/src/entities/issuanceBranding/TextAttributesEntity.ts +31 -31
- package/src/entities/machineState/MachineStateInfoEntity.ts +59 -59
- package/src/entities/presentationDefinition/PresentationDefinitionItemEntity.ts +44 -44
- package/src/entities/statusList2021/StatusList2021Entity.ts +96 -96
- package/src/entities/statusList2021/StatusList2021EntryEntity.ts +29 -29
- package/src/eventLogger/AbstractEventLoggerStore.ts +7 -7
- package/src/eventLogger/EventLoggerStore.ts +62 -62
- package/src/index.ts +160 -160
- package/src/issuanceBranding/IssuanceBrandingStore.ts +559 -559
- package/src/machineState/IAbstractMachineStateStore.ts +65 -65
- package/src/machineState/MachineStateStore.ts +149 -149
- package/src/migrations/generic/1-CreateContacts.ts +66 -66
- package/src/migrations/generic/10-CreatePresentationDefinitions.ts +66 -66
- package/src/migrations/generic/2-CreateIssuanceBranding.ts +64 -64
- package/src/migrations/generic/3-CreateContacts.ts +66 -66
- package/src/migrations/generic/4-CreateStatusList.ts +54 -54
- package/src/migrations/generic/5-CreateAuditEvents.ts +66 -66
- package/src/migrations/generic/6-CreateDigitalCredential.ts +66 -66
- package/src/migrations/generic/7-CreateMachineStateStore.ts +66 -66
- package/src/migrations/generic/8-CreateContacts.ts +66 -66
- package/src/migrations/generic/9-CreateContacts.ts +66 -66
- package/src/migrations/generic/index.ts +43 -43
- package/src/migrations/index.ts +10 -10
- package/src/migrations/postgres/1659463079428-CreateContacts.ts +63 -63
- package/src/migrations/postgres/1685628974232-CreateIssuanceBranding.ts +85 -85
- package/src/migrations/postgres/1690925872592-CreateContacts.ts +158 -158
- package/src/migrations/postgres/1693866470001-CreateStatusList.ts +24 -24
- package/src/migrations/postgres/1701634812183-CreateAuditEvents.ts +33 -33
- package/src/migrations/postgres/1708525189001-CreateDigitalCredential.ts +61 -61
- package/src/migrations/postgres/1708797018115-CreateMachineStateStore.ts +29 -29
- package/src/migrations/postgres/1710438363001-CreateContacts.ts +63 -63
- package/src/migrations/postgres/1715761125001-CreateContacts.ts +60 -60
- package/src/migrations/postgres/1716475165345-CreatePresentationDefinitions.ts +25 -25
- package/src/migrations/sqlite/1659463069549-CreateContacts.ts +110 -110
- package/src/migrations/sqlite/1685628973231-CreateIssuanceBranding.ts +119 -119
- package/src/migrations/sqlite/1690925872693-CreateContacts.ts +228 -228
- package/src/migrations/sqlite/1693866470000-CreateStatusList.ts +24 -24
- package/src/migrations/sqlite/1701634819487-CreateAuditEvents.ts +15 -15
- package/src/migrations/sqlite/1708525189002-CreateDigitalCredential.ts +46 -46
- package/src/migrations/sqlite/1708796002272-CreateMachineStateStore.ts +28 -28
- package/src/migrations/sqlite/1710438363002-CreateContacts.ts +83 -83
- package/src/migrations/sqlite/1715761125002-CreateContacts.ts +59 -59
- package/src/migrations/sqlite/1716475165344-CreatePresentationDefinitions.ts +24 -24
- package/src/presentationDefinition/AbstractPDStore.ts +20 -20
- package/src/presentationDefinition/PDStore.ts +185 -185
- package/src/statusList/IStatusListStore.ts +44 -44
- package/src/statusList/StatusListStore.ts +236 -236
- package/src/types/contact/IAbstractContactStore.ts +161 -161
- package/src/types/contact/contact.ts +295 -295
- package/src/types/digitalCredential/IAbstractDigitalCredentialStore.ts +42 -42
- package/src/types/digitalCredential/digitalCredential.ts +102 -102
- package/src/types/eventLogger/IAbstractEventLoggerStore.ts +12 -12
- package/src/types/eventLogger/eventLogger.ts +3 -3
- package/src/types/index.ts +14 -14
- package/src/types/machineState/IAbstractMachineStateStore.ts +68 -68
- package/src/types/presentationDefinition/IAbstractPDStore.ts +25 -25
- package/src/types/presentationDefinition/presentationDefinition.ts +17 -17
- package/src/utils/SortingUtils.ts +16 -16
- package/src/utils/contact/MappingUtils.ts +506 -506
- package/src/utils/digitalCredential/MappingUtils.ts +160 -160
- package/src/utils/hasher.ts +19 -19
- package/src/utils/presentationDefinition/MappingUtils.ts +52 -52
- package/dist/entities/contact/IMetadataEntity.d.ts +0 -8
- package/dist/entities/contact/IMetadataEntity.d.ts.map +0 -1
- package/dist/entities/contact/IMetadataEntity.js +0 -2
- package/dist/entities/contact/IMetadataEntity.js.map +0 -1
- package/dist/migrations/generic/8-CreatePresentationDefinitions.d.ts +0 -7
- package/dist/migrations/generic/8-CreatePresentationDefinitions.d.ts.map +0 -1
- package/dist/migrations/generic/8-CreatePresentationDefinitions.js +0 -78
- package/dist/migrations/generic/8-CreatePresentationDefinitions.js.map +0 -1
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CredentialMapper,
|
|
3
|
-
DocumentFormat,
|
|
4
|
-
IVerifiableCredential,
|
|
5
|
-
IVerifiablePresentation,
|
|
6
|
-
ObjectUtils,
|
|
7
|
-
OriginalVerifiableCredential,
|
|
8
|
-
OriginalVerifiablePresentation,
|
|
9
|
-
SdJwtDecodedVerifiableCredentialPayload,
|
|
10
|
-
} from '@sphereon/ssi-types'
|
|
11
|
-
import { computeEntryHash } from '@veramo/utils'
|
|
12
|
-
import { DigitalCredentialEntity } from '../../entities/digitalCredential/DigitalCredentialEntity'
|
|
13
|
-
import {
|
|
14
|
-
AddCredentialArgs,
|
|
15
|
-
CredentialDocumentFormat,
|
|
16
|
-
DigitalCredential,
|
|
17
|
-
DocumentType,
|
|
18
|
-
NonPersistedDigitalCredential,
|
|
19
|
-
RegulationType,
|
|
20
|
-
} from '../../types'
|
|
21
|
-
|
|
22
|
-
function determineDocumentType(raw: string): DocumentType {
|
|
23
|
-
const rawDocument = parseRawDocument(raw)
|
|
24
|
-
if (!rawDocument) {
|
|
25
|
-
throw new Error(`Couldn't parse the credential: ${raw}`)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const hasProof = CredentialMapper.hasProof(rawDocument)
|
|
29
|
-
const isCredential = isHex(raw) || ObjectUtils.isBase64(raw) || CredentialMapper.isCredential(rawDocument)
|
|
30
|
-
const isPresentation = CredentialMapper.isPresentation(rawDocument)
|
|
31
|
-
|
|
32
|
-
if (isCredential) {
|
|
33
|
-
return hasProof || isHex(raw) || ObjectUtils.isBase64(raw) ? DocumentType.VC : DocumentType.C
|
|
34
|
-
} else if (isPresentation) {
|
|
35
|
-
return hasProof ? DocumentType.VP : DocumentType.P
|
|
36
|
-
}
|
|
37
|
-
throw new Error(`Couldn't determine the type of the credential: ${raw}`)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function isHex(input: string) {
|
|
41
|
-
return input.match(/^([0-9A-Fa-f])+$/g) !== null
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function parseRawDocument(raw: string): OriginalVerifiableCredential | OriginalVerifiablePresentation {
|
|
45
|
-
if (isHex(raw) || ObjectUtils.isBase64(raw)) {
|
|
46
|
-
// mso_mdoc
|
|
47
|
-
return raw
|
|
48
|
-
} else if (CredentialMapper.isJwtEncoded(raw) || CredentialMapper.isSdJwtEncoded(raw)) {
|
|
49
|
-
return raw
|
|
50
|
-
}
|
|
51
|
-
try {
|
|
52
|
-
return JSON.parse(raw)
|
|
53
|
-
} catch (e) {
|
|
54
|
-
throw new Error(`Can't parse the raw credential: ${raw}`)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function ensureRawDocument(input: string | object): string {
|
|
59
|
-
if (typeof input === 'string') {
|
|
60
|
-
if (isHex(input) || ObjectUtils.isBase64(input)) {
|
|
61
|
-
// mso_mdoc
|
|
62
|
-
return input
|
|
63
|
-
} else if (CredentialMapper.isJwtEncoded(input) || CredentialMapper.isSdJwtEncoded(input)) {
|
|
64
|
-
return input
|
|
65
|
-
}
|
|
66
|
-
throw Error('Unknown input to be mapped as rawDocument')
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
return JSON.stringify(input)
|
|
71
|
-
} catch (e) {
|
|
72
|
-
throw new Error(`Can't stringify to a raw credential: ${input}`)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function determineCredentialDocumentFormat(documentFormat: DocumentFormat): CredentialDocumentFormat {
|
|
77
|
-
switch (documentFormat) {
|
|
78
|
-
case DocumentFormat.JSONLD:
|
|
79
|
-
return CredentialDocumentFormat.JSON_LD
|
|
80
|
-
case DocumentFormat.JWT:
|
|
81
|
-
return CredentialDocumentFormat.JWT
|
|
82
|
-
case DocumentFormat.SD_JWT_VC:
|
|
83
|
-
return CredentialDocumentFormat.SD_JWT
|
|
84
|
-
case DocumentFormat.MSO_MDOC:
|
|
85
|
-
return CredentialDocumentFormat.MSO_MDOC
|
|
86
|
-
default:
|
|
87
|
-
throw new Error(`Not supported document format: ${documentFormat}`)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function getValidUntil(uniformDocument: IVerifiableCredential | IVerifiablePresentation | SdJwtDecodedVerifiableCredentialPayload): Date | undefined {
|
|
92
|
-
if ('expirationDate' in uniformDocument && uniformDocument.expirationDate) {
|
|
93
|
-
return new Date(uniformDocument.expirationDate)
|
|
94
|
-
} else if ('validUntil' in uniformDocument && uniformDocument.validUntil) {
|
|
95
|
-
return new Date(uniformDocument.validUntil)
|
|
96
|
-
} else if ('exp' in uniformDocument && uniformDocument.exp) {
|
|
97
|
-
return new Date(uniformDocument.exp * 1000)
|
|
98
|
-
}
|
|
99
|
-
return undefined
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function getValidFrom(uniformDocument: IVerifiableCredential | IVerifiablePresentation | SdJwtDecodedVerifiableCredentialPayload): Date | undefined {
|
|
103
|
-
if ('issuanceDate' in uniformDocument && uniformDocument.issuanceDate) {
|
|
104
|
-
return new Date(uniformDocument.issuanceDate)
|
|
105
|
-
} else if ('validFrom' in uniformDocument && uniformDocument.validFrom) {
|
|
106
|
-
return new Date(uniformDocument['validFrom'])
|
|
107
|
-
} else if ('nbf' in uniformDocument && uniformDocument.nbf) {
|
|
108
|
-
return new Date(uniformDocument['nbf'] * 1000)
|
|
109
|
-
} else if ('iat' in uniformDocument && uniformDocument.iat) {
|
|
110
|
-
return new Date(uniformDocument['iat'] * 1000)
|
|
111
|
-
}
|
|
112
|
-
return undefined
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const safeStringify = (object: any): string => {
|
|
116
|
-
if (typeof object === 'string') {
|
|
117
|
-
return object
|
|
118
|
-
}
|
|
119
|
-
return JSON.stringify(object)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export const nonPersistedDigitalCredentialEntityFromAddArgs = (addCredentialArgs: AddCredentialArgs): NonPersistedDigitalCredential => {
|
|
123
|
-
const documentType: DocumentType = determineDocumentType(addCredentialArgs.rawDocument)
|
|
124
|
-
const documentFormat: DocumentFormat = CredentialMapper.detectDocumentType(addCredentialArgs.rawDocument)
|
|
125
|
-
if (documentFormat === DocumentFormat.SD_JWT_VC && !addCredentialArgs.opts?.hasher) {
|
|
126
|
-
throw new Error('No hasher function is provided for SD_JWT credential.')
|
|
127
|
-
}
|
|
128
|
-
const hasher = addCredentialArgs.opts?.hasher
|
|
129
|
-
const uniformDocument =
|
|
130
|
-
documentType === DocumentType.VC || documentType === DocumentType.C
|
|
131
|
-
? CredentialMapper.toUniformCredential(addCredentialArgs.rawDocument, { hasher })
|
|
132
|
-
: CredentialMapper.toUniformPresentation(addCredentialArgs.rawDocument)
|
|
133
|
-
const validFrom: Date | undefined = getValidFrom(uniformDocument)
|
|
134
|
-
const validUntil: Date | undefined = getValidUntil(uniformDocument)
|
|
135
|
-
const hash = computeEntryHash(addCredentialArgs.rawDocument)
|
|
136
|
-
const regulationType = addCredentialArgs.regulationType ?? RegulationType.NON_REGULATED
|
|
137
|
-
return {
|
|
138
|
-
...addCredentialArgs,
|
|
139
|
-
regulationType,
|
|
140
|
-
documentType,
|
|
141
|
-
documentFormat: determineCredentialDocumentFormat(documentFormat),
|
|
142
|
-
createdAt: new Date(),
|
|
143
|
-
credentialId: uniformDocument.id ?? hash,
|
|
144
|
-
hash,
|
|
145
|
-
uniformDocument: safeStringify(uniformDocument),
|
|
146
|
-
validFrom,
|
|
147
|
-
...(validUntil && { validUntil }),
|
|
148
|
-
lastUpdatedAt: new Date(),
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export const digitalCredentialFrom = (credentialEntity: DigitalCredentialEntity): DigitalCredential => {
|
|
153
|
-
return {
|
|
154
|
-
...credentialEntity,
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export const digitalCredentialsFrom = (credentialEntities: Array<DigitalCredentialEntity>): DigitalCredential[] => {
|
|
159
|
-
return credentialEntities.map((credentialEntity) => digitalCredentialFrom(credentialEntity))
|
|
160
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
CredentialMapper,
|
|
3
|
+
DocumentFormat,
|
|
4
|
+
IVerifiableCredential,
|
|
5
|
+
IVerifiablePresentation,
|
|
6
|
+
ObjectUtils,
|
|
7
|
+
OriginalVerifiableCredential,
|
|
8
|
+
OriginalVerifiablePresentation,
|
|
9
|
+
SdJwtDecodedVerifiableCredentialPayload,
|
|
10
|
+
} from '@sphereon/ssi-types'
|
|
11
|
+
import { computeEntryHash } from '@veramo/utils'
|
|
12
|
+
import { DigitalCredentialEntity } from '../../entities/digitalCredential/DigitalCredentialEntity'
|
|
13
|
+
import {
|
|
14
|
+
AddCredentialArgs,
|
|
15
|
+
CredentialDocumentFormat,
|
|
16
|
+
DigitalCredential,
|
|
17
|
+
DocumentType,
|
|
18
|
+
NonPersistedDigitalCredential,
|
|
19
|
+
RegulationType,
|
|
20
|
+
} from '../../types'
|
|
21
|
+
|
|
22
|
+
function determineDocumentType(raw: string): DocumentType {
|
|
23
|
+
const rawDocument = parseRawDocument(raw)
|
|
24
|
+
if (!rawDocument) {
|
|
25
|
+
throw new Error(`Couldn't parse the credential: ${raw}`)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const hasProof = CredentialMapper.hasProof(rawDocument)
|
|
29
|
+
const isCredential = isHex(raw) || ObjectUtils.isBase64(raw) || CredentialMapper.isCredential(rawDocument)
|
|
30
|
+
const isPresentation = CredentialMapper.isPresentation(rawDocument)
|
|
31
|
+
|
|
32
|
+
if (isCredential) {
|
|
33
|
+
return hasProof || isHex(raw) || ObjectUtils.isBase64(raw) ? DocumentType.VC : DocumentType.C
|
|
34
|
+
} else if (isPresentation) {
|
|
35
|
+
return hasProof ? DocumentType.VP : DocumentType.P
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`Couldn't determine the type of the credential: ${raw}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isHex(input: string) {
|
|
41
|
+
return input.match(/^([0-9A-Fa-f])+$/g) !== null
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function parseRawDocument(raw: string): OriginalVerifiableCredential | OriginalVerifiablePresentation {
|
|
45
|
+
if (isHex(raw) || ObjectUtils.isBase64(raw)) {
|
|
46
|
+
// mso_mdoc
|
|
47
|
+
return raw
|
|
48
|
+
} else if (CredentialMapper.isJwtEncoded(raw) || CredentialMapper.isSdJwtEncoded(raw)) {
|
|
49
|
+
return raw
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
return JSON.parse(raw)
|
|
53
|
+
} catch (e) {
|
|
54
|
+
throw new Error(`Can't parse the raw credential: ${raw}`)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function ensureRawDocument(input: string | object): string {
|
|
59
|
+
if (typeof input === 'string') {
|
|
60
|
+
if (isHex(input) || ObjectUtils.isBase64(input)) {
|
|
61
|
+
// mso_mdoc
|
|
62
|
+
return input
|
|
63
|
+
} else if (CredentialMapper.isJwtEncoded(input) || CredentialMapper.isSdJwtEncoded(input)) {
|
|
64
|
+
return input
|
|
65
|
+
}
|
|
66
|
+
throw Error('Unknown input to be mapped as rawDocument')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
return JSON.stringify(input)
|
|
71
|
+
} catch (e) {
|
|
72
|
+
throw new Error(`Can't stringify to a raw credential: ${input}`)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function determineCredentialDocumentFormat(documentFormat: DocumentFormat): CredentialDocumentFormat {
|
|
77
|
+
switch (documentFormat) {
|
|
78
|
+
case DocumentFormat.JSONLD:
|
|
79
|
+
return CredentialDocumentFormat.JSON_LD
|
|
80
|
+
case DocumentFormat.JWT:
|
|
81
|
+
return CredentialDocumentFormat.JWT
|
|
82
|
+
case DocumentFormat.SD_JWT_VC:
|
|
83
|
+
return CredentialDocumentFormat.SD_JWT
|
|
84
|
+
case DocumentFormat.MSO_MDOC:
|
|
85
|
+
return CredentialDocumentFormat.MSO_MDOC
|
|
86
|
+
default:
|
|
87
|
+
throw new Error(`Not supported document format: ${documentFormat}`)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function getValidUntil(uniformDocument: IVerifiableCredential | IVerifiablePresentation | SdJwtDecodedVerifiableCredentialPayload): Date | undefined {
|
|
92
|
+
if ('expirationDate' in uniformDocument && uniformDocument.expirationDate) {
|
|
93
|
+
return new Date(uniformDocument.expirationDate)
|
|
94
|
+
} else if ('validUntil' in uniformDocument && uniformDocument.validUntil) {
|
|
95
|
+
return new Date(uniformDocument.validUntil)
|
|
96
|
+
} else if ('exp' in uniformDocument && uniformDocument.exp) {
|
|
97
|
+
return new Date(uniformDocument.exp * 1000)
|
|
98
|
+
}
|
|
99
|
+
return undefined
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function getValidFrom(uniformDocument: IVerifiableCredential | IVerifiablePresentation | SdJwtDecodedVerifiableCredentialPayload): Date | undefined {
|
|
103
|
+
if ('issuanceDate' in uniformDocument && uniformDocument.issuanceDate) {
|
|
104
|
+
return new Date(uniformDocument.issuanceDate)
|
|
105
|
+
} else if ('validFrom' in uniformDocument && uniformDocument.validFrom) {
|
|
106
|
+
return new Date(uniformDocument['validFrom'])
|
|
107
|
+
} else if ('nbf' in uniformDocument && uniformDocument.nbf) {
|
|
108
|
+
return new Date(uniformDocument['nbf'] * 1000)
|
|
109
|
+
} else if ('iat' in uniformDocument && uniformDocument.iat) {
|
|
110
|
+
return new Date(uniformDocument['iat'] * 1000)
|
|
111
|
+
}
|
|
112
|
+
return undefined
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const safeStringify = (object: any): string => {
|
|
116
|
+
if (typeof object === 'string') {
|
|
117
|
+
return object
|
|
118
|
+
}
|
|
119
|
+
return JSON.stringify(object)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const nonPersistedDigitalCredentialEntityFromAddArgs = (addCredentialArgs: AddCredentialArgs): NonPersistedDigitalCredential => {
|
|
123
|
+
const documentType: DocumentType = determineDocumentType(addCredentialArgs.rawDocument)
|
|
124
|
+
const documentFormat: DocumentFormat = CredentialMapper.detectDocumentType(addCredentialArgs.rawDocument)
|
|
125
|
+
if (documentFormat === DocumentFormat.SD_JWT_VC && !addCredentialArgs.opts?.hasher) {
|
|
126
|
+
throw new Error('No hasher function is provided for SD_JWT credential.')
|
|
127
|
+
}
|
|
128
|
+
const hasher = addCredentialArgs.opts?.hasher
|
|
129
|
+
const uniformDocument =
|
|
130
|
+
documentType === DocumentType.VC || documentType === DocumentType.C
|
|
131
|
+
? CredentialMapper.toUniformCredential(addCredentialArgs.rawDocument, { hasher })
|
|
132
|
+
: CredentialMapper.toUniformPresentation(addCredentialArgs.rawDocument)
|
|
133
|
+
const validFrom: Date | undefined = getValidFrom(uniformDocument)
|
|
134
|
+
const validUntil: Date | undefined = getValidUntil(uniformDocument)
|
|
135
|
+
const hash = computeEntryHash(addCredentialArgs.rawDocument)
|
|
136
|
+
const regulationType = addCredentialArgs.regulationType ?? RegulationType.NON_REGULATED
|
|
137
|
+
return {
|
|
138
|
+
...addCredentialArgs,
|
|
139
|
+
regulationType,
|
|
140
|
+
documentType,
|
|
141
|
+
documentFormat: determineCredentialDocumentFormat(documentFormat),
|
|
142
|
+
createdAt: new Date(),
|
|
143
|
+
credentialId: uniformDocument.id ?? hash,
|
|
144
|
+
hash,
|
|
145
|
+
uniformDocument: safeStringify(uniformDocument),
|
|
146
|
+
validFrom,
|
|
147
|
+
...(validUntil && { validUntil }),
|
|
148
|
+
lastUpdatedAt: new Date(),
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export const digitalCredentialFrom = (credentialEntity: DigitalCredentialEntity): DigitalCredential => {
|
|
153
|
+
return {
|
|
154
|
+
...credentialEntity,
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export const digitalCredentialsFrom = (credentialEntities: Array<DigitalCredentialEntity>): DigitalCredential[] => {
|
|
159
|
+
return credentialEntities.map((credentialEntity) => digitalCredentialFrom(credentialEntity))
|
|
160
|
+
}
|
package/src/utils/hasher.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { Hasher } from '@sphereon/ssi-types'
|
|
2
|
-
import sha from 'sha.js'
|
|
3
|
-
|
|
4
|
-
const supportedAlgorithms = ['sha256', 'sha384', 'sha512'] as const
|
|
5
|
-
type SupportedAlgorithms = (typeof supportedAlgorithms)[number]
|
|
6
|
-
|
|
7
|
-
// FIXME this is a weird place for this, but it does have good reach in ssi-sdk cunlike the copy in oid4vc-common
|
|
8
|
-
export const defaultHasher: Hasher = (data, algorithm) => {
|
|
9
|
-
const sanitizedAlgorithm = algorithm.toLowerCase().replace(/[-_]/g, '')
|
|
10
|
-
if (!supportedAlgorithms.includes(sanitizedAlgorithm as SupportedAlgorithms)) {
|
|
11
|
-
throw new Error(`Unsupported hashing algorithm ${algorithm}`)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return new Uint8Array(
|
|
15
|
-
sha(sanitizedAlgorithm as SupportedAlgorithms)
|
|
16
|
-
.update(data)
|
|
17
|
-
.digest(),
|
|
18
|
-
)
|
|
19
|
-
}
|
|
1
|
+
import { Hasher } from '@sphereon/ssi-types'
|
|
2
|
+
import sha from 'sha.js'
|
|
3
|
+
|
|
4
|
+
const supportedAlgorithms = ['sha256', 'sha384', 'sha512'] as const
|
|
5
|
+
type SupportedAlgorithms = (typeof supportedAlgorithms)[number]
|
|
6
|
+
|
|
7
|
+
// FIXME this is a weird place for this, but it does have good reach in ssi-sdk cunlike the copy in oid4vc-common
|
|
8
|
+
export const defaultHasher: Hasher = (data, algorithm) => {
|
|
9
|
+
const sanitizedAlgorithm = algorithm.toLowerCase().replace(/[-_]/g, '')
|
|
10
|
+
if (!supportedAlgorithms.includes(sanitizedAlgorithm as SupportedAlgorithms)) {
|
|
11
|
+
throw new Error(`Unsupported hashing algorithm ${algorithm}`)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return new Uint8Array(
|
|
15
|
+
sha(sanitizedAlgorithm as SupportedAlgorithms)
|
|
16
|
+
.update(data)
|
|
17
|
+
.digest(),
|
|
18
|
+
)
|
|
19
|
+
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import { PresentationDefinitionItemEntity } from '../../entities/presentationDefinition/PresentationDefinitionItemEntity'
|
|
2
|
-
import { IPresentationDefinition } from '@sphereon/pex'
|
|
3
|
-
import { NonPersistedPresentationDefinitionItem, PartialPresentationDefinitionItem, PresentationDefinitionItem } from '../../types'
|
|
4
|
-
import { blake2bHex } from 'blakejs'
|
|
5
|
-
|
|
6
|
-
export const presentationDefinitionItemFrom = (entity: PresentationDefinitionItemEntity): PresentationDefinitionItem => {
|
|
7
|
-
return {
|
|
8
|
-
id: entity.id,
|
|
9
|
-
tenantId: entity.tenantId,
|
|
10
|
-
definitionId: entity.definitionId,
|
|
11
|
-
version: entity.version,
|
|
12
|
-
name: entity.name,
|
|
13
|
-
purpose: entity.purpose,
|
|
14
|
-
definitionPayload: JSON.parse(entity.definitionPayload) as IPresentationDefinition,
|
|
15
|
-
createdAt: entity.createdAt,
|
|
16
|
-
lastUpdatedAt: entity.lastUpdatedAt,
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const presentationDefinitionEntityItemFrom = (item: NonPersistedPresentationDefinitionItem): PresentationDefinitionItemEntity => {
|
|
21
|
-
const entity = new PresentationDefinitionItemEntity()
|
|
22
|
-
|
|
23
|
-
entity.tenantId = item.tenantId
|
|
24
|
-
entity.definitionId = item.definitionId!
|
|
25
|
-
entity.version = item.version
|
|
26
|
-
entity.name = item.name
|
|
27
|
-
entity.purpose = item.purpose
|
|
28
|
-
entity.definitionPayload = JSON.stringify(item.definitionPayload!)
|
|
29
|
-
return entity
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function hashPayload(payload: IPresentationDefinition): string {
|
|
33
|
-
return blake2bHex(JSON.stringify(payload))
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function isPresentationDefinitionEqual(base: PartialPresentationDefinitionItem, compare: PartialPresentationDefinitionItem): boolean {
|
|
37
|
-
if (
|
|
38
|
-
base.definitionId !== compare.definitionId ||
|
|
39
|
-
base.tenantId != compare.tenantId ||
|
|
40
|
-
base.version !== compare.version ||
|
|
41
|
-
base.name != compare.name ||
|
|
42
|
-
base.purpose != compare.purpose
|
|
43
|
-
) {
|
|
44
|
-
return false
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (base.definitionPayload && compare.definitionPayload) {
|
|
48
|
-
return hashPayload(base.definitionPayload) === hashPayload(compare.definitionPayload)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return false
|
|
52
|
-
}
|
|
1
|
+
import { PresentationDefinitionItemEntity } from '../../entities/presentationDefinition/PresentationDefinitionItemEntity'
|
|
2
|
+
import { IPresentationDefinition } from '@sphereon/pex'
|
|
3
|
+
import { NonPersistedPresentationDefinitionItem, PartialPresentationDefinitionItem, PresentationDefinitionItem } from '../../types'
|
|
4
|
+
import { blake2bHex } from 'blakejs'
|
|
5
|
+
|
|
6
|
+
export const presentationDefinitionItemFrom = (entity: PresentationDefinitionItemEntity): PresentationDefinitionItem => {
|
|
7
|
+
return {
|
|
8
|
+
id: entity.id,
|
|
9
|
+
tenantId: entity.tenantId,
|
|
10
|
+
definitionId: entity.definitionId,
|
|
11
|
+
version: entity.version,
|
|
12
|
+
name: entity.name,
|
|
13
|
+
purpose: entity.purpose,
|
|
14
|
+
definitionPayload: JSON.parse(entity.definitionPayload) as IPresentationDefinition,
|
|
15
|
+
createdAt: entity.createdAt,
|
|
16
|
+
lastUpdatedAt: entity.lastUpdatedAt,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const presentationDefinitionEntityItemFrom = (item: NonPersistedPresentationDefinitionItem): PresentationDefinitionItemEntity => {
|
|
21
|
+
const entity = new PresentationDefinitionItemEntity()
|
|
22
|
+
|
|
23
|
+
entity.tenantId = item.tenantId
|
|
24
|
+
entity.definitionId = item.definitionId!
|
|
25
|
+
entity.version = item.version
|
|
26
|
+
entity.name = item.name
|
|
27
|
+
entity.purpose = item.purpose
|
|
28
|
+
entity.definitionPayload = JSON.stringify(item.definitionPayload!)
|
|
29
|
+
return entity
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function hashPayload(payload: IPresentationDefinition): string {
|
|
33
|
+
return blake2bHex(JSON.stringify(payload))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isPresentationDefinitionEqual(base: PartialPresentationDefinitionItem, compare: PartialPresentationDefinitionItem): boolean {
|
|
37
|
+
if (
|
|
38
|
+
base.definitionId !== compare.definitionId ||
|
|
39
|
+
base.tenantId != compare.tenantId ||
|
|
40
|
+
base.version !== compare.version ||
|
|
41
|
+
base.name != compare.name ||
|
|
42
|
+
base.purpose != compare.purpose
|
|
43
|
+
) {
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (base.definitionPayload && compare.definitionPayload) {
|
|
48
|
+
return hashPayload(base.definitionPayload) === hashPayload(compare.definitionPayload)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IMetadataEntity.d.ts","sourceRoot":"","sources":["../../../src/entities/contact/IMetadataEntity.ts"],"names":[],"mappings":"AAAA,UAAU,eAAe;IAEvB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,IAAI,CAAA;IAChB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IMetadataEntity.js","sourceRoot":"","sources":["../../../src/entities/contact/IMetadataEntity.ts"],"names":[],"mappings":""}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
-
export declare class CreatePresentationDefinitions1716533767523 implements MigrationInterface {
|
|
3
|
-
name: string
|
|
4
|
-
up(queryRunner: QueryRunner): Promise<void>
|
|
5
|
-
down(queryRunner: QueryRunner): Promise<void>
|
|
6
|
-
}
|
|
7
|
-
//# sourceMappingURL=10-CreatePresentationDefinitions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"8-CreatePresentationDefinitions.d.ts","sourceRoot":"","sources":["../../../src/migrations/generic/8-CreatePresentationDefinitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,kBAAkB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAOvE,qBAAa,0CAA2C,YAAW,kBAAkB;IACnF,IAAI,SAAmD;IAE1C,EAAE,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA4B3C,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CA2B3D"}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.CreatePresentationDefinitions1716533767523 = void 0;
|
|
16
|
-
const debug_1 = __importDefault(require("debug"));
|
|
17
|
-
const _1716475165345_CreatePresentationDefinitions_1 = require("../postgres/1716475165345-CreatePresentationDefinitions");
|
|
18
|
-
const _1716475165344_CreatePresentationDefinitions_1 = require("../sqlite/1716475165344-CreatePresentationDefinitions");
|
|
19
|
-
const debug = (0, debug_1.default)('sphereon:ssi-sdk:migrations');
|
|
20
|
-
class CreatePresentationDefinitions1716533767523 {
|
|
21
|
-
constructor() {
|
|
22
|
-
this.name = 'CreatePresentationDefinitionItems1716533767523';
|
|
23
|
-
}
|
|
24
|
-
up(queryRunner) {
|
|
25
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
debug('migration: creating machine state tables');
|
|
27
|
-
const dbType = queryRunner.connection.driver.options.type;
|
|
28
|
-
switch (dbType) {
|
|
29
|
-
case 'postgres': {
|
|
30
|
-
debug('using postgres migration file');
|
|
31
|
-
const mig = new _1716475165345_CreatePresentationDefinitions_1.CreatePresentationDefinitions1716475165345();
|
|
32
|
-
yield mig.up(queryRunner);
|
|
33
|
-
debug('Migration statements executed');
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
case 'sqlite':
|
|
37
|
-
case 'expo':
|
|
38
|
-
case 'react-native': {
|
|
39
|
-
debug('using sqlite/react-native migration file');
|
|
40
|
-
const mig = new _1716475165344_CreatePresentationDefinitions_1.CreatePresentationDefinitions1716475165344();
|
|
41
|
-
yield mig.up(queryRunner);
|
|
42
|
-
debug('Migration statements executed');
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
default:
|
|
46
|
-
return Promise.reject(`Migrations are currently only supported for sqlite, react-native, expo and postgres. Was ${dbType}. Please run your database without migrations and with 'migrationsRun: false' and 'synchronize: true' for now`);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
down(queryRunner) {
|
|
51
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
-
debug('migration: reverting machine state tables');
|
|
53
|
-
const dbType = queryRunner.connection.driver.options.type;
|
|
54
|
-
switch (dbType) {
|
|
55
|
-
case 'postgres': {
|
|
56
|
-
debug('using postgres migration file');
|
|
57
|
-
const mig = new _1716475165345_CreatePresentationDefinitions_1.CreatePresentationDefinitions1716475165345();
|
|
58
|
-
yield mig.down(queryRunner);
|
|
59
|
-
debug('Migration statements executed');
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
case 'sqlite':
|
|
63
|
-
case 'expo':
|
|
64
|
-
case 'react-native': {
|
|
65
|
-
debug('using sqlite/react-native migration file');
|
|
66
|
-
const mig = new _1716475165344_CreatePresentationDefinitions_1.CreatePresentationDefinitions1716475165344();
|
|
67
|
-
yield mig.down(queryRunner);
|
|
68
|
-
debug('Migration statements executed');
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
default:
|
|
72
|
-
return Promise.reject(`Migrations are currently only supported for sqlite, react-native, expo and postgres. Was ${dbType}. Please run your database without migrations and with 'migrationsRun: false' and 'synchronize: true' for now`);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
exports.CreatePresentationDefinitions1716533767523 = CreatePresentationDefinitions1716533767523;
|
|
78
|
-
//# sourceMappingURL=8-CreatePresentationDefinitions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"8-CreatePresentationDefinitions.js","sourceRoot":"","sources":["../../../src/migrations/generic/8-CreatePresentationDefinitions.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,kDAAyB;AACzB,0HAAoH;AACpH,wHAAkH;AAElH,MAAM,KAAK,GAAmB,IAAA,eAAK,EAAC,6BAA6B,CAAC,CAAA;AAElE,MAAa,0CAA0C;IAAvD;QACE,SAAI,GAAG,gDAAgD,CAAA;IAyDzD,CAAC;IAvDc,EAAE,CAAC,WAAwB;;YACtC,KAAK,CAAC,0CAA0C,CAAC,CAAA;YACjD,MAAM,MAAM,GAAiB,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAA;YAEvE,QAAQ,MAAM,EAAE,CAAC;gBACf,KAAK,UAAU,CAAC,CAAC,CAAC;oBAChB,KAAK,CAAC,+BAA+B,CAAC,CAAA;oBACtC,MAAM,GAAG,GAA+C,IAAI,yFAA0C,EAAE,CAAA;oBACxG,MAAM,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC,CAAA;oBACzB,KAAK,CAAC,+BAA+B,CAAC,CAAA;oBACtC,OAAM;gBACR,CAAC;gBACD,KAAK,QAAQ,CAAC;gBACd,KAAK,MAAM,CAAC;gBACZ,KAAK,cAAc,CAAC,CAAC,CAAC;oBACpB,KAAK,CAAC,0CAA0C,CAAC,CAAA;oBACjD,MAAM,GAAG,GAA+C,IAAI,yFAA0C,EAAE,CAAA;oBACxG,MAAM,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC,CAAA;oBACzB,KAAK,CAAC,+BAA+B,CAAC,CAAA;oBACtC,OAAM;gBACR,CAAC;gBACD;oBACE,OAAO,OAAO,CAAC,MAAM,CACnB,4FAA4F,MAAM,+GAA+G,CAClN,CAAA;YACL,CAAC;QACH,CAAC;KAAA;IAEY,IAAI,CAAC,WAAwB;;YACxC,KAAK,CAAC,2CAA2C,CAAC,CAAA;YAClD,MAAM,MAAM,GAAiB,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAA;YAEvE,QAAQ,MAAM,EAAE,CAAC;gBACf,KAAK,UAAU,CAAC,CAAC,CAAC;oBAChB,KAAK,CAAC,+BAA+B,CAAC,CAAA;oBACtC,MAAM,GAAG,GAA+C,IAAI,yFAA0C,EAAE,CAAA;oBACxG,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;oBAC3B,KAAK,CAAC,+BAA+B,CAAC,CAAA;oBACtC,OAAM;gBACR,CAAC;gBACD,KAAK,QAAQ,CAAC;gBACd,KAAK,MAAM,CAAC;gBACZ,KAAK,cAAc,CAAC,CAAC,CAAC;oBACpB,KAAK,CAAC,0CAA0C,CAAC,CAAA;oBACjD,MAAM,GAAG,GAA+C,IAAI,yFAA0C,EAAE,CAAA;oBACxG,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;oBAC3B,KAAK,CAAC,+BAA+B,CAAC,CAAA;oBACtC,OAAM;gBACR,CAAC;gBACD;oBACE,OAAO,OAAO,CAAC,MAAM,CACnB,4FAA4F,MAAM,+GAA+G,CAClN,CAAA;YACL,CAAC;QACH,CAAC;KAAA;CACF;AA1DD,gGA0DC"}
|