@sphereon/ssi-sdk.data-store 0.36.1-next.11 → 0.36.1-next.115

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.
@@ -0,0 +1,39 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm'
2
+
3
+ export class AddLinkedVpFields1763387280001 implements MigrationInterface {
4
+ name = 'AddLinkedVpFields1763387280001'
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(`
8
+ ALTER TABLE "DigitalCredential"
9
+ ADD COLUMN "linked_vp_id" text
10
+ `)
11
+
12
+ await queryRunner.query(`
13
+ ALTER TABLE "DigitalCredential"
14
+ ADD COLUMN "linked_vp_from" TIMESTAMP
15
+ `)
16
+
17
+ await queryRunner.query(`
18
+ ALTER TABLE "DigitalCredential"
19
+ ADD COLUMN "linked_vp_until" TIMESTAMP
20
+ `)
21
+ }
22
+
23
+ public async down(queryRunner: QueryRunner): Promise<void> {
24
+ await queryRunner.query(`
25
+ ALTER TABLE "DigitalCredential"
26
+ DROP COLUMN "linked_vp_until"
27
+ `)
28
+
29
+ await queryRunner.query(`
30
+ ALTER TABLE "DigitalCredential"
31
+ DROP COLUMN "linked_vp_from"
32
+ `)
33
+
34
+ await queryRunner.query(`
35
+ ALTER TABLE "DigitalCredential"
36
+ DROP COLUMN "linked_vp_id"
37
+ `)
38
+ }
39
+ }
@@ -0,0 +1,39 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm'
2
+
3
+ export class AddLinkedVpFields1763387280002 implements MigrationInterface {
4
+ name = 'AddLinkedVpFields1763387280002'
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(`
8
+ ALTER TABLE "DigitalCredential"
9
+ ADD COLUMN "linked_vp_id" text
10
+ `)
11
+
12
+ await queryRunner.query(`
13
+ ALTER TABLE "DigitalCredential"
14
+ ADD COLUMN "linked_vp_from" datetime
15
+ `)
16
+
17
+ await queryRunner.query(`
18
+ ALTER TABLE "DigitalCredential"
19
+ ADD COLUMN "linked_vp_until" datetime
20
+ `)
21
+ }
22
+
23
+ public async down(queryRunner: QueryRunner): Promise<void> {
24
+ await queryRunner.query(`
25
+ ALTER TABLE "DigitalCredential"
26
+ DROP COLUMN "linked_vp_from"
27
+ `)
28
+
29
+ await queryRunner.query(`
30
+ ALTER TABLE "DigitalCredential"
31
+ DROP COLUMN "linked_vp_until"
32
+ `)
33
+
34
+ await queryRunner.query(`
35
+ ALTER TABLE "DigitalCredential"
36
+ DROP COLUMN "linked_vp_id"
37
+ `)
38
+ }
39
+ }
@@ -1,6 +1,11 @@
1
1
  import { defaultHasher } from '@sphereon/ssi-sdk.core'
2
- import type { AddCredentialArgs, DigitalCredential, NonPersistedDigitalCredential } from '@sphereon/ssi-sdk.data-store-types'
3
- import { CredentialDocumentFormat, DocumentType, RegulationType } from '@sphereon/ssi-sdk.data-store-types'
2
+ import type {
3
+ AddCredentialArgs,
4
+ DigitalCredential,
5
+ NonPersistedDigitalCredential,
6
+ UpdateCredentialStateArgs,
7
+ } from '@sphereon/ssi-sdk.data-store-types'
8
+ import { CredentialDocumentFormat, CredentialStateType, DocumentType, RegulationType } from '@sphereon/ssi-sdk.data-store-types'
4
9
  import {
5
10
  CredentialMapper,
6
11
  DocumentFormat,
@@ -66,6 +71,20 @@ function determineCredentialDocumentFormat(documentFormat: DocumentFormat): Cred
66
71
  }
67
72
  }
68
73
 
74
+ /**
75
+ * Normalizes nullable fields by converting undefined to null.
76
+ * This ensures TypeORM actually clears the database fields instead of ignoring them.
77
+ */
78
+ export function normalizeNullableFields<T extends Record<string, any>>(obj: T, nullableKeys: Array<keyof T>): T {
79
+ const normalized = { ...obj }
80
+ for (const key of nullableKeys) {
81
+ if (normalized[key] === undefined) {
82
+ normalized[key] = null as any
83
+ }
84
+ }
85
+ return normalized
86
+ }
87
+
69
88
  function getValidUntil(uniformDocument: IVerifiableCredential | IVerifiablePresentation | SdJwtDecodedVerifiableCredentialPayload): Date | undefined {
70
89
  if ('expirationDate' in uniformDocument && uniformDocument.expirationDate) {
71
90
  return new Date(uniformDocument.expirationDate)
@@ -127,6 +146,54 @@ export const nonPersistedDigitalCredentialEntityFromAddArgs = (addCredentialArgs
127
146
  }
128
147
  }
129
148
 
149
+ export const persistedDigitalCredentialEntityFromUpdateArgs = (
150
+ existingCredential: DigitalCredentialEntity,
151
+ updates: Partial<DigitalCredential>,
152
+ ): DigitalCredentialEntity => {
153
+ const entity = new DigitalCredentialEntity()
154
+
155
+ // Copy all fields from existing credential
156
+ Object.assign(entity, existingCredential)
157
+
158
+ // Normalize nullable fields before applying updates
159
+ const normalizedUpdates = normalizeNullableFields(updates, ['linkedVpId', 'linkedVpFrom', 'linkedVpUntil'])
160
+
161
+ // Apply updates
162
+ Object.assign(entity, normalizedUpdates)
163
+
164
+ // Ensure these fields are never overwritten
165
+ entity.id = existingCredential.id
166
+ entity.hash = existingCredential.hash
167
+ entity.createdAt = existingCredential.createdAt
168
+ entity.lastUpdatedAt = new Date()
169
+
170
+ return entity
171
+ }
172
+
173
+ export const persistedDigitalCredentialEntityFromStateArgs = (
174
+ existingCredential: DigitalCredentialEntity,
175
+ args: UpdateCredentialStateArgs,
176
+ ): DigitalCredentialEntity => {
177
+ const entity = new DigitalCredentialEntity()
178
+
179
+ // Copy all fields from existing credential
180
+ Object.assign(entity, existingCredential)
181
+
182
+ // Apply state updates
183
+ entity.verifiedState = args.verifiedState
184
+ entity.lastUpdatedAt = new Date()
185
+
186
+ if (args.verifiedState === CredentialStateType.REVOKED && args.revokedAt) {
187
+ entity.revokedAt = args.revokedAt
188
+ }
189
+
190
+ if (args.verifiedState !== CredentialStateType.REVOKED && args.verifiedAt) {
191
+ entity.verifiedAt = args.verifiedAt
192
+ }
193
+
194
+ return entity
195
+ }
196
+
130
197
  export const digitalCredentialFrom = (credentialEntity: DigitalCredentialEntity): DigitalCredential => {
131
198
  const result: DigitalCredential = {
132
199
  ...credentialEntity,